vfs_syscalls.c revision 1.324.4.2 1 1.324.4.2 pooka /* $NetBSD: vfs_syscalls.c,v 1.324.4.2 2007/07/31 21:14:22 pooka Exp $ */
2 1.324.4.2 pooka
3 1.324.4.2 pooka /*
4 1.324.4.2 pooka * Copyright (c) 1989, 1993
5 1.324.4.2 pooka * The Regents of the University of California. All rights reserved.
6 1.324.4.2 pooka * (c) UNIX System Laboratories, Inc.
7 1.324.4.2 pooka * All or some portions of this file are derived from material licensed
8 1.324.4.2 pooka * to the University of California by American Telephone and Telegraph
9 1.324.4.2 pooka * Co. or Unix System Laboratories, Inc. and are reproduced herein with
10 1.324.4.2 pooka * the permission of UNIX System Laboratories, Inc.
11 1.324.4.2 pooka *
12 1.324.4.2 pooka * Redistribution and use in source and binary forms, with or without
13 1.324.4.2 pooka * modification, are permitted provided that the following conditions
14 1.324.4.2 pooka * are met:
15 1.324.4.2 pooka * 1. Redistributions of source code must retain the above copyright
16 1.324.4.2 pooka * notice, this list of conditions and the following disclaimer.
17 1.324.4.2 pooka * 2. Redistributions in binary form must reproduce the above copyright
18 1.324.4.2 pooka * notice, this list of conditions and the following disclaimer in the
19 1.324.4.2 pooka * documentation and/or other materials provided with the distribution.
20 1.324.4.2 pooka * 3. Neither the name of the University nor the names of its contributors
21 1.324.4.2 pooka * may be used to endorse or promote products derived from this software
22 1.324.4.2 pooka * without specific prior written permission.
23 1.324.4.2 pooka *
24 1.324.4.2 pooka * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 1.324.4.2 pooka * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 1.324.4.2 pooka * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 1.324.4.2 pooka * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 1.324.4.2 pooka * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 1.324.4.2 pooka * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 1.324.4.2 pooka * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 1.324.4.2 pooka * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 1.324.4.2 pooka * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 1.324.4.2 pooka * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 1.324.4.2 pooka * SUCH DAMAGE.
35 1.324.4.2 pooka *
36 1.324.4.2 pooka * @(#)vfs_syscalls.c 8.42 (Berkeley) 7/31/95
37 1.324.4.2 pooka */
38 1.324.4.2 pooka
39 1.324.4.2 pooka #include <sys/cdefs.h>
40 1.324.4.2 pooka __KERNEL_RCSID(0, "$NetBSD: vfs_syscalls.c,v 1.324.4.2 2007/07/31 21:14:22 pooka Exp $");
41 1.324.4.2 pooka
42 1.324.4.2 pooka #include "opt_compat_netbsd.h"
43 1.324.4.2 pooka #include "opt_compat_43.h"
44 1.324.4.2 pooka #include "opt_fileassoc.h"
45 1.324.4.2 pooka #include "opt_ktrace.h"
46 1.324.4.2 pooka #include "fss.h"
47 1.324.4.2 pooka #include "veriexec.h"
48 1.324.4.2 pooka
49 1.324.4.2 pooka #include <sys/param.h>
50 1.324.4.2 pooka #include <sys/systm.h>
51 1.324.4.2 pooka #include <sys/namei.h>
52 1.324.4.2 pooka #include <sys/filedesc.h>
53 1.324.4.2 pooka #include <sys/kernel.h>
54 1.324.4.2 pooka #include <sys/file.h>
55 1.324.4.2 pooka #include <sys/stat.h>
56 1.324.4.2 pooka #include <sys/vnode.h>
57 1.324.4.2 pooka #include <sys/mount.h>
58 1.324.4.2 pooka #include <sys/proc.h>
59 1.324.4.2 pooka #include <sys/uio.h>
60 1.324.4.2 pooka #include <sys/malloc.h>
61 1.324.4.2 pooka #include <sys/kmem.h>
62 1.324.4.2 pooka #include <sys/dirent.h>
63 1.324.4.2 pooka #include <sys/sysctl.h>
64 1.324.4.2 pooka #include <sys/syscallargs.h>
65 1.324.4.2 pooka #include <sys/vfs_syscalls.h>
66 1.324.4.2 pooka #ifdef KTRACE
67 1.324.4.2 pooka #include <sys/ktrace.h>
68 1.324.4.2 pooka #endif
69 1.324.4.2 pooka #ifdef FILEASSOC
70 1.324.4.2 pooka #include <sys/fileassoc.h>
71 1.324.4.2 pooka #endif /* FILEASSOC */
72 1.324.4.2 pooka #include <sys/verified_exec.h>
73 1.324.4.2 pooka #include <sys/kauth.h>
74 1.324.4.2 pooka
75 1.324.4.2 pooka #include <miscfs/genfs/genfs.h>
76 1.324.4.2 pooka #include <miscfs/syncfs/syncfs.h>
77 1.324.4.2 pooka
78 1.324.4.2 pooka #ifdef COMPAT_30
79 1.324.4.2 pooka #include "opt_nfsserver.h"
80 1.324.4.2 pooka #include <nfs/rpcv2.h>
81 1.324.4.2 pooka #endif
82 1.324.4.2 pooka #include <nfs/nfsproto.h>
83 1.324.4.2 pooka #ifdef COMPAT_30
84 1.324.4.2 pooka #include <nfs/nfs.h>
85 1.324.4.2 pooka #include <nfs/nfs_var.h>
86 1.324.4.2 pooka #endif
87 1.324.4.2 pooka
88 1.324.4.2 pooka #if NFSS > 0
89 1.324.4.2 pooka #include <dev/fssvar.h>
90 1.324.4.2 pooka #endif
91 1.324.4.2 pooka
92 1.324.4.2 pooka MALLOC_DEFINE(M_MOUNT, "mount", "vfs mount struct");
93 1.324.4.2 pooka
94 1.324.4.2 pooka static int change_dir(struct nameidata *, struct lwp *);
95 1.324.4.2 pooka static int change_flags(struct vnode *, u_long, struct lwp *);
96 1.324.4.2 pooka static int change_mode(struct vnode *, int, struct lwp *l);
97 1.324.4.2 pooka static int change_owner(struct vnode *, uid_t, gid_t, struct lwp *, int);
98 1.324.4.2 pooka static int rename_files(const char *, const char *, struct lwp *, int);
99 1.324.4.2 pooka
100 1.324.4.2 pooka void checkdirs(struct vnode *);
101 1.324.4.2 pooka
102 1.324.4.2 pooka int dovfsusermount = 0;
103 1.324.4.2 pooka
104 1.324.4.2 pooka /*
105 1.324.4.2 pooka * Virtual File System System Calls
106 1.324.4.2 pooka */
107 1.324.4.2 pooka
108 1.324.4.2 pooka /*
109 1.324.4.2 pooka * Mount a file system.
110 1.324.4.2 pooka */
111 1.324.4.2 pooka
112 1.324.4.2 pooka #if defined(COMPAT_09) || defined(COMPAT_43)
113 1.324.4.2 pooka /*
114 1.324.4.2 pooka * This table is used to maintain compatibility with 4.3BSD
115 1.324.4.2 pooka * and NetBSD 0.9 mount syscalls. Note, the order is important!
116 1.324.4.2 pooka *
117 1.324.4.2 pooka * Do not modify this table. It should only contain filesystems
118 1.324.4.2 pooka * supported by NetBSD 0.9 and 4.3BSD.
119 1.324.4.2 pooka */
120 1.324.4.2 pooka const char * const mountcompatnames[] = {
121 1.324.4.2 pooka NULL, /* 0 = MOUNT_NONE */
122 1.324.4.2 pooka MOUNT_FFS, /* 1 = MOUNT_UFS */
123 1.324.4.2 pooka MOUNT_NFS, /* 2 */
124 1.324.4.2 pooka MOUNT_MFS, /* 3 */
125 1.324.4.2 pooka MOUNT_MSDOS, /* 4 */
126 1.324.4.2 pooka MOUNT_CD9660, /* 5 = MOUNT_ISOFS */
127 1.324.4.2 pooka MOUNT_FDESC, /* 6 */
128 1.324.4.2 pooka MOUNT_KERNFS, /* 7 */
129 1.324.4.2 pooka NULL, /* 8 = MOUNT_DEVFS */
130 1.324.4.2 pooka MOUNT_AFS, /* 9 */
131 1.324.4.2 pooka };
132 1.324.4.2 pooka const int nmountcompatnames = sizeof(mountcompatnames) /
133 1.324.4.2 pooka sizeof(mountcompatnames[0]);
134 1.324.4.2 pooka #endif /* COMPAT_09 || COMPAT_43 */
135 1.324.4.2 pooka
136 1.324.4.2 pooka static int
137 1.324.4.2 pooka mount_update(struct lwp *l, struct vnode *vp, const char *path, int flags,
138 1.324.4.2 pooka void *data, size_t *data_len)
139 1.324.4.2 pooka {
140 1.324.4.2 pooka struct mount *mp;
141 1.324.4.2 pooka int error = 0, saved_flags;
142 1.324.4.2 pooka
143 1.324.4.2 pooka mp = vp->v_mount;
144 1.324.4.2 pooka saved_flags = mp->mnt_flag;
145 1.324.4.2 pooka
146 1.324.4.2 pooka /* We can operate only on VROOT nodes. */
147 1.324.4.2 pooka if ((vp->v_flag & VROOT) == 0)
148 1.324.4.2 pooka return EINVAL;
149 1.324.4.2 pooka
150 1.324.4.2 pooka /*
151 1.324.4.2 pooka * We only allow the filesystem to be reloaded if it
152 1.324.4.2 pooka * is currently mounted read-only.
153 1.324.4.2 pooka */
154 1.324.4.2 pooka if (flags & MNT_RELOAD && !(mp->mnt_flag & MNT_RDONLY))
155 1.324.4.2 pooka return EOPNOTSUPP; /* Needs translation */
156 1.324.4.2 pooka
157 1.324.4.2 pooka error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_MOUNT,
158 1.324.4.2 pooka KAUTH_REQ_SYSTEM_MOUNT_UPDATE, mp, KAUTH_ARG(flags), data);
159 1.324.4.2 pooka if (error)
160 1.324.4.2 pooka return error;
161 1.324.4.2 pooka
162 1.324.4.2 pooka if (vfs_busy(mp, LK_NOWAIT, 0))
163 1.324.4.2 pooka return EPERM;
164 1.324.4.2 pooka
165 1.324.4.2 pooka mp->mnt_flag &= ~MNT_OP_FLAGS;
166 1.324.4.2 pooka mp->mnt_flag |= flags & (MNT_RELOAD | MNT_FORCE | MNT_UPDATE);
167 1.324.4.2 pooka
168 1.324.4.2 pooka /*
169 1.324.4.2 pooka * Set the mount level flags.
170 1.324.4.2 pooka */
171 1.324.4.2 pooka if (flags & MNT_RDONLY)
172 1.324.4.2 pooka mp->mnt_flag |= MNT_RDONLY;
173 1.324.4.2 pooka else if (mp->mnt_flag & MNT_RDONLY)
174 1.324.4.2 pooka mp->mnt_iflag |= IMNT_WANTRDWR;
175 1.324.4.2 pooka mp->mnt_flag &=
176 1.324.4.2 pooka ~(MNT_NOSUID | MNT_NOEXEC | MNT_NODEV |
177 1.324.4.2 pooka MNT_SYNCHRONOUS | MNT_UNION | MNT_ASYNC | MNT_NOCOREDUMP |
178 1.324.4.2 pooka MNT_NOATIME | MNT_NODEVMTIME | MNT_SYMPERM | MNT_SOFTDEP);
179 1.324.4.2 pooka mp->mnt_flag |= flags &
180 1.324.4.2 pooka (MNT_NOSUID | MNT_NOEXEC | MNT_NODEV |
181 1.324.4.2 pooka MNT_SYNCHRONOUS | MNT_UNION | MNT_ASYNC | MNT_NOCOREDUMP |
182 1.324.4.2 pooka MNT_NOATIME | MNT_NODEVMTIME | MNT_SYMPERM | MNT_SOFTDEP |
183 1.324.4.2 pooka MNT_IGNORE);
184 1.324.4.2 pooka
185 1.324.4.2 pooka error = VFS_MOUNT(mp, path, data, data_len, l);
186 1.324.4.2 pooka
187 1.324.4.2 pooka #if defined(COMPAT_30) && defined(NFSSERVER)
188 1.324.4.2 pooka if (error && data != NULL) {
189 1.324.4.2 pooka int error2;
190 1.324.4.2 pooka
191 1.324.4.2 pooka /* Update failed; let's try and see if it was an
192 1.324.4.2 pooka * export request. */
193 1.324.4.2 pooka error2 = nfs_update_exports_30(mp, path, data, l);
194 1.324.4.2 pooka
195 1.324.4.2 pooka /* Only update error code if the export request was
196 1.324.4.2 pooka * understood but some problem occurred while
197 1.324.4.2 pooka * processing it. */
198 1.324.4.2 pooka if (error2 != EJUSTRETURN)
199 1.324.4.2 pooka error = error2;
200 1.324.4.2 pooka }
201 1.324.4.2 pooka #endif
202 1.324.4.2 pooka if (mp->mnt_iflag & IMNT_WANTRDWR)
203 1.324.4.2 pooka mp->mnt_flag &= ~MNT_RDONLY;
204 1.324.4.2 pooka if (error)
205 1.324.4.2 pooka mp->mnt_flag = saved_flags;
206 1.324.4.2 pooka mp->mnt_flag &= ~MNT_OP_FLAGS;
207 1.324.4.2 pooka mp->mnt_iflag &= ~IMNT_WANTRDWR;
208 1.324.4.2 pooka if ((mp->mnt_flag & (MNT_RDONLY | MNT_ASYNC)) == 0) {
209 1.324.4.2 pooka if (mp->mnt_syncer == NULL)
210 1.324.4.2 pooka error = vfs_allocate_syncvnode(mp);
211 1.324.4.2 pooka } else {
212 1.324.4.2 pooka if (mp->mnt_syncer != NULL)
213 1.324.4.2 pooka vfs_deallocate_syncvnode(mp);
214 1.324.4.2 pooka }
215 1.324.4.2 pooka vfs_unbusy(mp);
216 1.324.4.2 pooka
217 1.324.4.2 pooka return (error);
218 1.324.4.2 pooka }
219 1.324.4.2 pooka
220 1.324.4.2 pooka static int
221 1.324.4.2 pooka mount_get_vfsops(const char *fstype, struct vfsops **vfsops)
222 1.324.4.2 pooka {
223 1.324.4.2 pooka char fstypename[sizeof(((struct statvfs *)NULL)->f_fstypename)];
224 1.324.4.2 pooka int error;
225 1.324.4.2 pooka
226 1.324.4.2 pooka /* Copy file-system type from userspace. */
227 1.324.4.2 pooka error = copyinstr(fstype, fstypename, sizeof(fstypename), NULL);
228 1.324.4.2 pooka if (error) {
229 1.324.4.2 pooka #if defined(COMPAT_09) || defined(COMPAT_43)
230 1.324.4.2 pooka /*
231 1.324.4.2 pooka * Historically, filesystem types were identified by numbers.
232 1.324.4.2 pooka * If we get an integer for the filesystem type instead of a
233 1.324.4.2 pooka * string, we check to see if it matches one of the historic
234 1.324.4.2 pooka * filesystem types.
235 1.324.4.2 pooka */
236 1.324.4.2 pooka u_long fsindex = (u_long)fstype;
237 1.324.4.2 pooka if (fsindex >= nmountcompatnames ||
238 1.324.4.2 pooka mountcompatnames[fsindex] == NULL)
239 1.324.4.2 pooka return ENODEV;
240 1.324.4.2 pooka strlcpy(fstypename, mountcompatnames[fsindex], sizeof(fstypename));
241 1.324.4.2 pooka #else
242 1.324.4.2 pooka return error;
243 1.324.4.2 pooka #endif
244 1.324.4.2 pooka }
245 1.324.4.2 pooka
246 1.324.4.2 pooka #ifdef COMPAT_10
247 1.324.4.2 pooka /* Accept `ufs' as an alias for `ffs'. */
248 1.324.4.2 pooka if (strcmp(fstypename, "ufs") == 0)
249 1.324.4.2 pooka fstypename[0] = 'f';
250 1.324.4.2 pooka #endif
251 1.324.4.2 pooka
252 1.324.4.2 pooka if ((*vfsops = vfs_getopsbyname(fstypename)) == NULL)
253 1.324.4.2 pooka return ENODEV;
254 1.324.4.2 pooka return 0;
255 1.324.4.2 pooka }
256 1.324.4.2 pooka
257 1.324.4.2 pooka static int
258 1.324.4.2 pooka mount_domount(struct lwp *l, struct vnode **vpp, struct vfsops *vfsops,
259 1.324.4.2 pooka const char *path, int flags, void *data, size_t *data_len)
260 1.324.4.2 pooka {
261 1.324.4.2 pooka struct mount *mp = NULL;
262 1.324.4.2 pooka struct vnode *vp = *vpp;
263 1.324.4.2 pooka struct vattr va;
264 1.324.4.2 pooka int error;
265 1.324.4.2 pooka
266 1.324.4.2 pooka error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_MOUNT,
267 1.324.4.2 pooka KAUTH_REQ_SYSTEM_MOUNT_NEW, vp, KAUTH_ARG(flags), data);
268 1.324.4.2 pooka if (error)
269 1.324.4.2 pooka return error;
270 1.324.4.2 pooka
271 1.324.4.2 pooka /* Can't make a non-dir a mount-point (from here anyway). */
272 1.324.4.2 pooka if (vp->v_type != VDIR)
273 1.324.4.2 pooka return ENOTDIR;
274 1.324.4.2 pooka
275 1.324.4.2 pooka /*
276 1.324.4.2 pooka * If the user is not root, ensure that they own the directory
277 1.324.4.2 pooka * onto which we are attempting to mount.
278 1.324.4.2 pooka */
279 1.324.4.2 pooka if ((error = VOP_GETATTR(vp, &va, l->l_cred, l)) != 0 ||
280 1.324.4.2 pooka (va.va_uid != kauth_cred_geteuid(l->l_cred) &&
281 1.324.4.2 pooka (error = kauth_authorize_generic(l->l_cred,
282 1.324.4.2 pooka KAUTH_GENERIC_ISSUSER, NULL)) != 0)) {
283 1.324.4.2 pooka return error;
284 1.324.4.2 pooka }
285 1.324.4.2 pooka
286 1.324.4.2 pooka if (flags & MNT_EXPORTED)
287 1.324.4.2 pooka return EINVAL;
288 1.324.4.2 pooka
289 1.324.4.2 pooka if ((error = vinvalbuf(vp, V_SAVE, l->l_cred, l, 0, 0)) != 0)
290 1.324.4.2 pooka return error;
291 1.324.4.2 pooka
292 1.324.4.2 pooka /*
293 1.324.4.2 pooka * Check if a file-system is not already mounted on this vnode.
294 1.324.4.2 pooka */
295 1.324.4.2 pooka if (vp->v_mountedhere != NULL)
296 1.324.4.2 pooka return EBUSY;
297 1.324.4.2 pooka
298 1.324.4.2 pooka mp = malloc(sizeof(*mp), M_MOUNT, M_WAITOK|M_ZERO);
299 1.324.4.2 pooka
300 1.324.4.2 pooka mp->mnt_op = vfsops;
301 1.324.4.2 pooka
302 1.324.4.2 pooka TAILQ_INIT(&mp->mnt_vnodelist);
303 1.324.4.2 pooka lockinit(&mp->mnt_lock, PVFS, "vfslock", 0, 0);
304 1.324.4.2 pooka simple_lock_init(&mp->mnt_slock);
305 1.324.4.2 pooka (void)vfs_busy(mp, LK_NOWAIT, 0);
306 1.324.4.2 pooka
307 1.324.4.2 pooka mp->mnt_op->vfs_refcount++;
308 1.324.4.2 pooka mp->mnt_vnodecovered = vp;
309 1.324.4.2 pooka mp->mnt_stat.f_owner = kauth_cred_geteuid(l->l_cred);
310 1.324.4.2 pooka mp->mnt_unmounter = NULL;
311 1.324.4.2 pooka mount_initspecific(mp);
312 1.324.4.2 pooka
313 1.324.4.2 pooka /*
314 1.324.4.2 pooka * The underlying file system may refuse the mount for
315 1.324.4.2 pooka * various reasons. Allow the user to force it to happen.
316 1.324.4.2 pooka *
317 1.324.4.2 pooka * Set the mount level flags.
318 1.324.4.2 pooka */
319 1.324.4.2 pooka mp->mnt_flag = flags &
320 1.324.4.2 pooka (MNT_FORCE | MNT_NOSUID | MNT_NOEXEC | MNT_NODEV |
321 1.324.4.2 pooka MNT_SYNCHRONOUS | MNT_UNION | MNT_ASYNC | MNT_NOCOREDUMP |
322 1.324.4.2 pooka MNT_NOATIME | MNT_NODEVMTIME | MNT_SYMPERM | MNT_SOFTDEP |
323 1.324.4.2 pooka MNT_IGNORE | MNT_RDONLY);
324 1.324.4.2 pooka
325 1.324.4.2 pooka error = VFS_MOUNT(mp, path, data, data_len, l);
326 1.324.4.2 pooka mp->mnt_flag &= ~MNT_OP_FLAGS;
327 1.324.4.2 pooka
328 1.324.4.2 pooka /*
329 1.324.4.2 pooka * Put the new filesystem on the mount list after root.
330 1.324.4.2 pooka */
331 1.324.4.2 pooka cache_purge(vp);
332 1.324.4.2 pooka if (error != 0) {
333 1.324.4.2 pooka vp->v_mountedhere = NULL;
334 1.324.4.2 pooka mp->mnt_op->vfs_refcount--;
335 1.324.4.2 pooka vfs_unbusy(mp);
336 1.324.4.2 pooka free(mp, M_MOUNT);
337 1.324.4.2 pooka return error;
338 1.324.4.2 pooka }
339 1.324.4.2 pooka
340 1.324.4.2 pooka mp->mnt_iflag &= ~IMNT_WANTRDWR;
341 1.324.4.2 pooka vp->v_mountedhere = mp;
342 1.324.4.2 pooka simple_lock(&mountlist_slock);
343 1.324.4.2 pooka CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list);
344 1.324.4.2 pooka simple_unlock(&mountlist_slock);
345 1.324.4.2 pooka VOP_UNLOCK(vp, 0);
346 1.324.4.2 pooka checkdirs(vp);
347 1.324.4.2 pooka if ((mp->mnt_flag & (MNT_RDONLY | MNT_ASYNC)) == 0)
348 1.324.4.2 pooka error = vfs_allocate_syncvnode(mp);
349 1.324.4.2 pooka vfs_unbusy(mp);
350 1.324.4.2 pooka (void) VFS_STATVFS(mp, &mp->mnt_stat, l);
351 1.324.4.2 pooka error = VFS_START(mp, 0, l);
352 1.324.4.2 pooka if (error)
353 1.324.4.2 pooka vrele(vp);
354 1.324.4.2 pooka *vpp = NULL;
355 1.324.4.2 pooka return error;
356 1.324.4.2 pooka }
357 1.324.4.2 pooka
358 1.324.4.2 pooka static int
359 1.324.4.2 pooka mount_getargs(struct lwp *l, struct vnode *vp, const char *path, int flags,
360 1.324.4.2 pooka void *data, size_t *data_len)
361 1.324.4.2 pooka {
362 1.324.4.2 pooka struct mount *mp;
363 1.324.4.2 pooka int error;
364 1.324.4.2 pooka
365 1.324.4.2 pooka /* If MNT_GETARGS is specified, it should be the only flag. */
366 1.324.4.2 pooka if (flags & ~MNT_GETARGS)
367 1.324.4.2 pooka return EINVAL;
368 1.324.4.2 pooka
369 1.324.4.2 pooka mp = vp->v_mount;
370 1.324.4.2 pooka
371 1.324.4.2 pooka /* XXX: probably some notion of "can see" here if we want isolation. */
372 1.324.4.2 pooka error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_MOUNT,
373 1.324.4.2 pooka KAUTH_REQ_SYSTEM_MOUNT_GET, mp, data, NULL);
374 1.324.4.2 pooka if (error)
375 1.324.4.2 pooka return error;
376 1.324.4.2 pooka
377 1.324.4.2 pooka if ((vp->v_flag & VROOT) == 0)
378 1.324.4.2 pooka return EINVAL;
379 1.324.4.2 pooka
380 1.324.4.2 pooka if (vfs_busy(mp, LK_NOWAIT, 0))
381 1.324.4.2 pooka return EPERM;
382 1.324.4.2 pooka
383 1.324.4.2 pooka mp->mnt_flag &= ~MNT_OP_FLAGS;
384 1.324.4.2 pooka mp->mnt_flag |= MNT_GETARGS;
385 1.324.4.2 pooka error = VFS_MOUNT(mp, path, data, data_len, l);
386 1.324.4.2 pooka mp->mnt_flag &= ~MNT_OP_FLAGS;
387 1.324.4.2 pooka
388 1.324.4.2 pooka vfs_unbusy(mp);
389 1.324.4.2 pooka return (error);
390 1.324.4.2 pooka }
391 1.324.4.2 pooka
392 1.324.4.2 pooka #ifdef COMPAT_40
393 1.324.4.2 pooka /* ARGSUSED */
394 1.324.4.2 pooka int
395 1.324.4.2 pooka compat_40_sys_mount(struct lwp *l, void *v, register_t *retval)
396 1.324.4.2 pooka {
397 1.324.4.2 pooka struct compat_40_sys_mount_args /* {
398 1.324.4.2 pooka syscallarg(const char *) type;
399 1.324.4.2 pooka syscallarg(const char *) path;
400 1.324.4.2 pooka syscallarg(int) flags;
401 1.324.4.2 pooka syscallarg(void *) data;
402 1.324.4.2 pooka } */ *uap = v;
403 1.324.4.2 pooka register_t dummy;
404 1.324.4.2 pooka
405 1.324.4.2 pooka return do_sys_mount(l, NULL, SCARG(uap, type), SCARG(uap, path),
406 1.324.4.2 pooka SCARG(uap, flags), SCARG(uap, data), UIO_USERSPACE, 0, &dummy);
407 1.324.4.2 pooka }
408 1.324.4.2 pooka #endif
409 1.324.4.2 pooka
410 1.324.4.2 pooka int
411 1.324.4.2 pooka sys___mount50(struct lwp *l, void *v, register_t *retval)
412 1.324.4.2 pooka {
413 1.324.4.2 pooka struct sys___mount50_args /* {
414 1.324.4.2 pooka syscallarg(const char *) type;
415 1.324.4.2 pooka syscallarg(const char *) path;
416 1.324.4.2 pooka syscallarg(int) flags;
417 1.324.4.2 pooka syscallarg(void *) data;
418 1.324.4.2 pooka syscallarg(size_t) data_len;
419 1.324.4.2 pooka } */ *uap = v;
420 1.324.4.2 pooka
421 1.324.4.2 pooka return do_sys_mount(l, NULL, SCARG(uap, type), SCARG(uap, path),
422 1.324.4.2 pooka SCARG(uap, flags), SCARG(uap, data), UIO_USERSPACE,
423 1.324.4.2 pooka SCARG(uap, data_len), retval);
424 1.324.4.2 pooka }
425 1.324.4.2 pooka
426 1.324.4.2 pooka int
427 1.324.4.2 pooka do_sys_mount(struct lwp *l, struct vfsops *vfsops, const char *type,
428 1.324.4.2 pooka const char *path, int flags, void *data, enum uio_seg data_seg,
429 1.324.4.2 pooka size_t data_len, register_t *retval)
430 1.324.4.2 pooka {
431 1.324.4.2 pooka struct vnode *vp;
432 1.324.4.2 pooka struct nameidata nd;
433 1.324.4.2 pooka void *data_buf = data;
434 1.324.4.2 pooka int error;
435 1.324.4.2 pooka
436 1.324.4.2 pooka /*
437 1.324.4.2 pooka * Get vnode to be covered
438 1.324.4.2 pooka */
439 1.324.4.2 pooka NDINIT(&nd, LOOKUP, FOLLOW | TRYEMULROOT, UIO_USERSPACE, path, l);
440 1.324.4.2 pooka if ((error = namei(&nd)) != 0)
441 1.324.4.2 pooka return (error);
442 1.324.4.2 pooka vp = nd.ni_vp;
443 1.324.4.2 pooka
444 1.324.4.2 pooka /*
445 1.324.4.2 pooka * A lookup in VFS_MOUNT might result in an attempt to
446 1.324.4.2 pooka * lock this vnode again, so make the lock recursive.
447 1.324.4.2 pooka */
448 1.324.4.2 pooka vn_lock(vp, LK_EXCLUSIVE | LK_RETRY | LK_SETRECURSE);
449 1.324.4.2 pooka
450 1.324.4.2 pooka if (vfsops == NULL) {
451 1.324.4.2 pooka if (flags & (MNT_GETARGS | MNT_UPDATE))
452 1.324.4.2 pooka vfsops = vp->v_mount->mnt_op;
453 1.324.4.2 pooka else {
454 1.324.4.2 pooka /* 'type' is userspace */
455 1.324.4.2 pooka error = mount_get_vfsops(type, &vfsops);
456 1.324.4.2 pooka if (error != 0)
457 1.324.4.2 pooka goto done;
458 1.324.4.2 pooka }
459 1.324.4.2 pooka }
460 1.324.4.2 pooka
461 1.324.4.2 pooka if (data != NULL && data_seg == UIO_USERSPACE) {
462 1.324.4.2 pooka if (data_len == 0) {
463 1.324.4.2 pooka /* No length supplied, use default for filesystem */
464 1.324.4.2 pooka data_len = vfsops->vfs_min_mount_data;
465 1.324.4.2 pooka if (data_len > VFS_MAX_MOUNT_DATA) {
466 1.324.4.2 pooka /* maybe a force loaded old LKM */
467 1.324.4.2 pooka error = EINVAL;
468 1.324.4.2 pooka goto done;
469 1.324.4.2 pooka }
470 1.324.4.2 pooka #ifdef COMPAT_30
471 1.324.4.2 pooka /* Hopefully a longer buffer won't make copyin() fail */
472 1.324.4.2 pooka if (flags & MNT_UPDATE
473 1.324.4.2 pooka && data_len < sizeof (struct mnt_export_args30))
474 1.324.4.2 pooka data_len = sizeof (struct mnt_export_args30);
475 1.324.4.2 pooka #endif
476 1.324.4.2 pooka }
477 1.324.4.2 pooka data_buf = malloc(data_len, M_TEMP, M_WAITOK);
478 1.324.4.2 pooka
479 1.324.4.2 pooka /* NFS needs the buffer even for mnt_getargs .... */
480 1.324.4.2 pooka error = copyin(data, data_buf, data_len);
481 1.324.4.2 pooka if (error != 0)
482 1.324.4.2 pooka goto done;
483 1.324.4.2 pooka }
484 1.324.4.2 pooka
485 1.324.4.2 pooka if (flags & MNT_GETARGS) {
486 1.324.4.2 pooka if (data_len == 0) {
487 1.324.4.2 pooka error = EINVAL;
488 1.324.4.2 pooka goto done;
489 1.324.4.2 pooka }
490 1.324.4.2 pooka error = mount_getargs(l, vp, path, flags, data_buf, &data_len);
491 1.324.4.2 pooka if (error != 0)
492 1.324.4.2 pooka goto done;
493 1.324.4.2 pooka if (data_seg == UIO_USERSPACE)
494 1.324.4.2 pooka error = copyout(data_buf, data, data_len);
495 1.324.4.2 pooka *retval = data_len;
496 1.324.4.2 pooka } else if (flags & MNT_UPDATE) {
497 1.324.4.2 pooka error = mount_update(l, vp, path, flags, data_buf, &data_len);
498 1.324.4.2 pooka } else {
499 1.324.4.2 pooka /* Locking is handled internally in mount_domount(). */
500 1.324.4.2 pooka error = mount_domount(l, &vp, vfsops, path, flags, data_buf,
501 1.324.4.2 pooka &data_len);
502 1.324.4.2 pooka }
503 1.324.4.2 pooka
504 1.324.4.2 pooka done:
505 1.324.4.2 pooka if (vp)
506 1.324.4.2 pooka vput(vp);
507 1.324.4.2 pooka if (data_buf != data)
508 1.324.4.2 pooka free(data_buf, M_TEMP);
509 1.324.4.2 pooka return (error);
510 1.324.4.2 pooka }
511 1.324.4.2 pooka
512 1.324.4.2 pooka /*
513 1.324.4.2 pooka * Scan all active processes to see if any of them have a current
514 1.324.4.2 pooka * or root directory onto which the new filesystem has just been
515 1.324.4.2 pooka * mounted. If so, replace them with the new mount point.
516 1.324.4.2 pooka */
517 1.324.4.2 pooka void
518 1.324.4.2 pooka checkdirs(struct vnode *olddp)
519 1.324.4.2 pooka {
520 1.324.4.2 pooka struct cwdinfo *cwdi;
521 1.324.4.2 pooka struct vnode *newdp;
522 1.324.4.2 pooka struct proc *p;
523 1.324.4.2 pooka
524 1.324.4.2 pooka if (olddp->v_usecount == 1)
525 1.324.4.2 pooka return;
526 1.324.4.2 pooka if (VFS_ROOT(olddp->v_mountedhere, &newdp))
527 1.324.4.2 pooka panic("mount: lost mount");
528 1.324.4.2 pooka mutex_enter(&proclist_lock);
529 1.324.4.2 pooka PROCLIST_FOREACH(p, &allproc) {
530 1.324.4.2 pooka cwdi = p->p_cwdi;
531 1.324.4.2 pooka if (!cwdi)
532 1.324.4.2 pooka continue;
533 1.324.4.2 pooka if (cwdi->cwdi_cdir == olddp) {
534 1.324.4.2 pooka vrele(cwdi->cwdi_cdir);
535 1.324.4.2 pooka VREF(newdp);
536 1.324.4.2 pooka cwdi->cwdi_cdir = newdp;
537 1.324.4.2 pooka }
538 1.324.4.2 pooka if (cwdi->cwdi_rdir == olddp) {
539 1.324.4.2 pooka vrele(cwdi->cwdi_rdir);
540 1.324.4.2 pooka VREF(newdp);
541 1.324.4.2 pooka cwdi->cwdi_rdir = newdp;
542 1.324.4.2 pooka }
543 1.324.4.2 pooka }
544 1.324.4.2 pooka mutex_exit(&proclist_lock);
545 1.324.4.2 pooka if (rootvnode == olddp) {
546 1.324.4.2 pooka vrele(rootvnode);
547 1.324.4.2 pooka VREF(newdp);
548 1.324.4.2 pooka rootvnode = newdp;
549 1.324.4.2 pooka }
550 1.324.4.2 pooka vput(newdp);
551 1.324.4.2 pooka }
552 1.324.4.2 pooka
553 1.324.4.2 pooka /*
554 1.324.4.2 pooka * Unmount a file system.
555 1.324.4.2 pooka *
556 1.324.4.2 pooka * Note: unmount takes a path to the vnode mounted on as argument,
557 1.324.4.2 pooka * not special file (as before).
558 1.324.4.2 pooka */
559 1.324.4.2 pooka /* ARGSUSED */
560 1.324.4.2 pooka int
561 1.324.4.2 pooka sys_unmount(struct lwp *l, void *v, register_t *retval)
562 1.324.4.2 pooka {
563 1.324.4.2 pooka struct sys_unmount_args /* {
564 1.324.4.2 pooka syscallarg(const char *) path;
565 1.324.4.2 pooka syscallarg(int) flags;
566 1.324.4.2 pooka } */ *uap = v;
567 1.324.4.2 pooka struct vnode *vp;
568 1.324.4.2 pooka struct mount *mp;
569 1.324.4.2 pooka int error;
570 1.324.4.2 pooka struct nameidata nd;
571 1.324.4.2 pooka
572 1.324.4.2 pooka NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | TRYEMULROOT, UIO_USERSPACE,
573 1.324.4.2 pooka SCARG(uap, path), l);
574 1.324.4.2 pooka if ((error = namei(&nd)) != 0)
575 1.324.4.2 pooka return (error);
576 1.324.4.2 pooka vp = nd.ni_vp;
577 1.324.4.2 pooka mp = vp->v_mount;
578 1.324.4.2 pooka
579 1.324.4.2 pooka error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_MOUNT,
580 1.324.4.2 pooka KAUTH_REQ_SYSTEM_MOUNT_UNMOUNT, mp, NULL, NULL);
581 1.324.4.2 pooka if (error) {
582 1.324.4.2 pooka vput(vp);
583 1.324.4.2 pooka return (error);
584 1.324.4.2 pooka }
585 1.324.4.2 pooka
586 1.324.4.2 pooka /*
587 1.324.4.2 pooka * Don't allow unmounting the root file system.
588 1.324.4.2 pooka */
589 1.324.4.2 pooka if (mp->mnt_flag & MNT_ROOTFS) {
590 1.324.4.2 pooka vput(vp);
591 1.324.4.2 pooka return (EINVAL);
592 1.324.4.2 pooka }
593 1.324.4.2 pooka
594 1.324.4.2 pooka /*
595 1.324.4.2 pooka * Must be the root of the filesystem
596 1.324.4.2 pooka */
597 1.324.4.2 pooka if ((vp->v_flag & VROOT) == 0) {
598 1.324.4.2 pooka vput(vp);
599 1.324.4.2 pooka return (EINVAL);
600 1.324.4.2 pooka }
601 1.324.4.2 pooka vput(vp);
602 1.324.4.2 pooka
603 1.324.4.2 pooka /*
604 1.324.4.2 pooka * XXX Freeze syncer. Must do this before locking the
605 1.324.4.2 pooka * mount point. See dounmount() for details.
606 1.324.4.2 pooka */
607 1.324.4.2 pooka mutex_enter(&syncer_mutex);
608 1.324.4.2 pooka
609 1.324.4.2 pooka if (vfs_busy(mp, 0, 0)) {
610 1.324.4.2 pooka mutex_exit(&syncer_mutex);
611 1.324.4.2 pooka return (EBUSY);
612 1.324.4.2 pooka }
613 1.324.4.2 pooka
614 1.324.4.2 pooka return (dounmount(mp, SCARG(uap, flags), l));
615 1.324.4.2 pooka }
616 1.324.4.2 pooka
617 1.324.4.2 pooka /*
618 1.324.4.2 pooka * Do the actual file system unmount. File system is assumed to have been
619 1.324.4.2 pooka * marked busy by the caller.
620 1.324.4.2 pooka */
621 1.324.4.2 pooka int
622 1.324.4.2 pooka dounmount(struct mount *mp, int flags, struct lwp *l)
623 1.324.4.2 pooka {
624 1.324.4.2 pooka struct vnode *coveredvp;
625 1.324.4.2 pooka int error;
626 1.324.4.2 pooka int async;
627 1.324.4.2 pooka int used_syncer;
628 1.324.4.2 pooka
629 1.324.4.2 pooka #if NVERIEXEC > 0
630 1.324.4.2 pooka error = veriexec_unmountchk(mp);
631 1.324.4.2 pooka if (error)
632 1.324.4.2 pooka return (error);
633 1.324.4.2 pooka #endif /* NVERIEXEC > 0 */
634 1.324.4.2 pooka
635 1.324.4.2 pooka simple_lock(&mountlist_slock);
636 1.324.4.2 pooka vfs_unbusy(mp);
637 1.324.4.2 pooka used_syncer = (mp->mnt_syncer != NULL);
638 1.324.4.2 pooka
639 1.324.4.2 pooka /*
640 1.324.4.2 pooka * XXX Syncer must be frozen when we get here. This should really
641 1.324.4.2 pooka * be done on a per-mountpoint basis, but especially the softdep
642 1.324.4.2 pooka * code possibly called from the syncer doesn't exactly work on a
643 1.324.4.2 pooka * per-mountpoint basis, so the softdep code would become a maze
644 1.324.4.2 pooka * of vfs_busy() calls.
645 1.324.4.2 pooka *
646 1.324.4.2 pooka * The caller of dounmount() must acquire syncer_mutex because
647 1.324.4.2 pooka * the syncer itself acquires locks in syncer_mutex -> vfs_busy
648 1.324.4.2 pooka * order, and we must preserve that order to avoid deadlock.
649 1.324.4.2 pooka *
650 1.324.4.2 pooka * So, if the file system did not use the syncer, now is
651 1.324.4.2 pooka * the time to release the syncer_mutex.
652 1.324.4.2 pooka */
653 1.324.4.2 pooka if (used_syncer == 0)
654 1.324.4.2 pooka mutex_exit(&syncer_mutex);
655 1.324.4.2 pooka
656 1.324.4.2 pooka mp->mnt_iflag |= IMNT_UNMOUNT;
657 1.324.4.2 pooka mp->mnt_unmounter = l;
658 1.324.4.2 pooka lockmgr(&mp->mnt_lock, LK_DRAIN | LK_INTERLOCK, &mountlist_slock);
659 1.324.4.2 pooka
660 1.324.4.2 pooka async = mp->mnt_flag & MNT_ASYNC;
661 1.324.4.2 pooka mp->mnt_flag &= ~MNT_ASYNC;
662 1.324.4.2 pooka cache_purgevfs(mp); /* remove cache entries for this file sys */
663 1.324.4.2 pooka if (mp->mnt_syncer != NULL)
664 1.324.4.2 pooka vfs_deallocate_syncvnode(mp);
665 1.324.4.2 pooka error = 0;
666 1.324.4.2 pooka if ((mp->mnt_flag & MNT_RDONLY) == 0) {
667 1.324.4.2 pooka #if NFSS > 0
668 1.324.4.2 pooka error = fss_umount_hook(mp, (flags & MNT_FORCE));
669 1.324.4.2 pooka #endif
670 1.324.4.2 pooka if (error == 0)
671 1.324.4.2 pooka error = VFS_SYNC(mp, MNT_WAIT, l->l_cred, l);
672 1.324.4.2 pooka }
673 1.324.4.2 pooka if (error == 0 || (flags & MNT_FORCE))
674 1.324.4.2 pooka error = VFS_UNMOUNT(mp, flags, l);
675 1.324.4.2 pooka if (error) {
676 1.324.4.2 pooka if ((mp->mnt_flag & (MNT_RDONLY | MNT_ASYNC)) == 0)
677 1.324.4.2 pooka (void) vfs_allocate_syncvnode(mp);
678 1.324.4.2 pooka simple_lock(&mountlist_slock);
679 1.324.4.2 pooka mp->mnt_iflag &= ~IMNT_UNMOUNT;
680 1.324.4.2 pooka mp->mnt_unmounter = NULL;
681 1.324.4.2 pooka mp->mnt_flag |= async;
682 1.324.4.2 pooka lockmgr(&mp->mnt_lock, LK_RELEASE | LK_INTERLOCK | LK_REENABLE,
683 1.324.4.2 pooka &mountlist_slock);
684 1.324.4.2 pooka if (used_syncer)
685 1.324.4.2 pooka mutex_exit(&syncer_mutex);
686 1.324.4.2 pooka simple_lock(&mp->mnt_slock);
687 1.324.4.2 pooka while (mp->mnt_wcnt > 0) {
688 1.324.4.2 pooka wakeup(mp);
689 1.324.4.2 pooka ltsleep(&mp->mnt_wcnt, PVFS, "mntwcnt1",
690 1.324.4.2 pooka 0, &mp->mnt_slock);
691 1.324.4.2 pooka }
692 1.324.4.2 pooka simple_unlock(&mp->mnt_slock);
693 1.324.4.2 pooka return (error);
694 1.324.4.2 pooka }
695 1.324.4.2 pooka simple_lock(&mountlist_slock);
696 1.324.4.2 pooka CIRCLEQ_REMOVE(&mountlist, mp, mnt_list);
697 1.324.4.2 pooka if ((coveredvp = mp->mnt_vnodecovered) != NULLVP)
698 1.324.4.2 pooka coveredvp->v_mountedhere = NULL;
699 1.324.4.2 pooka mp->mnt_op->vfs_refcount--;
700 1.324.4.2 pooka if (TAILQ_FIRST(&mp->mnt_vnodelist) != NULL)
701 1.324.4.2 pooka panic("unmount: dangling vnode");
702 1.324.4.2 pooka mp->mnt_iflag |= IMNT_GONE;
703 1.324.4.2 pooka lockmgr(&mp->mnt_lock, LK_RELEASE | LK_INTERLOCK, &mountlist_slock);
704 1.324.4.2 pooka if (coveredvp != NULLVP)
705 1.324.4.2 pooka vrele(coveredvp);
706 1.324.4.2 pooka mount_finispecific(mp);
707 1.324.4.2 pooka if (used_syncer)
708 1.324.4.2 pooka mutex_exit(&syncer_mutex);
709 1.324.4.2 pooka simple_lock(&mp->mnt_slock);
710 1.324.4.2 pooka while (mp->mnt_wcnt > 0) {
711 1.324.4.2 pooka wakeup(mp);
712 1.324.4.2 pooka ltsleep(&mp->mnt_wcnt, PVFS, "mntwcnt2", 0, &mp->mnt_slock);
713 1.324.4.2 pooka }
714 1.324.4.2 pooka simple_unlock(&mp->mnt_slock);
715 1.324.4.2 pooka vfs_hooks_unmount(mp);
716 1.324.4.2 pooka free(mp, M_MOUNT);
717 1.324.4.2 pooka return (0);
718 1.324.4.2 pooka }
719 1.324.4.2 pooka
720 1.324.4.2 pooka /*
721 1.324.4.2 pooka * Sync each mounted filesystem.
722 1.324.4.2 pooka */
723 1.324.4.2 pooka #ifdef DEBUG
724 1.324.4.2 pooka int syncprt = 0;
725 1.324.4.2 pooka struct ctldebug debug0 = { "syncprt", &syncprt };
726 1.324.4.2 pooka #endif
727 1.324.4.2 pooka
728 1.324.4.2 pooka /* ARGSUSED */
729 1.324.4.2 pooka int
730 1.324.4.2 pooka sys_sync(struct lwp *l, void *v, register_t *retval)
731 1.324.4.2 pooka {
732 1.324.4.2 pooka struct mount *mp, *nmp;
733 1.324.4.2 pooka int asyncflag;
734 1.324.4.2 pooka
735 1.324.4.2 pooka if (l == NULL)
736 1.324.4.2 pooka l = &lwp0;
737 1.324.4.2 pooka
738 1.324.4.2 pooka simple_lock(&mountlist_slock);
739 1.324.4.2 pooka for (mp = mountlist.cqh_last; mp != (void *)&mountlist; mp = nmp) {
740 1.324.4.2 pooka if (vfs_busy(mp, LK_NOWAIT, &mountlist_slock)) {
741 1.324.4.2 pooka nmp = mp->mnt_list.cqe_prev;
742 1.324.4.2 pooka continue;
743 1.324.4.2 pooka }
744 1.324.4.2 pooka if ((mp->mnt_flag & MNT_RDONLY) == 0) {
745 1.324.4.2 pooka asyncflag = mp->mnt_flag & MNT_ASYNC;
746 1.324.4.2 pooka mp->mnt_flag &= ~MNT_ASYNC;
747 1.324.4.2 pooka VFS_SYNC(mp, MNT_NOWAIT, l->l_cred, l);
748 1.324.4.2 pooka if (asyncflag)
749 1.324.4.2 pooka mp->mnt_flag |= MNT_ASYNC;
750 1.324.4.2 pooka }
751 1.324.4.2 pooka simple_lock(&mountlist_slock);
752 1.324.4.2 pooka nmp = mp->mnt_list.cqe_prev;
753 1.324.4.2 pooka vfs_unbusy(mp);
754 1.324.4.2 pooka
755 1.324.4.2 pooka }
756 1.324.4.2 pooka simple_unlock(&mountlist_slock);
757 1.324.4.2 pooka #ifdef DEBUG
758 1.324.4.2 pooka if (syncprt)
759 1.324.4.2 pooka vfs_bufstats();
760 1.324.4.2 pooka #endif /* DEBUG */
761 1.324.4.2 pooka return (0);
762 1.324.4.2 pooka }
763 1.324.4.2 pooka
764 1.324.4.2 pooka /*
765 1.324.4.2 pooka * Change filesystem quotas.
766 1.324.4.2 pooka */
767 1.324.4.2 pooka /* ARGSUSED */
768 1.324.4.2 pooka int
769 1.324.4.2 pooka sys_quotactl(struct lwp *l, void *v, register_t *retval)
770 1.324.4.2 pooka {
771 1.324.4.2 pooka struct sys_quotactl_args /* {
772 1.324.4.2 pooka syscallarg(const char *) path;
773 1.324.4.2 pooka syscallarg(int) cmd;
774 1.324.4.2 pooka syscallarg(int) uid;
775 1.324.4.2 pooka syscallarg(void *) arg;
776 1.324.4.2 pooka } */ *uap = v;
777 1.324.4.2 pooka struct mount *mp;
778 1.324.4.2 pooka int error;
779 1.324.4.2 pooka struct nameidata nd;
780 1.324.4.2 pooka
781 1.324.4.2 pooka NDINIT(&nd, LOOKUP, FOLLOW | TRYEMULROOT, UIO_USERSPACE, SCARG(uap, path), l);
782 1.324.4.2 pooka if ((error = namei(&nd)) != 0)
783 1.324.4.2 pooka return (error);
784 1.324.4.2 pooka mp = nd.ni_vp->v_mount;
785 1.324.4.2 pooka vrele(nd.ni_vp);
786 1.324.4.2 pooka error = VFS_QUOTACTL(mp, SCARG(uap, cmd), SCARG(uap, uid),
787 1.324.4.2 pooka SCARG(uap, arg), l);
788 1.324.4.2 pooka return (error);
789 1.324.4.2 pooka }
790 1.324.4.2 pooka
791 1.324.4.2 pooka int
792 1.324.4.2 pooka dostatvfs(struct mount *mp, struct statvfs *sp, struct lwp *l, int flags,
793 1.324.4.2 pooka int root)
794 1.324.4.2 pooka {
795 1.324.4.2 pooka struct cwdinfo *cwdi = l->l_proc->p_cwdi;
796 1.324.4.2 pooka int error = 0;
797 1.324.4.2 pooka
798 1.324.4.2 pooka /*
799 1.324.4.2 pooka * If MNT_NOWAIT or MNT_LAZY is specified, do not
800 1.324.4.2 pooka * refresh the fsstat cache. MNT_WAIT or MNT_LAZY
801 1.324.4.2 pooka * overrides MNT_NOWAIT.
802 1.324.4.2 pooka */
803 1.324.4.2 pooka if (flags == MNT_NOWAIT || flags == MNT_LAZY ||
804 1.324.4.2 pooka (flags != MNT_WAIT && flags != 0)) {
805 1.324.4.2 pooka memcpy(sp, &mp->mnt_stat, sizeof(*sp));
806 1.324.4.2 pooka goto done;
807 1.324.4.2 pooka }
808 1.324.4.2 pooka
809 1.324.4.2 pooka /* Get the filesystem stats now */
810 1.324.4.2 pooka memset(sp, 0, sizeof(*sp));
811 1.324.4.2 pooka if ((error = VFS_STATVFS(mp, sp, l)) != 0) {
812 1.324.4.2 pooka return error;
813 1.324.4.2 pooka }
814 1.324.4.2 pooka
815 1.324.4.2 pooka if (cwdi->cwdi_rdir == NULL)
816 1.324.4.2 pooka (void)memcpy(&mp->mnt_stat, sp, sizeof(mp->mnt_stat));
817 1.324.4.2 pooka done:
818 1.324.4.2 pooka if (cwdi->cwdi_rdir != NULL) {
819 1.324.4.2 pooka size_t len;
820 1.324.4.2 pooka char *bp;
821 1.324.4.2 pooka char *path = PNBUF_GET();
822 1.324.4.2 pooka
823 1.324.4.2 pooka bp = path + MAXPATHLEN;
824 1.324.4.2 pooka *--bp = '\0';
825 1.324.4.2 pooka error = getcwd_common(cwdi->cwdi_rdir, rootvnode, &bp, path,
826 1.324.4.2 pooka MAXPATHLEN / 2, 0, l);
827 1.324.4.2 pooka if (error) {
828 1.324.4.2 pooka PNBUF_PUT(path);
829 1.324.4.2 pooka return error;
830 1.324.4.2 pooka }
831 1.324.4.2 pooka len = strlen(bp);
832 1.324.4.2 pooka /*
833 1.324.4.2 pooka * for mount points that are below our root, we can see
834 1.324.4.2 pooka * them, so we fix up the pathname and return them. The
835 1.324.4.2 pooka * rest we cannot see, so we don't allow viewing the
836 1.324.4.2 pooka * data.
837 1.324.4.2 pooka */
838 1.324.4.2 pooka if (strncmp(bp, sp->f_mntonname, len) == 0) {
839 1.324.4.2 pooka strlcpy(sp->f_mntonname, &sp->f_mntonname[len],
840 1.324.4.2 pooka sizeof(sp->f_mntonname));
841 1.324.4.2 pooka if (sp->f_mntonname[0] == '\0')
842 1.324.4.2 pooka (void)strlcpy(sp->f_mntonname, "/",
843 1.324.4.2 pooka sizeof(sp->f_mntonname));
844 1.324.4.2 pooka } else {
845 1.324.4.2 pooka if (root)
846 1.324.4.2 pooka (void)strlcpy(sp->f_mntonname, "/",
847 1.324.4.2 pooka sizeof(sp->f_mntonname));
848 1.324.4.2 pooka else
849 1.324.4.2 pooka error = EPERM;
850 1.324.4.2 pooka }
851 1.324.4.2 pooka PNBUF_PUT(path);
852 1.324.4.2 pooka }
853 1.324.4.2 pooka sp->f_flag = mp->mnt_flag & MNT_VISFLAGMASK;
854 1.324.4.2 pooka return error;
855 1.324.4.2 pooka }
856 1.324.4.2 pooka
857 1.324.4.2 pooka /*
858 1.324.4.2 pooka * Get filesystem statistics by path.
859 1.324.4.2 pooka */
860 1.324.4.2 pooka int
861 1.324.4.2 pooka do_sys_pstatvfs(struct lwp *l, const char *path, int flags, struct statvfs *sb)
862 1.324.4.2 pooka {
863 1.324.4.2 pooka struct mount *mp;
864 1.324.4.2 pooka int error;
865 1.324.4.2 pooka struct nameidata nd;
866 1.324.4.2 pooka
867 1.324.4.2 pooka NDINIT(&nd, LOOKUP, FOLLOW | TRYEMULROOT, UIO_USERSPACE, path, l);
868 1.324.4.2 pooka if ((error = namei(&nd)) != 0)
869 1.324.4.2 pooka return error;
870 1.324.4.2 pooka mp = nd.ni_vp->v_mount;
871 1.324.4.2 pooka error = dostatvfs(mp, sb, l, flags, 1);
872 1.324.4.2 pooka vrele(nd.ni_vp);
873 1.324.4.2 pooka return error;
874 1.324.4.2 pooka }
875 1.324.4.2 pooka
876 1.324.4.2 pooka /* ARGSUSED */
877 1.324.4.2 pooka int
878 1.324.4.2 pooka sys_statvfs1(struct lwp *l, void *v, register_t *retval)
879 1.324.4.2 pooka {
880 1.324.4.2 pooka struct sys_statvfs1_args /* {
881 1.324.4.2 pooka syscallarg(const char *) path;
882 1.324.4.2 pooka syscallarg(struct statvfs *) buf;
883 1.324.4.2 pooka syscallarg(int) flags;
884 1.324.4.2 pooka } */ *uap = v;
885 1.324.4.2 pooka struct statvfs *sb;
886 1.324.4.2 pooka int error;
887 1.324.4.2 pooka
888 1.324.4.2 pooka sb = STATVFSBUF_GET();
889 1.324.4.2 pooka error = do_sys_pstatvfs(l, SCARG(uap, path), SCARG(uap, flags), sb);
890 1.324.4.2 pooka if (error == 0)
891 1.324.4.2 pooka error = copyout(sb, SCARG(uap, buf), sizeof(*sb));
892 1.324.4.2 pooka STATVFSBUF_PUT(sb);
893 1.324.4.2 pooka return error;
894 1.324.4.2 pooka }
895 1.324.4.2 pooka
896 1.324.4.2 pooka /*
897 1.324.4.2 pooka * Get filesystem statistics by fd.
898 1.324.4.2 pooka */
899 1.324.4.2 pooka int
900 1.324.4.2 pooka do_sys_fstatvfs(struct lwp *l, int fd, int flags, struct statvfs *sb)
901 1.324.4.2 pooka {
902 1.324.4.2 pooka struct proc *p = l->l_proc;
903 1.324.4.2 pooka struct file *fp;
904 1.324.4.2 pooka struct mount *mp;
905 1.324.4.2 pooka int error;
906 1.324.4.2 pooka
907 1.324.4.2 pooka /* getvnode() will use the descriptor for us */
908 1.324.4.2 pooka if ((error = getvnode(p->p_fd, fd, &fp)) != 0)
909 1.324.4.2 pooka return (error);
910 1.324.4.2 pooka mp = ((struct vnode *)fp->f_data)->v_mount;
911 1.324.4.2 pooka error = dostatvfs(mp, sb, l, flags, 1);
912 1.324.4.2 pooka FILE_UNUSE(fp, l);
913 1.324.4.2 pooka return error;
914 1.324.4.2 pooka }
915 1.324.4.2 pooka
916 1.324.4.2 pooka /* ARGSUSED */
917 1.324.4.2 pooka int
918 1.324.4.2 pooka sys_fstatvfs1(struct lwp *l, void *v, register_t *retval)
919 1.324.4.2 pooka {
920 1.324.4.2 pooka struct sys_fstatvfs1_args /* {
921 1.324.4.2 pooka syscallarg(int) fd;
922 1.324.4.2 pooka syscallarg(struct statvfs *) buf;
923 1.324.4.2 pooka syscallarg(int) flags;
924 1.324.4.2 pooka } */ *uap = v;
925 1.324.4.2 pooka struct statvfs *sb;
926 1.324.4.2 pooka int error;
927 1.324.4.2 pooka
928 1.324.4.2 pooka sb = STATVFSBUF_GET();
929 1.324.4.2 pooka error = do_sys_fstatvfs(l, SCARG(uap, fd), SCARG(uap, flags), sb);
930 1.324.4.2 pooka if (error == 0)
931 1.324.4.2 pooka error = copyout(sb, SCARG(uap, buf), sizeof(*sb));
932 1.324.4.2 pooka STATVFSBUF_PUT(sb);
933 1.324.4.2 pooka return error;
934 1.324.4.2 pooka }
935 1.324.4.2 pooka
936 1.324.4.2 pooka
937 1.324.4.2 pooka /*
938 1.324.4.2 pooka * Get statistics on all filesystems.
939 1.324.4.2 pooka */
940 1.324.4.2 pooka int
941 1.324.4.2 pooka do_sys_getvfsstat(struct lwp *l, void *sfsp, size_t bufsize, int flags,
942 1.324.4.2 pooka int (*copyfn)(const void *, void *, size_t), size_t entry_sz,
943 1.324.4.2 pooka register_t *retval)
944 1.324.4.2 pooka {
945 1.324.4.2 pooka int root = 0;
946 1.324.4.2 pooka struct proc *p = l->l_proc;
947 1.324.4.2 pooka struct mount *mp, *nmp;
948 1.324.4.2 pooka struct statvfs *sb;
949 1.324.4.2 pooka size_t count, maxcount;
950 1.324.4.2 pooka int error = 0;
951 1.324.4.2 pooka
952 1.324.4.2 pooka sb = STATVFSBUF_GET();
953 1.324.4.2 pooka maxcount = bufsize / entry_sz;
954 1.324.4.2 pooka simple_lock(&mountlist_slock);
955 1.324.4.2 pooka count = 0;
956 1.324.4.2 pooka for (mp = CIRCLEQ_FIRST(&mountlist); mp != (void *)&mountlist;
957 1.324.4.2 pooka mp = nmp) {
958 1.324.4.2 pooka if (vfs_busy(mp, LK_NOWAIT, &mountlist_slock)) {
959 1.324.4.2 pooka nmp = CIRCLEQ_NEXT(mp, mnt_list);
960 1.324.4.2 pooka continue;
961 1.324.4.2 pooka }
962 1.324.4.2 pooka if (sfsp && count < maxcount) {
963 1.324.4.2 pooka error = dostatvfs(mp, sb, l, flags, 0);
964 1.324.4.2 pooka if (error) {
965 1.324.4.2 pooka simple_lock(&mountlist_slock);
966 1.324.4.2 pooka nmp = CIRCLEQ_NEXT(mp, mnt_list);
967 1.324.4.2 pooka vfs_unbusy(mp);
968 1.324.4.2 pooka continue;
969 1.324.4.2 pooka }
970 1.324.4.2 pooka error = copyfn(sb, sfsp, entry_sz);
971 1.324.4.2 pooka if (error) {
972 1.324.4.2 pooka vfs_unbusy(mp);
973 1.324.4.2 pooka goto out;
974 1.324.4.2 pooka }
975 1.324.4.2 pooka sfsp = (char *)sfsp + entry_sz;
976 1.324.4.2 pooka root |= strcmp(sb->f_mntonname, "/") == 0;
977 1.324.4.2 pooka }
978 1.324.4.2 pooka count++;
979 1.324.4.2 pooka simple_lock(&mountlist_slock);
980 1.324.4.2 pooka nmp = CIRCLEQ_NEXT(mp, mnt_list);
981 1.324.4.2 pooka vfs_unbusy(mp);
982 1.324.4.2 pooka }
983 1.324.4.2 pooka simple_unlock(&mountlist_slock);
984 1.324.4.2 pooka if (root == 0 && p->p_cwdi->cwdi_rdir) {
985 1.324.4.2 pooka /*
986 1.324.4.2 pooka * fake a root entry
987 1.324.4.2 pooka */
988 1.324.4.2 pooka error = dostatvfs(p->p_cwdi->cwdi_rdir->v_mount, sb, l, flags, 1);
989 1.324.4.2 pooka if (error != 0)
990 1.324.4.2 pooka goto out;
991 1.324.4.2 pooka if (sfsp)
992 1.324.4.2 pooka error = copyfn(sb, sfsp, entry_sz);
993 1.324.4.2 pooka count++;
994 1.324.4.2 pooka }
995 1.324.4.2 pooka if (sfsp && count > maxcount)
996 1.324.4.2 pooka *retval = maxcount;
997 1.324.4.2 pooka else
998 1.324.4.2 pooka *retval = count;
999 1.324.4.2 pooka out:
1000 1.324.4.2 pooka STATVFSBUF_PUT(sb);
1001 1.324.4.2 pooka return error;
1002 1.324.4.2 pooka }
1003 1.324.4.2 pooka
1004 1.324.4.2 pooka int
1005 1.324.4.2 pooka sys_getvfsstat(struct lwp *l, void *v, register_t *retval)
1006 1.324.4.2 pooka {
1007 1.324.4.2 pooka struct sys_getvfsstat_args /* {
1008 1.324.4.2 pooka syscallarg(struct statvfs *) buf;
1009 1.324.4.2 pooka syscallarg(size_t) bufsize;
1010 1.324.4.2 pooka syscallarg(int) flags;
1011 1.324.4.2 pooka } */ *uap = v;
1012 1.324.4.2 pooka
1013 1.324.4.2 pooka return do_sys_getvfsstat(l, SCARG(uap, buf), SCARG(uap, bufsize),
1014 1.324.4.2 pooka SCARG(uap, flags), copyout, sizeof (struct statvfs), retval);
1015 1.324.4.2 pooka }
1016 1.324.4.2 pooka
1017 1.324.4.2 pooka /*
1018 1.324.4.2 pooka * Change current working directory to a given file descriptor.
1019 1.324.4.2 pooka */
1020 1.324.4.2 pooka /* ARGSUSED */
1021 1.324.4.2 pooka int
1022 1.324.4.2 pooka sys_fchdir(struct lwp *l, void *v, register_t *retval)
1023 1.324.4.2 pooka {
1024 1.324.4.2 pooka struct sys_fchdir_args /* {
1025 1.324.4.2 pooka syscallarg(int) fd;
1026 1.324.4.2 pooka } */ *uap = v;
1027 1.324.4.2 pooka struct proc *p = l->l_proc;
1028 1.324.4.2 pooka struct filedesc *fdp = p->p_fd;
1029 1.324.4.2 pooka struct cwdinfo *cwdi = p->p_cwdi;
1030 1.324.4.2 pooka struct vnode *vp, *tdp;
1031 1.324.4.2 pooka struct mount *mp;
1032 1.324.4.2 pooka struct file *fp;
1033 1.324.4.2 pooka int error;
1034 1.324.4.2 pooka
1035 1.324.4.2 pooka /* getvnode() will use the descriptor for us */
1036 1.324.4.2 pooka if ((error = getvnode(fdp, SCARG(uap, fd), &fp)) != 0)
1037 1.324.4.2 pooka return (error);
1038 1.324.4.2 pooka vp = (struct vnode *)fp->f_data;
1039 1.324.4.2 pooka
1040 1.324.4.2 pooka VREF(vp);
1041 1.324.4.2 pooka vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
1042 1.324.4.2 pooka if (vp->v_type != VDIR)
1043 1.324.4.2 pooka error = ENOTDIR;
1044 1.324.4.2 pooka else
1045 1.324.4.2 pooka error = VOP_ACCESS(vp, VEXEC, l->l_cred, l);
1046 1.324.4.2 pooka if (error) {
1047 1.324.4.2 pooka vput(vp);
1048 1.324.4.2 pooka goto out;
1049 1.324.4.2 pooka }
1050 1.324.4.2 pooka while ((mp = vp->v_mountedhere) != NULL) {
1051 1.324.4.2 pooka if (vfs_busy(mp, 0, 0))
1052 1.324.4.2 pooka continue;
1053 1.324.4.2 pooka
1054 1.324.4.2 pooka vput(vp);
1055 1.324.4.2 pooka error = VFS_ROOT(mp, &tdp);
1056 1.324.4.2 pooka vfs_unbusy(mp);
1057 1.324.4.2 pooka if (error)
1058 1.324.4.2 pooka goto out;
1059 1.324.4.2 pooka vp = tdp;
1060 1.324.4.2 pooka }
1061 1.324.4.2 pooka VOP_UNLOCK(vp, 0);
1062 1.324.4.2 pooka
1063 1.324.4.2 pooka /*
1064 1.324.4.2 pooka * Disallow changing to a directory not under the process's
1065 1.324.4.2 pooka * current root directory (if there is one).
1066 1.324.4.2 pooka */
1067 1.324.4.2 pooka if (cwdi->cwdi_rdir && !vn_isunder(vp, NULL, l)) {
1068 1.324.4.2 pooka vrele(vp);
1069 1.324.4.2 pooka error = EPERM; /* operation not permitted */
1070 1.324.4.2 pooka goto out;
1071 1.324.4.2 pooka }
1072 1.324.4.2 pooka
1073 1.324.4.2 pooka vrele(cwdi->cwdi_cdir);
1074 1.324.4.2 pooka cwdi->cwdi_cdir = vp;
1075 1.324.4.2 pooka out:
1076 1.324.4.2 pooka FILE_UNUSE(fp, l);
1077 1.324.4.2 pooka return (error);
1078 1.324.4.2 pooka }
1079 1.324.4.2 pooka
1080 1.324.4.2 pooka /*
1081 1.324.4.2 pooka * Change this process's notion of the root directory to a given file
1082 1.324.4.2 pooka * descriptor.
1083 1.324.4.2 pooka */
1084 1.324.4.2 pooka int
1085 1.324.4.2 pooka sys_fchroot(struct lwp *l, void *v, register_t *retval)
1086 1.324.4.2 pooka {
1087 1.324.4.2 pooka struct sys_fchroot_args *uap = v;
1088 1.324.4.2 pooka struct proc *p = l->l_proc;
1089 1.324.4.2 pooka struct filedesc *fdp = p->p_fd;
1090 1.324.4.2 pooka struct cwdinfo *cwdi = p->p_cwdi;
1091 1.324.4.2 pooka struct vnode *vp;
1092 1.324.4.2 pooka struct file *fp;
1093 1.324.4.2 pooka int error;
1094 1.324.4.2 pooka
1095 1.324.4.2 pooka if ((error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_CHROOT,
1096 1.324.4.2 pooka KAUTH_REQ_SYSTEM_CHROOT_FCHROOT, NULL, NULL, NULL)) != 0)
1097 1.324.4.2 pooka return error;
1098 1.324.4.2 pooka /* getvnode() will use the descriptor for us */
1099 1.324.4.2 pooka if ((error = getvnode(fdp, SCARG(uap, fd), &fp)) != 0)
1100 1.324.4.2 pooka return error;
1101 1.324.4.2 pooka vp = (struct vnode *) fp->f_data;
1102 1.324.4.2 pooka vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
1103 1.324.4.2 pooka if (vp->v_type != VDIR)
1104 1.324.4.2 pooka error = ENOTDIR;
1105 1.324.4.2 pooka else
1106 1.324.4.2 pooka error = VOP_ACCESS(vp, VEXEC, l->l_cred, l);
1107 1.324.4.2 pooka VOP_UNLOCK(vp, 0);
1108 1.324.4.2 pooka if (error)
1109 1.324.4.2 pooka goto out;
1110 1.324.4.2 pooka VREF(vp);
1111 1.324.4.2 pooka
1112 1.324.4.2 pooka /*
1113 1.324.4.2 pooka * Prevent escaping from chroot by putting the root under
1114 1.324.4.2 pooka * the working directory. Silently chdir to / if we aren't
1115 1.324.4.2 pooka * already there.
1116 1.324.4.2 pooka */
1117 1.324.4.2 pooka if (!vn_isunder(cwdi->cwdi_cdir, vp, l)) {
1118 1.324.4.2 pooka /*
1119 1.324.4.2 pooka * XXX would be more failsafe to change directory to a
1120 1.324.4.2 pooka * deadfs node here instead
1121 1.324.4.2 pooka */
1122 1.324.4.2 pooka vrele(cwdi->cwdi_cdir);
1123 1.324.4.2 pooka VREF(vp);
1124 1.324.4.2 pooka cwdi->cwdi_cdir = vp;
1125 1.324.4.2 pooka }
1126 1.324.4.2 pooka
1127 1.324.4.2 pooka if (cwdi->cwdi_rdir != NULL)
1128 1.324.4.2 pooka vrele(cwdi->cwdi_rdir);
1129 1.324.4.2 pooka cwdi->cwdi_rdir = vp;
1130 1.324.4.2 pooka out:
1131 1.324.4.2 pooka FILE_UNUSE(fp, l);
1132 1.324.4.2 pooka return (error);
1133 1.324.4.2 pooka }
1134 1.324.4.2 pooka
1135 1.324.4.2 pooka /*
1136 1.324.4.2 pooka * Change current working directory (``.'').
1137 1.324.4.2 pooka */
1138 1.324.4.2 pooka /* ARGSUSED */
1139 1.324.4.2 pooka int
1140 1.324.4.2 pooka sys_chdir(struct lwp *l, void *v, register_t *retval)
1141 1.324.4.2 pooka {
1142 1.324.4.2 pooka struct sys_chdir_args /* {
1143 1.324.4.2 pooka syscallarg(const char *) path;
1144 1.324.4.2 pooka } */ *uap = v;
1145 1.324.4.2 pooka struct proc *p = l->l_proc;
1146 1.324.4.2 pooka struct cwdinfo *cwdi = p->p_cwdi;
1147 1.324.4.2 pooka int error;
1148 1.324.4.2 pooka struct nameidata nd;
1149 1.324.4.2 pooka
1150 1.324.4.2 pooka NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | TRYEMULROOT, UIO_USERSPACE,
1151 1.324.4.2 pooka SCARG(uap, path), l);
1152 1.324.4.2 pooka if ((error = change_dir(&nd, l)) != 0)
1153 1.324.4.2 pooka return (error);
1154 1.324.4.2 pooka vrele(cwdi->cwdi_cdir);
1155 1.324.4.2 pooka cwdi->cwdi_cdir = nd.ni_vp;
1156 1.324.4.2 pooka return (0);
1157 1.324.4.2 pooka }
1158 1.324.4.2 pooka
1159 1.324.4.2 pooka /*
1160 1.324.4.2 pooka * Change notion of root (``/'') directory.
1161 1.324.4.2 pooka */
1162 1.324.4.2 pooka /* ARGSUSED */
1163 1.324.4.2 pooka int
1164 1.324.4.2 pooka sys_chroot(struct lwp *l, void *v, register_t *retval)
1165 1.324.4.2 pooka {
1166 1.324.4.2 pooka struct sys_chroot_args /* {
1167 1.324.4.2 pooka syscallarg(const char *) path;
1168 1.324.4.2 pooka } */ *uap = v;
1169 1.324.4.2 pooka struct proc *p = l->l_proc;
1170 1.324.4.2 pooka struct cwdinfo *cwdi = p->p_cwdi;
1171 1.324.4.2 pooka struct vnode *vp;
1172 1.324.4.2 pooka int error;
1173 1.324.4.2 pooka struct nameidata nd;
1174 1.324.4.2 pooka
1175 1.324.4.2 pooka if ((error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_CHROOT,
1176 1.324.4.2 pooka KAUTH_REQ_SYSTEM_CHROOT_CHROOT, NULL, NULL, NULL)) != 0)
1177 1.324.4.2 pooka return (error);
1178 1.324.4.2 pooka NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | TRYEMULROOT, UIO_USERSPACE,
1179 1.324.4.2 pooka SCARG(uap, path), l);
1180 1.324.4.2 pooka if ((error = change_dir(&nd, l)) != 0)
1181 1.324.4.2 pooka return (error);
1182 1.324.4.2 pooka if (cwdi->cwdi_rdir != NULL)
1183 1.324.4.2 pooka vrele(cwdi->cwdi_rdir);
1184 1.324.4.2 pooka vp = nd.ni_vp;
1185 1.324.4.2 pooka cwdi->cwdi_rdir = vp;
1186 1.324.4.2 pooka
1187 1.324.4.2 pooka /*
1188 1.324.4.2 pooka * Prevent escaping from chroot by putting the root under
1189 1.324.4.2 pooka * the working directory. Silently chdir to / if we aren't
1190 1.324.4.2 pooka * already there.
1191 1.324.4.2 pooka */
1192 1.324.4.2 pooka if (!vn_isunder(cwdi->cwdi_cdir, vp, l)) {
1193 1.324.4.2 pooka /*
1194 1.324.4.2 pooka * XXX would be more failsafe to change directory to a
1195 1.324.4.2 pooka * deadfs node here instead
1196 1.324.4.2 pooka */
1197 1.324.4.2 pooka vrele(cwdi->cwdi_cdir);
1198 1.324.4.2 pooka VREF(vp);
1199 1.324.4.2 pooka cwdi->cwdi_cdir = vp;
1200 1.324.4.2 pooka }
1201 1.324.4.2 pooka
1202 1.324.4.2 pooka return (0);
1203 1.324.4.2 pooka }
1204 1.324.4.2 pooka
1205 1.324.4.2 pooka /*
1206 1.324.4.2 pooka * Common routine for chroot and chdir.
1207 1.324.4.2 pooka */
1208 1.324.4.2 pooka static int
1209 1.324.4.2 pooka change_dir(struct nameidata *ndp, struct lwp *l)
1210 1.324.4.2 pooka {
1211 1.324.4.2 pooka struct vnode *vp;
1212 1.324.4.2 pooka int error;
1213 1.324.4.2 pooka
1214 1.324.4.2 pooka if ((error = namei(ndp)) != 0)
1215 1.324.4.2 pooka return (error);
1216 1.324.4.2 pooka vp = ndp->ni_vp;
1217 1.324.4.2 pooka if (vp->v_type != VDIR)
1218 1.324.4.2 pooka error = ENOTDIR;
1219 1.324.4.2 pooka else
1220 1.324.4.2 pooka error = VOP_ACCESS(vp, VEXEC, l->l_cred, l);
1221 1.324.4.2 pooka
1222 1.324.4.2 pooka if (error)
1223 1.324.4.2 pooka vput(vp);
1224 1.324.4.2 pooka else
1225 1.324.4.2 pooka VOP_UNLOCK(vp, 0);
1226 1.324.4.2 pooka return (error);
1227 1.324.4.2 pooka }
1228 1.324.4.2 pooka
1229 1.324.4.2 pooka /*
1230 1.324.4.2 pooka * Check permissions, allocate an open file structure,
1231 1.324.4.2 pooka * and call the device open routine if any.
1232 1.324.4.2 pooka */
1233 1.324.4.2 pooka int
1234 1.324.4.2 pooka sys_open(struct lwp *l, void *v, register_t *retval)
1235 1.324.4.2 pooka {
1236 1.324.4.2 pooka struct sys_open_args /* {
1237 1.324.4.2 pooka syscallarg(const char *) path;
1238 1.324.4.2 pooka syscallarg(int) flags;
1239 1.324.4.2 pooka syscallarg(int) mode;
1240 1.324.4.2 pooka } */ *uap = v;
1241 1.324.4.2 pooka struct proc *p = l->l_proc;
1242 1.324.4.2 pooka struct cwdinfo *cwdi = p->p_cwdi;
1243 1.324.4.2 pooka struct filedesc *fdp = p->p_fd;
1244 1.324.4.2 pooka struct file *fp;
1245 1.324.4.2 pooka struct vnode *vp;
1246 1.324.4.2 pooka int flags, cmode;
1247 1.324.4.2 pooka int type, indx, error;
1248 1.324.4.2 pooka struct flock lf;
1249 1.324.4.2 pooka struct nameidata nd;
1250 1.324.4.2 pooka
1251 1.324.4.2 pooka flags = FFLAGS(SCARG(uap, flags));
1252 1.324.4.2 pooka if ((flags & (FREAD | FWRITE)) == 0)
1253 1.324.4.2 pooka return (EINVAL);
1254 1.324.4.2 pooka /* falloc() will use the file descriptor for us */
1255 1.324.4.2 pooka if ((error = falloc(l, &fp, &indx)) != 0)
1256 1.324.4.2 pooka return (error);
1257 1.324.4.2 pooka cmode = ((SCARG(uap, mode) &~ cwdi->cwdi_cmask) & ALLPERMS) &~ S_ISTXT;
1258 1.324.4.2 pooka NDINIT(&nd, LOOKUP, FOLLOW | TRYEMULROOT, UIO_USERSPACE, SCARG(uap, path), l);
1259 1.324.4.2 pooka l->l_dupfd = -indx - 1; /* XXX check for fdopen */
1260 1.324.4.2 pooka if ((error = vn_open(&nd, flags, cmode)) != 0) {
1261 1.324.4.2 pooka FILE_UNUSE(fp, l);
1262 1.324.4.2 pooka fdp->fd_ofiles[indx] = NULL;
1263 1.324.4.2 pooka ffree(fp);
1264 1.324.4.2 pooka if ((error == EDUPFD || error == EMOVEFD) &&
1265 1.324.4.2 pooka l->l_dupfd >= 0 && /* XXX from fdopen */
1266 1.324.4.2 pooka (error =
1267 1.324.4.2 pooka dupfdopen(l, indx, l->l_dupfd, flags, error)) == 0) {
1268 1.324.4.2 pooka *retval = indx;
1269 1.324.4.2 pooka return (0);
1270 1.324.4.2 pooka }
1271 1.324.4.2 pooka if (error == ERESTART)
1272 1.324.4.2 pooka error = EINTR;
1273 1.324.4.2 pooka fdremove(fdp, indx);
1274 1.324.4.2 pooka return (error);
1275 1.324.4.2 pooka }
1276 1.324.4.2 pooka l->l_dupfd = 0;
1277 1.324.4.2 pooka vp = nd.ni_vp;
1278 1.324.4.2 pooka fp->f_flag = flags & FMASK;
1279 1.324.4.2 pooka fp->f_type = DTYPE_VNODE;
1280 1.324.4.2 pooka fp->f_ops = &vnops;
1281 1.324.4.2 pooka fp->f_data = vp;
1282 1.324.4.2 pooka if (flags & (O_EXLOCK | O_SHLOCK)) {
1283 1.324.4.2 pooka lf.l_whence = SEEK_SET;
1284 1.324.4.2 pooka lf.l_start = 0;
1285 1.324.4.2 pooka lf.l_len = 0;
1286 1.324.4.2 pooka if (flags & O_EXLOCK)
1287 1.324.4.2 pooka lf.l_type = F_WRLCK;
1288 1.324.4.2 pooka else
1289 1.324.4.2 pooka lf.l_type = F_RDLCK;
1290 1.324.4.2 pooka type = F_FLOCK;
1291 1.324.4.2 pooka if ((flags & FNONBLOCK) == 0)
1292 1.324.4.2 pooka type |= F_WAIT;
1293 1.324.4.2 pooka VOP_UNLOCK(vp, 0);
1294 1.324.4.2 pooka error = VOP_ADVLOCK(vp, fp, F_SETLK, &lf, type);
1295 1.324.4.2 pooka if (error) {
1296 1.324.4.2 pooka (void) vn_close(vp, fp->f_flag, fp->f_cred, l);
1297 1.324.4.2 pooka FILE_UNUSE(fp, l);
1298 1.324.4.2 pooka ffree(fp);
1299 1.324.4.2 pooka fdremove(fdp, indx);
1300 1.324.4.2 pooka return (error);
1301 1.324.4.2 pooka }
1302 1.324.4.2 pooka vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
1303 1.324.4.2 pooka fp->f_flag |= FHASLOCK;
1304 1.324.4.2 pooka }
1305 1.324.4.2 pooka VOP_UNLOCK(vp, 0);
1306 1.324.4.2 pooka *retval = indx;
1307 1.324.4.2 pooka FILE_SET_MATURE(fp);
1308 1.324.4.2 pooka FILE_UNUSE(fp, l);
1309 1.324.4.2 pooka return (0);
1310 1.324.4.2 pooka }
1311 1.324.4.2 pooka
1312 1.324.4.2 pooka static void
1313 1.324.4.2 pooka vfs__fhfree(fhandle_t *fhp)
1314 1.324.4.2 pooka {
1315 1.324.4.2 pooka size_t fhsize;
1316 1.324.4.2 pooka
1317 1.324.4.2 pooka if (fhp == NULL) {
1318 1.324.4.2 pooka return;
1319 1.324.4.2 pooka }
1320 1.324.4.2 pooka fhsize = FHANDLE_SIZE(fhp);
1321 1.324.4.2 pooka kmem_free(fhp, fhsize);
1322 1.324.4.2 pooka }
1323 1.324.4.2 pooka
1324 1.324.4.2 pooka /*
1325 1.324.4.2 pooka * vfs_composefh: compose a filehandle.
1326 1.324.4.2 pooka */
1327 1.324.4.2 pooka
1328 1.324.4.2 pooka int
1329 1.324.4.2 pooka vfs_composefh(struct vnode *vp, fhandle_t *fhp, size_t *fh_size)
1330 1.324.4.2 pooka {
1331 1.324.4.2 pooka struct mount *mp;
1332 1.324.4.2 pooka struct fid *fidp;
1333 1.324.4.2 pooka int error;
1334 1.324.4.2 pooka size_t needfhsize;
1335 1.324.4.2 pooka size_t fidsize;
1336 1.324.4.2 pooka
1337 1.324.4.2 pooka mp = vp->v_mount;
1338 1.324.4.2 pooka fidp = NULL;
1339 1.324.4.2 pooka if (*fh_size < FHANDLE_SIZE_MIN) {
1340 1.324.4.2 pooka fidsize = 0;
1341 1.324.4.2 pooka } else {
1342 1.324.4.2 pooka fidsize = *fh_size - offsetof(fhandle_t, fh_fid);
1343 1.324.4.2 pooka if (fhp != NULL) {
1344 1.324.4.2 pooka memset(fhp, 0, *fh_size);
1345 1.324.4.2 pooka fhp->fh_fsid = mp->mnt_stat.f_fsidx;
1346 1.324.4.2 pooka fidp = &fhp->fh_fid;
1347 1.324.4.2 pooka }
1348 1.324.4.2 pooka }
1349 1.324.4.2 pooka error = VFS_VPTOFH(vp, fidp, &fidsize);
1350 1.324.4.2 pooka needfhsize = FHANDLE_SIZE_FROM_FILEID_SIZE(fidsize);
1351 1.324.4.2 pooka if (error == 0 && *fh_size < needfhsize) {
1352 1.324.4.2 pooka error = E2BIG;
1353 1.324.4.2 pooka }
1354 1.324.4.2 pooka *fh_size = needfhsize;
1355 1.324.4.2 pooka return error;
1356 1.324.4.2 pooka }
1357 1.324.4.2 pooka
1358 1.324.4.2 pooka int
1359 1.324.4.2 pooka vfs_composefh_alloc(struct vnode *vp, fhandle_t **fhpp)
1360 1.324.4.2 pooka {
1361 1.324.4.2 pooka struct mount *mp;
1362 1.324.4.2 pooka fhandle_t *fhp;
1363 1.324.4.2 pooka size_t fhsize;
1364 1.324.4.2 pooka size_t fidsize;
1365 1.324.4.2 pooka int error;
1366 1.324.4.2 pooka
1367 1.324.4.2 pooka *fhpp = NULL;
1368 1.324.4.2 pooka mp = vp->v_mount;
1369 1.324.4.2 pooka fidsize = 0;
1370 1.324.4.2 pooka error = VFS_VPTOFH(vp, NULL, &fidsize);
1371 1.324.4.2 pooka KASSERT(error != 0);
1372 1.324.4.2 pooka if (error != E2BIG) {
1373 1.324.4.2 pooka goto out;
1374 1.324.4.2 pooka }
1375 1.324.4.2 pooka fhsize = FHANDLE_SIZE_FROM_FILEID_SIZE(fidsize);
1376 1.324.4.2 pooka fhp = kmem_zalloc(fhsize, KM_SLEEP);
1377 1.324.4.2 pooka if (fhp == NULL) {
1378 1.324.4.2 pooka error = ENOMEM;
1379 1.324.4.2 pooka goto out;
1380 1.324.4.2 pooka }
1381 1.324.4.2 pooka fhp->fh_fsid = mp->mnt_stat.f_fsidx;
1382 1.324.4.2 pooka error = VFS_VPTOFH(vp, &fhp->fh_fid, &fidsize);
1383 1.324.4.2 pooka if (error == 0) {
1384 1.324.4.2 pooka KASSERT((FHANDLE_SIZE(fhp) == fhsize &&
1385 1.324.4.2 pooka FHANDLE_FILEID(fhp)->fid_len == fidsize));
1386 1.324.4.2 pooka *fhpp = fhp;
1387 1.324.4.2 pooka } else {
1388 1.324.4.2 pooka kmem_free(fhp, fhsize);
1389 1.324.4.2 pooka }
1390 1.324.4.2 pooka out:
1391 1.324.4.2 pooka return error;
1392 1.324.4.2 pooka }
1393 1.324.4.2 pooka
1394 1.324.4.2 pooka void
1395 1.324.4.2 pooka vfs_composefh_free(fhandle_t *fhp)
1396 1.324.4.2 pooka {
1397 1.324.4.2 pooka
1398 1.324.4.2 pooka vfs__fhfree(fhp);
1399 1.324.4.2 pooka }
1400 1.324.4.2 pooka
1401 1.324.4.2 pooka /*
1402 1.324.4.2 pooka * vfs_fhtovp: lookup a vnode by a filehandle.
1403 1.324.4.2 pooka */
1404 1.324.4.2 pooka
1405 1.324.4.2 pooka int
1406 1.324.4.2 pooka vfs_fhtovp(fhandle_t *fhp, struct vnode **vpp)
1407 1.324.4.2 pooka {
1408 1.324.4.2 pooka struct mount *mp;
1409 1.324.4.2 pooka int error;
1410 1.324.4.2 pooka
1411 1.324.4.2 pooka *vpp = NULL;
1412 1.324.4.2 pooka mp = vfs_getvfs(FHANDLE_FSID(fhp));
1413 1.324.4.2 pooka if (mp == NULL) {
1414 1.324.4.2 pooka error = ESTALE;
1415 1.324.4.2 pooka goto out;
1416 1.324.4.2 pooka }
1417 1.324.4.2 pooka if (mp->mnt_op->vfs_fhtovp == NULL) {
1418 1.324.4.2 pooka error = EOPNOTSUPP;
1419 1.324.4.2 pooka goto out;
1420 1.324.4.2 pooka }
1421 1.324.4.2 pooka error = VFS_FHTOVP(mp, FHANDLE_FILEID(fhp), vpp);
1422 1.324.4.2 pooka out:
1423 1.324.4.2 pooka return error;
1424 1.324.4.2 pooka }
1425 1.324.4.2 pooka
1426 1.324.4.2 pooka /*
1427 1.324.4.2 pooka * vfs_copyinfh_alloc: allocate and copyin a filehandle, given
1428 1.324.4.2 pooka * the needed size.
1429 1.324.4.2 pooka */
1430 1.324.4.2 pooka
1431 1.324.4.2 pooka int
1432 1.324.4.2 pooka vfs_copyinfh_alloc(const void *ufhp, size_t fhsize, fhandle_t **fhpp)
1433 1.324.4.2 pooka {
1434 1.324.4.2 pooka fhandle_t *fhp;
1435 1.324.4.2 pooka int error;
1436 1.324.4.2 pooka
1437 1.324.4.2 pooka *fhpp = NULL;
1438 1.324.4.2 pooka if (fhsize > FHANDLE_SIZE_MAX) {
1439 1.324.4.2 pooka return EINVAL;
1440 1.324.4.2 pooka }
1441 1.324.4.2 pooka if (fhsize < FHANDLE_SIZE_MIN) {
1442 1.324.4.2 pooka return EINVAL;
1443 1.324.4.2 pooka }
1444 1.324.4.2 pooka again:
1445 1.324.4.2 pooka fhp = kmem_alloc(fhsize, KM_SLEEP);
1446 1.324.4.2 pooka if (fhp == NULL) {
1447 1.324.4.2 pooka return ENOMEM;
1448 1.324.4.2 pooka }
1449 1.324.4.2 pooka error = copyin(ufhp, fhp, fhsize);
1450 1.324.4.2 pooka if (error == 0) {
1451 1.324.4.2 pooka /* XXX this check shouldn't be here */
1452 1.324.4.2 pooka if (FHANDLE_SIZE(fhp) == fhsize) {
1453 1.324.4.2 pooka *fhpp = fhp;
1454 1.324.4.2 pooka return 0;
1455 1.324.4.2 pooka } else if (fhsize == NFSX_V2FH && FHANDLE_SIZE(fhp) < fhsize) {
1456 1.324.4.2 pooka /*
1457 1.324.4.2 pooka * a kludge for nfsv2 padded handles.
1458 1.324.4.2 pooka */
1459 1.324.4.2 pooka size_t sz;
1460 1.324.4.2 pooka
1461 1.324.4.2 pooka sz = FHANDLE_SIZE(fhp);
1462 1.324.4.2 pooka kmem_free(fhp, fhsize);
1463 1.324.4.2 pooka fhsize = sz;
1464 1.324.4.2 pooka goto again;
1465 1.324.4.2 pooka } else {
1466 1.324.4.2 pooka /*
1467 1.324.4.2 pooka * userland told us wrong size.
1468 1.324.4.2 pooka */
1469 1.324.4.2 pooka error = EINVAL;
1470 1.324.4.2 pooka }
1471 1.324.4.2 pooka }
1472 1.324.4.2 pooka kmem_free(fhp, fhsize);
1473 1.324.4.2 pooka return error;
1474 1.324.4.2 pooka }
1475 1.324.4.2 pooka
1476 1.324.4.2 pooka void
1477 1.324.4.2 pooka vfs_copyinfh_free(fhandle_t *fhp)
1478 1.324.4.2 pooka {
1479 1.324.4.2 pooka
1480 1.324.4.2 pooka vfs__fhfree(fhp);
1481 1.324.4.2 pooka }
1482 1.324.4.2 pooka
1483 1.324.4.2 pooka /*
1484 1.324.4.2 pooka * Get file handle system call
1485 1.324.4.2 pooka */
1486 1.324.4.2 pooka int
1487 1.324.4.2 pooka sys___getfh30(struct lwp *l, void *v, register_t *retval)
1488 1.324.4.2 pooka {
1489 1.324.4.2 pooka struct sys___getfh30_args /* {
1490 1.324.4.2 pooka syscallarg(char *) fname;
1491 1.324.4.2 pooka syscallarg(fhandle_t *) fhp;
1492 1.324.4.2 pooka syscallarg(size_t *) fh_size;
1493 1.324.4.2 pooka } */ *uap = v;
1494 1.324.4.2 pooka struct vnode *vp;
1495 1.324.4.2 pooka fhandle_t *fh;
1496 1.324.4.2 pooka int error;
1497 1.324.4.2 pooka struct nameidata nd;
1498 1.324.4.2 pooka size_t sz;
1499 1.324.4.2 pooka size_t usz;
1500 1.324.4.2 pooka
1501 1.324.4.2 pooka /*
1502 1.324.4.2 pooka * Must be super user
1503 1.324.4.2 pooka */
1504 1.324.4.2 pooka error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_FILEHANDLE,
1505 1.324.4.2 pooka 0, NULL, NULL, NULL);
1506 1.324.4.2 pooka if (error)
1507 1.324.4.2 pooka return (error);
1508 1.324.4.2 pooka NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | TRYEMULROOT, UIO_USERSPACE,
1509 1.324.4.2 pooka SCARG(uap, fname), l);
1510 1.324.4.2 pooka error = namei(&nd);
1511 1.324.4.2 pooka if (error)
1512 1.324.4.2 pooka return (error);
1513 1.324.4.2 pooka vp = nd.ni_vp;
1514 1.324.4.2 pooka error = vfs_composefh_alloc(vp, &fh);
1515 1.324.4.2 pooka vput(vp);
1516 1.324.4.2 pooka if (error != 0) {
1517 1.324.4.2 pooka goto out;
1518 1.324.4.2 pooka }
1519 1.324.4.2 pooka error = copyin(SCARG(uap, fh_size), &usz, sizeof(size_t));
1520 1.324.4.2 pooka if (error != 0) {
1521 1.324.4.2 pooka goto out;
1522 1.324.4.2 pooka }
1523 1.324.4.2 pooka sz = FHANDLE_SIZE(fh);
1524 1.324.4.2 pooka error = copyout(&sz, SCARG(uap, fh_size), sizeof(size_t));
1525 1.324.4.2 pooka if (error != 0) {
1526 1.324.4.2 pooka goto out;
1527 1.324.4.2 pooka }
1528 1.324.4.2 pooka if (usz >= sz) {
1529 1.324.4.2 pooka error = copyout(fh, SCARG(uap, fhp), sz);
1530 1.324.4.2 pooka } else {
1531 1.324.4.2 pooka error = E2BIG;
1532 1.324.4.2 pooka }
1533 1.324.4.2 pooka out:
1534 1.324.4.2 pooka vfs_composefh_free(fh);
1535 1.324.4.2 pooka return (error);
1536 1.324.4.2 pooka }
1537 1.324.4.2 pooka
1538 1.324.4.2 pooka /*
1539 1.324.4.2 pooka * Open a file given a file handle.
1540 1.324.4.2 pooka *
1541 1.324.4.2 pooka * Check permissions, allocate an open file structure,
1542 1.324.4.2 pooka * and call the device open routine if any.
1543 1.324.4.2 pooka */
1544 1.324.4.2 pooka
1545 1.324.4.2 pooka int
1546 1.324.4.2 pooka dofhopen(struct lwp *l, const void *ufhp, size_t fhsize, int oflags,
1547 1.324.4.2 pooka register_t *retval)
1548 1.324.4.2 pooka {
1549 1.324.4.2 pooka struct filedesc *fdp = l->l_proc->p_fd;
1550 1.324.4.2 pooka struct file *fp;
1551 1.324.4.2 pooka struct vnode *vp = NULL;
1552 1.324.4.2 pooka kauth_cred_t cred = l->l_cred;
1553 1.324.4.2 pooka struct file *nfp;
1554 1.324.4.2 pooka int type, indx, error=0;
1555 1.324.4.2 pooka struct flock lf;
1556 1.324.4.2 pooka struct vattr va;
1557 1.324.4.2 pooka fhandle_t *fh;
1558 1.324.4.2 pooka int flags;
1559 1.324.4.2 pooka
1560 1.324.4.2 pooka /*
1561 1.324.4.2 pooka * Must be super user
1562 1.324.4.2 pooka */
1563 1.324.4.2 pooka if ((error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_FILEHANDLE,
1564 1.324.4.2 pooka 0, NULL, NULL, NULL)))
1565 1.324.4.2 pooka return (error);
1566 1.324.4.2 pooka
1567 1.324.4.2 pooka flags = FFLAGS(oflags);
1568 1.324.4.2 pooka if ((flags & (FREAD | FWRITE)) == 0)
1569 1.324.4.2 pooka return (EINVAL);
1570 1.324.4.2 pooka if ((flags & O_CREAT))
1571 1.324.4.2 pooka return (EINVAL);
1572 1.324.4.2 pooka /* falloc() will use the file descriptor for us */
1573 1.324.4.2 pooka if ((error = falloc(l, &nfp, &indx)) != 0)
1574 1.324.4.2 pooka return (error);
1575 1.324.4.2 pooka fp = nfp;
1576 1.324.4.2 pooka error = vfs_copyinfh_alloc(ufhp, fhsize, &fh);
1577 1.324.4.2 pooka if (error != 0) {
1578 1.324.4.2 pooka goto bad;
1579 1.324.4.2 pooka }
1580 1.324.4.2 pooka error = vfs_fhtovp(fh, &vp);
1581 1.324.4.2 pooka if (error != 0) {
1582 1.324.4.2 pooka goto bad;
1583 1.324.4.2 pooka }
1584 1.324.4.2 pooka
1585 1.324.4.2 pooka /* Now do an effective vn_open */
1586 1.324.4.2 pooka
1587 1.324.4.2 pooka if (vp->v_type == VSOCK) {
1588 1.324.4.2 pooka error = EOPNOTSUPP;
1589 1.324.4.2 pooka goto bad;
1590 1.324.4.2 pooka }
1591 1.324.4.2 pooka if (flags & FREAD) {
1592 1.324.4.2 pooka if ((error = VOP_ACCESS(vp, VREAD, cred, l)) != 0)
1593 1.324.4.2 pooka goto bad;
1594 1.324.4.2 pooka }
1595 1.324.4.2 pooka if (flags & (FWRITE | O_TRUNC)) {
1596 1.324.4.2 pooka if (vp->v_type == VDIR) {
1597 1.324.4.2 pooka error = EISDIR;
1598 1.324.4.2 pooka goto bad;
1599 1.324.4.2 pooka }
1600 1.324.4.2 pooka if ((error = vn_writechk(vp)) != 0 ||
1601 1.324.4.2 pooka (error = VOP_ACCESS(vp, VWRITE, cred, l)) != 0)
1602 1.324.4.2 pooka goto bad;
1603 1.324.4.2 pooka }
1604 1.324.4.2 pooka if (flags & O_TRUNC) {
1605 1.324.4.2 pooka VOP_UNLOCK(vp, 0); /* XXX */
1606 1.324.4.2 pooka VOP_LEASE(vp, l, cred, LEASE_WRITE);
1607 1.324.4.2 pooka vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); /* XXX */
1608 1.324.4.2 pooka VATTR_NULL(&va);
1609 1.324.4.2 pooka va.va_size = 0;
1610 1.324.4.2 pooka error = VOP_SETATTR(vp, &va, cred, l);
1611 1.324.4.2 pooka if (error)
1612 1.324.4.2 pooka goto bad;
1613 1.324.4.2 pooka }
1614 1.324.4.2 pooka if ((error = VOP_OPEN(vp, flags, cred, l)) != 0)
1615 1.324.4.2 pooka goto bad;
1616 1.324.4.2 pooka if (flags & FWRITE)
1617 1.324.4.2 pooka vp->v_writecount++;
1618 1.324.4.2 pooka
1619 1.324.4.2 pooka /* done with modified vn_open, now finish what sys_open does. */
1620 1.324.4.2 pooka
1621 1.324.4.2 pooka fp->f_flag = flags & FMASK;
1622 1.324.4.2 pooka fp->f_type = DTYPE_VNODE;
1623 1.324.4.2 pooka fp->f_ops = &vnops;
1624 1.324.4.2 pooka fp->f_data = vp;
1625 1.324.4.2 pooka if (flags & (O_EXLOCK | O_SHLOCK)) {
1626 1.324.4.2 pooka lf.l_whence = SEEK_SET;
1627 1.324.4.2 pooka lf.l_start = 0;
1628 1.324.4.2 pooka lf.l_len = 0;
1629 1.324.4.2 pooka if (flags & O_EXLOCK)
1630 1.324.4.2 pooka lf.l_type = F_WRLCK;
1631 1.324.4.2 pooka else
1632 1.324.4.2 pooka lf.l_type = F_RDLCK;
1633 1.324.4.2 pooka type = F_FLOCK;
1634 1.324.4.2 pooka if ((flags & FNONBLOCK) == 0)
1635 1.324.4.2 pooka type |= F_WAIT;
1636 1.324.4.2 pooka VOP_UNLOCK(vp, 0);
1637 1.324.4.2 pooka error = VOP_ADVLOCK(vp, fp, F_SETLK, &lf, type);
1638 1.324.4.2 pooka if (error) {
1639 1.324.4.2 pooka (void) vn_close(vp, fp->f_flag, fp->f_cred, l);
1640 1.324.4.2 pooka FILE_UNUSE(fp, l);
1641 1.324.4.2 pooka ffree(fp);
1642 1.324.4.2 pooka fdremove(fdp, indx);
1643 1.324.4.2 pooka return (error);
1644 1.324.4.2 pooka }
1645 1.324.4.2 pooka vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
1646 1.324.4.2 pooka fp->f_flag |= FHASLOCK;
1647 1.324.4.2 pooka }
1648 1.324.4.2 pooka VOP_UNLOCK(vp, 0);
1649 1.324.4.2 pooka *retval = indx;
1650 1.324.4.2 pooka FILE_SET_MATURE(fp);
1651 1.324.4.2 pooka FILE_UNUSE(fp, l);
1652 1.324.4.2 pooka vfs_copyinfh_free(fh);
1653 1.324.4.2 pooka return (0);
1654 1.324.4.2 pooka
1655 1.324.4.2 pooka bad:
1656 1.324.4.2 pooka FILE_UNUSE(fp, l);
1657 1.324.4.2 pooka ffree(fp);
1658 1.324.4.2 pooka fdremove(fdp, indx);
1659 1.324.4.2 pooka if (vp != NULL)
1660 1.324.4.2 pooka vput(vp);
1661 1.324.4.2 pooka vfs_copyinfh_free(fh);
1662 1.324.4.2 pooka return (error);
1663 1.324.4.2 pooka }
1664 1.324.4.2 pooka
1665 1.324.4.2 pooka int
1666 1.324.4.2 pooka sys___fhopen40(struct lwp *l, void *v, register_t *retval)
1667 1.324.4.2 pooka {
1668 1.324.4.2 pooka struct sys___fhopen40_args /* {
1669 1.324.4.2 pooka syscallarg(const void *) fhp;
1670 1.324.4.2 pooka syscallarg(size_t) fh_size;
1671 1.324.4.2 pooka syscallarg(int) flags;
1672 1.324.4.2 pooka } */ *uap = v;
1673 1.324.4.2 pooka
1674 1.324.4.2 pooka return dofhopen(l, SCARG(uap, fhp), SCARG(uap, fh_size),
1675 1.324.4.2 pooka SCARG(uap, flags), retval);
1676 1.324.4.2 pooka }
1677 1.324.4.2 pooka
1678 1.324.4.2 pooka int
1679 1.324.4.2 pooka do_fhstat(struct lwp *l, const void *ufhp, size_t fhsize, struct stat *sb)
1680 1.324.4.2 pooka {
1681 1.324.4.2 pooka int error;
1682 1.324.4.2 pooka fhandle_t *fh;
1683 1.324.4.2 pooka struct vnode *vp;
1684 1.324.4.2 pooka
1685 1.324.4.2 pooka /*
1686 1.324.4.2 pooka * Must be super user
1687 1.324.4.2 pooka */
1688 1.324.4.2 pooka if ((error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_FILEHANDLE,
1689 1.324.4.2 pooka 0, NULL, NULL, NULL)))
1690 1.324.4.2 pooka return (error);
1691 1.324.4.2 pooka
1692 1.324.4.2 pooka error = vfs_copyinfh_alloc(ufhp, fhsize, &fh);
1693 1.324.4.2 pooka if (error != 0)
1694 1.324.4.2 pooka return error;
1695 1.324.4.2 pooka
1696 1.324.4.2 pooka error = vfs_fhtovp(fh, &vp);
1697 1.324.4.2 pooka vfs_copyinfh_free(fh);
1698 1.324.4.2 pooka if (error != 0)
1699 1.324.4.2 pooka return error;
1700 1.324.4.2 pooka
1701 1.324.4.2 pooka error = vn_stat(vp, sb, l);
1702 1.324.4.2 pooka vput(vp);
1703 1.324.4.2 pooka return error;
1704 1.324.4.2 pooka }
1705 1.324.4.2 pooka
1706 1.324.4.2 pooka
1707 1.324.4.2 pooka /* ARGSUSED */
1708 1.324.4.2 pooka int
1709 1.324.4.2 pooka sys___fhstat40(struct lwp *l, void *v, register_t *retval)
1710 1.324.4.2 pooka {
1711 1.324.4.2 pooka struct sys___fhstat40_args /* {
1712 1.324.4.2 pooka syscallarg(const void *) fhp;
1713 1.324.4.2 pooka syscallarg(size_t) fh_size;
1714 1.324.4.2 pooka syscallarg(struct stat *) sb;
1715 1.324.4.2 pooka } */ *uap = v;
1716 1.324.4.2 pooka struct stat sb;
1717 1.324.4.2 pooka int error;
1718 1.324.4.2 pooka
1719 1.324.4.2 pooka error = do_fhstat(l, SCARG(uap, fhp), SCARG(uap, fh_size), &sb);
1720 1.324.4.2 pooka if (error)
1721 1.324.4.2 pooka return error;
1722 1.324.4.2 pooka return copyout(&sb, SCARG(uap, sb), sizeof(sb));
1723 1.324.4.2 pooka }
1724 1.324.4.2 pooka
1725 1.324.4.2 pooka int
1726 1.324.4.2 pooka do_fhstatvfs(struct lwp *l, const void *ufhp, size_t fhsize, struct statvfs *sb,
1727 1.324.4.2 pooka int flags)
1728 1.324.4.2 pooka {
1729 1.324.4.2 pooka fhandle_t *fh;
1730 1.324.4.2 pooka struct mount *mp;
1731 1.324.4.2 pooka struct vnode *vp;
1732 1.324.4.2 pooka int error;
1733 1.324.4.2 pooka
1734 1.324.4.2 pooka /*
1735 1.324.4.2 pooka * Must be super user
1736 1.324.4.2 pooka */
1737 1.324.4.2 pooka if ((error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_FILEHANDLE,
1738 1.324.4.2 pooka 0, NULL, NULL, NULL)))
1739 1.324.4.2 pooka return error;
1740 1.324.4.2 pooka
1741 1.324.4.2 pooka error = vfs_copyinfh_alloc(ufhp, fhsize, &fh);
1742 1.324.4.2 pooka if (error != 0)
1743 1.324.4.2 pooka return error;
1744 1.324.4.2 pooka
1745 1.324.4.2 pooka error = vfs_fhtovp(fh, &vp);
1746 1.324.4.2 pooka vfs_copyinfh_free(fh);
1747 1.324.4.2 pooka if (error != 0)
1748 1.324.4.2 pooka return error;
1749 1.324.4.2 pooka
1750 1.324.4.2 pooka mp = vp->v_mount;
1751 1.324.4.2 pooka error = dostatvfs(mp, sb, l, flags, 1);
1752 1.324.4.2 pooka vput(vp);
1753 1.324.4.2 pooka return error;
1754 1.324.4.2 pooka }
1755 1.324.4.2 pooka
1756 1.324.4.2 pooka /* ARGSUSED */
1757 1.324.4.2 pooka int
1758 1.324.4.2 pooka sys___fhstatvfs140(struct lwp *l, void *v, register_t *retval)
1759 1.324.4.2 pooka {
1760 1.324.4.2 pooka struct sys___fhstatvfs140_args /* {
1761 1.324.4.2 pooka syscallarg(const void *) fhp;
1762 1.324.4.2 pooka syscallarg(size_t) fh_size;
1763 1.324.4.2 pooka syscallarg(struct statvfs *) buf;
1764 1.324.4.2 pooka syscallarg(int) flags;
1765 1.324.4.2 pooka } */ *uap = v;
1766 1.324.4.2 pooka struct statvfs *sb = STATVFSBUF_GET();
1767 1.324.4.2 pooka int error;
1768 1.324.4.2 pooka
1769 1.324.4.2 pooka error = do_fhstatvfs(l, SCARG(uap, fhp), SCARG(uap, fh_size), sb,
1770 1.324.4.2 pooka SCARG(uap, flags));
1771 1.324.4.2 pooka if (error == 0)
1772 1.324.4.2 pooka error = copyout(sb, SCARG(uap, buf), sizeof(*sb));
1773 1.324.4.2 pooka STATVFSBUF_PUT(sb);
1774 1.324.4.2 pooka return error;
1775 1.324.4.2 pooka }
1776 1.324.4.2 pooka
1777 1.324.4.2 pooka /*
1778 1.324.4.2 pooka * Create a special file.
1779 1.324.4.2 pooka */
1780 1.324.4.2 pooka /* ARGSUSED */
1781 1.324.4.2 pooka int
1782 1.324.4.2 pooka sys_mknod(struct lwp *l, void *v, register_t *retval)
1783 1.324.4.2 pooka {
1784 1.324.4.2 pooka struct sys_mknod_args /* {
1785 1.324.4.2 pooka syscallarg(const char *) path;
1786 1.324.4.2 pooka syscallarg(int) mode;
1787 1.324.4.2 pooka syscallarg(int) dev;
1788 1.324.4.2 pooka } */ *uap = v;
1789 1.324.4.2 pooka struct proc *p = l->l_proc;
1790 1.324.4.2 pooka struct vnode *vp;
1791 1.324.4.2 pooka struct vattr vattr;
1792 1.324.4.2 pooka int error, optype;
1793 1.324.4.2 pooka struct nameidata nd;
1794 1.324.4.2 pooka char *path;
1795 1.324.4.2 pooka const char *cpath;
1796 1.324.4.2 pooka enum uio_seg seg = UIO_USERSPACE;
1797 1.324.4.2 pooka
1798 1.324.4.2 pooka if ((error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_MKNOD,
1799 1.324.4.2 pooka 0, NULL, NULL, NULL)) != 0)
1800 1.324.4.2 pooka return (error);
1801 1.324.4.2 pooka
1802 1.324.4.2 pooka optype = VOP_MKNOD_DESCOFFSET;
1803 1.324.4.2 pooka
1804 1.324.4.2 pooka VERIEXEC_PATH_GET(SCARG(uap, path), seg, cpath, path);
1805 1.324.4.2 pooka NDINIT(&nd, CREATE, LOCKPARENT | TRYEMULROOT, seg, cpath, l);
1806 1.324.4.2 pooka
1807 1.324.4.2 pooka if ((error = namei(&nd)) != 0)
1808 1.324.4.2 pooka goto out;
1809 1.324.4.2 pooka vp = nd.ni_vp;
1810 1.324.4.2 pooka if (vp != NULL)
1811 1.324.4.2 pooka error = EEXIST;
1812 1.324.4.2 pooka else {
1813 1.324.4.2 pooka VATTR_NULL(&vattr);
1814 1.324.4.2 pooka vattr.va_mode =
1815 1.324.4.2 pooka (SCARG(uap, mode) & ALLPERMS) &~ p->p_cwdi->cwdi_cmask;
1816 1.324.4.2 pooka vattr.va_rdev = SCARG(uap, dev);
1817 1.324.4.2 pooka
1818 1.324.4.2 pooka switch (SCARG(uap, mode) & S_IFMT) {
1819 1.324.4.2 pooka case S_IFMT: /* used by badsect to flag bad sectors */
1820 1.324.4.2 pooka vattr.va_type = VBAD;
1821 1.324.4.2 pooka break;
1822 1.324.4.2 pooka case S_IFCHR:
1823 1.324.4.2 pooka vattr.va_type = VCHR;
1824 1.324.4.2 pooka break;
1825 1.324.4.2 pooka case S_IFBLK:
1826 1.324.4.2 pooka vattr.va_type = VBLK;
1827 1.324.4.2 pooka break;
1828 1.324.4.2 pooka case S_IFWHT:
1829 1.324.4.2 pooka optype = VOP_WHITEOUT_DESCOFFSET;
1830 1.324.4.2 pooka break;
1831 1.324.4.2 pooka case S_IFREG:
1832 1.324.4.2 pooka #if NVERIEXEC > 0
1833 1.324.4.2 pooka error = veriexec_openchk(l, nd.ni_vp, nd.ni_dirp,
1834 1.324.4.2 pooka O_CREAT);
1835 1.324.4.2 pooka #endif /* NVERIEXEC > 0 */
1836 1.324.4.2 pooka vattr.va_type = VREG;
1837 1.324.4.2 pooka vattr.va_rdev = VNOVAL;
1838 1.324.4.2 pooka optype = VOP_CREATE_DESCOFFSET;
1839 1.324.4.2 pooka break;
1840 1.324.4.2 pooka default:
1841 1.324.4.2 pooka error = EINVAL;
1842 1.324.4.2 pooka break;
1843 1.324.4.2 pooka }
1844 1.324.4.2 pooka }
1845 1.324.4.2 pooka if (!error) {
1846 1.324.4.2 pooka VOP_LEASE(nd.ni_dvp, l, l->l_cred, LEASE_WRITE);
1847 1.324.4.2 pooka switch (optype) {
1848 1.324.4.2 pooka case VOP_WHITEOUT_DESCOFFSET:
1849 1.324.4.2 pooka error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, CREATE);
1850 1.324.4.2 pooka if (error)
1851 1.324.4.2 pooka VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1852 1.324.4.2 pooka vput(nd.ni_dvp);
1853 1.324.4.2 pooka break;
1854 1.324.4.2 pooka
1855 1.324.4.2 pooka case VOP_MKNOD_DESCOFFSET:
1856 1.324.4.2 pooka error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp,
1857 1.324.4.2 pooka &nd.ni_cnd, &vattr);
1858 1.324.4.2 pooka if (error == 0)
1859 1.324.4.2 pooka vput(nd.ni_vp);
1860 1.324.4.2 pooka break;
1861 1.324.4.2 pooka
1862 1.324.4.2 pooka case VOP_CREATE_DESCOFFSET:
1863 1.324.4.2 pooka error = VOP_CREATE(nd.ni_dvp, &nd.ni_vp,
1864 1.324.4.2 pooka &nd.ni_cnd, &vattr);
1865 1.324.4.2 pooka if (error == 0)
1866 1.324.4.2 pooka vput(nd.ni_vp);
1867 1.324.4.2 pooka break;
1868 1.324.4.2 pooka }
1869 1.324.4.2 pooka } else {
1870 1.324.4.2 pooka VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1871 1.324.4.2 pooka if (nd.ni_dvp == vp)
1872 1.324.4.2 pooka vrele(nd.ni_dvp);
1873 1.324.4.2 pooka else
1874 1.324.4.2 pooka vput(nd.ni_dvp);
1875 1.324.4.2 pooka if (vp)
1876 1.324.4.2 pooka vrele(vp);
1877 1.324.4.2 pooka }
1878 1.324.4.2 pooka out:
1879 1.324.4.2 pooka VERIEXEC_PATH_PUT(path);
1880 1.324.4.2 pooka return (error);
1881 1.324.4.2 pooka }
1882 1.324.4.2 pooka
1883 1.324.4.2 pooka /*
1884 1.324.4.2 pooka * Create a named pipe.
1885 1.324.4.2 pooka */
1886 1.324.4.2 pooka /* ARGSUSED */
1887 1.324.4.2 pooka int
1888 1.324.4.2 pooka sys_mkfifo(struct lwp *l, void *v, register_t *retval)
1889 1.324.4.2 pooka {
1890 1.324.4.2 pooka struct sys_mkfifo_args /* {
1891 1.324.4.2 pooka syscallarg(const char *) path;
1892 1.324.4.2 pooka syscallarg(int) mode;
1893 1.324.4.2 pooka } */ *uap = v;
1894 1.324.4.2 pooka struct proc *p = l->l_proc;
1895 1.324.4.2 pooka struct vattr vattr;
1896 1.324.4.2 pooka int error;
1897 1.324.4.2 pooka struct nameidata nd;
1898 1.324.4.2 pooka
1899 1.324.4.2 pooka NDINIT(&nd, CREATE, LOCKPARENT | TRYEMULROOT, UIO_USERSPACE, SCARG(uap, path), l);
1900 1.324.4.2 pooka if ((error = namei(&nd)) != 0)
1901 1.324.4.2 pooka return (error);
1902 1.324.4.2 pooka if (nd.ni_vp != NULL) {
1903 1.324.4.2 pooka VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1904 1.324.4.2 pooka if (nd.ni_dvp == nd.ni_vp)
1905 1.324.4.2 pooka vrele(nd.ni_dvp);
1906 1.324.4.2 pooka else
1907 1.324.4.2 pooka vput(nd.ni_dvp);
1908 1.324.4.2 pooka vrele(nd.ni_vp);
1909 1.324.4.2 pooka return (EEXIST);
1910 1.324.4.2 pooka }
1911 1.324.4.2 pooka VATTR_NULL(&vattr);
1912 1.324.4.2 pooka vattr.va_type = VFIFO;
1913 1.324.4.2 pooka vattr.va_mode = (SCARG(uap, mode) & ALLPERMS) &~ p->p_cwdi->cwdi_cmask;
1914 1.324.4.2 pooka VOP_LEASE(nd.ni_dvp, l, l->l_cred, LEASE_WRITE);
1915 1.324.4.2 pooka error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
1916 1.324.4.2 pooka if (error == 0)
1917 1.324.4.2 pooka vput(nd.ni_vp);
1918 1.324.4.2 pooka return (error);
1919 1.324.4.2 pooka }
1920 1.324.4.2 pooka
1921 1.324.4.2 pooka /*
1922 1.324.4.2 pooka * Make a hard file link.
1923 1.324.4.2 pooka */
1924 1.324.4.2 pooka /* ARGSUSED */
1925 1.324.4.2 pooka int
1926 1.324.4.2 pooka sys_link(struct lwp *l, void *v, register_t *retval)
1927 1.324.4.2 pooka {
1928 1.324.4.2 pooka struct sys_link_args /* {
1929 1.324.4.2 pooka syscallarg(const char *) path;
1930 1.324.4.2 pooka syscallarg(const char *) link;
1931 1.324.4.2 pooka } */ *uap = v;
1932 1.324.4.2 pooka struct vnode *vp;
1933 1.324.4.2 pooka struct nameidata nd;
1934 1.324.4.2 pooka int error;
1935 1.324.4.2 pooka
1936 1.324.4.2 pooka NDINIT(&nd, LOOKUP, FOLLOW | TRYEMULROOT, UIO_USERSPACE, SCARG(uap, path), l);
1937 1.324.4.2 pooka if ((error = namei(&nd)) != 0)
1938 1.324.4.2 pooka return (error);
1939 1.324.4.2 pooka vp = nd.ni_vp;
1940 1.324.4.2 pooka NDINIT(&nd, CREATE, LOCKPARENT | TRYEMULROOT, UIO_USERSPACE, SCARG(uap, link), l);
1941 1.324.4.2 pooka if ((error = namei(&nd)) != 0)
1942 1.324.4.2 pooka goto out;
1943 1.324.4.2 pooka if (nd.ni_vp) {
1944 1.324.4.2 pooka VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1945 1.324.4.2 pooka if (nd.ni_dvp == nd.ni_vp)
1946 1.324.4.2 pooka vrele(nd.ni_dvp);
1947 1.324.4.2 pooka else
1948 1.324.4.2 pooka vput(nd.ni_dvp);
1949 1.324.4.2 pooka vrele(nd.ni_vp);
1950 1.324.4.2 pooka error = EEXIST;
1951 1.324.4.2 pooka goto out;
1952 1.324.4.2 pooka }
1953 1.324.4.2 pooka VOP_LEASE(nd.ni_dvp, l, l->l_cred, LEASE_WRITE);
1954 1.324.4.2 pooka VOP_LEASE(vp, l, l->l_cred, LEASE_WRITE);
1955 1.324.4.2 pooka error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd);
1956 1.324.4.2 pooka out:
1957 1.324.4.2 pooka vrele(vp);
1958 1.324.4.2 pooka return (error);
1959 1.324.4.2 pooka }
1960 1.324.4.2 pooka
1961 1.324.4.2 pooka /*
1962 1.324.4.2 pooka * Make a symbolic link.
1963 1.324.4.2 pooka */
1964 1.324.4.2 pooka /* ARGSUSED */
1965 1.324.4.2 pooka int
1966 1.324.4.2 pooka sys_symlink(struct lwp *l, void *v, register_t *retval)
1967 1.324.4.2 pooka {
1968 1.324.4.2 pooka struct sys_symlink_args /* {
1969 1.324.4.2 pooka syscallarg(const char *) path;
1970 1.324.4.2 pooka syscallarg(const char *) link;
1971 1.324.4.2 pooka } */ *uap = v;
1972 1.324.4.2 pooka struct proc *p = l->l_proc;
1973 1.324.4.2 pooka struct vattr vattr;
1974 1.324.4.2 pooka char *path;
1975 1.324.4.2 pooka int error;
1976 1.324.4.2 pooka struct nameidata nd;
1977 1.324.4.2 pooka
1978 1.324.4.2 pooka path = PNBUF_GET();
1979 1.324.4.2 pooka error = copyinstr(SCARG(uap, path), path, MAXPATHLEN, NULL);
1980 1.324.4.2 pooka if (error)
1981 1.324.4.2 pooka goto out;
1982 1.324.4.2 pooka NDINIT(&nd, CREATE, LOCKPARENT | TRYEMULROOT, UIO_USERSPACE, SCARG(uap, link), l);
1983 1.324.4.2 pooka if ((error = namei(&nd)) != 0)
1984 1.324.4.2 pooka goto out;
1985 1.324.4.2 pooka if (nd.ni_vp) {
1986 1.324.4.2 pooka VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1987 1.324.4.2 pooka if (nd.ni_dvp == nd.ni_vp)
1988 1.324.4.2 pooka vrele(nd.ni_dvp);
1989 1.324.4.2 pooka else
1990 1.324.4.2 pooka vput(nd.ni_dvp);
1991 1.324.4.2 pooka vrele(nd.ni_vp);
1992 1.324.4.2 pooka error = EEXIST;
1993 1.324.4.2 pooka goto out;
1994 1.324.4.2 pooka }
1995 1.324.4.2 pooka VATTR_NULL(&vattr);
1996 1.324.4.2 pooka vattr.va_type = VLNK;
1997 1.324.4.2 pooka vattr.va_mode = ACCESSPERMS &~ p->p_cwdi->cwdi_cmask;
1998 1.324.4.2 pooka VOP_LEASE(nd.ni_dvp, l, l->l_cred, LEASE_WRITE);
1999 1.324.4.2 pooka error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr, path);
2000 1.324.4.2 pooka if (error == 0)
2001 1.324.4.2 pooka vput(nd.ni_vp);
2002 1.324.4.2 pooka out:
2003 1.324.4.2 pooka PNBUF_PUT(path);
2004 1.324.4.2 pooka return (error);
2005 1.324.4.2 pooka }
2006 1.324.4.2 pooka
2007 1.324.4.2 pooka /*
2008 1.324.4.2 pooka * Delete a whiteout from the filesystem.
2009 1.324.4.2 pooka */
2010 1.324.4.2 pooka /* ARGSUSED */
2011 1.324.4.2 pooka int
2012 1.324.4.2 pooka sys_undelete(struct lwp *l, void *v, register_t *retval)
2013 1.324.4.2 pooka {
2014 1.324.4.2 pooka struct sys_undelete_args /* {
2015 1.324.4.2 pooka syscallarg(const char *) path;
2016 1.324.4.2 pooka } */ *uap = v;
2017 1.324.4.2 pooka int error;
2018 1.324.4.2 pooka struct nameidata nd;
2019 1.324.4.2 pooka
2020 1.324.4.2 pooka NDINIT(&nd, DELETE, LOCKPARENT | DOWHITEOUT | TRYEMULROOT, UIO_USERSPACE,
2021 1.324.4.2 pooka SCARG(uap, path), l);
2022 1.324.4.2 pooka error = namei(&nd);
2023 1.324.4.2 pooka if (error)
2024 1.324.4.2 pooka return (error);
2025 1.324.4.2 pooka
2026 1.324.4.2 pooka if (nd.ni_vp != NULLVP || !(nd.ni_cnd.cn_flags & ISWHITEOUT)) {
2027 1.324.4.2 pooka VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
2028 1.324.4.2 pooka if (nd.ni_dvp == nd.ni_vp)
2029 1.324.4.2 pooka vrele(nd.ni_dvp);
2030 1.324.4.2 pooka else
2031 1.324.4.2 pooka vput(nd.ni_dvp);
2032 1.324.4.2 pooka if (nd.ni_vp)
2033 1.324.4.2 pooka vrele(nd.ni_vp);
2034 1.324.4.2 pooka return (EEXIST);
2035 1.324.4.2 pooka }
2036 1.324.4.2 pooka VOP_LEASE(nd.ni_dvp, l, l->l_cred, LEASE_WRITE);
2037 1.324.4.2 pooka if ((error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, DELETE)) != 0)
2038 1.324.4.2 pooka VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
2039 1.324.4.2 pooka vput(nd.ni_dvp);
2040 1.324.4.2 pooka return (error);
2041 1.324.4.2 pooka }
2042 1.324.4.2 pooka
2043 1.324.4.2 pooka /*
2044 1.324.4.2 pooka * Delete a name from the filesystem.
2045 1.324.4.2 pooka */
2046 1.324.4.2 pooka /* ARGSUSED */
2047 1.324.4.2 pooka int
2048 1.324.4.2 pooka sys_unlink(struct lwp *l, void *v, register_t *retval)
2049 1.324.4.2 pooka {
2050 1.324.4.2 pooka struct sys_unlink_args /* {
2051 1.324.4.2 pooka syscallarg(const char *) path;
2052 1.324.4.2 pooka } */ *uap = v;
2053 1.324.4.2 pooka struct vnode *vp;
2054 1.324.4.2 pooka int error;
2055 1.324.4.2 pooka struct nameidata nd;
2056 1.324.4.2 pooka char *path;
2057 1.324.4.2 pooka const char *cpath;
2058 1.324.4.2 pooka enum uio_seg seg = UIO_USERSPACE;
2059 1.324.4.2 pooka
2060 1.324.4.2 pooka VERIEXEC_PATH_GET(SCARG(uap, path), seg, cpath, path);
2061 1.324.4.2 pooka NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF | TRYEMULROOT, seg, cpath, l);
2062 1.324.4.2 pooka
2063 1.324.4.2 pooka if ((error = namei(&nd)) != 0)
2064 1.324.4.2 pooka goto out;
2065 1.324.4.2 pooka vp = nd.ni_vp;
2066 1.324.4.2 pooka
2067 1.324.4.2 pooka /*
2068 1.324.4.2 pooka * The root of a mounted filesystem cannot be deleted.
2069 1.324.4.2 pooka */
2070 1.324.4.2 pooka if (vp->v_flag & VROOT) {
2071 1.324.4.2 pooka VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
2072 1.324.4.2 pooka if (nd.ni_dvp == vp)
2073 1.324.4.2 pooka vrele(nd.ni_dvp);
2074 1.324.4.2 pooka else
2075 1.324.4.2 pooka vput(nd.ni_dvp);
2076 1.324.4.2 pooka vput(vp);
2077 1.324.4.2 pooka error = EBUSY;
2078 1.324.4.2 pooka goto out;
2079 1.324.4.2 pooka }
2080 1.324.4.2 pooka
2081 1.324.4.2 pooka #if NVERIEXEC > 0
2082 1.324.4.2 pooka /* Handle remove requests for veriexec entries. */
2083 1.324.4.2 pooka if ((error = veriexec_removechk(l, nd.ni_vp, nd.ni_dirp)) != 0) {
2084 1.324.4.2 pooka VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
2085 1.324.4.2 pooka if (nd.ni_dvp == vp)
2086 1.324.4.2 pooka vrele(nd.ni_dvp);
2087 1.324.4.2 pooka else
2088 1.324.4.2 pooka vput(nd.ni_dvp);
2089 1.324.4.2 pooka vput(vp);
2090 1.324.4.2 pooka goto out;
2091 1.324.4.2 pooka }
2092 1.324.4.2 pooka #endif /* NVERIEXEC > 0 */
2093 1.324.4.2 pooka
2094 1.324.4.2 pooka VOP_LEASE(nd.ni_dvp, l, l->l_cred, LEASE_WRITE);
2095 1.324.4.2 pooka VOP_LEASE(vp, l, l->l_cred, LEASE_WRITE);
2096 1.324.4.2 pooka #ifdef FILEASSOC
2097 1.324.4.2 pooka (void)fileassoc_file_delete(vp);
2098 1.324.4.2 pooka #endif /* FILEASSOC */
2099 1.324.4.2 pooka error = VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
2100 1.324.4.2 pooka out:
2101 1.324.4.2 pooka VERIEXEC_PATH_PUT(path);
2102 1.324.4.2 pooka return (error);
2103 1.324.4.2 pooka }
2104 1.324.4.2 pooka
2105 1.324.4.2 pooka /*
2106 1.324.4.2 pooka * Reposition read/write file offset.
2107 1.324.4.2 pooka */
2108 1.324.4.2 pooka int
2109 1.324.4.2 pooka sys_lseek(struct lwp *l, void *v, register_t *retval)
2110 1.324.4.2 pooka {
2111 1.324.4.2 pooka struct sys_lseek_args /* {
2112 1.324.4.2 pooka syscallarg(int) fd;
2113 1.324.4.2 pooka syscallarg(int) pad;
2114 1.324.4.2 pooka syscallarg(off_t) offset;
2115 1.324.4.2 pooka syscallarg(int) whence;
2116 1.324.4.2 pooka } */ *uap = v;
2117 1.324.4.2 pooka struct proc *p = l->l_proc;
2118 1.324.4.2 pooka kauth_cred_t cred = l->l_cred;
2119 1.324.4.2 pooka struct filedesc *fdp = p->p_fd;
2120 1.324.4.2 pooka struct file *fp;
2121 1.324.4.2 pooka struct vnode *vp;
2122 1.324.4.2 pooka struct vattr vattr;
2123 1.324.4.2 pooka off_t newoff;
2124 1.324.4.2 pooka int error;
2125 1.324.4.2 pooka
2126 1.324.4.2 pooka if ((fp = fd_getfile(fdp, SCARG(uap, fd))) == NULL)
2127 1.324.4.2 pooka return (EBADF);
2128 1.324.4.2 pooka
2129 1.324.4.2 pooka FILE_USE(fp);
2130 1.324.4.2 pooka
2131 1.324.4.2 pooka vp = (struct vnode *)fp->f_data;
2132 1.324.4.2 pooka if (fp->f_type != DTYPE_VNODE || vp->v_type == VFIFO) {
2133 1.324.4.2 pooka error = ESPIPE;
2134 1.324.4.2 pooka goto out;
2135 1.324.4.2 pooka }
2136 1.324.4.2 pooka
2137 1.324.4.2 pooka switch (SCARG(uap, whence)) {
2138 1.324.4.2 pooka case SEEK_CUR:
2139 1.324.4.2 pooka newoff = fp->f_offset + SCARG(uap, offset);
2140 1.324.4.2 pooka break;
2141 1.324.4.2 pooka case SEEK_END:
2142 1.324.4.2 pooka error = VOP_GETATTR(vp, &vattr, cred, l);
2143 1.324.4.2 pooka if (error)
2144 1.324.4.2 pooka goto out;
2145 1.324.4.2 pooka newoff = SCARG(uap, offset) + vattr.va_size;
2146 1.324.4.2 pooka break;
2147 1.324.4.2 pooka case SEEK_SET:
2148 1.324.4.2 pooka newoff = SCARG(uap, offset);
2149 1.324.4.2 pooka break;
2150 1.324.4.2 pooka default:
2151 1.324.4.2 pooka error = EINVAL;
2152 1.324.4.2 pooka goto out;
2153 1.324.4.2 pooka }
2154 1.324.4.2 pooka if ((error = VOP_SEEK(vp, fp->f_offset, newoff, cred)) != 0)
2155 1.324.4.2 pooka goto out;
2156 1.324.4.2 pooka
2157 1.324.4.2 pooka *(off_t *)retval = fp->f_offset = newoff;
2158 1.324.4.2 pooka out:
2159 1.324.4.2 pooka FILE_UNUSE(fp, l);
2160 1.324.4.2 pooka return (error);
2161 1.324.4.2 pooka }
2162 1.324.4.2 pooka
2163 1.324.4.2 pooka /*
2164 1.324.4.2 pooka * Positional read system call.
2165 1.324.4.2 pooka */
2166 1.324.4.2 pooka int
2167 1.324.4.2 pooka sys_pread(struct lwp *l, void *v, register_t *retval)
2168 1.324.4.2 pooka {
2169 1.324.4.2 pooka struct sys_pread_args /* {
2170 1.324.4.2 pooka syscallarg(int) fd;
2171 1.324.4.2 pooka syscallarg(void *) buf;
2172 1.324.4.2 pooka syscallarg(size_t) nbyte;
2173 1.324.4.2 pooka syscallarg(off_t) offset;
2174 1.324.4.2 pooka } */ *uap = v;
2175 1.324.4.2 pooka struct proc *p = l->l_proc;
2176 1.324.4.2 pooka struct filedesc *fdp = p->p_fd;
2177 1.324.4.2 pooka struct file *fp;
2178 1.324.4.2 pooka struct vnode *vp;
2179 1.324.4.2 pooka off_t offset;
2180 1.324.4.2 pooka int error, fd = SCARG(uap, fd);
2181 1.324.4.2 pooka
2182 1.324.4.2 pooka if ((fp = fd_getfile(fdp, fd)) == NULL)
2183 1.324.4.2 pooka return (EBADF);
2184 1.324.4.2 pooka
2185 1.324.4.2 pooka if ((fp->f_flag & FREAD) == 0) {
2186 1.324.4.2 pooka simple_unlock(&fp->f_slock);
2187 1.324.4.2 pooka return (EBADF);
2188 1.324.4.2 pooka }
2189 1.324.4.2 pooka
2190 1.324.4.2 pooka FILE_USE(fp);
2191 1.324.4.2 pooka
2192 1.324.4.2 pooka vp = (struct vnode *)fp->f_data;
2193 1.324.4.2 pooka if (fp->f_type != DTYPE_VNODE || vp->v_type == VFIFO) {
2194 1.324.4.2 pooka error = ESPIPE;
2195 1.324.4.2 pooka goto out;
2196 1.324.4.2 pooka }
2197 1.324.4.2 pooka
2198 1.324.4.2 pooka offset = SCARG(uap, offset);
2199 1.324.4.2 pooka
2200 1.324.4.2 pooka /*
2201 1.324.4.2 pooka * XXX This works because no file systems actually
2202 1.324.4.2 pooka * XXX take any action on the seek operation.
2203 1.324.4.2 pooka */
2204 1.324.4.2 pooka if ((error = VOP_SEEK(vp, fp->f_offset, offset, fp->f_cred)) != 0)
2205 1.324.4.2 pooka goto out;
2206 1.324.4.2 pooka
2207 1.324.4.2 pooka /* dofileread() will unuse the descriptor for us */
2208 1.324.4.2 pooka return (dofileread(l, fd, fp, SCARG(uap, buf), SCARG(uap, nbyte),
2209 1.324.4.2 pooka &offset, 0, retval));
2210 1.324.4.2 pooka
2211 1.324.4.2 pooka out:
2212 1.324.4.2 pooka FILE_UNUSE(fp, l);
2213 1.324.4.2 pooka return (error);
2214 1.324.4.2 pooka }
2215 1.324.4.2 pooka
2216 1.324.4.2 pooka /*
2217 1.324.4.2 pooka * Positional scatter read system call.
2218 1.324.4.2 pooka */
2219 1.324.4.2 pooka int
2220 1.324.4.2 pooka sys_preadv(struct lwp *l, void *v, register_t *retval)
2221 1.324.4.2 pooka {
2222 1.324.4.2 pooka struct sys_preadv_args /* {
2223 1.324.4.2 pooka syscallarg(int) fd;
2224 1.324.4.2 pooka syscallarg(const struct iovec *) iovp;
2225 1.324.4.2 pooka syscallarg(int) iovcnt;
2226 1.324.4.2 pooka syscallarg(off_t) offset;
2227 1.324.4.2 pooka } */ *uap = v;
2228 1.324.4.2 pooka
2229 1.324.4.2 pooka return do_filereadv(l, SCARG(uap, fd), SCARG(uap, iovp),
2230 1.324.4.2 pooka SCARG(uap, iovcnt), &SCARG(uap, offset), 0, retval);
2231 1.324.4.2 pooka }
2232 1.324.4.2 pooka
2233 1.324.4.2 pooka /*
2234 1.324.4.2 pooka * Positional write system call.
2235 1.324.4.2 pooka */
2236 1.324.4.2 pooka int
2237 1.324.4.2 pooka sys_pwrite(struct lwp *l, void *v, register_t *retval)
2238 1.324.4.2 pooka {
2239 1.324.4.2 pooka struct sys_pwrite_args /* {
2240 1.324.4.2 pooka syscallarg(int) fd;
2241 1.324.4.2 pooka syscallarg(const void *) buf;
2242 1.324.4.2 pooka syscallarg(size_t) nbyte;
2243 1.324.4.2 pooka syscallarg(off_t) offset;
2244 1.324.4.2 pooka } */ *uap = v;
2245 1.324.4.2 pooka struct proc *p = l->l_proc;
2246 1.324.4.2 pooka struct filedesc *fdp = p->p_fd;
2247 1.324.4.2 pooka struct file *fp;
2248 1.324.4.2 pooka struct vnode *vp;
2249 1.324.4.2 pooka off_t offset;
2250 1.324.4.2 pooka int error, fd = SCARG(uap, fd);
2251 1.324.4.2 pooka
2252 1.324.4.2 pooka if ((fp = fd_getfile(fdp, fd)) == NULL)
2253 1.324.4.2 pooka return (EBADF);
2254 1.324.4.2 pooka
2255 1.324.4.2 pooka if ((fp->f_flag & FWRITE) == 0) {
2256 1.324.4.2 pooka simple_unlock(&fp->f_slock);
2257 1.324.4.2 pooka return (EBADF);
2258 1.324.4.2 pooka }
2259 1.324.4.2 pooka
2260 1.324.4.2 pooka FILE_USE(fp);
2261 1.324.4.2 pooka
2262 1.324.4.2 pooka vp = (struct vnode *)fp->f_data;
2263 1.324.4.2 pooka if (fp->f_type != DTYPE_VNODE || vp->v_type == VFIFO) {
2264 1.324.4.2 pooka error = ESPIPE;
2265 1.324.4.2 pooka goto out;
2266 1.324.4.2 pooka }
2267 1.324.4.2 pooka
2268 1.324.4.2 pooka offset = SCARG(uap, offset);
2269 1.324.4.2 pooka
2270 1.324.4.2 pooka /*
2271 1.324.4.2 pooka * XXX This works because no file systems actually
2272 1.324.4.2 pooka * XXX take any action on the seek operation.
2273 1.324.4.2 pooka */
2274 1.324.4.2 pooka if ((error = VOP_SEEK(vp, fp->f_offset, offset, fp->f_cred)) != 0)
2275 1.324.4.2 pooka goto out;
2276 1.324.4.2 pooka
2277 1.324.4.2 pooka /* dofilewrite() will unuse the descriptor for us */
2278 1.324.4.2 pooka return (dofilewrite(l, fd, fp, SCARG(uap, buf), SCARG(uap, nbyte),
2279 1.324.4.2 pooka &offset, 0, retval));
2280 1.324.4.2 pooka
2281 1.324.4.2 pooka out:
2282 1.324.4.2 pooka FILE_UNUSE(fp, l);
2283 1.324.4.2 pooka return (error);
2284 1.324.4.2 pooka }
2285 1.324.4.2 pooka
2286 1.324.4.2 pooka /*
2287 1.324.4.2 pooka * Positional gather write system call.
2288 1.324.4.2 pooka */
2289 1.324.4.2 pooka int
2290 1.324.4.2 pooka sys_pwritev(struct lwp *l, void *v, register_t *retval)
2291 1.324.4.2 pooka {
2292 1.324.4.2 pooka struct sys_pwritev_args /* {
2293 1.324.4.2 pooka syscallarg(int) fd;
2294 1.324.4.2 pooka syscallarg(const struct iovec *) iovp;
2295 1.324.4.2 pooka syscallarg(int) iovcnt;
2296 1.324.4.2 pooka syscallarg(off_t) offset;
2297 1.324.4.2 pooka } */ *uap = v;
2298 1.324.4.2 pooka
2299 1.324.4.2 pooka return do_filewritev(l, SCARG(uap, fd), SCARG(uap, iovp),
2300 1.324.4.2 pooka SCARG(uap, iovcnt), &SCARG(uap, offset), 0, retval);
2301 1.324.4.2 pooka }
2302 1.324.4.2 pooka
2303 1.324.4.2 pooka /*
2304 1.324.4.2 pooka * Check access permissions.
2305 1.324.4.2 pooka */
2306 1.324.4.2 pooka int
2307 1.324.4.2 pooka sys_access(struct lwp *l, void *v, register_t *retval)
2308 1.324.4.2 pooka {
2309 1.324.4.2 pooka struct sys_access_args /* {
2310 1.324.4.2 pooka syscallarg(const char *) path;
2311 1.324.4.2 pooka syscallarg(int) flags;
2312 1.324.4.2 pooka } */ *uap = v;
2313 1.324.4.2 pooka kauth_cred_t cred;
2314 1.324.4.2 pooka struct vnode *vp;
2315 1.324.4.2 pooka int error, flags;
2316 1.324.4.2 pooka struct nameidata nd;
2317 1.324.4.2 pooka
2318 1.324.4.2 pooka cred = kauth_cred_dup(l->l_cred);
2319 1.324.4.2 pooka kauth_cred_seteuid(cred, kauth_cred_getuid(l->l_cred));
2320 1.324.4.2 pooka kauth_cred_setegid(cred, kauth_cred_getgid(l->l_cred));
2321 1.324.4.2 pooka NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | TRYEMULROOT, UIO_USERSPACE,
2322 1.324.4.2 pooka SCARG(uap, path), l);
2323 1.324.4.2 pooka /* Override default credentials */
2324 1.324.4.2 pooka nd.ni_cnd.cn_cred = cred;
2325 1.324.4.2 pooka if ((error = namei(&nd)) != 0)
2326 1.324.4.2 pooka goto out;
2327 1.324.4.2 pooka vp = nd.ni_vp;
2328 1.324.4.2 pooka
2329 1.324.4.2 pooka /* Flags == 0 means only check for existence. */
2330 1.324.4.2 pooka if (SCARG(uap, flags)) {
2331 1.324.4.2 pooka flags = 0;
2332 1.324.4.2 pooka if (SCARG(uap, flags) & R_OK)
2333 1.324.4.2 pooka flags |= VREAD;
2334 1.324.4.2 pooka if (SCARG(uap, flags) & W_OK)
2335 1.324.4.2 pooka flags |= VWRITE;
2336 1.324.4.2 pooka if (SCARG(uap, flags) & X_OK)
2337 1.324.4.2 pooka flags |= VEXEC;
2338 1.324.4.2 pooka
2339 1.324.4.2 pooka error = VOP_ACCESS(vp, flags, cred, l);
2340 1.324.4.2 pooka if (!error && (flags & VWRITE))
2341 1.324.4.2 pooka error = vn_writechk(vp);
2342 1.324.4.2 pooka }
2343 1.324.4.2 pooka vput(vp);
2344 1.324.4.2 pooka out:
2345 1.324.4.2 pooka kauth_cred_free(cred);
2346 1.324.4.2 pooka return (error);
2347 1.324.4.2 pooka }
2348 1.324.4.2 pooka
2349 1.324.4.2 pooka /*
2350 1.324.4.2 pooka * Common code for all sys_stat functions, including compat versions.
2351 1.324.4.2 pooka */
2352 1.324.4.2 pooka int
2353 1.324.4.2 pooka do_sys_stat(struct lwp *l, const char *path, unsigned int nd_flags,
2354 1.324.4.2 pooka struct stat *sb)
2355 1.324.4.2 pooka {
2356 1.324.4.2 pooka int error;
2357 1.324.4.2 pooka struct nameidata nd;
2358 1.324.4.2 pooka
2359 1.324.4.2 pooka NDINIT(&nd, LOOKUP, nd_flags | LOCKLEAF | TRYEMULROOT , UIO_USERSPACE, path, l);
2360 1.324.4.2 pooka error = namei(&nd);
2361 1.324.4.2 pooka if (error != 0)
2362 1.324.4.2 pooka return error;
2363 1.324.4.2 pooka error = vn_stat(nd.ni_vp, sb, l);
2364 1.324.4.2 pooka vput(nd.ni_vp);
2365 1.324.4.2 pooka return error;
2366 1.324.4.2 pooka }
2367 1.324.4.2 pooka
2368 1.324.4.2 pooka /*
2369 1.324.4.2 pooka * Get file status; this version follows links.
2370 1.324.4.2 pooka */
2371 1.324.4.2 pooka /* ARGSUSED */
2372 1.324.4.2 pooka int
2373 1.324.4.2 pooka sys___stat30(struct lwp *l, void *v, register_t *retval)
2374 1.324.4.2 pooka {
2375 1.324.4.2 pooka struct sys___stat30_args /* {
2376 1.324.4.2 pooka syscallarg(const char *) path;
2377 1.324.4.2 pooka syscallarg(struct stat *) ub;
2378 1.324.4.2 pooka } */ *uap = v;
2379 1.324.4.2 pooka struct stat sb;
2380 1.324.4.2 pooka int error;
2381 1.324.4.2 pooka
2382 1.324.4.2 pooka error = do_sys_stat(l, SCARG(uap, path), FOLLOW, &sb);
2383 1.324.4.2 pooka if (error)
2384 1.324.4.2 pooka return error;
2385 1.324.4.2 pooka return copyout(&sb, SCARG(uap, ub), sizeof(sb));
2386 1.324.4.2 pooka }
2387 1.324.4.2 pooka
2388 1.324.4.2 pooka /*
2389 1.324.4.2 pooka * Get file status; this version does not follow links.
2390 1.324.4.2 pooka */
2391 1.324.4.2 pooka /* ARGSUSED */
2392 1.324.4.2 pooka int
2393 1.324.4.2 pooka sys___lstat30(struct lwp *l, void *v, register_t *retval)
2394 1.324.4.2 pooka {
2395 1.324.4.2 pooka struct sys___lstat30_args /* {
2396 1.324.4.2 pooka syscallarg(const char *) path;
2397 1.324.4.2 pooka syscallarg(struct stat *) ub;
2398 1.324.4.2 pooka } */ *uap = v;
2399 1.324.4.2 pooka struct stat sb;
2400 1.324.4.2 pooka int error;
2401 1.324.4.2 pooka
2402 1.324.4.2 pooka error = do_sys_stat(l, SCARG(uap, path), NOFOLLOW, &sb);
2403 1.324.4.2 pooka if (error)
2404 1.324.4.2 pooka return error;
2405 1.324.4.2 pooka return copyout(&sb, SCARG(uap, ub), sizeof(sb));
2406 1.324.4.2 pooka }
2407 1.324.4.2 pooka
2408 1.324.4.2 pooka /*
2409 1.324.4.2 pooka * Get configurable pathname variables.
2410 1.324.4.2 pooka */
2411 1.324.4.2 pooka /* ARGSUSED */
2412 1.324.4.2 pooka int
2413 1.324.4.2 pooka sys_pathconf(struct lwp *l, void *v, register_t *retval)
2414 1.324.4.2 pooka {
2415 1.324.4.2 pooka struct sys_pathconf_args /* {
2416 1.324.4.2 pooka syscallarg(const char *) path;
2417 1.324.4.2 pooka syscallarg(int) name;
2418 1.324.4.2 pooka } */ *uap = v;
2419 1.324.4.2 pooka int error;
2420 1.324.4.2 pooka struct nameidata nd;
2421 1.324.4.2 pooka
2422 1.324.4.2 pooka NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | TRYEMULROOT, UIO_USERSPACE,
2423 1.324.4.2 pooka SCARG(uap, path), l);
2424 1.324.4.2 pooka if ((error = namei(&nd)) != 0)
2425 1.324.4.2 pooka return (error);
2426 1.324.4.2 pooka error = VOP_PATHCONF(nd.ni_vp, SCARG(uap, name), retval);
2427 1.324.4.2 pooka vput(nd.ni_vp);
2428 1.324.4.2 pooka return (error);
2429 1.324.4.2 pooka }
2430 1.324.4.2 pooka
2431 1.324.4.2 pooka /*
2432 1.324.4.2 pooka * Return target name of a symbolic link.
2433 1.324.4.2 pooka */
2434 1.324.4.2 pooka /* ARGSUSED */
2435 1.324.4.2 pooka int
2436 1.324.4.2 pooka sys_readlink(struct lwp *l, void *v, register_t *retval)
2437 1.324.4.2 pooka {
2438 1.324.4.2 pooka struct sys_readlink_args /* {
2439 1.324.4.2 pooka syscallarg(const char *) path;
2440 1.324.4.2 pooka syscallarg(char *) buf;
2441 1.324.4.2 pooka syscallarg(size_t) count;
2442 1.324.4.2 pooka } */ *uap = v;
2443 1.324.4.2 pooka struct vnode *vp;
2444 1.324.4.2 pooka struct iovec aiov;
2445 1.324.4.2 pooka struct uio auio;
2446 1.324.4.2 pooka int error;
2447 1.324.4.2 pooka struct nameidata nd;
2448 1.324.4.2 pooka
2449 1.324.4.2 pooka NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | TRYEMULROOT, UIO_USERSPACE,
2450 1.324.4.2 pooka SCARG(uap, path), l);
2451 1.324.4.2 pooka if ((error = namei(&nd)) != 0)
2452 1.324.4.2 pooka return (error);
2453 1.324.4.2 pooka vp = nd.ni_vp;
2454 1.324.4.2 pooka if (vp->v_type != VLNK)
2455 1.324.4.2 pooka error = EINVAL;
2456 1.324.4.2 pooka else if (!(vp->v_mount->mnt_flag & MNT_SYMPERM) ||
2457 1.324.4.2 pooka (error = VOP_ACCESS(vp, VREAD, l->l_cred, l)) == 0) {
2458 1.324.4.2 pooka aiov.iov_base = SCARG(uap, buf);
2459 1.324.4.2 pooka aiov.iov_len = SCARG(uap, count);
2460 1.324.4.2 pooka auio.uio_iov = &aiov;
2461 1.324.4.2 pooka auio.uio_iovcnt = 1;
2462 1.324.4.2 pooka auio.uio_offset = 0;
2463 1.324.4.2 pooka auio.uio_rw = UIO_READ;
2464 1.324.4.2 pooka KASSERT(l == curlwp);
2465 1.324.4.2 pooka auio.uio_vmspace = l->l_proc->p_vmspace;
2466 1.324.4.2 pooka auio.uio_resid = SCARG(uap, count);
2467 1.324.4.2 pooka error = VOP_READLINK(vp, &auio, l->l_cred);
2468 1.324.4.2 pooka }
2469 1.324.4.2 pooka vput(vp);
2470 1.324.4.2 pooka *retval = SCARG(uap, count) - auio.uio_resid;
2471 1.324.4.2 pooka return (error);
2472 1.324.4.2 pooka }
2473 1.324.4.2 pooka
2474 1.324.4.2 pooka /*
2475 1.324.4.2 pooka * Change flags of a file given a path name.
2476 1.324.4.2 pooka */
2477 1.324.4.2 pooka /* ARGSUSED */
2478 1.324.4.2 pooka int
2479 1.324.4.2 pooka sys_chflags(struct lwp *l, void *v, register_t *retval)
2480 1.324.4.2 pooka {
2481 1.324.4.2 pooka struct sys_chflags_args /* {
2482 1.324.4.2 pooka syscallarg(const char *) path;
2483 1.324.4.2 pooka syscallarg(u_long) flags;
2484 1.324.4.2 pooka } */ *uap = v;
2485 1.324.4.2 pooka struct vnode *vp;
2486 1.324.4.2 pooka int error;
2487 1.324.4.2 pooka struct nameidata nd;
2488 1.324.4.2 pooka
2489 1.324.4.2 pooka NDINIT(&nd, LOOKUP, FOLLOW | TRYEMULROOT, UIO_USERSPACE, SCARG(uap, path), l);
2490 1.324.4.2 pooka if ((error = namei(&nd)) != 0)
2491 1.324.4.2 pooka return (error);
2492 1.324.4.2 pooka vp = nd.ni_vp;
2493 1.324.4.2 pooka error = change_flags(vp, SCARG(uap, flags), l);
2494 1.324.4.2 pooka vput(vp);
2495 1.324.4.2 pooka return (error);
2496 1.324.4.2 pooka }
2497 1.324.4.2 pooka
2498 1.324.4.2 pooka /*
2499 1.324.4.2 pooka * Change flags of a file given a file descriptor.
2500 1.324.4.2 pooka */
2501 1.324.4.2 pooka /* ARGSUSED */
2502 1.324.4.2 pooka int
2503 1.324.4.2 pooka sys_fchflags(struct lwp *l, void *v, register_t *retval)
2504 1.324.4.2 pooka {
2505 1.324.4.2 pooka struct sys_fchflags_args /* {
2506 1.324.4.2 pooka syscallarg(int) fd;
2507 1.324.4.2 pooka syscallarg(u_long) flags;
2508 1.324.4.2 pooka } */ *uap = v;
2509 1.324.4.2 pooka struct proc *p = l->l_proc;
2510 1.324.4.2 pooka struct vnode *vp;
2511 1.324.4.2 pooka struct file *fp;
2512 1.324.4.2 pooka int error;
2513 1.324.4.2 pooka
2514 1.324.4.2 pooka /* getvnode() will use the descriptor for us */
2515 1.324.4.2 pooka if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
2516 1.324.4.2 pooka return (error);
2517 1.324.4.2 pooka vp = (struct vnode *)fp->f_data;
2518 1.324.4.2 pooka error = change_flags(vp, SCARG(uap, flags), l);
2519 1.324.4.2 pooka VOP_UNLOCK(vp, 0);
2520 1.324.4.2 pooka FILE_UNUSE(fp, l);
2521 1.324.4.2 pooka return (error);
2522 1.324.4.2 pooka }
2523 1.324.4.2 pooka
2524 1.324.4.2 pooka /*
2525 1.324.4.2 pooka * Change flags of a file given a path name; this version does
2526 1.324.4.2 pooka * not follow links.
2527 1.324.4.2 pooka */
2528 1.324.4.2 pooka int
2529 1.324.4.2 pooka sys_lchflags(struct lwp *l, void *v, register_t *retval)
2530 1.324.4.2 pooka {
2531 1.324.4.2 pooka struct sys_lchflags_args /* {
2532 1.324.4.2 pooka syscallarg(const char *) path;
2533 1.324.4.2 pooka syscallarg(u_long) flags;
2534 1.324.4.2 pooka } */ *uap = v;
2535 1.324.4.2 pooka struct vnode *vp;
2536 1.324.4.2 pooka int error;
2537 1.324.4.2 pooka struct nameidata nd;
2538 1.324.4.2 pooka
2539 1.324.4.2 pooka NDINIT(&nd, LOOKUP, NOFOLLOW | TRYEMULROOT, UIO_USERSPACE, SCARG(uap, path), l);
2540 1.324.4.2 pooka if ((error = namei(&nd)) != 0)
2541 1.324.4.2 pooka return (error);
2542 1.324.4.2 pooka vp = nd.ni_vp;
2543 1.324.4.2 pooka error = change_flags(vp, SCARG(uap, flags), l);
2544 1.324.4.2 pooka vput(vp);
2545 1.324.4.2 pooka return (error);
2546 1.324.4.2 pooka }
2547 1.324.4.2 pooka
2548 1.324.4.2 pooka /*
2549 1.324.4.2 pooka * Common routine to change flags of a file.
2550 1.324.4.2 pooka */
2551 1.324.4.2 pooka int
2552 1.324.4.2 pooka change_flags(struct vnode *vp, u_long flags, struct lwp *l)
2553 1.324.4.2 pooka {
2554 1.324.4.2 pooka struct vattr vattr;
2555 1.324.4.2 pooka int error;
2556 1.324.4.2 pooka
2557 1.324.4.2 pooka VOP_LEASE(vp, l, l->l_cred, LEASE_WRITE);
2558 1.324.4.2 pooka vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
2559 1.324.4.2 pooka /*
2560 1.324.4.2 pooka * Non-superusers cannot change the flags on devices, even if they
2561 1.324.4.2 pooka * own them.
2562 1.324.4.2 pooka */
2563 1.324.4.2 pooka if (kauth_authorize_generic(l->l_cred, KAUTH_GENERIC_ISSUSER, NULL)) {
2564 1.324.4.2 pooka if ((error = VOP_GETATTR(vp, &vattr, l->l_cred, l)) != 0)
2565 1.324.4.2 pooka goto out;
2566 1.324.4.2 pooka if (vattr.va_type == VCHR || vattr.va_type == VBLK) {
2567 1.324.4.2 pooka error = EINVAL;
2568 1.324.4.2 pooka goto out;
2569 1.324.4.2 pooka }
2570 1.324.4.2 pooka }
2571 1.324.4.2 pooka VATTR_NULL(&vattr);
2572 1.324.4.2 pooka vattr.va_flags = flags;
2573 1.324.4.2 pooka error = VOP_SETATTR(vp, &vattr, l->l_cred, l);
2574 1.324.4.2 pooka out:
2575 1.324.4.2 pooka return (error);
2576 1.324.4.2 pooka }
2577 1.324.4.2 pooka
2578 1.324.4.2 pooka /*
2579 1.324.4.2 pooka * Change mode of a file given path name; this version follows links.
2580 1.324.4.2 pooka */
2581 1.324.4.2 pooka /* ARGSUSED */
2582 1.324.4.2 pooka int
2583 1.324.4.2 pooka sys_chmod(struct lwp *l, void *v, register_t *retval)
2584 1.324.4.2 pooka {
2585 1.324.4.2 pooka struct sys_chmod_args /* {
2586 1.324.4.2 pooka syscallarg(const char *) path;
2587 1.324.4.2 pooka syscallarg(int) mode;
2588 1.324.4.2 pooka } */ *uap = v;
2589 1.324.4.2 pooka int error;
2590 1.324.4.2 pooka struct nameidata nd;
2591 1.324.4.2 pooka
2592 1.324.4.2 pooka NDINIT(&nd, LOOKUP, FOLLOW | TRYEMULROOT, UIO_USERSPACE, SCARG(uap, path), l);
2593 1.324.4.2 pooka if ((error = namei(&nd)) != 0)
2594 1.324.4.2 pooka return (error);
2595 1.324.4.2 pooka
2596 1.324.4.2 pooka error = change_mode(nd.ni_vp, SCARG(uap, mode), l);
2597 1.324.4.2 pooka
2598 1.324.4.2 pooka vrele(nd.ni_vp);
2599 1.324.4.2 pooka return (error);
2600 1.324.4.2 pooka }
2601 1.324.4.2 pooka
2602 1.324.4.2 pooka /*
2603 1.324.4.2 pooka * Change mode of a file given a file descriptor.
2604 1.324.4.2 pooka */
2605 1.324.4.2 pooka /* ARGSUSED */
2606 1.324.4.2 pooka int
2607 1.324.4.2 pooka sys_fchmod(struct lwp *l, void *v, register_t *retval)
2608 1.324.4.2 pooka {
2609 1.324.4.2 pooka struct sys_fchmod_args /* {
2610 1.324.4.2 pooka syscallarg(int) fd;
2611 1.324.4.2 pooka syscallarg(int) mode;
2612 1.324.4.2 pooka } */ *uap = v;
2613 1.324.4.2 pooka struct proc *p = l->l_proc;
2614 1.324.4.2 pooka struct file *fp;
2615 1.324.4.2 pooka int error;
2616 1.324.4.2 pooka
2617 1.324.4.2 pooka /* getvnode() will use the descriptor for us */
2618 1.324.4.2 pooka if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
2619 1.324.4.2 pooka return (error);
2620 1.324.4.2 pooka
2621 1.324.4.2 pooka error = change_mode((struct vnode *)fp->f_data, SCARG(uap, mode), l);
2622 1.324.4.2 pooka FILE_UNUSE(fp, l);
2623 1.324.4.2 pooka return (error);
2624 1.324.4.2 pooka }
2625 1.324.4.2 pooka
2626 1.324.4.2 pooka /*
2627 1.324.4.2 pooka * Change mode of a file given path name; this version does not follow links.
2628 1.324.4.2 pooka */
2629 1.324.4.2 pooka /* ARGSUSED */
2630 1.324.4.2 pooka int
2631 1.324.4.2 pooka sys_lchmod(struct lwp *l, void *v, register_t *retval)
2632 1.324.4.2 pooka {
2633 1.324.4.2 pooka struct sys_lchmod_args /* {
2634 1.324.4.2 pooka syscallarg(const char *) path;
2635 1.324.4.2 pooka syscallarg(int) mode;
2636 1.324.4.2 pooka } */ *uap = v;
2637 1.324.4.2 pooka int error;
2638 1.324.4.2 pooka struct nameidata nd;
2639 1.324.4.2 pooka
2640 1.324.4.2 pooka NDINIT(&nd, LOOKUP, NOFOLLOW | TRYEMULROOT, UIO_USERSPACE, SCARG(uap, path), l);
2641 1.324.4.2 pooka if ((error = namei(&nd)) != 0)
2642 1.324.4.2 pooka return (error);
2643 1.324.4.2 pooka
2644 1.324.4.2 pooka error = change_mode(nd.ni_vp, SCARG(uap, mode), l);
2645 1.324.4.2 pooka
2646 1.324.4.2 pooka vrele(nd.ni_vp);
2647 1.324.4.2 pooka return (error);
2648 1.324.4.2 pooka }
2649 1.324.4.2 pooka
2650 1.324.4.2 pooka /*
2651 1.324.4.2 pooka * Common routine to set mode given a vnode.
2652 1.324.4.2 pooka */
2653 1.324.4.2 pooka static int
2654 1.324.4.2 pooka change_mode(struct vnode *vp, int mode, struct lwp *l)
2655 1.324.4.2 pooka {
2656 1.324.4.2 pooka struct vattr vattr;
2657 1.324.4.2 pooka int error;
2658 1.324.4.2 pooka
2659 1.324.4.2 pooka VOP_LEASE(vp, l, l->l_cred, LEASE_WRITE);
2660 1.324.4.2 pooka vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
2661 1.324.4.2 pooka VATTR_NULL(&vattr);
2662 1.324.4.2 pooka vattr.va_mode = mode & ALLPERMS;
2663 1.324.4.2 pooka error = VOP_SETATTR(vp, &vattr, l->l_cred, l);
2664 1.324.4.2 pooka VOP_UNLOCK(vp, 0);
2665 1.324.4.2 pooka return (error);
2666 1.324.4.2 pooka }
2667 1.324.4.2 pooka
2668 1.324.4.2 pooka /*
2669 1.324.4.2 pooka * Set ownership given a path name; this version follows links.
2670 1.324.4.2 pooka */
2671 1.324.4.2 pooka /* ARGSUSED */
2672 1.324.4.2 pooka int
2673 1.324.4.2 pooka sys_chown(struct lwp *l, void *v, register_t *retval)
2674 1.324.4.2 pooka {
2675 1.324.4.2 pooka struct sys_chown_args /* {
2676 1.324.4.2 pooka syscallarg(const char *) path;
2677 1.324.4.2 pooka syscallarg(uid_t) uid;
2678 1.324.4.2 pooka syscallarg(gid_t) gid;
2679 1.324.4.2 pooka } */ *uap = v;
2680 1.324.4.2 pooka int error;
2681 1.324.4.2 pooka struct nameidata nd;
2682 1.324.4.2 pooka
2683 1.324.4.2 pooka NDINIT(&nd, LOOKUP, FOLLOW | TRYEMULROOT, UIO_USERSPACE, SCARG(uap, path), l);
2684 1.324.4.2 pooka if ((error = namei(&nd)) != 0)
2685 1.324.4.2 pooka return (error);
2686 1.324.4.2 pooka
2687 1.324.4.2 pooka error = change_owner(nd.ni_vp, SCARG(uap, uid), SCARG(uap, gid), l, 0);
2688 1.324.4.2 pooka
2689 1.324.4.2 pooka vrele(nd.ni_vp);
2690 1.324.4.2 pooka return (error);
2691 1.324.4.2 pooka }
2692 1.324.4.2 pooka
2693 1.324.4.2 pooka /*
2694 1.324.4.2 pooka * Set ownership given a path name; this version follows links.
2695 1.324.4.2 pooka * Provides POSIX semantics.
2696 1.324.4.2 pooka */
2697 1.324.4.2 pooka /* ARGSUSED */
2698 1.324.4.2 pooka int
2699 1.324.4.2 pooka sys___posix_chown(struct lwp *l, void *v, register_t *retval)
2700 1.324.4.2 pooka {
2701 1.324.4.2 pooka struct sys_chown_args /* {
2702 1.324.4.2 pooka syscallarg(const char *) path;
2703 1.324.4.2 pooka syscallarg(uid_t) uid;
2704 1.324.4.2 pooka syscallarg(gid_t) gid;
2705 1.324.4.2 pooka } */ *uap = v;
2706 1.324.4.2 pooka int error;
2707 1.324.4.2 pooka struct nameidata nd;
2708 1.324.4.2 pooka
2709 1.324.4.2 pooka NDINIT(&nd, LOOKUP, FOLLOW | TRYEMULROOT, UIO_USERSPACE, SCARG(uap, path), l);
2710 1.324.4.2 pooka if ((error = namei(&nd)) != 0)
2711 1.324.4.2 pooka return (error);
2712 1.324.4.2 pooka
2713 1.324.4.2 pooka error = change_owner(nd.ni_vp, SCARG(uap, uid), SCARG(uap, gid), l, 1);
2714 1.324.4.2 pooka
2715 1.324.4.2 pooka vrele(nd.ni_vp);
2716 1.324.4.2 pooka return (error);
2717 1.324.4.2 pooka }
2718 1.324.4.2 pooka
2719 1.324.4.2 pooka /*
2720 1.324.4.2 pooka * Set ownership given a file descriptor.
2721 1.324.4.2 pooka */
2722 1.324.4.2 pooka /* ARGSUSED */
2723 1.324.4.2 pooka int
2724 1.324.4.2 pooka sys_fchown(struct lwp *l, void *v, register_t *retval)
2725 1.324.4.2 pooka {
2726 1.324.4.2 pooka struct sys_fchown_args /* {
2727 1.324.4.2 pooka syscallarg(int) fd;
2728 1.324.4.2 pooka syscallarg(uid_t) uid;
2729 1.324.4.2 pooka syscallarg(gid_t) gid;
2730 1.324.4.2 pooka } */ *uap = v;
2731 1.324.4.2 pooka struct proc *p = l->l_proc;
2732 1.324.4.2 pooka int error;
2733 1.324.4.2 pooka struct file *fp;
2734 1.324.4.2 pooka
2735 1.324.4.2 pooka /* getvnode() will use the descriptor for us */
2736 1.324.4.2 pooka if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
2737 1.324.4.2 pooka return (error);
2738 1.324.4.2 pooka
2739 1.324.4.2 pooka error = change_owner((struct vnode *)fp->f_data, SCARG(uap, uid),
2740 1.324.4.2 pooka SCARG(uap, gid), l, 0);
2741 1.324.4.2 pooka FILE_UNUSE(fp, l);
2742 1.324.4.2 pooka return (error);
2743 1.324.4.2 pooka }
2744 1.324.4.2 pooka
2745 1.324.4.2 pooka /*
2746 1.324.4.2 pooka * Set ownership given a file descriptor, providing POSIX/XPG semantics.
2747 1.324.4.2 pooka */
2748 1.324.4.2 pooka /* ARGSUSED */
2749 1.324.4.2 pooka int
2750 1.324.4.2 pooka sys___posix_fchown(struct lwp *l, void *v, register_t *retval)
2751 1.324.4.2 pooka {
2752 1.324.4.2 pooka struct sys_fchown_args /* {
2753 1.324.4.2 pooka syscallarg(int) fd;
2754 1.324.4.2 pooka syscallarg(uid_t) uid;
2755 1.324.4.2 pooka syscallarg(gid_t) gid;
2756 1.324.4.2 pooka } */ *uap = v;
2757 1.324.4.2 pooka struct proc *p = l->l_proc;
2758 1.324.4.2 pooka int error;
2759 1.324.4.2 pooka struct file *fp;
2760 1.324.4.2 pooka
2761 1.324.4.2 pooka /* getvnode() will use the descriptor for us */
2762 1.324.4.2 pooka if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
2763 1.324.4.2 pooka return (error);
2764 1.324.4.2 pooka
2765 1.324.4.2 pooka error = change_owner((struct vnode *)fp->f_data, SCARG(uap, uid),
2766 1.324.4.2 pooka SCARG(uap, gid), l, 1);
2767 1.324.4.2 pooka FILE_UNUSE(fp, l);
2768 1.324.4.2 pooka return (error);
2769 1.324.4.2 pooka }
2770 1.324.4.2 pooka
2771 1.324.4.2 pooka /*
2772 1.324.4.2 pooka * Set ownership given a path name; this version does not follow links.
2773 1.324.4.2 pooka */
2774 1.324.4.2 pooka /* ARGSUSED */
2775 1.324.4.2 pooka int
2776 1.324.4.2 pooka sys_lchown(struct lwp *l, void *v, register_t *retval)
2777 1.324.4.2 pooka {
2778 1.324.4.2 pooka struct sys_lchown_args /* {
2779 1.324.4.2 pooka syscallarg(const char *) path;
2780 1.324.4.2 pooka syscallarg(uid_t) uid;
2781 1.324.4.2 pooka syscallarg(gid_t) gid;
2782 1.324.4.2 pooka } */ *uap = v;
2783 1.324.4.2 pooka int error;
2784 1.324.4.2 pooka struct nameidata nd;
2785 1.324.4.2 pooka
2786 1.324.4.2 pooka NDINIT(&nd, LOOKUP, NOFOLLOW | TRYEMULROOT, UIO_USERSPACE, SCARG(uap, path), l);
2787 1.324.4.2 pooka if ((error = namei(&nd)) != 0)
2788 1.324.4.2 pooka return (error);
2789 1.324.4.2 pooka
2790 1.324.4.2 pooka error = change_owner(nd.ni_vp, SCARG(uap, uid), SCARG(uap, gid), l, 0);
2791 1.324.4.2 pooka
2792 1.324.4.2 pooka vrele(nd.ni_vp);
2793 1.324.4.2 pooka return (error);
2794 1.324.4.2 pooka }
2795 1.324.4.2 pooka
2796 1.324.4.2 pooka /*
2797 1.324.4.2 pooka * Set ownership given a path name; this version does not follow links.
2798 1.324.4.2 pooka * Provides POSIX/XPG semantics.
2799 1.324.4.2 pooka */
2800 1.324.4.2 pooka /* ARGSUSED */
2801 1.324.4.2 pooka int
2802 1.324.4.2 pooka sys___posix_lchown(struct lwp *l, void *v, register_t *retval)
2803 1.324.4.2 pooka {
2804 1.324.4.2 pooka struct sys_lchown_args /* {
2805 1.324.4.2 pooka syscallarg(const char *) path;
2806 1.324.4.2 pooka syscallarg(uid_t) uid;
2807 1.324.4.2 pooka syscallarg(gid_t) gid;
2808 1.324.4.2 pooka } */ *uap = v;
2809 1.324.4.2 pooka int error;
2810 1.324.4.2 pooka struct nameidata nd;
2811 1.324.4.2 pooka
2812 1.324.4.2 pooka NDINIT(&nd, LOOKUP, NOFOLLOW | TRYEMULROOT, UIO_USERSPACE, SCARG(uap, path), l);
2813 1.324.4.2 pooka if ((error = namei(&nd)) != 0)
2814 1.324.4.2 pooka return (error);
2815 1.324.4.2 pooka
2816 1.324.4.2 pooka error = change_owner(nd.ni_vp, SCARG(uap, uid), SCARG(uap, gid), l, 1);
2817 1.324.4.2 pooka
2818 1.324.4.2 pooka vrele(nd.ni_vp);
2819 1.324.4.2 pooka return (error);
2820 1.324.4.2 pooka }
2821 1.324.4.2 pooka
2822 1.324.4.2 pooka /*
2823 1.324.4.2 pooka * Common routine to set ownership given a vnode.
2824 1.324.4.2 pooka */
2825 1.324.4.2 pooka static int
2826 1.324.4.2 pooka change_owner(struct vnode *vp, uid_t uid, gid_t gid, struct lwp *l,
2827 1.324.4.2 pooka int posix_semantics)
2828 1.324.4.2 pooka {
2829 1.324.4.2 pooka struct vattr vattr;
2830 1.324.4.2 pooka mode_t newmode;
2831 1.324.4.2 pooka int error;
2832 1.324.4.2 pooka
2833 1.324.4.2 pooka VOP_LEASE(vp, l, l->l_cred, LEASE_WRITE);
2834 1.324.4.2 pooka vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
2835 1.324.4.2 pooka if ((error = VOP_GETATTR(vp, &vattr, l->l_cred, l)) != 0)
2836 1.324.4.2 pooka goto out;
2837 1.324.4.2 pooka
2838 1.324.4.2 pooka #define CHANGED(x) ((int)(x) != -1)
2839 1.324.4.2 pooka newmode = vattr.va_mode;
2840 1.324.4.2 pooka if (posix_semantics) {
2841 1.324.4.2 pooka /*
2842 1.324.4.2 pooka * POSIX/XPG semantics: if the caller is not the super-user,
2843 1.324.4.2 pooka * clear set-user-id and set-group-id bits. Both POSIX and
2844 1.324.4.2 pooka * the XPG consider the behaviour for calls by the super-user
2845 1.324.4.2 pooka * implementation-defined; we leave the set-user-id and set-
2846 1.324.4.2 pooka * group-id settings intact in that case.
2847 1.324.4.2 pooka */
2848 1.324.4.2 pooka if (kauth_authorize_generic(l->l_cred, KAUTH_GENERIC_ISSUSER,
2849 1.324.4.2 pooka NULL) != 0)
2850 1.324.4.2 pooka newmode &= ~(S_ISUID | S_ISGID);
2851 1.324.4.2 pooka } else {
2852 1.324.4.2 pooka /*
2853 1.324.4.2 pooka * NetBSD semantics: when changing owner and/or group,
2854 1.324.4.2 pooka * clear the respective bit(s).
2855 1.324.4.2 pooka */
2856 1.324.4.2 pooka if (CHANGED(uid))
2857 1.324.4.2 pooka newmode &= ~S_ISUID;
2858 1.324.4.2 pooka if (CHANGED(gid))
2859 1.324.4.2 pooka newmode &= ~S_ISGID;
2860 1.324.4.2 pooka }
2861 1.324.4.2 pooka /* Update va_mode iff altered. */
2862 1.324.4.2 pooka if (vattr.va_mode == newmode)
2863 1.324.4.2 pooka newmode = VNOVAL;
2864 1.324.4.2 pooka
2865 1.324.4.2 pooka VATTR_NULL(&vattr);
2866 1.324.4.2 pooka vattr.va_uid = CHANGED(uid) ? uid : (uid_t)VNOVAL;
2867 1.324.4.2 pooka vattr.va_gid = CHANGED(gid) ? gid : (gid_t)VNOVAL;
2868 1.324.4.2 pooka vattr.va_mode = newmode;
2869 1.324.4.2 pooka error = VOP_SETATTR(vp, &vattr, l->l_cred, l);
2870 1.324.4.2 pooka #undef CHANGED
2871 1.324.4.2 pooka
2872 1.324.4.2 pooka out:
2873 1.324.4.2 pooka VOP_UNLOCK(vp, 0);
2874 1.324.4.2 pooka return (error);
2875 1.324.4.2 pooka }
2876 1.324.4.2 pooka
2877 1.324.4.2 pooka /*
2878 1.324.4.2 pooka * Set the access and modification times given a path name; this
2879 1.324.4.2 pooka * version follows links.
2880 1.324.4.2 pooka */
2881 1.324.4.2 pooka /* ARGSUSED */
2882 1.324.4.2 pooka int
2883 1.324.4.2 pooka sys_utimes(struct lwp *l, void *v, register_t *retval)
2884 1.324.4.2 pooka {
2885 1.324.4.2 pooka struct sys_utimes_args /* {
2886 1.324.4.2 pooka syscallarg(const char *) path;
2887 1.324.4.2 pooka syscallarg(const struct timeval *) tptr;
2888 1.324.4.2 pooka } */ *uap = v;
2889 1.324.4.2 pooka
2890 1.324.4.2 pooka return do_sys_utimes(l, NULL, SCARG(uap, path), FOLLOW,
2891 1.324.4.2 pooka SCARG(uap, tptr), UIO_USERSPACE);
2892 1.324.4.2 pooka }
2893 1.324.4.2 pooka
2894 1.324.4.2 pooka /*
2895 1.324.4.2 pooka * Set the access and modification times given a file descriptor.
2896 1.324.4.2 pooka */
2897 1.324.4.2 pooka /* ARGSUSED */
2898 1.324.4.2 pooka int
2899 1.324.4.2 pooka sys_futimes(struct lwp *l, void *v, register_t *retval)
2900 1.324.4.2 pooka {
2901 1.324.4.2 pooka struct sys_futimes_args /* {
2902 1.324.4.2 pooka syscallarg(int) fd;
2903 1.324.4.2 pooka syscallarg(const struct timeval *) tptr;
2904 1.324.4.2 pooka } */ *uap = v;
2905 1.324.4.2 pooka int error;
2906 1.324.4.2 pooka struct file *fp;
2907 1.324.4.2 pooka
2908 1.324.4.2 pooka /* getvnode() will use the descriptor for us */
2909 1.324.4.2 pooka if ((error = getvnode(l->l_proc->p_fd, SCARG(uap, fd), &fp)) != 0)
2910 1.324.4.2 pooka return (error);
2911 1.324.4.2 pooka
2912 1.324.4.2 pooka error = do_sys_utimes(l, fp->f_data, NULL, 0,
2913 1.324.4.2 pooka SCARG(uap, tptr), UIO_USERSPACE);
2914 1.324.4.2 pooka
2915 1.324.4.2 pooka FILE_UNUSE(fp, l);
2916 1.324.4.2 pooka return (error);
2917 1.324.4.2 pooka }
2918 1.324.4.2 pooka
2919 1.324.4.2 pooka /*
2920 1.324.4.2 pooka * Set the access and modification times given a path name; this
2921 1.324.4.2 pooka * version does not follow links.
2922 1.324.4.2 pooka */
2923 1.324.4.2 pooka int
2924 1.324.4.2 pooka sys_lutimes(struct lwp *l, void *v, register_t *retval)
2925 1.324.4.2 pooka {
2926 1.324.4.2 pooka struct sys_lutimes_args /* {
2927 1.324.4.2 pooka syscallarg(const char *) path;
2928 1.324.4.2 pooka syscallarg(const struct timeval *) tptr;
2929 1.324.4.2 pooka } */ *uap = v;
2930 1.324.4.2 pooka
2931 1.324.4.2 pooka return do_sys_utimes(l, NULL, SCARG(uap, path), NOFOLLOW,
2932 1.324.4.2 pooka SCARG(uap, tptr), UIO_USERSPACE);
2933 1.324.4.2 pooka }
2934 1.324.4.2 pooka
2935 1.324.4.2 pooka /*
2936 1.324.4.2 pooka * Common routine to set access and modification times given a vnode.
2937 1.324.4.2 pooka */
2938 1.324.4.2 pooka int
2939 1.324.4.2 pooka do_sys_utimes(struct lwp *l, struct vnode *vp, const char *path, int flag,
2940 1.324.4.2 pooka const struct timeval *tptr, enum uio_seg seg)
2941 1.324.4.2 pooka {
2942 1.324.4.2 pooka struct vattr vattr;
2943 1.324.4.2 pooka struct nameidata nd;
2944 1.324.4.2 pooka int error;
2945 1.324.4.2 pooka
2946 1.324.4.2 pooka VATTR_NULL(&vattr);
2947 1.324.4.2 pooka if (tptr == NULL) {
2948 1.324.4.2 pooka nanotime(&vattr.va_atime);
2949 1.324.4.2 pooka vattr.va_mtime = vattr.va_atime;
2950 1.324.4.2 pooka vattr.va_vaflags |= VA_UTIMES_NULL;
2951 1.324.4.2 pooka } else {
2952 1.324.4.2 pooka struct timeval tv[2];
2953 1.324.4.2 pooka
2954 1.324.4.2 pooka if (seg != UIO_SYSSPACE) {
2955 1.324.4.2 pooka error = copyin(tptr, &tv, sizeof (tv));
2956 1.324.4.2 pooka if (error != 0)
2957 1.324.4.2 pooka return error;
2958 1.324.4.2 pooka tptr = tv;
2959 1.324.4.2 pooka }
2960 1.324.4.2 pooka TIMEVAL_TO_TIMESPEC(tptr, &vattr.va_atime);
2961 1.324.4.2 pooka TIMEVAL_TO_TIMESPEC(tptr + 1, &vattr.va_mtime);
2962 1.324.4.2 pooka }
2963 1.324.4.2 pooka
2964 1.324.4.2 pooka if (vp == NULL) {
2965 1.324.4.2 pooka NDINIT(&nd, LOOKUP, flag | TRYEMULROOT, UIO_USERSPACE, path, l);
2966 1.324.4.2 pooka if ((error = namei(&nd)) != 0)
2967 1.324.4.2 pooka return (error);
2968 1.324.4.2 pooka vp = nd.ni_vp;
2969 1.324.4.2 pooka } else
2970 1.324.4.2 pooka nd.ni_vp = NULL;
2971 1.324.4.2 pooka
2972 1.324.4.2 pooka VOP_LEASE(vp, l, l->l_cred, LEASE_WRITE);
2973 1.324.4.2 pooka vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
2974 1.324.4.2 pooka error = VOP_SETATTR(vp, &vattr, l->l_cred, l);
2975 1.324.4.2 pooka VOP_UNLOCK(vp, 0);
2976 1.324.4.2 pooka
2977 1.324.4.2 pooka if (nd.ni_vp != NULL)
2978 1.324.4.2 pooka vrele(nd.ni_vp);
2979 1.324.4.2 pooka
2980 1.324.4.2 pooka return (error);
2981 1.324.4.2 pooka }
2982 1.324.4.2 pooka
2983 1.324.4.2 pooka /*
2984 1.324.4.2 pooka * Truncate a file given its path name.
2985 1.324.4.2 pooka */
2986 1.324.4.2 pooka /* ARGSUSED */
2987 1.324.4.2 pooka int
2988 1.324.4.2 pooka sys_truncate(struct lwp *l, void *v, register_t *retval)
2989 1.324.4.2 pooka {
2990 1.324.4.2 pooka struct sys_truncate_args /* {
2991 1.324.4.2 pooka syscallarg(const char *) path;
2992 1.324.4.2 pooka syscallarg(int) pad;
2993 1.324.4.2 pooka syscallarg(off_t) length;
2994 1.324.4.2 pooka } */ *uap = v;
2995 1.324.4.2 pooka struct vnode *vp;
2996 1.324.4.2 pooka struct vattr vattr;
2997 1.324.4.2 pooka int error;
2998 1.324.4.2 pooka struct nameidata nd;
2999 1.324.4.2 pooka
3000 1.324.4.2 pooka NDINIT(&nd, LOOKUP, FOLLOW | TRYEMULROOT, UIO_USERSPACE, SCARG(uap, path), l);
3001 1.324.4.2 pooka if ((error = namei(&nd)) != 0)
3002 1.324.4.2 pooka return (error);
3003 1.324.4.2 pooka vp = nd.ni_vp;
3004 1.324.4.2 pooka VOP_LEASE(vp, l, l->l_cred, LEASE_WRITE);
3005 1.324.4.2 pooka vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
3006 1.324.4.2 pooka if (vp->v_type == VDIR)
3007 1.324.4.2 pooka error = EISDIR;
3008 1.324.4.2 pooka else if ((error = vn_writechk(vp)) == 0 &&
3009 1.324.4.2 pooka (error = VOP_ACCESS(vp, VWRITE, l->l_cred, l)) == 0) {
3010 1.324.4.2 pooka VATTR_NULL(&vattr);
3011 1.324.4.2 pooka vattr.va_size = SCARG(uap, length);
3012 1.324.4.2 pooka error = VOP_SETATTR(vp, &vattr, l->l_cred, l);
3013 1.324.4.2 pooka }
3014 1.324.4.2 pooka vput(vp);
3015 1.324.4.2 pooka return (error);
3016 1.324.4.2 pooka }
3017 1.324.4.2 pooka
3018 1.324.4.2 pooka /*
3019 1.324.4.2 pooka * Truncate a file given a file descriptor.
3020 1.324.4.2 pooka */
3021 1.324.4.2 pooka /* ARGSUSED */
3022 1.324.4.2 pooka int
3023 1.324.4.2 pooka sys_ftruncate(struct lwp *l, void *v, register_t *retval)
3024 1.324.4.2 pooka {
3025 1.324.4.2 pooka struct sys_ftruncate_args /* {
3026 1.324.4.2 pooka syscallarg(int) fd;
3027 1.324.4.2 pooka syscallarg(int) pad;
3028 1.324.4.2 pooka syscallarg(off_t) length;
3029 1.324.4.2 pooka } */ *uap = v;
3030 1.324.4.2 pooka struct proc *p = l->l_proc;
3031 1.324.4.2 pooka struct vattr vattr;
3032 1.324.4.2 pooka struct vnode *vp;
3033 1.324.4.2 pooka struct file *fp;
3034 1.324.4.2 pooka int error;
3035 1.324.4.2 pooka
3036 1.324.4.2 pooka /* getvnode() will use the descriptor for us */
3037 1.324.4.2 pooka if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
3038 1.324.4.2 pooka return (error);
3039 1.324.4.2 pooka if ((fp->f_flag & FWRITE) == 0) {
3040 1.324.4.2 pooka error = EINVAL;
3041 1.324.4.2 pooka goto out;
3042 1.324.4.2 pooka }
3043 1.324.4.2 pooka vp = (struct vnode *)fp->f_data;
3044 1.324.4.2 pooka VOP_LEASE(vp, l, l->l_cred, LEASE_WRITE);
3045 1.324.4.2 pooka vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
3046 1.324.4.2 pooka if (vp->v_type == VDIR)
3047 1.324.4.2 pooka error = EISDIR;
3048 1.324.4.2 pooka else if ((error = vn_writechk(vp)) == 0) {
3049 1.324.4.2 pooka VATTR_NULL(&vattr);
3050 1.324.4.2 pooka vattr.va_size = SCARG(uap, length);
3051 1.324.4.2 pooka error = VOP_SETATTR(vp, &vattr, fp->f_cred, l);
3052 1.324.4.2 pooka }
3053 1.324.4.2 pooka VOP_UNLOCK(vp, 0);
3054 1.324.4.2 pooka out:
3055 1.324.4.2 pooka FILE_UNUSE(fp, l);
3056 1.324.4.2 pooka return (error);
3057 1.324.4.2 pooka }
3058 1.324.4.2 pooka
3059 1.324.4.2 pooka /*
3060 1.324.4.2 pooka * Sync an open file.
3061 1.324.4.2 pooka */
3062 1.324.4.2 pooka /* ARGSUSED */
3063 1.324.4.2 pooka int
3064 1.324.4.2 pooka sys_fsync(struct lwp *l, void *v, register_t *retval)
3065 1.324.4.2 pooka {
3066 1.324.4.2 pooka struct sys_fsync_args /* {
3067 1.324.4.2 pooka syscallarg(int) fd;
3068 1.324.4.2 pooka } */ *uap = v;
3069 1.324.4.2 pooka struct proc *p = l->l_proc;
3070 1.324.4.2 pooka struct vnode *vp;
3071 1.324.4.2 pooka struct file *fp;
3072 1.324.4.2 pooka int error;
3073 1.324.4.2 pooka
3074 1.324.4.2 pooka /* getvnode() will use the descriptor for us */
3075 1.324.4.2 pooka if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
3076 1.324.4.2 pooka return (error);
3077 1.324.4.2 pooka vp = (struct vnode *)fp->f_data;
3078 1.324.4.2 pooka vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
3079 1.324.4.2 pooka error = VOP_FSYNC(vp, fp->f_cred, FSYNC_WAIT, 0, 0, l);
3080 1.324.4.2 pooka if (error == 0 && bioops.io_fsync != NULL &&
3081 1.324.4.2 pooka vp->v_mount && (vp->v_mount->mnt_flag & MNT_SOFTDEP))
3082 1.324.4.2 pooka (*bioops.io_fsync)(vp, 0);
3083 1.324.4.2 pooka VOP_UNLOCK(vp, 0);
3084 1.324.4.2 pooka FILE_UNUSE(fp, l);
3085 1.324.4.2 pooka return (error);
3086 1.324.4.2 pooka }
3087 1.324.4.2 pooka
3088 1.324.4.2 pooka /*
3089 1.324.4.2 pooka * Sync a range of file data. API modeled after that found in AIX.
3090 1.324.4.2 pooka *
3091 1.324.4.2 pooka * FDATASYNC indicates that we need only save enough metadata to be able
3092 1.324.4.2 pooka * to re-read the written data. Note we duplicate AIX's requirement that
3093 1.324.4.2 pooka * the file be open for writing.
3094 1.324.4.2 pooka */
3095 1.324.4.2 pooka /* ARGSUSED */
3096 1.324.4.2 pooka int
3097 1.324.4.2 pooka sys_fsync_range(struct lwp *l, void *v, register_t *retval)
3098 1.324.4.2 pooka {
3099 1.324.4.2 pooka struct sys_fsync_range_args /* {
3100 1.324.4.2 pooka syscallarg(int) fd;
3101 1.324.4.2 pooka syscallarg(int) flags;
3102 1.324.4.2 pooka syscallarg(off_t) start;
3103 1.324.4.2 pooka syscallarg(off_t) length;
3104 1.324.4.2 pooka } */ *uap = v;
3105 1.324.4.2 pooka struct proc *p = l->l_proc;
3106 1.324.4.2 pooka struct vnode *vp;
3107 1.324.4.2 pooka struct file *fp;
3108 1.324.4.2 pooka int flags, nflags;
3109 1.324.4.2 pooka off_t s, e, len;
3110 1.324.4.2 pooka int error;
3111 1.324.4.2 pooka
3112 1.324.4.2 pooka /* getvnode() will use the descriptor for us */
3113 1.324.4.2 pooka if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
3114 1.324.4.2 pooka return (error);
3115 1.324.4.2 pooka
3116 1.324.4.2 pooka if ((fp->f_flag & FWRITE) == 0) {
3117 1.324.4.2 pooka error = EBADF;
3118 1.324.4.2 pooka goto out;
3119 1.324.4.2 pooka }
3120 1.324.4.2 pooka
3121 1.324.4.2 pooka flags = SCARG(uap, flags);
3122 1.324.4.2 pooka if (((flags & (FDATASYNC | FFILESYNC)) == 0) ||
3123 1.324.4.2 pooka ((~flags & (FDATASYNC | FFILESYNC)) == 0)) {
3124 1.324.4.2 pooka error = EINVAL;
3125 1.324.4.2 pooka goto out;
3126 1.324.4.2 pooka }
3127 1.324.4.2 pooka /* Now set up the flags for value(s) to pass to VOP_FSYNC() */
3128 1.324.4.2 pooka if (flags & FDATASYNC)
3129 1.324.4.2 pooka nflags = FSYNC_DATAONLY | FSYNC_WAIT;
3130 1.324.4.2 pooka else
3131 1.324.4.2 pooka nflags = FSYNC_WAIT;
3132 1.324.4.2 pooka if (flags & FDISKSYNC)
3133 1.324.4.2 pooka nflags |= FSYNC_CACHE;
3134 1.324.4.2 pooka
3135 1.324.4.2 pooka len = SCARG(uap, length);
3136 1.324.4.2 pooka /* If length == 0, we do the whole file, and s = l = 0 will do that */
3137 1.324.4.2 pooka if (len) {
3138 1.324.4.2 pooka s = SCARG(uap, start);
3139 1.324.4.2 pooka e = s + len;
3140 1.324.4.2 pooka if (e < s) {
3141 1.324.4.2 pooka error = EINVAL;
3142 1.324.4.2 pooka goto out;
3143 1.324.4.2 pooka }
3144 1.324.4.2 pooka } else {
3145 1.324.4.2 pooka e = 0;
3146 1.324.4.2 pooka s = 0;
3147 1.324.4.2 pooka }
3148 1.324.4.2 pooka
3149 1.324.4.2 pooka vp = (struct vnode *)fp->f_data;
3150 1.324.4.2 pooka vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
3151 1.324.4.2 pooka error = VOP_FSYNC(vp, fp->f_cred, nflags, s, e, l);
3152 1.324.4.2 pooka
3153 1.324.4.2 pooka if (error == 0 && bioops.io_fsync != NULL &&
3154 1.324.4.2 pooka vp->v_mount && (vp->v_mount->mnt_flag & MNT_SOFTDEP))
3155 1.324.4.2 pooka (*bioops.io_fsync)(vp, nflags);
3156 1.324.4.2 pooka
3157 1.324.4.2 pooka VOP_UNLOCK(vp, 0);
3158 1.324.4.2 pooka out:
3159 1.324.4.2 pooka FILE_UNUSE(fp, l);
3160 1.324.4.2 pooka return (error);
3161 1.324.4.2 pooka }
3162 1.324.4.2 pooka
3163 1.324.4.2 pooka /*
3164 1.324.4.2 pooka * Sync the data of an open file.
3165 1.324.4.2 pooka */
3166 1.324.4.2 pooka /* ARGSUSED */
3167 1.324.4.2 pooka int
3168 1.324.4.2 pooka sys_fdatasync(struct lwp *l, void *v, register_t *retval)
3169 1.324.4.2 pooka {
3170 1.324.4.2 pooka struct sys_fdatasync_args /* {
3171 1.324.4.2 pooka syscallarg(int) fd;
3172 1.324.4.2 pooka } */ *uap = v;
3173 1.324.4.2 pooka struct proc *p = l->l_proc;
3174 1.324.4.2 pooka struct vnode *vp;
3175 1.324.4.2 pooka struct file *fp;
3176 1.324.4.2 pooka int error;
3177 1.324.4.2 pooka
3178 1.324.4.2 pooka /* getvnode() will use the descriptor for us */
3179 1.324.4.2 pooka if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
3180 1.324.4.2 pooka return (error);
3181 1.324.4.2 pooka if ((fp->f_flag & FWRITE) == 0) {
3182 1.324.4.2 pooka FILE_UNUSE(fp, l);
3183 1.324.4.2 pooka return (EBADF);
3184 1.324.4.2 pooka }
3185 1.324.4.2 pooka vp = (struct vnode *)fp->f_data;
3186 1.324.4.2 pooka vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
3187 1.324.4.2 pooka error = VOP_FSYNC(vp, fp->f_cred, FSYNC_WAIT|FSYNC_DATAONLY, 0, 0, l);
3188 1.324.4.2 pooka VOP_UNLOCK(vp, 0);
3189 1.324.4.2 pooka FILE_UNUSE(fp, l);
3190 1.324.4.2 pooka return (error);
3191 1.324.4.2 pooka }
3192 1.324.4.2 pooka
3193 1.324.4.2 pooka /*
3194 1.324.4.2 pooka * Rename files, (standard) BSD semantics frontend.
3195 1.324.4.2 pooka */
3196 1.324.4.2 pooka /* ARGSUSED */
3197 1.324.4.2 pooka int
3198 1.324.4.2 pooka sys_rename(struct lwp *l, void *v, register_t *retval)
3199 1.324.4.2 pooka {
3200 1.324.4.2 pooka struct sys_rename_args /* {
3201 1.324.4.2 pooka syscallarg(const char *) from;
3202 1.324.4.2 pooka syscallarg(const char *) to;
3203 1.324.4.2 pooka } */ *uap = v;
3204 1.324.4.2 pooka
3205 1.324.4.2 pooka return (rename_files(SCARG(uap, from), SCARG(uap, to), l, 0));
3206 1.324.4.2 pooka }
3207 1.324.4.2 pooka
3208 1.324.4.2 pooka /*
3209 1.324.4.2 pooka * Rename files, POSIX semantics frontend.
3210 1.324.4.2 pooka */
3211 1.324.4.2 pooka /* ARGSUSED */
3212 1.324.4.2 pooka int
3213 1.324.4.2 pooka sys___posix_rename(struct lwp *l, void *v, register_t *retval)
3214 1.324.4.2 pooka {
3215 1.324.4.2 pooka struct sys___posix_rename_args /* {
3216 1.324.4.2 pooka syscallarg(const char *) from;
3217 1.324.4.2 pooka syscallarg(const char *) to;
3218 1.324.4.2 pooka } */ *uap = v;
3219 1.324.4.2 pooka
3220 1.324.4.2 pooka return (rename_files(SCARG(uap, from), SCARG(uap, to), l, 1));
3221 1.324.4.2 pooka }
3222 1.324.4.2 pooka
3223 1.324.4.2 pooka /*
3224 1.324.4.2 pooka * Rename files. Source and destination must either both be directories,
3225 1.324.4.2 pooka * or both not be directories. If target is a directory, it must be empty.
3226 1.324.4.2 pooka * If `from' and `to' refer to the same object, the value of the `retain'
3227 1.324.4.2 pooka * argument is used to determine whether `from' will be
3228 1.324.4.2 pooka *
3229 1.324.4.2 pooka * (retain == 0) deleted unless `from' and `to' refer to the same
3230 1.324.4.2 pooka * object in the file system's name space (BSD).
3231 1.324.4.2 pooka * (retain == 1) always retained (POSIX).
3232 1.324.4.2 pooka */
3233 1.324.4.2 pooka static int
3234 1.324.4.2 pooka rename_files(const char *from, const char *to, struct lwp *l, int retain)
3235 1.324.4.2 pooka {
3236 1.324.4.2 pooka struct vnode *tvp, *fvp, *tdvp;
3237 1.324.4.2 pooka struct nameidata fromnd, tond;
3238 1.324.4.2 pooka struct proc *p;
3239 1.324.4.2 pooka int error;
3240 1.324.4.2 pooka
3241 1.324.4.2 pooka NDINIT(&fromnd, DELETE, LOCKPARENT | SAVESTART | TRYEMULROOT, UIO_USERSPACE,
3242 1.324.4.2 pooka from, l);
3243 1.324.4.2 pooka if ((error = namei(&fromnd)) != 0)
3244 1.324.4.2 pooka return (error);
3245 1.324.4.2 pooka if (fromnd.ni_dvp != fromnd.ni_vp)
3246 1.324.4.2 pooka VOP_UNLOCK(fromnd.ni_dvp, 0);
3247 1.324.4.2 pooka fvp = fromnd.ni_vp;
3248 1.324.4.2 pooka NDINIT(&tond, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART | TRYEMULROOT |
3249 1.324.4.2 pooka (fvp->v_type == VDIR ? CREATEDIR : 0), UIO_USERSPACE, to, l);
3250 1.324.4.2 pooka if ((error = namei(&tond)) != 0) {
3251 1.324.4.2 pooka VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
3252 1.324.4.2 pooka vrele(fromnd.ni_dvp);
3253 1.324.4.2 pooka vrele(fvp);
3254 1.324.4.2 pooka goto out1;
3255 1.324.4.2 pooka }
3256 1.324.4.2 pooka tdvp = tond.ni_dvp;
3257 1.324.4.2 pooka tvp = tond.ni_vp;
3258 1.324.4.2 pooka
3259 1.324.4.2 pooka if (tvp != NULL) {
3260 1.324.4.2 pooka if (fvp->v_type == VDIR && tvp->v_type != VDIR) {
3261 1.324.4.2 pooka error = ENOTDIR;
3262 1.324.4.2 pooka goto out;
3263 1.324.4.2 pooka } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) {
3264 1.324.4.2 pooka error = EISDIR;
3265 1.324.4.2 pooka goto out;
3266 1.324.4.2 pooka }
3267 1.324.4.2 pooka }
3268 1.324.4.2 pooka
3269 1.324.4.2 pooka if (fvp == tdvp)
3270 1.324.4.2 pooka error = EINVAL;
3271 1.324.4.2 pooka
3272 1.324.4.2 pooka /*
3273 1.324.4.2 pooka * Source and destination refer to the same object.
3274 1.324.4.2 pooka */
3275 1.324.4.2 pooka if (fvp == tvp) {
3276 1.324.4.2 pooka if (retain)
3277 1.324.4.2 pooka error = -1;
3278 1.324.4.2 pooka else if (fromnd.ni_dvp == tdvp &&
3279 1.324.4.2 pooka fromnd.ni_cnd.cn_namelen == tond.ni_cnd.cn_namelen &&
3280 1.324.4.2 pooka !memcmp(fromnd.ni_cnd.cn_nameptr,
3281 1.324.4.2 pooka tond.ni_cnd.cn_nameptr,
3282 1.324.4.2 pooka fromnd.ni_cnd.cn_namelen))
3283 1.324.4.2 pooka error = -1;
3284 1.324.4.2 pooka }
3285 1.324.4.2 pooka
3286 1.324.4.2 pooka #if NVERIEXEC > 0
3287 1.324.4.2 pooka if (!error) {
3288 1.324.4.2 pooka char *f1, *f2;
3289 1.324.4.2 pooka
3290 1.324.4.2 pooka f1 = malloc(fromnd.ni_cnd.cn_namelen + 1, M_TEMP, M_WAITOK);
3291 1.324.4.2 pooka strlcpy(f1, fromnd.ni_cnd.cn_nameptr, fromnd.ni_cnd.cn_namelen);
3292 1.324.4.2 pooka
3293 1.324.4.2 pooka f2 = malloc(tond.ni_cnd.cn_namelen + 1, M_TEMP, M_WAITOK);
3294 1.324.4.2 pooka strlcpy(f2, tond.ni_cnd.cn_nameptr, tond.ni_cnd.cn_namelen);
3295 1.324.4.2 pooka
3296 1.324.4.2 pooka error = veriexec_renamechk(l, fvp, f1, tvp, f2);
3297 1.324.4.2 pooka
3298 1.324.4.2 pooka free(f1, M_TEMP);
3299 1.324.4.2 pooka free(f2, M_TEMP);
3300 1.324.4.2 pooka }
3301 1.324.4.2 pooka #endif /* NVERIEXEC > 0 */
3302 1.324.4.2 pooka
3303 1.324.4.2 pooka out:
3304 1.324.4.2 pooka p = l->l_proc;
3305 1.324.4.2 pooka if (!error) {
3306 1.324.4.2 pooka VOP_LEASE(tdvp, l, l->l_cred, LEASE_WRITE);
3307 1.324.4.2 pooka if (fromnd.ni_dvp != tdvp)
3308 1.324.4.2 pooka VOP_LEASE(fromnd.ni_dvp, l, l->l_cred, LEASE_WRITE);
3309 1.324.4.2 pooka if (tvp) {
3310 1.324.4.2 pooka VOP_LEASE(tvp, l, l->l_cred, LEASE_WRITE);
3311 1.324.4.2 pooka }
3312 1.324.4.2 pooka error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd,
3313 1.324.4.2 pooka tond.ni_dvp, tond.ni_vp, &tond.ni_cnd);
3314 1.324.4.2 pooka } else {
3315 1.324.4.2 pooka VOP_ABORTOP(tond.ni_dvp, &tond.ni_cnd);
3316 1.324.4.2 pooka if (tdvp == tvp)
3317 1.324.4.2 pooka vrele(tdvp);
3318 1.324.4.2 pooka else
3319 1.324.4.2 pooka vput(tdvp);
3320 1.324.4.2 pooka if (tvp)
3321 1.324.4.2 pooka vput(tvp);
3322 1.324.4.2 pooka VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
3323 1.324.4.2 pooka vrele(fromnd.ni_dvp);
3324 1.324.4.2 pooka vrele(fvp);
3325 1.324.4.2 pooka }
3326 1.324.4.2 pooka vrele(tond.ni_startdir);
3327 1.324.4.2 pooka PNBUF_PUT(tond.ni_cnd.cn_pnbuf);
3328 1.324.4.2 pooka out1:
3329 1.324.4.2 pooka if (fromnd.ni_startdir)
3330 1.324.4.2 pooka vrele(fromnd.ni_startdir);
3331 1.324.4.2 pooka PNBUF_PUT(fromnd.ni_cnd.cn_pnbuf);
3332 1.324.4.2 pooka return (error == -1 ? 0 : error);
3333 1.324.4.2 pooka }
3334 1.324.4.2 pooka
3335 1.324.4.2 pooka /*
3336 1.324.4.2 pooka * Make a directory file.
3337 1.324.4.2 pooka */
3338 1.324.4.2 pooka /* ARGSUSED */
3339 1.324.4.2 pooka int
3340 1.324.4.2 pooka sys_mkdir(struct lwp *l, void *v, register_t *retval)
3341 1.324.4.2 pooka {
3342 1.324.4.2 pooka struct sys_mkdir_args /* {
3343 1.324.4.2 pooka syscallarg(const char *) path;
3344 1.324.4.2 pooka syscallarg(int) mode;
3345 1.324.4.2 pooka } */ *uap = v;
3346 1.324.4.2 pooka struct proc *p = l->l_proc;
3347 1.324.4.2 pooka struct vnode *vp;
3348 1.324.4.2 pooka struct vattr vattr;
3349 1.324.4.2 pooka int error;
3350 1.324.4.2 pooka struct nameidata nd;
3351 1.324.4.2 pooka
3352 1.324.4.2 pooka NDINIT(&nd, CREATE, LOCKPARENT | CREATEDIR | TRYEMULROOT, UIO_USERSPACE,
3353 1.324.4.2 pooka SCARG(uap, path), l);
3354 1.324.4.2 pooka if ((error = namei(&nd)) != 0)
3355 1.324.4.2 pooka return (error);
3356 1.324.4.2 pooka vp = nd.ni_vp;
3357 1.324.4.2 pooka if (vp != NULL) {
3358 1.324.4.2 pooka VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
3359 1.324.4.2 pooka if (nd.ni_dvp == vp)
3360 1.324.4.2 pooka vrele(nd.ni_dvp);
3361 1.324.4.2 pooka else
3362 1.324.4.2 pooka vput(nd.ni_dvp);
3363 1.324.4.2 pooka vrele(vp);
3364 1.324.4.2 pooka return (EEXIST);
3365 1.324.4.2 pooka }
3366 1.324.4.2 pooka VATTR_NULL(&vattr);
3367 1.324.4.2 pooka vattr.va_type = VDIR;
3368 1.324.4.2 pooka vattr.va_mode =
3369 1.324.4.2 pooka (SCARG(uap, mode) & ACCESSPERMS) &~ p->p_cwdi->cwdi_cmask;
3370 1.324.4.2 pooka VOP_LEASE(nd.ni_dvp, l, l->l_cred, LEASE_WRITE);
3371 1.324.4.2 pooka error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
3372 1.324.4.2 pooka if (!error)
3373 1.324.4.2 pooka vput(nd.ni_vp);
3374 1.324.4.2 pooka return (error);
3375 1.324.4.2 pooka }
3376 1.324.4.2 pooka
3377 1.324.4.2 pooka /*
3378 1.324.4.2 pooka * Remove a directory file.
3379 1.324.4.2 pooka */
3380 1.324.4.2 pooka /* ARGSUSED */
3381 1.324.4.2 pooka int
3382 1.324.4.2 pooka sys_rmdir(struct lwp *l, void *v, register_t *retval)
3383 1.324.4.2 pooka {
3384 1.324.4.2 pooka struct sys_rmdir_args /* {
3385 1.324.4.2 pooka syscallarg(const char *) path;
3386 1.324.4.2 pooka } */ *uap = v;
3387 1.324.4.2 pooka struct vnode *vp;
3388 1.324.4.2 pooka int error;
3389 1.324.4.2 pooka struct nameidata nd;
3390 1.324.4.2 pooka
3391 1.324.4.2 pooka NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF | TRYEMULROOT, UIO_USERSPACE,
3392 1.324.4.2 pooka SCARG(uap, path), l);
3393 1.324.4.2 pooka if ((error = namei(&nd)) != 0)
3394 1.324.4.2 pooka return (error);
3395 1.324.4.2 pooka vp = nd.ni_vp;
3396 1.324.4.2 pooka if (vp->v_type != VDIR) {
3397 1.324.4.2 pooka error = ENOTDIR;
3398 1.324.4.2 pooka goto out;
3399 1.324.4.2 pooka }
3400 1.324.4.2 pooka /*
3401 1.324.4.2 pooka * No rmdir "." please.
3402 1.324.4.2 pooka */
3403 1.324.4.2 pooka if (nd.ni_dvp == vp) {
3404 1.324.4.2 pooka error = EINVAL;
3405 1.324.4.2 pooka goto out;
3406 1.324.4.2 pooka }
3407 1.324.4.2 pooka /*
3408 1.324.4.2 pooka * The root of a mounted filesystem cannot be deleted.
3409 1.324.4.2 pooka */
3410 1.324.4.2 pooka if (vp->v_flag & VROOT) {
3411 1.324.4.2 pooka error = EBUSY;
3412 1.324.4.2 pooka goto out;
3413 1.324.4.2 pooka }
3414 1.324.4.2 pooka VOP_LEASE(nd.ni_dvp, l, l->l_cred, LEASE_WRITE);
3415 1.324.4.2 pooka VOP_LEASE(vp, l, l->l_cred, LEASE_WRITE);
3416 1.324.4.2 pooka error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
3417 1.324.4.2 pooka return (error);
3418 1.324.4.2 pooka
3419 1.324.4.2 pooka out:
3420 1.324.4.2 pooka VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
3421 1.324.4.2 pooka if (nd.ni_dvp == vp)
3422 1.324.4.2 pooka vrele(nd.ni_dvp);
3423 1.324.4.2 pooka else
3424 1.324.4.2 pooka vput(nd.ni_dvp);
3425 1.324.4.2 pooka vput(vp);
3426 1.324.4.2 pooka return (error);
3427 1.324.4.2 pooka }
3428 1.324.4.2 pooka
3429 1.324.4.2 pooka /*
3430 1.324.4.2 pooka * Read a block of directory entries in a file system independent format.
3431 1.324.4.2 pooka */
3432 1.324.4.2 pooka int
3433 1.324.4.2 pooka sys___getdents30(struct lwp *l, void *v, register_t *retval)
3434 1.324.4.2 pooka {
3435 1.324.4.2 pooka struct sys___getdents30_args /* {
3436 1.324.4.2 pooka syscallarg(int) fd;
3437 1.324.4.2 pooka syscallarg(char *) buf;
3438 1.324.4.2 pooka syscallarg(size_t) count;
3439 1.324.4.2 pooka } */ *uap = v;
3440 1.324.4.2 pooka struct proc *p = l->l_proc;
3441 1.324.4.2 pooka struct file *fp;
3442 1.324.4.2 pooka int error, done;
3443 1.324.4.2 pooka
3444 1.324.4.2 pooka /* getvnode() will use the descriptor for us */
3445 1.324.4.2 pooka if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
3446 1.324.4.2 pooka return (error);
3447 1.324.4.2 pooka if ((fp->f_flag & FREAD) == 0) {
3448 1.324.4.2 pooka error = EBADF;
3449 1.324.4.2 pooka goto out;
3450 1.324.4.2 pooka }
3451 1.324.4.2 pooka error = vn_readdir(fp, SCARG(uap, buf), UIO_USERSPACE,
3452 1.324.4.2 pooka SCARG(uap, count), &done, l, 0, 0);
3453 1.324.4.2 pooka #ifdef KTRACE
3454 1.324.4.2 pooka if (!error && KTRPOINT(p, KTR_GENIO)) {
3455 1.324.4.2 pooka struct iovec iov;
3456 1.324.4.2 pooka iov.iov_base = SCARG(uap, buf);
3457 1.324.4.2 pooka iov.iov_len = done;
3458 1.324.4.2 pooka ktrgenio(l, SCARG(uap, fd), UIO_READ, &iov, done, 0);
3459 1.324.4.2 pooka }
3460 1.324.4.2 pooka #endif
3461 1.324.4.2 pooka *retval = done;
3462 1.324.4.2 pooka out:
3463 1.324.4.2 pooka FILE_UNUSE(fp, l);
3464 1.324.4.2 pooka return (error);
3465 1.324.4.2 pooka }
3466 1.324.4.2 pooka
3467 1.324.4.2 pooka /*
3468 1.324.4.2 pooka * Set the mode mask for creation of filesystem nodes.
3469 1.324.4.2 pooka */
3470 1.324.4.2 pooka int
3471 1.324.4.2 pooka sys_umask(struct lwp *l, void *v, register_t *retval)
3472 1.324.4.2 pooka {
3473 1.324.4.2 pooka struct sys_umask_args /* {
3474 1.324.4.2 pooka syscallarg(mode_t) newmask;
3475 1.324.4.2 pooka } */ *uap = v;
3476 1.324.4.2 pooka struct proc *p = l->l_proc;
3477 1.324.4.2 pooka struct cwdinfo *cwdi;
3478 1.324.4.2 pooka
3479 1.324.4.2 pooka cwdi = p->p_cwdi;
3480 1.324.4.2 pooka *retval = cwdi->cwdi_cmask;
3481 1.324.4.2 pooka cwdi->cwdi_cmask = SCARG(uap, newmask) & ALLPERMS;
3482 1.324.4.2 pooka return (0);
3483 1.324.4.2 pooka }
3484 1.324.4.2 pooka
3485 1.324.4.2 pooka /*
3486 1.324.4.2 pooka * Void all references to file by ripping underlying filesystem
3487 1.324.4.2 pooka * away from vnode.
3488 1.324.4.2 pooka */
3489 1.324.4.2 pooka /* ARGSUSED */
3490 1.324.4.2 pooka int
3491 1.324.4.2 pooka sys_revoke(struct lwp *l, void *v, register_t *retval)
3492 1.324.4.2 pooka {
3493 1.324.4.2 pooka struct sys_revoke_args /* {
3494 1.324.4.2 pooka syscallarg(const char *) path;
3495 1.324.4.2 pooka } */ *uap = v;
3496 1.324.4.2 pooka struct vnode *vp;
3497 1.324.4.2 pooka struct vattr vattr;
3498 1.324.4.2 pooka int error;
3499 1.324.4.2 pooka struct nameidata nd;
3500 1.324.4.2 pooka
3501 1.324.4.2 pooka NDINIT(&nd, LOOKUP, FOLLOW | TRYEMULROOT, UIO_USERSPACE, SCARG(uap, path), l);
3502 1.324.4.2 pooka if ((error = namei(&nd)) != 0)
3503 1.324.4.2 pooka return (error);
3504 1.324.4.2 pooka vp = nd.ni_vp;
3505 1.324.4.2 pooka if ((error = VOP_GETATTR(vp, &vattr, l->l_cred, l)) != 0)
3506 1.324.4.2 pooka goto out;
3507 1.324.4.2 pooka if (kauth_cred_geteuid(l->l_cred) != vattr.va_uid &&
3508 1.324.4.2 pooka (error = kauth_authorize_generic(l->l_cred,
3509 1.324.4.2 pooka KAUTH_GENERIC_ISSUSER, NULL)) != 0)
3510 1.324.4.2 pooka goto out;
3511 1.324.4.2 pooka if (vp->v_usecount > 1 || (vp->v_flag & (VALIASED | VLAYER)))
3512 1.324.4.2 pooka VOP_REVOKE(vp, REVOKEALL);
3513 1.324.4.2 pooka out:
3514 1.324.4.2 pooka vrele(vp);
3515 1.324.4.2 pooka return (error);
3516 1.324.4.2 pooka }
3517 1.324.4.2 pooka
3518 1.324.4.2 pooka /*
3519 1.324.4.2 pooka * Convert a user file descriptor to a kernel file entry.
3520 1.324.4.2 pooka */
3521 1.324.4.2 pooka int
3522 1.324.4.2 pooka getvnode(struct filedesc *fdp, int fd, struct file **fpp)
3523 1.324.4.2 pooka {
3524 1.324.4.2 pooka struct vnode *vp;
3525 1.324.4.2 pooka struct file *fp;
3526 1.324.4.2 pooka
3527 1.324.4.2 pooka if ((fp = fd_getfile(fdp, fd)) == NULL)
3528 1.324.4.2 pooka return (EBADF);
3529 1.324.4.2 pooka
3530 1.324.4.2 pooka FILE_USE(fp);
3531 1.324.4.2 pooka
3532 1.324.4.2 pooka if (fp->f_type != DTYPE_VNODE) {
3533 1.324.4.2 pooka FILE_UNUSE(fp, NULL);
3534 1.324.4.2 pooka return (EINVAL);
3535 1.324.4.2 pooka }
3536 1.324.4.2 pooka
3537 1.324.4.2 pooka vp = (struct vnode *)fp->f_data;
3538 1.324.4.2 pooka if (vp->v_type == VBAD) {
3539 1.324.4.2 pooka FILE_UNUSE(fp, NULL);
3540 1.324.4.2 pooka return (EBADF);
3541 1.324.4.2 pooka }
3542 1.324.4.2 pooka
3543 1.324.4.2 pooka *fpp = fp;
3544 1.324.4.2 pooka return (0);
3545 1.324.4.2 pooka }
3546