xref: /freebsd/sys/kern/vfs_syscalls.c (revision 11f0b352e05306cf6f1f85e9087022c0a92624a3)
1 /*
2  * Copyright (c) 1989, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  * (c) UNIX System Laboratories, Inc.
5  * All or some portions of this file are derived from material licensed
6  * to the University of California by American Telephone and Telegraph
7  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
8  * the permission of UNIX System Laboratories, Inc.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. All advertising materials mentioning features or use of this software
19  *    must display the following acknowledgement:
20  *	This product includes software developed by the University of
21  *	California, Berkeley and its contributors.
22  * 4. Neither the name of the University nor the names of its contributors
23  *    may be used to endorse or promote products derived from this software
24  *    without specific prior written permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36  * SUCH DAMAGE.
37  *
38  *	@(#)vfs_syscalls.c	8.13 (Berkeley) 4/15/94
39  * $FreeBSD$
40  */
41 
42 /* For 4.3 integer FS ID compatibility */
43 #include "opt_compat.h"
44 
45 #include <sys/param.h>
46 #include <sys/systm.h>
47 #include <sys/bio.h>
48 #include <sys/buf.h>
49 #include <sys/sysent.h>
50 #include <sys/malloc.h>
51 #include <sys/mount.h>
52 #include <sys/mutex.h>
53 #include <sys/sysproto.h>
54 #include <sys/namei.h>
55 #include <sys/filedesc.h>
56 #include <sys/kernel.h>
57 #include <sys/fcntl.h>
58 #include <sys/file.h>
59 #include <sys/linker.h>
60 #include <sys/stat.h>
61 #include <sys/sx.h>
62 #include <sys/unistd.h>
63 #include <sys/vnode.h>
64 #include <sys/proc.h>
65 #include <sys/dirent.h>
66 #include <sys/extattr.h>
67 #include <sys/jail.h>
68 #include <sys/sysctl.h>
69 
70 #include <machine/limits.h>
71 #include <machine/stdarg.h>
72 
73 #include <vm/vm.h>
74 #include <vm/vm_object.h>
75 #include <vm/vm_page.h>
76 #include <vm/uma.h>
77 
78 static int change_dir(struct nameidata *ndp, struct thread *td);
79 static int chroot_refuse_vdir_fds(struct filedesc *fdp);
80 static int getutimes(const struct timeval *, struct timespec *);
81 static int setfown(struct thread *td, struct vnode *, uid_t, gid_t);
82 static int setfmode(struct thread *td, struct vnode *, int);
83 static int setfflags(struct thread *td, struct vnode *, int);
84 static int setutimes(struct thread *td, struct vnode *,
85     const struct timespec *, int);
86 static int vn_access(struct vnode *vp, int user_flags, struct ucred *cred,
87     struct thread *td);
88 
89 int (*union_dircheckp)(struct thread *td, struct vnode **, struct file *);
90 int (*softdep_fsync_hook)(struct vnode *);
91 
92 /*
93  * Sync each mounted filesystem.
94  */
95 #ifndef _SYS_SYSPROTO_H_
96 struct sync_args {
97         int     dummy;
98 };
99 #endif
100 
101 #ifdef DEBUG
102 static int syncprt = 0;
103 SYSCTL_INT(_debug, OID_AUTO, syncprt, CTLFLAG_RW, &syncprt, 0, "");
104 #endif
105 
106 /* ARGSUSED */
107 int
108 sync(td, uap)
109 	struct thread *td;
110 	struct sync_args *uap;
111 {
112 	struct mount *mp, *nmp;
113 	int asyncflag;
114 
115 	mtx_lock(&mountlist_mtx);
116 	for (mp = TAILQ_FIRST(&mountlist); mp != NULL; mp = nmp) {
117 		if (vfs_busy(mp, LK_NOWAIT, &mountlist_mtx, td)) {
118 			nmp = TAILQ_NEXT(mp, mnt_list);
119 			continue;
120 		}
121 		if ((mp->mnt_flag & MNT_RDONLY) == 0 &&
122 		    vn_start_write(NULL, &mp, V_NOWAIT) == 0) {
123 			asyncflag = mp->mnt_flag & MNT_ASYNC;
124 			mp->mnt_flag &= ~MNT_ASYNC;
125 			vfs_msync(mp, MNT_NOWAIT);
126 			VFS_SYNC(mp, MNT_NOWAIT,
127 			    ((td != NULL) ? td->td_ucred : NOCRED), td);
128 			mp->mnt_flag |= asyncflag;
129 			vn_finished_write(mp);
130 		}
131 		mtx_lock(&mountlist_mtx);
132 		nmp = TAILQ_NEXT(mp, mnt_list);
133 		vfs_unbusy(mp, td);
134 	}
135 	mtx_unlock(&mountlist_mtx);
136 #if 0
137 /*
138  * XXX don't call vfs_bufstats() yet because that routine
139  * was not imported in the Lite2 merge.
140  */
141 #ifdef DIAGNOSTIC
142 	if (syncprt)
143 		vfs_bufstats();
144 #endif /* DIAGNOSTIC */
145 #endif
146 	return (0);
147 }
148 
149 /* XXX PRISON: could be per prison flag */
150 static int prison_quotas;
151 #if 0
152 SYSCTL_INT(_kern_prison, OID_AUTO, quotas, CTLFLAG_RW, &prison_quotas, 0, "");
153 #endif
154 
155 /*
156  * Change filesystem quotas.
157  */
158 #ifndef _SYS_SYSPROTO_H_
159 struct quotactl_args {
160 	char *path;
161 	int cmd;
162 	int uid;
163 	caddr_t arg;
164 };
165 #endif
166 /* ARGSUSED */
167 int
168 quotactl(td, uap)
169 	struct thread *td;
170 	register struct quotactl_args /* {
171 		syscallarg(char *) path;
172 		syscallarg(int) cmd;
173 		syscallarg(int) uid;
174 		syscallarg(caddr_t) arg;
175 	} */ *uap;
176 {
177 	struct mount *mp;
178 	int error;
179 	struct nameidata nd;
180 
181 	if (jailed(td->td_ucred) && !prison_quotas)
182 		return (EPERM);
183 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td);
184 	if ((error = namei(&nd)) != 0)
185 		return (error);
186 	NDFREE(&nd, NDF_ONLY_PNBUF);
187 	error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH);
188 	vrele(nd.ni_vp);
189 	if (error)
190 		return (error);
191 	error = VFS_QUOTACTL(mp, SCARG(uap, cmd), SCARG(uap, uid),
192 	    SCARG(uap, arg), td);
193 	vn_finished_write(mp);
194 	return (error);
195 }
196 
197 /*
198  * Get filesystem statistics.
199  */
200 #ifndef _SYS_SYSPROTO_H_
201 struct statfs_args {
202 	char *path;
203 	struct statfs *buf;
204 };
205 #endif
206 /* ARGSUSED */
207 int
208 statfs(td, uap)
209 	struct thread *td;
210 	register struct statfs_args /* {
211 		syscallarg(char *) path;
212 		syscallarg(struct statfs *) buf;
213 	} */ *uap;
214 {
215 	register struct mount *mp;
216 	register struct statfs *sp;
217 	int error;
218 	struct nameidata nd;
219 	struct statfs sb;
220 
221 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td);
222 	if ((error = namei(&nd)) != 0)
223 		return (error);
224 	mp = nd.ni_vp->v_mount;
225 	sp = &mp->mnt_stat;
226 	NDFREE(&nd, NDF_ONLY_PNBUF);
227 	vrele(nd.ni_vp);
228 	error = VFS_STATFS(mp, sp, td);
229 	if (error)
230 		return (error);
231 	sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
232 	if (suser(td)) {
233 		bcopy(sp, &sb, sizeof(sb));
234 		sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0;
235 		sp = &sb;
236 	}
237 	return (copyout(sp, SCARG(uap, buf), sizeof(*sp)));
238 }
239 
240 /*
241  * Get filesystem statistics.
242  */
243 #ifndef _SYS_SYSPROTO_H_
244 struct fstatfs_args {
245 	int fd;
246 	struct statfs *buf;
247 };
248 #endif
249 /* ARGSUSED */
250 int
251 fstatfs(td, uap)
252 	struct thread *td;
253 	register struct fstatfs_args /* {
254 		syscallarg(int) fd;
255 		syscallarg(struct statfs *) buf;
256 	} */ *uap;
257 {
258 	struct file *fp;
259 	struct mount *mp;
260 	register struct statfs *sp;
261 	int error;
262 	struct statfs sb;
263 
264 	if ((error = getvnode(td->td_proc->p_fd, SCARG(uap, fd), &fp)) != 0)
265 		return (error);
266 	mp = ((struct vnode *)fp->f_data)->v_mount;
267 	fdrop(fp, td);
268 	if (mp == NULL)
269 		return (EBADF);
270 	sp = &mp->mnt_stat;
271 	error = VFS_STATFS(mp, sp, td);
272 	if (error)
273 		return (error);
274 	sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
275 	if (suser(td)) {
276 		bcopy(sp, &sb, sizeof(sb));
277 		sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0;
278 		sp = &sb;
279 	}
280 	return (copyout(sp, SCARG(uap, buf), sizeof(*sp)));
281 }
282 
283 /*
284  * Get statistics on all filesystems.
285  */
286 #ifndef _SYS_SYSPROTO_H_
287 struct getfsstat_args {
288 	struct statfs *buf;
289 	long bufsize;
290 	int flags;
291 };
292 #endif
293 int
294 getfsstat(td, uap)
295 	struct thread *td;
296 	register struct getfsstat_args /* {
297 		syscallarg(struct statfs *) buf;
298 		syscallarg(long) bufsize;
299 		syscallarg(int) flags;
300 	} */ *uap;
301 {
302 	register struct mount *mp, *nmp;
303 	register struct statfs *sp;
304 	caddr_t sfsp;
305 	long count, maxcount, error;
306 
307 	maxcount = SCARG(uap, bufsize) / sizeof(struct statfs);
308 	sfsp = (caddr_t)SCARG(uap, buf);
309 	count = 0;
310 	mtx_lock(&mountlist_mtx);
311 	for (mp = TAILQ_FIRST(&mountlist); mp != NULL; mp = nmp) {
312 		if (vfs_busy(mp, LK_NOWAIT, &mountlist_mtx, td)) {
313 			nmp = TAILQ_NEXT(mp, mnt_list);
314 			continue;
315 		}
316 		if (sfsp && count < maxcount) {
317 			sp = &mp->mnt_stat;
318 			/*
319 			 * If MNT_NOWAIT or MNT_LAZY is specified, do not
320 			 * refresh the fsstat cache. MNT_NOWAIT or MNT_LAZY
321 			 * overrides MNT_WAIT.
322 			 */
323 			if (((SCARG(uap, flags) & (MNT_LAZY|MNT_NOWAIT)) == 0 ||
324 			    (SCARG(uap, flags) & MNT_WAIT)) &&
325 			    (error = VFS_STATFS(mp, sp, td))) {
326 				mtx_lock(&mountlist_mtx);
327 				nmp = TAILQ_NEXT(mp, mnt_list);
328 				vfs_unbusy(mp, td);
329 				continue;
330 			}
331 			sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
332 			error = copyout(sp, sfsp, sizeof(*sp));
333 			if (error) {
334 				vfs_unbusy(mp, td);
335 				return (error);
336 			}
337 			sfsp += sizeof(*sp);
338 		}
339 		count++;
340 		mtx_lock(&mountlist_mtx);
341 		nmp = TAILQ_NEXT(mp, mnt_list);
342 		vfs_unbusy(mp, td);
343 	}
344 	mtx_unlock(&mountlist_mtx);
345 	if (sfsp && count > maxcount)
346 		td->td_retval[0] = maxcount;
347 	else
348 		td->td_retval[0] = count;
349 	return (0);
350 }
351 
352 /*
353  * Change current working directory to a given file descriptor.
354  */
355 #ifndef _SYS_SYSPROTO_H_
356 struct fchdir_args {
357 	int	fd;
358 };
359 #endif
360 /* ARGSUSED */
361 int
362 fchdir(td, uap)
363 	struct thread *td;
364 	struct fchdir_args /* {
365 		syscallarg(int) fd;
366 	} */ *uap;
367 {
368 	register struct filedesc *fdp = td->td_proc->p_fd;
369 	struct vnode *vp, *tdp, *vpold;
370 	struct mount *mp;
371 	struct file *fp;
372 	int error;
373 
374 	if ((error = getvnode(fdp, SCARG(uap, fd), &fp)) != 0)
375 		return (error);
376 	vp = (struct vnode *)fp->f_data;
377 	VREF(vp);
378 	fdrop(fp, td);
379 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
380 	if (vp->v_type != VDIR)
381 		error = ENOTDIR;
382 	else
383 		error = VOP_ACCESS(vp, VEXEC, td->td_ucred, td);
384 	while (!error && (mp = vp->v_mountedhere) != NULL) {
385 		if (vfs_busy(mp, 0, 0, td))
386 			continue;
387 		error = VFS_ROOT(mp, &tdp);
388 		vfs_unbusy(mp, td);
389 		if (error)
390 			break;
391 		vput(vp);
392 		vp = tdp;
393 	}
394 	if (error) {
395 		vput(vp);
396 		return (error);
397 	}
398 	VOP_UNLOCK(vp, 0, td);
399 	FILEDESC_LOCK(fdp);
400 	vpold = fdp->fd_cdir;
401 	fdp->fd_cdir = vp;
402 	FILEDESC_UNLOCK(fdp);
403 	vrele(vpold);
404 	return (0);
405 }
406 
407 /*
408  * Change current working directory (``.'').
409  */
410 #ifndef _SYS_SYSPROTO_H_
411 struct chdir_args {
412 	char	*path;
413 };
414 #endif
415 /* ARGSUSED */
416 int
417 chdir(td, uap)
418 	struct thread *td;
419 	struct chdir_args /* {
420 		syscallarg(char *) path;
421 	} */ *uap;
422 {
423 	register struct filedesc *fdp = td->td_proc->p_fd;
424 	int error;
425 	struct nameidata nd;
426 	struct vnode *vp;
427 
428 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
429 	    SCARG(uap, path), td);
430 	if ((error = change_dir(&nd, td)) != 0)
431 		return (error);
432 	NDFREE(&nd, NDF_ONLY_PNBUF);
433 	FILEDESC_LOCK(fdp);
434 	vp = fdp->fd_cdir;
435 	fdp->fd_cdir = nd.ni_vp;
436 	FILEDESC_UNLOCK(fdp);
437 	vrele(vp);
438 	return (0);
439 }
440 
441 /*
442  * Helper function for raised chroot(2) security function:  Refuse if
443  * any filedescriptors are open directories.
444  */
445 static int
446 chroot_refuse_vdir_fds(fdp)
447 	struct filedesc *fdp;
448 {
449 	struct vnode *vp;
450 	struct file *fp;
451 	int fd;
452 
453 	FILEDESC_LOCK(fdp);
454 	for (fd = 0; fd < fdp->fd_nfiles ; fd++) {
455 		fp = fget_locked(fdp, fd);
456 		if (fp == NULL)
457 			continue;
458 		if (fp->f_type == DTYPE_VNODE) {
459 			vp = (struct vnode *)fp->f_data;
460 			if (vp->v_type == VDIR) {
461 				FILEDESC_UNLOCK(fdp);
462 				return (EPERM);
463 			}
464 		}
465 	}
466 	FILEDESC_UNLOCK(fdp);
467 	return (0);
468 }
469 
470 /*
471  * This sysctl determines if we will allow a process to chroot(2) if it
472  * has a directory open:
473  *	0: disallowed for all processes.
474  *	1: allowed for processes that were not already chroot(2)'ed.
475  *	2: allowed for all processes.
476  */
477 
478 static int chroot_allow_open_directories = 1;
479 
480 SYSCTL_INT(_kern, OID_AUTO, chroot_allow_open_directories, CTLFLAG_RW,
481      &chroot_allow_open_directories, 0, "");
482 
483 /*
484  * Change notion of root (``/'') directory.
485  */
486 #ifndef _SYS_SYSPROTO_H_
487 struct chroot_args {
488 	char	*path;
489 };
490 #endif
491 /* ARGSUSED */
492 int
493 chroot(td, uap)
494 	struct thread *td;
495 	struct chroot_args /* {
496 		syscallarg(char *) path;
497 	} */ *uap;
498 {
499 	register struct filedesc *fdp = td->td_proc->p_fd;
500 	int error;
501 	struct nameidata nd;
502 	struct vnode *vp;
503 
504 	error = suser_cred(td->td_ucred, PRISON_ROOT);
505 	if (error)
506 		return (error);
507 	FILEDESC_LOCK(fdp);
508 	if (chroot_allow_open_directories == 0 ||
509 	    (chroot_allow_open_directories == 1 && fdp->fd_rdir != rootvnode)) {
510 		FILEDESC_UNLOCK(fdp);
511 		error = chroot_refuse_vdir_fds(fdp);
512 	} else
513 		FILEDESC_UNLOCK(fdp);
514 	if (error)
515 		return (error);
516 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
517 	    SCARG(uap, path), td);
518 	if ((error = change_dir(&nd, td)) != 0)
519 		return (error);
520 	NDFREE(&nd, NDF_ONLY_PNBUF);
521 	FILEDESC_LOCK(fdp);
522 	vp = fdp->fd_rdir;
523 	fdp->fd_rdir = nd.ni_vp;
524 	if (!fdp->fd_jdir) {
525 		fdp->fd_jdir = nd.ni_vp;
526                 VREF(fdp->fd_jdir);
527 	}
528 	FILEDESC_UNLOCK(fdp);
529 	vrele(vp);
530 	return (0);
531 }
532 
533 /*
534  * Common routine for chroot and chdir.
535  */
536 static int
537 change_dir(ndp, td)
538 	register struct nameidata *ndp;
539 	struct thread *td;
540 {
541 	struct vnode *vp;
542 	int error;
543 
544 	error = namei(ndp);
545 	if (error)
546 		return (error);
547 	vp = ndp->ni_vp;
548 	if (vp->v_type != VDIR)
549 		error = ENOTDIR;
550 	else
551 		error = VOP_ACCESS(vp, VEXEC, td->td_ucred, td);
552 	if (error)
553 		vput(vp);
554 	else
555 		VOP_UNLOCK(vp, 0, td);
556 	return (error);
557 }
558 
559 /*
560  * Check permissions, allocate an open file structure,
561  * and call the device open routine if any.
562  */
563 #ifndef _SYS_SYSPROTO_H_
564 struct open_args {
565 	char	*path;
566 	int	flags;
567 	int	mode;
568 };
569 #endif
570 int
571 open(td, uap)
572 	struct thread *td;
573 	register struct open_args /* {
574 		syscallarg(char *) path;
575 		syscallarg(int) flags;
576 		syscallarg(int) mode;
577 	} */ *uap;
578 {
579 	struct proc *p = td->td_proc;
580 	struct filedesc *fdp = p->p_fd;
581 	struct file *fp;
582 	struct vnode *vp;
583 	struct vattr vat;
584 	struct mount *mp;
585 	int cmode, flags, oflags;
586 	struct file *nfp;
587 	int type, indx, error;
588 	struct flock lf;
589 	struct nameidata nd;
590 
591 	oflags = SCARG(uap, flags);
592 	if ((oflags & O_ACCMODE) == O_ACCMODE)
593 		return (EINVAL);
594 	flags = FFLAGS(oflags);
595 	error = falloc(td, &nfp, &indx);
596 	if (error)
597 		return (error);
598 	fp = nfp;
599 	FILEDESC_LOCK(fdp);
600 	cmode = ((SCARG(uap, mode) &~ fdp->fd_cmask) & ALLPERMS) &~ S_ISTXT;
601 	FILEDESC_UNLOCK(fdp);
602 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td);
603 	td->td_dupfd = -indx - 1;		/* XXX check for fdopen */
604 	/*
605 	 * Bump the ref count to prevent another process from closing
606 	 * the descriptor while we are blocked in vn_open()
607 	 */
608 	fhold(fp);
609 	error = vn_open(&nd, &flags, cmode);
610 	if (error) {
611 		/*
612 		 * release our own reference
613 		 */
614 		fdrop(fp, td);
615 
616 		/*
617 		 * handle special fdopen() case.  bleh.  dupfdopen() is
618 		 * responsible for dropping the old contents of ofiles[indx]
619 		 * if it succeeds.
620 		 */
621 		if ((error == ENODEV || error == ENXIO) &&
622 		    td->td_dupfd >= 0 &&		/* XXX from fdopen */
623 		    (error =
624 			dupfdopen(td, fdp, indx, td->td_dupfd, flags, error)) == 0) {
625 			td->td_retval[0] = indx;
626 			return (0);
627 		}
628 		/*
629 		 * Clean up the descriptor, but only if another thread hadn't
630 		 * replaced or closed it.
631 		 */
632 		FILEDESC_LOCK(fdp);
633 		if (fdp->fd_ofiles[indx] == fp) {
634 			fdp->fd_ofiles[indx] = NULL;
635 			FILEDESC_UNLOCK(fdp);
636 			fdrop(fp, td);
637 		} else
638 			FILEDESC_UNLOCK(fdp);
639 
640 		if (error == ERESTART)
641 			error = EINTR;
642 		return (error);
643 	}
644 	td->td_dupfd = 0;
645 	NDFREE(&nd, NDF_ONLY_PNBUF);
646 	vp = nd.ni_vp;
647 
648 	/*
649 	 * There should be 2 references on the file, one from the descriptor
650 	 * table, and one for us.
651 	 *
652 	 * Handle the case where someone closed the file (via its file
653 	 * descriptor) while we were blocked.  The end result should look
654 	 * like opening the file succeeded but it was immediately closed.
655 	 */
656 	FILEDESC_LOCK(fdp);
657 	FILE_LOCK(fp);
658 	if (fp->f_count == 1) {
659 		KASSERT(fdp->fd_ofiles[indx] != fp,
660 		    ("Open file descriptor lost all refs"));
661 		FILEDESC_UNLOCK(fdp);
662 		FILE_UNLOCK(fp);
663 		VOP_UNLOCK(vp, 0, td);
664 		vn_close(vp, flags & FMASK, fp->f_cred, td);
665 		fdrop(fp, td);
666 		td->td_retval[0] = indx;
667 		return 0;
668 	}
669 
670 	/* assert that vn_open created a backing object if one is needed */
671 	KASSERT(!vn_canvmio(vp) || VOP_GETVOBJECT(vp, NULL) == 0,
672 		("open: vmio vnode has no backing object after vn_open"));
673 
674 	fp->f_data = vp;
675 	fp->f_flag = flags & FMASK;
676 	fp->f_ops = &vnops;
677 	fp->f_type = (vp->v_type == VFIFO ? DTYPE_FIFO : DTYPE_VNODE);
678 	FILEDESC_UNLOCK(fdp);
679 	FILE_UNLOCK(fp);
680 	VOP_UNLOCK(vp, 0, td);
681 	if (flags & (O_EXLOCK | O_SHLOCK)) {
682 		lf.l_whence = SEEK_SET;
683 		lf.l_start = 0;
684 		lf.l_len = 0;
685 		if (flags & O_EXLOCK)
686 			lf.l_type = F_WRLCK;
687 		else
688 			lf.l_type = F_RDLCK;
689 		type = F_FLOCK;
690 		if ((flags & FNONBLOCK) == 0)
691 			type |= F_WAIT;
692 		if ((error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf,
693 			    type)) != 0)
694 			goto bad;
695 		fp->f_flag |= FHASLOCK;
696 	}
697 	if (flags & O_TRUNC) {
698 		if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
699 			goto bad;
700 		VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
701 		VATTR_NULL(&vat);
702 		vat.va_size = 0;
703 		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
704 		error = VOP_SETATTR(vp, &vat, td->td_ucred, td);
705 		VOP_UNLOCK(vp, 0, td);
706 		vn_finished_write(mp);
707 		if (error)
708 			goto bad;
709 	}
710 	/*
711 	 * Release our private reference, leaving the one associated with
712 	 * the descriptor table intact.
713 	 */
714 	fdrop(fp, td);
715 	td->td_retval[0] = indx;
716 	return (0);
717 bad:
718 	FILEDESC_LOCK(fdp);
719 	if (fdp->fd_ofiles[indx] == fp) {
720 		fdp->fd_ofiles[indx] = NULL;
721 		FILEDESC_UNLOCK(fdp);
722 		fdrop(fp, td);
723 	} else
724 		FILEDESC_UNLOCK(fdp);
725 	return (error);
726 }
727 
728 #ifdef COMPAT_43
729 /*
730  * Create a file.
731  */
732 #ifndef _SYS_SYSPROTO_H_
733 struct ocreat_args {
734 	char	*path;
735 	int	mode;
736 };
737 #endif
738 int
739 ocreat(td, uap)
740 	struct thread *td;
741 	register struct ocreat_args /* {
742 		syscallarg(char *) path;
743 		syscallarg(int) mode;
744 	} */ *uap;
745 {
746 	struct open_args /* {
747 		syscallarg(char *) path;
748 		syscallarg(int) flags;
749 		syscallarg(int) mode;
750 	} */ nuap;
751 
752 	SCARG(&nuap, path) = SCARG(uap, path);
753 	SCARG(&nuap, mode) = SCARG(uap, mode);
754 	SCARG(&nuap, flags) = O_WRONLY | O_CREAT | O_TRUNC;
755 	return (open(td, &nuap));
756 }
757 #endif /* COMPAT_43 */
758 
759 /*
760  * Create a special file.
761  */
762 #ifndef _SYS_SYSPROTO_H_
763 struct mknod_args {
764 	char	*path;
765 	int	mode;
766 	int	dev;
767 };
768 #endif
769 /* ARGSUSED */
770 int
771 mknod(td, uap)
772 	struct thread *td;
773 	register struct mknod_args /* {
774 		syscallarg(char *) path;
775 		syscallarg(int) mode;
776 		syscallarg(int) dev;
777 	} */ *uap;
778 {
779 	struct vnode *vp;
780 	struct mount *mp;
781 	struct vattr vattr;
782 	int error;
783 	int whiteout = 0;
784 	struct nameidata nd;
785 
786 	switch (SCARG(uap, mode) & S_IFMT) {
787 	case S_IFCHR:
788 	case S_IFBLK:
789 		error = suser(td);
790 		break;
791 	default:
792 		error = suser_cred(td->td_ucred, PRISON_ROOT);
793 		break;
794 	}
795 	if (error)
796 		return (error);
797 restart:
798 	bwillwrite();
799 	NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), td);
800 	if ((error = namei(&nd)) != 0)
801 		return (error);
802 	vp = nd.ni_vp;
803 	if (vp != NULL) {
804 		vrele(vp);
805 		error = EEXIST;
806 	} else {
807 		VATTR_NULL(&vattr);
808 		FILEDESC_LOCK(td->td_proc->p_fd);
809 		vattr.va_mode = (SCARG(uap, mode) & ALLPERMS) &~ td->td_proc->p_fd->fd_cmask;
810 		FILEDESC_UNLOCK(td->td_proc->p_fd);
811 		vattr.va_rdev = SCARG(uap, dev);
812 		whiteout = 0;
813 
814 		switch (SCARG(uap, mode) & S_IFMT) {
815 		case S_IFMT:	/* used by badsect to flag bad sectors */
816 			vattr.va_type = VBAD;
817 			break;
818 		case S_IFCHR:
819 			vattr.va_type = VCHR;
820 			break;
821 		case S_IFBLK:
822 			vattr.va_type = VBLK;
823 			break;
824 		case S_IFWHT:
825 			whiteout = 1;
826 			break;
827 		default:
828 			error = EINVAL;
829 			break;
830 		}
831 	}
832 	if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) {
833 		NDFREE(&nd, NDF_ONLY_PNBUF);
834 		vput(nd.ni_dvp);
835 		if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0)
836 			return (error);
837 		goto restart;
838 	}
839 	if (!error) {
840 		VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
841 		if (whiteout)
842 			error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, CREATE);
843 		else {
844 			error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp,
845 						&nd.ni_cnd, &vattr);
846 			if (error == 0)
847 				vput(nd.ni_vp);
848 		}
849 	}
850 	NDFREE(&nd, NDF_ONLY_PNBUF);
851 	vput(nd.ni_dvp);
852 	vn_finished_write(mp);
853 	ASSERT_VOP_UNLOCKED(nd.ni_dvp, "mknod");
854 	ASSERT_VOP_UNLOCKED(nd.ni_vp, "mknod");
855 	return (error);
856 }
857 
858 /*
859  * Create a named pipe.
860  */
861 #ifndef _SYS_SYSPROTO_H_
862 struct mkfifo_args {
863 	char	*path;
864 	int	mode;
865 };
866 #endif
867 /* ARGSUSED */
868 int
869 mkfifo(td, uap)
870 	struct thread *td;
871 	register struct mkfifo_args /* {
872 		syscallarg(char *) path;
873 		syscallarg(int) mode;
874 	} */ *uap;
875 {
876 	struct mount *mp;
877 	struct vattr vattr;
878 	int error;
879 	struct nameidata nd;
880 
881 restart:
882 	bwillwrite();
883 	NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), td);
884 	if ((error = namei(&nd)) != 0)
885 		return (error);
886 	if (nd.ni_vp != NULL) {
887 		NDFREE(&nd, NDF_ONLY_PNBUF);
888 		vrele(nd.ni_vp);
889 		vput(nd.ni_dvp);
890 		return (EEXIST);
891 	}
892 	if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) {
893 		NDFREE(&nd, NDF_ONLY_PNBUF);
894 		vput(nd.ni_dvp);
895 		if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0)
896 			return (error);
897 		goto restart;
898 	}
899 	VATTR_NULL(&vattr);
900 	vattr.va_type = VFIFO;
901 	FILEDESC_LOCK(td->td_proc->p_fd);
902 	vattr.va_mode = (SCARG(uap, mode) & ALLPERMS) &~ td->td_proc->p_fd->fd_cmask;
903 	FILEDESC_UNLOCK(td->td_proc->p_fd);
904 	VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
905 	error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
906 	if (error == 0)
907 		vput(nd.ni_vp);
908 	NDFREE(&nd, NDF_ONLY_PNBUF);
909 	vput(nd.ni_dvp);
910 	vn_finished_write(mp);
911 	return (error);
912 }
913 
914 /*
915  * Make a hard file link.
916  */
917 #ifndef _SYS_SYSPROTO_H_
918 struct link_args {
919 	char	*path;
920 	char	*link;
921 };
922 #endif
923 /* ARGSUSED */
924 int
925 link(td, uap)
926 	struct thread *td;
927 	register struct link_args /* {
928 		syscallarg(char *) path;
929 		syscallarg(char *) link;
930 	} */ *uap;
931 {
932 	struct vnode *vp;
933 	struct mount *mp;
934 	struct nameidata nd;
935 	int error;
936 
937 	bwillwrite();
938 	NDINIT(&nd, LOOKUP, FOLLOW|NOOBJ, UIO_USERSPACE, SCARG(uap, path), td);
939 	if ((error = namei(&nd)) != 0)
940 		return (error);
941 	NDFREE(&nd, NDF_ONLY_PNBUF);
942 	vp = nd.ni_vp;
943 	if (vp->v_type == VDIR) {
944 		vrele(vp);
945 		return (EPERM);		/* POSIX */
946 	}
947 	if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) {
948 		vrele(vp);
949 		return (error);
950 	}
951 	NDINIT(&nd, CREATE, LOCKPARENT|NOOBJ, UIO_USERSPACE, SCARG(uap, link), td);
952 	if ((error = namei(&nd)) == 0) {
953 		if (nd.ni_vp != NULL) {
954 			vrele(nd.ni_vp);
955 			error = EEXIST;
956 		} else {
957 			VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
958 			VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
959 			error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd);
960 		}
961 		NDFREE(&nd, NDF_ONLY_PNBUF);
962 		vput(nd.ni_dvp);
963 	}
964 	vrele(vp);
965 	vn_finished_write(mp);
966 	ASSERT_VOP_UNLOCKED(nd.ni_dvp, "link");
967 	ASSERT_VOP_UNLOCKED(nd.ni_vp, "link");
968 	return (error);
969 }
970 
971 /*
972  * Make a symbolic link.
973  */
974 #ifndef _SYS_SYSPROTO_H_
975 struct symlink_args {
976 	char	*path;
977 	char	*link;
978 };
979 #endif
980 /* ARGSUSED */
981 int
982 symlink(td, uap)
983 	struct thread *td;
984 	register struct symlink_args /* {
985 		syscallarg(char *) path;
986 		syscallarg(char *) link;
987 	} */ *uap;
988 {
989 	struct mount *mp;
990 	struct vattr vattr;
991 	char *path;
992 	int error;
993 	struct nameidata nd;
994 
995 	path = uma_zalloc(namei_zone, M_WAITOK);
996 	if ((error = copyinstr(SCARG(uap, path), path, MAXPATHLEN, NULL)) != 0)
997 		goto out;
998 restart:
999 	bwillwrite();
1000 	NDINIT(&nd, CREATE, LOCKPARENT|NOOBJ, UIO_USERSPACE, SCARG(uap, link), td);
1001 	if ((error = namei(&nd)) != 0)
1002 		goto out;
1003 	if (nd.ni_vp) {
1004 		NDFREE(&nd, NDF_ONLY_PNBUF);
1005 		vrele(nd.ni_vp);
1006 		vput(nd.ni_dvp);
1007 		error = EEXIST;
1008 		goto out;
1009 	}
1010 	if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) {
1011 		NDFREE(&nd, NDF_ONLY_PNBUF);
1012 		vput(nd.ni_dvp);
1013 		if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0)
1014 			return (error);
1015 		goto restart;
1016 	}
1017 	VATTR_NULL(&vattr);
1018 	FILEDESC_LOCK(td->td_proc->p_fd);
1019 	vattr.va_mode = ACCESSPERMS &~ td->td_proc->p_fd->fd_cmask;
1020 	FILEDESC_UNLOCK(td->td_proc->p_fd);
1021 	VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
1022 	error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr, path);
1023 	NDFREE(&nd, NDF_ONLY_PNBUF);
1024 	if (error == 0)
1025 		vput(nd.ni_vp);
1026 	vput(nd.ni_dvp);
1027 	vn_finished_write(mp);
1028 	ASSERT_VOP_UNLOCKED(nd.ni_dvp, "symlink");
1029 	ASSERT_VOP_UNLOCKED(nd.ni_vp, "symlink");
1030 out:
1031 	uma_zfree(namei_zone, path);
1032 	return (error);
1033 }
1034 
1035 /*
1036  * Delete a whiteout from the filesystem.
1037  */
1038 /* ARGSUSED */
1039 int
1040 undelete(td, uap)
1041 	struct thread *td;
1042 	register struct undelete_args /* {
1043 		syscallarg(char *) path;
1044 	} */ *uap;
1045 {
1046 	int error;
1047 	struct mount *mp;
1048 	struct nameidata nd;
1049 
1050 restart:
1051 	bwillwrite();
1052 	NDINIT(&nd, DELETE, LOCKPARENT|DOWHITEOUT, UIO_USERSPACE,
1053 	    SCARG(uap, path), td);
1054 	error = namei(&nd);
1055 	if (error)
1056 		return (error);
1057 
1058 	if (nd.ni_vp != NULLVP || !(nd.ni_cnd.cn_flags & ISWHITEOUT)) {
1059 		NDFREE(&nd, NDF_ONLY_PNBUF);
1060 		if (nd.ni_vp)
1061 			vrele(nd.ni_vp);
1062 		vput(nd.ni_dvp);
1063 		return (EEXIST);
1064 	}
1065 	if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) {
1066 		NDFREE(&nd, NDF_ONLY_PNBUF);
1067 		vput(nd.ni_dvp);
1068 		if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0)
1069 			return (error);
1070 		goto restart;
1071 	}
1072 	VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
1073 	error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, DELETE);
1074 	NDFREE(&nd, NDF_ONLY_PNBUF);
1075 	vput(nd.ni_dvp);
1076 	vn_finished_write(mp);
1077 	ASSERT_VOP_UNLOCKED(nd.ni_dvp, "undelete");
1078 	ASSERT_VOP_UNLOCKED(nd.ni_vp, "undelete");
1079 	return (error);
1080 }
1081 
1082 /*
1083  * Delete a name from the filesystem.
1084  */
1085 #ifndef _SYS_SYSPROTO_H_
1086 struct unlink_args {
1087 	char	*path;
1088 };
1089 #endif
1090 /* ARGSUSED */
1091 int
1092 unlink(td, uap)
1093 	struct thread *td;
1094 	struct unlink_args /* {
1095 		syscallarg(char *) path;
1096 	} */ *uap;
1097 {
1098 	struct mount *mp;
1099 	struct vnode *vp;
1100 	int error;
1101 	struct nameidata nd;
1102 
1103 restart:
1104 	bwillwrite();
1105 	NDINIT(&nd, DELETE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), td);
1106 	if ((error = namei(&nd)) != 0)
1107 		return (error);
1108 	vp = nd.ni_vp;
1109 	if (vp->v_type == VDIR)
1110 		error = EPERM;		/* POSIX */
1111 	else {
1112 		/*
1113 		 * The root of a mounted filesystem cannot be deleted.
1114 		 *
1115 		 * XXX: can this only be a VDIR case?
1116 		 */
1117 		if (vp->v_flag & VROOT)
1118 			error = EBUSY;
1119 	}
1120 	if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) {
1121 		NDFREE(&nd, NDF_ONLY_PNBUF);
1122 		vrele(vp);
1123 		vput(nd.ni_dvp);
1124 		if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0)
1125 			return (error);
1126 		goto restart;
1127 	}
1128 	VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
1129 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
1130 	if (!error) {
1131 		VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
1132 		error = VOP_REMOVE(nd.ni_dvp, vp, &nd.ni_cnd);
1133 	}
1134 	NDFREE(&nd, NDF_ONLY_PNBUF);
1135 	vput(nd.ni_dvp);
1136 	vput(vp);
1137 	vn_finished_write(mp);
1138 	ASSERT_VOP_UNLOCKED(nd.ni_dvp, "unlink");
1139 	ASSERT_VOP_UNLOCKED(nd.ni_vp, "unlink");
1140 	return (error);
1141 }
1142 
1143 /*
1144  * Reposition read/write file offset.
1145  */
1146 #ifndef _SYS_SYSPROTO_H_
1147 struct lseek_args {
1148 	int	fd;
1149 	int	pad;
1150 	off_t	offset;
1151 	int	whence;
1152 };
1153 #endif
1154 int
1155 lseek(td, uap)
1156 	struct thread *td;
1157 	register struct lseek_args /* {
1158 		syscallarg(int) fd;
1159 		syscallarg(int) pad;
1160 		syscallarg(off_t) offset;
1161 		syscallarg(int) whence;
1162 	} */ *uap;
1163 {
1164 	struct ucred *cred = td->td_ucred;
1165 	struct file *fp;
1166 	struct vnode *vp;
1167 	struct vattr vattr;
1168 	off_t offset;
1169 	int error, noneg;
1170 
1171 	if ((error = fget(td, uap->fd, &fp)) != 0)
1172 		return (error);
1173 	if (fp->f_type != DTYPE_VNODE) {
1174 		fdrop(fp, td);
1175 		return (ESPIPE);
1176 	}
1177 	vp = (struct vnode *)fp->f_data;
1178 	noneg = (vp->v_type != VCHR);
1179 	offset = SCARG(uap, offset);
1180 	switch (SCARG(uap, whence)) {
1181 	case L_INCR:
1182 		if (noneg &&
1183 		    (fp->f_offset < 0 ||
1184 		     (offset > 0 && fp->f_offset > OFF_MAX - offset)))
1185 			return (EOVERFLOW);
1186 		offset += fp->f_offset;
1187 		break;
1188 	case L_XTND:
1189 		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
1190 		error = VOP_GETATTR(vp, &vattr, cred, td);
1191 		VOP_UNLOCK(vp, 0, td);
1192 		if (error)
1193 			return (error);
1194 		if (noneg &&
1195 		    (vattr.va_size > OFF_MAX ||
1196 		     (offset > 0 && vattr.va_size > OFF_MAX - offset)))
1197 			return (EOVERFLOW);
1198 		offset += vattr.va_size;
1199 		break;
1200 	case L_SET:
1201 		break;
1202 	default:
1203 		fdrop(fp, td);
1204 		return (EINVAL);
1205 	}
1206 	if (noneg && offset < 0)
1207 		return (EINVAL);
1208 	fp->f_offset = offset;
1209 	*(off_t *)(td->td_retval) = fp->f_offset;
1210 	fdrop(fp, td);
1211 	return (0);
1212 }
1213 
1214 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
1215 /*
1216  * Reposition read/write file offset.
1217  */
1218 #ifndef _SYS_SYSPROTO_H_
1219 struct olseek_args {
1220 	int	fd;
1221 	long	offset;
1222 	int	whence;
1223 };
1224 #endif
1225 int
1226 olseek(td, uap)
1227 	struct thread *td;
1228 	register struct olseek_args /* {
1229 		syscallarg(int) fd;
1230 		syscallarg(long) offset;
1231 		syscallarg(int) whence;
1232 	} */ *uap;
1233 {
1234 	struct lseek_args /* {
1235 		syscallarg(int) fd;
1236 		syscallarg(int) pad;
1237 		syscallarg(off_t) offset;
1238 		syscallarg(int) whence;
1239 	} */ nuap;
1240 	int error;
1241 
1242 	SCARG(&nuap, fd) = SCARG(uap, fd);
1243 	SCARG(&nuap, offset) = SCARG(uap, offset);
1244 	SCARG(&nuap, whence) = SCARG(uap, whence);
1245 	error = lseek(td, &nuap);
1246 	return (error);
1247 }
1248 #endif /* COMPAT_43 */
1249 
1250 /*
1251  * Check access permissions using passed credentials.
1252  */
1253 static int
1254 vn_access(vp, user_flags, cred, td)
1255 	struct vnode	*vp;
1256 	int		user_flags;
1257 	struct ucred	*cred;
1258 	struct thread	*td;
1259 {
1260 	int error, flags;
1261 
1262 	/* Flags == 0 means only check for existence. */
1263 	error = 0;
1264 	if (user_flags) {
1265 		flags = 0;
1266 		if (user_flags & R_OK)
1267 			flags |= VREAD;
1268 		if (user_flags & W_OK)
1269 			flags |= VWRITE;
1270 		if (user_flags & X_OK)
1271 			flags |= VEXEC;
1272 		if ((flags & VWRITE) == 0 || (error = vn_writechk(vp)) == 0)
1273 			error = VOP_ACCESS(vp, flags, cred, td);
1274 	}
1275 	return (error);
1276 }
1277 
1278 /*
1279  * Check access permissions using "real" credentials.
1280  */
1281 #ifndef _SYS_SYSPROTO_H_
1282 struct access_args {
1283 	char	*path;
1284 	int	flags;
1285 };
1286 #endif
1287 int
1288 access(td, uap)
1289 	struct thread *td;
1290 	register struct access_args /* {
1291 		syscallarg(char *) path;
1292 		syscallarg(int) flags;
1293 	} */ *uap;
1294 {
1295 	struct ucred *cred, *tmpcred;
1296 	register struct vnode *vp;
1297 	int error;
1298 	struct nameidata nd;
1299 
1300 	/*
1301 	 * Create and modify a temporary credential instead of one that
1302 	 * is potentially shared.  This could also mess up socket
1303 	 * buffer accounting which can run in an interrupt context.
1304 	 *
1305 	 * XXX - Depending on how "threads" are finally implemented, it
1306 	 * may be better to explicitly pass the credential to namei()
1307 	 * rather than to modify the potentially shared process structure.
1308 	 */
1309 	cred = td->td_ucred;
1310 	tmpcred = crdup(cred);
1311 	tmpcred->cr_uid = cred->cr_ruid;
1312 	tmpcred->cr_groups[0] = cred->cr_rgid;
1313 	td->td_ucred = tmpcred;
1314 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
1315 	    SCARG(uap, path), td);
1316 	if ((error = namei(&nd)) != 0)
1317 		goto out1;
1318 	vp = nd.ni_vp;
1319 
1320 	error = vn_access(vp, SCARG(uap, flags), tmpcred, td);
1321 	NDFREE(&nd, NDF_ONLY_PNBUF);
1322 	vput(vp);
1323 out1:
1324 	td->td_ucred = cred;
1325 	crfree(tmpcred);
1326 	return (error);
1327 }
1328 
1329 /*
1330  * Check access permissions using "effective" credentials.
1331  */
1332 #ifndef _SYS_SYSPROTO_H_
1333 struct eaccess_args {
1334 	char	*path;
1335 	int	flags;
1336 };
1337 #endif
1338 int
1339 eaccess(td, uap)
1340 	struct thread *td;
1341 	register struct eaccess_args /* {
1342 		syscallarg(char *) path;
1343 		syscallarg(int) flags;
1344 	} */ *uap;
1345 {
1346 	struct nameidata nd;
1347 	struct vnode *vp;
1348 	int error;
1349 
1350 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
1351 	    SCARG(uap, path), td);
1352 	if ((error = namei(&nd)) != 0)
1353 		return (error);
1354 	vp = nd.ni_vp;
1355 
1356 	error = vn_access(vp, SCARG(uap, flags), td->td_ucred, td);
1357 	NDFREE(&nd, NDF_ONLY_PNBUF);
1358 	vput(vp);
1359 	return (error);
1360 }
1361 
1362 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
1363 /*
1364  * Get file status; this version follows links.
1365  */
1366 #ifndef _SYS_SYSPROTO_H_
1367 struct ostat_args {
1368 	char	*path;
1369 	struct ostat *ub;
1370 };
1371 #endif
1372 /* ARGSUSED */
1373 int
1374 ostat(td, uap)
1375 	struct thread *td;
1376 	register struct ostat_args /* {
1377 		syscallarg(char *) path;
1378 		syscallarg(struct ostat *) ub;
1379 	} */ *uap;
1380 {
1381 	struct stat sb;
1382 	struct ostat osb;
1383 	int error;
1384 	struct nameidata nd;
1385 
1386 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
1387 	    SCARG(uap, path), td);
1388 	if ((error = namei(&nd)) != 0)
1389 		return (error);
1390 	NDFREE(&nd, NDF_ONLY_PNBUF);
1391 	error = vn_stat(nd.ni_vp, &sb, td);
1392 	vput(nd.ni_vp);
1393 	if (error)
1394 		return (error);
1395 	cvtstat(&sb, &osb);
1396 	error = copyout(&osb, SCARG(uap, ub), sizeof (osb));
1397 	return (error);
1398 }
1399 
1400 /*
1401  * Get file status; this version does not follow links.
1402  */
1403 #ifndef _SYS_SYSPROTO_H_
1404 struct olstat_args {
1405 	char	*path;
1406 	struct ostat *ub;
1407 };
1408 #endif
1409 /* ARGSUSED */
1410 int
1411 olstat(td, uap)
1412 	struct thread *td;
1413 	register struct olstat_args /* {
1414 		syscallarg(char *) path;
1415 		syscallarg(struct ostat *) ub;
1416 	} */ *uap;
1417 {
1418 	struct vnode *vp;
1419 	struct stat sb;
1420 	struct ostat osb;
1421 	int error;
1422 	struct nameidata nd;
1423 
1424 	NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
1425 	    SCARG(uap, path), td);
1426 	if ((error = namei(&nd)) != 0)
1427 		return (error);
1428 	vp = nd.ni_vp;
1429 	error = vn_stat(vp, &sb, td);
1430 	NDFREE(&nd, NDF_ONLY_PNBUF);
1431 	vput(vp);
1432 	if (error)
1433 		return (error);
1434 	cvtstat(&sb, &osb);
1435 	error = copyout(&osb, SCARG(uap, ub), sizeof (osb));
1436 	return (error);
1437 }
1438 
1439 /*
1440  * Convert from an old to a new stat structure.
1441  */
1442 void
1443 cvtstat(st, ost)
1444 	struct stat *st;
1445 	struct ostat *ost;
1446 {
1447 
1448 	ost->st_dev = st->st_dev;
1449 	ost->st_ino = st->st_ino;
1450 	ost->st_mode = st->st_mode;
1451 	ost->st_nlink = st->st_nlink;
1452 	ost->st_uid = st->st_uid;
1453 	ost->st_gid = st->st_gid;
1454 	ost->st_rdev = st->st_rdev;
1455 	if (st->st_size < (quad_t)1 << 32)
1456 		ost->st_size = st->st_size;
1457 	else
1458 		ost->st_size = -2;
1459 	ost->st_atime = st->st_atime;
1460 	ost->st_mtime = st->st_mtime;
1461 	ost->st_ctime = st->st_ctime;
1462 	ost->st_blksize = st->st_blksize;
1463 	ost->st_blocks = st->st_blocks;
1464 	ost->st_flags = st->st_flags;
1465 	ost->st_gen = st->st_gen;
1466 }
1467 #endif /* COMPAT_43 || COMPAT_SUNOS */
1468 
1469 /*
1470  * Get file status; this version follows links.
1471  */
1472 #ifndef _SYS_SYSPROTO_H_
1473 struct stat_args {
1474 	char	*path;
1475 	struct stat *ub;
1476 };
1477 #endif
1478 /* ARGSUSED */
1479 int
1480 stat(td, uap)
1481 	struct thread *td;
1482 	register struct stat_args /* {
1483 		syscallarg(char *) path;
1484 		syscallarg(struct stat *) ub;
1485 	} */ *uap;
1486 {
1487 	struct stat sb;
1488 	int error;
1489 	struct nameidata nd;
1490 
1491 #ifdef LOOKUP_SHARED
1492 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKSHARED | LOCKLEAF | NOOBJ,
1493 	    UIO_USERSPACE, SCARG(uap, path), td);
1494 #else
1495 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
1496 	    SCARG(uap, path), td);
1497 #endif
1498 	if ((error = namei(&nd)) != 0)
1499 		return (error);
1500 	error = vn_stat(nd.ni_vp, &sb, td);
1501 	NDFREE(&nd, NDF_ONLY_PNBUF);
1502 	vput(nd.ni_vp);
1503 	if (error)
1504 		return (error);
1505 	error = copyout(&sb, SCARG(uap, ub), sizeof (sb));
1506 	return (error);
1507 }
1508 
1509 /*
1510  * Get file status; this version does not follow links.
1511  */
1512 #ifndef _SYS_SYSPROTO_H_
1513 struct lstat_args {
1514 	char	*path;
1515 	struct stat *ub;
1516 };
1517 #endif
1518 /* ARGSUSED */
1519 int
1520 lstat(td, uap)
1521 	struct thread *td;
1522 	register struct lstat_args /* {
1523 		syscallarg(char *) path;
1524 		syscallarg(struct stat *) ub;
1525 	} */ *uap;
1526 {
1527 	int error;
1528 	struct vnode *vp;
1529 	struct stat sb;
1530 	struct nameidata nd;
1531 
1532 	NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
1533 	    SCARG(uap, path), td);
1534 	if ((error = namei(&nd)) != 0)
1535 		return (error);
1536 	vp = nd.ni_vp;
1537 	error = vn_stat(vp, &sb, td);
1538 	NDFREE(&nd, NDF_ONLY_PNBUF);
1539 	vput(vp);
1540 	if (error)
1541 		return (error);
1542 	error = copyout(&sb, SCARG(uap, ub), sizeof (sb));
1543 	return (error);
1544 }
1545 
1546 /*
1547  * Implementation of the NetBSD stat() function.
1548  * XXX This should probably be collapsed with the FreeBSD version,
1549  * as the differences are only due to vn_stat() clearing spares at
1550  * the end of the structures.  vn_stat could be split to avoid this,
1551  * and thus collapse the following to close to zero code.
1552  */
1553 void
1554 cvtnstat(sb, nsb)
1555 	struct stat *sb;
1556 	struct nstat *nsb;
1557 {
1558 	bzero(nsb, sizeof *nsb);
1559 	nsb->st_dev = sb->st_dev;
1560 	nsb->st_ino = sb->st_ino;
1561 	nsb->st_mode = sb->st_mode;
1562 	nsb->st_nlink = sb->st_nlink;
1563 	nsb->st_uid = sb->st_uid;
1564 	nsb->st_gid = sb->st_gid;
1565 	nsb->st_rdev = sb->st_rdev;
1566 	nsb->st_atimespec = sb->st_atimespec;
1567 	nsb->st_mtimespec = sb->st_mtimespec;
1568 	nsb->st_ctimespec = sb->st_ctimespec;
1569 	nsb->st_size = sb->st_size;
1570 	nsb->st_blocks = sb->st_blocks;
1571 	nsb->st_blksize = sb->st_blksize;
1572 	nsb->st_flags = sb->st_flags;
1573 	nsb->st_gen = sb->st_gen;
1574 	nsb->st_createtimespec = sb->st_createtimespec;
1575 }
1576 
1577 #ifndef _SYS_SYSPROTO_H_
1578 struct nstat_args {
1579 	char	*path;
1580 	struct nstat *ub;
1581 };
1582 #endif
1583 /* ARGSUSED */
1584 int
1585 nstat(td, uap)
1586 	struct thread *td;
1587 	register struct nstat_args /* {
1588 		syscallarg(char *) path;
1589 		syscallarg(struct nstat *) ub;
1590 	} */ *uap;
1591 {
1592 	struct stat sb;
1593 	struct nstat nsb;
1594 	int error;
1595 	struct nameidata nd;
1596 
1597 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
1598 	    SCARG(uap, path), td);
1599 	if ((error = namei(&nd)) != 0)
1600 		return (error);
1601 	NDFREE(&nd, NDF_ONLY_PNBUF);
1602 	error = vn_stat(nd.ni_vp, &sb, td);
1603 	vput(nd.ni_vp);
1604 	if (error)
1605 		return (error);
1606 	cvtnstat(&sb, &nsb);
1607 	error = copyout(&nsb, SCARG(uap, ub), sizeof (nsb));
1608 	return (error);
1609 }
1610 
1611 /*
1612  * NetBSD lstat.  Get file status; this version does not follow links.
1613  */
1614 #ifndef _SYS_SYSPROTO_H_
1615 struct lstat_args {
1616 	char	*path;
1617 	struct stat *ub;
1618 };
1619 #endif
1620 /* ARGSUSED */
1621 int
1622 nlstat(td, uap)
1623 	struct thread *td;
1624 	register struct nlstat_args /* {
1625 		syscallarg(char *) path;
1626 		syscallarg(struct nstat *) ub;
1627 	} */ *uap;
1628 {
1629 	int error;
1630 	struct vnode *vp;
1631 	struct stat sb;
1632 	struct nstat nsb;
1633 	struct nameidata nd;
1634 
1635 	NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
1636 	    SCARG(uap, path), td);
1637 	if ((error = namei(&nd)) != 0)
1638 		return (error);
1639 	vp = nd.ni_vp;
1640 	NDFREE(&nd, NDF_ONLY_PNBUF);
1641 	error = vn_stat(vp, &sb, td);
1642 	vput(vp);
1643 	if (error)
1644 		return (error);
1645 	cvtnstat(&sb, &nsb);
1646 	error = copyout(&nsb, SCARG(uap, ub), sizeof (nsb));
1647 	return (error);
1648 }
1649 
1650 /*
1651  * Get configurable pathname variables.
1652  */
1653 #ifndef _SYS_SYSPROTO_H_
1654 struct pathconf_args {
1655 	char	*path;
1656 	int	name;
1657 };
1658 #endif
1659 /* ARGSUSED */
1660 int
1661 pathconf(td, uap)
1662 	struct thread *td;
1663 	register struct pathconf_args /* {
1664 		syscallarg(char *) path;
1665 		syscallarg(int) name;
1666 	} */ *uap;
1667 {
1668 	int error;
1669 	struct nameidata nd;
1670 
1671 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
1672 	    SCARG(uap, path), td);
1673 	if ((error = namei(&nd)) != 0)
1674 		return (error);
1675 	NDFREE(&nd, NDF_ONLY_PNBUF);
1676 	error = VOP_PATHCONF(nd.ni_vp, SCARG(uap, name), td->td_retval);
1677 	vput(nd.ni_vp);
1678 	return (error);
1679 }
1680 
1681 /*
1682  * Return target name of a symbolic link.
1683  */
1684 #ifndef _SYS_SYSPROTO_H_
1685 struct readlink_args {
1686 	char	*path;
1687 	char	*buf;
1688 	int	count;
1689 };
1690 #endif
1691 /* ARGSUSED */
1692 int
1693 readlink(td, uap)
1694 	struct thread *td;
1695 	register struct readlink_args /* {
1696 		syscallarg(char *) path;
1697 		syscallarg(char *) buf;
1698 		syscallarg(int) count;
1699 	} */ *uap;
1700 {
1701 	register struct vnode *vp;
1702 	struct iovec aiov;
1703 	struct uio auio;
1704 	int error;
1705 	struct nameidata nd;
1706 
1707 	NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
1708 	    SCARG(uap, path), td);
1709 	if ((error = namei(&nd)) != 0)
1710 		return (error);
1711 	NDFREE(&nd, NDF_ONLY_PNBUF);
1712 	vp = nd.ni_vp;
1713 	if (vp->v_type != VLNK)
1714 		error = EINVAL;
1715 	else {
1716 		aiov.iov_base = SCARG(uap, buf);
1717 		aiov.iov_len = SCARG(uap, count);
1718 		auio.uio_iov = &aiov;
1719 		auio.uio_iovcnt = 1;
1720 		auio.uio_offset = 0;
1721 		auio.uio_rw = UIO_READ;
1722 		auio.uio_segflg = UIO_USERSPACE;
1723 		auio.uio_td = td;
1724 		auio.uio_resid = SCARG(uap, count);
1725 		error = VOP_READLINK(vp, &auio, td->td_ucred);
1726 	}
1727 	vput(vp);
1728 	td->td_retval[0] = SCARG(uap, count) - auio.uio_resid;
1729 	return (error);
1730 }
1731 
1732 /*
1733  * Common implementation code for chflags() and fchflags().
1734  */
1735 static int
1736 setfflags(td, vp, flags)
1737 	struct thread *td;
1738 	struct vnode *vp;
1739 	int flags;
1740 {
1741 	int error;
1742 	struct mount *mp;
1743 	struct vattr vattr;
1744 
1745 	/*
1746 	 * Prevent non-root users from setting flags on devices.  When
1747 	 * a device is reused, users can retain ownership of the device
1748 	 * if they are allowed to set flags and programs assume that
1749 	 * chown can't fail when done as root.
1750 	 */
1751 	if (vp->v_type == VCHR || vp->v_type == VBLK) {
1752 		error = suser_cred(td->td_ucred, PRISON_ROOT);
1753 		if (error)
1754 			return (error);
1755 	}
1756 
1757 	if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
1758 		return (error);
1759 	VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
1760 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
1761 	VATTR_NULL(&vattr);
1762 	vattr.va_flags = flags;
1763 	error = VOP_SETATTR(vp, &vattr, td->td_ucred, td);
1764 	VOP_UNLOCK(vp, 0, td);
1765 	vn_finished_write(mp);
1766 	return (error);
1767 }
1768 
1769 /*
1770  * Change flags of a file given a path name.
1771  */
1772 #ifndef _SYS_SYSPROTO_H_
1773 struct chflags_args {
1774 	char	*path;
1775 	int	flags;
1776 };
1777 #endif
1778 /* ARGSUSED */
1779 int
1780 chflags(td, uap)
1781 	struct thread *td;
1782 	register struct chflags_args /* {
1783 		syscallarg(char *) path;
1784 		syscallarg(int) flags;
1785 	} */ *uap;
1786 {
1787 	int error;
1788 	struct nameidata nd;
1789 
1790 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td);
1791 	if ((error = namei(&nd)) != 0)
1792 		return (error);
1793 	NDFREE(&nd, NDF_ONLY_PNBUF);
1794 	error = setfflags(td, nd.ni_vp, SCARG(uap, flags));
1795 	vrele(nd.ni_vp);
1796 	return error;
1797 }
1798 
1799 /*
1800  * Same as chflags() but doesn't follow symlinks.
1801  */
1802 int
1803 lchflags(td, uap)
1804 	struct thread *td;
1805 	register struct lchflags_args /* {
1806 		syscallarg(char *) path;
1807 		syscallarg(int) flags;
1808 	} */ *uap;
1809 {
1810 	int error;
1811 	struct nameidata nd;
1812 
1813 	NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), td);
1814 	if ((error = namei(&nd)) != 0)
1815 		return (error);
1816 	NDFREE(&nd, NDF_ONLY_PNBUF);
1817 	error = setfflags(td, nd.ni_vp, SCARG(uap, flags));
1818 	vrele(nd.ni_vp);
1819 	return error;
1820 }
1821 
1822 /*
1823  * Change flags of a file given a file descriptor.
1824  */
1825 #ifndef _SYS_SYSPROTO_H_
1826 struct fchflags_args {
1827 	int	fd;
1828 	int	flags;
1829 };
1830 #endif
1831 /* ARGSUSED */
1832 int
1833 fchflags(td, uap)
1834 	struct thread *td;
1835 	register struct fchflags_args /* {
1836 		syscallarg(int) fd;
1837 		syscallarg(int) flags;
1838 	} */ *uap;
1839 {
1840 	struct file *fp;
1841 	int error;
1842 
1843 	if ((error = getvnode(td->td_proc->p_fd, SCARG(uap, fd), &fp)) != 0)
1844 		return (error);
1845 	error = setfflags(td, (struct vnode *) fp->f_data, SCARG(uap, flags));
1846 	fdrop(fp, td);
1847 	return (error);
1848 }
1849 
1850 /*
1851  * Common implementation code for chmod(), lchmod() and fchmod().
1852  */
1853 static int
1854 setfmode(td, vp, mode)
1855 	struct thread *td;
1856 	struct vnode *vp;
1857 	int mode;
1858 {
1859 	int error;
1860 	struct mount *mp;
1861 	struct vattr vattr;
1862 
1863 	if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
1864 		return (error);
1865 	VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
1866 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
1867 	VATTR_NULL(&vattr);
1868 	vattr.va_mode = mode & ALLPERMS;
1869 	error = VOP_SETATTR(vp, &vattr, td->td_ucred, td);
1870 	VOP_UNLOCK(vp, 0, td);
1871 	vn_finished_write(mp);
1872 	return error;
1873 }
1874 
1875 /*
1876  * Change mode of a file given path name.
1877  */
1878 #ifndef _SYS_SYSPROTO_H_
1879 struct chmod_args {
1880 	char	*path;
1881 	int	mode;
1882 };
1883 #endif
1884 /* ARGSUSED */
1885 int
1886 chmod(td, uap)
1887 	struct thread *td;
1888 	register struct chmod_args /* {
1889 		syscallarg(char *) path;
1890 		syscallarg(int) mode;
1891 	} */ *uap;
1892 {
1893 	int error;
1894 	struct nameidata nd;
1895 
1896 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td);
1897 	if ((error = namei(&nd)) != 0)
1898 		return (error);
1899 	NDFREE(&nd, NDF_ONLY_PNBUF);
1900 	error = setfmode(td, nd.ni_vp, SCARG(uap, mode));
1901 	vrele(nd.ni_vp);
1902 	return error;
1903 }
1904 
1905 /*
1906  * Change mode of a file given path name (don't follow links.)
1907  */
1908 #ifndef _SYS_SYSPROTO_H_
1909 struct lchmod_args {
1910 	char	*path;
1911 	int	mode;
1912 };
1913 #endif
1914 /* ARGSUSED */
1915 int
1916 lchmod(td, uap)
1917 	struct thread *td;
1918 	register struct lchmod_args /* {
1919 		syscallarg(char *) path;
1920 		syscallarg(int) mode;
1921 	} */ *uap;
1922 {
1923 	int error;
1924 	struct nameidata nd;
1925 
1926 	NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), td);
1927 	if ((error = namei(&nd)) != 0)
1928 		return (error);
1929 	NDFREE(&nd, NDF_ONLY_PNBUF);
1930 	error = setfmode(td, nd.ni_vp, SCARG(uap, mode));
1931 	vrele(nd.ni_vp);
1932 	return error;
1933 }
1934 
1935 /*
1936  * Change mode of a file given a file descriptor.
1937  */
1938 #ifndef _SYS_SYSPROTO_H_
1939 struct fchmod_args {
1940 	int	fd;
1941 	int	mode;
1942 };
1943 #endif
1944 /* ARGSUSED */
1945 int
1946 fchmod(td, uap)
1947 	struct thread *td;
1948 	register struct fchmod_args /* {
1949 		syscallarg(int) fd;
1950 		syscallarg(int) mode;
1951 	} */ *uap;
1952 {
1953 	struct file *fp;
1954 	struct vnode *vp;
1955 	int error;
1956 
1957 	if ((error = getvnode(td->td_proc->p_fd, SCARG(uap, fd), &fp)) != 0)
1958 		return (error);
1959 	vp = (struct vnode *)fp->f_data;
1960 	error = setfmode(td, (struct vnode *)fp->f_data, SCARG(uap, mode));
1961 	fdrop(fp, td);
1962 	return (error);
1963 }
1964 
1965 /*
1966  * Common implementation for chown(), lchown(), and fchown()
1967  */
1968 static int
1969 setfown(td, vp, uid, gid)
1970 	struct thread *td;
1971 	struct vnode *vp;
1972 	uid_t uid;
1973 	gid_t gid;
1974 {
1975 	int error;
1976 	struct mount *mp;
1977 	struct vattr vattr;
1978 
1979 	if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
1980 		return (error);
1981 	VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
1982 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
1983 	VATTR_NULL(&vattr);
1984 	vattr.va_uid = uid;
1985 	vattr.va_gid = gid;
1986 	error = VOP_SETATTR(vp, &vattr, td->td_ucred, td);
1987 	VOP_UNLOCK(vp, 0, td);
1988 	vn_finished_write(mp);
1989 	return error;
1990 }
1991 
1992 /*
1993  * Set ownership given a path name.
1994  */
1995 #ifndef _SYS_SYSPROTO_H_
1996 struct chown_args {
1997 	char	*path;
1998 	int	uid;
1999 	int	gid;
2000 };
2001 #endif
2002 /* ARGSUSED */
2003 int
2004 chown(td, uap)
2005 	struct thread *td;
2006 	register struct chown_args /* {
2007 		syscallarg(char *) path;
2008 		syscallarg(int) uid;
2009 		syscallarg(int) gid;
2010 	} */ *uap;
2011 {
2012 	int error;
2013 	struct nameidata nd;
2014 
2015 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td);
2016 	if ((error = namei(&nd)) != 0)
2017 		return (error);
2018 	NDFREE(&nd, NDF_ONLY_PNBUF);
2019 	error = setfown(td, nd.ni_vp, SCARG(uap, uid), SCARG(uap, gid));
2020 	vrele(nd.ni_vp);
2021 	return (error);
2022 }
2023 
2024 /*
2025  * Set ownership given a path name, do not cross symlinks.
2026  */
2027 #ifndef _SYS_SYSPROTO_H_
2028 struct lchown_args {
2029 	char	*path;
2030 	int	uid;
2031 	int	gid;
2032 };
2033 #endif
2034 /* ARGSUSED */
2035 int
2036 lchown(td, uap)
2037 	struct thread *td;
2038 	register struct lchown_args /* {
2039 		syscallarg(char *) path;
2040 		syscallarg(int) uid;
2041 		syscallarg(int) gid;
2042 	} */ *uap;
2043 {
2044 	int error;
2045 	struct nameidata nd;
2046 
2047 	NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), td);
2048 	if ((error = namei(&nd)) != 0)
2049 		return (error);
2050 	NDFREE(&nd, NDF_ONLY_PNBUF);
2051 	error = setfown(td, nd.ni_vp, SCARG(uap, uid), SCARG(uap, gid));
2052 	vrele(nd.ni_vp);
2053 	return (error);
2054 }
2055 
2056 /*
2057  * Set ownership given a file descriptor.
2058  */
2059 #ifndef _SYS_SYSPROTO_H_
2060 struct fchown_args {
2061 	int	fd;
2062 	int	uid;
2063 	int	gid;
2064 };
2065 #endif
2066 /* ARGSUSED */
2067 int
2068 fchown(td, uap)
2069 	struct thread *td;
2070 	register struct fchown_args /* {
2071 		syscallarg(int) fd;
2072 		syscallarg(int) uid;
2073 		syscallarg(int) gid;
2074 	} */ *uap;
2075 {
2076 	struct file *fp;
2077 	struct vnode *vp;
2078 	int error;
2079 
2080 	if ((error = getvnode(td->td_proc->p_fd, SCARG(uap, fd), &fp)) != 0)
2081 		return (error);
2082 	vp = (struct vnode *)fp->f_data;
2083 	error = setfown(td, (struct vnode *)fp->f_data,
2084 		SCARG(uap, uid), SCARG(uap, gid));
2085 	fdrop(fp, td);
2086 	return (error);
2087 }
2088 
2089 /*
2090  * Common implementation code for utimes(), lutimes(), and futimes().
2091  */
2092 static int
2093 getutimes(usrtvp, tsp)
2094 	const struct timeval *usrtvp;
2095 	struct timespec *tsp;
2096 {
2097 	struct timeval tv[2];
2098 	int error;
2099 
2100 	if (usrtvp == NULL) {
2101 		microtime(&tv[0]);
2102 		TIMEVAL_TO_TIMESPEC(&tv[0], &tsp[0]);
2103 		tsp[1] = tsp[0];
2104 	} else {
2105 		if ((error = copyin(usrtvp, tv, sizeof (tv))) != 0)
2106 			return (error);
2107 		TIMEVAL_TO_TIMESPEC(&tv[0], &tsp[0]);
2108 		TIMEVAL_TO_TIMESPEC(&tv[1], &tsp[1]);
2109 	}
2110 	return 0;
2111 }
2112 
2113 /*
2114  * Common implementation code for utimes(), lutimes(), and futimes().
2115  */
2116 static int
2117 setutimes(td, vp, ts, nullflag)
2118 	struct thread *td;
2119 	struct vnode *vp;
2120 	const struct timespec *ts;
2121 	int nullflag;
2122 {
2123 	int error;
2124 	struct mount *mp;
2125 	struct vattr vattr;
2126 
2127 	if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
2128 		return (error);
2129 	VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
2130 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
2131 	VATTR_NULL(&vattr);
2132 	vattr.va_atime = ts[0];
2133 	vattr.va_mtime = ts[1];
2134 	if (nullflag)
2135 		vattr.va_vaflags |= VA_UTIMES_NULL;
2136 	error = VOP_SETATTR(vp, &vattr, td->td_ucred, td);
2137 	VOP_UNLOCK(vp, 0, td);
2138 	vn_finished_write(mp);
2139 	return error;
2140 }
2141 
2142 /*
2143  * Set the access and modification times of a file.
2144  */
2145 #ifndef _SYS_SYSPROTO_H_
2146 struct utimes_args {
2147 	char	*path;
2148 	struct	timeval *tptr;
2149 };
2150 #endif
2151 /* ARGSUSED */
2152 int
2153 utimes(td, uap)
2154 	struct thread *td;
2155 	register struct utimes_args /* {
2156 		syscallarg(char *) path;
2157 		syscallarg(struct timeval *) tptr;
2158 	} */ *uap;
2159 {
2160 	struct timespec ts[2];
2161 	struct timeval *usrtvp;
2162 	int error;
2163 	struct nameidata nd;
2164 
2165 	usrtvp = SCARG(uap, tptr);
2166 	if ((error = getutimes(usrtvp, ts)) != 0)
2167 		return (error);
2168 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td);
2169 	if ((error = namei(&nd)) != 0)
2170 		return (error);
2171 	NDFREE(&nd, NDF_ONLY_PNBUF);
2172 	error = setutimes(td, nd.ni_vp, ts, usrtvp == NULL);
2173 	vrele(nd.ni_vp);
2174 	return (error);
2175 }
2176 
2177 /*
2178  * Set the access and modification times of a file.
2179  */
2180 #ifndef _SYS_SYSPROTO_H_
2181 struct lutimes_args {
2182 	char	*path;
2183 	struct	timeval *tptr;
2184 };
2185 #endif
2186 /* ARGSUSED */
2187 int
2188 lutimes(td, uap)
2189 	struct thread *td;
2190 	register struct lutimes_args /* {
2191 		syscallarg(char *) path;
2192 		syscallarg(struct timeval *) tptr;
2193 	} */ *uap;
2194 {
2195 	struct timespec ts[2];
2196 	struct timeval *usrtvp;
2197 	int error;
2198 	struct nameidata nd;
2199 
2200 	usrtvp = SCARG(uap, tptr);
2201 	if ((error = getutimes(usrtvp, ts)) != 0)
2202 		return (error);
2203 	NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), td);
2204 	if ((error = namei(&nd)) != 0)
2205 		return (error);
2206 	NDFREE(&nd, NDF_ONLY_PNBUF);
2207 	error = setutimes(td, nd.ni_vp, ts, usrtvp == NULL);
2208 	vrele(nd.ni_vp);
2209 	return (error);
2210 }
2211 
2212 /*
2213  * Set the access and modification times of a file.
2214  */
2215 #ifndef _SYS_SYSPROTO_H_
2216 struct futimes_args {
2217 	int	fd;
2218 	struct	timeval *tptr;
2219 };
2220 #endif
2221 /* ARGSUSED */
2222 int
2223 futimes(td, uap)
2224 	struct thread *td;
2225 	register struct futimes_args /* {
2226 		syscallarg(int ) fd;
2227 		syscallarg(struct timeval *) tptr;
2228 	} */ *uap;
2229 {
2230 	struct timespec ts[2];
2231 	struct file *fp;
2232 	struct timeval *usrtvp;
2233 	int error;
2234 
2235 	usrtvp = SCARG(uap, tptr);
2236 	if ((error = getutimes(usrtvp, ts)) != 0)
2237 		return (error);
2238 	if ((error = getvnode(td->td_proc->p_fd, SCARG(uap, fd), &fp)) != 0)
2239 		return (error);
2240 	error = setutimes(td, (struct vnode *)fp->f_data, ts, usrtvp == NULL);
2241 	fdrop(fp, td);
2242 	return (error);
2243 }
2244 
2245 /*
2246  * Truncate a file given its path name.
2247  */
2248 #ifndef _SYS_SYSPROTO_H_
2249 struct truncate_args {
2250 	char	*path;
2251 	int	pad;
2252 	off_t	length;
2253 };
2254 #endif
2255 /* ARGSUSED */
2256 int
2257 truncate(td, uap)
2258 	struct thread *td;
2259 	register struct truncate_args /* {
2260 		syscallarg(char *) path;
2261 		syscallarg(int) pad;
2262 		syscallarg(off_t) length;
2263 	} */ *uap;
2264 {
2265 	struct mount *mp;
2266 	struct vnode *vp;
2267 	struct vattr vattr;
2268 	int error;
2269 	struct nameidata nd;
2270 
2271 	if (uap->length < 0)
2272 		return(EINVAL);
2273 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td);
2274 	if ((error = namei(&nd)) != 0)
2275 		return (error);
2276 	vp = nd.ni_vp;
2277 	if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) {
2278 		vrele(vp);
2279 		return (error);
2280 	}
2281 	NDFREE(&nd, NDF_ONLY_PNBUF);
2282 	VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
2283 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
2284 	if (vp->v_type == VDIR)
2285 		error = EISDIR;
2286 	else if ((error = vn_writechk(vp)) == 0 &&
2287 	    (error = VOP_ACCESS(vp, VWRITE, td->td_ucred, td)) == 0) {
2288 		VATTR_NULL(&vattr);
2289 		vattr.va_size = SCARG(uap, length);
2290 		error = VOP_SETATTR(vp, &vattr, td->td_ucred, td);
2291 	}
2292 	vput(vp);
2293 	vn_finished_write(mp);
2294 	return (error);
2295 }
2296 
2297 /*
2298  * Truncate a file given a file descriptor.
2299  */
2300 #ifndef _SYS_SYSPROTO_H_
2301 struct ftruncate_args {
2302 	int	fd;
2303 	int	pad;
2304 	off_t	length;
2305 };
2306 #endif
2307 /* ARGSUSED */
2308 int
2309 ftruncate(td, uap)
2310 	struct thread *td;
2311 	register struct ftruncate_args /* {
2312 		syscallarg(int) fd;
2313 		syscallarg(int) pad;
2314 		syscallarg(off_t) length;
2315 	} */ *uap;
2316 {
2317 	struct mount *mp;
2318 	struct vattr vattr;
2319 	struct vnode *vp;
2320 	struct file *fp;
2321 	int error;
2322 
2323 	if (uap->length < 0)
2324 		return(EINVAL);
2325 	if ((error = getvnode(td->td_proc->p_fd, SCARG(uap, fd), &fp)) != 0)
2326 		return (error);
2327 	if ((fp->f_flag & FWRITE) == 0) {
2328 		fdrop(fp, td);
2329 		return (EINVAL);
2330 	}
2331 	vp = (struct vnode *)fp->f_data;
2332 	if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) {
2333 		fdrop(fp, td);
2334 		return (error);
2335 	}
2336 	VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
2337 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
2338 	if (vp->v_type == VDIR)
2339 		error = EISDIR;
2340 	else if ((error = vn_writechk(vp)) == 0) {
2341 		VATTR_NULL(&vattr);
2342 		vattr.va_size = SCARG(uap, length);
2343 		error = VOP_SETATTR(vp, &vattr, fp->f_cred, td);
2344 	}
2345 	VOP_UNLOCK(vp, 0, td);
2346 	vn_finished_write(mp);
2347 	fdrop(fp, td);
2348 	return (error);
2349 }
2350 
2351 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
2352 /*
2353  * Truncate a file given its path name.
2354  */
2355 #ifndef _SYS_SYSPROTO_H_
2356 struct otruncate_args {
2357 	char	*path;
2358 	long	length;
2359 };
2360 #endif
2361 /* ARGSUSED */
2362 int
2363 otruncate(td, uap)
2364 	struct thread *td;
2365 	register struct otruncate_args /* {
2366 		syscallarg(char *) path;
2367 		syscallarg(long) length;
2368 	} */ *uap;
2369 {
2370 	struct truncate_args /* {
2371 		syscallarg(char *) path;
2372 		syscallarg(int) pad;
2373 		syscallarg(off_t) length;
2374 	} */ nuap;
2375 
2376 	SCARG(&nuap, path) = SCARG(uap, path);
2377 	SCARG(&nuap, length) = SCARG(uap, length);
2378 	return (truncate(td, &nuap));
2379 }
2380 
2381 /*
2382  * Truncate a file given a file descriptor.
2383  */
2384 #ifndef _SYS_SYSPROTO_H_
2385 struct oftruncate_args {
2386 	int	fd;
2387 	long	length;
2388 };
2389 #endif
2390 /* ARGSUSED */
2391 int
2392 oftruncate(td, uap)
2393 	struct thread *td;
2394 	register struct oftruncate_args /* {
2395 		syscallarg(int) fd;
2396 		syscallarg(long) length;
2397 	} */ *uap;
2398 {
2399 	struct ftruncate_args /* {
2400 		syscallarg(int) fd;
2401 		syscallarg(int) pad;
2402 		syscallarg(off_t) length;
2403 	} */ nuap;
2404 
2405 	SCARG(&nuap, fd) = SCARG(uap, fd);
2406 	SCARG(&nuap, length) = SCARG(uap, length);
2407 	return (ftruncate(td, &nuap));
2408 }
2409 #endif /* COMPAT_43 || COMPAT_SUNOS */
2410 
2411 /*
2412  * Sync an open file.
2413  */
2414 #ifndef _SYS_SYSPROTO_H_
2415 struct fsync_args {
2416 	int	fd;
2417 };
2418 #endif
2419 /* ARGSUSED */
2420 int
2421 fsync(td, uap)
2422 	struct thread *td;
2423 	struct fsync_args /* {
2424 		syscallarg(int) fd;
2425 	} */ *uap;
2426 {
2427 	struct vnode *vp;
2428 	struct mount *mp;
2429 	struct file *fp;
2430 	vm_object_t obj;
2431 	int error;
2432 
2433 	GIANT_REQUIRED;
2434 
2435 	if ((error = getvnode(td->td_proc->p_fd, SCARG(uap, fd), &fp)) != 0)
2436 		return (error);
2437 	vp = (struct vnode *)fp->f_data;
2438 	if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) {
2439 		fdrop(fp, td);
2440 		return (error);
2441 	}
2442 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
2443 	if (VOP_GETVOBJECT(vp, &obj) == 0) {
2444 		vm_object_page_clean(obj, 0, 0, 0);
2445 	}
2446 	error = VOP_FSYNC(vp, fp->f_cred, MNT_WAIT, td);
2447 	if (error == 0 && vp->v_mount && (vp->v_mount->mnt_flag & MNT_SOFTDEP)
2448 	    && softdep_fsync_hook != NULL)
2449 		error = (*softdep_fsync_hook)(vp);
2450 
2451 	VOP_UNLOCK(vp, 0, td);
2452 	vn_finished_write(mp);
2453 	fdrop(fp, td);
2454 	return (error);
2455 }
2456 
2457 /*
2458  * Rename files.  Source and destination must either both be directories,
2459  * or both not be directories.  If target is a directory, it must be empty.
2460  */
2461 #ifndef _SYS_SYSPROTO_H_
2462 struct rename_args {
2463 	char	*from;
2464 	char	*to;
2465 };
2466 #endif
2467 /* ARGSUSED */
2468 int
2469 rename(td, uap)
2470 	struct thread *td;
2471 	register struct rename_args /* {
2472 		syscallarg(char *) from;
2473 		syscallarg(char *) to;
2474 	} */ *uap;
2475 {
2476 	struct mount *mp;
2477 	struct vnode *tvp, *fvp, *tdvp;
2478 	struct nameidata fromnd, tond;
2479 	int error;
2480 
2481 	bwillwrite();
2482 	NDINIT(&fromnd, DELETE, WANTPARENT | SAVESTART, UIO_USERSPACE,
2483 	    SCARG(uap, from), td);
2484 	if ((error = namei(&fromnd)) != 0)
2485 		return (error);
2486 	fvp = fromnd.ni_vp;
2487 	if ((error = vn_start_write(fvp, &mp, V_WAIT | PCATCH)) != 0) {
2488 		NDFREE(&fromnd, NDF_ONLY_PNBUF);
2489 		vrele(fromnd.ni_dvp);
2490 		vrele(fvp);
2491 		goto out1;
2492 	}
2493 	NDINIT(&tond, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART | NOOBJ,
2494 	    UIO_USERSPACE, SCARG(uap, to), td);
2495 	if (fromnd.ni_vp->v_type == VDIR)
2496 		tond.ni_cnd.cn_flags |= WILLBEDIR;
2497 	if ((error = namei(&tond)) != 0) {
2498 		/* Translate error code for rename("dir1", "dir2/."). */
2499 		if (error == EISDIR && fvp->v_type == VDIR)
2500 			error = EINVAL;
2501 		NDFREE(&fromnd, NDF_ONLY_PNBUF);
2502 		vrele(fromnd.ni_dvp);
2503 		vrele(fvp);
2504 		goto out1;
2505 	}
2506 	tdvp = tond.ni_dvp;
2507 	tvp = tond.ni_vp;
2508 	if (tvp != NULL) {
2509 		if (fvp->v_type == VDIR && tvp->v_type != VDIR) {
2510 			error = ENOTDIR;
2511 			goto out;
2512 		} else if (fvp->v_type != VDIR && tvp->v_type == VDIR) {
2513 			error = EISDIR;
2514 			goto out;
2515 		}
2516 	}
2517 	if (fvp == tdvp)
2518 		error = EINVAL;
2519 	/*
2520 	 * If source is the same as the destination (that is the
2521 	 * same inode number with the same name in the same directory),
2522 	 * then there is nothing to do.
2523 	 */
2524 	if (fvp == tvp && fromnd.ni_dvp == tdvp &&
2525 	    fromnd.ni_cnd.cn_namelen == tond.ni_cnd.cn_namelen &&
2526 	    !bcmp(fromnd.ni_cnd.cn_nameptr, tond.ni_cnd.cn_nameptr,
2527 	      fromnd.ni_cnd.cn_namelen))
2528 		error = -1;
2529 out:
2530 	if (!error) {
2531 		VOP_LEASE(tdvp, td, td->td_ucred, LEASE_WRITE);
2532 		if (fromnd.ni_dvp != tdvp) {
2533 			VOP_LEASE(fromnd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
2534 		}
2535 		if (tvp) {
2536 			VOP_LEASE(tvp, td, td->td_ucred, LEASE_WRITE);
2537 		}
2538 		error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd,
2539 				   tond.ni_dvp, tond.ni_vp, &tond.ni_cnd);
2540 		NDFREE(&fromnd, NDF_ONLY_PNBUF);
2541 		NDFREE(&tond, NDF_ONLY_PNBUF);
2542 	} else {
2543 		NDFREE(&fromnd, NDF_ONLY_PNBUF);
2544 		NDFREE(&tond, NDF_ONLY_PNBUF);
2545 		if (tdvp == tvp)
2546 			vrele(tdvp);
2547 		else
2548 			vput(tdvp);
2549 		if (tvp)
2550 			vput(tvp);
2551 		vrele(fromnd.ni_dvp);
2552 		vrele(fvp);
2553 	}
2554 	vrele(tond.ni_startdir);
2555 	vn_finished_write(mp);
2556 	ASSERT_VOP_UNLOCKED(fromnd.ni_dvp, "rename");
2557 	ASSERT_VOP_UNLOCKED(fromnd.ni_vp, "rename");
2558 	ASSERT_VOP_UNLOCKED(tond.ni_dvp, "rename");
2559 	ASSERT_VOP_UNLOCKED(tond.ni_vp, "rename");
2560 out1:
2561 	if (fromnd.ni_startdir)
2562 		vrele(fromnd.ni_startdir);
2563 	if (error == -1)
2564 		return (0);
2565 	return (error);
2566 }
2567 
2568 /*
2569  * Make a directory file.
2570  */
2571 #ifndef _SYS_SYSPROTO_H_
2572 struct mkdir_args {
2573 	char	*path;
2574 	int	mode;
2575 };
2576 #endif
2577 /* ARGSUSED */
2578 int
2579 mkdir(td, uap)
2580 	struct thread *td;
2581 	register struct mkdir_args /* {
2582 		syscallarg(char *) path;
2583 		syscallarg(int) mode;
2584 	} */ *uap;
2585 {
2586 
2587 	return vn_mkdir(uap->path, uap->mode, UIO_USERSPACE, td);
2588 }
2589 
2590 int
2591 vn_mkdir(path, mode, segflg, td)
2592 	char *path;
2593 	int mode;
2594 	enum uio_seg segflg;
2595 	struct thread *td;
2596 {
2597 	struct mount *mp;
2598 	struct vnode *vp;
2599 	struct vattr vattr;
2600 	int error;
2601 	struct nameidata nd;
2602 
2603 restart:
2604 	bwillwrite();
2605 	NDINIT(&nd, CREATE, LOCKPARENT, segflg, path, td);
2606 	nd.ni_cnd.cn_flags |= WILLBEDIR;
2607 	if ((error = namei(&nd)) != 0)
2608 		return (error);
2609 	vp = nd.ni_vp;
2610 	if (vp != NULL) {
2611 		NDFREE(&nd, NDF_ONLY_PNBUF);
2612 		vrele(vp);
2613 		/*
2614 		 * XXX namei called with LOCKPARENT but not LOCKLEAF has
2615 		 * the strange behaviour of leaving the vnode unlocked
2616 		 * if the target is the same vnode as the parent.
2617 		 */
2618 		if (vp == nd.ni_dvp)
2619 			vrele(nd.ni_dvp);
2620 		else
2621 			vput(nd.ni_dvp);
2622 		return (EEXIST);
2623 	}
2624 	if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) {
2625 		NDFREE(&nd, NDF_ONLY_PNBUF);
2626 		vput(nd.ni_dvp);
2627 		if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0)
2628 			return (error);
2629 		goto restart;
2630 	}
2631 	VATTR_NULL(&vattr);
2632 	vattr.va_type = VDIR;
2633 	FILEDESC_LOCK(td->td_proc->p_fd);
2634 	vattr.va_mode = (mode & ACCESSPERMS) &~ td->td_proc->p_fd->fd_cmask;
2635 	FILEDESC_UNLOCK(td->td_proc->p_fd);
2636 	VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
2637 	error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
2638 	NDFREE(&nd, NDF_ONLY_PNBUF);
2639 	vput(nd.ni_dvp);
2640 	if (!error)
2641 		vput(nd.ni_vp);
2642 	vn_finished_write(mp);
2643 	ASSERT_VOP_UNLOCKED(nd.ni_dvp, "mkdir");
2644 	ASSERT_VOP_UNLOCKED(nd.ni_vp, "mkdir");
2645 	return (error);
2646 }
2647 
2648 /*
2649  * Remove a directory file.
2650  */
2651 #ifndef _SYS_SYSPROTO_H_
2652 struct rmdir_args {
2653 	char	*path;
2654 };
2655 #endif
2656 /* ARGSUSED */
2657 int
2658 rmdir(td, uap)
2659 	struct thread *td;
2660 	struct rmdir_args /* {
2661 		syscallarg(char *) path;
2662 	} */ *uap;
2663 {
2664 	struct mount *mp;
2665 	struct vnode *vp;
2666 	int error;
2667 	struct nameidata nd;
2668 
2669 restart:
2670 	bwillwrite();
2671 	NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF, UIO_USERSPACE,
2672 	    SCARG(uap, path), td);
2673 	if ((error = namei(&nd)) != 0)
2674 		return (error);
2675 	vp = nd.ni_vp;
2676 	if (vp->v_type != VDIR) {
2677 		error = ENOTDIR;
2678 		goto out;
2679 	}
2680 	/*
2681 	 * No rmdir "." please.
2682 	 */
2683 	if (nd.ni_dvp == vp) {
2684 		error = EINVAL;
2685 		goto out;
2686 	}
2687 	/*
2688 	 * The root of a mounted filesystem cannot be deleted.
2689 	 */
2690 	if (vp->v_flag & VROOT) {
2691 		error = EBUSY;
2692 		goto out;
2693 	}
2694 	if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) {
2695 		NDFREE(&nd, NDF_ONLY_PNBUF);
2696 		if (nd.ni_dvp == vp)
2697 			vrele(nd.ni_dvp);
2698 		else
2699 			vput(nd.ni_dvp);
2700 		vput(vp);
2701 		if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0)
2702 			return (error);
2703 		goto restart;
2704 	}
2705 	VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
2706 	VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
2707 	error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
2708 	vn_finished_write(mp);
2709 out:
2710 	NDFREE(&nd, NDF_ONLY_PNBUF);
2711 	if (nd.ni_dvp == vp)
2712 		vrele(nd.ni_dvp);
2713 	else
2714 		vput(nd.ni_dvp);
2715 	vput(vp);
2716 	ASSERT_VOP_UNLOCKED(nd.ni_dvp, "rmdir");
2717 	ASSERT_VOP_UNLOCKED(nd.ni_vp, "rmdir");
2718 	return (error);
2719 }
2720 
2721 #ifdef COMPAT_43
2722 /*
2723  * Read a block of directory entries in a filesystem independent format.
2724  */
2725 #ifndef _SYS_SYSPROTO_H_
2726 struct ogetdirentries_args {
2727 	int	fd;
2728 	char	*buf;
2729 	u_int	count;
2730 	long	*basep;
2731 };
2732 #endif
2733 int
2734 ogetdirentries(td, uap)
2735 	struct thread *td;
2736 	register struct ogetdirentries_args /* {
2737 		syscallarg(int) fd;
2738 		syscallarg(char *) buf;
2739 		syscallarg(u_int) count;
2740 		syscallarg(long *) basep;
2741 	} */ *uap;
2742 {
2743 	struct vnode *vp;
2744 	struct file *fp;
2745 	struct uio auio, kuio;
2746 	struct iovec aiov, kiov;
2747 	struct dirent *dp, *edp;
2748 	caddr_t dirbuf;
2749 	int error, eofflag, readcnt;
2750 	long loff;
2751 
2752 	/* XXX arbitrary sanity limit on `count'. */
2753 	if (SCARG(uap, count) > 64 * 1024)
2754 		return (EINVAL);
2755 	if ((error = getvnode(td->td_proc->p_fd, SCARG(uap, fd), &fp)) != 0)
2756 		return (error);
2757 	if ((fp->f_flag & FREAD) == 0) {
2758 		fdrop(fp, td);
2759 		return (EBADF);
2760 	}
2761 	vp = (struct vnode *)fp->f_data;
2762 unionread:
2763 	if (vp->v_type != VDIR) {
2764 		fdrop(fp, td);
2765 		return (EINVAL);
2766 	}
2767 	aiov.iov_base = SCARG(uap, buf);
2768 	aiov.iov_len = SCARG(uap, count);
2769 	auio.uio_iov = &aiov;
2770 	auio.uio_iovcnt = 1;
2771 	auio.uio_rw = UIO_READ;
2772 	auio.uio_segflg = UIO_USERSPACE;
2773 	auio.uio_td = td;
2774 	auio.uio_resid = SCARG(uap, count);
2775 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
2776 	loff = auio.uio_offset = fp->f_offset;
2777 #	if (BYTE_ORDER != LITTLE_ENDIAN)
2778 		if (vp->v_mount->mnt_maxsymlinklen <= 0) {
2779 			error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag,
2780 			    NULL, NULL);
2781 			fp->f_offset = auio.uio_offset;
2782 		} else
2783 #	endif
2784 	{
2785 		kuio = auio;
2786 		kuio.uio_iov = &kiov;
2787 		kuio.uio_segflg = UIO_SYSSPACE;
2788 		kiov.iov_len = SCARG(uap, count);
2789 		MALLOC(dirbuf, caddr_t, SCARG(uap, count), M_TEMP, M_WAITOK);
2790 		kiov.iov_base = dirbuf;
2791 		error = VOP_READDIR(vp, &kuio, fp->f_cred, &eofflag,
2792 			    NULL, NULL);
2793 		fp->f_offset = kuio.uio_offset;
2794 		if (error == 0) {
2795 			readcnt = SCARG(uap, count) - kuio.uio_resid;
2796 			edp = (struct dirent *)&dirbuf[readcnt];
2797 			for (dp = (struct dirent *)dirbuf; dp < edp; ) {
2798 #				if (BYTE_ORDER == LITTLE_ENDIAN)
2799 					/*
2800 					 * The expected low byte of
2801 					 * dp->d_namlen is our dp->d_type.
2802 					 * The high MBZ byte of dp->d_namlen
2803 					 * is our dp->d_namlen.
2804 					 */
2805 					dp->d_type = dp->d_namlen;
2806 					dp->d_namlen = 0;
2807 #				else
2808 					/*
2809 					 * The dp->d_type is the high byte
2810 					 * of the expected dp->d_namlen,
2811 					 * so must be zero'ed.
2812 					 */
2813 					dp->d_type = 0;
2814 #				endif
2815 				if (dp->d_reclen > 0) {
2816 					dp = (struct dirent *)
2817 					    ((char *)dp + dp->d_reclen);
2818 				} else {
2819 					error = EIO;
2820 					break;
2821 				}
2822 			}
2823 			if (dp >= edp)
2824 				error = uiomove(dirbuf, readcnt, &auio);
2825 		}
2826 		FREE(dirbuf, M_TEMP);
2827 	}
2828 	VOP_UNLOCK(vp, 0, td);
2829 	if (error) {
2830 		fdrop(fp, td);
2831 		return (error);
2832 	}
2833 	if (SCARG(uap, count) == auio.uio_resid) {
2834 		if (union_dircheckp) {
2835 			error = union_dircheckp(td, &vp, fp);
2836 			if (error == -1)
2837 				goto unionread;
2838 			if (error) {
2839 				fdrop(fp, td);
2840 				return (error);
2841 			}
2842 		}
2843 		if ((vp->v_flag & VROOT) &&
2844 		    (vp->v_mount->mnt_flag & MNT_UNION)) {
2845 			struct vnode *tvp = vp;
2846 			vp = vp->v_mount->mnt_vnodecovered;
2847 			VREF(vp);
2848 			fp->f_data = vp;
2849 			fp->f_offset = 0;
2850 			vrele(tvp);
2851 			goto unionread;
2852 		}
2853 	}
2854 	error = copyout(&loff, SCARG(uap, basep), sizeof(long));
2855 	fdrop(fp, td);
2856 	td->td_retval[0] = SCARG(uap, count) - auio.uio_resid;
2857 	return (error);
2858 }
2859 #endif /* COMPAT_43 */
2860 
2861 /*
2862  * Read a block of directory entries in a filesystem independent format.
2863  */
2864 #ifndef _SYS_SYSPROTO_H_
2865 struct getdirentries_args {
2866 	int	fd;
2867 	char	*buf;
2868 	u_int	count;
2869 	long	*basep;
2870 };
2871 #endif
2872 int
2873 getdirentries(td, uap)
2874 	struct thread *td;
2875 	register struct getdirentries_args /* {
2876 		syscallarg(int) fd;
2877 		syscallarg(char *) buf;
2878 		syscallarg(u_int) count;
2879 		syscallarg(long *) basep;
2880 	} */ *uap;
2881 {
2882 	struct vnode *vp;
2883 	struct file *fp;
2884 	struct uio auio;
2885 	struct iovec aiov;
2886 	long loff;
2887 	int error, eofflag;
2888 
2889 	if ((error = getvnode(td->td_proc->p_fd, SCARG(uap, fd), &fp)) != 0)
2890 		return (error);
2891 	if ((fp->f_flag & FREAD) == 0) {
2892 		fdrop(fp, td);
2893 		return (EBADF);
2894 	}
2895 	vp = (struct vnode *)fp->f_data;
2896 unionread:
2897 	if (vp->v_type != VDIR) {
2898 		fdrop(fp, td);
2899 		return (EINVAL);
2900 	}
2901 	aiov.iov_base = SCARG(uap, buf);
2902 	aiov.iov_len = SCARG(uap, count);
2903 	auio.uio_iov = &aiov;
2904 	auio.uio_iovcnt = 1;
2905 	auio.uio_rw = UIO_READ;
2906 	auio.uio_segflg = UIO_USERSPACE;
2907 	auio.uio_td = td;
2908 	auio.uio_resid = SCARG(uap, count);
2909 	/* vn_lock(vp, LK_SHARED | LK_RETRY, td); */
2910 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
2911 	loff = auio.uio_offset = fp->f_offset;
2912 	error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, NULL, NULL);
2913 	fp->f_offset = auio.uio_offset;
2914 	VOP_UNLOCK(vp, 0, td);
2915 	if (error) {
2916 		fdrop(fp, td);
2917 		return (error);
2918 	}
2919 	if (SCARG(uap, count) == auio.uio_resid) {
2920 		if (union_dircheckp) {
2921 			error = union_dircheckp(td, &vp, fp);
2922 			if (error == -1)
2923 				goto unionread;
2924 			if (error) {
2925 				fdrop(fp, td);
2926 				return (error);
2927 			}
2928 		}
2929 		if ((vp->v_flag & VROOT) &&
2930 		    (vp->v_mount->mnt_flag & MNT_UNION)) {
2931 			struct vnode *tvp = vp;
2932 			vp = vp->v_mount->mnt_vnodecovered;
2933 			VREF(vp);
2934 			fp->f_data = vp;
2935 			fp->f_offset = 0;
2936 			vrele(tvp);
2937 			goto unionread;
2938 		}
2939 	}
2940 	if (SCARG(uap, basep) != NULL) {
2941 		error = copyout(&loff, SCARG(uap, basep), sizeof(long));
2942 	}
2943 	td->td_retval[0] = SCARG(uap, count) - auio.uio_resid;
2944 	fdrop(fp, td);
2945 	return (error);
2946 }
2947 #ifndef _SYS_SYSPROTO_H_
2948 struct getdents_args {
2949 	int fd;
2950 	char *buf;
2951 	size_t count;
2952 };
2953 #endif
2954 int
2955 getdents(td, uap)
2956 	struct thread *td;
2957 	register struct getdents_args /* {
2958 		syscallarg(int) fd;
2959 		syscallarg(char *) buf;
2960 		syscallarg(u_int) count;
2961 	} */ *uap;
2962 {
2963 	struct getdirentries_args ap;
2964 	ap.fd = uap->fd;
2965 	ap.buf = uap->buf;
2966 	ap.count = uap->count;
2967 	ap.basep = NULL;
2968 	return getdirentries(td, &ap);
2969 }
2970 
2971 /*
2972  * Set the mode mask for creation of filesystem nodes.
2973  *
2974  * MP SAFE
2975  */
2976 #ifndef _SYS_SYSPROTO_H_
2977 struct umask_args {
2978 	int	newmask;
2979 };
2980 #endif
2981 int
2982 umask(td, uap)
2983 	struct thread *td;
2984 	struct umask_args /* {
2985 		syscallarg(int) newmask;
2986 	} */ *uap;
2987 {
2988 	register struct filedesc *fdp;
2989 
2990 	FILEDESC_LOCK(td->td_proc->p_fd);
2991 	fdp = td->td_proc->p_fd;
2992 	td->td_retval[0] = fdp->fd_cmask;
2993 	fdp->fd_cmask = SCARG(uap, newmask) & ALLPERMS;
2994 	FILEDESC_UNLOCK(td->td_proc->p_fd);
2995 	return (0);
2996 }
2997 
2998 /*
2999  * Void all references to file by ripping underlying filesystem
3000  * away from vnode.
3001  */
3002 #ifndef _SYS_SYSPROTO_H_
3003 struct revoke_args {
3004 	char	*path;
3005 };
3006 #endif
3007 /* ARGSUSED */
3008 int
3009 revoke(td, uap)
3010 	struct thread *td;
3011 	register struct revoke_args /* {
3012 		syscallarg(char *) path;
3013 	} */ *uap;
3014 {
3015 	struct mount *mp;
3016 	struct vnode *vp;
3017 	struct vattr vattr;
3018 	int error;
3019 	struct nameidata nd;
3020 
3021 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, SCARG(uap, path),
3022 	    td);
3023 	if ((error = namei(&nd)) != 0)
3024 		return (error);
3025 	vp = nd.ni_vp;
3026 	NDFREE(&nd, NDF_ONLY_PNBUF);
3027 	if (vp->v_type != VCHR) {
3028 		vput(vp);
3029 		return (EINVAL);
3030 	}
3031 	error = VOP_GETATTR(vp, &vattr, td->td_ucred, td);
3032 	if (error) {
3033 		vput(vp);
3034 		return (error);
3035 	}
3036 	VOP_UNLOCK(vp, 0, td);
3037 	if (td->td_ucred->cr_uid != vattr.va_uid) {
3038 		error = suser_cred(td->td_ucred, PRISON_ROOT);
3039 		if (error)
3040 			goto out;
3041 	}
3042 	if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
3043 		goto out;
3044 	if (vcount(vp) > 1)
3045 		VOP_REVOKE(vp, REVOKEALL);
3046 	vn_finished_write(mp);
3047 out:
3048 	vrele(vp);
3049 	return (error);
3050 }
3051 
3052 /*
3053  * Convert a user file descriptor to a kernel file entry.
3054  * The file entry is locked upon returning.
3055  */
3056 int
3057 getvnode(fdp, fd, fpp)
3058 	struct filedesc *fdp;
3059 	int fd;
3060 	struct file **fpp;
3061 {
3062 	int error;
3063 	struct file *fp;
3064 
3065 	fp = NULL;
3066 	if (fdp == NULL)
3067 		error = EBADF;
3068 	else {
3069 		FILEDESC_LOCK(fdp);
3070 		if ((u_int)fd >= fdp->fd_nfiles ||
3071 		    (fp = fdp->fd_ofiles[fd]) == NULL)
3072 			error = EBADF;
3073 		else if (fp->f_type != DTYPE_VNODE && fp->f_type != DTYPE_FIFO) {
3074 			fp = NULL;
3075 			error = EINVAL;
3076 		} else {
3077 			fhold(fp);
3078 			error = 0;
3079 		}
3080 		FILEDESC_UNLOCK(fdp);
3081 	}
3082 	*fpp = fp;
3083 	return (error);
3084 }
3085 /*
3086  * Get (NFS) file handle
3087  */
3088 #ifndef _SYS_SYSPROTO_H_
3089 struct getfh_args {
3090 	char	*fname;
3091 	fhandle_t *fhp;
3092 };
3093 #endif
3094 int
3095 getfh(td, uap)
3096 	struct thread *td;
3097 	register struct getfh_args *uap;
3098 {
3099 	struct nameidata nd;
3100 	fhandle_t fh;
3101 	register struct vnode *vp;
3102 	int error;
3103 
3104 	/*
3105 	 * Must be super user
3106 	 */
3107 	error = suser(td);
3108 	if (error)
3109 		return (error);
3110 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, td);
3111 	error = namei(&nd);
3112 	if (error)
3113 		return (error);
3114 	NDFREE(&nd, NDF_ONLY_PNBUF);
3115 	vp = nd.ni_vp;
3116 	bzero(&fh, sizeof(fh));
3117 	fh.fh_fsid = vp->v_mount->mnt_stat.f_fsid;
3118 	error = VFS_VPTOFH(vp, &fh.fh_fid);
3119 	vput(vp);
3120 	if (error)
3121 		return (error);
3122 	error = copyout(&fh, uap->fhp, sizeof (fh));
3123 	return (error);
3124 }
3125 
3126 /*
3127  * syscall for the rpc.lockd to use to translate a NFS file handle into
3128  * an open descriptor.
3129  *
3130  * warning: do not remove the suser() call or this becomes one giant
3131  * security hole.
3132  */
3133 #ifndef _SYS_SYSPROTO_H_
3134 struct fhopen_args {
3135 	const struct fhandle *u_fhp;
3136 	int flags;
3137 };
3138 #endif
3139 int
3140 fhopen(td, uap)
3141 	struct thread *td;
3142 	struct fhopen_args /* {
3143 		syscallarg(const struct fhandle *) u_fhp;
3144 		syscallarg(int) flags;
3145 	} */ *uap;
3146 {
3147 	struct proc *p = td->td_proc;
3148 	struct mount *mp;
3149 	struct vnode *vp;
3150 	struct fhandle fhp;
3151 	struct vattr vat;
3152 	struct vattr *vap = &vat;
3153 	struct flock lf;
3154 	struct file *fp;
3155 	register struct filedesc *fdp = p->p_fd;
3156 	int fmode, mode, error, type;
3157 	struct file *nfp;
3158 	int indx;
3159 
3160 	/*
3161 	 * Must be super user
3162 	 */
3163 	error = suser(td);
3164 	if (error)
3165 		return (error);
3166 
3167 	fmode = FFLAGS(SCARG(uap, flags));
3168 	/* why not allow a non-read/write open for our lockd? */
3169 	if (((fmode & (FREAD | FWRITE)) == 0) || (fmode & O_CREAT))
3170 		return (EINVAL);
3171 	error = copyin(SCARG(uap,u_fhp), &fhp, sizeof(fhp));
3172 	if (error)
3173 		return(error);
3174 	/* find the mount point */
3175 	mp = vfs_getvfs(&fhp.fh_fsid);
3176 	if (mp == NULL)
3177 		return (ESTALE);
3178 	/* now give me my vnode, it gets returned to me locked */
3179 	error = VFS_FHTOVP(mp, &fhp.fh_fid, &vp);
3180 	if (error)
3181 		return (error);
3182  	/*
3183 	 * from now on we have to make sure not
3184 	 * to forget about the vnode
3185 	 * any error that causes an abort must vput(vp)
3186 	 * just set error = err and 'goto bad;'.
3187 	 */
3188 
3189 	/*
3190 	 * from vn_open
3191 	 */
3192 	if (vp->v_type == VLNK) {
3193 		error = EMLINK;
3194 		goto bad;
3195 	}
3196 	if (vp->v_type == VSOCK) {
3197 		error = EOPNOTSUPP;
3198 		goto bad;
3199 	}
3200 	mode = 0;
3201 	if (fmode & (FWRITE | O_TRUNC)) {
3202 		if (vp->v_type == VDIR) {
3203 			error = EISDIR;
3204 			goto bad;
3205 		}
3206 		error = vn_writechk(vp);
3207 		if (error)
3208 			goto bad;
3209 		mode |= VWRITE;
3210 	}
3211 	if (fmode & FREAD)
3212 		mode |= VREAD;
3213 	if (mode) {
3214 		error = VOP_ACCESS(vp, mode, td->td_ucred, td);
3215 		if (error)
3216 			goto bad;
3217 	}
3218 	if (fmode & O_TRUNC) {
3219 		VOP_UNLOCK(vp, 0, td);				/* XXX */
3220 		if ((error = vn_start_write(NULL, &mp, V_WAIT | PCATCH)) != 0) {
3221 			vrele(vp);
3222 			return (error);
3223 		}
3224 		VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
3225 		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);	/* XXX */
3226 		VATTR_NULL(vap);
3227 		vap->va_size = 0;
3228 		error = VOP_SETATTR(vp, vap, td->td_ucred, td);
3229 		vn_finished_write(mp);
3230 		if (error)
3231 			goto bad;
3232 	}
3233 	error = VOP_OPEN(vp, fmode, td->td_ucred, td);
3234 	if (error)
3235 		goto bad;
3236 	/*
3237 	 * Make sure that a VM object is created for VMIO support.
3238 	 */
3239 	if (vn_canvmio(vp) == TRUE) {
3240 		if ((error = vfs_object_create(vp, td, td->td_ucred)) != 0)
3241 			goto bad;
3242 	}
3243 	if (fmode & FWRITE)
3244 		vp->v_writecount++;
3245 
3246 	/*
3247 	 * end of vn_open code
3248 	 */
3249 
3250 	if ((error = falloc(td, &nfp, &indx)) != 0) {
3251 		if (fmode & FWRITE)
3252 			vp->v_writecount--;
3253 		goto bad;
3254 	}
3255 	fp = nfp;
3256 
3257 	/*
3258 	 * Hold an extra reference to avoid having fp ripped out
3259 	 * from under us while we block in the lock op
3260 	 */
3261 	fhold(fp);
3262 	nfp->f_data = vp;
3263 	nfp->f_flag = fmode & FMASK;
3264 	nfp->f_ops = &vnops;
3265 	nfp->f_type = DTYPE_VNODE;
3266 	if (fmode & (O_EXLOCK | O_SHLOCK)) {
3267 		lf.l_whence = SEEK_SET;
3268 		lf.l_start = 0;
3269 		lf.l_len = 0;
3270 		if (fmode & O_EXLOCK)
3271 			lf.l_type = F_WRLCK;
3272 		else
3273 			lf.l_type = F_RDLCK;
3274 		type = F_FLOCK;
3275 		if ((fmode & FNONBLOCK) == 0)
3276 			type |= F_WAIT;
3277 		VOP_UNLOCK(vp, 0, td);
3278 		if ((error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf,
3279 			    type)) != 0) {
3280 			/*
3281 			 * The lock request failed.  Normally close the
3282 			 * descriptor but handle the case where someone might
3283 			 * have dup()d or close()d it when we weren't looking.
3284 			 */
3285 			FILEDESC_LOCK(fdp);
3286 			if (fdp->fd_ofiles[indx] == fp) {
3287 				fdp->fd_ofiles[indx] = NULL;
3288 				FILEDESC_UNLOCK(fdp);
3289 				fdrop(fp, td);
3290 			} else
3291 				FILEDESC_UNLOCK(fdp);
3292 			/*
3293 			 * release our private reference
3294 			 */
3295 			fdrop(fp, td);
3296 			return(error);
3297 		}
3298 		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
3299 		fp->f_flag |= FHASLOCK;
3300 	}
3301 	if ((vp->v_type == VREG) && (VOP_GETVOBJECT(vp, NULL) != 0))
3302 		vfs_object_create(vp, td, td->td_ucred);
3303 
3304 	VOP_UNLOCK(vp, 0, td);
3305 	fdrop(fp, td);
3306 	td->td_retval[0] = indx;
3307 	return (0);
3308 
3309 bad:
3310 	vput(vp);
3311 	return (error);
3312 }
3313 
3314 /*
3315  * Stat an (NFS) file handle.
3316  */
3317 #ifndef _SYS_SYSPROTO_H_
3318 struct fhstat_args {
3319 	struct fhandle *u_fhp;
3320 	struct stat *sb;
3321 };
3322 #endif
3323 int
3324 fhstat(td, uap)
3325 	struct thread *td;
3326 	register struct fhstat_args /* {
3327 		syscallarg(struct fhandle *) u_fhp;
3328 		syscallarg(struct stat *) sb;
3329 	} */ *uap;
3330 {
3331 	struct stat sb;
3332 	fhandle_t fh;
3333 	struct mount *mp;
3334 	struct vnode *vp;
3335 	int error;
3336 
3337 	/*
3338 	 * Must be super user
3339 	 */
3340 	error = suser(td);
3341 	if (error)
3342 		return (error);
3343 
3344 	error = copyin(SCARG(uap, u_fhp), &fh, sizeof(fhandle_t));
3345 	if (error)
3346 		return (error);
3347 
3348 	if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL)
3349 		return (ESTALE);
3350 	if ((error = VFS_FHTOVP(mp, &fh.fh_fid, &vp)))
3351 		return (error);
3352 	error = vn_stat(vp, &sb, td);
3353 	vput(vp);
3354 	if (error)
3355 		return (error);
3356 	error = copyout(&sb, SCARG(uap, sb), sizeof(sb));
3357 	return (error);
3358 }
3359 
3360 /*
3361  * Implement fstatfs() for (NFS) file handles.
3362  */
3363 #ifndef _SYS_SYSPROTO_H_
3364 struct fhstatfs_args {
3365 	struct fhandle *u_fhp;
3366 	struct statfs *buf;
3367 };
3368 #endif
3369 int
3370 fhstatfs(td, uap)
3371 	struct thread *td;
3372 	struct fhstatfs_args /* {
3373 		syscallarg(struct fhandle) *u_fhp;
3374 		syscallarg(struct statfs) *buf;
3375 	} */ *uap;
3376 {
3377 	struct statfs *sp;
3378 	struct mount *mp;
3379 	struct vnode *vp;
3380 	struct statfs sb;
3381 	fhandle_t fh;
3382 	int error;
3383 
3384 	/*
3385 	 * Must be super user
3386 	 */
3387 	error = suser(td);
3388 	if (error)
3389 		return (error);
3390 
3391 	if ((error = copyin(SCARG(uap, u_fhp), &fh, sizeof(fhandle_t))) != 0)
3392 		return (error);
3393 
3394 	if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL)
3395 		return (ESTALE);
3396 	if ((error = VFS_FHTOVP(mp, &fh.fh_fid, &vp)))
3397 		return (error);
3398 	mp = vp->v_mount;
3399 	sp = &mp->mnt_stat;
3400 	vput(vp);
3401 	if ((error = VFS_STATFS(mp, sp, td)) != 0)
3402 		return (error);
3403 	sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
3404 	if (suser(td)) {
3405 		bcopy(sp, &sb, sizeof(sb));
3406 		sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0;
3407 		sp = &sb;
3408 	}
3409 	return (copyout(sp, SCARG(uap, buf), sizeof(*sp)));
3410 }
3411 
3412 /*
3413  * Syscall to push extended attribute configuration information into the
3414  * VFS.  Accepts a path, which it converts to a mountpoint, as well as
3415  * a command (int cmd), and attribute name and misc data.  For now, the
3416  * attribute name is left in userspace for consumption by the VFS_op.
3417  * It will probably be changed to be copied into sysspace by the
3418  * syscall in the future, once issues with various consumers of the
3419  * attribute code have raised their hands.
3420  *
3421  * Currently this is used only by UFS Extended Attributes.
3422  */
3423 int
3424 extattrctl(td, uap)
3425 	struct thread *td;
3426 	struct extattrctl_args /* {
3427 		syscallarg(const char *) path;
3428 		syscallarg(int) cmd;
3429 		syscallarg(const char *) filename;
3430 		syscallarg(int) attrnamespace;
3431 		syscallarg(const char *) attrname;
3432 	} */ *uap;
3433 {
3434 	struct vnode *filename_vp;
3435 	struct nameidata nd;
3436 	struct mount *mp, *mp_writable;
3437 	char attrname[EXTATTR_MAXNAMELEN];
3438 	int error;
3439 
3440 	/*
3441 	 * uap->attrname is not always defined.  We check again later when we
3442 	 * invoke the VFS call so as to pass in NULL there if needed.
3443 	 */
3444 	if (uap->attrname != NULL) {
3445 		error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN,
3446 		    NULL);
3447 		if (error)
3448 			return (error);
3449 	}
3450 
3451 	/*
3452 	 * uap->filename is not always defined.  If it is, grab a vnode lock,
3453 	 * which VFS_EXTATTRCTL() will later release.
3454 	 */
3455 	filename_vp = NULL;
3456 	if (uap->filename != NULL) {
3457 		NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
3458 		    uap->filename, td);
3459 		if ((error = namei(&nd)) != 0)
3460 			return (error);
3461 		filename_vp = nd.ni_vp;
3462 		NDFREE(&nd, NDF_NO_VP_RELE | NDF_NO_VP_UNLOCK);
3463 	}
3464 
3465 	/* uap->path is always defined. */
3466 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, td);
3467 	if ((error = namei(&nd)) != 0) {
3468 		if (filename_vp != NULL)
3469 			vput(filename_vp);
3470 		return (error);
3471 	}
3472 	mp = nd.ni_vp->v_mount;
3473 	error = vn_start_write(nd.ni_vp, &mp_writable, V_WAIT | PCATCH);
3474 	NDFREE(&nd, 0);
3475 	if (error) {
3476 		if (filename_vp != NULL)
3477 			vput(filename_vp);
3478 		return (error);
3479 	}
3480 
3481 	if (uap->attrname != NULL) {
3482 		error = VFS_EXTATTRCTL(mp, uap->cmd, filename_vp,
3483 		    uap->attrnamespace, attrname, td);
3484 	} else {
3485 		error = VFS_EXTATTRCTL(mp, uap->cmd, filename_vp,
3486 		    uap->attrnamespace, NULL, td);
3487 	}
3488 
3489 	vn_finished_write(mp_writable);
3490 	/*
3491 	 * VFS_EXTATTRCTL will have unlocked, but not de-ref'd,
3492 	 * filename_vp, so vrele it if it is defined.
3493 	 */
3494 	if (filename_vp != NULL)
3495 		vrele(filename_vp);
3496 
3497 	return (error);
3498 }
3499 
3500 /*-
3501  * Set a named extended attribute on a file or directory
3502  *
3503  * Arguments: unlocked vnode "vp", attribute namespace "attrnamespace",
3504  *            kernelspace string pointer "attrname", userspace buffer
3505  *            pointer "data", buffer length "nbytes", thread "td".
3506  * Returns: 0 on success, an error number otherwise
3507  * Locks: none
3508  * References: vp must be a valid reference for the duration of the call
3509  */
3510 static int
3511 extattr_set_vp(struct vnode *vp, int attrnamespace, const char *attrname,
3512     void *data, size_t nbytes, struct thread *td)
3513 {
3514 	struct mount *mp;
3515 	struct uio auio;
3516 	struct iovec aiov;
3517 	ssize_t cnt;
3518 	int error;
3519 
3520 	if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
3521 		return (error);
3522 	VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
3523 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
3524 
3525 	aiov.iov_base = data;
3526 	aiov.iov_len = nbytes;
3527 	auio.uio_iov = &aiov;
3528 	auio.uio_iovcnt = 1;
3529 	auio.uio_offset = 0;
3530 	if (nbytes > INT_MAX) {
3531 		error = EINVAL;
3532 		goto done;
3533 	}
3534 	auio.uio_resid = nbytes;
3535 	auio.uio_rw = UIO_WRITE;
3536 	auio.uio_segflg = UIO_USERSPACE;
3537 	auio.uio_td = td;
3538 	cnt = nbytes;
3539 
3540 	error = VOP_SETEXTATTR(vp, attrnamespace, attrname, &auio,
3541 	    td->td_ucred, td);
3542 	cnt -= auio.uio_resid;
3543 	td->td_retval[0] = cnt;
3544 
3545 done:
3546 	VOP_UNLOCK(vp, 0, td);
3547 	vn_finished_write(mp);
3548 	return (error);
3549 }
3550 
3551 int
3552 extattr_set_file(td, uap)
3553 	struct thread *td;
3554 	struct extattr_set_file_args /* {
3555 		syscallarg(const char *) path;
3556 		syscallarg(int) attrnamespace;
3557 		syscallarg(const char *) attrname;
3558 		syscallarg(void *) data;
3559 		syscallarg(size_t) nbytes;
3560 	} */ *uap;
3561 {
3562 	struct nameidata nd;
3563 	char attrname[EXTATTR_MAXNAMELEN];
3564 	int error;
3565 
3566 	error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
3567 	if (error)
3568 		return (error);
3569 
3570 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, td);
3571 	if ((error = namei(&nd)) != 0)
3572 		return (error);
3573 	NDFREE(&nd, NDF_ONLY_PNBUF);
3574 
3575 	error = extattr_set_vp(nd.ni_vp, uap->attrnamespace, attrname,
3576 	    uap->data, uap->nbytes, td);
3577 
3578 	vrele(nd.ni_vp);
3579 	return (error);
3580 }
3581 
3582 int
3583 extattr_set_fd(td, uap)
3584 	struct thread *td;
3585 	struct extattr_set_fd_args /* {
3586 		syscallarg(int) fd;
3587 		syscallarg(int) attrnamespace;
3588 		syscallarg(const char *) attrname;
3589 		syscallarg(void *) data;
3590 		syscallarg(size_t) nbytes;
3591 	} */ *uap;
3592 {
3593 	struct file *fp;
3594 	char attrname[EXTATTR_MAXNAMELEN];
3595 	int error;
3596 
3597 	error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
3598 	if (error)
3599 		return (error);
3600 
3601 	if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0)
3602 		return (error);
3603 
3604 	error = extattr_set_vp((struct vnode *)fp->f_data, uap->attrnamespace,
3605 	    attrname, uap->data, uap->nbytes, td);
3606 	fdrop(fp, td);
3607 
3608 	return (error);
3609 }
3610 
3611 /*-
3612  * Get a named extended attribute on a file or directory
3613  *
3614  * Arguments: unlocked vnode "vp", attribute namespace "attrnamespace",
3615  *            kernelspace string pointer "attrname", userspace buffer
3616  *            pointer "data", buffer length "nbytes", thread "td".
3617  * Returns: 0 on success, an error number otherwise
3618  * Locks: none
3619  * References: vp must be a valid reference for the duration of the call
3620  */
3621 static int
3622 extattr_get_vp(struct vnode *vp, int attrnamespace, const char *attrname,
3623     void *data, size_t nbytes, struct thread *td)
3624 {
3625 	struct uio auio, *auiop;
3626 	struct iovec aiov;
3627 	ssize_t cnt;
3628 	size_t size, *sizep;
3629 	int error;
3630 
3631 	VOP_LEASE(vp, td, td->td_ucred, LEASE_READ);
3632 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
3633 
3634 	/*
3635 	 * Slightly unusual semantics: if the user provides a NULL data
3636 	 * pointer, they don't want to receive the data, just the
3637 	 * maximum read length.
3638 	 */
3639 	auiop = NULL;
3640 	sizep = NULL;
3641 	cnt = 0;
3642 	if (data != NULL) {
3643 		aiov.iov_base = data;
3644 		aiov.iov_len = nbytes;
3645 		auio.uio_iov = &aiov;
3646 		auio.uio_offset = 0;
3647 		if (nbytes > INT_MAX) {
3648 			error = EINVAL;
3649 			goto done;
3650 		}
3651 		auio.uio_resid = nbytes;
3652 		auio.uio_rw = UIO_READ;
3653 		auio.uio_segflg = UIO_USERSPACE;
3654 		auio.uio_td = td;
3655 		auiop = &auio;
3656 		cnt = nbytes;
3657 	} else
3658 		sizep = &size;
3659 
3660 	error = VOP_GETEXTATTR(vp, attrnamespace, attrname, auiop, sizep,
3661 	    td->td_ucred, td);
3662 
3663 	if (auiop != NULL) {
3664 		cnt -= auio.uio_resid;
3665 		td->td_retval[0] = cnt;
3666 	} else
3667 		td->td_retval[0] = size;
3668 
3669 done:
3670 	VOP_UNLOCK(vp, 0, td);
3671 	return (error);
3672 }
3673 
3674 int
3675 extattr_get_file(td, uap)
3676 	struct thread *td;
3677 	struct extattr_get_file_args /* {
3678 		syscallarg(const char *) path;
3679 		syscallarg(int) attrnamespace;
3680 		syscallarg(const char *) attrname;
3681 		syscallarg(void *) data;
3682 		syscallarg(size_t) nbytes;
3683 	} */ *uap;
3684 {
3685 	struct nameidata nd;
3686 	char attrname[EXTATTR_MAXNAMELEN];
3687 	int error;
3688 
3689 	error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
3690 	if (error)
3691 		return (error);
3692 
3693 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, td);
3694 	if ((error = namei(&nd)) != 0)
3695 		return (error);
3696 	NDFREE(&nd, NDF_ONLY_PNBUF);
3697 
3698 	error = extattr_get_vp(nd.ni_vp, uap->attrnamespace, attrname,
3699 	    uap->data, uap->nbytes, td);
3700 
3701 	vrele(nd.ni_vp);
3702 	return (error);
3703 }
3704 
3705 int
3706 extattr_get_fd(td, uap)
3707 	struct thread *td;
3708 	struct extattr_get_fd_args /* {
3709 		syscallarg(int) fd;
3710 		syscallarg(int) attrnamespace;
3711 		syscallarg(const char *) attrname;
3712 		syscallarg(void *) data;
3713 		syscallarg(size_t) nbytes;
3714 	} */ *uap;
3715 {
3716 	struct file *fp;
3717 	char attrname[EXTATTR_MAXNAMELEN];
3718 	int error;
3719 
3720 	error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
3721 	if (error)
3722 		return (error);
3723 
3724 	if ((error = getvnode(td->td_proc->p_fd, SCARG(uap, fd), &fp)) != 0)
3725 		return (error);
3726 
3727 	error = extattr_get_vp((struct vnode *)fp->f_data, uap->attrnamespace,
3728 	    attrname, uap->data, uap->nbytes, td);
3729 
3730 	fdrop(fp, td);
3731 	return (error);
3732 }
3733 
3734 /*
3735  * extattr_delete_vp(): Delete a named extended attribute on a file or
3736  *                      directory
3737  *
3738  * Arguments: unlocked vnode "vp", attribute namespace "attrnamespace",
3739  *            kernelspace string pointer "attrname", proc "p"
3740  * Returns: 0 on success, an error number otherwise
3741  * Locks: none
3742  * References: vp must be a valid reference for the duration of the call
3743  */
3744 static int
3745 extattr_delete_vp(struct vnode *vp, int attrnamespace, const char *attrname,
3746     struct thread *td)
3747 {
3748 	struct mount *mp;
3749 	int error;
3750 
3751 	if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
3752 		return (error);
3753 	VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
3754 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
3755 
3756 	error = VOP_SETEXTATTR(vp, attrnamespace, attrname, NULL, td->td_ucred,
3757 	    td);
3758 
3759 	VOP_UNLOCK(vp, 0, td);
3760 	vn_finished_write(mp);
3761 	return (error);
3762 }
3763 
3764 int
3765 extattr_delete_file(td, uap)
3766 	struct thread *td;
3767 	struct extattr_delete_file_args /* {
3768 		syscallarg(const char *) path;
3769 		syscallarg(int) attrnamespace;
3770 		syscallarg(const char *) attrname;
3771 	} */ *uap;
3772 {
3773 	struct nameidata nd;
3774 	char attrname[EXTATTR_MAXNAMELEN];
3775 	int error;
3776 
3777 	error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
3778 	if (error)
3779 		return(error);
3780 
3781 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, td);
3782 	if ((error = namei(&nd)) != 0)
3783 		return(error);
3784 	NDFREE(&nd, NDF_ONLY_PNBUF);
3785 
3786 	error = extattr_delete_vp(nd.ni_vp, uap->attrnamespace, attrname, td);
3787 
3788 	vrele(nd.ni_vp);
3789 	return(error);
3790 }
3791 
3792 int
3793 extattr_delete_fd(td, uap)
3794 	struct thread *td;
3795 	struct extattr_delete_fd_args /* {
3796 		syscallarg(int) fd;
3797 		syscallarg(int) attrnamespace;
3798 		syscallarg(const char *) attrname;
3799 	} */ *uap;
3800 {
3801 	struct file *fp;
3802 	struct vnode *vp;
3803 	char attrname[EXTATTR_MAXNAMELEN];
3804 	int error;
3805 
3806 	error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
3807 	if (error)
3808 		return (error);
3809 
3810 	if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0)
3811 		return (error);
3812 	vp = (struct vnode *)fp->f_data;
3813 
3814 	error = extattr_delete_vp((struct vnode *)fp->f_data,
3815 	    uap->attrnamespace, attrname, td);
3816 
3817 	fdrop(fp, td);
3818 	return (error);
3819 }
3820