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.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
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.
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
38 * @(#)vfs_syscalls.c 8.13 (Berkeley) 4/15/94
42 /* For 4.3 integer FS ID compatibility */
43 #include "opt_compat.h"
45 #include <sys/param.h>
46 #include <sys/systm.h>
48 #include <sys/sysent.h>
49 #include <sys/malloc.h>
50 #include <sys/mount.h>
51 #include <sys/sysproto.h>
52 #include <sys/namei.h>
53 #include <sys/filedesc.h>
54 #include <sys/kernel.h>
55 #include <sys/fcntl.h>
57 #include <sys/linker.h>
59 #include <sys/unistd.h>
60 #include <sys/vnode.h>
62 #include <sys/dirent.h>
64 #include <miscfs/union/union.h>
67 #include <vm/vm_object.h>
68 #include <vm/vm_zone.h>
69 #include <sys/sysctl.h>
71 static int change_dir __P((struct nameidata *ndp, struct proc *p));
72 static void checkdirs __P((struct vnode *olddp));
73 static int chroot_refuse_vdir_fds __P((struct filedesc *fdp));
74 static int getutimes __P((const struct timeval *, struct timespec *));
75 static int setfown __P((struct proc *, struct vnode *, uid_t, gid_t));
76 static int setfmode __P((struct proc *, struct vnode *, int));
77 static int setfflags __P((struct proc *, struct vnode *, int));
78 static int setutimes __P((struct proc *, struct vnode *,
79 const struct timespec *, int));
80 static int usermount = 0; /* if 1, non-root can mount fs. */
82 int (*union_dircheckp) __P((struct proc *, struct vnode **, struct file *));
84 SYSCTL_INT(_vfs, OID_AUTO, usermount, CTLFLAG_RW, &usermount, 0, "");
87 * Virtual File System System Calls
91 * Mount a file system.
93 #ifndef _SYS_SYSPROTO_H_
105 register struct mount_args /* {
106 syscallarg(char *) type;
107 syscallarg(char *) path;
108 syscallarg(int) flags;
109 syscallarg(caddr_t) data;
114 struct vfsconf *vfsp;
115 int error, flag = 0, flag2 = 0;
121 char fstypename[MFSNAMELEN];
123 if (usermount == 0 && (error = suser(p)))
126 * Do not allow NFS export by non-root users.
128 if (SCARG(uap, flags) & MNT_EXPORTED) {
134 * Silently enforce MNT_NOSUID and MNT_NODEV for non-root users
136 if (suser_xxx(p->p_ucred, 0, 0))
137 SCARG(uap, flags) |= MNT_NOSUID | MNT_NODEV;
139 * Get vnode to be covered
141 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
142 SCARG(uap, path), p);
143 if ((error = namei(&nd)) != 0)
146 if (SCARG(uap, flags) & MNT_UPDATE) {
147 if ((vp->v_flag & VROOT) == 0) {
153 flag2 = mp->mnt_kern_flag;
155 * We only allow the filesystem to be reloaded if it
156 * is currently mounted read-only.
158 if ((SCARG(uap, flags) & MNT_RELOAD) &&
159 ((mp->mnt_flag & MNT_RDONLY) == 0)) {
161 return (EOPNOTSUPP); /* Needs translation */
164 SCARG(uap, flags) & (MNT_RELOAD | MNT_FORCE | MNT_UPDATE);
166 * Only root, or the user that did the original mount is
167 * permitted to update it.
169 if (mp->mnt_stat.f_owner != p->p_ucred->cr_uid &&
170 (error = suser(p))) {
174 if (vfs_busy(mp, LK_NOWAIT, 0, p)) {
178 VOP_UNLOCK(vp, 0, p);
182 * If the user is not root, ensure that they own the directory
183 * onto which we are attempting to mount.
185 if ((error = VOP_GETATTR(vp, &va, p->p_ucred, p)) ||
186 (va.va_uid != p->p_ucred->cr_uid &&
187 (error = suser(p)))) {
191 if ((error = vinvalbuf(vp, V_SAVE, p->p_ucred, p, 0, 0)) != 0)
193 if (vp->v_type != VDIR) {
199 * Historically filesystem types were identified by number. If we
200 * get an integer for the filesystem type instead of a string, we
201 * check to see if it matches one of the historic filesystem types.
203 fstypenum = (uintptr_t)SCARG(uap, type);
204 if (fstypenum < maxvfsconf) {
205 for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next)
206 if (vfsp->vfc_typenum == fstypenum)
212 strncpy(fstypename, vfsp->vfc_name, MFSNAMELEN);
214 #endif /* COMPAT_43 */
215 if ((error = copyinstr(SCARG(uap, type), fstypename, MFSNAMELEN, NULL)) != 0) {
219 for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next)
220 if (!strcmp(vfsp->vfc_name, fstypename))
225 /* Refuse to load modules if securelevel raised */
226 if (securelevel > 0) {
230 /* Only load modules for root (very important!) */
231 if ((error = suser(p)) != 0) {
235 error = linker_load_file(fstypename, &lf);
236 if (error || lf == NULL) {
243 /* lookup again, see if the VFS was loaded */
244 for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next)
245 if (!strcmp(vfsp->vfc_name, fstypename))
249 linker_file_unload(lf);
254 simple_lock(&vp->v_interlock);
255 if ((vp->v_flag & VMOUNT) != 0 ||
256 vp->v_mountedhere != NULL) {
257 simple_unlock(&vp->v_interlock);
261 vp->v_flag |= VMOUNT;
262 simple_unlock(&vp->v_interlock);
265 * Allocate and initialize the filesystem.
267 mp = (struct mount *)malloc((u_long)sizeof(struct mount),
269 bzero((char *)mp, (u_long)sizeof(struct mount));
270 lockinit(&mp->mnt_lock, PVFS, "vfslock", 0, LK_NOPAUSE);
271 (void)vfs_busy(mp, LK_NOWAIT, 0, p);
272 mp->mnt_op = vfsp->vfc_vfsops;
274 vfsp->vfc_refcount++;
275 mp->mnt_stat.f_type = vfsp->vfc_typenum;
276 mp->mnt_flag |= vfsp->vfc_flags & MNT_VISFLAGMASK;
277 strncpy(mp->mnt_stat.f_fstypename, vfsp->vfc_name, MFSNAMELEN);
278 mp->mnt_vnodecovered = vp;
279 mp->mnt_stat.f_owner = p->p_ucred->cr_uid;
280 mp->mnt_iosize_max = DFLTPHYS;
281 VOP_UNLOCK(vp, 0, p);
284 * Set the mount level flags.
286 if (SCARG(uap, flags) & MNT_RDONLY)
287 mp->mnt_flag |= MNT_RDONLY;
288 else if (mp->mnt_flag & MNT_RDONLY)
289 mp->mnt_kern_flag |= MNTK_WANTRDWR;
290 mp->mnt_flag &=~ (MNT_NOSUID | MNT_NOEXEC | MNT_NODEV |
291 MNT_SYNCHRONOUS | MNT_UNION | MNT_ASYNC | MNT_NOATIME |
292 MNT_NOSYMFOLLOW | MNT_IGNORE |
293 MNT_NOCLUSTERR | MNT_NOCLUSTERW | MNT_SUIDDIR);
294 mp->mnt_flag |= SCARG(uap, flags) & (MNT_NOSUID | MNT_NOEXEC |
295 MNT_NODEV | MNT_SYNCHRONOUS | MNT_UNION | MNT_ASYNC | MNT_FORCE |
296 MNT_NOSYMFOLLOW | MNT_IGNORE |
297 MNT_NOATIME | MNT_NOCLUSTERR | MNT_NOCLUSTERW | MNT_SUIDDIR);
299 * Mount the filesystem.
301 error = VFS_MOUNT(mp, SCARG(uap, path), SCARG(uap, data), &nd, p);
302 if (mp->mnt_flag & MNT_UPDATE) {
304 if (mp->mnt_kern_flag & MNTK_WANTRDWR)
305 mp->mnt_flag &= ~MNT_RDONLY;
306 mp->mnt_flag &=~ (MNT_UPDATE | MNT_RELOAD | MNT_FORCE);
307 mp->mnt_kern_flag &=~ MNTK_WANTRDWR;
310 mp->mnt_kern_flag = flag2;
312 if ((mp->mnt_flag & MNT_RDONLY) == 0) {
313 if (mp->mnt_syncer == NULL)
314 error = vfs_allocate_syncvnode(mp);
316 if (mp->mnt_syncer != NULL)
317 vrele(mp->mnt_syncer);
318 mp->mnt_syncer = NULL;
323 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
325 * Put the new filesystem on the mount list after root.
329 simple_lock(&vp->v_interlock);
330 vp->v_flag &= ~VMOUNT;
331 vp->v_mountedhere = mp;
332 simple_unlock(&vp->v_interlock);
333 simple_lock(&mountlist_slock);
334 TAILQ_INSERT_TAIL(&mountlist, mp, mnt_list);
335 simple_unlock(&mountlist_slock);
337 VOP_UNLOCK(vp, 0, p);
338 if ((mp->mnt_flag & MNT_RDONLY) == 0)
339 error = vfs_allocate_syncvnode(mp);
341 if ((error = VFS_START(mp, 0, p)) != 0)
344 simple_lock(&vp->v_interlock);
345 vp->v_flag &= ~VMOUNT;
346 simple_unlock(&vp->v_interlock);
347 mp->mnt_vfc->vfc_refcount--;
349 free((caddr_t)mp, M_MOUNT);
356 * Scan all active processes to see if any of them have a current
357 * or root directory onto which the new filesystem has just been
358 * mounted. If so, replace them with the new mount point.
364 struct filedesc *fdp;
368 if (olddp->v_usecount == 1)
370 if (VFS_ROOT(olddp->v_mountedhere, &newdp))
371 panic("mount: lost mount");
372 LIST_FOREACH(p, &allproc, p_list) {
374 if (fdp->fd_cdir == olddp) {
377 fdp->fd_cdir = newdp;
379 if (fdp->fd_rdir == olddp) {
382 fdp->fd_rdir = newdp;
385 if (rootvnode == olddp) {
394 * Unmount a file system.
396 * Note: unmount takes a path to the vnode mounted on as argument,
397 * not special file (as before).
399 #ifndef _SYS_SYSPROTO_H_
400 struct unmount_args {
409 register struct unmount_args /* {
410 syscallarg(char *) path;
411 syscallarg(int) flags;
414 register struct vnode *vp;
419 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
420 SCARG(uap, path), p);
421 if ((error = namei(&nd)) != 0)
427 * Only root, or the user that did the original mount is
428 * permitted to unmount this filesystem.
430 if ((mp->mnt_stat.f_owner != p->p_ucred->cr_uid) &&
431 (error = suser(p))) {
437 * Don't allow unmounting the root file system.
439 if (mp->mnt_flag & MNT_ROOTFS) {
445 * Must be the root of the filesystem
447 if ((vp->v_flag & VROOT) == 0) {
452 return (dounmount(mp, SCARG(uap, flags), p));
456 * Do the actual file system unmount.
459 dounmount(mp, flags, p)
460 register struct mount *mp;
464 struct vnode *coveredvp;
468 simple_lock(&mountlist_slock);
469 mp->mnt_kern_flag |= MNTK_UNMOUNT;
470 lockmgr(&mp->mnt_lock, LK_DRAIN | LK_INTERLOCK, &mountlist_slock, p);
472 if (mp->mnt_flag & MNT_EXPUBLIC)
473 vfs_setpublicfs(NULL, NULL, NULL);
475 vfs_msync(mp, MNT_WAIT);
476 async_flag = mp->mnt_flag & MNT_ASYNC;
477 mp->mnt_flag &=~ MNT_ASYNC;
478 cache_purgevfs(mp); /* remove cache entries for this file sys */
479 if (mp->mnt_syncer != NULL)
480 vrele(mp->mnt_syncer);
481 if (((mp->mnt_flag & MNT_RDONLY) ||
482 (error = VFS_SYNC(mp, MNT_WAIT, p->p_ucred, p)) == 0) ||
484 error = VFS_UNMOUNT(mp, flags, p);
485 simple_lock(&mountlist_slock);
487 if ((mp->mnt_flag & MNT_RDONLY) == 0 && mp->mnt_syncer == NULL)
488 (void) vfs_allocate_syncvnode(mp);
489 mp->mnt_kern_flag &= ~MNTK_UNMOUNT;
490 mp->mnt_flag |= async_flag;
491 lockmgr(&mp->mnt_lock, LK_RELEASE | LK_INTERLOCK | LK_REENABLE,
492 &mountlist_slock, p);
493 if (mp->mnt_kern_flag & MNTK_MWAIT)
497 TAILQ_REMOVE(&mountlist, mp, mnt_list);
498 if ((coveredvp = mp->mnt_vnodecovered) != NULLVP) {
499 coveredvp->v_mountedhere = (struct mount *)0;
502 mp->mnt_vfc->vfc_refcount--;
503 if (!LIST_EMPTY(&mp->mnt_vnodelist))
504 panic("unmount: dangling vnode");
505 lockmgr(&mp->mnt_lock, LK_RELEASE | LK_INTERLOCK, &mountlist_slock, p);
506 if (mp->mnt_kern_flag & MNTK_MWAIT)
508 free((caddr_t)mp, M_MOUNT);
513 * Sync each mounted filesystem.
515 #ifndef _SYS_SYSPROTO_H_
522 static int syncprt = 0;
523 SYSCTL_INT(_debug, OID_AUTO, syncprt, CTLFLAG_RW, &syncprt, 0, "");
530 struct sync_args *uap;
532 register struct mount *mp, *nmp;
535 simple_lock(&mountlist_slock);
536 for (mp = TAILQ_FIRST(&mountlist); mp != NULL; mp = nmp) {
537 if (vfs_busy(mp, LK_NOWAIT, &mountlist_slock, p)) {
538 nmp = TAILQ_NEXT(mp, mnt_list);
541 if ((mp->mnt_flag & MNT_RDONLY) == 0) {
542 asyncflag = mp->mnt_flag & MNT_ASYNC;
543 mp->mnt_flag &= ~MNT_ASYNC;
544 vfs_msync(mp, MNT_NOWAIT);
545 VFS_SYNC(mp, MNT_NOWAIT,
546 ((p != NULL) ? p->p_ucred : NOCRED), p);
547 mp->mnt_flag |= asyncflag;
549 simple_lock(&mountlist_slock);
550 nmp = TAILQ_NEXT(mp, mnt_list);
553 simple_unlock(&mountlist_slock);
556 * XXX don't call vfs_bufstats() yet because that routine
557 * was not imported in the Lite2 merge.
562 #endif /* DIAGNOSTIC */
567 /* XXX PRISON: could be per prison flag */
568 static int prison_quotas;
570 SYSCTL_INT(_kern_prison, OID_AUTO, quotas, CTLFLAG_RW, &prison_quotas, 0, "");
574 * Change filesystem quotas.
576 #ifndef _SYS_SYSPROTO_H_
577 struct quotactl_args {
588 register struct quotactl_args /* {
589 syscallarg(char *) path;
592 syscallarg(caddr_t) arg;
595 register struct mount *mp;
599 if (p->p_prison && !prison_quotas)
601 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
602 if ((error = namei(&nd)) != 0)
604 mp = nd.ni_vp->v_mount;
606 return (VFS_QUOTACTL(mp, SCARG(uap, cmd), SCARG(uap, uid),
607 SCARG(uap, arg), p));
611 * Get filesystem statistics.
613 #ifndef _SYS_SYSPROTO_H_
623 register struct statfs_args /* {
624 syscallarg(char *) path;
625 syscallarg(struct statfs *) buf;
628 register struct mount *mp;
629 register struct statfs *sp;
634 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
635 if ((error = namei(&nd)) != 0)
637 mp = nd.ni_vp->v_mount;
640 error = VFS_STATFS(mp, sp, p);
643 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
644 if (suser_xxx(p->p_ucred, 0, 0)) {
645 bcopy((caddr_t)sp, (caddr_t)&sb, sizeof(sb));
646 sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0;
649 return (copyout((caddr_t)sp, (caddr_t)SCARG(uap, buf), sizeof(*sp)));
653 * Get filesystem statistics.
655 #ifndef _SYS_SYSPROTO_H_
656 struct fstatfs_args {
665 register struct fstatfs_args /* {
667 syscallarg(struct statfs *) buf;
672 register struct statfs *sp;
676 if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
678 mp = ((struct vnode *)fp->f_data)->v_mount;
680 error = VFS_STATFS(mp, sp, p);
683 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
684 if (suser_xxx(p->p_ucred, 0, 0)) {
685 bcopy((caddr_t)sp, (caddr_t)&sb, sizeof(sb));
686 sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0;
689 return (copyout((caddr_t)sp, (caddr_t)SCARG(uap, buf), sizeof(*sp)));
693 * Get statistics on all filesystems.
695 #ifndef _SYS_SYSPROTO_H_
696 struct getfsstat_args {
705 register struct getfsstat_args /* {
706 syscallarg(struct statfs *) buf;
707 syscallarg(long) bufsize;
708 syscallarg(int) flags;
711 register struct mount *mp, *nmp;
712 register struct statfs *sp;
714 long count, maxcount, error;
716 maxcount = SCARG(uap, bufsize) / sizeof(struct statfs);
717 sfsp = (caddr_t)SCARG(uap, buf);
719 simple_lock(&mountlist_slock);
720 for (mp = TAILQ_FIRST(&mountlist); mp != NULL; mp = nmp) {
721 if (vfs_busy(mp, LK_NOWAIT, &mountlist_slock, p)) {
722 nmp = TAILQ_NEXT(mp, mnt_list);
725 if (sfsp && count < maxcount) {
728 * If MNT_NOWAIT or MNT_LAZY is specified, do not
729 * refresh the fsstat cache. MNT_NOWAIT or MNT_LAZY
730 * overrides MNT_WAIT.
732 if (((SCARG(uap, flags) & (MNT_LAZY|MNT_NOWAIT)) == 0 ||
733 (SCARG(uap, flags) & MNT_WAIT)) &&
734 (error = VFS_STATFS(mp, sp, p))) {
735 simple_lock(&mountlist_slock);
736 nmp = TAILQ_NEXT(mp, mnt_list);
740 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
741 error = copyout((caddr_t)sp, sfsp, sizeof(*sp));
749 simple_lock(&mountlist_slock);
750 nmp = TAILQ_NEXT(mp, mnt_list);
753 simple_unlock(&mountlist_slock);
754 if (sfsp && count > maxcount)
755 p->p_retval[0] = maxcount;
757 p->p_retval[0] = count;
762 * Change current working directory to a given file descriptor.
764 #ifndef _SYS_SYSPROTO_H_
773 struct fchdir_args /* {
777 register struct filedesc *fdp = p->p_fd;
778 struct vnode *vp, *tdp;
783 if ((error = getvnode(fdp, SCARG(uap, fd), &fp)) != 0)
785 vp = (struct vnode *)fp->f_data;
787 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
788 if (vp->v_type != VDIR)
791 error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p);
792 while (!error && (mp = vp->v_mountedhere) != NULL) {
793 if (vfs_busy(mp, 0, 0, p))
795 error = VFS_ROOT(mp, &tdp);
806 VOP_UNLOCK(vp, 0, p);
813 * Change current working directory (``.'').
815 #ifndef _SYS_SYSPROTO_H_
824 struct chdir_args /* {
825 syscallarg(char *) path;
828 register struct filedesc *fdp = p->p_fd;
832 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
833 SCARG(uap, path), p);
834 if ((error = change_dir(&nd, p)) != 0)
837 fdp->fd_cdir = nd.ni_vp;
842 * Helper function for raised chroot(2) security function: Refuse if
843 * any filedescriptors are open directories.
846 chroot_refuse_vdir_fds(fdp)
847 struct filedesc *fdp;
854 for (fd = 0; fd < fdp->fd_nfiles ; fd++) {
855 error = getvnode(fdp, fd, &fp);
858 vp = (struct vnode *)fp->f_data;
859 if (vp->v_type != VDIR)
867 * This sysctl determines if we will allow a process to chroot(2) if it
868 * has a directory open:
869 * 0: disallowed for all processes.
870 * 1: allowed for processes that were not already chroot(2)'ed.
871 * 2: allowed for all processes.
874 static int chroot_allow_open_directories = 1;
876 SYSCTL_INT(_kern, OID_AUTO, chroot_allow_open_directories, CTLFLAG_RW,
877 &chroot_allow_open_directories, 0, "");
880 * Change notion of root (``/'') directory.
882 #ifndef _SYS_SYSPROTO_H_
891 struct chroot_args /* {
892 syscallarg(char *) path;
895 register struct filedesc *fdp = p->p_fd;
899 error = suser_xxx(0, p, PRISON_ROOT);
902 if (chroot_allow_open_directories == 0 ||
903 (chroot_allow_open_directories == 1 && fdp->fd_rdir != rootvnode))
904 error = chroot_refuse_vdir_fds(fdp);
907 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
908 SCARG(uap, path), p);
909 if ((error = change_dir(&nd, p)) != 0)
912 fdp->fd_rdir = nd.ni_vp;
914 fdp->fd_jdir = nd.ni_vp;
921 * Common routine for chroot and chdir.
925 register struct nameidata *ndp;
935 if (vp->v_type != VDIR)
938 error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p);
942 VOP_UNLOCK(vp, 0, p);
947 * Check permissions, allocate an open file structure,
948 * and call the device open routine if any.
950 #ifndef _SYS_SYSPROTO_H_
960 register struct open_args /* {
961 syscallarg(char *) path;
962 syscallarg(int) flags;
963 syscallarg(int) mode;
966 register struct filedesc *fdp = p->p_fd;
967 register struct file *fp;
968 register struct vnode *vp;
969 int cmode, flags, oflags;
971 int type, indx, error;
975 oflags = SCARG(uap, flags);
976 if ((oflags & O_ACCMODE) == O_ACCMODE)
978 flags = FFLAGS(oflags);
979 error = falloc(p, &nfp, &indx);
983 cmode = ((SCARG(uap, mode) &~ fdp->fd_cmask) & ALLPERMS) &~ S_ISTXT;
984 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
985 p->p_dupfd = -indx - 1; /* XXX check for fdopen */
986 error = vn_open(&nd, flags, cmode);
989 if ((error == ENODEV || error == ENXIO) &&
990 p->p_dupfd >= 0 && /* XXX from fdopen */
992 dupfdopen(fdp, indx, p->p_dupfd, flags, error)) == 0) {
993 p->p_retval[0] = indx;
996 if (error == ERESTART)
998 fdp->fd_ofiles[indx] = NULL;
1004 fp->f_data = (caddr_t)vp;
1005 fp->f_flag = flags & FMASK;
1007 fp->f_type = (vp->v_type == VFIFO ? DTYPE_FIFO : DTYPE_VNODE);
1008 if (flags & (O_EXLOCK | O_SHLOCK)) {
1009 lf.l_whence = SEEK_SET;
1012 if (flags & O_EXLOCK)
1013 lf.l_type = F_WRLCK;
1015 lf.l_type = F_RDLCK;
1017 if ((flags & FNONBLOCK) == 0)
1019 VOP_UNLOCK(vp, 0, p);
1020 if ((error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type)) != 0) {
1021 (void) vn_close(vp, fp->f_flag, fp->f_cred, p);
1023 fdp->fd_ofiles[indx] = NULL;
1026 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
1027 fp->f_flag |= FHASLOCK;
1029 /* assert that vn_open created a backing object if one is needed */
1030 KASSERT(!vn_canvmio(vp) || vp->v_object != NULL,
1031 ("open: vmio vnode has no backing object after vn_open"));
1032 VOP_UNLOCK(vp, 0, p);
1033 p->p_retval[0] = indx;
1041 #ifndef _SYS_SYSPROTO_H_
1042 struct ocreat_args {
1050 register struct ocreat_args /* {
1051 syscallarg(char *) path;
1052 syscallarg(int) mode;
1055 struct open_args /* {
1056 syscallarg(char *) path;
1057 syscallarg(int) flags;
1058 syscallarg(int) mode;
1061 SCARG(&nuap, path) = SCARG(uap, path);
1062 SCARG(&nuap, mode) = SCARG(uap, mode);
1063 SCARG(&nuap, flags) = O_WRONLY | O_CREAT | O_TRUNC;
1064 return (open(p, &nuap));
1066 #endif /* COMPAT_43 */
1069 * Create a special file.
1071 #ifndef _SYS_SYSPROTO_H_
1082 register struct mknod_args /* {
1083 syscallarg(char *) path;
1084 syscallarg(int) mode;
1085 syscallarg(int) dev;
1088 register struct vnode *vp;
1092 struct nameidata nd;
1094 switch (SCARG(uap, mode) & S_IFMT) {
1100 error = suser_xxx(0, p, PRISON_ROOT);
1105 NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p);
1106 if ((error = namei(&nd)) != 0)
1113 vattr.va_mode = (SCARG(uap, mode) & ALLPERMS) &~ p->p_fd->fd_cmask;
1114 vattr.va_rdev = SCARG(uap, dev);
1117 switch (SCARG(uap, mode) & S_IFMT) {
1118 case S_IFMT: /* used by badsect to flag bad sectors */
1119 vattr.va_type = VBAD;
1122 vattr.va_type = VCHR;
1125 vattr.va_type = VBLK;
1136 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
1138 error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, CREATE);
1140 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1143 error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp,
1144 &nd.ni_cnd, &vattr);
1150 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1151 if (nd.ni_dvp == vp)
1158 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "mknod");
1159 ASSERT_VOP_UNLOCKED(nd.ni_vp, "mknod");
1164 * Create a named pipe.
1166 #ifndef _SYS_SYSPROTO_H_
1167 struct mkfifo_args {
1176 register struct mkfifo_args /* {
1177 syscallarg(char *) path;
1178 syscallarg(int) mode;
1183 struct nameidata nd;
1185 NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p);
1186 if ((error = namei(&nd)) != 0)
1188 if (nd.ni_vp != NULL) {
1189 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1190 if (nd.ni_dvp == nd.ni_vp)
1198 vattr.va_type = VFIFO;
1199 vattr.va_mode = (SCARG(uap, mode) & ALLPERMS) &~ p->p_fd->fd_cmask;
1200 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
1201 error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
1209 * Make a hard file link.
1211 #ifndef _SYS_SYSPROTO_H_
1221 register struct link_args /* {
1222 syscallarg(char *) path;
1223 syscallarg(char *) link;
1226 register struct vnode *vp;
1227 struct nameidata nd;
1230 NDINIT(&nd, LOOKUP, FOLLOW|NOOBJ, UIO_USERSPACE, SCARG(uap, path), p);
1231 if ((error = namei(&nd)) != 0)
1234 if (vp->v_type == VDIR)
1235 error = EPERM; /* POSIX */
1237 NDINIT(&nd, CREATE, LOCKPARENT|NOOBJ, UIO_USERSPACE, SCARG(uap, link), p);
1240 if (nd.ni_vp != NULL) {
1241 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1246 VOP_LEASE(nd.ni_dvp, p, p->p_ucred,
1248 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
1249 error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd);
1251 if (nd.ni_dvp == nd.ni_vp)
1258 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "link");
1259 ASSERT_VOP_UNLOCKED(nd.ni_vp, "link");
1264 * Make a symbolic link.
1266 #ifndef _SYS_SYSPROTO_H_
1267 struct symlink_args {
1276 register struct symlink_args /* {
1277 syscallarg(char *) path;
1278 syscallarg(char *) link;
1284 struct nameidata nd;
1286 path = zalloc(namei_zone);
1287 if ((error = copyinstr(SCARG(uap, path), path, MAXPATHLEN, NULL)) != 0)
1289 NDINIT(&nd, CREATE, LOCKPARENT|NOOBJ, UIO_USERSPACE, SCARG(uap, link), p);
1290 if ((error = namei(&nd)) != 0)
1293 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1294 if (nd.ni_dvp == nd.ni_vp)
1303 vattr.va_mode = ACCESSPERMS &~ p->p_fd->fd_cmask;
1304 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
1305 error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr, path);
1309 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "symlink");
1311 ASSERT_VOP_UNLOCKED(nd.ni_vp, "symlink");
1313 zfree(namei_zone, path);
1318 * Delete a whiteout from the filesystem.
1324 register struct undelete_args /* {
1325 syscallarg(char *) path;
1329 struct nameidata nd;
1331 NDINIT(&nd, DELETE, LOCKPARENT|DOWHITEOUT, UIO_USERSPACE,
1332 SCARG(uap, path), p);
1337 if (nd.ni_vp != NULLVP || !(nd.ni_cnd.cn_flags & ISWHITEOUT)) {
1338 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1339 if (nd.ni_dvp == nd.ni_vp)
1348 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
1349 if ((error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, DELETE)) != 0)
1350 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1352 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "undelete");
1353 ASSERT_VOP_UNLOCKED(nd.ni_vp, "undelete");
1358 * Delete a name from the filesystem.
1360 #ifndef _SYS_SYSPROTO_H_
1361 struct unlink_args {
1369 struct unlink_args /* {
1370 syscallarg(char *) path;
1373 register struct vnode *vp;
1375 struct nameidata nd;
1377 NDINIT(&nd, DELETE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p);
1378 if ((error = namei(&nd)) != 0)
1381 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
1382 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
1384 if (vp->v_type == VDIR)
1385 error = EPERM; /* POSIX */
1388 * The root of a mounted filesystem cannot be deleted.
1390 * XXX: can this only be a VDIR case?
1392 if (vp->v_flag & VROOT)
1397 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
1398 error = VOP_REMOVE(nd.ni_dvp, vp, &nd.ni_cnd);
1400 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1402 if (nd.ni_dvp == vp)
1408 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "unlink");
1409 ASSERT_VOP_UNLOCKED(nd.ni_vp, "unlink");
1414 * Reposition read/write file offset.
1416 #ifndef _SYS_SYSPROTO_H_
1427 register struct lseek_args /* {
1429 syscallarg(int) pad;
1430 syscallarg(off_t) offset;
1431 syscallarg(int) whence;
1434 struct ucred *cred = p->p_ucred;
1435 register struct filedesc *fdp = p->p_fd;
1436 register struct file *fp;
1440 if ((u_int)SCARG(uap, fd) >= fdp->fd_nfiles ||
1441 (fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL)
1443 if (fp->f_type != DTYPE_VNODE)
1445 switch (SCARG(uap, whence)) {
1447 fp->f_offset += SCARG(uap, offset);
1450 error=VOP_GETATTR((struct vnode *)fp->f_data, &vattr, cred, p);
1453 fp->f_offset = SCARG(uap, offset) + vattr.va_size;
1456 fp->f_offset = SCARG(uap, offset);
1461 *(off_t *)(p->p_retval) = fp->f_offset;
1465 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
1467 * Reposition read/write file offset.
1469 #ifndef _SYS_SYSPROTO_H_
1470 struct olseek_args {
1479 register struct olseek_args /* {
1481 syscallarg(long) offset;
1482 syscallarg(int) whence;
1485 struct lseek_args /* {
1487 syscallarg(int) pad;
1488 syscallarg(off_t) offset;
1489 syscallarg(int) whence;
1493 SCARG(&nuap, fd) = SCARG(uap, fd);
1494 SCARG(&nuap, offset) = SCARG(uap, offset);
1495 SCARG(&nuap, whence) = SCARG(uap, whence);
1496 error = lseek(p, &nuap);
1499 #endif /* COMPAT_43 */
1502 * Check access permissions.
1504 #ifndef _SYS_SYSPROTO_H_
1505 struct access_args {
1513 register struct access_args /* {
1514 syscallarg(char *) path;
1515 syscallarg(int) flags;
1518 register struct ucred *cred = p->p_ucred;
1519 register struct vnode *vp;
1520 int error, flags, t_gid, t_uid;
1521 struct nameidata nd;
1523 t_uid = cred->cr_uid;
1524 t_gid = cred->cr_groups[0];
1525 cred->cr_uid = p->p_cred->p_ruid;
1526 cred->cr_groups[0] = p->p_cred->p_rgid;
1527 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
1528 SCARG(uap, path), p);
1529 if ((error = namei(&nd)) != 0)
1533 /* Flags == 0 means only check for existence. */
1534 if (SCARG(uap, flags)) {
1536 if (SCARG(uap, flags) & R_OK)
1538 if (SCARG(uap, flags) & W_OK)
1540 if (SCARG(uap, flags) & X_OK)
1542 if ((flags & VWRITE) == 0 || (error = vn_writechk(vp)) == 0)
1543 error = VOP_ACCESS(vp, flags, cred, p);
1547 cred->cr_uid = t_uid;
1548 cred->cr_groups[0] = t_gid;
1552 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
1554 * Get file status; this version follows links.
1556 #ifndef _SYS_SYSPROTO_H_
1566 register struct ostat_args /* {
1567 syscallarg(char *) path;
1568 syscallarg(struct ostat *) ub;
1574 struct nameidata nd;
1576 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
1577 SCARG(uap, path), p);
1578 if ((error = namei(&nd)) != 0)
1580 error = vn_stat(nd.ni_vp, &sb, p);
1585 error = copyout((caddr_t)&osb, (caddr_t)SCARG(uap, ub), sizeof (osb));
1590 * Get file status; this version does not follow links.
1592 #ifndef _SYS_SYSPROTO_H_
1593 struct olstat_args {
1602 register struct olstat_args /* {
1603 syscallarg(char *) path;
1604 syscallarg(struct ostat *) ub;
1611 struct nameidata nd;
1613 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
1614 SCARG(uap, path), p);
1615 if ((error = namei(&nd)) != 0)
1618 error = vn_stat(vp, &sb, p);
1623 error = copyout((caddr_t)&osb, (caddr_t)SCARG(uap, ub), sizeof (osb));
1628 * Convert from an old to a new stat structure.
1636 ost->st_dev = st->st_dev;
1637 ost->st_ino = st->st_ino;
1638 ost->st_mode = st->st_mode;
1639 ost->st_nlink = st->st_nlink;
1640 ost->st_uid = st->st_uid;
1641 ost->st_gid = st->st_gid;
1642 ost->st_rdev = st->st_rdev;
1643 if (st->st_size < (quad_t)1 << 32)
1644 ost->st_size = st->st_size;
1647 ost->st_atime = st->st_atime;
1648 ost->st_mtime = st->st_mtime;
1649 ost->st_ctime = st->st_ctime;
1650 ost->st_blksize = st->st_blksize;
1651 ost->st_blocks = st->st_blocks;
1652 ost->st_flags = st->st_flags;
1653 ost->st_gen = st->st_gen;
1655 #endif /* COMPAT_43 || COMPAT_SUNOS */
1658 * Get file status; this version follows links.
1660 #ifndef _SYS_SYSPROTO_H_
1670 register struct stat_args /* {
1671 syscallarg(char *) path;
1672 syscallarg(struct stat *) ub;
1677 struct nameidata nd;
1679 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
1680 SCARG(uap, path), p);
1681 if ((error = namei(&nd)) != 0)
1683 error = vn_stat(nd.ni_vp, &sb, p);
1687 error = copyout((caddr_t)&sb, (caddr_t)SCARG(uap, ub), sizeof (sb));
1692 * Get file status; this version does not follow links.
1694 #ifndef _SYS_SYSPROTO_H_
1704 register struct lstat_args /* {
1705 syscallarg(char *) path;
1706 syscallarg(struct stat *) ub;
1712 struct nameidata nd;
1714 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
1715 SCARG(uap, path), p);
1716 if ((error = namei(&nd)) != 0)
1719 error = vn_stat(vp, &sb, p);
1723 error = copyout((caddr_t)&sb, (caddr_t)SCARG(uap, ub), sizeof (sb));
1732 nsb->st_dev = sb->st_dev;
1733 nsb->st_ino = sb->st_ino;
1734 nsb->st_mode = sb->st_mode;
1735 nsb->st_nlink = sb->st_nlink;
1736 nsb->st_uid = sb->st_uid;
1737 nsb->st_gid = sb->st_gid;
1738 nsb->st_rdev = sb->st_rdev;
1739 nsb->st_atimespec = sb->st_atimespec;
1740 nsb->st_mtimespec = sb->st_mtimespec;
1741 nsb->st_ctimespec = sb->st_ctimespec;
1742 nsb->st_size = sb->st_size;
1743 nsb->st_blocks = sb->st_blocks;
1744 nsb->st_blksize = sb->st_blksize;
1745 nsb->st_flags = sb->st_flags;
1746 nsb->st_gen = sb->st_gen;
1747 nsb->st_qspare[0] = sb->st_qspare[0];
1748 nsb->st_qspare[1] = sb->st_qspare[1];
1751 #ifndef _SYS_SYSPROTO_H_
1761 register struct nstat_args /* {
1762 syscallarg(char *) path;
1763 syscallarg(struct nstat *) ub;
1769 struct nameidata nd;
1771 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
1772 SCARG(uap, path), p);
1773 if ((error = namei(&nd)) != 0)
1775 error = vn_stat(nd.ni_vp, &sb, p);
1779 cvtnstat(&sb, &nsb);
1780 error = copyout((caddr_t)&nsb, (caddr_t)SCARG(uap, ub), sizeof (nsb));
1785 * Get file status; this version does not follow links.
1787 #ifndef _SYS_SYSPROTO_H_
1797 register struct nlstat_args /* {
1798 syscallarg(char *) path;
1799 syscallarg(struct nstat *) ub;
1806 struct nameidata nd;
1808 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
1809 SCARG(uap, path), p);
1810 if ((error = namei(&nd)) != 0)
1813 error = vn_stat(vp, &sb, p);
1817 cvtnstat(&sb, &nsb);
1818 error = copyout((caddr_t)&nsb, (caddr_t)SCARG(uap, ub), sizeof (nsb));
1823 * Get configurable pathname variables.
1825 #ifndef _SYS_SYSPROTO_H_
1826 struct pathconf_args {
1835 register struct pathconf_args /* {
1836 syscallarg(char *) path;
1837 syscallarg(int) name;
1841 struct nameidata nd;
1843 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
1844 SCARG(uap, path), p);
1845 if ((error = namei(&nd)) != 0)
1847 error = VOP_PATHCONF(nd.ni_vp, SCARG(uap, name), p->p_retval);
1853 * Return target name of a symbolic link.
1855 #ifndef _SYS_SYSPROTO_H_
1856 struct readlink_args {
1866 register struct readlink_args /* {
1867 syscallarg(char *) path;
1868 syscallarg(char *) buf;
1869 syscallarg(int) count;
1872 register struct vnode *vp;
1876 struct nameidata nd;
1878 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
1879 SCARG(uap, path), p);
1880 if ((error = namei(&nd)) != 0)
1883 if (vp->v_type != VLNK)
1886 aiov.iov_base = SCARG(uap, buf);
1887 aiov.iov_len = SCARG(uap, count);
1888 auio.uio_iov = &aiov;
1889 auio.uio_iovcnt = 1;
1890 auio.uio_offset = 0;
1891 auio.uio_rw = UIO_READ;
1892 auio.uio_segflg = UIO_USERSPACE;
1894 auio.uio_resid = SCARG(uap, count);
1895 error = VOP_READLINK(vp, &auio, p->p_ucred);
1898 p->p_retval[0] = SCARG(uap, count) - auio.uio_resid;
1903 setfflags(p, vp, flags)
1912 * Prevent non-root users from setting flags on devices. When
1913 * a device is reused, users can retain ownership of the device
1914 * if they are allowed to set flags and programs assume that
1915 * chown can't fail when done as root.
1917 if ((vp->v_type == VCHR || vp->v_type == VBLK) &&
1918 ((error = suser_xxx(p->p_ucred, p, PRISON_ROOT)) != 0))
1921 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
1922 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
1924 vattr.va_flags = flags;
1925 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1926 VOP_UNLOCK(vp, 0, p);
1931 * Change flags of a file given a path name.
1933 #ifndef _SYS_SYSPROTO_H_
1934 struct chflags_args {
1943 register struct chflags_args /* {
1944 syscallarg(char *) path;
1945 syscallarg(int) flags;
1949 struct nameidata nd;
1951 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
1952 if ((error = namei(&nd)) != 0)
1954 error = setfflags(p, nd.ni_vp, SCARG(uap, flags));
1960 * Change flags of a file given a file descriptor.
1962 #ifndef _SYS_SYSPROTO_H_
1963 struct fchflags_args {
1972 register struct fchflags_args /* {
1974 syscallarg(int) flags;
1980 if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
1982 return setfflags(p, (struct vnode *) fp->f_data, SCARG(uap, flags));
1986 setfmode(p, vp, mode)
1994 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
1995 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
1997 vattr.va_mode = mode & ALLPERMS;
1998 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1999 VOP_UNLOCK(vp, 0, p);
2004 * Change mode of a file given path name.
2006 #ifndef _SYS_SYSPROTO_H_
2016 register struct chmod_args /* {
2017 syscallarg(char *) path;
2018 syscallarg(int) mode;
2022 struct nameidata nd;
2024 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
2025 if ((error = namei(&nd)) != 0)
2027 error = setfmode(p, nd.ni_vp, SCARG(uap, mode));
2033 * Change mode of a file given path name (don't follow links.)
2035 #ifndef _SYS_SYSPROTO_H_
2036 struct lchmod_args {
2045 register struct lchmod_args /* {
2046 syscallarg(char *) path;
2047 syscallarg(int) mode;
2051 struct nameidata nd;
2053 NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
2054 if ((error = namei(&nd)) != 0)
2056 error = setfmode(p, nd.ni_vp, SCARG(uap, mode));
2062 * Change mode of a file given a file descriptor.
2064 #ifndef _SYS_SYSPROTO_H_
2065 struct fchmod_args {
2074 register struct fchmod_args /* {
2076 syscallarg(int) mode;
2082 if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
2084 return setfmode(p, (struct vnode *)fp->f_data, SCARG(uap, mode));
2088 setfown(p, vp, uid, gid)
2097 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
2098 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
2102 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
2103 VOP_UNLOCK(vp, 0, p);
2108 * Set ownership given a path name.
2110 #ifndef _SYS_SYSPROTO_H_
2121 register struct chown_args /* {
2122 syscallarg(char *) path;
2123 syscallarg(int) uid;
2124 syscallarg(int) gid;
2128 struct nameidata nd;
2130 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
2131 if ((error = namei(&nd)) != 0)
2133 error = setfown(p, nd.ni_vp, SCARG(uap, uid), SCARG(uap, gid));
2140 * Set ownership given a path name, do not cross symlinks.
2142 #ifndef _SYS_SYSPROTO_H_
2143 struct lchown_args {
2153 register struct lchown_args /* {
2154 syscallarg(char *) path;
2155 syscallarg(int) uid;
2156 syscallarg(int) gid;
2160 struct nameidata nd;
2162 NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
2163 if ((error = namei(&nd)) != 0)
2165 error = setfown(p, nd.ni_vp, SCARG(uap, uid), SCARG(uap, gid));
2171 * Set ownership given a file descriptor.
2173 #ifndef _SYS_SYSPROTO_H_
2174 struct fchown_args {
2184 register struct fchown_args /* {
2186 syscallarg(int) uid;
2187 syscallarg(int) gid;
2193 if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
2195 return setfown(p, (struct vnode *)fp->f_data,
2196 SCARG(uap, uid), SCARG(uap, gid));
2200 getutimes(usrtvp, tsp)
2201 const struct timeval *usrtvp;
2202 struct timespec *tsp;
2204 struct timeval tv[2];
2207 if (usrtvp == NULL) {
2209 TIMEVAL_TO_TIMESPEC(&tv[0], &tsp[0]);
2212 if ((error = copyin(usrtvp, tv, sizeof (tv))) != 0)
2214 TIMEVAL_TO_TIMESPEC(&tv[0], &tsp[0]);
2215 TIMEVAL_TO_TIMESPEC(&tv[1], &tsp[1]);
2221 setutimes(p, vp, ts, nullflag)
2224 const struct timespec *ts;
2230 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
2231 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
2233 vattr.va_atime = ts[0];
2234 vattr.va_mtime = ts[1];
2236 vattr.va_vaflags |= VA_UTIMES_NULL;
2237 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
2238 VOP_UNLOCK(vp, 0, p);
2243 * Set the access and modification times of a file.
2245 #ifndef _SYS_SYSPROTO_H_
2246 struct utimes_args {
2248 struct timeval *tptr;
2255 register struct utimes_args /* {
2256 syscallarg(char *) path;
2257 syscallarg(struct timeval *) tptr;
2260 struct timespec ts[2];
2261 struct timeval *usrtvp;
2263 struct nameidata nd;
2265 usrtvp = SCARG(uap, tptr);
2266 if ((error = getutimes(usrtvp, ts)) != 0)
2268 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
2269 if ((error = namei(&nd)) != 0)
2271 error = setutimes(p, nd.ni_vp, ts, usrtvp == NULL);
2277 * Set the access and modification times of a file.
2279 #ifndef _SYS_SYSPROTO_H_
2280 struct lutimes_args {
2282 struct timeval *tptr;
2289 register struct lutimes_args /* {
2290 syscallarg(char *) path;
2291 syscallarg(struct timeval *) tptr;
2294 struct timespec ts[2];
2295 struct timeval *usrtvp;
2297 struct nameidata nd;
2299 usrtvp = SCARG(uap, tptr);
2300 if ((error = getutimes(usrtvp, ts)) != 0)
2302 NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
2303 if ((error = namei(&nd)) != 0)
2305 error = setutimes(p, nd.ni_vp, ts, usrtvp == NULL);
2311 * Set the access and modification times of a file.
2313 #ifndef _SYS_SYSPROTO_H_
2314 struct futimes_args {
2316 struct timeval *tptr;
2323 register struct futimes_args /* {
2324 syscallarg(int ) fd;
2325 syscallarg(struct timeval *) tptr;
2328 struct timespec ts[2];
2330 struct timeval *usrtvp;
2333 usrtvp = SCARG(uap, tptr);
2334 if ((error = getutimes(usrtvp, ts)) != 0)
2336 if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
2338 return setutimes(p, (struct vnode *)fp->f_data, ts, usrtvp == NULL);
2342 * Truncate a file given its path name.
2344 #ifndef _SYS_SYSPROTO_H_
2345 struct truncate_args {
2355 register struct truncate_args /* {
2356 syscallarg(char *) path;
2357 syscallarg(int) pad;
2358 syscallarg(off_t) length;
2361 register struct vnode *vp;
2364 struct nameidata nd;
2366 if (uap->length < 0)
2368 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
2369 if ((error = namei(&nd)) != 0)
2372 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
2373 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
2374 if (vp->v_type == VDIR)
2376 else if ((error = vn_writechk(vp)) == 0 &&
2377 (error = VOP_ACCESS(vp, VWRITE, p->p_ucred, p)) == 0) {
2379 vattr.va_size = SCARG(uap, length);
2380 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
2387 * Truncate a file given a file descriptor.
2389 #ifndef _SYS_SYSPROTO_H_
2390 struct ftruncate_args {
2400 register struct ftruncate_args /* {
2402 syscallarg(int) pad;
2403 syscallarg(off_t) length;
2411 if (uap->length < 0)
2413 if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
2415 if ((fp->f_flag & FWRITE) == 0)
2417 vp = (struct vnode *)fp->f_data;
2418 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
2419 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
2420 if (vp->v_type == VDIR)
2422 else if ((error = vn_writechk(vp)) == 0) {
2424 vattr.va_size = SCARG(uap, length);
2425 error = VOP_SETATTR(vp, &vattr, fp->f_cred, p);
2427 VOP_UNLOCK(vp, 0, p);
2431 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
2433 * Truncate a file given its path name.
2435 #ifndef _SYS_SYSPROTO_H_
2436 struct otruncate_args {
2445 register struct otruncate_args /* {
2446 syscallarg(char *) path;
2447 syscallarg(long) length;
2450 struct truncate_args /* {
2451 syscallarg(char *) path;
2452 syscallarg(int) pad;
2453 syscallarg(off_t) length;
2456 SCARG(&nuap, path) = SCARG(uap, path);
2457 SCARG(&nuap, length) = SCARG(uap, length);
2458 return (truncate(p, &nuap));
2462 * Truncate a file given a file descriptor.
2464 #ifndef _SYS_SYSPROTO_H_
2465 struct oftruncate_args {
2474 register struct oftruncate_args /* {
2476 syscallarg(long) length;
2479 struct ftruncate_args /* {
2481 syscallarg(int) pad;
2482 syscallarg(off_t) length;
2485 SCARG(&nuap, fd) = SCARG(uap, fd);
2486 SCARG(&nuap, length) = SCARG(uap, length);
2487 return (ftruncate(p, &nuap));
2489 #endif /* COMPAT_43 || COMPAT_SUNOS */
2492 * Sync an open file.
2494 #ifndef _SYS_SYSPROTO_H_
2503 struct fsync_args /* {
2507 register struct vnode *vp;
2511 if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
2513 vp = (struct vnode *)fp->f_data;
2514 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
2516 vm_object_page_clean(vp->v_object, 0, 0, 0);
2517 if ((error = VOP_FSYNC(vp, fp->f_cred, MNT_WAIT, p)) == 0 &&
2518 vp->v_mount && (vp->v_mount->mnt_flag & MNT_SOFTDEP) &&
2520 error = (*bioops.io_fsync)(vp);
2521 VOP_UNLOCK(vp, 0, p);
2526 * Rename files. Source and destination must either both be directories,
2527 * or both not be directories. If target is a directory, it must be empty.
2529 #ifndef _SYS_SYSPROTO_H_
2530 struct rename_args {
2539 register struct rename_args /* {
2540 syscallarg(char *) from;
2541 syscallarg(char *) to;
2544 register struct vnode *tvp, *fvp, *tdvp;
2545 struct nameidata fromnd, tond;
2548 NDINIT(&fromnd, DELETE, WANTPARENT | SAVESTART, UIO_USERSPACE,
2549 SCARG(uap, from), p);
2550 if ((error = namei(&fromnd)) != 0)
2553 NDINIT(&tond, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART | NOOBJ,
2554 UIO_USERSPACE, SCARG(uap, to), p);
2555 if (fromnd.ni_vp->v_type == VDIR)
2556 tond.ni_cnd.cn_flags |= WILLBEDIR;
2557 if ((error = namei(&tond)) != 0) {
2558 /* Translate error code for rename("dir1", "dir2/."). */
2559 if (error == EISDIR && fvp->v_type == VDIR)
2561 VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
2562 vrele(fromnd.ni_dvp);
2569 if (fvp->v_type == VDIR && tvp->v_type != VDIR) {
2572 } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) {
2580 * If source is the same as the destination (that is the
2581 * same inode number with the same name in the same directory),
2582 * then there is nothing to do.
2584 if (fvp == tvp && fromnd.ni_dvp == tdvp &&
2585 fromnd.ni_cnd.cn_namelen == tond.ni_cnd.cn_namelen &&
2586 !bcmp(fromnd.ni_cnd.cn_nameptr, tond.ni_cnd.cn_nameptr,
2587 fromnd.ni_cnd.cn_namelen))
2591 VOP_LEASE(tdvp, p, p->p_ucred, LEASE_WRITE);
2592 if (fromnd.ni_dvp != tdvp) {
2593 VOP_LEASE(fromnd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
2596 VOP_LEASE(tvp, p, p->p_ucred, LEASE_WRITE);
2598 error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd,
2599 tond.ni_dvp, tond.ni_vp, &tond.ni_cnd);
2601 VOP_ABORTOP(tond.ni_dvp, &tond.ni_cnd);
2608 VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
2609 vrele(fromnd.ni_dvp);
2612 vrele(tond.ni_startdir);
2613 ASSERT_VOP_UNLOCKED(fromnd.ni_dvp, "rename");
2614 ASSERT_VOP_UNLOCKED(fromnd.ni_vp, "rename");
2615 ASSERT_VOP_UNLOCKED(tond.ni_dvp, "rename");
2616 ASSERT_VOP_UNLOCKED(tond.ni_vp, "rename");
2617 zfree(namei_zone, tond.ni_cnd.cn_pnbuf);
2619 if (fromnd.ni_startdir)
2620 vrele(fromnd.ni_startdir);
2621 zfree(namei_zone, fromnd.ni_cnd.cn_pnbuf);
2628 * Make a directory file.
2630 #ifndef _SYS_SYSPROTO_H_
2640 register struct mkdir_args /* {
2641 syscallarg(char *) path;
2642 syscallarg(int) mode;
2645 register struct vnode *vp;
2648 struct nameidata nd;
2650 NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p);
2651 nd.ni_cnd.cn_flags |= WILLBEDIR;
2652 if ((error = namei(&nd)) != 0)
2656 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
2657 if (nd.ni_dvp == vp)
2665 vattr.va_type = VDIR;
2666 vattr.va_mode = (SCARG(uap, mode) & ACCESSPERMS) &~ p->p_fd->fd_cmask;
2667 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
2668 error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
2672 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "mkdir");
2673 ASSERT_VOP_UNLOCKED(nd.ni_vp, "mkdir");
2678 * Remove a directory file.
2680 #ifndef _SYS_SYSPROTO_H_
2689 struct rmdir_args /* {
2690 syscallarg(char *) path;
2693 register struct vnode *vp;
2695 struct nameidata nd;
2697 NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF, UIO_USERSPACE,
2698 SCARG(uap, path), p);
2699 if ((error = namei(&nd)) != 0)
2702 if (vp->v_type != VDIR) {
2707 * No rmdir "." please.
2709 if (nd.ni_dvp == vp) {
2714 * The root of a mounted filesystem cannot be deleted.
2716 if (vp->v_flag & VROOT)
2720 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
2721 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
2722 error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
2724 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
2726 if (nd.ni_dvp == vp)
2732 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "rmdir");
2733 ASSERT_VOP_UNLOCKED(nd.ni_vp, "rmdir");
2739 * Read a block of directory entries in a file system independent format.
2741 #ifndef _SYS_SYSPROTO_H_
2742 struct ogetdirentries_args {
2750 ogetdirentries(p, uap)
2752 register struct ogetdirentries_args /* {
2754 syscallarg(char *) buf;
2755 syscallarg(u_int) count;
2756 syscallarg(long *) basep;
2761 struct uio auio, kuio;
2762 struct iovec aiov, kiov;
2763 struct dirent *dp, *edp;
2765 int error, eofflag, readcnt;
2768 if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
2770 if ((fp->f_flag & FREAD) == 0)
2772 vp = (struct vnode *)fp->f_data;
2774 if (vp->v_type != VDIR)
2776 aiov.iov_base = SCARG(uap, buf);
2777 aiov.iov_len = SCARG(uap, count);
2778 auio.uio_iov = &aiov;
2779 auio.uio_iovcnt = 1;
2780 auio.uio_rw = UIO_READ;
2781 auio.uio_segflg = UIO_USERSPACE;
2783 auio.uio_resid = SCARG(uap, count);
2784 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
2785 loff = auio.uio_offset = fp->f_offset;
2786 # if (BYTE_ORDER != LITTLE_ENDIAN)
2787 if (vp->v_mount->mnt_maxsymlinklen <= 0) {
2788 error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag,
2790 fp->f_offset = auio.uio_offset;
2795 kuio.uio_iov = &kiov;
2796 kuio.uio_segflg = UIO_SYSSPACE;
2797 kiov.iov_len = SCARG(uap, count);
2798 MALLOC(dirbuf, caddr_t, SCARG(uap, count), M_TEMP, M_WAITOK);
2799 kiov.iov_base = dirbuf;
2800 error = VOP_READDIR(vp, &kuio, fp->f_cred, &eofflag,
2802 fp->f_offset = kuio.uio_offset;
2804 readcnt = SCARG(uap, count) - kuio.uio_resid;
2805 edp = (struct dirent *)&dirbuf[readcnt];
2806 for (dp = (struct dirent *)dirbuf; dp < edp; ) {
2807 # if (BYTE_ORDER == LITTLE_ENDIAN)
2809 * The expected low byte of
2810 * dp->d_namlen is our dp->d_type.
2811 * The high MBZ byte of dp->d_namlen
2812 * is our dp->d_namlen.
2814 dp->d_type = dp->d_namlen;
2818 * The dp->d_type is the high byte
2819 * of the expected dp->d_namlen,
2820 * so must be zero'ed.
2824 if (dp->d_reclen > 0) {
2825 dp = (struct dirent *)
2826 ((char *)dp + dp->d_reclen);
2833 error = uiomove(dirbuf, readcnt, &auio);
2835 FREE(dirbuf, M_TEMP);
2837 VOP_UNLOCK(vp, 0, p);
2840 if (SCARG(uap, count) == auio.uio_resid) {
2841 if (union_dircheckp) {
2842 error = union_dircheckp(p, &vp, fp);
2848 if ((vp->v_flag & VROOT) &&
2849 (vp->v_mount->mnt_flag & MNT_UNION)) {
2850 struct vnode *tvp = vp;
2851 vp = vp->v_mount->mnt_vnodecovered;
2853 fp->f_data = (caddr_t) vp;
2859 error = copyout((caddr_t)&loff, (caddr_t)SCARG(uap, basep),
2861 p->p_retval[0] = SCARG(uap, count) - auio.uio_resid;
2864 #endif /* COMPAT_43 */
2867 * Read a block of directory entries in a file system independent format.
2869 #ifndef _SYS_SYSPROTO_H_
2870 struct getdirentries_args {
2878 getdirentries(p, uap)
2880 register struct getdirentries_args /* {
2882 syscallarg(char *) buf;
2883 syscallarg(u_int) count;
2884 syscallarg(long *) basep;
2894 if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
2896 if ((fp->f_flag & FREAD) == 0)
2898 vp = (struct vnode *)fp->f_data;
2900 if (vp->v_type != VDIR)
2902 aiov.iov_base = SCARG(uap, buf);
2903 aiov.iov_len = SCARG(uap, count);
2904 auio.uio_iov = &aiov;
2905 auio.uio_iovcnt = 1;
2906 auio.uio_rw = UIO_READ;
2907 auio.uio_segflg = UIO_USERSPACE;
2909 auio.uio_resid = SCARG(uap, count);
2910 /* vn_lock(vp, LK_SHARED | LK_RETRY, p); */
2911 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
2912 loff = auio.uio_offset = fp->f_offset;
2913 error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, NULL, NULL);
2914 fp->f_offset = auio.uio_offset;
2915 VOP_UNLOCK(vp, 0, p);
2918 if (SCARG(uap, count) == auio.uio_resid) {
2919 if (union_dircheckp) {
2920 error = union_dircheckp(p, &vp, fp);
2926 if ((vp->v_flag & VROOT) &&
2927 (vp->v_mount->mnt_flag & MNT_UNION)) {
2928 struct vnode *tvp = vp;
2929 vp = vp->v_mount->mnt_vnodecovered;
2931 fp->f_data = (caddr_t) vp;
2937 if (SCARG(uap, basep) != NULL) {
2938 error = copyout((caddr_t)&loff, (caddr_t)SCARG(uap, basep),
2941 p->p_retval[0] = SCARG(uap, count) - auio.uio_resid;
2944 #ifndef _SYS_SYSPROTO_H_
2945 struct getdents_args {
2954 register struct getdents_args /* {
2956 syscallarg(char *) buf;
2957 syscallarg(u_int) count;
2960 struct getdirentries_args ap;
2963 ap.count = uap->count;
2965 return getdirentries(p, &ap);
2969 * Set the mode mask for creation of filesystem nodes.
2971 #ifndef _SYS_SYSPROTO_H_
2979 struct umask_args /* {
2980 syscallarg(int) newmask;
2983 register struct filedesc *fdp;
2986 p->p_retval[0] = fdp->fd_cmask;
2987 fdp->fd_cmask = SCARG(uap, newmask) & ALLPERMS;
2992 * Void all references to file by ripping underlying filesystem
2995 #ifndef _SYS_SYSPROTO_H_
2996 struct revoke_args {
3004 register struct revoke_args /* {
3005 syscallarg(char *) path;
3008 register struct vnode *vp;
3011 struct nameidata nd;
3013 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
3014 if ((error = namei(&nd)) != 0)
3017 if (vp->v_type != VCHR && vp->v_type != VBLK) {
3021 if ((error = VOP_GETATTR(vp, &vattr, p->p_ucred, p)) != 0)
3023 if (p->p_ucred->cr_uid != vattr.va_uid &&
3024 (error = suser_xxx(0, p, PRISON_ROOT)))
3027 VOP_REVOKE(vp, REVOKEALL);
3034 * Convert a user file descriptor to a kernel file entry.
3037 getvnode(fdp, fd, fpp)
3038 struct filedesc *fdp;
3044 if ((u_int)fd >= fdp->fd_nfiles ||
3045 (fp = fdp->fd_ofiles[fd]) == NULL)
3047 if (fp->f_type != DTYPE_VNODE && fp->f_type != DTYPE_FIFO)
3053 * Get (NFS) file handle
3055 #ifndef _SYS_SYSPROTO_H_
3064 register struct getfh_args *uap;
3066 struct nameidata nd;
3068 register struct vnode *vp;
3072 * Must be super user
3077 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p);
3082 bzero(&fh, sizeof(fh));
3083 fh.fh_fsid = vp->v_mount->mnt_stat.f_fsid;
3084 error = VFS_VPTOFH(vp, &fh.fh_fid);
3088 error = copyout(&fh, uap->fhp, sizeof (fh));
3093 * syscall for the rpc.lockd to use to translate a NFS file handle into
3094 * an open descriptor.
3096 * warning: do not remove the suser() call or this becomes one giant
3099 #ifndef _SYS_SYSPROTO_H_
3100 struct fhopen_args {
3101 const struct fhandle *u_fhp;
3108 struct fhopen_args /* {
3109 syscallarg(const struct fhandle *) u_fhp;
3110 syscallarg(int) flags;
3117 struct vattr *vap = &vat;
3120 register struct filedesc *fdp = p->p_fd;
3121 int fmode, mode, error, type;
3126 * Must be super user
3132 fmode = FFLAGS(SCARG(uap, flags));
3133 /* why not allow a non-read/write open for our lockd? */
3134 if (((fmode & (FREAD | FWRITE)) == 0) || (fmode & O_CREAT))
3136 error = copyin(SCARG(uap,u_fhp), &fhp, sizeof(fhp));
3139 /* find the mount point */
3140 mp = vfs_getvfs(&fhp.fh_fsid);
3143 /* now give me my vnode, it gets returned to me locked */
3144 error = VFS_FHTOVP(mp, &fhp.fh_fid, &vp);
3148 * from now on we have to make sure not
3149 * to forget about the vnode
3150 * any error that causes an abort must vput(vp)
3151 * just set error = err and 'goto bad;'.
3157 if (vp->v_type == VLNK) {
3161 if (vp->v_type == VSOCK) {
3166 if (fmode & (FWRITE | O_TRUNC)) {
3167 if (vp->v_type == VDIR) {
3171 error = vn_writechk(vp);
3179 error = VOP_ACCESS(vp, mode, p->p_ucred, p);
3183 if (fmode & O_TRUNC) {
3184 VOP_UNLOCK(vp, 0, p); /* XXX */
3185 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
3186 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); /* XXX */
3189 error = VOP_SETATTR(vp, vap, p->p_ucred, p);
3193 error = VOP_OPEN(vp, fmode, p->p_ucred, p);
3197 * Make sure that a VM object is created for VMIO support.
3199 if (vn_canvmio(vp) == TRUE) {
3200 if ((error = vfs_object_create(vp, p, p->p_ucred)) != 0)
3207 * end of vn_open code
3210 if ((error = falloc(p, &nfp, &indx)) != 0)
3213 nfp->f_data = (caddr_t)vp;
3214 nfp->f_flag = fmode & FMASK;
3215 nfp->f_ops = &vnops;
3216 nfp->f_type = DTYPE_VNODE;
3217 if (fmode & (O_EXLOCK | O_SHLOCK)) {
3218 lf.l_whence = SEEK_SET;
3221 if (fmode & O_EXLOCK)
3222 lf.l_type = F_WRLCK;
3224 lf.l_type = F_RDLCK;
3226 if ((fmode & FNONBLOCK) == 0)
3228 VOP_UNLOCK(vp, 0, p);
3229 if ((error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type)) != 0) {
3230 (void) vn_close(vp, fp->f_flag, fp->f_cred, p);
3232 fdp->fd_ofiles[indx] = NULL;
3235 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
3236 fp->f_flag |= FHASLOCK;
3238 if ((vp->v_type == VREG) && (vp->v_object == NULL))
3239 vfs_object_create(vp, p, p->p_ucred);
3241 VOP_UNLOCK(vp, 0, p);
3242 p->p_retval[0] = indx;
3250 #ifndef _SYS_SYSPROTO_H_
3251 struct fhstat_args {
3252 struct fhandle *u_fhp;
3259 register struct fhstat_args /* {
3260 syscallarg(struct fhandle *) u_fhp;
3261 syscallarg(struct stat *) sb;
3271 * Must be super user
3277 error = copyin(SCARG(uap, u_fhp), &fh, sizeof(fhandle_t));
3281 if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL)
3283 if ((error = VFS_FHTOVP(mp, &fh.fh_fid, &vp)))
3285 error = vn_stat(vp, &sb, p);
3289 error = copyout(&sb, SCARG(uap, sb), sizeof(sb));
3293 #ifndef _SYS_SYSPROTO_H_
3294 struct fhstatfs_args {
3295 struct fhandle *u_fhp;
3302 struct fhstatfs_args /* {
3303 syscallarg(struct fhandle) *u_fhp;
3304 syscallarg(struct statfs) *buf;
3315 * Must be super user
3317 if ((error = suser(p)))
3320 if ((error = copyin(SCARG(uap, u_fhp), &fh, sizeof(fhandle_t))) != 0)
3323 if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL)
3325 if ((error = VFS_FHTOVP(mp, &fh.fh_fid, &vp)))
3330 if ((error = VFS_STATFS(mp, sp, p)) != 0)
3332 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
3333 if (suser_xxx(p->p_ucred, 0, 0)) {
3334 bcopy((caddr_t)sp, (caddr_t)&sb, sizeof(sb));
3335 sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0;
3338 return (copyout(sp, SCARG(uap, buf), sizeof(*sp)));