Home | History | Annotate | Line # | Download | only in kern
vfs_syscalls.c revision 1.449.2.2.6.1
      1  1.449.2.2.6.1    bouyer /*	$NetBSD: vfs_syscalls.c,v 1.449.2.2.6.1 2014/04/21 10:17:47 bouyer Exp $	*/
      2          1.345        ad 
      3          1.345        ad /*-
      4          1.390        ad  * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc.
      5          1.345        ad  * All rights reserved.
      6          1.345        ad  *
      7          1.390        ad  * This code is derived from software contributed to The NetBSD Foundation
      8          1.390        ad  * by Andrew Doran.
      9          1.390        ad  *
     10          1.345        ad  * Redistribution and use in source and binary forms, with or without
     11          1.345        ad  * modification, are permitted provided that the following conditions
     12          1.345        ad  * are met:
     13          1.345        ad  * 1. Redistributions of source code must retain the above copyright
     14          1.345        ad  *    notice, this list of conditions and the following disclaimer.
     15          1.345        ad  * 2. Redistributions in binary form must reproduce the above copyright
     16          1.345        ad  *    notice, this list of conditions and the following disclaimer in the
     17          1.345        ad  *    documentation and/or other materials provided with the distribution.
     18          1.345        ad  *
     19          1.345        ad  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20          1.345        ad  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21          1.345        ad  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22          1.345        ad  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23          1.345        ad  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24          1.345        ad  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25          1.345        ad  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26          1.345        ad  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27          1.345        ad  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28          1.345        ad  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29          1.345        ad  * POSSIBILITY OF SUCH DAMAGE.
     30          1.345        ad  */
     31           1.31       cgd 
     32           1.31       cgd /*
     33           1.31       cgd  * Copyright (c) 1989, 1993
     34           1.31       cgd  *	The Regents of the University of California.  All rights reserved.
     35           1.31       cgd  * (c) UNIX System Laboratories, Inc.
     36           1.31       cgd  * All or some portions of this file are derived from material licensed
     37           1.31       cgd  * to the University of California by American Telephone and Telegraph
     38           1.31       cgd  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
     39           1.31       cgd  * the permission of UNIX System Laboratories, Inc.
     40           1.31       cgd  *
     41           1.31       cgd  * Redistribution and use in source and binary forms, with or without
     42           1.31       cgd  * modification, are permitted provided that the following conditions
     43           1.31       cgd  * are met:
     44           1.31       cgd  * 1. Redistributions of source code must retain the above copyright
     45           1.31       cgd  *    notice, this list of conditions and the following disclaimer.
     46           1.31       cgd  * 2. Redistributions in binary form must reproduce the above copyright
     47           1.31       cgd  *    notice, this list of conditions and the following disclaimer in the
     48           1.31       cgd  *    documentation and/or other materials provided with the distribution.
     49          1.191       agc  * 3. Neither the name of the University nor the names of its contributors
     50           1.31       cgd  *    may be used to endorse or promote products derived from this software
     51           1.31       cgd  *    without specific prior written permission.
     52           1.31       cgd  *
     53           1.31       cgd  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     54           1.31       cgd  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     55           1.31       cgd  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     56           1.31       cgd  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     57           1.31       cgd  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     58           1.31       cgd  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     59           1.31       cgd  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     60           1.31       cgd  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     61           1.31       cgd  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     62           1.31       cgd  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     63           1.31       cgd  * SUCH DAMAGE.
     64           1.31       cgd  *
     65          1.113      fvdl  *	@(#)vfs_syscalls.c	8.42 (Berkeley) 7/31/95
     66           1.31       cgd  */
     67          1.173     lukem 
     68          1.420     rmind /*
     69          1.420     rmind  * Virtual File System System Calls
     70          1.420     rmind  */
     71          1.420     rmind 
     72          1.173     lukem #include <sys/cdefs.h>
     73  1.449.2.2.6.1    bouyer __KERNEL_RCSID(0, "$NetBSD: vfs_syscalls.c,v 1.449.2.2.6.1 2014/04/21 10:17:47 bouyer Exp $");
     74          1.111       mrg 
     75          1.378        ad #ifdef _KERNEL_OPT
     76          1.258      elad #include "opt_fileassoc.h"
     77          1.261    dogcow #include "veriexec.h"
     78          1.378        ad #endif
     79           1.31       cgd 
     80           1.31       cgd #include <sys/param.h>
     81           1.31       cgd #include <sys/systm.h>
     82           1.31       cgd #include <sys/namei.h>
     83           1.31       cgd #include <sys/filedesc.h>
     84           1.31       cgd #include <sys/kernel.h>
     85           1.31       cgd #include <sys/file.h>
     86          1.433      manu #include <sys/fcntl.h>
     87           1.31       cgd #include <sys/stat.h>
     88           1.31       cgd #include <sys/vnode.h>
     89           1.31       cgd #include <sys/mount.h>
     90           1.31       cgd #include <sys/proc.h>
     91           1.31       cgd #include <sys/uio.h>
     92          1.248      yamt #include <sys/kmem.h>
     93           1.31       cgd #include <sys/dirent.h>
     94          1.172    simonb #include <sys/sysctl.h>
     95           1.35       cgd #include <sys/syscallargs.h>
     96          1.306       dsl #include <sys/vfs_syscalls.h>
     97          1.444  dholland #include <sys/quota.h>
     98          1.444  dholland #include <sys/quotactl.h>
     99          1.192  drochner #include <sys/ktrace.h>
    100          1.251      elad #ifdef FILEASSOC
    101          1.251      elad #include <sys/fileassoc.h>
    102          1.251      elad #endif /* FILEASSOC */
    103          1.430      manu #include <sys/extattr.h>
    104          1.219     blymn #include <sys/verified_exec.h>
    105          1.242      elad #include <sys/kauth.h>
    106          1.346        ad #include <sys/atomic.h>
    107          1.360        ad #include <sys/module.h>
    108          1.380     pooka #include <sys/buf.h>
    109           1.35       cgd 
    110          1.148      fvdl #include <miscfs/genfs/genfs.h>
    111          1.148      fvdl #include <miscfs/syncfs/syncfs.h>
    112          1.342        ad #include <miscfs/specfs/specdev.h>
    113          1.181   thorpej 
    114          1.232      jmmv #include <nfs/rpcv2.h>
    115          1.232      jmmv #include <nfs/nfsproto.h>
    116          1.232      jmmv #include <nfs/nfs.h>
    117          1.232      jmmv #include <nfs/nfs_var.h>
    118          1.232      jmmv 
    119          1.234  christos static int change_flags(struct vnode *, u_long, struct lwp *);
    120          1.234  christos static int change_mode(struct vnode *, int, struct lwp *l);
    121          1.234  christos static int change_owner(struct vnode *, uid_t, gid_t, struct lwp *, int);
    122          1.448    martin static int do_open(lwp_t *, struct pathbuf *, int, int, int *);
    123           1.63  christos 
    124           1.99   thorpej /*
    125           1.99   thorpej  * This table is used to maintain compatibility with 4.3BSD
    126          1.378        ad  * and NetBSD 0.9 mount syscalls - and possibly other systems.
    127          1.378        ad  * Note, the order is important!
    128          1.124   thorpej  *
    129          1.167  jdolecek  * Do not modify this table. It should only contain filesystems
    130          1.167  jdolecek  * supported by NetBSD 0.9 and 4.3BSD.
    131           1.99   thorpej  */
    132          1.167  jdolecek const char * const mountcompatnames[] = {
    133           1.99   thorpej 	NULL,		/* 0 = MOUNT_NONE */
    134          1.167  jdolecek 	MOUNT_FFS,	/* 1 = MOUNT_UFS */
    135           1.99   thorpej 	MOUNT_NFS,	/* 2 */
    136           1.99   thorpej 	MOUNT_MFS,	/* 3 */
    137           1.99   thorpej 	MOUNT_MSDOS,	/* 4 */
    138          1.167  jdolecek 	MOUNT_CD9660,	/* 5 = MOUNT_ISOFS */
    139          1.167  jdolecek 	MOUNT_FDESC,	/* 6 */
    140          1.167  jdolecek 	MOUNT_KERNFS,	/* 7 */
    141          1.167  jdolecek 	NULL,		/* 8 = MOUNT_DEVFS */
    142          1.167  jdolecek 	MOUNT_AFS,	/* 9 */
    143           1.99   thorpej };
    144          1.420     rmind 
    145          1.420     rmind const int nmountcompatnames = __arraycount(mountcompatnames);
    146           1.99   thorpej 
    147          1.285      elad static int
    148          1.422  christos open_setfp(struct lwp *l, file_t *fp, struct vnode *vp, int indx, int flags)
    149          1.422  christos {
    150          1.422  christos 	int error;
    151          1.422  christos 
    152          1.422  christos 	fp->f_flag = flags & FMASK;
    153          1.422  christos 	fp->f_type = DTYPE_VNODE;
    154          1.422  christos 	fp->f_ops = &vnops;
    155          1.422  christos 	fp->f_data = vp;
    156          1.422  christos 
    157          1.422  christos 	if (flags & (O_EXLOCK | O_SHLOCK)) {
    158          1.422  christos 		struct flock lf;
    159          1.422  christos 		int type;
    160          1.422  christos 
    161          1.422  christos 		lf.l_whence = SEEK_SET;
    162          1.422  christos 		lf.l_start = 0;
    163          1.422  christos 		lf.l_len = 0;
    164          1.422  christos 		if (flags & O_EXLOCK)
    165          1.422  christos 			lf.l_type = F_WRLCK;
    166          1.422  christos 		else
    167          1.422  christos 			lf.l_type = F_RDLCK;
    168          1.422  christos 		type = F_FLOCK;
    169          1.422  christos 		if ((flags & FNONBLOCK) == 0)
    170          1.422  christos 			type |= F_WAIT;
    171          1.422  christos 		VOP_UNLOCK(vp);
    172          1.422  christos 		error = VOP_ADVLOCK(vp, fp, F_SETLK, &lf, type);
    173          1.422  christos 		if (error) {
    174          1.422  christos 			(void) vn_close(vp, fp->f_flag, fp->f_cred);
    175          1.422  christos 			fd_abort(l->l_proc, fp, indx);
    176          1.422  christos 			return error;
    177          1.422  christos 		}
    178          1.422  christos 		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
    179          1.422  christos 		atomic_or_uint(&fp->f_flag, FHASLOCK);
    180          1.422  christos 	}
    181          1.422  christos 	if (flags & O_CLOEXEC)
    182          1.422  christos 		fd_set_exclose(l, indx, true);
    183          1.422  christos 	return 0;
    184          1.422  christos }
    185          1.422  christos 
    186          1.422  christos static int
    187          1.283      elad mount_update(struct lwp *l, struct vnode *vp, const char *path, int flags,
    188          1.324     pooka     void *data, size_t *data_len)
    189           1.56   thorpej {
    190          1.113      fvdl 	struct mount *mp;
    191          1.283      elad 	int error = 0, saved_flags;
    192          1.283      elad 
    193          1.283      elad 	mp = vp->v_mount;
    194          1.283      elad 	saved_flags = mp->mnt_flag;
    195          1.283      elad 
    196          1.329        ad 	/* We can operate only on VV_ROOT nodes. */
    197          1.329        ad 	if ((vp->v_vflag & VV_ROOT) == 0) {
    198          1.329        ad 		error = EINVAL;
    199          1.329        ad 		goto out;
    200          1.329        ad 	}
    201           1.31       cgd 
    202          1.218      yamt 	/*
    203          1.283      elad 	 * We only allow the filesystem to be reloaded if it
    204          1.373        ad 	 * is currently mounted read-only.  Additionally, we
    205          1.373        ad 	 * prevent read-write to read-only downgrades.
    206          1.283      elad 	 */
    207          1.373        ad 	if ((flags & (MNT_RELOAD | MNT_RDONLY)) != 0 &&
    208          1.414     pooka 	    (mp->mnt_flag & MNT_RDONLY) == 0 &&
    209          1.414     pooka 	    (mp->mnt_iflag & IMNT_CAN_RWTORO) == 0) {
    210          1.329        ad 		error = EOPNOTSUPP;	/* Needs translation */
    211          1.329        ad 		goto out;
    212          1.329        ad 	}
    213          1.292      elad 
    214          1.292      elad 	error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_MOUNT,
    215          1.292      elad 	    KAUTH_REQ_SYSTEM_MOUNT_UPDATE, mp, KAUTH_ARG(flags), data);
    216          1.292      elad 	if (error)
    217          1.329        ad 		goto out;
    218          1.292      elad 
    219          1.358        ad 	if (vfs_busy(mp, NULL)) {
    220          1.329        ad 		error = EPERM;
    221          1.329        ad 		goto out;
    222          1.329        ad 	}
    223          1.283      elad 
    224          1.358        ad 	mutex_enter(&mp->mnt_updating);
    225          1.358        ad 
    226          1.286      yamt 	mp->mnt_flag &= ~MNT_OP_FLAGS;
    227          1.441  christos 	mp->mnt_flag |= flags & MNT_OP_FLAGS;
    228          1.286      yamt 
    229          1.283      elad 	/*
    230          1.283      elad 	 * Set the mount level flags.
    231          1.283      elad 	 */
    232          1.283      elad 	if (flags & MNT_RDONLY)
    233          1.283      elad 		mp->mnt_flag |= MNT_RDONLY;
    234          1.283      elad 	else if (mp->mnt_flag & MNT_RDONLY)
    235          1.283      elad 		mp->mnt_iflag |= IMNT_WANTRDWR;
    236          1.441  christos 	mp->mnt_flag &= ~MNT_BASIC_FLAGS;
    237          1.441  christos 	mp->mnt_flag |= flags & MNT_BASIC_FLAGS;
    238          1.332     pooka 	error = VFS_MOUNT(mp, path, data, data_len);
    239          1.283      elad 
    240          1.320       dsl 	if (error && data != NULL) {
    241          1.283      elad 		int error2;
    242          1.283      elad 
    243          1.378        ad 		/*
    244          1.378        ad 		 * Update failed; let's try and see if it was an
    245          1.379        ad 		 * export request.  For compat with 3.0 and earlier.
    246          1.378        ad 		 */
    247          1.381        ad 		error2 = vfs_hooks_reexport(mp, path, data);
    248          1.283      elad 
    249          1.381        ad 		/*
    250          1.381        ad 		 * Only update error code if the export request was
    251          1.283      elad 		 * understood but some problem occurred while
    252          1.381        ad 		 * processing it.
    253          1.381        ad 		 */
    254          1.283      elad 		if (error2 != EJUSTRETURN)
    255          1.283      elad 			error = error2;
    256          1.283      elad 	}
    257          1.381        ad 
    258          1.283      elad 	if (mp->mnt_iflag & IMNT_WANTRDWR)
    259          1.283      elad 		mp->mnt_flag &= ~MNT_RDONLY;
    260          1.283      elad 	if (error)
    261          1.283      elad 		mp->mnt_flag = saved_flags;
    262          1.286      yamt 	mp->mnt_flag &= ~MNT_OP_FLAGS;
    263          1.286      yamt 	mp->mnt_iflag &= ~IMNT_WANTRDWR;
    264          1.283      elad 	if ((mp->mnt_flag & (MNT_RDONLY | MNT_ASYNC)) == 0) {
    265          1.283      elad 		if (mp->mnt_syncer == NULL)
    266          1.283      elad 			error = vfs_allocate_syncvnode(mp);
    267          1.125       tls 	} else {
    268          1.283      elad 		if (mp->mnt_syncer != NULL)
    269          1.283      elad 			vfs_deallocate_syncvnode(mp);
    270          1.283      elad 	}
    271          1.358        ad 	mutex_exit(&mp->mnt_updating);
    272          1.354        ad 	vfs_unbusy(mp, false, NULL);
    273          1.283      elad 
    274          1.430      manu 	if ((error == 0) && !(saved_flags & MNT_EXTATTR) &&
    275          1.430      manu 	    (flags & MNT_EXTATTR)) {
    276      1.449.2.2       riz 		if (VFS_EXTATTRCTL(mp, EXTATTR_CMD_START,
    277          1.430      manu 				   NULL, 0, NULL) != 0) {
    278          1.430      manu 			printf("%s: failed to start extattr, error = %d",
    279      1.449.2.2       riz 			       mp->mnt_stat.f_mntonname, error);
    280          1.430      manu 			mp->mnt_flag &= ~MNT_EXTATTR;
    281          1.430      manu 		}
    282          1.430      manu 	}
    283          1.430      manu 
    284          1.430      manu 	if ((error == 0) && (saved_flags & MNT_EXTATTR) &&
    285          1.430      manu 	    !(flags & MNT_EXTATTR)) {
    286      1.449.2.2       riz 		if (VFS_EXTATTRCTL(mp, EXTATTR_CMD_STOP,
    287          1.430      manu 				   NULL, 0, NULL) != 0) {
    288          1.430      manu 			printf("%s: failed to stop extattr, error = %d",
    289      1.449.2.2       riz 			       mp->mnt_stat.f_mntonname, error);
    290          1.430      manu 			mp->mnt_flag |= MNT_RDONLY;
    291          1.430      manu 		}
    292          1.430      manu 	}
    293          1.329        ad  out:
    294          1.283      elad 	return (error);
    295          1.283      elad }
    296          1.283      elad 
    297          1.285      elad static int
    298          1.320       dsl mount_get_vfsops(const char *fstype, struct vfsops **vfsops)
    299          1.283      elad {
    300          1.322  christos 	char fstypename[sizeof(((struct statvfs *)NULL)->f_fstypename)];
    301          1.283      elad 	int error;
    302          1.283      elad 
    303          1.320       dsl 	/* Copy file-system type from userspace.  */
    304          1.322  christos 	error = copyinstr(fstype, fstypename, sizeof(fstypename), NULL);
    305           1.63  christos 	if (error) {
    306           1.54       cgd 		/*
    307          1.227      jmmv 		 * Historically, filesystem types were identified by numbers.
    308           1.54       cgd 		 * If we get an integer for the filesystem type instead of a
    309           1.54       cgd 		 * string, we check to see if it matches one of the historic
    310           1.54       cgd 		 * filesystem types.
    311          1.205  junyoung 		 */
    312          1.283      elad 		u_long fsindex = (u_long)fstype;
    313           1.99   thorpej 		if (fsindex >= nmountcompatnames ||
    314          1.320       dsl 		    mountcompatnames[fsindex] == NULL)
    315          1.320       dsl 			return ENODEV;
    316          1.331     pooka 		strlcpy(fstypename, mountcompatnames[fsindex],
    317          1.331     pooka 		    sizeof(fstypename));
    318           1.31       cgd 	}
    319          1.283      elad 
    320          1.378        ad 	/* Accept `ufs' as an alias for `ffs', for compatibility. */
    321          1.320       dsl 	if (strcmp(fstypename, "ufs") == 0)
    322          1.320       dsl 		fstypename[0] = 'f';
    323          1.285      elad 
    324          1.360        ad 	if ((*vfsops = vfs_getopsbyname(fstypename)) != NULL)
    325          1.360        ad 		return 0;
    326          1.360        ad 
    327          1.360        ad 	/* If we can autoload a vfs module, try again */
    328          1.400    martin 	(void)module_autoload(fstypename, MODULE_CLASS_VFS);
    329          1.360        ad 
    330          1.360        ad 	if ((*vfsops = vfs_getopsbyname(fstypename)) != NULL)
    331          1.360        ad 		return 0;
    332          1.360        ad 
    333          1.360        ad 	return ENODEV;
    334          1.320       dsl }
    335          1.320       dsl 
    336          1.320       dsl static int
    337          1.283      elad mount_getargs(struct lwp *l, struct vnode *vp, const char *path, int flags,
    338          1.324     pooka     void *data, size_t *data_len)
    339          1.283      elad {
    340          1.283      elad 	struct mount *mp;
    341          1.283      elad 	int error;
    342          1.283      elad 
    343          1.289      elad 	/* If MNT_GETARGS is specified, it should be the only flag. */
    344          1.320       dsl 	if (flags & ~MNT_GETARGS)
    345          1.320       dsl 		return EINVAL;
    346          1.289      elad 
    347          1.283      elad 	mp = vp->v_mount;
    348          1.283      elad 
    349          1.292      elad 	/* XXX: probably some notion of "can see" here if we want isolation. */
    350          1.292      elad 	error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_MOUNT,
    351          1.292      elad 	    KAUTH_REQ_SYSTEM_MOUNT_GET, mp, data, NULL);
    352          1.292      elad 	if (error)
    353          1.320       dsl 		return error;
    354          1.292      elad 
    355          1.329        ad 	if ((vp->v_vflag & VV_ROOT) == 0)
    356          1.320       dsl 		return EINVAL;
    357          1.283      elad 
    358          1.358        ad 	if (vfs_busy(mp, NULL))
    359          1.320       dsl 		return EPERM;
    360          1.283      elad 
    361          1.358        ad 	mutex_enter(&mp->mnt_updating);
    362          1.286      yamt 	mp->mnt_flag &= ~MNT_OP_FLAGS;
    363          1.286      yamt 	mp->mnt_flag |= MNT_GETARGS;
    364          1.332     pooka 	error = VFS_MOUNT(mp, path, data, data_len);
    365          1.286      yamt 	mp->mnt_flag &= ~MNT_OP_FLAGS;
    366          1.358        ad 	mutex_exit(&mp->mnt_updating);
    367          1.283      elad 
    368          1.354        ad 	vfs_unbusy(mp, false, NULL);
    369          1.283      elad 	return (error);
    370          1.283      elad }
    371          1.283      elad 
    372          1.321       dsl int
    373          1.335       dsl sys___mount50(struct lwp *l, const struct sys___mount50_args *uap, register_t *retval)
    374          1.321       dsl {
    375          1.335       dsl 	/* {
    376          1.321       dsl 		syscallarg(const char *) type;
    377          1.321       dsl 		syscallarg(const char *) path;
    378          1.321       dsl 		syscallarg(int) flags;
    379          1.321       dsl 		syscallarg(void *) data;
    380          1.321       dsl 		syscallarg(size_t) data_len;
    381          1.335       dsl 	} */
    382          1.321       dsl 
    383          1.321       dsl 	return do_sys_mount(l, NULL, SCARG(uap, type), SCARG(uap, path),
    384          1.321       dsl 	    SCARG(uap, flags), SCARG(uap, data), UIO_USERSPACE,
    385          1.321       dsl 	    SCARG(uap, data_len), retval);
    386          1.321       dsl }
    387          1.320       dsl 
    388          1.320       dsl int
    389          1.320       dsl do_sys_mount(struct lwp *l, struct vfsops *vfsops, const char *type,
    390          1.320       dsl     const char *path, int flags, void *data, enum uio_seg data_seg,
    391          1.320       dsl     size_t data_len, register_t *retval)
    392          1.320       dsl {
    393          1.283      elad 	struct vnode *vp;
    394          1.320       dsl 	void *data_buf = data;
    395          1.403     pooka 	bool vfsopsrele = false;
    396  1.449.2.2.6.1    bouyer 	size_t alloc_sz = 0;
    397          1.283      elad 	int error;
    398          1.283      elad 
    399          1.403     pooka 	/* XXX: The calling convention of this routine is totally bizarre */
    400          1.403     pooka 	if (vfsops)
    401          1.403     pooka 		vfsopsrele = true;
    402          1.403     pooka 
    403          1.283      elad 	/*
    404          1.283      elad 	 * Get vnode to be covered
    405          1.283      elad 	 */
    406          1.395  dholland 	error = namei_simple_user(path, NSM_FOLLOW_TRYEMULROOT, &vp);
    407          1.403     pooka 	if (error != 0) {
    408          1.403     pooka 		vp = NULL;
    409          1.403     pooka 		goto done;
    410          1.403     pooka 	}
    411          1.283      elad 
    412          1.320       dsl 	if (vfsops == NULL) {
    413          1.361        ad 		if (flags & (MNT_GETARGS | MNT_UPDATE)) {
    414          1.320       dsl 			vfsops = vp->v_mount->mnt_op;
    415          1.361        ad 		} else {
    416          1.320       dsl 			/* 'type' is userspace */
    417          1.320       dsl 			error = mount_get_vfsops(type, &vfsops);
    418          1.320       dsl 			if (error != 0)
    419          1.320       dsl 				goto done;
    420          1.403     pooka 			vfsopsrele = true;
    421          1.320       dsl 		}
    422          1.320       dsl 	}
    423          1.320       dsl 
    424  1.449.2.2.6.1    bouyer 	/*
    425  1.449.2.2.6.1    bouyer 	 * We allow data to be NULL, even for userspace. Some fs's don't need
    426  1.449.2.2.6.1    bouyer 	 * it. The others will handle NULL.
    427  1.449.2.2.6.1    bouyer 	 */
    428          1.320       dsl 	if (data != NULL && data_seg == UIO_USERSPACE) {
    429          1.320       dsl 		if (data_len == 0) {
    430          1.320       dsl 			/* No length supplied, use default for filesystem */
    431          1.320       dsl 			data_len = vfsops->vfs_min_mount_data;
    432  1.449.2.2.6.1    bouyer 
    433          1.378        ad 			/*
    434          1.378        ad 			 * Hopefully a longer buffer won't make copyin() fail.
    435          1.378        ad 			 * For compatibility with 3.0 and earlier.
    436          1.378        ad 			 */
    437          1.320       dsl 			if (flags & MNT_UPDATE
    438          1.320       dsl 			    && data_len < sizeof (struct mnt_export_args30))
    439          1.320       dsl 				data_len = sizeof (struct mnt_export_args30);
    440          1.320       dsl 		}
    441  1.449.2.2.6.1    bouyer 		if ((data_len == 0) || (data_len > VFS_MAX_MOUNT_DATA)) {
    442  1.449.2.2.6.1    bouyer 			error = EINVAL;
    443  1.449.2.2.6.1    bouyer 			goto done;
    444  1.449.2.2.6.1    bouyer 		}
    445  1.449.2.2.6.1    bouyer 		alloc_sz = data_len;
    446  1.449.2.2.6.1    bouyer 		data_buf = kmem_alloc(alloc_sz, KM_SLEEP);
    447          1.283      elad 
    448          1.320       dsl 		/* NFS needs the buffer even for mnt_getargs .... */
    449          1.320       dsl 		error = copyin(data, data_buf, data_len);
    450          1.320       dsl 		if (error != 0)
    451          1.320       dsl 			goto done;
    452          1.320       dsl 	}
    453          1.320       dsl 
    454          1.320       dsl 	if (flags & MNT_GETARGS) {
    455          1.320       dsl 		if (data_len == 0) {
    456          1.320       dsl 			error = EINVAL;
    457          1.320       dsl 			goto done;
    458          1.320       dsl 		}
    459          1.324     pooka 		error = mount_getargs(l, vp, path, flags, data_buf, &data_len);
    460          1.320       dsl 		if (error != 0)
    461          1.320       dsl 			goto done;
    462          1.320       dsl 		if (data_seg == UIO_USERSPACE)
    463          1.320       dsl 			error = copyout(data_buf, data, data_len);
    464          1.320       dsl 		*retval = data_len;
    465          1.320       dsl 	} else if (flags & MNT_UPDATE) {
    466          1.324     pooka 		error = mount_update(l, vp, path, flags, data_buf, &data_len);
    467          1.283      elad 	} else {
    468          1.283      elad 		/* Locking is handled internally in mount_domount(). */
    469          1.403     pooka 		KASSERT(vfsopsrele == true);
    470          1.320       dsl 		error = mount_domount(l, &vp, vfsops, path, flags, data_buf,
    471          1.405   hannken 		    &data_len);
    472          1.403     pooka 		vfsopsrele = false;
    473          1.283      elad 	}
    474          1.283      elad 
    475          1.320       dsl     done:
    476          1.403     pooka 	if (vfsopsrele)
    477          1.403     pooka 		vfs_delref(vfsops);
    478          1.337        ad     	if (vp != NULL) {
    479          1.405   hannken 	    	vrele(vp);
    480          1.337        ad 	}
    481          1.320       dsl 	if (data_buf != data)
    482  1.449.2.2.6.1    bouyer 		kmem_free(data_buf, alloc_sz);
    483           1.31       cgd 	return (error);
    484           1.31       cgd }
    485           1.31       cgd 
    486           1.31       cgd /*
    487           1.31       cgd  * Unmount a file system.
    488           1.31       cgd  *
    489           1.31       cgd  * Note: unmount takes a path to the vnode mounted on as argument,
    490           1.31       cgd  * not special file (as before).
    491           1.31       cgd  */
    492           1.31       cgd /* ARGSUSED */
    493           1.63  christos int
    494          1.335       dsl sys_unmount(struct lwp *l, const struct sys_unmount_args *uap, register_t *retval)
    495           1.56   thorpej {
    496          1.335       dsl 	/* {
    497           1.74       cgd 		syscallarg(const char *) path;
    498           1.35       cgd 		syscallarg(int) flags;
    499          1.335       dsl 	} */
    500          1.155  augustss 	struct vnode *vp;
    501           1.31       cgd 	struct mount *mp;
    502           1.31       cgd 	int error;
    503          1.409  dholland 	struct pathbuf *pb;
    504           1.31       cgd 	struct nameidata nd;
    505           1.31       cgd 
    506          1.409  dholland 	error = pathbuf_copyin(SCARG(uap, path), &pb);
    507          1.409  dholland 	if (error) {
    508          1.409  dholland 		return error;
    509          1.409  dholland 	}
    510          1.409  dholland 
    511          1.409  dholland 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | TRYEMULROOT, pb);
    512          1.409  dholland 	if ((error = namei(&nd)) != 0) {
    513          1.409  dholland 		pathbuf_destroy(pb);
    514          1.409  dholland 		return error;
    515          1.409  dholland 	}
    516           1.31       cgd 	vp = nd.ni_vp;
    517          1.409  dholland 	pathbuf_destroy(pb);
    518          1.409  dholland 
    519           1.43   mycroft 	mp = vp->v_mount;
    520          1.358        ad 	atomic_inc_uint(&mp->mnt_refcnt);
    521          1.406   hannken 	VOP_UNLOCK(vp);
    522           1.31       cgd 
    523          1.295      elad 	error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_MOUNT,
    524          1.295      elad 	    KAUTH_REQ_SYSTEM_MOUNT_UNMOUNT, mp, NULL, NULL);
    525          1.295      elad 	if (error) {
    526          1.345        ad 		vrele(vp);
    527          1.358        ad 		vfs_destroy(mp);
    528           1.31       cgd 		return (error);
    529           1.31       cgd 	}
    530           1.31       cgd 
    531           1.31       cgd 	/*
    532           1.47   mycroft 	 * Don't allow unmounting the root file system.
    533           1.47   mycroft 	 */
    534           1.47   mycroft 	if (mp->mnt_flag & MNT_ROOTFS) {
    535          1.345        ad 		vrele(vp);
    536          1.358        ad 		vfs_destroy(mp);
    537           1.47   mycroft 		return (EINVAL);
    538           1.47   mycroft 	}
    539           1.47   mycroft 
    540           1.47   mycroft 	/*
    541           1.31       cgd 	 * Must be the root of the filesystem
    542           1.31       cgd 	 */
    543          1.329        ad 	if ((vp->v_vflag & VV_ROOT) == 0) {
    544          1.345        ad 		vrele(vp);
    545          1.358        ad 		vfs_destroy(mp);
    546           1.31       cgd 		return (EINVAL);
    547           1.31       cgd 	}
    548           1.78      fvdl 
    549          1.359        ad 	vrele(vp);
    550          1.358        ad 	error = dounmount(mp, SCARG(uap, flags), l);
    551          1.374        ad 	vfs_destroy(mp);
    552          1.358        ad 	return error;
    553           1.31       cgd }
    554           1.31       cgd 
    555           1.31       cgd /*
    556           1.31       cgd  * Sync each mounted filesystem.
    557           1.31       cgd  */
    558           1.31       cgd #ifdef DEBUG
    559           1.31       cgd int syncprt = 0;
    560           1.31       cgd struct ctldebug debug0 = { "syncprt", &syncprt };
    561           1.31       cgd #endif
    562           1.31       cgd 
    563          1.425       dsl void
    564          1.425       dsl do_sys_sync(struct lwp *l)
    565           1.31       cgd {
    566          1.155  augustss 	struct mount *mp, *nmp;
    567           1.31       cgd 	int asyncflag;
    568          1.257        ad 
    569          1.329        ad 	mutex_enter(&mountlist_lock);
    570          1.353        ad 	for (mp = CIRCLEQ_FIRST(&mountlist); mp != (void *)&mountlist;
    571          1.353        ad 	     mp = nmp) {
    572          1.358        ad 		if (vfs_busy(mp, &nmp)) {
    573          1.113      fvdl 			continue;
    574          1.113      fvdl 		}
    575          1.358        ad 		mutex_enter(&mp->mnt_updating);
    576          1.307   hannken 		if ((mp->mnt_flag & MNT_RDONLY) == 0) {
    577           1.31       cgd 			asyncflag = mp->mnt_flag & MNT_ASYNC;
    578           1.31       cgd 			mp->mnt_flag &= ~MNT_ASYNC;
    579          1.332     pooka 			VFS_SYNC(mp, MNT_NOWAIT, l->l_cred);
    580           1.31       cgd 			if (asyncflag)
    581          1.113      fvdl 				 mp->mnt_flag |= MNT_ASYNC;
    582           1.31       cgd 		}
    583          1.358        ad 		mutex_exit(&mp->mnt_updating);
    584          1.354        ad 		vfs_unbusy(mp, false, &nmp);
    585           1.31       cgd 	}
    586          1.329        ad 	mutex_exit(&mountlist_lock);
    587           1.31       cgd #ifdef DEBUG
    588           1.31       cgd 	if (syncprt)
    589           1.31       cgd 		vfs_bufstats();
    590           1.31       cgd #endif /* DEBUG */
    591          1.425       dsl }
    592          1.425       dsl 
    593          1.425       dsl /* ARGSUSED */
    594          1.425       dsl int
    595          1.425       dsl sys_sync(struct lwp *l, const void *v, register_t *retval)
    596          1.425       dsl {
    597          1.425       dsl 	do_sys_sync(l);
    598           1.31       cgd 	return (0);
    599           1.31       cgd }
    600           1.31       cgd 
    601          1.425       dsl 
    602           1.31       cgd /*
    603          1.444  dholland  * Access or change filesystem quotas.
    604          1.444  dholland  *
    605          1.444  dholland  * (this is really 14 different calls bundled into one)
    606           1.31       cgd  */
    607          1.444  dholland 
    608          1.444  dholland static int
    609          1.444  dholland do_sys_quotactl_stat(struct mount *mp, struct quotastat *info_u)
    610          1.444  dholland {
    611          1.444  dholland 	struct quotastat info_k;
    612          1.444  dholland 	int error;
    613          1.444  dholland 
    614          1.444  dholland 	/* ensure any padding bytes are cleared */
    615          1.444  dholland 	memset(&info_k, 0, sizeof(info_k));
    616          1.444  dholland 
    617          1.444  dholland 	error = vfs_quotactl_stat(mp, &info_k);
    618          1.444  dholland 	if (error) {
    619          1.444  dholland 		return error;
    620          1.444  dholland 	}
    621          1.444  dholland 
    622          1.444  dholland 	return copyout(&info_k, info_u, sizeof(info_k));
    623          1.444  dholland }
    624          1.444  dholland 
    625          1.444  dholland static int
    626          1.444  dholland do_sys_quotactl_idtypestat(struct mount *mp, int idtype,
    627          1.444  dholland     struct quotaidtypestat *info_u)
    628          1.444  dholland {
    629          1.444  dholland 	struct quotaidtypestat info_k;
    630          1.444  dholland 	int error;
    631          1.444  dholland 
    632          1.444  dholland 	/* ensure any padding bytes are cleared */
    633          1.444  dholland 	memset(&info_k, 0, sizeof(info_k));
    634          1.444  dholland 
    635          1.444  dholland 	error = vfs_quotactl_idtypestat(mp, idtype, &info_k);
    636          1.444  dholland 	if (error) {
    637          1.444  dholland 		return error;
    638          1.444  dholland 	}
    639          1.444  dholland 
    640          1.444  dholland 	return copyout(&info_k, info_u, sizeof(info_k));
    641          1.444  dholland }
    642          1.444  dholland 
    643          1.444  dholland static int
    644          1.444  dholland do_sys_quotactl_objtypestat(struct mount *mp, int objtype,
    645          1.444  dholland     struct quotaobjtypestat *info_u)
    646          1.444  dholland {
    647          1.444  dholland 	struct quotaobjtypestat info_k;
    648          1.444  dholland 	int error;
    649          1.444  dholland 
    650          1.444  dholland 	/* ensure any padding bytes are cleared */
    651          1.444  dholland 	memset(&info_k, 0, sizeof(info_k));
    652          1.444  dholland 
    653          1.444  dholland 	error = vfs_quotactl_objtypestat(mp, objtype, &info_k);
    654          1.444  dholland 	if (error) {
    655          1.444  dholland 		return error;
    656          1.444  dholland 	}
    657          1.444  dholland 
    658          1.444  dholland 	return copyout(&info_k, info_u, sizeof(info_k));
    659          1.444  dholland }
    660          1.444  dholland 
    661          1.444  dholland static int
    662          1.444  dholland do_sys_quotactl_get(struct mount *mp, const struct quotakey *key_u,
    663          1.444  dholland     struct quotaval *val_u)
    664          1.444  dholland {
    665          1.444  dholland 	struct quotakey key_k;
    666          1.444  dholland 	struct quotaval val_k;
    667          1.444  dholland 	int error;
    668          1.444  dholland 
    669          1.444  dholland 	/* ensure any padding bytes are cleared */
    670          1.444  dholland 	memset(&val_k, 0, sizeof(val_k));
    671          1.444  dholland 
    672          1.444  dholland 	error = copyin(key_u, &key_k, sizeof(key_k));
    673          1.444  dholland 	if (error) {
    674          1.444  dholland 		return error;
    675          1.444  dholland 	}
    676          1.444  dholland 
    677          1.444  dholland 	error = vfs_quotactl_get(mp, &key_k, &val_k);
    678          1.444  dholland 	if (error) {
    679          1.444  dholland 		return error;
    680          1.444  dholland 	}
    681          1.444  dholland 
    682          1.444  dholland 	return copyout(&val_k, val_u, sizeof(val_k));
    683          1.444  dholland }
    684          1.444  dholland 
    685          1.444  dholland static int
    686          1.444  dholland do_sys_quotactl_put(struct mount *mp, const struct quotakey *key_u,
    687          1.444  dholland     const struct quotaval *val_u)
    688          1.444  dholland {
    689          1.444  dholland 	struct quotakey key_k;
    690          1.444  dholland 	struct quotaval val_k;
    691          1.444  dholland 	int error;
    692          1.444  dholland 
    693          1.444  dholland 	error = copyin(key_u, &key_k, sizeof(key_k));
    694          1.444  dholland 	if (error) {
    695          1.444  dholland 		return error;
    696          1.444  dholland 	}
    697          1.444  dholland 
    698          1.444  dholland 	error = copyin(val_u, &val_k, sizeof(val_k));
    699          1.444  dholland 	if (error) {
    700          1.444  dholland 		return error;
    701          1.444  dholland 	}
    702          1.444  dholland 
    703          1.444  dholland 	return vfs_quotactl_put(mp, &key_k, &val_k);
    704          1.444  dholland }
    705          1.444  dholland 
    706          1.444  dholland static int
    707          1.444  dholland do_sys_quotactl_delete(struct mount *mp, const struct quotakey *key_u)
    708          1.444  dholland {
    709          1.444  dholland 	struct quotakey key_k;
    710          1.444  dholland 	int error;
    711          1.444  dholland 
    712          1.444  dholland 	error = copyin(key_u, &key_k, sizeof(key_k));
    713          1.444  dholland 	if (error) {
    714          1.444  dholland 		return error;
    715          1.444  dholland 	}
    716          1.444  dholland 
    717          1.444  dholland 	return vfs_quotactl_delete(mp, &key_k);
    718          1.444  dholland }
    719          1.444  dholland 
    720          1.444  dholland static int
    721          1.444  dholland do_sys_quotactl_cursoropen(struct mount *mp, struct quotakcursor *cursor_u)
    722          1.444  dholland {
    723          1.444  dholland 	struct quotakcursor cursor_k;
    724          1.444  dholland 	int error;
    725          1.444  dholland 
    726          1.444  dholland 	/* ensure any padding bytes are cleared */
    727          1.444  dholland 	memset(&cursor_k, 0, sizeof(cursor_k));
    728          1.444  dholland 
    729          1.444  dholland 	error = vfs_quotactl_cursoropen(mp, &cursor_k);
    730          1.444  dholland 	if (error) {
    731          1.444  dholland 		return error;
    732          1.444  dholland 	}
    733          1.444  dholland 
    734          1.444  dholland 	return copyout(&cursor_k, cursor_u, sizeof(cursor_k));
    735          1.444  dholland }
    736          1.444  dholland 
    737          1.444  dholland static int
    738          1.444  dholland do_sys_quotactl_cursorclose(struct mount *mp, struct quotakcursor *cursor_u)
    739          1.444  dholland {
    740          1.444  dholland 	struct quotakcursor cursor_k;
    741          1.444  dholland 	int error;
    742          1.444  dholland 
    743          1.444  dholland 	error = copyin(cursor_u, &cursor_k, sizeof(cursor_k));
    744          1.444  dholland 	if (error) {
    745          1.444  dholland 		return error;
    746          1.444  dholland 	}
    747          1.444  dholland 
    748          1.444  dholland 	return vfs_quotactl_cursorclose(mp, &cursor_k);
    749          1.444  dholland }
    750          1.444  dholland 
    751          1.444  dholland static int
    752          1.444  dholland do_sys_quotactl_cursorskipidtype(struct mount *mp,
    753          1.444  dholland     struct quotakcursor *cursor_u, int idtype)
    754          1.444  dholland {
    755          1.444  dholland 	struct quotakcursor cursor_k;
    756          1.444  dholland 	int error;
    757          1.444  dholland 
    758          1.444  dholland 	error = copyin(cursor_u, &cursor_k, sizeof(cursor_k));
    759          1.444  dholland 	if (error) {
    760          1.444  dholland 		return error;
    761          1.444  dholland 	}
    762          1.444  dholland 
    763          1.444  dholland 	error = vfs_quotactl_cursorskipidtype(mp, &cursor_k, idtype);
    764          1.444  dholland 	if (error) {
    765          1.444  dholland 		return error;
    766          1.444  dholland 	}
    767          1.444  dholland 
    768          1.444  dholland 	return copyout(&cursor_k, cursor_u, sizeof(cursor_k));
    769          1.444  dholland }
    770          1.444  dholland 
    771          1.444  dholland static int
    772          1.444  dholland do_sys_quotactl_cursorget(struct mount *mp, struct quotakcursor *cursor_u,
    773          1.444  dholland     struct quotakey *keys_u, struct quotaval *vals_u, unsigned maxnum,
    774          1.447  dholland     unsigned *ret_u)
    775          1.444  dholland {
    776          1.444  dholland #define CGET_STACK_MAX 8
    777          1.444  dholland 	struct quotakcursor cursor_k;
    778          1.444  dholland 	struct quotakey stackkeys[CGET_STACK_MAX];
    779          1.444  dholland 	struct quotaval stackvals[CGET_STACK_MAX];
    780          1.444  dholland 	struct quotakey *keys_k;
    781          1.444  dholland 	struct quotaval *vals_k;
    782          1.447  dholland 	unsigned ret_k;
    783          1.444  dholland 	int error;
    784          1.444  dholland 
    785          1.444  dholland 	if (maxnum > 128) {
    786          1.444  dholland 		maxnum = 128;
    787          1.444  dholland 	}
    788          1.444  dholland 
    789          1.444  dholland 	error = copyin(cursor_u, &cursor_k, sizeof(cursor_k));
    790          1.444  dholland 	if (error) {
    791          1.444  dholland 		return error;
    792          1.444  dholland 	}
    793          1.444  dholland 
    794          1.444  dholland 	if (maxnum <= CGET_STACK_MAX) {
    795          1.444  dholland 		keys_k = stackkeys;
    796          1.444  dholland 		vals_k = stackvals;
    797          1.444  dholland 		/* ensure any padding bytes are cleared */
    798          1.444  dholland 		memset(keys_k, 0, maxnum * sizeof(keys_k[0]));
    799          1.444  dholland 		memset(vals_k, 0, maxnum * sizeof(vals_k[0]));
    800          1.444  dholland 	} else {
    801          1.444  dholland 		keys_k = kmem_zalloc(maxnum * sizeof(keys_k[0]), KM_SLEEP);
    802          1.444  dholland 		vals_k = kmem_zalloc(maxnum * sizeof(vals_k[0]), KM_SLEEP);
    803          1.444  dholland 	}
    804          1.444  dholland 
    805          1.444  dholland 	error = vfs_quotactl_cursorget(mp, &cursor_k, keys_k, vals_k, maxnum,
    806          1.444  dholland 				       &ret_k);
    807          1.444  dholland 	if (error) {
    808          1.444  dholland 		goto fail;
    809          1.444  dholland 	}
    810          1.444  dholland 
    811          1.444  dholland 	error = copyout(keys_k, keys_u, ret_k * sizeof(keys_k[0]));
    812          1.444  dholland 	if (error) {
    813          1.444  dholland 		goto fail;
    814          1.444  dholland 	}
    815          1.444  dholland 
    816          1.444  dholland 	error = copyout(vals_k, vals_u, ret_k * sizeof(vals_k[0]));
    817          1.444  dholland 	if (error) {
    818          1.444  dholland 		goto fail;
    819          1.444  dholland 	}
    820          1.444  dholland 
    821          1.444  dholland 	error = copyout(&ret_k, ret_u, sizeof(ret_k));
    822          1.444  dholland 	if (error) {
    823          1.444  dholland 		goto fail;
    824          1.444  dholland 	}
    825          1.444  dholland 
    826          1.444  dholland 	/* do last to maximize the chance of being able to recover a failure */
    827          1.444  dholland 	error = copyout(&cursor_k, cursor_u, sizeof(cursor_k));
    828          1.444  dholland 
    829          1.444  dholland fail:
    830          1.444  dholland 	if (keys_k != stackkeys) {
    831          1.444  dholland 		kmem_free(keys_k, maxnum * sizeof(keys_k[0]));
    832          1.444  dholland 	}
    833          1.444  dholland 	if (vals_k != stackvals) {
    834          1.444  dholland 		kmem_free(vals_k, maxnum * sizeof(vals_k[0]));
    835          1.444  dholland 	}
    836          1.444  dholland 	return error;
    837          1.444  dholland }
    838          1.444  dholland 
    839          1.444  dholland static int
    840          1.444  dholland do_sys_quotactl_cursoratend(struct mount *mp, struct quotakcursor *cursor_u,
    841          1.444  dholland     int *ret_u)
    842          1.444  dholland {
    843          1.444  dholland 	struct quotakcursor cursor_k;
    844          1.444  dholland 	int ret_k;
    845          1.444  dholland 	int error;
    846          1.444  dholland 
    847          1.444  dholland 	error = copyin(cursor_u, &cursor_k, sizeof(cursor_k));
    848          1.444  dholland 	if (error) {
    849          1.444  dholland 		return error;
    850          1.444  dholland 	}
    851          1.444  dholland 
    852          1.444  dholland 	error = vfs_quotactl_cursoratend(mp, &cursor_k, &ret_k);
    853          1.444  dholland 	if (error) {
    854          1.444  dholland 		return error;
    855          1.444  dholland 	}
    856          1.444  dholland 
    857          1.444  dholland 	error = copyout(&ret_k, ret_u, sizeof(ret_k));
    858          1.444  dholland 	if (error) {
    859          1.444  dholland 		return error;
    860          1.444  dholland 	}
    861          1.444  dholland 
    862          1.444  dholland 	return copyout(&cursor_k, cursor_u, sizeof(cursor_k));
    863          1.444  dholland }
    864          1.444  dholland 
    865          1.444  dholland static int
    866          1.444  dholland do_sys_quotactl_cursorrewind(struct mount *mp, struct quotakcursor *cursor_u)
    867          1.444  dholland {
    868          1.444  dholland 	struct quotakcursor cursor_k;
    869          1.444  dholland 	int error;
    870          1.444  dholland 
    871          1.444  dholland 	error = copyin(cursor_u, &cursor_k, sizeof(cursor_k));
    872          1.444  dholland 	if (error) {
    873          1.444  dholland 		return error;
    874          1.444  dholland 	}
    875          1.444  dholland 
    876          1.444  dholland 	error = vfs_quotactl_cursorrewind(mp, &cursor_k);
    877          1.444  dholland 	if (error) {
    878          1.444  dholland 		return error;
    879          1.444  dholland 	}
    880          1.444  dholland 
    881          1.444  dholland 	return copyout(&cursor_k, cursor_u, sizeof(cursor_k));
    882          1.444  dholland }
    883          1.444  dholland 
    884          1.444  dholland static int
    885          1.444  dholland do_sys_quotactl_quotaon(struct mount *mp, int idtype, const char *path_u)
    886          1.444  dholland {
    887          1.444  dholland 	char *path_k;
    888          1.444  dholland 	int error;
    889          1.444  dholland 
    890          1.444  dholland 	/* XXX this should probably be a struct pathbuf */
    891          1.444  dholland 	path_k = PNBUF_GET();
    892          1.444  dholland 	error = copyin(path_u, path_k, PATH_MAX);
    893          1.444  dholland 	if (error) {
    894          1.444  dholland 		PNBUF_PUT(path_k);
    895          1.444  dholland 		return error;
    896          1.444  dholland 	}
    897          1.444  dholland 
    898          1.444  dholland 	error = vfs_quotactl_quotaon(mp, idtype, path_k);
    899          1.444  dholland 
    900          1.444  dholland 	PNBUF_PUT(path_k);
    901          1.444  dholland 	return error;
    902          1.444  dholland }
    903          1.444  dholland 
    904          1.444  dholland static int
    905          1.444  dholland do_sys_quotactl_quotaoff(struct mount *mp, int idtype)
    906          1.444  dholland {
    907          1.444  dholland 	return vfs_quotactl_quotaoff(mp, idtype);
    908          1.444  dholland }
    909          1.444  dholland 
    910           1.63  christos int
    911          1.445  dholland do_sys_quotactl(const char *path_u, const struct quotactl_args *args)
    912           1.56   thorpej {
    913          1.155  augustss 	struct mount *mp;
    914          1.444  dholland 	struct vnode *vp;
    915           1.31       cgd 	int error;
    916           1.31       cgd 
    917          1.445  dholland 	error = namei_simple_user(path_u, NSM_FOLLOW_TRYEMULROOT, &vp);
    918          1.395  dholland 	if (error != 0)
    919           1.31       cgd 		return (error);
    920          1.395  dholland 	mp = vp->v_mount;
    921          1.444  dholland 
    922          1.445  dholland 	switch (args->qc_op) {
    923          1.444  dholland 	    case QUOTACTL_STAT:
    924          1.446  dholland 		error = do_sys_quotactl_stat(mp, args->u.stat.qc_info);
    925          1.444  dholland 		break;
    926          1.444  dholland 	    case QUOTACTL_IDTYPESTAT:
    927          1.444  dholland 		error = do_sys_quotactl_idtypestat(mp,
    928          1.445  dholland 				args->u.idtypestat.qc_idtype,
    929          1.445  dholland 				args->u.idtypestat.qc_info);
    930          1.444  dholland 		break;
    931          1.444  dholland 	    case QUOTACTL_OBJTYPESTAT:
    932          1.444  dholland 		error = do_sys_quotactl_objtypestat(mp,
    933          1.445  dholland 				args->u.objtypestat.qc_objtype,
    934          1.445  dholland 				args->u.objtypestat.qc_info);
    935          1.444  dholland 		break;
    936          1.444  dholland 	    case QUOTACTL_GET:
    937          1.444  dholland 		error = do_sys_quotactl_get(mp,
    938          1.445  dholland 				args->u.get.qc_key,
    939          1.446  dholland 				args->u.get.qc_val);
    940          1.444  dholland 		break;
    941          1.444  dholland 	    case QUOTACTL_PUT:
    942          1.444  dholland 		error = do_sys_quotactl_put(mp,
    943          1.445  dholland 				args->u.put.qc_key,
    944          1.445  dholland 				args->u.put.qc_val);
    945          1.444  dholland 		break;
    946          1.444  dholland 	    case QUOTACTL_DELETE:
    947          1.445  dholland 		error = do_sys_quotactl_delete(mp, args->u.delete.qc_key);
    948          1.444  dholland 		break;
    949          1.444  dholland 	    case QUOTACTL_CURSOROPEN:
    950          1.444  dholland 		error = do_sys_quotactl_cursoropen(mp,
    951          1.445  dholland 				args->u.cursoropen.qc_cursor);
    952          1.444  dholland 		break;
    953          1.444  dholland 	    case QUOTACTL_CURSORCLOSE:
    954          1.444  dholland 		error = do_sys_quotactl_cursorclose(mp,
    955          1.445  dholland 				args->u.cursorclose.qc_cursor);
    956          1.444  dholland 		break;
    957          1.444  dholland 	    case QUOTACTL_CURSORSKIPIDTYPE:
    958          1.444  dholland 		error = do_sys_quotactl_cursorskipidtype(mp,
    959          1.445  dholland 				args->u.cursorskipidtype.qc_cursor,
    960          1.445  dholland 				args->u.cursorskipidtype.qc_idtype);
    961          1.444  dholland 		break;
    962          1.444  dholland 	    case QUOTACTL_CURSORGET:
    963          1.444  dholland 		error = do_sys_quotactl_cursorget(mp,
    964          1.445  dholland 				args->u.cursorget.qc_cursor,
    965          1.445  dholland 				args->u.cursorget.qc_keys,
    966          1.445  dholland 				args->u.cursorget.qc_vals,
    967          1.445  dholland 				args->u.cursorget.qc_maxnum,
    968          1.445  dholland 				args->u.cursorget.qc_ret);
    969          1.444  dholland 		break;
    970          1.444  dholland 	    case QUOTACTL_CURSORATEND:
    971          1.444  dholland 		error = do_sys_quotactl_cursoratend(mp,
    972          1.445  dholland 				args->u.cursoratend.qc_cursor,
    973          1.445  dholland 				args->u.cursoratend.qc_ret);
    974          1.444  dholland 		break;
    975          1.444  dholland 	    case QUOTACTL_CURSORREWIND:
    976          1.444  dholland 		error = do_sys_quotactl_cursorrewind(mp,
    977          1.445  dholland 				args->u.cursorrewind.qc_cursor);
    978          1.444  dholland 		break;
    979          1.444  dholland 	    case QUOTACTL_QUOTAON:
    980          1.444  dholland 		error = do_sys_quotactl_quotaon(mp,
    981          1.445  dholland 				args->u.quotaon.qc_idtype,
    982          1.445  dholland 				args->u.quotaon.qc_quotafile);
    983          1.444  dholland 		break;
    984          1.444  dholland 	    case QUOTACTL_QUOTAOFF:
    985          1.444  dholland 		error = do_sys_quotactl_quotaoff(mp,
    986          1.445  dholland 				args->u.quotaoff.qc_idtype);
    987          1.444  dholland 		break;
    988          1.444  dholland 	    default:
    989          1.444  dholland 		error = EINVAL;
    990          1.444  dholland 		break;
    991          1.444  dholland 	}
    992          1.444  dholland 
    993          1.395  dholland 	vrele(vp);
    994          1.444  dholland 	return error;
    995           1.31       cgd }
    996           1.31       cgd 
    997          1.445  dholland /* ARGSUSED */
    998          1.445  dholland int
    999          1.445  dholland sys___quotactl(struct lwp *l, const struct sys___quotactl_args *uap,
   1000          1.445  dholland     register_t *retval)
   1001          1.445  dholland {
   1002          1.445  dholland 	/* {
   1003          1.445  dholland 		syscallarg(const char *) path;
   1004          1.445  dholland 		syscallarg(struct quotactl_args *) args;
   1005          1.445  dholland 	} */
   1006          1.445  dholland 	struct quotactl_args args;
   1007          1.445  dholland 	int error;
   1008          1.445  dholland 
   1009          1.445  dholland 	error = copyin(SCARG(uap, args), &args, sizeof(args));
   1010          1.445  dholland 	if (error) {
   1011          1.445  dholland 		return error;
   1012          1.445  dholland 	}
   1013          1.445  dholland 
   1014          1.445  dholland 	return do_sys_quotactl(SCARG(uap, path), &args);
   1015          1.445  dholland }
   1016          1.445  dholland 
   1017          1.206  christos int
   1018          1.234  christos dostatvfs(struct mount *mp, struct statvfs *sp, struct lwp *l, int flags,
   1019          1.185  christos     int root)
   1020          1.185  christos {
   1021          1.234  christos 	struct cwdinfo *cwdi = l->l_proc->p_cwdi;
   1022          1.185  christos 	int error = 0;
   1023          1.185  christos 
   1024          1.185  christos 	/*
   1025          1.185  christos 	 * If MNT_NOWAIT or MNT_LAZY is specified, do not
   1026          1.204       dbj 	 * refresh the fsstat cache. MNT_WAIT or MNT_LAZY
   1027          1.185  christos 	 * overrides MNT_NOWAIT.
   1028          1.185  christos 	 */
   1029          1.185  christos 	if (flags == MNT_NOWAIT	|| flags == MNT_LAZY ||
   1030          1.185  christos 	    (flags != MNT_WAIT && flags != 0)) {
   1031          1.185  christos 		memcpy(sp, &mp->mnt_stat, sizeof(*sp));
   1032          1.185  christos 		goto done;
   1033          1.185  christos 	}
   1034          1.205  junyoung 
   1035          1.211  jdolecek 	/* Get the filesystem stats now */
   1036          1.211  jdolecek 	memset(sp, 0, sizeof(*sp));
   1037          1.332     pooka 	if ((error = VFS_STATVFS(mp, sp)) != 0) {
   1038          1.185  christos 		return error;
   1039          1.185  christos 	}
   1040          1.185  christos 
   1041          1.185  christos 	if (cwdi->cwdi_rdir == NULL)
   1042          1.185  christos 		(void)memcpy(&mp->mnt_stat, sp, sizeof(mp->mnt_stat));
   1043          1.185  christos done:
   1044          1.185  christos 	if (cwdi->cwdi_rdir != NULL) {
   1045          1.185  christos 		size_t len;
   1046          1.185  christos 		char *bp;
   1047          1.364  christos 		char c;
   1048          1.236      yamt 		char *path = PNBUF_GET();
   1049          1.185  christos 
   1050          1.185  christos 		bp = path + MAXPATHLEN;
   1051          1.185  christos 		*--bp = '\0';
   1052          1.328        ad 		rw_enter(&cwdi->cwdi_lock, RW_READER);
   1053          1.185  christos 		error = getcwd_common(cwdi->cwdi_rdir, rootvnode, &bp, path,
   1054          1.234  christos 		    MAXPATHLEN / 2, 0, l);
   1055          1.328        ad 		rw_exit(&cwdi->cwdi_lock);
   1056          1.185  christos 		if (error) {
   1057          1.236      yamt 			PNBUF_PUT(path);
   1058          1.185  christos 			return error;
   1059          1.185  christos 		}
   1060          1.185  christos 		len = strlen(bp);
   1061          1.387  christos 		if (len != 1) {
   1062          1.387  christos 			/*
   1063          1.387  christos 			 * for mount points that are below our root, we can see
   1064          1.387  christos 			 * them, so we fix up the pathname and return them. The
   1065          1.387  christos 			 * rest we cannot see, so we don't allow viewing the
   1066          1.387  christos 			 * data.
   1067          1.387  christos 			 */
   1068          1.387  christos 			if (strncmp(bp, sp->f_mntonname, len) == 0 &&
   1069          1.387  christos 			    ((c = sp->f_mntonname[len]) == '/' || c == '\0')) {
   1070          1.387  christos 				(void)strlcpy(sp->f_mntonname,
   1071          1.388     enami 				    c == '\0' ? "/" : &sp->f_mntonname[len],
   1072          1.187    itojun 				    sizeof(sp->f_mntonname));
   1073          1.387  christos 			} else {
   1074          1.387  christos 				if (root)
   1075          1.387  christos 					(void)strlcpy(sp->f_mntonname, "/",
   1076          1.387  christos 					    sizeof(sp->f_mntonname));
   1077          1.387  christos 				else
   1078          1.387  christos 					error = EPERM;
   1079          1.387  christos 			}
   1080          1.185  christos 		}
   1081          1.236      yamt 		PNBUF_PUT(path);
   1082          1.185  christos 	}
   1083          1.206  christos 	sp->f_flag = mp->mnt_flag & MNT_VISFLAGMASK;
   1084          1.185  christos 	return error;
   1085          1.185  christos }
   1086          1.185  christos 
   1087           1.31       cgd /*
   1088          1.311       dsl  * Get filesystem statistics by path.
   1089           1.31       cgd  */
   1090          1.311       dsl int
   1091          1.311       dsl do_sys_pstatvfs(struct lwp *l, const char *path, int flags, struct statvfs *sb)
   1092          1.311       dsl {
   1093          1.311       dsl 	struct mount *mp;
   1094          1.311       dsl 	int error;
   1095          1.395  dholland 	struct vnode *vp;
   1096          1.311       dsl 
   1097          1.395  dholland 	error = namei_simple_user(path, NSM_FOLLOW_TRYEMULROOT, &vp);
   1098          1.395  dholland 	if (error != 0)
   1099          1.311       dsl 		return error;
   1100          1.395  dholland 	mp = vp->v_mount;
   1101          1.311       dsl 	error = dostatvfs(mp, sb, l, flags, 1);
   1102          1.395  dholland 	vrele(vp);
   1103          1.311       dsl 	return error;
   1104          1.311       dsl }
   1105          1.311       dsl 
   1106           1.31       cgd /* ARGSUSED */
   1107           1.63  christos int
   1108          1.335       dsl sys_statvfs1(struct lwp *l, const struct sys_statvfs1_args *uap, register_t *retval)
   1109           1.56   thorpej {
   1110          1.335       dsl 	/* {
   1111           1.74       cgd 		syscallarg(const char *) path;
   1112          1.206  christos 		syscallarg(struct statvfs *) buf;
   1113          1.206  christos 		syscallarg(int) flags;
   1114          1.335       dsl 	} */
   1115          1.241      yamt 	struct statvfs *sb;
   1116           1.31       cgd 	int error;
   1117           1.31       cgd 
   1118          1.241      yamt 	sb = STATVFSBUF_GET();
   1119          1.311       dsl 	error = do_sys_pstatvfs(l, SCARG(uap, path), SCARG(uap, flags), sb);
   1120          1.311       dsl 	if (error == 0)
   1121          1.241      yamt 		error = copyout(sb, SCARG(uap, buf), sizeof(*sb));
   1122          1.241      yamt 	STATVFSBUF_PUT(sb);
   1123          1.241      yamt 	return error;
   1124           1.31       cgd }
   1125           1.31       cgd 
   1126           1.31       cgd /*
   1127          1.311       dsl  * Get filesystem statistics by fd.
   1128           1.31       cgd  */
   1129          1.311       dsl int
   1130          1.311       dsl do_sys_fstatvfs(struct lwp *l, int fd, int flags, struct statvfs *sb)
   1131          1.311       dsl {
   1132          1.346        ad 	file_t *fp;
   1133          1.311       dsl 	struct mount *mp;
   1134          1.311       dsl 	int error;
   1135          1.311       dsl 
   1136          1.346        ad 	/* fd_getvnode() will use the descriptor for us */
   1137          1.346        ad 	if ((error = fd_getvnode(fd, &fp)) != 0)
   1138          1.311       dsl 		return (error);
   1139          1.311       dsl 	mp = ((struct vnode *)fp->f_data)->v_mount;
   1140          1.346        ad 	error = dostatvfs(mp, sb, curlwp, flags, 1);
   1141          1.346        ad 	fd_putfile(fd);
   1142          1.311       dsl 	return error;
   1143          1.311       dsl }
   1144          1.311       dsl 
   1145           1.31       cgd /* ARGSUSED */
   1146           1.63  christos int
   1147          1.335       dsl sys_fstatvfs1(struct lwp *l, const struct sys_fstatvfs1_args *uap, register_t *retval)
   1148           1.56   thorpej {
   1149          1.335       dsl 	/* {
   1150           1.35       cgd 		syscallarg(int) fd;
   1151          1.206  christos 		syscallarg(struct statvfs *) buf;
   1152          1.206  christos 		syscallarg(int) flags;
   1153          1.335       dsl 	} */
   1154          1.241      yamt 	struct statvfs *sb;
   1155           1.31       cgd 	int error;
   1156           1.31       cgd 
   1157          1.241      yamt 	sb = STATVFSBUF_GET();
   1158          1.311       dsl 	error = do_sys_fstatvfs(l, SCARG(uap, fd), SCARG(uap, flags), sb);
   1159          1.316       dsl 	if (error == 0)
   1160          1.311       dsl 		error = copyout(sb, SCARG(uap, buf), sizeof(*sb));
   1161          1.241      yamt 	STATVFSBUF_PUT(sb);
   1162          1.185  christos 	return error;
   1163           1.31       cgd }
   1164           1.31       cgd 
   1165          1.185  christos 
   1166           1.31       cgd /*
   1167           1.31       cgd  * Get statistics on all filesystems.
   1168           1.31       cgd  */
   1169           1.63  christos int
   1170          1.311       dsl do_sys_getvfsstat(struct lwp *l, void *sfsp, size_t bufsize, int flags,
   1171          1.311       dsl     int (*copyfn)(const void *, void *, size_t), size_t entry_sz,
   1172          1.311       dsl     register_t *retval)
   1173           1.56   thorpej {
   1174          1.185  christos 	int root = 0;
   1175          1.179   thorpej 	struct proc *p = l->l_proc;
   1176          1.155  augustss 	struct mount *mp, *nmp;
   1177          1.241      yamt 	struct statvfs *sb;
   1178          1.206  christos 	size_t count, maxcount;
   1179          1.206  christos 	int error = 0;
   1180           1.31       cgd 
   1181          1.241      yamt 	sb = STATVFSBUF_GET();
   1182          1.311       dsl 	maxcount = bufsize / entry_sz;
   1183          1.329        ad 	mutex_enter(&mountlist_lock);
   1184          1.113      fvdl 	count = 0;
   1185          1.176      matt 	for (mp = CIRCLEQ_FIRST(&mountlist); mp != (void *)&mountlist;
   1186          1.176      matt 	     mp = nmp) {
   1187          1.358        ad 		if (vfs_busy(mp, &nmp)) {
   1188          1.113      fvdl 			continue;
   1189          1.113      fvdl 		}
   1190          1.113      fvdl 		if (sfsp && count < maxcount) {
   1191          1.311       dsl 			error = dostatvfs(mp, sb, l, flags, 0);
   1192          1.185  christos 			if (error) {
   1193          1.354        ad 				vfs_unbusy(mp, false, &nmp);
   1194          1.365  christos 				error = 0;
   1195           1.31       cgd 				continue;
   1196          1.113      fvdl 			}
   1197          1.311       dsl 			error = copyfn(sb, sfsp, entry_sz);
   1198          1.133   mycroft 			if (error) {
   1199          1.354        ad 				vfs_unbusy(mp, false, NULL);
   1200          1.241      yamt 				goto out;
   1201          1.133   mycroft 			}
   1202          1.311       dsl 			sfsp = (char *)sfsp + entry_sz;
   1203          1.241      yamt 			root |= strcmp(sb->f_mntonname, "/") == 0;
   1204           1.31       cgd 		}
   1205           1.31       cgd 		count++;
   1206          1.354        ad 		vfs_unbusy(mp, false, &nmp);
   1207           1.31       cgd 	}
   1208          1.358        ad 	mutex_exit(&mountlist_lock);
   1209          1.331     pooka 
   1210          1.185  christos 	if (root == 0 && p->p_cwdi->cwdi_rdir) {
   1211          1.185  christos 		/*
   1212          1.185  christos 		 * fake a root entry
   1213          1.185  christos 		 */
   1214          1.331     pooka 		error = dostatvfs(p->p_cwdi->cwdi_rdir->v_mount,
   1215          1.331     pooka 		    sb, l, flags, 1);
   1216          1.311       dsl 		if (error != 0)
   1217          1.241      yamt 			goto out;
   1218          1.365  christos 		if (sfsp) {
   1219          1.311       dsl 			error = copyfn(sb, sfsp, entry_sz);
   1220          1.365  christos 			if (error != 0)
   1221          1.365  christos 				goto out;
   1222          1.365  christos 		}
   1223          1.185  christos 		count++;
   1224          1.185  christos 	}
   1225           1.31       cgd 	if (sfsp && count > maxcount)
   1226           1.31       cgd 		*retval = maxcount;
   1227           1.31       cgd 	else
   1228           1.31       cgd 		*retval = count;
   1229          1.241      yamt out:
   1230          1.241      yamt 	STATVFSBUF_PUT(sb);
   1231          1.185  christos 	return error;
   1232           1.31       cgd }
   1233           1.31       cgd 
   1234          1.311       dsl int
   1235          1.335       dsl sys_getvfsstat(struct lwp *l, const struct sys_getvfsstat_args *uap, register_t *retval)
   1236          1.311       dsl {
   1237          1.335       dsl 	/* {
   1238          1.311       dsl 		syscallarg(struct statvfs *) buf;
   1239          1.311       dsl 		syscallarg(size_t) bufsize;
   1240          1.311       dsl 		syscallarg(int) flags;
   1241          1.335       dsl 	} */
   1242          1.311       dsl 
   1243          1.311       dsl 	return do_sys_getvfsstat(l, SCARG(uap, buf), SCARG(uap, bufsize),
   1244          1.311       dsl 	    SCARG(uap, flags), copyout, sizeof (struct statvfs), retval);
   1245          1.311       dsl }
   1246          1.311       dsl 
   1247           1.31       cgd /*
   1248           1.31       cgd  * Change current working directory to a given file descriptor.
   1249           1.31       cgd  */
   1250           1.31       cgd /* ARGSUSED */
   1251           1.63  christos int
   1252          1.335       dsl sys_fchdir(struct lwp *l, const struct sys_fchdir_args *uap, register_t *retval)
   1253           1.56   thorpej {
   1254          1.335       dsl 	/* {
   1255           1.35       cgd 		syscallarg(int) fd;
   1256          1.335       dsl 	} */
   1257          1.179   thorpej 	struct proc *p = l->l_proc;
   1258          1.328        ad 	struct cwdinfo *cwdi;
   1259           1.43   mycroft 	struct vnode *vp, *tdp;
   1260           1.43   mycroft 	struct mount *mp;
   1261          1.346        ad 	file_t *fp;
   1262          1.346        ad 	int error, fd;
   1263           1.31       cgd 
   1264          1.346        ad 	/* fd_getvnode() will use the descriptor for us */
   1265          1.346        ad 	fd = SCARG(uap, fd);
   1266          1.346        ad 	if ((error = fd_getvnode(fd, &fp)) != 0)
   1267           1.31       cgd 		return (error);
   1268          1.346        ad 	vp = fp->f_data;
   1269          1.131  sommerfe 
   1270          1.402     pooka 	vref(vp);
   1271          1.113      fvdl 	vn_lock(vp,  LK_EXCLUSIVE | LK_RETRY);
   1272           1.31       cgd 	if (vp->v_type != VDIR)
   1273           1.31       cgd 		error = ENOTDIR;
   1274           1.31       cgd 	else
   1275          1.332     pooka 		error = VOP_ACCESS(vp, VEXEC, l->l_cred);
   1276          1.303     pooka 	if (error) {
   1277          1.303     pooka 		vput(vp);
   1278          1.303     pooka 		goto out;
   1279          1.303     pooka 	}
   1280          1.304     pooka 	while ((mp = vp->v_mountedhere) != NULL) {
   1281          1.358        ad 		error = vfs_busy(mp, NULL);
   1282          1.298       chs 		vput(vp);
   1283          1.357   xtraeme 		if (error != 0)
   1284          1.356        ad 			goto out;
   1285          1.189   thorpej 		error = VFS_ROOT(mp, &tdp);
   1286          1.354        ad 		vfs_unbusy(mp, false, NULL);
   1287          1.113      fvdl 		if (error)
   1288          1.303     pooka 			goto out;
   1289           1.43   mycroft 		vp = tdp;
   1290           1.43   mycroft 	}
   1291          1.406   hannken 	VOP_UNLOCK(vp);
   1292          1.131  sommerfe 
   1293          1.131  sommerfe 	/*
   1294          1.131  sommerfe 	 * Disallow changing to a directory not under the process's
   1295          1.131  sommerfe 	 * current root directory (if there is one).
   1296          1.131  sommerfe 	 */
   1297          1.328        ad 	cwdi = p->p_cwdi;
   1298          1.328        ad 	rw_enter(&cwdi->cwdi_lock, RW_WRITER);
   1299          1.234  christos 	if (cwdi->cwdi_rdir && !vn_isunder(vp, NULL, l)) {
   1300          1.131  sommerfe 		vrele(vp);
   1301          1.135   thorpej 		error = EPERM;	/* operation not permitted */
   1302          1.328        ad 	} else {
   1303          1.328        ad 		vrele(cwdi->cwdi_cdir);
   1304          1.328        ad 		cwdi->cwdi_cdir = vp;
   1305          1.131  sommerfe 	}
   1306          1.328        ad 	rw_exit(&cwdi->cwdi_lock);
   1307          1.205  junyoung 
   1308          1.135   thorpej  out:
   1309          1.346        ad 	fd_putfile(fd);
   1310          1.135   thorpej 	return (error);
   1311           1.31       cgd }
   1312           1.31       cgd 
   1313           1.31       cgd /*
   1314          1.221   thorpej  * Change this process's notion of the root directory to a given file
   1315          1.221   thorpej  * descriptor.
   1316          1.131  sommerfe  */
   1317          1.131  sommerfe int
   1318          1.335       dsl sys_fchroot(struct lwp *l, const struct sys_fchroot_args *uap, register_t *retval)
   1319          1.131  sommerfe {
   1320          1.179   thorpej 	struct proc *p = l->l_proc;
   1321          1.131  sommerfe 	struct vnode	*vp;
   1322          1.346        ad 	file_t	*fp;
   1323          1.346        ad 	int		 error, fd = SCARG(uap, fd);
   1324          1.131  sommerfe 
   1325          1.268      elad 	if ((error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_CHROOT,
   1326          1.268      elad  	    KAUTH_REQ_SYSTEM_CHROOT_FCHROOT, NULL, NULL, NULL)) != 0)
   1327          1.131  sommerfe 		return error;
   1328          1.346        ad 	/* fd_getvnode() will use the descriptor for us */
   1329          1.397       bad 	if ((error = fd_getvnode(fd, &fp)) != 0)
   1330          1.131  sommerfe 		return error;
   1331          1.346        ad 	vp = fp->f_data;
   1332          1.131  sommerfe 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
   1333          1.131  sommerfe 	if (vp->v_type != VDIR)
   1334          1.131  sommerfe 		error = ENOTDIR;
   1335          1.131  sommerfe 	else
   1336          1.332     pooka 		error = VOP_ACCESS(vp, VEXEC, l->l_cred);
   1337          1.406   hannken 	VOP_UNLOCK(vp);
   1338          1.131  sommerfe 	if (error)
   1339          1.135   thorpej 		goto out;
   1340          1.402     pooka 	vref(vp);
   1341          1.131  sommerfe 
   1342          1.397       bad 	change_root(p->p_cwdi, vp, l);
   1343          1.328        ad 
   1344          1.135   thorpej  out:
   1345          1.346        ad 	fd_putfile(fd);
   1346          1.135   thorpej 	return (error);
   1347          1.131  sommerfe }
   1348          1.131  sommerfe 
   1349          1.131  sommerfe /*
   1350           1.31       cgd  * Change current working directory (``.'').
   1351           1.31       cgd  */
   1352           1.31       cgd /* ARGSUSED */
   1353           1.63  christos int
   1354          1.335       dsl sys_chdir(struct lwp *l, const struct sys_chdir_args *uap, register_t *retval)
   1355           1.56   thorpej {
   1356          1.335       dsl 	/* {
   1357           1.74       cgd 		syscallarg(const char *) path;
   1358          1.335       dsl 	} */
   1359          1.179   thorpej 	struct proc *p = l->l_proc;
   1360          1.328        ad 	struct cwdinfo *cwdi;
   1361           1.31       cgd 	int error;
   1362          1.397       bad 	struct vnode *vp;
   1363           1.31       cgd 
   1364          1.397       bad 	if ((error = chdir_lookup(SCARG(uap, path), UIO_USERSPACE,
   1365          1.397       bad 				  &vp, l)) != 0)
   1366           1.31       cgd 		return (error);
   1367          1.328        ad 	cwdi = p->p_cwdi;
   1368          1.328        ad 	rw_enter(&cwdi->cwdi_lock, RW_WRITER);
   1369          1.134   thorpej 	vrele(cwdi->cwdi_cdir);
   1370          1.397       bad 	cwdi->cwdi_cdir = vp;
   1371          1.328        ad 	rw_exit(&cwdi->cwdi_lock);
   1372           1.31       cgd 	return (0);
   1373           1.31       cgd }
   1374           1.31       cgd 
   1375           1.31       cgd /*
   1376           1.31       cgd  * Change notion of root (``/'') directory.
   1377           1.31       cgd  */
   1378           1.31       cgd /* ARGSUSED */
   1379           1.63  christos int
   1380          1.335       dsl sys_chroot(struct lwp *l, const struct sys_chroot_args *uap, register_t *retval)
   1381           1.56   thorpej {
   1382          1.335       dsl 	/* {
   1383           1.74       cgd 		syscallarg(const char *) path;
   1384          1.335       dsl 	} */
   1385          1.179   thorpej 	struct proc *p = l->l_proc;
   1386          1.397       bad 	int error;
   1387          1.131  sommerfe 	struct vnode *vp;
   1388           1.31       cgd 
   1389          1.268      elad 	if ((error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_CHROOT,
   1390          1.268      elad 	    KAUTH_REQ_SYSTEM_CHROOT_CHROOT, NULL, NULL, NULL)) != 0)
   1391           1.31       cgd 		return (error);
   1392          1.397       bad 	if ((error = chdir_lookup(SCARG(uap, path), UIO_USERSPACE,
   1393          1.397       bad 				  &vp, l)) != 0)
   1394           1.31       cgd 		return (error);
   1395          1.328        ad 
   1396          1.397       bad 	change_root(p->p_cwdi, vp, l);
   1397          1.397       bad 
   1398          1.397       bad 	return (0);
   1399          1.397       bad }
   1400          1.397       bad 
   1401          1.397       bad /*
   1402          1.397       bad  * Common routine for chroot and fchroot.
   1403          1.398       bad  * NB: callers need to properly authorize the change root operation.
   1404          1.397       bad  */
   1405          1.397       bad void
   1406          1.397       bad change_root(struct cwdinfo *cwdi, struct vnode *vp, struct lwp *l)
   1407          1.397       bad {
   1408          1.397       bad 
   1409          1.328        ad 	rw_enter(&cwdi->cwdi_lock, RW_WRITER);
   1410          1.134   thorpej 	if (cwdi->cwdi_rdir != NULL)
   1411          1.134   thorpej 		vrele(cwdi->cwdi_rdir);
   1412          1.134   thorpej 	cwdi->cwdi_rdir = vp;
   1413          1.131  sommerfe 
   1414          1.131  sommerfe 	/*
   1415          1.131  sommerfe 	 * Prevent escaping from chroot by putting the root under
   1416          1.131  sommerfe 	 * the working directory.  Silently chdir to / if we aren't
   1417          1.131  sommerfe 	 * already there.
   1418          1.131  sommerfe 	 */
   1419          1.234  christos 	if (!vn_isunder(cwdi->cwdi_cdir, vp, l)) {
   1420          1.131  sommerfe 		/*
   1421          1.131  sommerfe 		 * XXX would be more failsafe to change directory to a
   1422          1.131  sommerfe 		 * deadfs node here instead
   1423          1.131  sommerfe 		 */
   1424          1.134   thorpej 		vrele(cwdi->cwdi_cdir);
   1425          1.402     pooka 		vref(vp);
   1426          1.134   thorpej 		cwdi->cwdi_cdir = vp;
   1427          1.131  sommerfe 	}
   1428          1.328        ad 	rw_exit(&cwdi->cwdi_lock);
   1429           1.31       cgd }
   1430           1.31       cgd 
   1431           1.31       cgd /*
   1432           1.31       cgd  * Common routine for chroot and chdir.
   1433          1.409  dholland  * XXX "where" should be enum uio_seg
   1434           1.31       cgd  */
   1435          1.397       bad int
   1436          1.397       bad chdir_lookup(const char *path, int where, struct vnode **vpp, struct lwp *l)
   1437           1.31       cgd {
   1438          1.409  dholland 	struct pathbuf *pb;
   1439          1.397       bad 	struct nameidata nd;
   1440           1.31       cgd 	int error;
   1441           1.31       cgd 
   1442          1.409  dholland 	error = pathbuf_maybe_copyin(path, where, &pb);
   1443          1.409  dholland 	if (error) {
   1444          1.409  dholland 		return error;
   1445          1.409  dholland 	}
   1446          1.409  dholland 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | TRYEMULROOT, pb);
   1447          1.409  dholland 	if ((error = namei(&nd)) != 0) {
   1448          1.409  dholland 		pathbuf_destroy(pb);
   1449          1.409  dholland 		return error;
   1450          1.409  dholland 	}
   1451          1.397       bad 	*vpp = nd.ni_vp;
   1452          1.409  dholland 	pathbuf_destroy(pb);
   1453          1.409  dholland 
   1454          1.397       bad 	if ((*vpp)->v_type != VDIR)
   1455           1.31       cgd 		error = ENOTDIR;
   1456           1.31       cgd 	else
   1457          1.397       bad 		error = VOP_ACCESS(*vpp, VEXEC, l->l_cred);
   1458          1.205  junyoung 
   1459           1.31       cgd 	if (error)
   1460          1.397       bad 		vput(*vpp);
   1461          1.113      fvdl 	else
   1462          1.406   hannken 		VOP_UNLOCK(*vpp);
   1463           1.31       cgd 	return (error);
   1464           1.31       cgd }
   1465           1.31       cgd 
   1466           1.31       cgd /*
   1467          1.448    martin  * Internals of sys_open - path has already been converted into a pathbuf
   1468          1.448    martin  * (so we can easily reuse this function from other parts of the kernel,
   1469          1.448    martin  * like posix_spawn post-processing).
   1470           1.31       cgd  */
   1471          1.448    martin static int
   1472          1.448    martin do_open(lwp_t *l, struct pathbuf *pb, int open_flags, int open_mode, int *fd)
   1473           1.56   thorpej {
   1474          1.179   thorpej 	struct proc *p = l->l_proc;
   1475          1.134   thorpej 	struct cwdinfo *cwdi = p->p_cwdi;
   1476          1.346        ad 	file_t *fp;
   1477          1.135   thorpej 	struct vnode *vp;
   1478           1.31       cgd 	int flags, cmode;
   1479          1.422  christos 	int indx, error;
   1480           1.31       cgd 	struct nameidata nd;
   1481           1.31       cgd 
   1482          1.448    martin 	flags = FFLAGS(open_flags);
   1483          1.104   mycroft 	if ((flags & (FREAD | FWRITE)) == 0)
   1484          1.448    martin 		return EINVAL;
   1485          1.409  dholland 
   1486          1.409  dholland 	if ((error = fd_allocfile(&fp, &indx)) != 0) {
   1487          1.409  dholland 		return error;
   1488          1.409  dholland 	}
   1489      1.449.2.1       riz 
   1490          1.328        ad 	/* We're going to read cwdi->cwdi_cmask unlocked here. */
   1491          1.448    martin 	cmode = ((open_mode &~ cwdi->cwdi_cmask) & ALLPERMS) &~ S_ISTXT;
   1492          1.409  dholland 	NDINIT(&nd, LOOKUP, FOLLOW | TRYEMULROOT, pb);
   1493          1.194  jdolecek 	l->l_dupfd = -indx - 1;			/* XXX check for fdopen */
   1494           1.63  christos 	if ((error = vn_open(&nd, flags, cmode)) != 0) {
   1495          1.346        ad 		fd_abort(p, fp, indx);
   1496          1.213  christos 		if ((error == EDUPFD || error == EMOVEFD) &&
   1497          1.194  jdolecek 		    l->l_dupfd >= 0 &&			/* XXX from fdopen */
   1498           1.45   mycroft 		    (error =
   1499          1.346        ad 			fd_dupopen(l->l_dupfd, &indx, flags, error)) == 0) {
   1500          1.448    martin 			*fd = indx;
   1501      1.449.2.1       riz 			return 0;
   1502           1.45   mycroft 		}
   1503           1.45   mycroft 		if (error == ERESTART)
   1504           1.44   mycroft 			error = EINTR;
   1505          1.448    martin 		return error;
   1506           1.31       cgd 	}
   1507          1.331     pooka 
   1508          1.194  jdolecek 	l->l_dupfd = 0;
   1509           1.31       cgd 	vp = nd.ni_vp;
   1510          1.409  dholland 
   1511          1.422  christos 	if ((error = open_setfp(l, fp, vp, indx, flags)))
   1512          1.422  christos 		return error;
   1513          1.422  christos 
   1514          1.406   hannken 	VOP_UNLOCK(vp);
   1515          1.448    martin 	*fd = indx;
   1516          1.346        ad 	fd_affix(p, fp, indx);
   1517          1.448    martin 	return 0;
   1518          1.448    martin }
   1519          1.448    martin 
   1520          1.448    martin int
   1521          1.448    martin fd_open(const char *path, int open_flags, int open_mode, int *fd)
   1522          1.448    martin {
   1523          1.448    martin 	struct pathbuf *pb;
   1524      1.449.2.1       riz 	int error, oflags;
   1525          1.448    martin 
   1526          1.449    martin 	oflags = FFLAGS(open_flags);
   1527          1.449    martin 	if ((oflags & (FREAD | FWRITE)) == 0)
   1528          1.448    martin 		return EINVAL;
   1529          1.448    martin 
   1530          1.448    martin 	pb = pathbuf_create(path);
   1531          1.448    martin 	if (pb == NULL)
   1532          1.448    martin 		return ENOMEM;
   1533          1.448    martin 
   1534      1.449.2.1       riz 	error = do_open(curlwp, pb, open_flags, open_mode, fd);
   1535      1.449.2.1       riz 	pathbuf_destroy(pb);
   1536      1.449.2.1       riz 
   1537      1.449.2.1       riz 	return error;
   1538          1.448    martin }
   1539          1.448    martin 
   1540          1.448    martin /*
   1541          1.448    martin  * Check permissions, allocate an open file structure,
   1542          1.448    martin  * and call the device open routine if any.
   1543          1.448    martin  */
   1544          1.448    martin int
   1545          1.448    martin sys_open(struct lwp *l, const struct sys_open_args *uap, register_t *retval)
   1546          1.448    martin {
   1547          1.448    martin 	/* {
   1548          1.448    martin 		syscallarg(const char *) path;
   1549          1.448    martin 		syscallarg(int) flags;
   1550          1.448    martin 		syscallarg(int) mode;
   1551          1.448    martin 	} */
   1552          1.448    martin 	struct pathbuf *pb;
   1553          1.448    martin 	int result, flags, error;
   1554          1.448    martin 
   1555          1.448    martin 	flags = FFLAGS(SCARG(uap, flags));
   1556          1.448    martin 	if ((flags & (FREAD | FWRITE)) == 0)
   1557      1.449.2.1       riz 		return EINVAL;
   1558          1.448    martin 
   1559          1.448    martin 	error = pathbuf_copyin(SCARG(uap, path), &pb);
   1560          1.448    martin 	if (error)
   1561          1.448    martin 		return error;
   1562          1.448    martin 
   1563          1.448    martin 	error = do_open(l, pb, SCARG(uap, flags), SCARG(uap, mode), &result);
   1564      1.449.2.1       riz 	pathbuf_destroy(pb);
   1565          1.448    martin 
   1566          1.448    martin 	*retval = result;
   1567      1.449.2.1       riz 	return error;
   1568          1.137  wrstuden }
   1569          1.137  wrstuden 
   1570          1.433      manu int
   1571          1.433      manu sys_openat(struct lwp *l, const struct sys_openat_args *uap, register_t *retval)
   1572          1.433      manu {
   1573          1.433      manu 	/* {
   1574          1.433      manu 		syscallarg(int) fd;
   1575          1.433      manu 		syscallarg(const char *) path;
   1576          1.433      manu 		syscallarg(int) flags;
   1577          1.433      manu 		syscallarg(int) mode;
   1578          1.433      manu 	} */
   1579          1.433      manu 
   1580          1.433      manu 	return ENOSYS;
   1581          1.433      manu }
   1582          1.433      manu 
   1583          1.249      yamt static void
   1584          1.249      yamt vfs__fhfree(fhandle_t *fhp)
   1585          1.249      yamt {
   1586          1.249      yamt 	size_t fhsize;
   1587          1.249      yamt 
   1588          1.249      yamt 	if (fhp == NULL) {
   1589          1.249      yamt 		return;
   1590          1.249      yamt 	}
   1591          1.249      yamt 	fhsize = FHANDLE_SIZE(fhp);
   1592          1.249      yamt 	kmem_free(fhp, fhsize);
   1593          1.249      yamt }
   1594          1.249      yamt 
   1595          1.137  wrstuden /*
   1596          1.243      yamt  * vfs_composefh: compose a filehandle.
   1597          1.243      yamt  */
   1598          1.243      yamt 
   1599          1.243      yamt int
   1600          1.244    martin vfs_composefh(struct vnode *vp, fhandle_t *fhp, size_t *fh_size)
   1601          1.243      yamt {
   1602          1.243      yamt 	struct mount *mp;
   1603          1.250      yamt 	struct fid *fidp;
   1604          1.243      yamt 	int error;
   1605          1.250      yamt 	size_t needfhsize;
   1606          1.250      yamt 	size_t fidsize;
   1607          1.243      yamt 
   1608          1.243      yamt 	mp = vp->v_mount;
   1609          1.250      yamt 	fidp = NULL;
   1610          1.252    martin 	if (*fh_size < FHANDLE_SIZE_MIN) {
   1611          1.250      yamt 		fidsize = 0;
   1612          1.244    martin 	} else {
   1613          1.250      yamt 		fidsize = *fh_size - offsetof(fhandle_t, fh_fid);
   1614          1.250      yamt 		if (fhp != NULL) {
   1615          1.250      yamt 			memset(fhp, 0, *fh_size);
   1616          1.250      yamt 			fhp->fh_fsid = mp->mnt_stat.f_fsidx;
   1617          1.250      yamt 			fidp = &fhp->fh_fid;
   1618          1.250      yamt 		}
   1619          1.244    martin 	}
   1620          1.250      yamt 	error = VFS_VPTOFH(vp, fidp, &fidsize);
   1621          1.250      yamt 	needfhsize = FHANDLE_SIZE_FROM_FILEID_SIZE(fidsize);
   1622          1.250      yamt 	if (error == 0 && *fh_size < needfhsize) {
   1623          1.250      yamt 		error = E2BIG;
   1624          1.250      yamt 	}
   1625          1.250      yamt 	*fh_size = needfhsize;
   1626          1.243      yamt 	return error;
   1627          1.243      yamt }
   1628          1.243      yamt 
   1629          1.249      yamt int
   1630          1.249      yamt vfs_composefh_alloc(struct vnode *vp, fhandle_t **fhpp)
   1631          1.249      yamt {
   1632          1.249      yamt 	struct mount *mp;
   1633          1.249      yamt 	fhandle_t *fhp;
   1634          1.249      yamt 	size_t fhsize;
   1635          1.249      yamt 	size_t fidsize;
   1636          1.249      yamt 	int error;
   1637          1.249      yamt 
   1638          1.249      yamt 	*fhpp = NULL;
   1639          1.249      yamt 	mp = vp->v_mount;
   1640          1.255  christos 	fidsize = 0;
   1641          1.249      yamt 	error = VFS_VPTOFH(vp, NULL, &fidsize);
   1642          1.249      yamt 	KASSERT(error != 0);
   1643          1.249      yamt 	if (error != E2BIG) {
   1644          1.249      yamt 		goto out;
   1645          1.249      yamt 	}
   1646          1.250      yamt 	fhsize = FHANDLE_SIZE_FROM_FILEID_SIZE(fidsize);
   1647          1.249      yamt 	fhp = kmem_zalloc(fhsize, KM_SLEEP);
   1648          1.249      yamt 	if (fhp == NULL) {
   1649          1.249      yamt 		error = ENOMEM;
   1650          1.249      yamt 		goto out;
   1651          1.249      yamt 	}
   1652          1.249      yamt 	fhp->fh_fsid = mp->mnt_stat.f_fsidx;
   1653          1.249      yamt 	error = VFS_VPTOFH(vp, &fhp->fh_fid, &fidsize);
   1654          1.249      yamt 	if (error == 0) {
   1655          1.249      yamt 		KASSERT((FHANDLE_SIZE(fhp) == fhsize &&
   1656          1.249      yamt 		    FHANDLE_FILEID(fhp)->fid_len == fidsize));
   1657          1.249      yamt 		*fhpp = fhp;
   1658          1.249      yamt 	} else {
   1659          1.249      yamt 		kmem_free(fhp, fhsize);
   1660          1.249      yamt 	}
   1661          1.249      yamt out:
   1662          1.249      yamt 	return error;
   1663          1.249      yamt }
   1664          1.249      yamt 
   1665          1.249      yamt void
   1666          1.249      yamt vfs_composefh_free(fhandle_t *fhp)
   1667          1.249      yamt {
   1668          1.249      yamt 
   1669          1.249      yamt 	vfs__fhfree(fhp);
   1670          1.249      yamt }
   1671          1.249      yamt 
   1672          1.243      yamt /*
   1673          1.248      yamt  * vfs_fhtovp: lookup a vnode by a filehandle.
   1674          1.248      yamt  */
   1675          1.248      yamt 
   1676          1.248      yamt int
   1677          1.248      yamt vfs_fhtovp(fhandle_t *fhp, struct vnode **vpp)
   1678          1.248      yamt {
   1679          1.248      yamt 	struct mount *mp;
   1680          1.248      yamt 	int error;
   1681          1.248      yamt 
   1682          1.248      yamt 	*vpp = NULL;
   1683          1.248      yamt 	mp = vfs_getvfs(FHANDLE_FSID(fhp));
   1684          1.248      yamt 	if (mp == NULL) {
   1685          1.248      yamt 		error = ESTALE;
   1686          1.248      yamt 		goto out;
   1687          1.248      yamt 	}
   1688          1.248      yamt 	if (mp->mnt_op->vfs_fhtovp == NULL) {
   1689          1.248      yamt 		error = EOPNOTSUPP;
   1690          1.248      yamt 		goto out;
   1691          1.248      yamt 	}
   1692          1.248      yamt 	error = VFS_FHTOVP(mp, FHANDLE_FILEID(fhp), vpp);
   1693          1.248      yamt out:
   1694          1.248      yamt 	return error;
   1695          1.248      yamt }
   1696          1.248      yamt 
   1697          1.248      yamt /*
   1698          1.265      yamt  * vfs_copyinfh_alloc: allocate and copyin a filehandle, given
   1699          1.263    martin  * the needed size.
   1700          1.263    martin  */
   1701          1.263    martin 
   1702          1.263    martin int
   1703          1.265      yamt vfs_copyinfh_alloc(const void *ufhp, size_t fhsize, fhandle_t **fhpp)
   1704          1.263    martin {
   1705          1.263    martin 	fhandle_t *fhp;
   1706          1.263    martin 	int error;
   1707          1.263    martin 
   1708          1.263    martin 	*fhpp = NULL;
   1709          1.250      yamt 	if (fhsize > FHANDLE_SIZE_MAX) {
   1710          1.250      yamt 		return EINVAL;
   1711          1.250      yamt 	}
   1712          1.265      yamt 	if (fhsize < FHANDLE_SIZE_MIN) {
   1713          1.265      yamt 		return EINVAL;
   1714          1.265      yamt 	}
   1715          1.267      yamt again:
   1716          1.248      yamt 	fhp = kmem_alloc(fhsize, KM_SLEEP);
   1717          1.248      yamt 	if (fhp == NULL) {
   1718          1.248      yamt 		return ENOMEM;
   1719          1.248      yamt 	}
   1720          1.248      yamt 	error = copyin(ufhp, fhp, fhsize);
   1721          1.248      yamt 	if (error == 0) {
   1722          1.265      yamt 		/* XXX this check shouldn't be here */
   1723          1.265      yamt 		if (FHANDLE_SIZE(fhp) == fhsize) {
   1724          1.263    martin 			*fhpp = fhp;
   1725          1.263    martin 			return 0;
   1726          1.267      yamt 		} else if (fhsize == NFSX_V2FH && FHANDLE_SIZE(fhp) < fhsize) {
   1727          1.267      yamt 			/*
   1728          1.267      yamt 			 * a kludge for nfsv2 padded handles.
   1729          1.267      yamt 			 */
   1730          1.267      yamt 			size_t sz;
   1731          1.267      yamt 
   1732          1.267      yamt 			sz = FHANDLE_SIZE(fhp);
   1733          1.267      yamt 			kmem_free(fhp, fhsize);
   1734          1.267      yamt 			fhsize = sz;
   1735          1.267      yamt 			goto again;
   1736          1.264      yamt 		} else {
   1737          1.265      yamt 			/*
   1738          1.265      yamt 			 * userland told us wrong size.
   1739          1.265      yamt 			 */
   1740          1.263    martin 		    	error = EINVAL;
   1741          1.264      yamt 		}
   1742          1.248      yamt 	}
   1743          1.263    martin 	kmem_free(fhp, fhsize);
   1744          1.248      yamt 	return error;
   1745          1.248      yamt }
   1746          1.248      yamt 
   1747          1.248      yamt void
   1748          1.248      yamt vfs_copyinfh_free(fhandle_t *fhp)
   1749          1.248      yamt {
   1750          1.248      yamt 
   1751          1.249      yamt 	vfs__fhfree(fhp);
   1752          1.248      yamt }
   1753          1.248      yamt 
   1754          1.248      yamt /*
   1755          1.137  wrstuden  * Get file handle system call
   1756          1.137  wrstuden  */
   1757          1.137  wrstuden int
   1758          1.335       dsl sys___getfh30(struct lwp *l, const struct sys___getfh30_args *uap, register_t *retval)
   1759          1.137  wrstuden {
   1760          1.335       dsl 	/* {
   1761          1.137  wrstuden 		syscallarg(char *) fname;
   1762          1.137  wrstuden 		syscallarg(fhandle_t *) fhp;
   1763          1.244    martin 		syscallarg(size_t *) fh_size;
   1764          1.335       dsl 	} */
   1765          1.155  augustss 	struct vnode *vp;
   1766          1.244    martin 	fhandle_t *fh;
   1767          1.137  wrstuden 	int error;
   1768          1.409  dholland 	struct pathbuf *pb;
   1769          1.137  wrstuden 	struct nameidata nd;
   1770          1.244    martin 	size_t sz;
   1771          1.249      yamt 	size_t usz;
   1772          1.137  wrstuden 
   1773          1.137  wrstuden 	/*
   1774          1.137  wrstuden 	 * Must be super user
   1775          1.137  wrstuden 	 */
   1776          1.268      elad 	error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_FILEHANDLE,
   1777          1.268      elad 	    0, NULL, NULL, NULL);
   1778          1.137  wrstuden 	if (error)
   1779          1.137  wrstuden 		return (error);
   1780          1.409  dholland 
   1781          1.409  dholland 	error = pathbuf_copyin(SCARG(uap, fname), &pb);
   1782          1.409  dholland 	if (error) {
   1783          1.409  dholland 		return error;
   1784          1.409  dholland 	}
   1785          1.409  dholland 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | TRYEMULROOT, pb);
   1786          1.137  wrstuden 	error = namei(&nd);
   1787          1.409  dholland 	if (error) {
   1788          1.409  dholland 		pathbuf_destroy(pb);
   1789          1.409  dholland 		return error;
   1790          1.409  dholland 	}
   1791          1.137  wrstuden 	vp = nd.ni_vp;
   1792          1.409  dholland 	pathbuf_destroy(pb);
   1793          1.409  dholland 
   1794          1.249      yamt 	error = vfs_composefh_alloc(vp, &fh);
   1795          1.247      yamt 	vput(vp);
   1796          1.249      yamt 	if (error != 0) {
   1797          1.249      yamt 		goto out;
   1798          1.249      yamt 	}
   1799          1.249      yamt 	error = copyin(SCARG(uap, fh_size), &usz, sizeof(size_t));
   1800          1.249      yamt 	if (error != 0) {
   1801          1.249      yamt 		goto out;
   1802          1.249      yamt 	}
   1803          1.249      yamt 	sz = FHANDLE_SIZE(fh);
   1804          1.249      yamt 	error = copyout(&sz, SCARG(uap, fh_size), sizeof(size_t));
   1805          1.249      yamt 	if (error != 0) {
   1806          1.249      yamt 		goto out;
   1807          1.244    martin 	}
   1808          1.249      yamt 	if (usz >= sz) {
   1809          1.249      yamt 		error = copyout(fh, SCARG(uap, fhp), sz);
   1810          1.249      yamt 	} else {
   1811          1.249      yamt 		error = E2BIG;
   1812          1.244    martin 	}
   1813          1.249      yamt out:
   1814          1.249      yamt 	vfs_composefh_free(fh);
   1815          1.137  wrstuden 	return (error);
   1816          1.137  wrstuden }
   1817          1.137  wrstuden 
   1818          1.137  wrstuden /*
   1819          1.137  wrstuden  * Open a file given a file handle.
   1820          1.137  wrstuden  *
   1821          1.137  wrstuden  * Check permissions, allocate an open file structure,
   1822          1.137  wrstuden  * and call the device open routine if any.
   1823          1.137  wrstuden  */
   1824          1.265      yamt 
   1825          1.137  wrstuden int
   1826          1.265      yamt dofhopen(struct lwp *l, const void *ufhp, size_t fhsize, int oflags,
   1827          1.265      yamt     register_t *retval)
   1828          1.137  wrstuden {
   1829          1.346        ad 	file_t *fp;
   1830          1.139  wrstuden 	struct vnode *vp = NULL;
   1831          1.257        ad 	kauth_cred_t cred = l->l_cred;
   1832          1.346        ad 	file_t *nfp;
   1833          1.422  christos 	int indx, error = 0;
   1834          1.137  wrstuden 	struct vattr va;
   1835          1.248      yamt 	fhandle_t *fh;
   1836          1.265      yamt 	int flags;
   1837          1.346        ad 	proc_t *p;
   1838          1.346        ad 
   1839          1.346        ad 	p = curproc;
   1840          1.137  wrstuden 
   1841          1.137  wrstuden 	/*
   1842          1.137  wrstuden 	 * Must be super user
   1843          1.137  wrstuden 	 */
   1844          1.269      elad 	if ((error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_FILEHANDLE,
   1845          1.270      elad 	    0, NULL, NULL, NULL)))
   1846          1.137  wrstuden 		return (error);
   1847          1.137  wrstuden 
   1848          1.265      yamt 	flags = FFLAGS(oflags);
   1849          1.137  wrstuden 	if ((flags & (FREAD | FWRITE)) == 0)
   1850          1.137  wrstuden 		return (EINVAL);
   1851          1.137  wrstuden 	if ((flags & O_CREAT))
   1852          1.137  wrstuden 		return (EINVAL);
   1853          1.346        ad 	if ((error = fd_allocfile(&nfp, &indx)) != 0)
   1854          1.137  wrstuden 		return (error);
   1855          1.137  wrstuden 	fp = nfp;
   1856          1.265      yamt 	error = vfs_copyinfh_alloc(ufhp, fhsize, &fh);
   1857          1.248      yamt 	if (error != 0) {
   1858          1.139  wrstuden 		goto bad;
   1859          1.139  wrstuden 	}
   1860          1.248      yamt 	error = vfs_fhtovp(fh, &vp);
   1861          1.248      yamt 	if (error != 0) {
   1862          1.139  wrstuden 		goto bad;
   1863          1.139  wrstuden 	}
   1864          1.137  wrstuden 
   1865          1.137  wrstuden 	/* Now do an effective vn_open */
   1866          1.137  wrstuden 
   1867          1.137  wrstuden 	if (vp->v_type == VSOCK) {
   1868          1.137  wrstuden 		error = EOPNOTSUPP;
   1869          1.137  wrstuden 		goto bad;
   1870          1.137  wrstuden 	}
   1871          1.333      yamt 	error = vn_openchk(vp, cred, flags);
   1872          1.333      yamt 	if (error != 0)
   1873          1.333      yamt 		goto bad;
   1874          1.137  wrstuden 	if (flags & O_TRUNC) {
   1875          1.406   hannken 		VOP_UNLOCK(vp);			/* XXX */
   1876          1.137  wrstuden 		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);   /* XXX */
   1877          1.402     pooka 		vattr_null(&va);
   1878          1.137  wrstuden 		va.va_size = 0;
   1879          1.332     pooka 		error = VOP_SETATTR(vp, &va, cred);
   1880          1.197   hannken 		if (error)
   1881          1.137  wrstuden 			goto bad;
   1882          1.137  wrstuden 	}
   1883          1.332     pooka 	if ((error = VOP_OPEN(vp, flags, cred)) != 0)
   1884          1.137  wrstuden 		goto bad;
   1885          1.346        ad 	if (flags & FWRITE) {
   1886          1.429     rmind 		mutex_enter(vp->v_interlock);
   1887          1.137  wrstuden 		vp->v_writecount++;
   1888          1.429     rmind 		mutex_exit(vp->v_interlock);
   1889          1.346        ad 	}
   1890          1.137  wrstuden 
   1891          1.137  wrstuden 	/* done with modified vn_open, now finish what sys_open does. */
   1892          1.422  christos 	if ((error = open_setfp(l, fp, vp, indx, flags)))
   1893          1.422  christos 		return error;
   1894          1.137  wrstuden 
   1895          1.406   hannken 	VOP_UNLOCK(vp);
   1896          1.137  wrstuden 	*retval = indx;
   1897          1.346        ad 	fd_affix(p, fp, indx);
   1898          1.248      yamt 	vfs_copyinfh_free(fh);
   1899          1.137  wrstuden 	return (0);
   1900          1.139  wrstuden 
   1901          1.137  wrstuden bad:
   1902          1.346        ad 	fd_abort(p, fp, indx);
   1903          1.139  wrstuden 	if (vp != NULL)
   1904          1.139  wrstuden 		vput(vp);
   1905          1.248      yamt 	vfs_copyinfh_free(fh);
   1906          1.137  wrstuden 	return (error);
   1907          1.137  wrstuden }
   1908          1.137  wrstuden 
   1909          1.137  wrstuden int
   1910          1.335       dsl sys___fhopen40(struct lwp *l, const struct sys___fhopen40_args *uap, register_t *retval)
   1911          1.137  wrstuden {
   1912          1.335       dsl 	/* {
   1913          1.263    martin 		syscallarg(const void *) fhp;
   1914          1.263    martin 		syscallarg(size_t) fh_size;
   1915          1.265      yamt 		syscallarg(int) flags;
   1916          1.335       dsl 	} */
   1917          1.265      yamt 
   1918          1.265      yamt 	return dofhopen(l, SCARG(uap, fhp), SCARG(uap, fh_size),
   1919          1.265      yamt 	    SCARG(uap, flags), retval);
   1920          1.265      yamt }
   1921          1.265      yamt 
   1922          1.306       dsl int
   1923          1.306       dsl do_fhstat(struct lwp *l, const void *ufhp, size_t fhsize, struct stat *sb)
   1924          1.306       dsl {
   1925          1.137  wrstuden 	int error;
   1926          1.248      yamt 	fhandle_t *fh;
   1927          1.137  wrstuden 	struct vnode *vp;
   1928          1.137  wrstuden 
   1929          1.137  wrstuden 	/*
   1930          1.137  wrstuden 	 * Must be super user
   1931          1.137  wrstuden 	 */
   1932          1.268      elad 	if ((error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_FILEHANDLE,
   1933          1.270      elad 	    0, NULL, NULL, NULL)))
   1934          1.137  wrstuden 		return (error);
   1935          1.137  wrstuden 
   1936          1.265      yamt 	error = vfs_copyinfh_alloc(ufhp, fhsize, &fh);
   1937          1.306       dsl 	if (error != 0)
   1938          1.306       dsl 		return error;
   1939          1.306       dsl 
   1940          1.248      yamt 	error = vfs_fhtovp(fh, &vp);
   1941          1.306       dsl 	vfs_copyinfh_free(fh);
   1942          1.306       dsl 	if (error != 0)
   1943          1.306       dsl 		return error;
   1944          1.306       dsl 
   1945          1.346        ad 	error = vn_stat(vp, sb);
   1946          1.137  wrstuden 	vput(vp);
   1947          1.248      yamt 	return error;
   1948          1.137  wrstuden }
   1949          1.137  wrstuden 
   1950          1.265      yamt 
   1951          1.137  wrstuden /* ARGSUSED */
   1952          1.137  wrstuden int
   1953          1.383  christos sys___fhstat50(struct lwp *l, const struct sys___fhstat50_args *uap, register_t *retval)
   1954          1.137  wrstuden {
   1955          1.335       dsl 	/* {
   1956          1.265      yamt 		syscallarg(const void *) fhp;
   1957          1.263    martin 		syscallarg(size_t) fh_size;
   1958          1.265      yamt 		syscallarg(struct stat *) sb;
   1959          1.335       dsl 	} */
   1960          1.306       dsl 	struct stat sb;
   1961          1.306       dsl 	int error;
   1962          1.265      yamt 
   1963          1.306       dsl 	error = do_fhstat(l, SCARG(uap, fhp), SCARG(uap, fh_size), &sb);
   1964          1.306       dsl 	if (error)
   1965          1.306       dsl 		return error;
   1966          1.306       dsl 	return copyout(&sb, SCARG(uap, sb), sizeof(sb));
   1967          1.265      yamt }
   1968          1.265      yamt 
   1969          1.306       dsl int
   1970          1.306       dsl do_fhstatvfs(struct lwp *l, const void *ufhp, size_t fhsize, struct statvfs *sb,
   1971          1.306       dsl     int flags)
   1972          1.306       dsl {
   1973          1.248      yamt 	fhandle_t *fh;
   1974          1.137  wrstuden 	struct mount *mp;
   1975          1.137  wrstuden 	struct vnode *vp;
   1976          1.137  wrstuden 	int error;
   1977          1.137  wrstuden 
   1978          1.137  wrstuden 	/*
   1979          1.137  wrstuden 	 * Must be super user
   1980          1.137  wrstuden 	 */
   1981          1.268      elad 	if ((error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_FILEHANDLE,
   1982          1.270      elad 	    0, NULL, NULL, NULL)))
   1983          1.206  christos 		return error;
   1984          1.137  wrstuden 
   1985          1.265      yamt 	error = vfs_copyinfh_alloc(ufhp, fhsize, &fh);
   1986          1.306       dsl 	if (error != 0)
   1987          1.306       dsl 		return error;
   1988          1.306       dsl 
   1989          1.248      yamt 	error = vfs_fhtovp(fh, &vp);
   1990          1.306       dsl 	vfs_copyinfh_free(fh);
   1991          1.306       dsl 	if (error != 0)
   1992          1.306       dsl 		return error;
   1993          1.306       dsl 
   1994          1.137  wrstuden 	mp = vp->v_mount;
   1995          1.306       dsl 	error = dostatvfs(mp, sb, l, flags, 1);
   1996          1.137  wrstuden 	vput(vp);
   1997          1.241      yamt 	return error;
   1998           1.31       cgd }
   1999           1.31       cgd 
   2000          1.265      yamt /* ARGSUSED */
   2001          1.265      yamt int
   2002          1.335       dsl sys___fhstatvfs140(struct lwp *l, const struct sys___fhstatvfs140_args *uap, register_t *retval)
   2003          1.265      yamt {
   2004          1.335       dsl 	/* {
   2005          1.266      yamt 		syscallarg(const void *) fhp;
   2006          1.265      yamt 		syscallarg(size_t) fh_size;
   2007          1.265      yamt 		syscallarg(struct statvfs *) buf;
   2008          1.265      yamt 		syscallarg(int)	flags;
   2009          1.335       dsl 	} */
   2010          1.306       dsl 	struct statvfs *sb = STATVFSBUF_GET();
   2011          1.306       dsl 	int error;
   2012          1.265      yamt 
   2013          1.306       dsl 	error = do_fhstatvfs(l, SCARG(uap, fhp), SCARG(uap, fh_size), sb,
   2014          1.306       dsl 	    SCARG(uap, flags));
   2015          1.306       dsl 	if (error == 0)
   2016          1.306       dsl 		error = copyout(sb, SCARG(uap, buf), sizeof(*sb));
   2017          1.306       dsl 	STATVFSBUF_PUT(sb);
   2018          1.306       dsl 	return error;
   2019          1.265      yamt }
   2020          1.265      yamt 
   2021           1.31       cgd /*
   2022           1.31       cgd  * Create a special file.
   2023           1.31       cgd  */
   2024           1.31       cgd /* ARGSUSED */
   2025           1.63  christos int
   2026          1.383  christos sys___mknod50(struct lwp *l, const struct sys___mknod50_args *uap,
   2027          1.383  christos     register_t *retval)
   2028           1.56   thorpej {
   2029          1.335       dsl 	/* {
   2030           1.74       cgd 		syscallarg(const char *) path;
   2031          1.383  christos 		syscallarg(mode_t) mode;
   2032          1.383  christos 		syscallarg(dev_t) dev;
   2033          1.335       dsl 	} */
   2034          1.383  christos 	return do_sys_mknod(l, SCARG(uap, path), SCARG(uap, mode),
   2035          1.399      haad 	    SCARG(uap, dev), retval, UIO_USERSPACE);
   2036          1.383  christos }
   2037          1.383  christos 
   2038          1.383  christos int
   2039          1.433      manu sys_mknodat(struct lwp *l, const struct sys_mknodat_args *uap,
   2040          1.433      manu     register_t *retval)
   2041          1.433      manu {
   2042          1.433      manu 	/* {
   2043          1.433      manu 		syscallarg(int) fd;
   2044          1.433      manu 		syscallarg(const char *) path;
   2045          1.433      manu 		syscallarg(mode_t) mode;
   2046          1.433      manu 		syscallarg(uint32_t) dev;
   2047          1.433      manu 	} */
   2048          1.433      manu 
   2049          1.433      manu 	return ENOSYS;
   2050          1.433      manu }
   2051          1.433      manu 
   2052          1.433      manu int
   2053          1.383  christos do_sys_mknod(struct lwp *l, const char *pathname, mode_t mode, dev_t dev,
   2054          1.399      haad     register_t *retval, enum uio_seg seg)
   2055          1.383  christos {
   2056          1.179   thorpej 	struct proc *p = l->l_proc;
   2057          1.155  augustss 	struct vnode *vp;
   2058           1.31       cgd 	struct vattr vattr;
   2059          1.301     pooka 	int error, optype;
   2060          1.409  dholland 	struct pathbuf *pb;
   2061          1.315  christos 	struct nameidata nd;
   2062          1.409  dholland 	const char *pathstring;
   2063           1.31       cgd 
   2064          1.268      elad 	if ((error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_MKNOD,
   2065          1.268      elad 	    0, NULL, NULL, NULL)) != 0)
   2066           1.31       cgd 		return (error);
   2067          1.301     pooka 
   2068          1.301     pooka 	optype = VOP_MKNOD_DESCOFFSET;
   2069          1.315  christos 
   2070          1.409  dholland 	error = pathbuf_maybe_copyin(pathname, seg, &pb);
   2071          1.409  dholland 	if (error) {
   2072          1.409  dholland 		return error;
   2073          1.409  dholland 	}
   2074          1.409  dholland 	pathstring = pathbuf_stringcopy_get(pb);
   2075          1.409  dholland 	if (pathstring == NULL) {
   2076          1.409  dholland 		pathbuf_destroy(pb);
   2077          1.409  dholland 		return ENOMEM;
   2078          1.409  dholland 	}
   2079          1.315  christos 
   2080          1.409  dholland 	NDINIT(&nd, CREATE, LOCKPARENT | TRYEMULROOT, pb);
   2081           1.63  christos 	if ((error = namei(&nd)) != 0)
   2082          1.314  christos 		goto out;
   2083           1.31       cgd 	vp = nd.ni_vp;
   2084          1.409  dholland 
   2085           1.43   mycroft 	if (vp != NULL)
   2086           1.31       cgd 		error = EEXIST;
   2087           1.43   mycroft 	else {
   2088          1.402     pooka 		vattr_null(&vattr);
   2089          1.328        ad 		/* We will read cwdi->cwdi_cmask unlocked. */
   2090          1.383  christos 		vattr.va_mode = (mode & ALLPERMS) &~ p->p_cwdi->cwdi_cmask;
   2091          1.383  christos 		vattr.va_rdev = dev;
   2092           1.43   mycroft 
   2093          1.383  christos 		switch (mode & S_IFMT) {
   2094           1.43   mycroft 		case S_IFMT:	/* used by badsect to flag bad sectors */
   2095           1.43   mycroft 			vattr.va_type = VBAD;
   2096           1.43   mycroft 			break;
   2097           1.43   mycroft 		case S_IFCHR:
   2098           1.43   mycroft 			vattr.va_type = VCHR;
   2099           1.43   mycroft 			break;
   2100           1.43   mycroft 		case S_IFBLK:
   2101           1.43   mycroft 			vattr.va_type = VBLK;
   2102           1.43   mycroft 			break;
   2103           1.43   mycroft 		case S_IFWHT:
   2104          1.301     pooka 			optype = VOP_WHITEOUT_DESCOFFSET;
   2105          1.301     pooka 			break;
   2106          1.301     pooka 		case S_IFREG:
   2107          1.314  christos #if NVERIEXEC > 0
   2108          1.409  dholland 			error = veriexec_openchk(l, nd.ni_vp, pathstring,
   2109          1.314  christos 			    O_CREAT);
   2110          1.314  christos #endif /* NVERIEXEC > 0 */
   2111          1.301     pooka 			vattr.va_type = VREG;
   2112          1.302     pooka 			vattr.va_rdev = VNOVAL;
   2113          1.301     pooka 			optype = VOP_CREATE_DESCOFFSET;
   2114           1.43   mycroft 			break;
   2115           1.43   mycroft 		default:
   2116           1.43   mycroft 			error = EINVAL;
   2117           1.43   mycroft 			break;
   2118           1.43   mycroft 		}
   2119           1.31       cgd 	}
   2120          1.432    martin 	if (error == 0 && optype == VOP_MKNOD_DESCOFFSET
   2121          1.432    martin 	    && vattr.va_rdev == VNOVAL)
   2122          1.431   hannken 		error = EINVAL;
   2123           1.43   mycroft 	if (!error) {
   2124          1.301     pooka 		switch (optype) {
   2125          1.301     pooka 		case VOP_WHITEOUT_DESCOFFSET:
   2126           1.43   mycroft 			error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, CREATE);
   2127           1.43   mycroft 			if (error)
   2128           1.43   mycroft 				VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
   2129           1.43   mycroft 			vput(nd.ni_dvp);
   2130          1.301     pooka 			break;
   2131          1.301     pooka 
   2132          1.301     pooka 		case VOP_MKNOD_DESCOFFSET:
   2133           1.43   mycroft 			error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp,
   2134           1.43   mycroft 						&nd.ni_cnd, &vattr);
   2135          1.168     assar 			if (error == 0)
   2136          1.168     assar 				vput(nd.ni_vp);
   2137          1.301     pooka 			break;
   2138          1.301     pooka 
   2139          1.301     pooka 		case VOP_CREATE_DESCOFFSET:
   2140          1.301     pooka 			error = VOP_CREATE(nd.ni_dvp, &nd.ni_vp,
   2141          1.301     pooka 						&nd.ni_cnd, &vattr);
   2142          1.301     pooka 			if (error == 0)
   2143          1.301     pooka 				vput(nd.ni_vp);
   2144          1.301     pooka 			break;
   2145           1.43   mycroft 		}
   2146           1.43   mycroft 	} else {
   2147           1.43   mycroft 		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
   2148           1.43   mycroft 		if (nd.ni_dvp == vp)
   2149           1.43   mycroft 			vrele(nd.ni_dvp);
   2150           1.43   mycroft 		else
   2151           1.43   mycroft 			vput(nd.ni_dvp);
   2152           1.43   mycroft 		if (vp)
   2153           1.43   mycroft 			vrele(vp);
   2154           1.31       cgd 	}
   2155          1.314  christos out:
   2156          1.409  dholland 	pathbuf_stringcopy_put(pb, pathstring);
   2157          1.409  dholland 	pathbuf_destroy(pb);
   2158           1.31       cgd 	return (error);
   2159           1.31       cgd }
   2160           1.31       cgd 
   2161           1.31       cgd /*
   2162           1.31       cgd  * Create a named pipe.
   2163           1.31       cgd  */
   2164           1.31       cgd /* ARGSUSED */
   2165           1.63  christos int
   2166          1.335       dsl sys_mkfifo(struct lwp *l, const struct sys_mkfifo_args *uap, register_t *retval)
   2167           1.56   thorpej {
   2168          1.335       dsl 	/* {
   2169           1.74       cgd 		syscallarg(const char *) path;
   2170           1.35       cgd 		syscallarg(int) mode;
   2171          1.335       dsl 	} */
   2172          1.179   thorpej 	struct proc *p = l->l_proc;
   2173           1.31       cgd 	struct vattr vattr;
   2174           1.31       cgd 	int error;
   2175          1.409  dholland 	struct pathbuf *pb;
   2176           1.31       cgd 	struct nameidata nd;
   2177           1.31       cgd 
   2178          1.409  dholland 	error = pathbuf_copyin(SCARG(uap, path), &pb);
   2179          1.409  dholland 	if (error) {
   2180          1.409  dholland 		return error;
   2181          1.409  dholland 	}
   2182          1.409  dholland 	NDINIT(&nd, CREATE, LOCKPARENT | TRYEMULROOT, pb);
   2183          1.409  dholland 	if ((error = namei(&nd)) != 0) {
   2184          1.409  dholland 		pathbuf_destroy(pb);
   2185          1.409  dholland 		return error;
   2186          1.409  dholland 	}
   2187           1.31       cgd 	if (nd.ni_vp != NULL) {
   2188           1.31       cgd 		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
   2189           1.31       cgd 		if (nd.ni_dvp == nd.ni_vp)
   2190           1.31       cgd 			vrele(nd.ni_dvp);
   2191           1.31       cgd 		else
   2192           1.31       cgd 			vput(nd.ni_dvp);
   2193           1.31       cgd 		vrele(nd.ni_vp);
   2194          1.409  dholland 		pathbuf_destroy(pb);
   2195           1.31       cgd 		return (EEXIST);
   2196           1.31       cgd 	}
   2197          1.402     pooka 	vattr_null(&vattr);
   2198           1.31       cgd 	vattr.va_type = VFIFO;
   2199          1.328        ad 	/* We will read cwdi->cwdi_cmask unlocked. */
   2200          1.134   thorpej 	vattr.va_mode = (SCARG(uap, mode) & ALLPERMS) &~ p->p_cwdi->cwdi_cmask;
   2201          1.168     assar 	error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
   2202          1.168     assar 	if (error == 0)
   2203          1.168     assar 		vput(nd.ni_vp);
   2204          1.409  dholland 	pathbuf_destroy(pb);
   2205          1.168     assar 	return (error);
   2206           1.31       cgd }
   2207           1.31       cgd 
   2208          1.433      manu int
   2209          1.433      manu sys_mkfifoat(struct lwp *l, const struct sys_mkfifoat_args *uap,
   2210          1.433      manu     register_t *retval)
   2211          1.433      manu {
   2212          1.433      manu 	/* {
   2213          1.433      manu 		syscallarg(int) fd;
   2214          1.433      manu 		syscallarg(const char *) path;
   2215          1.433      manu 		syscallarg(int) mode;
   2216          1.433      manu 	} */
   2217          1.433      manu 
   2218          1.433      manu 	return ENOSYS;
   2219          1.433      manu }
   2220           1.31       cgd /*
   2221           1.31       cgd  * Make a hard file link.
   2222           1.31       cgd  */
   2223           1.31       cgd /* ARGSUSED */
   2224          1.433      manu static int
   2225          1.433      manu do_sys_link(struct lwp *l, const char *path, const char *link,
   2226          1.433      manu 	    int follow, register_t *retval)
   2227           1.56   thorpej {
   2228          1.155  augustss 	struct vnode *vp;
   2229          1.409  dholland 	struct pathbuf *linkpb;
   2230           1.31       cgd 	struct nameidata nd;
   2231          1.433      manu 	namei_simple_flags_t namei_simple_flags;
   2232           1.31       cgd 	int error;
   2233           1.31       cgd 
   2234          1.433      manu 	if (follow)
   2235          1.433      manu 		namei_simple_flags = NSM_FOLLOW_TRYEMULROOT;
   2236          1.433      manu 	else
   2237          1.433      manu 		namei_simple_flags =  NSM_NOFOLLOW_TRYEMULROOT;
   2238          1.433      manu 
   2239          1.433      manu 	error = namei_simple_user(path, namei_simple_flags, &vp);
   2240          1.395  dholland 	if (error != 0)
   2241           1.31       cgd 		return (error);
   2242          1.433      manu 	error = pathbuf_copyin(link, &linkpb);
   2243          1.409  dholland 	if (error) {
   2244          1.409  dholland 		goto out1;
   2245          1.409  dholland 	}
   2246          1.409  dholland 	NDINIT(&nd, CREATE, LOCKPARENT | TRYEMULROOT, linkpb);
   2247           1.66   mycroft 	if ((error = namei(&nd)) != 0)
   2248          1.409  dholland 		goto out2;
   2249           1.66   mycroft 	if (nd.ni_vp) {
   2250           1.66   mycroft 		error = EEXIST;
   2251          1.419      yamt 		goto abortop;
   2252          1.419      yamt 	}
   2253          1.423     rmind 	/* Prevent hard links on directories. */
   2254          1.423     rmind 	if (vp->v_type == VDIR) {
   2255          1.423     rmind 		error = EPERM;
   2256          1.423     rmind 		goto abortop;
   2257          1.423     rmind 	}
   2258          1.423     rmind 	/* Prevent cross-mount operation. */
   2259          1.419      yamt 	if (nd.ni_dvp->v_mount != vp->v_mount) {
   2260          1.419      yamt 		error = EXDEV;
   2261          1.419      yamt 		goto abortop;
   2262           1.31       cgd 	}
   2263           1.66   mycroft 	error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd);
   2264          1.409  dholland out2:
   2265          1.409  dholland 	pathbuf_destroy(linkpb);
   2266          1.409  dholland out1:
   2267           1.31       cgd 	vrele(vp);
   2268           1.31       cgd 	return (error);
   2269          1.419      yamt abortop:
   2270          1.419      yamt 	VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
   2271          1.419      yamt 	if (nd.ni_dvp == nd.ni_vp)
   2272          1.419      yamt 		vrele(nd.ni_dvp);
   2273          1.419      yamt 	else
   2274          1.419      yamt 		vput(nd.ni_dvp);
   2275          1.419      yamt 	if (nd.ni_vp != NULL)
   2276          1.419      yamt 		vrele(nd.ni_vp);
   2277          1.419      yamt 	goto out2;
   2278           1.31       cgd }
   2279           1.31       cgd 
   2280           1.63  christos int
   2281          1.433      manu sys_link(struct lwp *l, const struct sys_link_args *uap, register_t *retval)
   2282          1.433      manu {
   2283          1.433      manu 	/* {
   2284          1.433      manu 		syscallarg(const char *) path;
   2285          1.433      manu 		syscallarg(const char *) link;
   2286          1.433      manu 	} */
   2287          1.433      manu 	const char *path = SCARG(uap, path);
   2288          1.433      manu 	const char *link = SCARG(uap, link);
   2289          1.433      manu 
   2290          1.433      manu 	return do_sys_link(l, path, link, 1, retval);
   2291          1.433      manu }
   2292          1.433      manu 
   2293          1.433      manu int
   2294          1.433      manu sys_linkat(struct lwp *l, const struct sys_linkat_args *uap,
   2295          1.433      manu     register_t *retval)
   2296          1.433      manu {
   2297          1.433      manu 	/* {
   2298          1.433      manu 		syscallarg(int) fd1;
   2299          1.433      manu 		syscallarg(const char *) name1;
   2300          1.433      manu 		syscallarg(int) fd2;
   2301          1.433      manu 		syscallarg(const char *) name2;
   2302          1.433      manu 		syscallarg(int) flags;
   2303          1.433      manu 	} */
   2304          1.433      manu 	const char *name1 = SCARG(uap, name1);
   2305          1.433      manu 	const char *name2 = SCARG(uap, name2);
   2306          1.433      manu 	int follow;
   2307          1.433      manu 
   2308          1.433      manu 	/*
   2309          1.433      manu 	 * Specified fd1 and fd2 are not yet implemented
   2310          1.433      manu 	 */
   2311          1.433      manu 	if ((SCARG(uap, fd1) != AT_FDCWD) || (SCARG(uap, fd2) != AT_FDCWD))
   2312          1.433      manu 		return ENOSYS;
   2313          1.433      manu 
   2314          1.433      manu 	follow = SCARG(uap, flags) & AT_SYMLINK_FOLLOW;
   2315          1.433      manu 
   2316          1.433      manu 	return do_sys_link(l, name1, name2, follow, retval);
   2317          1.433      manu }
   2318          1.433      manu 
   2319          1.433      manu 
   2320          1.433      manu int
   2321          1.407     pooka do_sys_symlink(const char *patharg, const char *link, enum uio_seg seg)
   2322           1.56   thorpej {
   2323          1.407     pooka 	struct proc *p = curproc;
   2324           1.31       cgd 	struct vattr vattr;
   2325           1.31       cgd 	char *path;
   2326           1.31       cgd 	int error;
   2327          1.409  dholland 	struct pathbuf *linkpb;
   2328           1.31       cgd 	struct nameidata nd;
   2329           1.31       cgd 
   2330          1.161   thorpej 	path = PNBUF_GET();
   2331          1.407     pooka 	if (seg == UIO_USERSPACE) {
   2332          1.407     pooka 		if ((error = copyinstr(patharg, path, MAXPATHLEN, NULL)) != 0)
   2333          1.409  dholland 			goto out1;
   2334          1.409  dholland 		if ((error = pathbuf_copyin(link, &linkpb)) != 0)
   2335          1.409  dholland 			goto out1;
   2336          1.407     pooka 	} else {
   2337          1.407     pooka 		KASSERT(strlen(patharg) < MAXPATHLEN);
   2338          1.407     pooka 		strcpy(path, patharg);
   2339          1.409  dholland 		linkpb = pathbuf_create(link);
   2340          1.409  dholland 		if (linkpb == NULL) {
   2341          1.409  dholland 			error = ENOMEM;
   2342          1.409  dholland 			goto out1;
   2343          1.409  dholland 		}
   2344          1.407     pooka 	}
   2345          1.433      manu 	ktrkuser("symlink-target", path, strlen(path));
   2346          1.433      manu 
   2347          1.409  dholland 	NDINIT(&nd, CREATE, LOCKPARENT | TRYEMULROOT, linkpb);
   2348           1.63  christos 	if ((error = namei(&nd)) != 0)
   2349          1.409  dholland 		goto out2;
   2350           1.31       cgd 	if (nd.ni_vp) {
   2351           1.31       cgd 		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
   2352           1.31       cgd 		if (nd.ni_dvp == nd.ni_vp)
   2353           1.31       cgd 			vrele(nd.ni_dvp);
   2354           1.31       cgd 		else
   2355           1.31       cgd 			vput(nd.ni_dvp);
   2356           1.31       cgd 		vrele(nd.ni_vp);
   2357           1.31       cgd 		error = EEXIST;
   2358          1.409  dholland 		goto out2;
   2359           1.31       cgd 	}
   2360          1.402     pooka 	vattr_null(&vattr);
   2361          1.230      jmmv 	vattr.va_type = VLNK;
   2362          1.328        ad 	/* We will read cwdi->cwdi_cmask unlocked. */
   2363          1.134   thorpej 	vattr.va_mode = ACCESSPERMS &~ p->p_cwdi->cwdi_cmask;
   2364           1.31       cgd 	error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr, path);
   2365          1.168     assar 	if (error == 0)
   2366          1.168     assar 		vput(nd.ni_vp);
   2367          1.409  dholland out2:
   2368          1.409  dholland 	pathbuf_destroy(linkpb);
   2369          1.409  dholland out1:
   2370          1.161   thorpej 	PNBUF_PUT(path);
   2371           1.31       cgd 	return (error);
   2372           1.31       cgd }
   2373           1.31       cgd 
   2374           1.31       cgd /*
   2375          1.407     pooka  * Make a symbolic link.
   2376          1.407     pooka  */
   2377          1.407     pooka /* ARGSUSED */
   2378          1.407     pooka int
   2379          1.407     pooka sys_symlink(struct lwp *l, const struct sys_symlink_args *uap, register_t *retval)
   2380          1.407     pooka {
   2381          1.407     pooka 	/* {
   2382          1.407     pooka 		syscallarg(const char *) path;
   2383          1.407     pooka 		syscallarg(const char *) link;
   2384          1.407     pooka 	} */
   2385          1.407     pooka 
   2386          1.407     pooka 	return do_sys_symlink(SCARG(uap, path), SCARG(uap, link),
   2387          1.407     pooka 	    UIO_USERSPACE);
   2388          1.407     pooka }
   2389          1.407     pooka 
   2390          1.433      manu int
   2391          1.433      manu sys_symlinkat(struct lwp *l, const struct sys_symlinkat_args *uap,
   2392          1.433      manu     register_t *retval)
   2393          1.433      manu {
   2394          1.433      manu 	/* {
   2395          1.433      manu 		syscallarg(int) fd;
   2396          1.433      manu 		syscallarg(const char *) path;
   2397          1.433      manu 		syscallarg(const char *) link;
   2398          1.433      manu 	} */
   2399          1.433      manu 
   2400          1.433      manu 	return ENOSYS;
   2401          1.433      manu }
   2402          1.433      manu 
   2403          1.407     pooka /*
   2404           1.43   mycroft  * Delete a whiteout from the filesystem.
   2405           1.43   mycroft  */
   2406           1.43   mycroft /* ARGSUSED */
   2407           1.63  christos int
   2408          1.335       dsl sys_undelete(struct lwp *l, const struct sys_undelete_args *uap, register_t *retval)
   2409           1.56   thorpej {
   2410          1.335       dsl 	/* {
   2411           1.74       cgd 		syscallarg(const char *) path;
   2412          1.335       dsl 	} */
   2413           1.43   mycroft 	int error;
   2414          1.409  dholland 	struct pathbuf *pb;
   2415           1.43   mycroft 	struct nameidata nd;
   2416           1.43   mycroft 
   2417          1.409  dholland 	error = pathbuf_copyin(SCARG(uap, path), &pb);
   2418          1.409  dholland 	if (error) {
   2419          1.409  dholland 		return error;
   2420          1.409  dholland 	}
   2421          1.409  dholland 
   2422          1.409  dholland 	NDINIT(&nd, DELETE, LOCKPARENT | DOWHITEOUT | TRYEMULROOT, pb);
   2423           1.43   mycroft 	error = namei(&nd);
   2424          1.409  dholland 	if (error) {
   2425          1.409  dholland 		pathbuf_destroy(pb);
   2426           1.43   mycroft 		return (error);
   2427          1.409  dholland 	}
   2428           1.43   mycroft 
   2429           1.43   mycroft 	if (nd.ni_vp != NULLVP || !(nd.ni_cnd.cn_flags & ISWHITEOUT)) {
   2430           1.43   mycroft 		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
   2431           1.43   mycroft 		if (nd.ni_dvp == nd.ni_vp)
   2432           1.43   mycroft 			vrele(nd.ni_dvp);
   2433           1.43   mycroft 		else
   2434           1.43   mycroft 			vput(nd.ni_dvp);
   2435           1.43   mycroft 		if (nd.ni_vp)
   2436           1.43   mycroft 			vrele(nd.ni_vp);
   2437          1.409  dholland 		pathbuf_destroy(pb);
   2438           1.43   mycroft 		return (EEXIST);
   2439           1.43   mycroft 	}
   2440           1.63  christos 	if ((error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, DELETE)) != 0)
   2441           1.43   mycroft 		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
   2442           1.43   mycroft 	vput(nd.ni_dvp);
   2443          1.409  dholland 	pathbuf_destroy(pb);
   2444           1.43   mycroft 	return (error);
   2445           1.43   mycroft }
   2446           1.43   mycroft 
   2447           1.43   mycroft /*
   2448           1.31       cgd  * Delete a name from the filesystem.
   2449           1.31       cgd  */
   2450           1.31       cgd /* ARGSUSED */
   2451           1.63  christos int
   2452          1.335       dsl sys_unlink(struct lwp *l, const struct sys_unlink_args *uap, register_t *retval)
   2453           1.56   thorpej {
   2454          1.335       dsl 	/* {
   2455           1.74       cgd 		syscallarg(const char *) path;
   2456          1.335       dsl 	} */
   2457          1.336        ad 
   2458          1.336        ad 	return do_sys_unlink(SCARG(uap, path), UIO_USERSPACE);
   2459          1.336        ad }
   2460          1.336        ad 
   2461          1.336        ad int
   2462          1.433      manu sys_unlinkat(struct lwp *l, const struct sys_unlinkat_args *uap,
   2463          1.433      manu     register_t *retval)
   2464          1.433      manu {
   2465          1.433      manu 	/* {
   2466          1.433      manu 		syscallarg(int) fd;
   2467          1.433      manu 		syscallarg(const char *) path;
   2468          1.433      manu 	} */
   2469          1.433      manu 
   2470          1.433      manu 	return ENOSYS;
   2471          1.433      manu }
   2472          1.433      manu 
   2473          1.433      manu int
   2474          1.336        ad do_sys_unlink(const char *arg, enum uio_seg seg)
   2475          1.336        ad {
   2476          1.155  augustss 	struct vnode *vp;
   2477           1.31       cgd 	int error;
   2478          1.409  dholland 	struct pathbuf *pb;
   2479           1.31       cgd 	struct nameidata nd;
   2480          1.409  dholland 	const char *pathstring;
   2481           1.31       cgd 
   2482          1.409  dholland 	error = pathbuf_maybe_copyin(arg, seg, &pb);
   2483          1.409  dholland 	if (error) {
   2484          1.409  dholland 		return error;
   2485          1.409  dholland 	}
   2486          1.409  dholland 	pathstring = pathbuf_stringcopy_get(pb);
   2487          1.409  dholland 	if (pathstring == NULL) {
   2488          1.409  dholland 		pathbuf_destroy(pb);
   2489          1.409  dholland 		return ENOMEM;
   2490          1.409  dholland 	}
   2491          1.313      elad 
   2492          1.409  dholland 	NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF | TRYEMULROOT, pb);
   2493           1.63  christos 	if ((error = namei(&nd)) != 0)
   2494          1.313      elad 		goto out;
   2495           1.31       cgd 	vp = nd.ni_vp;
   2496           1.31       cgd 
   2497           1.66   mycroft 	/*
   2498           1.66   mycroft 	 * The root of a mounted filesystem cannot be deleted.
   2499           1.66   mycroft 	 */
   2500          1.329        ad 	if (vp->v_vflag & VV_ROOT) {
   2501           1.43   mycroft 		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
   2502           1.43   mycroft 		if (nd.ni_dvp == vp)
   2503           1.43   mycroft 			vrele(nd.ni_dvp);
   2504           1.43   mycroft 		else
   2505           1.43   mycroft 			vput(nd.ni_dvp);
   2506           1.66   mycroft 		vput(vp);
   2507           1.66   mycroft 		error = EBUSY;
   2508           1.66   mycroft 		goto out;
   2509           1.31       cgd 	}
   2510          1.219     blymn 
   2511          1.256      elad #if NVERIEXEC > 0
   2512          1.222      elad 	/* Handle remove requests for veriexec entries. */
   2513          1.409  dholland 	if ((error = veriexec_removechk(curlwp, nd.ni_vp, pathstring)) != 0) {
   2514          1.219     blymn 		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
   2515          1.219     blymn 		if (nd.ni_dvp == vp)
   2516          1.219     blymn 			vrele(nd.ni_dvp);
   2517          1.219     blymn 		else
   2518          1.219     blymn 			vput(nd.ni_dvp);
   2519          1.219     blymn 		vput(vp);
   2520          1.219     blymn 		goto out;
   2521          1.219     blymn 	}
   2522          1.256      elad #endif /* NVERIEXEC > 0 */
   2523          1.256      elad 
   2524          1.253      elad #ifdef FILEASSOC
   2525          1.278      elad 	(void)fileassoc_file_delete(vp);
   2526          1.253      elad #endif /* FILEASSOC */
   2527           1.66   mycroft 	error = VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
   2528           1.66   mycroft out:
   2529          1.409  dholland 	pathbuf_stringcopy_put(pb, pathstring);
   2530          1.409  dholland 	pathbuf_destroy(pb);
   2531           1.31       cgd 	return (error);
   2532           1.31       cgd }
   2533           1.31       cgd 
   2534           1.31       cgd /*
   2535           1.31       cgd  * Reposition read/write file offset.
   2536           1.31       cgd  */
   2537           1.63  christos int
   2538          1.335       dsl sys_lseek(struct lwp *l, const struct sys_lseek_args *uap, register_t *retval)
   2539           1.56   thorpej {
   2540          1.335       dsl 	/* {
   2541           1.35       cgd 		syscallarg(int) fd;
   2542           1.35       cgd 		syscallarg(int) pad;
   2543           1.35       cgd 		syscallarg(off_t) offset;
   2544           1.35       cgd 		syscallarg(int) whence;
   2545          1.335       dsl 	} */
   2546          1.257        ad 	kauth_cred_t cred = l->l_cred;
   2547          1.346        ad 	file_t *fp;
   2548           1.84    kleink 	struct vnode *vp;
   2549           1.31       cgd 	struct vattr vattr;
   2550          1.155  augustss 	off_t newoff;
   2551          1.346        ad 	int error, fd;
   2552          1.346        ad 
   2553          1.346        ad 	fd = SCARG(uap, fd);
   2554           1.31       cgd 
   2555          1.346        ad 	if ((fp = fd_getfile(fd)) == NULL)
   2556           1.31       cgd 		return (EBADF);
   2557           1.84    kleink 
   2558          1.346        ad 	vp = fp->f_data;
   2559          1.135   thorpej 	if (fp->f_type != DTYPE_VNODE || vp->v_type == VFIFO) {
   2560          1.135   thorpej 		error = ESPIPE;
   2561          1.135   thorpej 		goto out;
   2562          1.135   thorpej 	}
   2563           1.84    kleink 
   2564           1.35       cgd 	switch (SCARG(uap, whence)) {
   2565           1.92    kleink 	case SEEK_CUR:
   2566           1.84    kleink 		newoff = fp->f_offset + SCARG(uap, offset);
   2567           1.31       cgd 		break;
   2568           1.92    kleink 	case SEEK_END:
   2569          1.440   hannken 		vn_lock(vp, LK_SHARED | LK_RETRY);
   2570          1.332     pooka 		error = VOP_GETATTR(vp, &vattr, cred);
   2571          1.440   hannken 		VOP_UNLOCK(vp);
   2572          1.328        ad 		if (error) {
   2573          1.135   thorpej 			goto out;
   2574          1.328        ad 		}
   2575           1.84    kleink 		newoff = SCARG(uap, offset) + vattr.va_size;
   2576           1.31       cgd 		break;
   2577           1.92    kleink 	case SEEK_SET:
   2578           1.84    kleink 		newoff = SCARG(uap, offset);
   2579           1.31       cgd 		break;
   2580           1.31       cgd 	default:
   2581          1.135   thorpej 		error = EINVAL;
   2582          1.135   thorpej 		goto out;
   2583           1.31       cgd 	}
   2584          1.328        ad 	if ((error = VOP_SEEK(vp, fp->f_offset, newoff, cred)) == 0) {
   2585          1.328        ad 		*(off_t *)retval = fp->f_offset = newoff;
   2586          1.328        ad 	}
   2587          1.135   thorpej  out:
   2588          1.346        ad  	fd_putfile(fd);
   2589          1.135   thorpej 	return (error);
   2590          1.120   thorpej }
   2591          1.120   thorpej 
   2592          1.120   thorpej /*
   2593          1.120   thorpej  * Positional read system call.
   2594          1.120   thorpej  */
   2595          1.120   thorpej int
   2596          1.335       dsl sys_pread(struct lwp *l, const struct sys_pread_args *uap, register_t *retval)
   2597          1.120   thorpej {
   2598          1.335       dsl 	/* {
   2599          1.120   thorpej 		syscallarg(int) fd;
   2600          1.120   thorpej 		syscallarg(void *) buf;
   2601          1.120   thorpej 		syscallarg(size_t) nbyte;
   2602          1.120   thorpej 		syscallarg(off_t) offset;
   2603          1.335       dsl 	} */
   2604          1.346        ad 	file_t *fp;
   2605          1.120   thorpej 	struct vnode *vp;
   2606          1.120   thorpej 	off_t offset;
   2607          1.120   thorpej 	int error, fd = SCARG(uap, fd);
   2608          1.120   thorpej 
   2609          1.346        ad 	if ((fp = fd_getfile(fd)) == NULL)
   2610          1.166   thorpej 		return (EBADF);
   2611          1.166   thorpej 
   2612          1.183        pk 	if ((fp->f_flag & FREAD) == 0) {
   2613          1.346        ad 		fd_putfile(fd);
   2614          1.120   thorpej 		return (EBADF);
   2615          1.183        pk 	}
   2616          1.120   thorpej 
   2617          1.346        ad 	vp = fp->f_data;
   2618          1.135   thorpej 	if (fp->f_type != DTYPE_VNODE || vp->v_type == VFIFO) {
   2619          1.135   thorpej 		error = ESPIPE;
   2620          1.135   thorpej 		goto out;
   2621          1.135   thorpej 	}
   2622          1.120   thorpej 
   2623          1.120   thorpej 	offset = SCARG(uap, offset);
   2624          1.120   thorpej 
   2625          1.120   thorpej 	/*
   2626          1.120   thorpej 	 * XXX This works because no file systems actually
   2627          1.120   thorpej 	 * XXX take any action on the seek operation.
   2628          1.120   thorpej 	 */
   2629          1.120   thorpej 	if ((error = VOP_SEEK(vp, fp->f_offset, offset, fp->f_cred)) != 0)
   2630          1.135   thorpej 		goto out;
   2631          1.120   thorpej 
   2632          1.135   thorpej 	/* dofileread() will unuse the descriptor for us */
   2633          1.328        ad 	return (dofileread(fd, fp, SCARG(uap, buf), SCARG(uap, nbyte),
   2634          1.120   thorpej 	    &offset, 0, retval));
   2635          1.135   thorpej 
   2636          1.135   thorpej  out:
   2637          1.346        ad 	fd_putfile(fd);
   2638          1.135   thorpej 	return (error);
   2639          1.120   thorpej }
   2640          1.120   thorpej 
   2641          1.120   thorpej /*
   2642          1.120   thorpej  * Positional scatter read system call.
   2643          1.120   thorpej  */
   2644          1.120   thorpej int
   2645          1.335       dsl sys_preadv(struct lwp *l, const struct sys_preadv_args *uap, register_t *retval)
   2646          1.120   thorpej {
   2647          1.335       dsl 	/* {
   2648          1.120   thorpej 		syscallarg(int) fd;
   2649          1.120   thorpej 		syscallarg(const struct iovec *) iovp;
   2650          1.120   thorpej 		syscallarg(int) iovcnt;
   2651          1.120   thorpej 		syscallarg(off_t) offset;
   2652          1.335       dsl 	} */
   2653          1.335       dsl 	off_t offset = SCARG(uap, offset);
   2654          1.120   thorpej 
   2655          1.328        ad 	return do_filereadv(SCARG(uap, fd), SCARG(uap, iovp),
   2656          1.335       dsl 	    SCARG(uap, iovcnt), &offset, 0, retval);
   2657          1.120   thorpej }
   2658          1.120   thorpej 
   2659          1.120   thorpej /*
   2660          1.120   thorpej  * Positional write system call.
   2661          1.120   thorpej  */
   2662          1.120   thorpej int
   2663          1.335       dsl sys_pwrite(struct lwp *l, const struct sys_pwrite_args *uap, register_t *retval)
   2664          1.120   thorpej {
   2665          1.335       dsl 	/* {
   2666          1.120   thorpej 		syscallarg(int) fd;
   2667          1.120   thorpej 		syscallarg(const void *) buf;
   2668          1.120   thorpej 		syscallarg(size_t) nbyte;
   2669          1.120   thorpej 		syscallarg(off_t) offset;
   2670          1.335       dsl 	} */
   2671          1.346        ad 	file_t *fp;
   2672          1.120   thorpej 	struct vnode *vp;
   2673          1.120   thorpej 	off_t offset;
   2674          1.120   thorpej 	int error, fd = SCARG(uap, fd);
   2675          1.120   thorpej 
   2676          1.346        ad 	if ((fp = fd_getfile(fd)) == NULL)
   2677          1.166   thorpej 		return (EBADF);
   2678          1.166   thorpej 
   2679          1.183        pk 	if ((fp->f_flag & FWRITE) == 0) {
   2680          1.346        ad 		fd_putfile(fd);
   2681          1.120   thorpej 		return (EBADF);
   2682          1.183        pk 	}
   2683          1.120   thorpej 
   2684          1.346        ad 	vp = fp->f_data;
   2685          1.135   thorpej 	if (fp->f_type != DTYPE_VNODE || vp->v_type == VFIFO) {
   2686          1.135   thorpej 		error = ESPIPE;
   2687          1.135   thorpej 		goto out;
   2688          1.135   thorpej 	}
   2689          1.120   thorpej 
   2690          1.120   thorpej 	offset = SCARG(uap, offset);
   2691          1.120   thorpej 
   2692          1.120   thorpej 	/*
   2693          1.120   thorpej 	 * XXX This works because no file systems actually
   2694          1.120   thorpej 	 * XXX take any action on the seek operation.
   2695          1.120   thorpej 	 */
   2696          1.120   thorpej 	if ((error = VOP_SEEK(vp, fp->f_offset, offset, fp->f_cred)) != 0)
   2697          1.135   thorpej 		goto out;
   2698          1.120   thorpej 
   2699          1.135   thorpej 	/* dofilewrite() will unuse the descriptor for us */
   2700          1.328        ad 	return (dofilewrite(fd, fp, SCARG(uap, buf), SCARG(uap, nbyte),
   2701          1.120   thorpej 	    &offset, 0, retval));
   2702          1.135   thorpej 
   2703          1.135   thorpej  out:
   2704          1.346        ad 	fd_putfile(fd);
   2705          1.135   thorpej 	return (error);
   2706          1.120   thorpej }
   2707          1.120   thorpej 
   2708          1.120   thorpej /*
   2709          1.120   thorpej  * Positional gather write system call.
   2710          1.120   thorpej  */
   2711          1.120   thorpej int
   2712          1.335       dsl sys_pwritev(struct lwp *l, const struct sys_pwritev_args *uap, register_t *retval)
   2713          1.120   thorpej {
   2714          1.335       dsl 	/* {
   2715          1.120   thorpej 		syscallarg(int) fd;
   2716          1.120   thorpej 		syscallarg(const struct iovec *) iovp;
   2717          1.120   thorpej 		syscallarg(int) iovcnt;
   2718          1.120   thorpej 		syscallarg(off_t) offset;
   2719          1.335       dsl 	} */
   2720          1.335       dsl 	off_t offset = SCARG(uap, offset);
   2721          1.120   thorpej 
   2722          1.328        ad 	return do_filewritev(SCARG(uap, fd), SCARG(uap, iovp),
   2723          1.335       dsl 	    SCARG(uap, iovcnt), &offset, 0, retval);
   2724           1.31       cgd }
   2725           1.31       cgd 
   2726           1.31       cgd /*
   2727           1.31       cgd  * Check access permissions.
   2728           1.31       cgd  */
   2729           1.63  christos int
   2730          1.335       dsl sys_access(struct lwp *l, const struct sys_access_args *uap, register_t *retval)
   2731           1.56   thorpej {
   2732          1.335       dsl 	/* {
   2733           1.74       cgd 		syscallarg(const char *) path;
   2734           1.35       cgd 		syscallarg(int) flags;
   2735          1.335       dsl 	} */
   2736          1.242      elad 	kauth_cred_t cred;
   2737          1.155  augustss 	struct vnode *vp;
   2738          1.169  christos 	int error, flags;
   2739          1.409  dholland 	struct pathbuf *pb;
   2740           1.31       cgd 	struct nameidata nd;
   2741           1.31       cgd 
   2742          1.417  dholland 	CTASSERT(F_OK == 0);
   2743          1.417  dholland 	if ((SCARG(uap, flags) & ~(R_OK | W_OK | X_OK)) != 0) {
   2744          1.415  dholland 		/* nonsense flags */
   2745          1.415  dholland 		return EINVAL;
   2746          1.415  dholland 	}
   2747          1.415  dholland 
   2748          1.409  dholland 	error = pathbuf_copyin(SCARG(uap, path), &pb);
   2749          1.409  dholland 	if (error) {
   2750          1.409  dholland 		return error;
   2751          1.409  dholland 	}
   2752          1.409  dholland 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | TRYEMULROOT, pb);
   2753          1.409  dholland 
   2754          1.409  dholland 	/* Override default credentials */
   2755          1.257        ad 	cred = kauth_cred_dup(l->l_cred);
   2756          1.257        ad 	kauth_cred_seteuid(cred, kauth_cred_getuid(l->l_cred));
   2757          1.257        ad 	kauth_cred_setegid(cred, kauth_cred_getgid(l->l_cred));
   2758          1.169  christos 	nd.ni_cnd.cn_cred = cred;
   2759          1.409  dholland 
   2760          1.409  dholland 	if ((error = namei(&nd)) != 0) {
   2761          1.409  dholland 		pathbuf_destroy(pb);
   2762          1.169  christos 		goto out;
   2763          1.409  dholland 	}
   2764           1.31       cgd 	vp = nd.ni_vp;
   2765          1.409  dholland 	pathbuf_destroy(pb);
   2766           1.31       cgd 
   2767           1.31       cgd 	/* Flags == 0 means only check for existence. */
   2768           1.35       cgd 	if (SCARG(uap, flags)) {
   2769           1.31       cgd 		flags = 0;
   2770           1.35       cgd 		if (SCARG(uap, flags) & R_OK)
   2771           1.31       cgd 			flags |= VREAD;
   2772           1.35       cgd 		if (SCARG(uap, flags) & W_OK)
   2773           1.31       cgd 			flags |= VWRITE;
   2774           1.89   mycroft 		if (SCARG(uap, flags) & X_OK)
   2775           1.89   mycroft 			flags |= VEXEC;
   2776          1.138        is 
   2777          1.332     pooka 		error = VOP_ACCESS(vp, flags, cred);
   2778          1.138        is 		if (!error && (flags & VWRITE))
   2779          1.138        is 			error = vn_writechk(vp);
   2780           1.31       cgd 	}
   2781           1.31       cgd 	vput(vp);
   2782          1.169  christos out:
   2783          1.242      elad 	kauth_cred_free(cred);
   2784           1.31       cgd 	return (error);
   2785           1.31       cgd }
   2786           1.31       cgd 
   2787          1.433      manu int
   2788          1.433      manu sys_faccessat(struct lwp *l, const struct sys_faccessat_args *uap,
   2789          1.433      manu     register_t *retval)
   2790          1.433      manu {
   2791          1.433      manu 	/* {
   2792          1.433      manu 		syscallarg(int) fd;
   2793          1.433      manu 		syscallarg(const char *) path;
   2794          1.433      manu 		syscallarg(int) amode;
   2795          1.433      manu 		syscallarg(int) flag;
   2796          1.433      manu 	} */
   2797          1.433      manu 
   2798          1.433      manu 	return ENOSYS;
   2799          1.433      manu }
   2800          1.433      manu 
   2801           1.31       cgd /*
   2802          1.306       dsl  * Common code for all sys_stat functions, including compat versions.
   2803          1.306       dsl  */
   2804          1.306       dsl int
   2805          1.409  dholland do_sys_stat(const char *userpath, unsigned int nd_flags, struct stat *sb)
   2806          1.306       dsl {
   2807          1.306       dsl 	int error;
   2808          1.409  dholland 	struct pathbuf *pb;
   2809          1.306       dsl 	struct nameidata nd;
   2810          1.306       dsl 
   2811          1.409  dholland 	error = pathbuf_copyin(userpath, &pb);
   2812          1.409  dholland 	if (error) {
   2813          1.409  dholland 		return error;
   2814          1.409  dholland 	}
   2815          1.409  dholland 	NDINIT(&nd, LOOKUP, nd_flags | LOCKLEAF | TRYEMULROOT, pb);
   2816          1.306       dsl 	error = namei(&nd);
   2817          1.409  dholland 	if (error != 0) {
   2818          1.409  dholland 		pathbuf_destroy(pb);
   2819          1.306       dsl 		return error;
   2820          1.409  dholland 	}
   2821          1.346        ad 	error = vn_stat(nd.ni_vp, sb);
   2822          1.306       dsl 	vput(nd.ni_vp);
   2823          1.409  dholland 	pathbuf_destroy(pb);
   2824          1.306       dsl 	return error;
   2825          1.306       dsl }
   2826          1.306       dsl 
   2827          1.306       dsl /*
   2828           1.31       cgd  * Get file status; this version follows links.
   2829           1.31       cgd  */
   2830           1.31       cgd /* ARGSUSED */
   2831           1.63  christos int
   2832          1.383  christos sys___stat50(struct lwp *l, const struct sys___stat50_args *uap, register_t *retval)
   2833           1.56   thorpej {
   2834          1.335       dsl 	/* {
   2835           1.74       cgd 		syscallarg(const char *) path;
   2836           1.35       cgd 		syscallarg(struct stat *) ub;
   2837          1.335       dsl 	} */
   2838           1.31       cgd 	struct stat sb;
   2839           1.31       cgd 	int error;
   2840           1.31       cgd 
   2841          1.346        ad 	error = do_sys_stat(SCARG(uap, path), FOLLOW, &sb);
   2842           1.31       cgd 	if (error)
   2843          1.306       dsl 		return error;
   2844          1.306       dsl 	return copyout(&sb, SCARG(uap, ub), sizeof(sb));
   2845           1.31       cgd }
   2846           1.31       cgd 
   2847           1.31       cgd /*
   2848           1.31       cgd  * Get file status; this version does not follow links.
   2849           1.31       cgd  */
   2850           1.31       cgd /* ARGSUSED */
   2851           1.63  christos int
   2852          1.383  christos sys___lstat50(struct lwp *l, const struct sys___lstat50_args *uap, register_t *retval)
   2853           1.56   thorpej {
   2854          1.335       dsl 	/* {
   2855           1.74       cgd 		syscallarg(const char *) path;
   2856           1.35       cgd 		syscallarg(struct stat *) ub;
   2857          1.335       dsl 	} */
   2858           1.65   mycroft 	struct stat sb;
   2859           1.31       cgd 	int error;
   2860           1.31       cgd 
   2861          1.346        ad 	error = do_sys_stat(SCARG(uap, path), NOFOLLOW, &sb);
   2862           1.64       jtc 	if (error)
   2863          1.306       dsl 		return error;
   2864          1.306       dsl 	return copyout(&sb, SCARG(uap, ub), sizeof(sb));
   2865           1.31       cgd }
   2866           1.31       cgd 
   2867          1.433      manu int
   2868          1.433      manu sys_fstatat(struct lwp *l, const struct sys_fstatat_args *uap,
   2869          1.433      manu     register_t *retval)
   2870          1.433      manu {
   2871          1.433      manu 	/* {
   2872          1.433      manu 		syscallarg(int) fd;
   2873          1.433      manu 		syscallarg(const char *) path;
   2874          1.433      manu 		syscallarg(struct stat *) ub;
   2875          1.433      manu 		syscallarg(int) flag;
   2876          1.433      manu 	} */
   2877          1.433      manu 
   2878          1.433      manu 	return ENOSYS;
   2879          1.433      manu }
   2880           1.31       cgd /*
   2881           1.31       cgd  * Get configurable pathname variables.
   2882           1.31       cgd  */
   2883           1.31       cgd /* ARGSUSED */
   2884           1.63  christos int
   2885          1.335       dsl sys_pathconf(struct lwp *l, const struct sys_pathconf_args *uap, register_t *retval)
   2886           1.56   thorpej {
   2887          1.335       dsl 	/* {
   2888           1.74       cgd 		syscallarg(const char *) path;
   2889           1.35       cgd 		syscallarg(int) name;
   2890          1.335       dsl 	} */
   2891           1.31       cgd 	int error;
   2892          1.409  dholland 	struct pathbuf *pb;
   2893           1.31       cgd 	struct nameidata nd;
   2894           1.31       cgd 
   2895          1.409  dholland 	error = pathbuf_copyin(SCARG(uap, path), &pb);
   2896          1.409  dholland 	if (error) {
   2897          1.409  dholland 		return error;
   2898          1.409  dholland 	}
   2899          1.409  dholland 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | TRYEMULROOT, pb);
   2900          1.409  dholland 	if ((error = namei(&nd)) != 0) {
   2901          1.409  dholland 		pathbuf_destroy(pb);
   2902           1.31       cgd 		return (error);
   2903          1.409  dholland 	}
   2904           1.35       cgd 	error = VOP_PATHCONF(nd.ni_vp, SCARG(uap, name), retval);
   2905           1.31       cgd 	vput(nd.ni_vp);
   2906          1.409  dholland 	pathbuf_destroy(pb);
   2907           1.31       cgd 	return (error);
   2908           1.31       cgd }
   2909           1.31       cgd 
   2910           1.31       cgd /*
   2911           1.31       cgd  * Return target name of a symbolic link.
   2912           1.31       cgd  */
   2913           1.31       cgd /* ARGSUSED */
   2914           1.63  christos int
   2915          1.335       dsl sys_readlink(struct lwp *l, const struct sys_readlink_args *uap, register_t *retval)
   2916           1.56   thorpej {
   2917          1.335       dsl 	/* {
   2918           1.74       cgd 		syscallarg(const char *) path;
   2919           1.35       cgd 		syscallarg(char *) buf;
   2920          1.115    kleink 		syscallarg(size_t) count;
   2921          1.335       dsl 	} */
   2922          1.155  augustss 	struct vnode *vp;
   2923           1.31       cgd 	struct iovec aiov;
   2924           1.31       cgd 	struct uio auio;
   2925           1.31       cgd 	int error;
   2926          1.409  dholland 	struct pathbuf *pb;
   2927           1.31       cgd 	struct nameidata nd;
   2928           1.31       cgd 
   2929          1.409  dholland 	error = pathbuf_copyin(SCARG(uap, path), &pb);
   2930          1.409  dholland 	if (error) {
   2931          1.409  dholland 		return error;
   2932          1.409  dholland 	}
   2933          1.409  dholland 	NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | TRYEMULROOT, pb);
   2934          1.409  dholland 	if ((error = namei(&nd)) != 0) {
   2935          1.409  dholland 		pathbuf_destroy(pb);
   2936          1.409  dholland 		return error;
   2937          1.409  dholland 	}
   2938           1.31       cgd 	vp = nd.ni_vp;
   2939          1.409  dholland 	pathbuf_destroy(pb);
   2940           1.31       cgd 	if (vp->v_type != VLNK)
   2941           1.31       cgd 		error = EINVAL;
   2942          1.106     enami 	else if (!(vp->v_mount->mnt_flag & MNT_SYMPERM) ||
   2943          1.332     pooka 	    (error = VOP_ACCESS(vp, VREAD, l->l_cred)) == 0) {
   2944           1.35       cgd 		aiov.iov_base = SCARG(uap, buf);
   2945           1.35       cgd 		aiov.iov_len = SCARG(uap, count);
   2946           1.31       cgd 		auio.uio_iov = &aiov;
   2947           1.31       cgd 		auio.uio_iovcnt = 1;
   2948           1.31       cgd 		auio.uio_offset = 0;
   2949           1.31       cgd 		auio.uio_rw = UIO_READ;
   2950          1.238      yamt 		KASSERT(l == curlwp);
   2951          1.238      yamt 		auio.uio_vmspace = l->l_proc->p_vmspace;
   2952           1.35       cgd 		auio.uio_resid = SCARG(uap, count);
   2953          1.257        ad 		error = VOP_READLINK(vp, &auio, l->l_cred);
   2954           1.31       cgd 	}
   2955           1.31       cgd 	vput(vp);
   2956           1.35       cgd 	*retval = SCARG(uap, count) - auio.uio_resid;
   2957           1.31       cgd 	return (error);
   2958           1.31       cgd }
   2959           1.31       cgd 
   2960          1.433      manu int
   2961          1.433      manu sys_readlinkat(struct lwp *l, const struct sys_readlinkat_args *uap,
   2962          1.433      manu     register_t *retval)
   2963          1.433      manu {
   2964          1.433      manu 	/* {
   2965          1.433      manu 		syscallarg(int) fd;
   2966          1.433      manu 		syscallarg(const char *) path;
   2967          1.433      manu 		syscallarg(char *) buf;
   2968          1.433      manu 		syscallarg(size_t) count;
   2969          1.433      manu 	} */
   2970          1.433      manu 
   2971          1.433      manu 	return ENOSYS;
   2972          1.433      manu }
   2973          1.433      manu 
   2974           1.31       cgd /*
   2975           1.31       cgd  * Change flags of a file given a path name.
   2976           1.31       cgd  */
   2977           1.31       cgd /* ARGSUSED */
   2978           1.63  christos int
   2979          1.335       dsl sys_chflags(struct lwp *l, const struct sys_chflags_args *uap, register_t *retval)
   2980           1.56   thorpej {
   2981          1.335       dsl 	/* {
   2982           1.74       cgd 		syscallarg(const char *) path;
   2983           1.74       cgd 		syscallarg(u_long) flags;
   2984          1.335       dsl 	} */
   2985          1.155  augustss 	struct vnode *vp;
   2986           1.31       cgd 	int error;
   2987           1.31       cgd 
   2988          1.395  dholland 	error = namei_simple_user(SCARG(uap, path),
   2989          1.395  dholland 				NSM_FOLLOW_TRYEMULROOT, &vp);
   2990          1.395  dholland 	if (error != 0)
   2991           1.31       cgd 		return (error);
   2992          1.234  christos 	error = change_flags(vp, SCARG(uap, flags), l);
   2993           1.31       cgd 	vput(vp);
   2994           1.31       cgd 	return (error);
   2995           1.31       cgd }
   2996           1.31       cgd 
   2997           1.31       cgd /*
   2998           1.31       cgd  * Change flags of a file given a file descriptor.
   2999           1.31       cgd  */
   3000           1.31       cgd /* ARGSUSED */
   3001           1.63  christos int
   3002          1.335       dsl sys_fchflags(struct lwp *l, const struct sys_fchflags_args *uap, register_t *retval)
   3003           1.56   thorpej {
   3004          1.335       dsl 	/* {
   3005           1.35       cgd 		syscallarg(int) fd;
   3006           1.74       cgd 		syscallarg(u_long) flags;
   3007          1.335       dsl 	} */
   3008           1.31       cgd 	struct vnode *vp;
   3009          1.346        ad 	file_t *fp;
   3010           1.31       cgd 	int error;
   3011           1.31       cgd 
   3012          1.346        ad 	/* fd_getvnode() will use the descriptor for us */
   3013          1.346        ad 	if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0)
   3014           1.31       cgd 		return (error);
   3015          1.346        ad 	vp = fp->f_data;
   3016          1.234  christos 	error = change_flags(vp, SCARG(uap, flags), l);
   3017          1.406   hannken 	VOP_UNLOCK(vp);
   3018          1.346        ad 	fd_putfile(SCARG(uap, fd));
   3019          1.156       mrg 	return (error);
   3020          1.156       mrg }
   3021          1.156       mrg 
   3022          1.156       mrg /*
   3023          1.163     enami  * Change flags of a file given a path name; this version does
   3024          1.156       mrg  * not follow links.
   3025          1.156       mrg  */
   3026          1.156       mrg int
   3027          1.335       dsl sys_lchflags(struct lwp *l, const struct sys_lchflags_args *uap, register_t *retval)
   3028          1.156       mrg {
   3029          1.335       dsl 	/* {
   3030          1.156       mrg 		syscallarg(const char *) path;
   3031          1.156       mrg 		syscallarg(u_long) flags;
   3032          1.335       dsl 	} */
   3033          1.163     enami 	struct vnode *vp;
   3034          1.156       mrg 	int error;
   3035          1.156       mrg 
   3036          1.395  dholland 	error = namei_simple_user(SCARG(uap, path),
   3037          1.395  dholland 				NSM_NOFOLLOW_TRYEMULROOT, &vp);
   3038          1.395  dholland 	if (error != 0)
   3039          1.156       mrg 		return (error);
   3040          1.234  christos 	error = change_flags(vp, SCARG(uap, flags), l);
   3041          1.163     enami 	vput(vp);
   3042          1.163     enami 	return (error);
   3043          1.163     enami }
   3044          1.163     enami 
   3045          1.163     enami /*
   3046          1.163     enami  * Common routine to change flags of a file.
   3047          1.163     enami  */
   3048          1.163     enami int
   3049          1.234  christos change_flags(struct vnode *vp, u_long flags, struct lwp *l)
   3050          1.163     enami {
   3051          1.163     enami 	struct vattr vattr;
   3052          1.163     enami 	int error;
   3053          1.163     enami 
   3054          1.156       mrg 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
   3055          1.163     enami 	/*
   3056          1.163     enami 	 * Non-superusers cannot change the flags on devices, even if they
   3057          1.163     enami 	 * own them.
   3058          1.163     enami 	 */
   3059          1.294      elad 	if (kauth_authorize_generic(l->l_cred, KAUTH_GENERIC_ISSUSER, NULL)) {
   3060          1.332     pooka 		if ((error = VOP_GETATTR(vp, &vattr, l->l_cred)) != 0)
   3061          1.156       mrg 			goto out;
   3062          1.156       mrg 		if (vattr.va_type == VCHR || vattr.va_type == VBLK) {
   3063          1.156       mrg 			error = EINVAL;
   3064          1.156       mrg 			goto out;
   3065          1.156       mrg 		}
   3066          1.156       mrg 	}
   3067          1.402     pooka 	vattr_null(&vattr);
   3068          1.163     enami 	vattr.va_flags = flags;
   3069          1.332     pooka 	error = VOP_SETATTR(vp, &vattr, l->l_cred);
   3070          1.156       mrg out:
   3071           1.31       cgd 	return (error);
   3072           1.31       cgd }
   3073           1.31       cgd 
   3074           1.31       cgd /*
   3075           1.98     enami  * Change mode of a file given path name; this version follows links.
   3076           1.31       cgd  */
   3077           1.31       cgd /* ARGSUSED */
   3078           1.63  christos int
   3079          1.335       dsl sys_chmod(struct lwp *l, const struct sys_chmod_args *uap, register_t *retval)
   3080           1.56   thorpej {
   3081          1.335       dsl 	/* {
   3082           1.74       cgd 		syscallarg(const char *) path;
   3083           1.35       cgd 		syscallarg(int) mode;
   3084          1.335       dsl 	} */
   3085           1.31       cgd 	int error;
   3086          1.395  dholland 	struct vnode *vp;
   3087           1.31       cgd 
   3088          1.395  dholland 	error = namei_simple_user(SCARG(uap, path),
   3089          1.395  dholland 				NSM_FOLLOW_TRYEMULROOT, &vp);
   3090          1.395  dholland 	if (error != 0)
   3091           1.31       cgd 		return (error);
   3092           1.97     enami 
   3093          1.395  dholland 	error = change_mode(vp, SCARG(uap, mode), l);
   3094           1.97     enami 
   3095          1.395  dholland 	vrele(vp);
   3096           1.31       cgd 	return (error);
   3097           1.31       cgd }
   3098           1.31       cgd 
   3099           1.31       cgd /*
   3100           1.31       cgd  * Change mode of a file given a file descriptor.
   3101           1.31       cgd  */
   3102           1.31       cgd /* ARGSUSED */
   3103           1.63  christos int
   3104          1.335       dsl sys_fchmod(struct lwp *l, const struct sys_fchmod_args *uap, register_t *retval)
   3105           1.56   thorpej {
   3106          1.335       dsl 	/* {
   3107           1.35       cgd 		syscallarg(int) fd;
   3108           1.35       cgd 		syscallarg(int) mode;
   3109          1.335       dsl 	} */
   3110          1.346        ad 	file_t *fp;
   3111           1.31       cgd 	int error;
   3112           1.31       cgd 
   3113          1.346        ad 	/* fd_getvnode() will use the descriptor for us */
   3114          1.346        ad 	if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0)
   3115           1.31       cgd 		return (error);
   3116          1.346        ad 	error = change_mode(fp->f_data, SCARG(uap, mode), l);
   3117          1.346        ad 	fd_putfile(SCARG(uap, fd));
   3118          1.135   thorpej 	return (error);
   3119           1.97     enami }
   3120           1.97     enami 
   3121          1.433      manu int
   3122          1.433      manu sys_fchmodat(struct lwp *l, const struct sys_fchmodat_args *uap,
   3123          1.433      manu     register_t *retval)
   3124          1.433      manu {
   3125          1.433      manu 	/* {
   3126          1.433      manu 		syscallarg(int) fd;
   3127          1.433      manu 		syscallarg(const char *) path;
   3128          1.433      manu 		syscallarg(int) mode;
   3129          1.433      manu 		syscallarg(int) flag;
   3130          1.433      manu 	} */
   3131          1.433      manu 
   3132          1.433      manu 	return ENOSYS;
   3133          1.433      manu }
   3134          1.433      manu 
   3135           1.97     enami /*
   3136           1.98     enami  * Change mode of a file given path name; this version does not follow links.
   3137           1.98     enami  */
   3138           1.98     enami /* ARGSUSED */
   3139           1.98     enami int
   3140          1.335       dsl sys_lchmod(struct lwp *l, const struct sys_lchmod_args *uap, register_t *retval)
   3141           1.98     enami {
   3142          1.335       dsl 	/* {
   3143           1.98     enami 		syscallarg(const char *) path;
   3144           1.98     enami 		syscallarg(int) mode;
   3145          1.335       dsl 	} */
   3146           1.98     enami 	int error;
   3147          1.395  dholland 	struct vnode *vp;
   3148           1.98     enami 
   3149          1.395  dholland 	error = namei_simple_user(SCARG(uap, path),
   3150          1.395  dholland 				NSM_NOFOLLOW_TRYEMULROOT, &vp);
   3151          1.395  dholland 	if (error != 0)
   3152           1.98     enami 		return (error);
   3153           1.98     enami 
   3154          1.395  dholland 	error = change_mode(vp, SCARG(uap, mode), l);
   3155           1.98     enami 
   3156          1.395  dholland 	vrele(vp);
   3157           1.98     enami 	return (error);
   3158           1.98     enami }
   3159           1.98     enami 
   3160           1.98     enami /*
   3161           1.97     enami  * Common routine to set mode given a vnode.
   3162           1.97     enami  */
   3163           1.97     enami static int
   3164          1.234  christos change_mode(struct vnode *vp, int mode, struct lwp *l)
   3165           1.97     enami {
   3166           1.97     enami 	struct vattr vattr;
   3167           1.97     enami 	int error;
   3168           1.97     enami 
   3169          1.113      fvdl 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
   3170          1.402     pooka 	vattr_null(&vattr);
   3171          1.113      fvdl 	vattr.va_mode = mode & ALLPERMS;
   3172          1.332     pooka 	error = VOP_SETATTR(vp, &vattr, l->l_cred);
   3173          1.406   hannken 	VOP_UNLOCK(vp);
   3174           1.31       cgd 	return (error);
   3175           1.31       cgd }
   3176           1.31       cgd 
   3177           1.31       cgd /*
   3178           1.98     enami  * Set ownership given a path name; this version follows links.
   3179           1.31       cgd  */
   3180           1.31       cgd /* ARGSUSED */
   3181           1.63  christos int
   3182          1.335       dsl sys_chown(struct lwp *l, const struct sys_chown_args *uap, register_t *retval)
   3183           1.56   thorpej {
   3184          1.335       dsl 	/* {
   3185           1.74       cgd 		syscallarg(const char *) path;
   3186           1.74       cgd 		syscallarg(uid_t) uid;
   3187           1.74       cgd 		syscallarg(gid_t) gid;
   3188          1.335       dsl 	} */
   3189           1.31       cgd 	int error;
   3190          1.395  dholland 	struct vnode *vp;
   3191           1.31       cgd 
   3192          1.395  dholland 	error = namei_simple_user(SCARG(uap, path),
   3193          1.395  dholland 				NSM_FOLLOW_TRYEMULROOT, &vp);
   3194          1.395  dholland 	if (error != 0)
   3195           1.31       cgd 		return (error);
   3196           1.86    kleink 
   3197          1.395  dholland 	error = change_owner(vp, SCARG(uap, uid), SCARG(uap, gid), l, 0);
   3198          1.112    kleink 
   3199          1.395  dholland 	vrele(vp);
   3200          1.112    kleink 	return (error);
   3201          1.112    kleink }
   3202          1.112    kleink 
   3203          1.112    kleink /*
   3204          1.112    kleink  * Set ownership given a path name; this version follows links.
   3205          1.112    kleink  * Provides POSIX semantics.
   3206          1.112    kleink  */
   3207          1.112    kleink /* ARGSUSED */
   3208          1.112    kleink int
   3209          1.335       dsl sys___posix_chown(struct lwp *l, const struct sys___posix_chown_args *uap, register_t *retval)
   3210          1.112    kleink {
   3211          1.335       dsl 	/* {
   3212          1.112    kleink 		syscallarg(const char *) path;
   3213          1.112    kleink 		syscallarg(uid_t) uid;
   3214          1.112    kleink 		syscallarg(gid_t) gid;
   3215          1.335       dsl 	} */
   3216          1.112    kleink 	int error;
   3217          1.395  dholland 	struct vnode *vp;
   3218          1.112    kleink 
   3219          1.395  dholland 	error = namei_simple_user(SCARG(uap, path),
   3220          1.395  dholland 				NSM_FOLLOW_TRYEMULROOT, &vp);
   3221          1.395  dholland 	if (error != 0)
   3222          1.112    kleink 		return (error);
   3223          1.112    kleink 
   3224          1.395  dholland 	error = change_owner(vp, SCARG(uap, uid), SCARG(uap, gid), l, 1);
   3225           1.86    kleink 
   3226          1.395  dholland 	vrele(vp);
   3227           1.31       cgd 	return (error);
   3228           1.31       cgd }
   3229           1.31       cgd 
   3230           1.31       cgd /*
   3231           1.31       cgd  * Set ownership given a file descriptor.
   3232           1.31       cgd  */
   3233           1.31       cgd /* ARGSUSED */
   3234           1.63  christos int
   3235          1.335       dsl sys_fchown(struct lwp *l, const struct sys_fchown_args *uap, register_t *retval)
   3236           1.56   thorpej {
   3237          1.335       dsl 	/* {
   3238           1.35       cgd 		syscallarg(int) fd;
   3239           1.74       cgd 		syscallarg(uid_t) uid;
   3240           1.74       cgd 		syscallarg(gid_t) gid;
   3241          1.335       dsl 	} */
   3242           1.71   mycroft 	int error;
   3243          1.346        ad 	file_t *fp;
   3244           1.31       cgd 
   3245          1.346        ad 	/* fd_getvnode() will use the descriptor for us */
   3246          1.346        ad 	if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0)
   3247           1.31       cgd 		return (error);
   3248          1.346        ad 	error = change_owner(fp->f_data, SCARG(uap, uid), SCARG(uap, gid),
   3249          1.346        ad 	    l, 0);
   3250          1.346        ad 	fd_putfile(SCARG(uap, fd));
   3251          1.135   thorpej 	return (error);
   3252          1.112    kleink }
   3253          1.112    kleink 
   3254          1.433      manu int
   3255          1.433      manu sys_fchownat(struct lwp *l, const struct sys_fchownat_args *uap,
   3256          1.433      manu     register_t *retval)
   3257          1.433      manu {
   3258          1.433      manu 	/* {
   3259          1.433      manu 		syscallarg(int) fd;
   3260          1.433      manu 		syscallarg(const char *) path;
   3261          1.433      manu 		syscallarg(uid_t) uid;
   3262          1.433      manu 		syscallarg(gid_t) gid;
   3263          1.433      manu 		syscallarg(int) flag;
   3264          1.433      manu 	} */
   3265          1.433      manu 
   3266          1.433      manu 	return ENOSYS;
   3267          1.433      manu }
   3268          1.433      manu 
   3269          1.112    kleink /*
   3270          1.112    kleink  * Set ownership given a file descriptor, providing POSIX/XPG semantics.
   3271          1.112    kleink  */
   3272          1.112    kleink /* ARGSUSED */
   3273          1.112    kleink int
   3274          1.335       dsl sys___posix_fchown(struct lwp *l, const struct sys___posix_fchown_args *uap, register_t *retval)
   3275          1.112    kleink {
   3276          1.335       dsl 	/* {
   3277          1.112    kleink 		syscallarg(int) fd;
   3278          1.112    kleink 		syscallarg(uid_t) uid;
   3279          1.112    kleink 		syscallarg(gid_t) gid;
   3280          1.335       dsl 	} */
   3281          1.112    kleink 	int error;
   3282          1.346        ad 	file_t *fp;
   3283          1.112    kleink 
   3284          1.346        ad 	/* fd_getvnode() will use the descriptor for us */
   3285          1.346        ad 	if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0)
   3286          1.112    kleink 		return (error);
   3287          1.346        ad 	error = change_owner(fp->f_data, SCARG(uap, uid), SCARG(uap, gid),
   3288          1.346        ad 	    l, 1);
   3289          1.346        ad 	fd_putfile(SCARG(uap, fd));
   3290          1.135   thorpej 	return (error);
   3291           1.86    kleink }
   3292           1.86    kleink 
   3293           1.86    kleink /*
   3294           1.98     enami  * Set ownership given a path name; this version does not follow links.
   3295           1.98     enami  */
   3296           1.98     enami /* ARGSUSED */
   3297           1.98     enami int
   3298          1.335       dsl sys_lchown(struct lwp *l, const struct sys_lchown_args *uap, register_t *retval)
   3299           1.98     enami {
   3300          1.335       dsl 	/* {
   3301           1.98     enami 		syscallarg(const char *) path;
   3302           1.98     enami 		syscallarg(uid_t) uid;
   3303           1.98     enami 		syscallarg(gid_t) gid;
   3304          1.335       dsl 	} */
   3305           1.98     enami 	int error;
   3306          1.395  dholland 	struct vnode *vp;
   3307           1.98     enami 
   3308          1.395  dholland 	error = namei_simple_user(SCARG(uap, path),
   3309          1.395  dholland 				NSM_NOFOLLOW_TRYEMULROOT, &vp);
   3310          1.395  dholland 	if (error != 0)
   3311           1.98     enami 		return (error);
   3312           1.98     enami 
   3313          1.395  dholland 	error = change_owner(vp, SCARG(uap, uid), SCARG(uap, gid), l, 0);
   3314          1.112    kleink 
   3315          1.395  dholland 	vrele(vp);
   3316          1.112    kleink 	return (error);
   3317          1.112    kleink }
   3318          1.112    kleink 
   3319          1.112    kleink /*
   3320          1.112    kleink  * Set ownership given a path name; this version does not follow links.
   3321          1.112    kleink  * Provides POSIX/XPG semantics.
   3322          1.112    kleink  */
   3323          1.112    kleink /* ARGSUSED */
   3324          1.112    kleink int
   3325          1.335       dsl sys___posix_lchown(struct lwp *l, const struct sys___posix_lchown_args *uap, register_t *retval)
   3326          1.112    kleink {
   3327          1.335       dsl 	/* {
   3328          1.112    kleink 		syscallarg(const char *) path;
   3329          1.112    kleink 		syscallarg(uid_t) uid;
   3330          1.112    kleink 		syscallarg(gid_t) gid;
   3331          1.335       dsl 	} */
   3332          1.112    kleink 	int error;
   3333          1.395  dholland 	struct vnode *vp;
   3334          1.112    kleink 
   3335          1.395  dholland 	error = namei_simple_user(SCARG(uap, path),
   3336          1.395  dholland 				NSM_NOFOLLOW_TRYEMULROOT, &vp);
   3337          1.395  dholland 	if (error != 0)
   3338          1.112    kleink 		return (error);
   3339          1.112    kleink 
   3340          1.395  dholland 	error = change_owner(vp, SCARG(uap, uid), SCARG(uap, gid), l, 1);
   3341           1.98     enami 
   3342          1.395  dholland 	vrele(vp);
   3343           1.98     enami 	return (error);
   3344           1.98     enami }
   3345           1.98     enami 
   3346           1.98     enami /*
   3347          1.205  junyoung  * Common routine to set ownership given a vnode.
   3348           1.86    kleink  */
   3349           1.86    kleink static int
   3350          1.234  christos change_owner(struct vnode *vp, uid_t uid, gid_t gid, struct lwp *l,
   3351          1.221   thorpej     int posix_semantics)
   3352           1.86    kleink {
   3353           1.86    kleink 	struct vattr vattr;
   3354          1.112    kleink 	mode_t newmode;
   3355           1.86    kleink 	int error;
   3356           1.86    kleink 
   3357          1.113      fvdl 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
   3358          1.332     pooka 	if ((error = VOP_GETATTR(vp, &vattr, l->l_cred)) != 0)
   3359           1.86    kleink 		goto out;
   3360           1.86    kleink 
   3361          1.175   thorpej #define CHANGED(x) ((int)(x) != -1)
   3362          1.112    kleink 	newmode = vattr.va_mode;
   3363          1.112    kleink 	if (posix_semantics) {
   3364          1.112    kleink 		/*
   3365          1.114    kleink 		 * POSIX/XPG semantics: if the caller is not the super-user,
   3366          1.114    kleink 		 * clear set-user-id and set-group-id bits.  Both POSIX and
   3367          1.114    kleink 		 * the XPG consider the behaviour for calls by the super-user
   3368          1.114    kleink 		 * implementation-defined; we leave the set-user-id and set-
   3369          1.114    kleink 		 * group-id settings intact in that case.
   3370          1.112    kleink 		 */
   3371          1.257        ad 		if (kauth_authorize_generic(l->l_cred, KAUTH_GENERIC_ISSUSER,
   3372          1.242      elad 				      NULL) != 0)
   3373          1.112    kleink 			newmode &= ~(S_ISUID | S_ISGID);
   3374          1.112    kleink 	} else {
   3375          1.112    kleink 		/*
   3376          1.112    kleink 		 * NetBSD semantics: when changing owner and/or group,
   3377          1.112    kleink 		 * clear the respective bit(s).
   3378          1.112    kleink 		 */
   3379          1.112    kleink 		if (CHANGED(uid))
   3380          1.112    kleink 			newmode &= ~S_ISUID;
   3381          1.112    kleink 		if (CHANGED(gid))
   3382          1.112    kleink 			newmode &= ~S_ISGID;
   3383          1.112    kleink 	}
   3384          1.112    kleink 	/* Update va_mode iff altered. */
   3385          1.112    kleink 	if (vattr.va_mode == newmode)
   3386          1.112    kleink 		newmode = VNOVAL;
   3387          1.205  junyoung 
   3388          1.402     pooka 	vattr_null(&vattr);
   3389          1.175   thorpej 	vattr.va_uid = CHANGED(uid) ? uid : (uid_t)VNOVAL;
   3390          1.175   thorpej 	vattr.va_gid = CHANGED(gid) ? gid : (gid_t)VNOVAL;
   3391           1.86    kleink 	vattr.va_mode = newmode;
   3392          1.332     pooka 	error = VOP_SETATTR(vp, &vattr, l->l_cred);
   3393          1.112    kleink #undef CHANGED
   3394          1.205  junyoung 
   3395           1.86    kleink out:
   3396          1.406   hannken 	VOP_UNLOCK(vp);
   3397           1.31       cgd 	return (error);
   3398           1.31       cgd }
   3399           1.31       cgd 
   3400           1.31       cgd /*
   3401           1.98     enami  * Set the access and modification times given a path name; this
   3402           1.98     enami  * version follows links.
   3403           1.31       cgd  */
   3404           1.31       cgd /* ARGSUSED */
   3405           1.63  christos int
   3406          1.383  christos sys___utimes50(struct lwp *l, const struct sys___utimes50_args *uap,
   3407          1.383  christos     register_t *retval)
   3408           1.56   thorpej {
   3409          1.335       dsl 	/* {
   3410           1.74       cgd 		syscallarg(const char *) path;
   3411           1.74       cgd 		syscallarg(const struct timeval *) tptr;
   3412          1.335       dsl 	} */
   3413           1.31       cgd 
   3414          1.312       dsl 	return do_sys_utimes(l, NULL, SCARG(uap, path), FOLLOW,
   3415          1.346        ad 	    SCARG(uap, tptr), UIO_USERSPACE);
   3416           1.71   mycroft }
   3417           1.71   mycroft 
   3418           1.71   mycroft /*
   3419           1.71   mycroft  * Set the access and modification times given a file descriptor.
   3420           1.71   mycroft  */
   3421           1.71   mycroft /* ARGSUSED */
   3422           1.71   mycroft int
   3423          1.383  christos sys___futimes50(struct lwp *l, const struct sys___futimes50_args *uap,
   3424          1.383  christos     register_t *retval)
   3425           1.71   mycroft {
   3426          1.335       dsl 	/* {
   3427           1.71   mycroft 		syscallarg(int) fd;
   3428           1.74       cgd 		syscallarg(const struct timeval *) tptr;
   3429          1.335       dsl 	} */
   3430           1.71   mycroft 	int error;
   3431          1.346        ad 	file_t *fp;
   3432           1.71   mycroft 
   3433          1.346        ad 	/* fd_getvnode() will use the descriptor for us */
   3434          1.346        ad 	if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0)
   3435           1.96     enami 		return (error);
   3436          1.346        ad 	error = do_sys_utimes(l, fp->f_data, NULL, 0, SCARG(uap, tptr),
   3437          1.346        ad 	    UIO_USERSPACE);
   3438          1.346        ad 	fd_putfile(SCARG(uap, fd));
   3439          1.135   thorpej 	return (error);
   3440           1.98     enami }
   3441           1.98     enami 
   3442          1.434      manu int
   3443          1.434      manu sys_futimens(struct lwp *l, const struct sys_futimens_args *uap,
   3444          1.434      manu     register_t *retval)
   3445          1.434      manu {
   3446          1.434      manu 	/* {
   3447          1.434      manu 		syscallarg(int) fd;
   3448          1.434      manu 		syscallarg(const struct timespec *) tptr;
   3449          1.434      manu 	} */
   3450          1.434      manu 	int error;
   3451          1.434      manu 	file_t *fp;
   3452          1.434      manu 
   3453          1.434      manu 	/* fd_getvnode() will use the descriptor for us */
   3454          1.434      manu 	if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0)
   3455          1.434      manu 		return (error);
   3456          1.434      manu 	error = do_sys_utimens(l, fp->f_data, NULL, 0, SCARG(uap, tptr),
   3457          1.434      manu 	    UIO_USERSPACE);
   3458          1.434      manu 	fd_putfile(SCARG(uap, fd));
   3459          1.434      manu 	return (error);
   3460          1.434      manu }
   3461          1.434      manu 
   3462           1.98     enami /*
   3463           1.98     enami  * Set the access and modification times given a path name; this
   3464           1.98     enami  * version does not follow links.
   3465           1.98     enami  */
   3466           1.98     enami int
   3467          1.383  christos sys___lutimes50(struct lwp *l, const struct sys___lutimes50_args *uap,
   3468          1.383  christos     register_t *retval)
   3469           1.98     enami {
   3470          1.335       dsl 	/* {
   3471           1.98     enami 		syscallarg(const char *) path;
   3472           1.98     enami 		syscallarg(const struct timeval *) tptr;
   3473          1.335       dsl 	} */
   3474           1.98     enami 
   3475          1.312       dsl 	return do_sys_utimes(l, NULL, SCARG(uap, path), NOFOLLOW,
   3476          1.346        ad 	    SCARG(uap, tptr), UIO_USERSPACE);
   3477           1.97     enami }
   3478           1.97     enami 
   3479          1.433      manu int
   3480          1.433      manu sys_utimensat(struct lwp *l, const struct sys_utimensat_args *uap,
   3481          1.433      manu     register_t *retval)
   3482          1.433      manu {
   3483          1.433      manu 	/* {
   3484          1.433      manu 		syscallarg(int) fd;
   3485          1.433      manu 		syscallarg(const char *) path;
   3486          1.433      manu 		syscallarg(const struct timespec *) tptr;
   3487          1.433      manu 		syscallarg(int) flag;
   3488          1.433      manu 	} */
   3489          1.434      manu 	int follow;
   3490          1.434      manu 	const struct timespec *tptr;
   3491          1.434      manu 
   3492          1.434      manu 	/*
   3493          1.434      manu 	 * Specified fd is not yet implemented
   3494          1.434      manu 	 */
   3495          1.434      manu 	if (SCARG(uap, fd) != AT_FDCWD)
   3496          1.434      manu 		return ENOSYS;
   3497          1.434      manu 
   3498          1.434      manu 	tptr = SCARG(uap, tptr);
   3499          1.434      manu 	follow = (SCARG(uap, flag) & AT_SYMLINK_NOFOLLOW) ? NOFOLLOW : FOLLOW;
   3500          1.434      manu 
   3501          1.434      manu 	return do_sys_utimens(l, NULL, SCARG(uap, path), follow,
   3502          1.434      manu 	    tptr, UIO_USERSPACE);
   3503          1.433      manu }
   3504          1.433      manu 
   3505           1.97     enami /*
   3506           1.97     enami  * Common routine to set access and modification times given a vnode.
   3507           1.97     enami  */
   3508          1.312       dsl int
   3509          1.434      manu do_sys_utimens(struct lwp *l, struct vnode *vp, const char *path, int flag,
   3510          1.434      manu     const struct timespec *tptr, enum uio_seg seg)
   3511           1.97     enami {
   3512           1.97     enami 	struct vattr vattr;
   3513          1.395  dholland 	int error, dorele = 0;
   3514          1.395  dholland 	namei_simple_flags_t sflags;
   3515          1.395  dholland 
   3516          1.367  christos 	bool vanull, setbirthtime;
   3517          1.367  christos 	struct timespec ts[2];
   3518           1.97     enami 
   3519          1.395  dholland 	/*
   3520          1.395  dholland 	 * I have checked all callers and they pass either FOLLOW,
   3521          1.395  dholland 	 * NOFOLLOW, or 0 (when they don't pass a path), and NOFOLLOW
   3522          1.395  dholland 	 * is 0. More to the point, they don't pass anything else.
   3523          1.395  dholland 	 * Let's keep it that way at least until the namei interfaces
   3524          1.395  dholland 	 * are fully sanitized.
   3525          1.395  dholland 	 */
   3526          1.395  dholland 	KASSERT(flag == NOFOLLOW || flag == FOLLOW);
   3527          1.395  dholland 	sflags = (flag == FOLLOW) ?
   3528          1.395  dholland 		NSM_FOLLOW_TRYEMULROOT : NSM_NOFOLLOW_TRYEMULROOT;
   3529          1.395  dholland 
   3530           1.97     enami 	if (tptr == NULL) {
   3531          1.367  christos 		vanull = true;
   3532          1.367  christos 		nanotime(&ts[0]);
   3533          1.367  christos 		ts[1] = ts[0];
   3534           1.71   mycroft 	} else {
   3535          1.367  christos 		vanull = false;
   3536          1.312       dsl 		if (seg != UIO_SYSSPACE) {
   3537          1.434      manu 			error = copyin(tptr, ts, sizeof (ts));
   3538          1.312       dsl 			if (error != 0)
   3539          1.312       dsl 				return error;
   3540          1.437      manu 		} else {
   3541          1.437      manu 			ts[0] = tptr[0];
   3542          1.437      manu 			ts[1] = tptr[1];
   3543          1.312       dsl 		}
   3544           1.71   mycroft 	}
   3545          1.312       dsl 
   3546          1.438     enami 	if (ts[0].tv_nsec == UTIME_NOW) {
   3547          1.434      manu 		nanotime(&ts[0]);
   3548          1.438     enami 		if (ts[1].tv_nsec == UTIME_NOW) {
   3549          1.438     enami 			vanull = true;
   3550          1.438     enami 			ts[1] = ts[0];
   3551          1.438     enami 		}
   3552          1.438     enami 	} else if (ts[1].tv_nsec == UTIME_NOW)
   3553          1.434      manu 		nanotime(&ts[1]);
   3554          1.434      manu 
   3555          1.312       dsl 	if (vp == NULL) {
   3556          1.395  dholland 		/* note: SEG describes TPTR, not PATH; PATH is always user */
   3557          1.395  dholland 		error = namei_simple_user(path, sflags, &vp);
   3558          1.395  dholland 		if (error != 0)
   3559          1.367  christos 			return error;
   3560          1.395  dholland 		dorele = 1;
   3561          1.395  dholland 	}
   3562          1.312       dsl 
   3563          1.113      fvdl 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
   3564          1.367  christos 	setbirthtime = (VOP_GETATTR(vp, &vattr, l->l_cred) == 0 &&
   3565          1.367  christos 	    timespeccmp(&ts[1], &vattr.va_birthtime, <));
   3566          1.402     pooka 	vattr_null(&vattr);
   3567          1.434      manu 
   3568          1.434      manu 	if (ts[0].tv_nsec != UTIME_OMIT)
   3569          1.434      manu 		vattr.va_atime = ts[0];
   3570          1.434      manu 
   3571          1.434      manu 	if (ts[1].tv_nsec != UTIME_OMIT) {
   3572          1.434      manu 		vattr.va_mtime = ts[1];
   3573          1.434      manu 		if (setbirthtime)
   3574          1.434      manu 			vattr.va_birthtime = ts[1];
   3575          1.434      manu 	}
   3576          1.434      manu 
   3577          1.367  christos 	if (vanull)
   3578          1.392      yamt 		vattr.va_vaflags |= VA_UTIMES_NULL;
   3579          1.332     pooka 	error = VOP_SETATTR(vp, &vattr, l->l_cred);
   3580          1.406   hannken 	VOP_UNLOCK(vp);
   3581          1.312       dsl 
   3582          1.395  dholland 	if (dorele != 0)
   3583          1.395  dholland 		vrele(vp);
   3584          1.312       dsl 
   3585          1.367  christos 	return error;
   3586           1.31       cgd }
   3587           1.31       cgd 
   3588          1.434      manu int
   3589          1.434      manu do_sys_utimes(struct lwp *l, struct vnode *vp, const char *path, int flag,
   3590          1.434      manu     const struct timeval *tptr, enum uio_seg seg)
   3591          1.434      manu {
   3592          1.434      manu 	struct timespec ts[2];
   3593          1.434      manu 	struct timespec *tsptr = NULL;
   3594          1.434      manu 	int error;
   3595          1.434      manu 
   3596          1.434      manu 	if (tptr != NULL) {
   3597          1.434      manu 		struct timeval tv[2];
   3598          1.434      manu 
   3599          1.434      manu 		if (seg != UIO_SYSSPACE) {
   3600          1.434      manu 			error = copyin(tptr, tv, sizeof (tv));
   3601          1.434      manu 			if (error != 0)
   3602          1.434      manu 				return error;
   3603          1.434      manu 			tptr = tv;
   3604          1.434      manu 		}
   3605          1.434      manu 
   3606          1.434      manu 		if ((tv[0].tv_usec == UTIME_NOW) ||
   3607          1.434      manu 		    (tv[0].tv_usec == UTIME_OMIT))
   3608          1.434      manu 			ts[0].tv_nsec = tv[0].tv_usec;
   3609          1.434      manu 		else
   3610          1.434      manu 			TIMEVAL_TO_TIMESPEC(&tptr[0], &ts[0]);
   3611          1.434      manu 
   3612          1.434      manu 		if ((tv[1].tv_usec == UTIME_NOW) ||
   3613          1.434      manu 		    (tv[1].tv_usec == UTIME_OMIT))
   3614          1.434      manu 			ts[1].tv_nsec = tv[1].tv_usec;
   3615          1.434      manu 		else
   3616          1.434      manu 			TIMEVAL_TO_TIMESPEC(&tptr[1], &ts[1]);
   3617          1.434      manu 
   3618          1.434      manu 		tsptr = &ts[0];
   3619          1.434      manu 	}
   3620          1.434      manu 
   3621          1.434      manu 	return do_sys_utimens(l, vp, path, flag, tsptr, UIO_SYSSPACE);
   3622          1.434      manu }
   3623          1.434      manu 
   3624           1.31       cgd /*
   3625           1.31       cgd  * Truncate a file given its path name.
   3626           1.31       cgd  */
   3627           1.31       cgd /* ARGSUSED */
   3628           1.63  christos int
   3629          1.335       dsl sys_truncate(struct lwp *l, const struct sys_truncate_args *uap, register_t *retval)
   3630           1.56   thorpej {
   3631          1.335       dsl 	/* {
   3632           1.74       cgd 		syscallarg(const char *) path;
   3633           1.35       cgd 		syscallarg(int) pad;
   3634           1.35       cgd 		syscallarg(off_t) length;
   3635          1.335       dsl 	} */
   3636          1.155  augustss 	struct vnode *vp;
   3637           1.31       cgd 	struct vattr vattr;
   3638           1.31       cgd 	int error;
   3639           1.31       cgd 
   3640          1.395  dholland 	error = namei_simple_user(SCARG(uap, path),
   3641          1.395  dholland 				NSM_FOLLOW_TRYEMULROOT, &vp);
   3642          1.395  dholland 	if (error != 0)
   3643           1.31       cgd 		return (error);
   3644          1.113      fvdl 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
   3645           1.31       cgd 	if (vp->v_type == VDIR)
   3646           1.31       cgd 		error = EISDIR;
   3647           1.31       cgd 	else if ((error = vn_writechk(vp)) == 0 &&
   3648          1.332     pooka 	    (error = VOP_ACCESS(vp, VWRITE, l->l_cred)) == 0) {
   3649          1.402     pooka 		vattr_null(&vattr);
   3650           1.35       cgd 		vattr.va_size = SCARG(uap, length);
   3651          1.332     pooka 		error = VOP_SETATTR(vp, &vattr, l->l_cred);
   3652           1.31       cgd 	}
   3653           1.31       cgd 	vput(vp);
   3654           1.31       cgd 	return (error);
   3655           1.31       cgd }
   3656           1.31       cgd 
   3657           1.31       cgd /*
   3658           1.31       cgd  * Truncate a file given a file descriptor.
   3659           1.31       cgd  */
   3660           1.31       cgd /* ARGSUSED */
   3661           1.63  christos int
   3662          1.335       dsl sys_ftruncate(struct lwp *l, const struct sys_ftruncate_args *uap, register_t *retval)
   3663           1.56   thorpej {
   3664          1.335       dsl 	/* {
   3665           1.35       cgd 		syscallarg(int) fd;
   3666           1.35       cgd 		syscallarg(int) pad;
   3667           1.35       cgd 		syscallarg(off_t) length;
   3668          1.335       dsl 	} */
   3669           1.31       cgd 	struct vattr vattr;
   3670           1.31       cgd 	struct vnode *vp;
   3671          1.346        ad 	file_t *fp;
   3672           1.31       cgd 	int error;
   3673           1.31       cgd 
   3674          1.346        ad 	/* fd_getvnode() will use the descriptor for us */
   3675          1.346        ad 	if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0)
   3676           1.31       cgd 		return (error);
   3677          1.135   thorpej 	if ((fp->f_flag & FWRITE) == 0) {
   3678          1.135   thorpej 		error = EINVAL;
   3679          1.135   thorpej 		goto out;
   3680          1.135   thorpej 	}
   3681          1.346        ad 	vp = fp->f_data;
   3682          1.113      fvdl 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
   3683           1.31       cgd 	if (vp->v_type == VDIR)
   3684           1.31       cgd 		error = EISDIR;
   3685           1.31       cgd 	else if ((error = vn_writechk(vp)) == 0) {
   3686          1.402     pooka 		vattr_null(&vattr);
   3687           1.35       cgd 		vattr.va_size = SCARG(uap, length);
   3688          1.332     pooka 		error = VOP_SETATTR(vp, &vattr, fp->f_cred);
   3689           1.31       cgd 	}
   3690          1.406   hannken 	VOP_UNLOCK(vp);
   3691          1.135   thorpej  out:
   3692          1.346        ad 	fd_putfile(SCARG(uap, fd));
   3693           1.31       cgd 	return (error);
   3694           1.31       cgd }
   3695           1.31       cgd 
   3696           1.31       cgd /*
   3697           1.31       cgd  * Sync an open file.
   3698           1.31       cgd  */
   3699           1.31       cgd /* ARGSUSED */
   3700           1.63  christos int
   3701          1.335       dsl sys_fsync(struct lwp *l, const struct sys_fsync_args *uap, register_t *retval)
   3702           1.56   thorpej {
   3703          1.335       dsl 	/* {
   3704           1.35       cgd 		syscallarg(int) fd;
   3705          1.335       dsl 	} */
   3706          1.155  augustss 	struct vnode *vp;
   3707          1.346        ad 	file_t *fp;
   3708           1.31       cgd 	int error;
   3709           1.31       cgd 
   3710          1.346        ad 	/* fd_getvnode() will use the descriptor for us */
   3711          1.346        ad 	if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0)
   3712           1.31       cgd 		return (error);
   3713          1.346        ad 	vp = fp->f_data;
   3714          1.113      fvdl 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
   3715          1.332     pooka 	error = VOP_FSYNC(vp, fp->f_cred, FSYNC_WAIT, 0, 0);
   3716          1.406   hannken 	VOP_UNLOCK(vp);
   3717          1.346        ad 	fd_putfile(SCARG(uap, fd));
   3718          1.201   thorpej 	return (error);
   3719          1.201   thorpej }
   3720          1.201   thorpej 
   3721          1.201   thorpej /*
   3722          1.201   thorpej  * Sync a range of file data.  API modeled after that found in AIX.
   3723          1.201   thorpej  *
   3724          1.201   thorpej  * FDATASYNC indicates that we need only save enough metadata to be able
   3725          1.201   thorpej  * to re-read the written data.  Note we duplicate AIX's requirement that
   3726          1.201   thorpej  * the file be open for writing.
   3727          1.201   thorpej  */
   3728          1.201   thorpej /* ARGSUSED */
   3729          1.201   thorpej int
   3730          1.335       dsl sys_fsync_range(struct lwp *l, const struct sys_fsync_range_args *uap, register_t *retval)
   3731          1.201   thorpej {
   3732          1.335       dsl 	/* {
   3733          1.201   thorpej 		syscallarg(int) fd;
   3734          1.201   thorpej 		syscallarg(int) flags;
   3735          1.201   thorpej 		syscallarg(off_t) start;
   3736          1.225      cube 		syscallarg(off_t) length;
   3737          1.335       dsl 	} */
   3738          1.201   thorpej 	struct vnode *vp;
   3739          1.346        ad 	file_t *fp;
   3740          1.201   thorpej 	int flags, nflags;
   3741          1.201   thorpej 	off_t s, e, len;
   3742          1.201   thorpej 	int error;
   3743          1.201   thorpej 
   3744          1.346        ad 	/* fd_getvnode() will use the descriptor for us */
   3745          1.346        ad 	if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0)
   3746          1.201   thorpej 		return (error);
   3747          1.201   thorpej 
   3748          1.201   thorpej 	if ((fp->f_flag & FWRITE) == 0) {
   3749          1.293  wrstuden 		error = EBADF;
   3750          1.293  wrstuden 		goto out;
   3751          1.201   thorpej 	}
   3752          1.201   thorpej 
   3753          1.201   thorpej 	flags = SCARG(uap, flags);
   3754          1.201   thorpej 	if (((flags & (FDATASYNC | FFILESYNC)) == 0) ||
   3755          1.201   thorpej 	    ((~flags & (FDATASYNC | FFILESYNC)) == 0)) {
   3756          1.293  wrstuden 		error = EINVAL;
   3757          1.293  wrstuden 		goto out;
   3758          1.201   thorpej 	}
   3759          1.201   thorpej 	/* Now set up the flags for value(s) to pass to VOP_FSYNC() */
   3760          1.201   thorpej 	if (flags & FDATASYNC)
   3761          1.201   thorpej 		nflags = FSYNC_DATAONLY | FSYNC_WAIT;
   3762          1.201   thorpej 	else
   3763          1.201   thorpej 		nflags = FSYNC_WAIT;
   3764          1.216  wrstuden 	if (flags & FDISKSYNC)
   3765          1.216  wrstuden 		nflags |= FSYNC_CACHE;
   3766          1.201   thorpej 
   3767          1.201   thorpej 	len = SCARG(uap, length);
   3768          1.424       dsl 	/* If length == 0, we do the whole file, and s = e = 0 will do that */
   3769          1.201   thorpej 	if (len) {
   3770          1.201   thorpej 		s = SCARG(uap, start);
   3771          1.201   thorpej 		e = s + len;
   3772          1.201   thorpej 		if (e < s) {
   3773          1.293  wrstuden 			error = EINVAL;
   3774          1.293  wrstuden 			goto out;
   3775          1.201   thorpej 		}
   3776          1.201   thorpej 	} else {
   3777          1.201   thorpej 		e = 0;
   3778          1.201   thorpej 		s = 0;
   3779          1.201   thorpej 	}
   3780          1.201   thorpej 
   3781          1.346        ad 	vp = fp->f_data;
   3782          1.201   thorpej 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
   3783          1.332     pooka 	error = VOP_FSYNC(vp, fp->f_cred, nflags, s, e);
   3784          1.406   hannken 	VOP_UNLOCK(vp);
   3785          1.293  wrstuden out:
   3786          1.346        ad 	fd_putfile(SCARG(uap, fd));
   3787           1.31       cgd 	return (error);
   3788           1.31       cgd }
   3789           1.31       cgd 
   3790           1.31       cgd /*
   3791          1.117    kleink  * Sync the data of an open file.
   3792          1.117    kleink  */
   3793          1.117    kleink /* ARGSUSED */
   3794          1.117    kleink int
   3795          1.335       dsl sys_fdatasync(struct lwp *l, const struct sys_fdatasync_args *uap, register_t *retval)
   3796          1.117    kleink {
   3797          1.335       dsl 	/* {
   3798          1.117    kleink 		syscallarg(int) fd;
   3799          1.335       dsl 	} */
   3800          1.117    kleink 	struct vnode *vp;
   3801          1.346        ad 	file_t *fp;
   3802          1.117    kleink 	int error;
   3803          1.117    kleink 
   3804          1.346        ad 	/* fd_getvnode() will use the descriptor for us */
   3805          1.346        ad 	if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0)
   3806          1.117    kleink 		return (error);
   3807          1.199    kleink 	if ((fp->f_flag & FWRITE) == 0) {
   3808          1.346        ad 		fd_putfile(SCARG(uap, fd));
   3809          1.199    kleink 		return (EBADF);
   3810          1.199    kleink 	}
   3811          1.346        ad 	vp = fp->f_data;
   3812          1.117    kleink 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
   3813          1.332     pooka 	error = VOP_FSYNC(vp, fp->f_cred, FSYNC_WAIT|FSYNC_DATAONLY, 0, 0);
   3814          1.406   hannken 	VOP_UNLOCK(vp);
   3815          1.346        ad 	fd_putfile(SCARG(uap, fd));
   3816          1.117    kleink 	return (error);
   3817          1.117    kleink }
   3818          1.117    kleink 
   3819          1.117    kleink /*
   3820           1.90    kleink  * Rename files, (standard) BSD semantics frontend.
   3821           1.31       cgd  */
   3822           1.31       cgd /* ARGSUSED */
   3823           1.63  christos int
   3824          1.335       dsl sys_rename(struct lwp *l, const struct sys_rename_args *uap, register_t *retval)
   3825           1.56   thorpej {
   3826          1.335       dsl 	/* {
   3827           1.74       cgd 		syscallarg(const char *) from;
   3828           1.74       cgd 		syscallarg(const char *) to;
   3829          1.335       dsl 	} */
   3830           1.90    kleink 
   3831          1.336        ad 	return (do_sys_rename(SCARG(uap, from), SCARG(uap, to), UIO_USERSPACE, 0));
   3832           1.90    kleink }
   3833           1.90    kleink 
   3834          1.433      manu int
   3835          1.433      manu sys_renameat(struct lwp *l, const struct sys_renameat_args *uap,
   3836          1.433      manu     register_t *retval)
   3837          1.433      manu {
   3838          1.433      manu 	/* {
   3839          1.433      manu 		syscallarg(int) fromfd;
   3840          1.433      manu 		syscallarg(const char *) from;
   3841          1.433      manu 		syscallarg(int) tofd;
   3842          1.433      manu 		syscallarg(const char *) to;
   3843          1.433      manu 	} */
   3844          1.433      manu 
   3845          1.433      manu 	return ENOSYS;
   3846          1.433      manu }
   3847          1.433      manu 
   3848           1.90    kleink /*
   3849           1.90    kleink  * Rename files, POSIX semantics frontend.
   3850           1.90    kleink  */
   3851           1.90    kleink /* ARGSUSED */
   3852           1.90    kleink int
   3853          1.335       dsl sys___posix_rename(struct lwp *l, const struct sys___posix_rename_args *uap, register_t *retval)
   3854           1.90    kleink {
   3855          1.335       dsl 	/* {
   3856           1.90    kleink 		syscallarg(const char *) from;
   3857           1.90    kleink 		syscallarg(const char *) to;
   3858          1.335       dsl 	} */
   3859           1.90    kleink 
   3860          1.336        ad 	return (do_sys_rename(SCARG(uap, from), SCARG(uap, to), UIO_USERSPACE, 1));
   3861           1.90    kleink }
   3862           1.90    kleink 
   3863           1.90    kleink /*
   3864           1.90    kleink  * Rename files.  Source and destination must either both be directories,
   3865           1.90    kleink  * or both not be directories.  If target is a directory, it must be empty.
   3866           1.90    kleink  * If `from' and `to' refer to the same object, the value of the `retain'
   3867           1.90    kleink  * argument is used to determine whether `from' will be
   3868           1.90    kleink  *
   3869           1.90    kleink  * (retain == 0)	deleted unless `from' and `to' refer to the same
   3870           1.90    kleink  *			object in the file system's name space (BSD).
   3871           1.90    kleink  * (retain == 1)	always retained (POSIX).
   3872           1.90    kleink  */
   3873          1.336        ad int
   3874          1.336        ad do_sys_rename(const char *from, const char *to, enum uio_seg seg, int retain)
   3875           1.90    kleink {
   3876          1.155  augustss 	struct vnode *tvp, *fvp, *tdvp;
   3877          1.409  dholland 	struct pathbuf *frompb, *topb;
   3878           1.31       cgd 	struct nameidata fromnd, tond;
   3879          1.344  dholland 	struct mount *fs;
   3880           1.31       cgd 	int error;
   3881           1.31       cgd 
   3882          1.409  dholland 	error = pathbuf_maybe_copyin(from, seg, &frompb);
   3883          1.409  dholland 	if (error) {
   3884          1.409  dholland 		return error;
   3885          1.409  dholland 	}
   3886          1.409  dholland 	error = pathbuf_maybe_copyin(to, seg, &topb);
   3887          1.409  dholland 	if (error) {
   3888          1.409  dholland 		pathbuf_destroy(frompb);
   3889          1.409  dholland 		return error;
   3890          1.409  dholland 	}
   3891          1.409  dholland 
   3892          1.413  dholland 	NDINIT(&fromnd, DELETE, LOCKPARENT | TRYEMULROOT | INRENAME,
   3893          1.409  dholland 	    frompb);
   3894          1.409  dholland 	if ((error = namei(&fromnd)) != 0) {
   3895          1.409  dholland 		pathbuf_destroy(frompb);
   3896          1.409  dholland 		pathbuf_destroy(topb);
   3897           1.31       cgd 		return (error);
   3898          1.409  dholland 	}
   3899          1.291     pooka 	if (fromnd.ni_dvp != fromnd.ni_vp)
   3900          1.406   hannken 		VOP_UNLOCK(fromnd.ni_dvp);
   3901           1.31       cgd 	fvp = fromnd.ni_vp;
   3902          1.344  dholland 
   3903          1.344  dholland 	fs = fvp->v_mount;
   3904          1.344  dholland 	error = VFS_RENAMELOCK_ENTER(fs);
   3905          1.344  dholland 	if (error) {
   3906          1.344  dholland 		VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
   3907          1.344  dholland 		vrele(fromnd.ni_dvp);
   3908          1.344  dholland 		vrele(fvp);
   3909          1.344  dholland 		goto out1;
   3910          1.344  dholland 	}
   3911          1.344  dholland 
   3912          1.344  dholland 	/*
   3913          1.344  dholland 	 * close, partially, yet another race - ideally we should only
   3914          1.344  dholland 	 * go as far as getting fromnd.ni_dvp before getting the per-fs
   3915          1.344  dholland 	 * lock, and then continue to get fromnd.ni_vp, but we can't do
   3916          1.344  dholland 	 * that with namei as it stands.
   3917          1.344  dholland 	 *
   3918          1.344  dholland 	 * This still won't prevent rmdir from nuking fromnd.ni_vp
   3919          1.344  dholland 	 * under us. The real fix is to get the locks in the right
   3920          1.344  dholland 	 * order and do the lookups in the right places, but that's a
   3921          1.344  dholland 	 * major rototill.
   3922          1.344  dholland 	 *
   3923          1.344  dholland 	 * Note: this logic (as well as this whole function) is cloned
   3924          1.344  dholland 	 * in nfs_serv.c. Proceed accordingly.
   3925          1.344  dholland 	 */
   3926          1.344  dholland 	vrele(fvp);
   3927          1.348  dholland 	if ((fromnd.ni_cnd.cn_namelen == 1 &&
   3928          1.348  dholland 	     fromnd.ni_cnd.cn_nameptr[0] == '.') ||
   3929          1.348  dholland 	    (fromnd.ni_cnd.cn_namelen == 2 &&
   3930          1.348  dholland 	     fromnd.ni_cnd.cn_nameptr[0] == '.' &&
   3931          1.348  dholland 	     fromnd.ni_cnd.cn_nameptr[1] == '.')) {
   3932          1.348  dholland 		error = EINVAL;
   3933          1.348  dholland 		VFS_RENAMELOCK_EXIT(fs);
   3934          1.348  dholland 		VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
   3935          1.348  dholland 		vrele(fromnd.ni_dvp);
   3936          1.348  dholland 		goto out1;
   3937          1.348  dholland 	}
   3938          1.344  dholland 	vn_lock(fromnd.ni_dvp, LK_EXCLUSIVE | LK_RETRY);
   3939          1.412  dholland 	error = relookup(fromnd.ni_dvp, &fromnd.ni_vp, &fromnd.ni_cnd, 0);
   3940          1.344  dholland 	if (error) {
   3941          1.406   hannken 		VOP_UNLOCK(fromnd.ni_dvp);
   3942          1.344  dholland 		VFS_RENAMELOCK_EXIT(fs);
   3943          1.344  dholland 		VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
   3944          1.344  dholland 		vrele(fromnd.ni_dvp);
   3945          1.344  dholland 		goto out1;
   3946          1.344  dholland 	}
   3947          1.406   hannken 	VOP_UNLOCK(fromnd.ni_vp);
   3948          1.344  dholland 	if (fromnd.ni_dvp != fromnd.ni_vp)
   3949          1.406   hannken 		VOP_UNLOCK(fromnd.ni_dvp);
   3950          1.344  dholland 	fvp = fromnd.ni_vp;
   3951          1.344  dholland 
   3952          1.331     pooka 	NDINIT(&tond, RENAME,
   3953          1.413  dholland 	    LOCKPARENT | LOCKLEAF | NOCACHE | TRYEMULROOT
   3954          1.401     pooka 	      | INRENAME | (fvp->v_type == VDIR ? CREATEDIR : 0),
   3955          1.409  dholland 	    topb);
   3956           1.63  christos 	if ((error = namei(&tond)) != 0) {
   3957          1.344  dholland 		VFS_RENAMELOCK_EXIT(fs);
   3958           1.31       cgd 		VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
   3959           1.31       cgd 		vrele(fromnd.ni_dvp);
   3960           1.31       cgd 		vrele(fvp);
   3961           1.31       cgd 		goto out1;
   3962           1.31       cgd 	}
   3963           1.31       cgd 	tdvp = tond.ni_dvp;
   3964           1.31       cgd 	tvp = tond.ni_vp;
   3965           1.90    kleink 
   3966           1.31       cgd 	if (tvp != NULL) {
   3967           1.31       cgd 		if (fvp->v_type == VDIR && tvp->v_type != VDIR) {
   3968           1.31       cgd 			error = ENOTDIR;
   3969           1.31       cgd 			goto out;
   3970           1.31       cgd 		} else if (fvp->v_type != VDIR && tvp->v_type == VDIR) {
   3971           1.31       cgd 			error = EISDIR;
   3972           1.31       cgd 			goto out;
   3973           1.31       cgd 		}
   3974           1.31       cgd 	}
   3975           1.90    kleink 
   3976           1.31       cgd 	if (fvp == tdvp)
   3977           1.31       cgd 		error = EINVAL;
   3978           1.90    kleink 
   3979           1.82    kleink 	/*
   3980           1.90    kleink 	 * Source and destination refer to the same object.
   3981           1.82    kleink 	 */
   3982           1.90    kleink 	if (fvp == tvp) {
   3983           1.90    kleink 		if (retain)
   3984           1.90    kleink 			error = -1;
   3985           1.90    kleink 		else if (fromnd.ni_dvp == tdvp &&
   3986           1.90    kleink 		    fromnd.ni_cnd.cn_namelen == tond.ni_cnd.cn_namelen &&
   3987          1.442      yamt 		    !memcmp(fromnd.ni_cnd.cn_nameptr, tond.ni_cnd.cn_nameptr,
   3988           1.90    kleink 		          fromnd.ni_cnd.cn_namelen))
   3989          1.442      yamt 			error = -1;
   3990           1.90    kleink 	}
   3991          1.419      yamt 	/*
   3992          1.419      yamt 	 * Prevent cross-mount operation.
   3993          1.419      yamt 	 */
   3994          1.419      yamt 	if (error == 0) {
   3995          1.419      yamt 		if (tond.ni_dvp->v_mount != fromnd.ni_dvp->v_mount) {
   3996          1.419      yamt 			error = EXDEV;
   3997          1.419      yamt 		}
   3998          1.419      yamt 	}
   3999          1.256      elad #if NVERIEXEC > 0
   4000          1.282      elad 	if (!error) {
   4001          1.313      elad 		char *f1, *f2;
   4002          1.384      yamt 		size_t f1_len;
   4003          1.384      yamt 		size_t f2_len;
   4004          1.313      elad 
   4005          1.384      yamt 		f1_len = fromnd.ni_cnd.cn_namelen + 1;
   4006          1.384      yamt 		f1 = kmem_alloc(f1_len, KM_SLEEP);
   4007          1.384      yamt 		strlcpy(f1, fromnd.ni_cnd.cn_nameptr, f1_len);
   4008          1.384      yamt 
   4009          1.384      yamt 		f2_len = tond.ni_cnd.cn_namelen + 1;
   4010          1.384      yamt 		f2 = kmem_alloc(f2_len, KM_SLEEP);
   4011          1.384      yamt 		strlcpy(f2, tond.ni_cnd.cn_nameptr, f2_len);
   4012          1.282      elad 
   4013          1.428  uebayasi 		error = veriexec_renamechk(curlwp, fvp, f1, tvp, f2);
   4014          1.282      elad 
   4015          1.384      yamt 		kmem_free(f1, f1_len);
   4016          1.384      yamt 		kmem_free(f2, f2_len);
   4017          1.282      elad 	}
   4018          1.256      elad #endif /* NVERIEXEC > 0 */
   4019          1.229      elad 
   4020           1.31       cgd out:
   4021           1.31       cgd 	if (!error) {
   4022           1.31       cgd 		error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd,
   4023           1.31       cgd 				   tond.ni_dvp, tond.ni_vp, &tond.ni_cnd);
   4024          1.344  dholland 		VFS_RENAMELOCK_EXIT(fs);
   4025           1.31       cgd 	} else {
   4026           1.31       cgd 		VOP_ABORTOP(tond.ni_dvp, &tond.ni_cnd);
   4027           1.31       cgd 		if (tdvp == tvp)
   4028           1.31       cgd 			vrele(tdvp);
   4029           1.31       cgd 		else
   4030           1.31       cgd 			vput(tdvp);
   4031           1.31       cgd 		if (tvp)
   4032           1.31       cgd 			vput(tvp);
   4033          1.344  dholland 		VFS_RENAMELOCK_EXIT(fs);
   4034           1.31       cgd 		VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
   4035           1.31       cgd 		vrele(fromnd.ni_dvp);
   4036           1.31       cgd 		vrele(fvp);
   4037           1.31       cgd 	}
   4038           1.31       cgd out1:
   4039          1.409  dholland 	pathbuf_destroy(frompb);
   4040          1.409  dholland 	pathbuf_destroy(topb);
   4041           1.80    kleink 	return (error == -1 ? 0 : error);
   4042           1.31       cgd }
   4043           1.31       cgd 
   4044           1.31       cgd /*
   4045           1.31       cgd  * Make a directory file.
   4046           1.31       cgd  */
   4047           1.31       cgd /* ARGSUSED */
   4048           1.63  christos int
   4049          1.335       dsl sys_mkdir(struct lwp *l, const struct sys_mkdir_args *uap, register_t *retval)
   4050           1.56   thorpej {
   4051          1.335       dsl 	/* {
   4052           1.74       cgd 		syscallarg(const char *) path;
   4053           1.35       cgd 		syscallarg(int) mode;
   4054          1.335       dsl 	} */
   4055          1.396     pooka 
   4056          1.399      haad 	return do_sys_mkdir(SCARG(uap, path), SCARG(uap, mode), UIO_USERSPACE);
   4057          1.396     pooka }
   4058          1.396     pooka 
   4059          1.396     pooka int
   4060          1.433      manu sys_mkdirat(struct lwp *l, const struct sys_mkdirat_args *uap,
   4061          1.433      manu     register_t *retval)
   4062          1.433      manu {
   4063          1.433      manu 	/* {
   4064          1.433      manu 		syscallarg(int) fd;
   4065          1.433      manu 		syscallarg(const char *) path;
   4066          1.433      manu 		syscallarg(int) mode;
   4067          1.433      manu 	} */
   4068          1.433      manu 
   4069          1.433      manu 	return ENOSYS;
   4070          1.433      manu }
   4071          1.433      manu 
   4072          1.433      manu 
   4073          1.433      manu int
   4074          1.399      haad do_sys_mkdir(const char *path, mode_t mode, enum uio_seg seg)
   4075          1.396     pooka {
   4076          1.396     pooka 	struct proc *p = curlwp->l_proc;
   4077          1.155  augustss 	struct vnode *vp;
   4078           1.31       cgd 	struct vattr vattr;
   4079           1.31       cgd 	int error;
   4080          1.409  dholland 	struct pathbuf *pb;
   4081           1.31       cgd 	struct nameidata nd;
   4082           1.31       cgd 
   4083          1.409  dholland 	/* XXX bollocks, should pass in a pathbuf */
   4084          1.409  dholland 	error = pathbuf_maybe_copyin(path, seg, &pb);
   4085          1.409  dholland 	if (error) {
   4086          1.409  dholland 		return error;
   4087          1.409  dholland 	}
   4088          1.409  dholland 
   4089          1.409  dholland 	NDINIT(&nd, CREATE, LOCKPARENT | CREATEDIR | TRYEMULROOT, pb);
   4090          1.409  dholland 	if ((error = namei(&nd)) != 0) {
   4091          1.409  dholland 		pathbuf_destroy(pb);
   4092           1.31       cgd 		return (error);
   4093          1.409  dholland 	}
   4094           1.31       cgd 	vp = nd.ni_vp;
   4095           1.31       cgd 	if (vp != NULL) {
   4096           1.31       cgd 		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
   4097           1.31       cgd 		if (nd.ni_dvp == vp)
   4098           1.31       cgd 			vrele(nd.ni_dvp);
   4099           1.31       cgd 		else
   4100           1.31       cgd 			vput(nd.ni_dvp);
   4101           1.31       cgd 		vrele(vp);
   4102          1.409  dholland 		pathbuf_destroy(pb);
   4103           1.31       cgd 		return (EEXIST);
   4104           1.31       cgd 	}
   4105          1.402     pooka 	vattr_null(&vattr);
   4106           1.31       cgd 	vattr.va_type = VDIR;
   4107          1.328        ad 	/* We will read cwdi->cwdi_cmask unlocked. */
   4108          1.396     pooka 	vattr.va_mode = (mode & ACCESSPERMS) &~ p->p_cwdi->cwdi_cmask;
   4109           1.31       cgd 	error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
   4110           1.31       cgd 	if (!error)
   4111           1.31       cgd 		vput(nd.ni_vp);
   4112          1.409  dholland 	pathbuf_destroy(pb);
   4113           1.31       cgd 	return (error);
   4114           1.31       cgd }
   4115           1.31       cgd 
   4116           1.31       cgd /*
   4117           1.31       cgd  * Remove a directory file.
   4118           1.31       cgd  */
   4119           1.31       cgd /* ARGSUSED */
   4120           1.63  christos int
   4121          1.335       dsl sys_rmdir(struct lwp *l, const struct sys_rmdir_args *uap, register_t *retval)
   4122           1.56   thorpej {
   4123          1.335       dsl 	/* {
   4124           1.74       cgd 		syscallarg(const char *) path;
   4125          1.335       dsl 	} */
   4126          1.155  augustss 	struct vnode *vp;
   4127           1.31       cgd 	int error;
   4128          1.409  dholland 	struct pathbuf *pb;
   4129           1.31       cgd 	struct nameidata nd;
   4130           1.31       cgd 
   4131          1.409  dholland 	error = pathbuf_copyin(SCARG(uap, path), &pb);
   4132          1.409  dholland 	if (error) {
   4133          1.409  dholland 		return error;
   4134          1.409  dholland 	}
   4135          1.409  dholland 	NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF | TRYEMULROOT, pb);
   4136          1.409  dholland 	if ((error = namei(&nd)) != 0) {
   4137          1.409  dholland 		pathbuf_destroy(pb);
   4138          1.409  dholland 		return error;
   4139          1.409  dholland 	}
   4140           1.31       cgd 	vp = nd.ni_vp;
   4141           1.31       cgd 	if (vp->v_type != VDIR) {
   4142           1.31       cgd 		error = ENOTDIR;
   4143           1.31       cgd 		goto out;
   4144           1.31       cgd 	}
   4145           1.31       cgd 	/*
   4146           1.31       cgd 	 * No rmdir "." please.
   4147           1.31       cgd 	 */
   4148           1.31       cgd 	if (nd.ni_dvp == vp) {
   4149           1.31       cgd 		error = EINVAL;
   4150           1.31       cgd 		goto out;
   4151           1.31       cgd 	}
   4152           1.31       cgd 	/*
   4153           1.31       cgd 	 * The root of a mounted filesystem cannot be deleted.
   4154           1.31       cgd 	 */
   4155          1.350     joerg 	if ((vp->v_vflag & VV_ROOT) != 0 || vp->v_mountedhere != NULL) {
   4156           1.31       cgd 		error = EBUSY;
   4157          1.197   hannken 		goto out;
   4158          1.197   hannken 	}
   4159          1.197   hannken 	error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
   4160          1.409  dholland 	pathbuf_destroy(pb);
   4161          1.197   hannken 	return (error);
   4162          1.197   hannken 
   4163          1.197   hannken out:
   4164          1.197   hannken 	VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
   4165          1.197   hannken 	if (nd.ni_dvp == vp)
   4166          1.197   hannken 		vrele(nd.ni_dvp);
   4167          1.197   hannken 	else
   4168          1.197   hannken 		vput(nd.ni_dvp);
   4169          1.197   hannken 	vput(vp);
   4170          1.409  dholland 	pathbuf_destroy(pb);
   4171           1.31       cgd 	return (error);
   4172           1.31       cgd }
   4173           1.31       cgd 
   4174           1.31       cgd /*
   4175           1.31       cgd  * Read a block of directory entries in a file system independent format.
   4176           1.31       cgd  */
   4177           1.63  christos int
   4178          1.335       dsl sys___getdents30(struct lwp *l, const struct sys___getdents30_args *uap, register_t *retval)
   4179           1.56   thorpej {
   4180          1.335       dsl 	/* {
   4181           1.35       cgd 		syscallarg(int) fd;
   4182           1.35       cgd 		syscallarg(char *) buf;
   4183          1.101      fvdl 		syscallarg(size_t) count;
   4184          1.335       dsl 	} */
   4185          1.346        ad 	file_t *fp;
   4186          1.101      fvdl 	int error, done;
   4187           1.31       cgd 
   4188          1.346        ad 	/* fd_getvnode() will use the descriptor for us */
   4189          1.346        ad 	if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0)
   4190           1.31       cgd 		return (error);
   4191          1.135   thorpej 	if ((fp->f_flag & FREAD) == 0) {
   4192          1.135   thorpej 		error = EBADF;
   4193          1.135   thorpej 		goto out;
   4194          1.135   thorpej 	}
   4195          1.101      fvdl 	error = vn_readdir(fp, SCARG(uap, buf), UIO_USERSPACE,
   4196          1.234  christos 			SCARG(uap, count), &done, l, 0, 0);
   4197          1.325        ad 	ktrgenio(SCARG(uap, fd), UIO_READ, SCARG(uap, buf), done, error);
   4198          1.101      fvdl 	*retval = done;
   4199          1.135   thorpej  out:
   4200          1.346        ad 	fd_putfile(SCARG(uap, fd));
   4201           1.31       cgd 	return (error);
   4202           1.31       cgd }
   4203           1.31       cgd 
   4204           1.31       cgd /*
   4205           1.31       cgd  * Set the mode mask for creation of filesystem nodes.
   4206           1.31       cgd  */
   4207           1.56   thorpej int
   4208          1.335       dsl sys_umask(struct lwp *l, const struct sys_umask_args *uap, register_t *retval)
   4209           1.56   thorpej {
   4210          1.335       dsl 	/* {
   4211          1.103   mycroft 		syscallarg(mode_t) newmask;
   4212          1.335       dsl 	} */
   4213          1.179   thorpej 	struct proc *p = l->l_proc;
   4214          1.134   thorpej 	struct cwdinfo *cwdi;
   4215           1.31       cgd 
   4216          1.328        ad 	/*
   4217          1.328        ad 	 * cwdi->cwdi_cmask will be read unlocked elsewhere.  What's
   4218          1.328        ad 	 * important is that we serialize changes to the mask.  The
   4219          1.328        ad 	 * rw_exit() will issue a write memory barrier on our behalf,
   4220          1.328        ad 	 * and force the changes out to other CPUs (as it must use an
   4221          1.328        ad 	 * atomic operation, draining the local CPU's store buffers).
   4222          1.328        ad 	 */
   4223          1.134   thorpej 	cwdi = p->p_cwdi;
   4224          1.328        ad 	rw_enter(&cwdi->cwdi_lock, RW_WRITER);
   4225          1.134   thorpej 	*retval = cwdi->cwdi_cmask;
   4226          1.134   thorpej 	cwdi->cwdi_cmask = SCARG(uap, newmask) & ALLPERMS;
   4227          1.328        ad 	rw_exit(&cwdi->cwdi_lock);
   4228          1.328        ad 
   4229           1.31       cgd 	return (0);
   4230           1.31       cgd }
   4231           1.31       cgd 
   4232          1.340      elad int
   4233          1.340      elad dorevoke(struct vnode *vp, kauth_cred_t cred)
   4234          1.340      elad {
   4235          1.340      elad 	struct vattr vattr;
   4236          1.340      elad 	int error;
   4237          1.340      elad 
   4238          1.440   hannken 	vn_lock(vp, LK_SHARED | LK_RETRY);
   4239          1.440   hannken 	error = VOP_GETATTR(vp, &vattr, cred);
   4240          1.440   hannken 	VOP_UNLOCK(vp);
   4241          1.440   hannken 	if (error != 0)
   4242          1.342        ad 		return error;
   4243          1.385     enami 	if (kauth_cred_geteuid(cred) == vattr.va_uid ||
   4244          1.340      elad 	    (error = kauth_authorize_generic(cred,
   4245          1.342        ad 	    KAUTH_GENERIC_ISSUSER, NULL)) == 0)
   4246          1.340      elad 		VOP_REVOKE(vp, REVOKEALL);
   4247          1.340      elad 	return (error);
   4248          1.340      elad }
   4249          1.340      elad 
   4250           1.31       cgd /*
   4251           1.31       cgd  * Void all references to file by ripping underlying filesystem
   4252           1.31       cgd  * away from vnode.
   4253           1.31       cgd  */
   4254           1.31       cgd /* ARGSUSED */
   4255           1.63  christos int
   4256          1.335       dsl sys_revoke(struct lwp *l, const struct sys_revoke_args *uap, register_t *retval)
   4257           1.56   thorpej {
   4258          1.335       dsl 	/* {
   4259           1.74       cgd 		syscallarg(const char *) path;
   4260          1.335       dsl 	} */
   4261          1.155  augustss 	struct vnode *vp;
   4262           1.31       cgd 	int error;
   4263           1.31       cgd 
   4264          1.395  dholland 	error = namei_simple_user(SCARG(uap, path),
   4265          1.395  dholland 				NSM_FOLLOW_TRYEMULROOT, &vp);
   4266          1.395  dholland 	if (error != 0)
   4267           1.31       cgd 		return (error);
   4268          1.340      elad 	error = dorevoke(vp, l->l_cred);
   4269           1.31       cgd 	vrele(vp);
   4270           1.31       cgd 	return (error);
   4271           1.31       cgd }
   4272