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"
46 #include <sys/param.h>
47 #include <sys/systm.h>
50 #include <sys/sysent.h>
51 #include <sys/malloc.h>
52 #include <sys/mount.h>
53 #include <sys/mutex.h>
54 #include <sys/sysproto.h>
55 #include <sys/namei.h>
56 #include <sys/filedesc.h>
57 #include <sys/kernel.h>
58 #include <sys/fcntl.h>
60 #include <sys/linker.h>
63 #include <sys/unistd.h>
64 #include <sys/vnode.h>
66 #include <sys/dirent.h>
67 #include <sys/extattr.h>
69 #include <sys/sysctl.h>
71 #include <machine/limits.h>
74 #include <vm/vm_object.h>
75 #include <vm/vm_zone.h>
76 #include <vm/vm_page.h>
78 static int change_dir __P((struct nameidata *ndp, struct thread *td));
79 static void checkdirs __P((struct vnode *olddp, struct vnode *newdp));
80 static int chroot_refuse_vdir_fds __P((struct filedesc *fdp));
81 static int getutimes __P((const struct timeval *, struct timespec *));
82 static int setfown __P((struct thread *td, struct vnode *, uid_t, gid_t));
83 static int setfmode __P((struct thread *td, struct vnode *, int));
84 static int setfflags __P((struct thread *td, struct vnode *, int));
85 static int setutimes __P((struct thread *td, struct vnode *,
86 const struct timespec *, int));
87 static int vn_access __P((struct vnode *vp, int user_flags, struct ucred *cred,
90 static int usermount = 0; /* if 1, non-root can mount fs. */
92 int (*union_dircheckp) __P((struct thread *td, struct vnode **, struct file *));
94 SYSCTL_INT(_vfs, OID_AUTO, usermount, CTLFLAG_RW, &usermount, 0, "");
97 * Virtual File System System Calls
100 #ifndef _SYS_SYSPROTO_H_
111 struct nmount_args /* {
112 syscallarg(struct iovec *) iovp;
113 syscallarg(unsigned int) iovcnt;
114 syscallarg(int) flags;
122 * Mount a file system.
124 #ifndef _SYS_SYSPROTO_H_
136 struct mount_args /* {
137 syscallarg(char *) type;
138 syscallarg(char *) path;
139 syscallarg(int) flags;
140 syscallarg(caddr_t) data;
147 fstype = malloc(MFSNAMELEN, M_TEMP, M_WAITOK | M_ZERO);
148 fspath = malloc(MNAMELEN, M_TEMP, M_WAITOK | M_ZERO);
151 * vfs_mount() actually takes a kernel string for `type' and
152 * `path' now, so extract them.
154 error = copyinstr(SCARG(uap, type), fstype, MFSNAMELEN, NULL);
157 error = copyinstr(SCARG(uap, path), fspath, MNAMELEN, NULL);
160 error = vfs_mount(td, fstype, fspath, SCARG(uap, flags),
163 free(fstype, M_TEMP);
164 free(fspath, M_TEMP);
169 * vfs_mount(): actually attempt a filesystem mount.
171 * This routine is designed to be a "generic" entry point for routines
172 * that wish to mount a filesystem. All parameters except `fsdata' are
173 * pointers into kernel space. `fsdata' is currently still a pointer
177 vfs_mount(td, fstype, fspath, fsflags, fsdata)
186 struct vfsconf *vfsp;
187 int error, flag = 0, flag2 = 0;
192 * Be ultra-paranoid about making sure the type and fspath
193 * variables will fit in our mp buffers, including the
196 if ((strlen(fstype) >= MFSNAMELEN - 1) ||
197 (strlen(fspath) >= MNAMELEN - 1))
198 return (ENAMETOOLONG);
200 if (usermount == 0) {
201 error = suser_td(td);
206 * Do not allow NFS export by non-root users.
208 if (fsflags & MNT_EXPORTED) {
209 error = suser_td(td);
214 * Silently enforce MNT_NOSUID and MNT_NODEV for non-root users
216 if (suser_xxx(td->td_proc->p_ucred, 0, 0))
217 fsflags |= MNT_NOSUID | MNT_NODEV;
219 * Get vnode to be covered
221 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, fspath, td);
222 if ((error = namei(&nd)) != 0)
224 NDFREE(&nd, NDF_ONLY_PNBUF);
226 if (fsflags & MNT_UPDATE) {
227 if ((vp->v_flag & VROOT) == 0) {
233 flag2 = mp->mnt_kern_flag;
235 * We only allow the filesystem to be reloaded if it
236 * is currently mounted read-only.
238 if ((fsflags & MNT_RELOAD) &&
239 ((mp->mnt_flag & MNT_RDONLY) == 0)) {
241 return (EOPNOTSUPP); /* Needs translation */
244 * Only root, or the user that did the original mount is
245 * permitted to update it.
247 if (mp->mnt_stat.f_owner != td->td_proc->p_ucred->cr_uid) {
248 error = suser_td(td);
254 if (vfs_busy(mp, LK_NOWAIT, 0, td)) {
258 mtx_lock(&vp->v_interlock);
259 if ((vp->v_flag & VMOUNT) != 0 ||
260 vp->v_mountedhere != NULL) {
261 mtx_unlock(&vp->v_interlock);
266 vp->v_flag |= VMOUNT;
267 mtx_unlock(&vp->v_interlock);
268 mp->mnt_flag |= fsflags &
269 (MNT_RELOAD | MNT_FORCE | MNT_UPDATE | MNT_SNAPSHOT);
270 VOP_UNLOCK(vp, 0, td);
274 * If the user is not root, ensure that they own the directory
275 * onto which we are attempting to mount.
277 error = VOP_GETATTR(vp, &va, td->td_proc->p_ucred, td);
282 if (va.va_uid != td->td_proc->p_ucred->cr_uid) {
283 error = suser_td(td);
289 if ((error = vinvalbuf(vp, V_SAVE, td->td_proc->p_ucred, td, 0, 0))
294 if (vp->v_type != VDIR) {
298 for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next)
299 if (!strcmp(vfsp->vfc_name, fstype))
304 /* Only load modules for root (very important!) */
305 error = suser_td(td);
310 error = linker_load_file(fstype, &lf);
311 if (error || lf == NULL) {
318 /* lookup again, see if the VFS was loaded */
319 for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next)
320 if (!strcmp(vfsp->vfc_name, fstype))
324 linker_file_unload(lf);
329 mtx_lock(&vp->v_interlock);
330 if ((vp->v_flag & VMOUNT) != 0 ||
331 vp->v_mountedhere != NULL) {
332 mtx_unlock(&vp->v_interlock);
336 vp->v_flag |= VMOUNT;
337 mtx_unlock(&vp->v_interlock);
340 * Allocate and initialize the filesystem.
342 mp = malloc(sizeof(struct mount), M_MOUNT, M_WAITOK | M_ZERO);
343 TAILQ_INIT(&mp->mnt_nvnodelist);
344 TAILQ_INIT(&mp->mnt_reservedvnlist);
345 lockinit(&mp->mnt_lock, PVFS, "vfslock", 0, LK_NOPAUSE);
346 (void)vfs_busy(mp, LK_NOWAIT, 0, td);
347 mp->mnt_op = vfsp->vfc_vfsops;
349 vfsp->vfc_refcount++;
350 mp->mnt_stat.f_type = vfsp->vfc_typenum;
351 mp->mnt_flag |= vfsp->vfc_flags & MNT_VISFLAGMASK;
352 strncpy(mp->mnt_stat.f_fstypename, fstype, MFSNAMELEN);
353 mp->mnt_stat.f_fstypename[MFSNAMELEN - 1] = '\0';
354 mp->mnt_vnodecovered = vp;
355 mp->mnt_stat.f_owner = td->td_proc->p_ucred->cr_uid;
356 strncpy(mp->mnt_stat.f_mntonname, fspath, MNAMELEN);
357 mp->mnt_stat.f_mntonname[MNAMELEN - 1] = '\0';
358 mp->mnt_iosize_max = DFLTPHYS;
359 VOP_UNLOCK(vp, 0, td);
362 * Set the mount level flags.
364 if (fsflags & MNT_RDONLY)
365 mp->mnt_flag |= MNT_RDONLY;
366 else if (mp->mnt_flag & MNT_RDONLY)
367 mp->mnt_kern_flag |= MNTK_WANTRDWR;
368 mp->mnt_flag &=~ MNT_UPDATEMASK;
369 mp->mnt_flag |= fsflags & (MNT_UPDATEMASK | MNT_FORCE);
371 * Mount the filesystem.
372 * XXX The final recipients of VFS_MOUNT just overwrite the ndp they
373 * get. No freeing of cn_pnbuf.
375 error = VFS_MOUNT(mp, fspath, fsdata, &nd, td);
376 if (mp->mnt_flag & MNT_UPDATE) {
377 if (mp->mnt_kern_flag & MNTK_WANTRDWR)
378 mp->mnt_flag &= ~MNT_RDONLY;
380 (MNT_UPDATE | MNT_RELOAD | MNT_FORCE | MNT_SNAPSHOT);
381 mp->mnt_kern_flag &=~ MNTK_WANTRDWR;
384 mp->mnt_kern_flag = flag2;
386 if ((mp->mnt_flag & MNT_RDONLY) == 0) {
387 if (mp->mnt_syncer == NULL)
388 error = vfs_allocate_syncvnode(mp);
390 if (mp->mnt_syncer != NULL)
391 vrele(mp->mnt_syncer);
392 mp->mnt_syncer = NULL;
395 mtx_lock(&vp->v_interlock);
396 vp->v_flag &= ~VMOUNT;
397 mtx_unlock(&vp->v_interlock);
401 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
403 * Put the new filesystem on the mount list after root.
409 mtx_lock(&vp->v_interlock);
410 vp->v_flag &= ~VMOUNT;
411 vp->v_mountedhere = mp;
412 mtx_unlock(&vp->v_interlock);
413 mtx_lock(&mountlist_mtx);
414 TAILQ_INSERT_TAIL(&mountlist, mp, mnt_list);
415 mtx_unlock(&mountlist_mtx);
416 if (VFS_ROOT(mp, &newdp))
417 panic("mount: lost mount");
418 checkdirs(vp, newdp);
420 VOP_UNLOCK(vp, 0, td);
421 if ((mp->mnt_flag & MNT_RDONLY) == 0)
422 error = vfs_allocate_syncvnode(mp);
424 if ((error = VFS_START(mp, 0, td)) != 0)
427 mtx_lock(&vp->v_interlock);
428 vp->v_flag &= ~VMOUNT;
429 mtx_unlock(&vp->v_interlock);
430 mp->mnt_vfc->vfc_refcount--;
432 free((caddr_t)mp, M_MOUNT);
439 * Scan all active processes to see if any of them have a current
440 * or root directory of `olddp'. If so, replace them with the new
444 checkdirs(olddp, newdp)
445 struct vnode *olddp, *newdp;
447 struct filedesc *fdp;
450 if (olddp->v_usecount == 1)
452 sx_slock(&allproc_lock);
453 LIST_FOREACH(p, &allproc, p_list) {
458 if (fdp->fd_cdir == olddp) {
460 fdp->fd_cdir = newdp;
461 FILEDESC_UNLOCK(fdp);
465 if (fdp->fd_rdir == olddp) {
467 fdp->fd_rdir = newdp;
468 FILEDESC_UNLOCK(fdp);
471 FILEDESC_UNLOCK(fdp);
473 sx_sunlock(&allproc_lock);
474 if (rootvnode == olddp) {
482 * Unmount a file system.
484 * Note: unmount takes a path to the vnode mounted on as argument,
485 * not special file (as before).
487 #ifndef _SYS_SYSPROTO_H_
488 struct unmount_args {
497 register struct unmount_args /* {
498 syscallarg(char *) path;
499 syscallarg(int) flags;
502 register struct vnode *vp;
507 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
508 SCARG(uap, path), td);
509 if ((error = namei(&nd)) != 0)
512 NDFREE(&nd, NDF_ONLY_PNBUF);
516 * Only root, or the user that did the original mount is
517 * permitted to unmount this filesystem.
519 if (mp->mnt_stat.f_owner != td->td_proc->p_ucred->cr_uid) {
520 error = suser_td(td);
528 * Don't allow unmounting the root file system.
530 if (mp->mnt_flag & MNT_ROOTFS) {
536 * Must be the root of the filesystem
538 if ((vp->v_flag & VROOT) == 0) {
543 return (dounmount(mp, SCARG(uap, flags), td));
547 * Do the actual file system unmount.
550 dounmount(mp, flags, td)
555 struct vnode *coveredvp, *fsrootvp;
559 mtx_lock(&mountlist_mtx);
560 mp->mnt_kern_flag |= MNTK_UNMOUNT;
561 error = lockmgr(&mp->mnt_lock, LK_DRAIN | LK_INTERLOCK |
562 ((flags & MNT_FORCE) ? 0 : LK_NOWAIT), &mountlist_mtx, td);
564 mp->mnt_kern_flag &= ~MNTK_UNMOUNT;
565 if (mp->mnt_kern_flag & MNTK_MWAIT)
569 vn_start_write(NULL, &mp, V_WAIT);
571 if (mp->mnt_flag & MNT_EXPUBLIC)
572 vfs_setpublicfs(NULL, NULL, NULL);
574 vfs_msync(mp, MNT_WAIT);
575 async_flag = mp->mnt_flag & MNT_ASYNC;
576 mp->mnt_flag &=~ MNT_ASYNC;
577 cache_purgevfs(mp); /* remove cache entries for this file sys */
578 if (mp->mnt_syncer != NULL)
579 vrele(mp->mnt_syncer);
580 /* Move process cdir/rdir refs on fs root to underlying vnode. */
581 if (VFS_ROOT(mp, &fsrootvp) == 0) {
582 if (mp->mnt_vnodecovered != NULL)
583 checkdirs(fsrootvp, mp->mnt_vnodecovered);
584 if (fsrootvp == rootvnode) {
590 if (((mp->mnt_flag & MNT_RDONLY) ||
591 (error = VFS_SYNC(mp, MNT_WAIT, td->td_proc->p_ucred, td)) == 0) ||
592 (flags & MNT_FORCE)) {
593 error = VFS_UNMOUNT(mp, flags, td);
595 vn_finished_write(mp);
597 /* Undo cdir/rdir and rootvnode changes made above. */
598 if (VFS_ROOT(mp, &fsrootvp) == 0) {
599 if (mp->mnt_vnodecovered != NULL)
600 checkdirs(mp->mnt_vnodecovered, fsrootvp);
601 if (rootvnode == NULL) {
602 rootvnode = fsrootvp;
607 if ((mp->mnt_flag & MNT_RDONLY) == 0 && mp->mnt_syncer == NULL)
608 (void) vfs_allocate_syncvnode(mp);
609 mtx_lock(&mountlist_mtx);
610 mp->mnt_kern_flag &= ~MNTK_UNMOUNT;
611 mp->mnt_flag |= async_flag;
612 lockmgr(&mp->mnt_lock, LK_RELEASE | LK_INTERLOCK,
614 if (mp->mnt_kern_flag & MNTK_MWAIT)
618 mtx_lock(&mountlist_mtx);
619 TAILQ_REMOVE(&mountlist, mp, mnt_list);
620 if ((coveredvp = mp->mnt_vnodecovered) != NULL)
621 coveredvp->v_mountedhere = NULL;
622 mp->mnt_vfc->vfc_refcount--;
623 if (!TAILQ_EMPTY(&mp->mnt_nvnodelist))
624 panic("unmount: dangling vnode");
625 lockmgr(&mp->mnt_lock, LK_RELEASE | LK_INTERLOCK, &mountlist_mtx, td);
626 lockdestroy(&mp->mnt_lock);
627 if (coveredvp != NULL)
629 if (mp->mnt_kern_flag & MNTK_MWAIT)
631 free((caddr_t)mp, M_MOUNT);
636 * Sync each mounted filesystem.
638 #ifndef _SYS_SYSPROTO_H_
645 static int syncprt = 0;
646 SYSCTL_INT(_debug, OID_AUTO, syncprt, CTLFLAG_RW, &syncprt, 0, "");
653 struct sync_args *uap;
655 struct mount *mp, *nmp;
658 mtx_lock(&mountlist_mtx);
659 for (mp = TAILQ_FIRST(&mountlist); mp != NULL; mp = nmp) {
660 if (vfs_busy(mp, LK_NOWAIT, &mountlist_mtx, td)) {
661 nmp = TAILQ_NEXT(mp, mnt_list);
664 if ((mp->mnt_flag & MNT_RDONLY) == 0 &&
665 vn_start_write(NULL, &mp, V_NOWAIT) == 0) {
666 asyncflag = mp->mnt_flag & MNT_ASYNC;
667 mp->mnt_flag &= ~MNT_ASYNC;
668 vfs_msync(mp, MNT_NOWAIT);
669 VFS_SYNC(mp, MNT_NOWAIT,
670 ((td != NULL) ? td->td_proc->p_ucred : NOCRED), td);
671 mp->mnt_flag |= asyncflag;
672 vn_finished_write(mp);
674 mtx_lock(&mountlist_mtx);
675 nmp = TAILQ_NEXT(mp, mnt_list);
678 mtx_unlock(&mountlist_mtx);
681 * XXX don't call vfs_bufstats() yet because that routine
682 * was not imported in the Lite2 merge.
687 #endif /* DIAGNOSTIC */
692 /* XXX PRISON: could be per prison flag */
693 static int prison_quotas;
695 SYSCTL_INT(_kern_prison, OID_AUTO, quotas, CTLFLAG_RW, &prison_quotas, 0, "");
699 * Change filesystem quotas.
701 #ifndef _SYS_SYSPROTO_H_
702 struct quotactl_args {
713 register struct quotactl_args /* {
714 syscallarg(char *) path;
717 syscallarg(caddr_t) arg;
724 if (jailed(td->td_proc->p_ucred) && !prison_quotas)
726 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td);
727 if ((error = namei(&nd)) != 0)
729 NDFREE(&nd, NDF_ONLY_PNBUF);
730 error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH);
734 error = VFS_QUOTACTL(mp, SCARG(uap, cmd), SCARG(uap, uid),
735 SCARG(uap, arg), td);
736 vn_finished_write(mp);
741 * Get filesystem statistics.
743 #ifndef _SYS_SYSPROTO_H_
753 register struct statfs_args /* {
754 syscallarg(char *) path;
755 syscallarg(struct statfs *) buf;
758 register struct mount *mp;
759 register struct statfs *sp;
764 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td);
765 if ((error = namei(&nd)) != 0)
767 mp = nd.ni_vp->v_mount;
769 NDFREE(&nd, NDF_ONLY_PNBUF);
771 error = VFS_STATFS(mp, sp, td);
774 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
775 if (suser_xxx(td->td_proc->p_ucred, 0, 0)) {
776 bcopy((caddr_t)sp, (caddr_t)&sb, sizeof(sb));
777 sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0;
780 return (copyout((caddr_t)sp, (caddr_t)SCARG(uap, buf), sizeof(*sp)));
784 * Get filesystem statistics.
786 #ifndef _SYS_SYSPROTO_H_
787 struct fstatfs_args {
796 register struct fstatfs_args /* {
798 syscallarg(struct statfs *) buf;
803 register struct statfs *sp;
807 if ((error = getvnode(td->td_proc->p_fd, SCARG(uap, fd), &fp)) != 0)
809 mp = ((struct vnode *)fp->f_data)->v_mount;
814 error = VFS_STATFS(mp, sp, td);
817 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
818 if (suser_xxx(td->td_proc->p_ucred, 0, 0)) {
819 bcopy((caddr_t)sp, (caddr_t)&sb, sizeof(sb));
820 sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0;
823 return (copyout((caddr_t)sp, (caddr_t)SCARG(uap, buf), sizeof(*sp)));
827 * Get statistics on all filesystems.
829 #ifndef _SYS_SYSPROTO_H_
830 struct getfsstat_args {
839 register struct getfsstat_args /* {
840 syscallarg(struct statfs *) buf;
841 syscallarg(long) bufsize;
842 syscallarg(int) flags;
845 register struct mount *mp, *nmp;
846 register struct statfs *sp;
848 long count, maxcount, error;
850 maxcount = SCARG(uap, bufsize) / sizeof(struct statfs);
851 sfsp = (caddr_t)SCARG(uap, buf);
853 mtx_lock(&mountlist_mtx);
854 for (mp = TAILQ_FIRST(&mountlist); mp != NULL; mp = nmp) {
855 if (vfs_busy(mp, LK_NOWAIT, &mountlist_mtx, td)) {
856 nmp = TAILQ_NEXT(mp, mnt_list);
859 if (sfsp && count < maxcount) {
862 * If MNT_NOWAIT or MNT_LAZY is specified, do not
863 * refresh the fsstat cache. MNT_NOWAIT or MNT_LAZY
864 * overrides MNT_WAIT.
866 if (((SCARG(uap, flags) & (MNT_LAZY|MNT_NOWAIT)) == 0 ||
867 (SCARG(uap, flags) & MNT_WAIT)) &&
868 (error = VFS_STATFS(mp, sp, td))) {
869 mtx_lock(&mountlist_mtx);
870 nmp = TAILQ_NEXT(mp, mnt_list);
874 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
875 error = copyout((caddr_t)sp, sfsp, sizeof(*sp));
883 mtx_lock(&mountlist_mtx);
884 nmp = TAILQ_NEXT(mp, mnt_list);
887 mtx_unlock(&mountlist_mtx);
888 if (sfsp && count > maxcount)
889 td->td_retval[0] = maxcount;
891 td->td_retval[0] = count;
896 * Change current working directory to a given file descriptor.
898 #ifndef _SYS_SYSPROTO_H_
907 struct fchdir_args /* {
911 register struct filedesc *fdp = td->td_proc->p_fd;
912 struct vnode *vp, *tdp, *vpold;
917 if ((error = getvnode(fdp, SCARG(uap, fd), &fp)) != 0)
919 vp = (struct vnode *)fp->f_data;
922 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
923 if (vp->v_type != VDIR)
926 error = VOP_ACCESS(vp, VEXEC, td->td_proc->p_ucred, td);
927 while (!error && (mp = vp->v_mountedhere) != NULL) {
928 if (vfs_busy(mp, 0, 0, td))
930 error = VFS_ROOT(mp, &tdp);
941 VOP_UNLOCK(vp, 0, td);
943 vpold = fdp->fd_cdir;
945 FILEDESC_UNLOCK(fdp);
951 * Change current working directory (``.'').
953 #ifndef _SYS_SYSPROTO_H_
962 struct chdir_args /* {
963 syscallarg(char *) path;
966 register struct filedesc *fdp = td->td_proc->p_fd;
971 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
972 SCARG(uap, path), td);
973 if ((error = change_dir(&nd, td)) != 0)
975 NDFREE(&nd, NDF_ONLY_PNBUF);
978 fdp->fd_cdir = nd.ni_vp;
979 FILEDESC_UNLOCK(fdp);
985 * Helper function for raised chroot(2) security function: Refuse if
986 * any filedescriptors are open directories.
989 chroot_refuse_vdir_fds(fdp)
990 struct filedesc *fdp;
997 for (fd = 0; fd < fdp->fd_nfiles ; fd++) {
998 fp = fget_locked(fdp, fd);
1001 if (fp->f_type == DTYPE_VNODE) {
1002 vp = (struct vnode *)fp->f_data;
1003 if (vp->v_type == VDIR) {
1004 FILEDESC_UNLOCK(fdp);
1009 FILEDESC_UNLOCK(fdp);
1014 * This sysctl determines if we will allow a process to chroot(2) if it
1015 * has a directory open:
1016 * 0: disallowed for all processes.
1017 * 1: allowed for processes that were not already chroot(2)'ed.
1018 * 2: allowed for all processes.
1021 static int chroot_allow_open_directories = 1;
1023 SYSCTL_INT(_kern, OID_AUTO, chroot_allow_open_directories, CTLFLAG_RW,
1024 &chroot_allow_open_directories, 0, "");
1027 * Change notion of root (``/'') directory.
1029 #ifndef _SYS_SYSPROTO_H_
1030 struct chroot_args {
1038 struct chroot_args /* {
1039 syscallarg(char *) path;
1042 register struct filedesc *fdp = td->td_proc->p_fd;
1044 struct nameidata nd;
1047 error = suser_xxx(0, td->td_proc, PRISON_ROOT);
1051 if (chroot_allow_open_directories == 0 ||
1052 (chroot_allow_open_directories == 1 && fdp->fd_rdir != rootvnode)) {
1053 FILEDESC_UNLOCK(fdp);
1054 error = chroot_refuse_vdir_fds(fdp);
1056 FILEDESC_UNLOCK(fdp);
1059 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
1060 SCARG(uap, path), td);
1061 if ((error = change_dir(&nd, td)) != 0)
1063 NDFREE(&nd, NDF_ONLY_PNBUF);
1066 fdp->fd_rdir = nd.ni_vp;
1067 if (!fdp->fd_jdir) {
1068 fdp->fd_jdir = nd.ni_vp;
1071 FILEDESC_UNLOCK(fdp);
1077 * Common routine for chroot and chdir.
1081 register struct nameidata *ndp;
1091 if (vp->v_type != VDIR)
1094 error = VOP_ACCESS(vp, VEXEC, td->td_proc->p_ucred, td);
1098 VOP_UNLOCK(vp, 0, td);
1103 * Check permissions, allocate an open file structure,
1104 * and call the device open routine if any.
1106 #ifndef _SYS_SYSPROTO_H_
1116 register struct open_args /* {
1117 syscallarg(char *) path;
1118 syscallarg(int) flags;
1119 syscallarg(int) mode;
1122 struct proc *p = td->td_proc;
1123 struct filedesc *fdp = p->p_fd;
1128 int cmode, flags, oflags;
1130 int type, indx, error;
1132 struct nameidata nd;
1134 oflags = SCARG(uap, flags);
1135 if ((oflags & O_ACCMODE) == O_ACCMODE)
1137 flags = FFLAGS(oflags);
1138 error = falloc(td, &nfp, &indx);
1143 cmode = ((SCARG(uap, mode) &~ fdp->fd_cmask) & ALLPERMS) &~ S_ISTXT;
1144 FILEDESC_UNLOCK(fdp);
1145 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td);
1146 td->td_dupfd = -indx - 1; /* XXX check for fdopen */
1148 * Bump the ref count to prevent another process from closing
1149 * the descriptor while we are blocked in vn_open()
1152 error = vn_open(&nd, &flags, cmode);
1155 * release our own reference
1160 * handle special fdopen() case. bleh. dupfdopen() is
1161 * responsible for dropping the old contents of ofiles[indx]
1164 if ((error == ENODEV || error == ENXIO) &&
1165 td->td_dupfd >= 0 && /* XXX from fdopen */
1167 dupfdopen(td, fdp, indx, td->td_dupfd, flags, error)) == 0) {
1168 td->td_retval[0] = indx;
1172 * Clean up the descriptor, but only if another thread hadn't
1173 * replaced or closed it.
1176 if (fdp->fd_ofiles[indx] == fp) {
1177 fdp->fd_ofiles[indx] = NULL;
1178 FILEDESC_UNLOCK(fdp);
1181 FILEDESC_UNLOCK(fdp);
1183 if (error == ERESTART)
1188 NDFREE(&nd, NDF_ONLY_PNBUF);
1192 * There should be 2 references on the file, one from the descriptor
1193 * table, and one for us.
1195 * Handle the case where someone closed the file (via its file
1196 * descriptor) while we were blocked. The end result should look
1197 * like opening the file succeeded but it was immediately closed.
1201 if (fp->f_count == 1) {
1202 KASSERT(fdp->fd_ofiles[indx] != fp,
1203 ("Open file descriptor lost all refs"));
1204 FILEDESC_UNLOCK(fdp);
1206 VOP_UNLOCK(vp, 0, td);
1207 vn_close(vp, flags & FMASK, fp->f_cred, td);
1209 td->td_retval[0] = indx;
1213 fp->f_data = (caddr_t)vp;
1214 fp->f_flag = flags & FMASK;
1216 fp->f_type = (vp->v_type == VFIFO ? DTYPE_FIFO : DTYPE_VNODE);
1217 FILEDESC_UNLOCK(fdp);
1219 VOP_UNLOCK(vp, 0, td);
1220 if (flags & (O_EXLOCK | O_SHLOCK)) {
1221 lf.l_whence = SEEK_SET;
1224 if (flags & O_EXLOCK)
1225 lf.l_type = F_WRLCK;
1227 lf.l_type = F_RDLCK;
1229 if ((flags & FNONBLOCK) == 0)
1231 if ((error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type)) != 0)
1233 fp->f_flag |= FHASLOCK;
1235 if (flags & O_TRUNC) {
1236 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
1238 VOP_LEASE(vp, td, p->p_ucred, LEASE_WRITE);
1241 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
1242 error = VOP_SETATTR(vp, &vat, p->p_ucred, td);
1243 VOP_UNLOCK(vp, 0, td);
1244 vn_finished_write(mp);
1248 /* assert that vn_open created a backing object if one is needed */
1249 KASSERT(!vn_canvmio(vp) || VOP_GETVOBJECT(vp, NULL) == 0,
1250 ("open: vmio vnode has no backing object after vn_open"));
1252 * Release our private reference, leaving the one associated with
1253 * the descriptor table intact.
1256 td->td_retval[0] = indx;
1260 if (fdp->fd_ofiles[indx] == fp) {
1261 fdp->fd_ofiles[indx] = NULL;
1262 FILEDESC_UNLOCK(fdp);
1265 FILEDESC_UNLOCK(fdp);
1273 #ifndef _SYS_SYSPROTO_H_
1274 struct ocreat_args {
1282 register struct ocreat_args /* {
1283 syscallarg(char *) path;
1284 syscallarg(int) mode;
1287 struct open_args /* {
1288 syscallarg(char *) path;
1289 syscallarg(int) flags;
1290 syscallarg(int) mode;
1293 SCARG(&nuap, path) = SCARG(uap, path);
1294 SCARG(&nuap, mode) = SCARG(uap, mode);
1295 SCARG(&nuap, flags) = O_WRONLY | O_CREAT | O_TRUNC;
1296 return (open(td, &nuap));
1298 #endif /* COMPAT_43 */
1301 * Create a special file.
1303 #ifndef _SYS_SYSPROTO_H_
1314 register struct mknod_args /* {
1315 syscallarg(char *) path;
1316 syscallarg(int) mode;
1317 syscallarg(int) dev;
1325 struct nameidata nd;
1327 switch (SCARG(uap, mode) & S_IFMT) {
1330 error = suser_td(td);
1333 error = suser_xxx(0, td->td_proc, PRISON_ROOT);
1340 NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), td);
1341 if ((error = namei(&nd)) != 0)
1349 FILEDESC_LOCK(td->td_proc->p_fd);
1350 vattr.va_mode = (SCARG(uap, mode) & ALLPERMS) &~ td->td_proc->p_fd->fd_cmask;
1351 FILEDESC_UNLOCK(td->td_proc->p_fd);
1352 vattr.va_rdev = SCARG(uap, dev);
1355 switch (SCARG(uap, mode) & S_IFMT) {
1356 case S_IFMT: /* used by badsect to flag bad sectors */
1357 vattr.va_type = VBAD;
1360 vattr.va_type = VCHR;
1363 vattr.va_type = VBLK;
1373 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) {
1374 NDFREE(&nd, NDF_ONLY_PNBUF);
1376 if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0)
1381 VOP_LEASE(nd.ni_dvp, td, td->td_proc->p_ucred, LEASE_WRITE);
1383 error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, CREATE);
1385 error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp,
1386 &nd.ni_cnd, &vattr);
1391 NDFREE(&nd, NDF_ONLY_PNBUF);
1393 vn_finished_write(mp);
1394 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "mknod");
1395 ASSERT_VOP_UNLOCKED(nd.ni_vp, "mknod");
1400 * Create a named pipe.
1402 #ifndef _SYS_SYSPROTO_H_
1403 struct mkfifo_args {
1412 register struct mkfifo_args /* {
1413 syscallarg(char *) path;
1414 syscallarg(int) mode;
1420 struct nameidata nd;
1424 NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), td);
1425 if ((error = namei(&nd)) != 0)
1427 if (nd.ni_vp != NULL) {
1428 NDFREE(&nd, NDF_ONLY_PNBUF);
1433 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) {
1434 NDFREE(&nd, NDF_ONLY_PNBUF);
1436 if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0)
1441 vattr.va_type = VFIFO;
1442 FILEDESC_LOCK(td->td_proc->p_fd);
1443 vattr.va_mode = (SCARG(uap, mode) & ALLPERMS) &~ td->td_proc->p_fd->fd_cmask;
1444 FILEDESC_UNLOCK(td->td_proc->p_fd);
1445 VOP_LEASE(nd.ni_dvp, td, td->td_proc->p_ucred, LEASE_WRITE);
1446 error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
1449 NDFREE(&nd, NDF_ONLY_PNBUF);
1451 vn_finished_write(mp);
1456 * Make a hard file link.
1458 #ifndef _SYS_SYSPROTO_H_
1468 register struct link_args /* {
1469 syscallarg(char *) path;
1470 syscallarg(char *) link;
1475 struct nameidata nd;
1479 NDINIT(&nd, LOOKUP, FOLLOW|NOOBJ, UIO_USERSPACE, SCARG(uap, path), td);
1480 if ((error = namei(&nd)) != 0)
1482 NDFREE(&nd, NDF_ONLY_PNBUF);
1484 if (vp->v_type == VDIR) {
1486 return (EPERM); /* POSIX */
1488 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) {
1492 NDINIT(&nd, CREATE, LOCKPARENT|NOOBJ, UIO_USERSPACE, SCARG(uap, link), td);
1493 if ((error = namei(&nd)) == 0) {
1494 if (nd.ni_vp != NULL) {
1498 VOP_LEASE(nd.ni_dvp, td, td->td_proc->p_ucred, LEASE_WRITE);
1499 VOP_LEASE(vp, td, td->td_proc->p_ucred, LEASE_WRITE);
1500 error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd);
1502 NDFREE(&nd, NDF_ONLY_PNBUF);
1506 vn_finished_write(mp);
1507 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "link");
1508 ASSERT_VOP_UNLOCKED(nd.ni_vp, "link");
1513 * Make a symbolic link.
1515 #ifndef _SYS_SYSPROTO_H_
1516 struct symlink_args {
1525 register struct symlink_args /* {
1526 syscallarg(char *) path;
1527 syscallarg(char *) link;
1534 struct nameidata nd;
1536 path = zalloc(namei_zone);
1537 if ((error = copyinstr(SCARG(uap, path), path, MAXPATHLEN, NULL)) != 0)
1541 NDINIT(&nd, CREATE, LOCKPARENT|NOOBJ, UIO_USERSPACE, SCARG(uap, link), td);
1542 if ((error = namei(&nd)) != 0)
1545 NDFREE(&nd, NDF_ONLY_PNBUF);
1551 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) {
1552 NDFREE(&nd, NDF_ONLY_PNBUF);
1554 if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0)
1559 FILEDESC_LOCK(td->td_proc->p_fd);
1560 vattr.va_mode = ACCESSPERMS &~ td->td_proc->p_fd->fd_cmask;
1561 FILEDESC_UNLOCK(td->td_proc->p_fd);
1562 VOP_LEASE(nd.ni_dvp, td, td->td_proc->p_ucred, LEASE_WRITE);
1563 error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr, path);
1564 NDFREE(&nd, NDF_ONLY_PNBUF);
1568 vn_finished_write(mp);
1569 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "symlink");
1570 ASSERT_VOP_UNLOCKED(nd.ni_vp, "symlink");
1572 zfree(namei_zone, path);
1577 * Delete a whiteout from the filesystem.
1583 register struct undelete_args /* {
1584 syscallarg(char *) path;
1589 struct nameidata nd;
1593 NDINIT(&nd, DELETE, LOCKPARENT|DOWHITEOUT, UIO_USERSPACE,
1594 SCARG(uap, path), td);
1599 if (nd.ni_vp != NULLVP || !(nd.ni_cnd.cn_flags & ISWHITEOUT)) {
1600 NDFREE(&nd, NDF_ONLY_PNBUF);
1606 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) {
1607 NDFREE(&nd, NDF_ONLY_PNBUF);
1609 if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0)
1613 VOP_LEASE(nd.ni_dvp, td, td->td_proc->p_ucred, LEASE_WRITE);
1614 error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, DELETE);
1615 NDFREE(&nd, NDF_ONLY_PNBUF);
1617 vn_finished_write(mp);
1618 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "undelete");
1619 ASSERT_VOP_UNLOCKED(nd.ni_vp, "undelete");
1624 * Delete a name from the filesystem.
1626 #ifndef _SYS_SYSPROTO_H_
1627 struct unlink_args {
1635 struct unlink_args /* {
1636 syscallarg(char *) path;
1642 struct nameidata nd;
1646 NDINIT(&nd, DELETE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), td);
1647 if ((error = namei(&nd)) != 0)
1650 if (vp->v_type == VDIR)
1651 error = EPERM; /* POSIX */
1654 * The root of a mounted filesystem cannot be deleted.
1656 * XXX: can this only be a VDIR case?
1658 if (vp->v_flag & VROOT)
1661 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) {
1662 NDFREE(&nd, NDF_ONLY_PNBUF);
1665 if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0)
1669 VOP_LEASE(vp, td, td->td_proc->p_ucred, LEASE_WRITE);
1670 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
1672 VOP_LEASE(nd.ni_dvp, td, td->td_proc->p_ucred, LEASE_WRITE);
1673 error = VOP_REMOVE(nd.ni_dvp, vp, &nd.ni_cnd);
1675 NDFREE(&nd, NDF_ONLY_PNBUF);
1678 vn_finished_write(mp);
1679 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "unlink");
1680 ASSERT_VOP_UNLOCKED(nd.ni_vp, "unlink");
1685 * Reposition read/write file offset.
1687 #ifndef _SYS_SYSPROTO_H_
1698 register struct lseek_args /* {
1700 syscallarg(int) pad;
1701 syscallarg(off_t) offset;
1702 syscallarg(int) whence;
1705 struct ucred *cred = td->td_proc->p_ucred;
1712 if ((error = fget(td, uap->fd, &fp)) != 0)
1714 if (fp->f_type != DTYPE_VNODE) {
1718 vp = (struct vnode *)fp->f_data;
1719 noneg = (vp->v_type != VCHR);
1720 offset = SCARG(uap, offset);
1721 switch (SCARG(uap, whence)) {
1724 (fp->f_offset < 0 ||
1725 (offset > 0 && fp->f_offset > OFF_MAX - offset)))
1727 offset += fp->f_offset;
1730 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
1731 error = VOP_GETATTR(vp, &vattr, cred, td);
1732 VOP_UNLOCK(vp, 0, td);
1736 (vattr.va_size > OFF_MAX ||
1737 (offset > 0 && vattr.va_size > OFF_MAX - offset)))
1739 offset += vattr.va_size;
1747 if (noneg && offset < 0)
1749 fp->f_offset = offset;
1750 *(off_t *)(td->td_retval) = fp->f_offset;
1755 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
1757 * Reposition read/write file offset.
1759 #ifndef _SYS_SYSPROTO_H_
1760 struct olseek_args {
1769 register struct olseek_args /* {
1771 syscallarg(long) offset;
1772 syscallarg(int) whence;
1775 struct lseek_args /* {
1777 syscallarg(int) pad;
1778 syscallarg(off_t) offset;
1779 syscallarg(int) whence;
1783 SCARG(&nuap, fd) = SCARG(uap, fd);
1784 SCARG(&nuap, offset) = SCARG(uap, offset);
1785 SCARG(&nuap, whence) = SCARG(uap, whence);
1786 error = lseek(td, &nuap);
1789 #endif /* COMPAT_43 */
1792 * Check access permissions using passed credentials.
1795 vn_access(vp, user_flags, cred, td)
1803 /* Flags == 0 means only check for existence. */
1807 if (user_flags & R_OK)
1809 if (user_flags & W_OK)
1811 if (user_flags & X_OK)
1813 if ((flags & VWRITE) == 0 || (error = vn_writechk(vp)) == 0)
1814 error = VOP_ACCESS(vp, flags, cred, td);
1820 * Check access permissions using "real" credentials.
1822 #ifndef _SYS_SYSPROTO_H_
1823 struct access_args {
1831 register struct access_args /* {
1832 syscallarg(char *) path;
1833 syscallarg(int) flags;
1836 struct ucred *cred, *tmpcred;
1837 register struct vnode *vp;
1839 struct nameidata nd;
1841 cred = td->td_proc->p_ucred;
1843 * Create and modify a temporary credential instead of one that
1844 * is potentially shared. This could also mess up socket
1845 * buffer accounting which can run in an interrupt context.
1847 * XXX - Depending on how "threads" are finally implemented, it
1848 * may be better to explicitly pass the credential to namei()
1849 * rather than to modify the potentially shared process structure.
1851 tmpcred = crdup(cred);
1852 tmpcred->cr_uid = cred->cr_ruid;
1853 tmpcred->cr_groups[0] = cred->cr_rgid;
1854 td->td_proc->p_ucred = tmpcred;
1855 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
1856 SCARG(uap, path), td);
1857 if ((error = namei(&nd)) != 0)
1861 error = vn_access(vp, SCARG(uap, flags), tmpcred, td);
1862 NDFREE(&nd, NDF_ONLY_PNBUF);
1865 td->td_proc->p_ucred = cred;
1871 * Check access permissions using "effective" credentials.
1873 #ifndef _SYS_SYSPROTO_H_
1874 struct eaccess_args {
1882 register struct eaccess_args /* {
1883 syscallarg(char *) path;
1884 syscallarg(int) flags;
1887 struct nameidata nd;
1891 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
1892 SCARG(uap, path), td);
1893 if ((error = namei(&nd)) != 0)
1897 error = vn_access(vp, SCARG(uap, flags), td->td_proc->p_ucred, td);
1898 NDFREE(&nd, NDF_ONLY_PNBUF);
1903 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
1905 * Get file status; this version follows links.
1907 #ifndef _SYS_SYSPROTO_H_
1917 register struct ostat_args /* {
1918 syscallarg(char *) path;
1919 syscallarg(struct ostat *) ub;
1925 struct nameidata nd;
1927 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
1928 SCARG(uap, path), td);
1929 if ((error = namei(&nd)) != 0)
1931 NDFREE(&nd, NDF_ONLY_PNBUF);
1932 error = vn_stat(nd.ni_vp, &sb, td);
1937 error = copyout((caddr_t)&osb, (caddr_t)SCARG(uap, ub), sizeof (osb));
1942 * Get file status; this version does not follow links.
1944 #ifndef _SYS_SYSPROTO_H_
1945 struct olstat_args {
1954 register struct olstat_args /* {
1955 syscallarg(char *) path;
1956 syscallarg(struct ostat *) ub;
1963 struct nameidata nd;
1965 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
1966 SCARG(uap, path), td);
1967 if ((error = namei(&nd)) != 0)
1970 error = vn_stat(vp, &sb, td);
1971 NDFREE(&nd, NDF_ONLY_PNBUF);
1976 error = copyout((caddr_t)&osb, (caddr_t)SCARG(uap, ub), sizeof (osb));
1981 * Convert from an old to a new stat structure.
1989 ost->st_dev = st->st_dev;
1990 ost->st_ino = st->st_ino;
1991 ost->st_mode = st->st_mode;
1992 ost->st_nlink = st->st_nlink;
1993 ost->st_uid = st->st_uid;
1994 ost->st_gid = st->st_gid;
1995 ost->st_rdev = st->st_rdev;
1996 if (st->st_size < (quad_t)1 << 32)
1997 ost->st_size = st->st_size;
2000 ost->st_atime = st->st_atime;
2001 ost->st_mtime = st->st_mtime;
2002 ost->st_ctime = st->st_ctime;
2003 ost->st_blksize = st->st_blksize;
2004 ost->st_blocks = st->st_blocks;
2005 ost->st_flags = st->st_flags;
2006 ost->st_gen = st->st_gen;
2008 #endif /* COMPAT_43 || COMPAT_SUNOS */
2011 * Get file status; this version follows links.
2013 #ifndef _SYS_SYSPROTO_H_
2023 register struct stat_args /* {
2024 syscallarg(char *) path;
2025 syscallarg(struct stat *) ub;
2030 struct nameidata nd;
2032 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
2033 SCARG(uap, path), td);
2034 if ((error = namei(&nd)) != 0)
2036 error = vn_stat(nd.ni_vp, &sb, td);
2037 NDFREE(&nd, NDF_ONLY_PNBUF);
2041 error = copyout((caddr_t)&sb, (caddr_t)SCARG(uap, ub), sizeof (sb));
2046 * Get file status; this version does not follow links.
2048 #ifndef _SYS_SYSPROTO_H_
2058 register struct lstat_args /* {
2059 syscallarg(char *) path;
2060 syscallarg(struct stat *) ub;
2066 struct nameidata nd;
2068 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
2069 SCARG(uap, path), td);
2070 if ((error = namei(&nd)) != 0)
2073 error = vn_stat(vp, &sb, td);
2074 NDFREE(&nd, NDF_ONLY_PNBUF);
2078 error = copyout((caddr_t)&sb, (caddr_t)SCARG(uap, ub), sizeof (sb));
2083 * Implementation of the NetBSD stat() function.
2084 * XXX This should probably be collapsed with the FreeBSD version,
2085 * as the differences are only due to vn_stat() clearing spares at
2086 * the end of the structures. vn_stat could be split to avoid this,
2087 * and thus collapse the following to close to zero code.
2094 nsb->st_dev = sb->st_dev;
2095 nsb->st_ino = sb->st_ino;
2096 nsb->st_mode = sb->st_mode;
2097 nsb->st_nlink = sb->st_nlink;
2098 nsb->st_uid = sb->st_uid;
2099 nsb->st_gid = sb->st_gid;
2100 nsb->st_rdev = sb->st_rdev;
2101 nsb->st_atimespec = sb->st_atimespec;
2102 nsb->st_mtimespec = sb->st_mtimespec;
2103 nsb->st_ctimespec = sb->st_ctimespec;
2104 nsb->st_size = sb->st_size;
2105 nsb->st_blocks = sb->st_blocks;
2106 nsb->st_blksize = sb->st_blksize;
2107 nsb->st_flags = sb->st_flags;
2108 nsb->st_gen = sb->st_gen;
2109 nsb->st_qspare[0] = sb->st_qspare[0];
2110 nsb->st_qspare[1] = sb->st_qspare[1];
2113 #ifndef _SYS_SYSPROTO_H_
2123 register struct nstat_args /* {
2124 syscallarg(char *) path;
2125 syscallarg(struct nstat *) ub;
2131 struct nameidata nd;
2133 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
2134 SCARG(uap, path), td);
2135 if ((error = namei(&nd)) != 0)
2137 NDFREE(&nd, NDF_ONLY_PNBUF);
2138 error = vn_stat(nd.ni_vp, &sb, td);
2142 cvtnstat(&sb, &nsb);
2143 error = copyout((caddr_t)&nsb, (caddr_t)SCARG(uap, ub), sizeof (nsb));
2148 * NetBSD lstat. Get file status; this version does not follow links.
2150 #ifndef _SYS_SYSPROTO_H_
2160 register struct nlstat_args /* {
2161 syscallarg(char *) path;
2162 syscallarg(struct nstat *) ub;
2169 struct nameidata nd;
2171 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
2172 SCARG(uap, path), td);
2173 if ((error = namei(&nd)) != 0)
2176 NDFREE(&nd, NDF_ONLY_PNBUF);
2177 error = vn_stat(vp, &sb, td);
2181 cvtnstat(&sb, &nsb);
2182 error = copyout((caddr_t)&nsb, (caddr_t)SCARG(uap, ub), sizeof (nsb));
2187 * Get configurable pathname variables.
2189 #ifndef _SYS_SYSPROTO_H_
2190 struct pathconf_args {
2199 register struct pathconf_args /* {
2200 syscallarg(char *) path;
2201 syscallarg(int) name;
2205 struct nameidata nd;
2207 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
2208 SCARG(uap, path), td);
2209 if ((error = namei(&nd)) != 0)
2211 NDFREE(&nd, NDF_ONLY_PNBUF);
2212 error = VOP_PATHCONF(nd.ni_vp, SCARG(uap, name), td->td_retval);
2218 * Return target name of a symbolic link.
2220 #ifndef _SYS_SYSPROTO_H_
2221 struct readlink_args {
2231 register struct readlink_args /* {
2232 syscallarg(char *) path;
2233 syscallarg(char *) buf;
2234 syscallarg(int) count;
2237 register struct vnode *vp;
2241 struct nameidata nd;
2243 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
2244 SCARG(uap, path), td);
2245 if ((error = namei(&nd)) != 0)
2247 NDFREE(&nd, NDF_ONLY_PNBUF);
2249 if (vp->v_type != VLNK)
2252 aiov.iov_base = SCARG(uap, buf);
2253 aiov.iov_len = SCARG(uap, count);
2254 auio.uio_iov = &aiov;
2255 auio.uio_iovcnt = 1;
2256 auio.uio_offset = 0;
2257 auio.uio_rw = UIO_READ;
2258 auio.uio_segflg = UIO_USERSPACE;
2260 auio.uio_resid = SCARG(uap, count);
2261 error = VOP_READLINK(vp, &auio, td->td_proc->p_ucred);
2264 td->td_retval[0] = SCARG(uap, count) - auio.uio_resid;
2269 * Common implementation code for chflags() and fchflags().
2272 setfflags(td, vp, flags)
2282 * Prevent non-root users from setting flags on devices. When
2283 * a device is reused, users can retain ownership of the device
2284 * if they are allowed to set flags and programs assume that
2285 * chown can't fail when done as root.
2287 if (vp->v_type == VCHR || vp->v_type == VBLK) {
2288 error = suser_xxx(td->td_proc->p_ucred, td->td_proc,
2294 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
2296 VOP_LEASE(vp, td, td->td_proc->p_ucred, LEASE_WRITE);
2297 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
2299 vattr.va_flags = flags;
2300 error = VOP_SETATTR(vp, &vattr, td->td_proc->p_ucred, td);
2301 VOP_UNLOCK(vp, 0, td);
2302 vn_finished_write(mp);
2307 * Change flags of a file given a path name.
2309 #ifndef _SYS_SYSPROTO_H_
2310 struct chflags_args {
2319 register struct chflags_args /* {
2320 syscallarg(char *) path;
2321 syscallarg(int) flags;
2325 struct nameidata nd;
2327 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td);
2328 if ((error = namei(&nd)) != 0)
2330 NDFREE(&nd, NDF_ONLY_PNBUF);
2331 error = setfflags(td, nd.ni_vp, SCARG(uap, flags));
2337 * Change flags of a file given a file descriptor.
2339 #ifndef _SYS_SYSPROTO_H_
2340 struct fchflags_args {
2349 register struct fchflags_args /* {
2351 syscallarg(int) flags;
2357 if ((error = getvnode(td->td_proc->p_fd, SCARG(uap, fd), &fp)) != 0)
2359 error = setfflags(td, (struct vnode *) fp->f_data, SCARG(uap, flags));
2365 * Common implementation code for chmod(), lchmod() and fchmod().
2368 setfmode(td, vp, mode)
2377 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
2379 VOP_LEASE(vp, td, td->td_proc->p_ucred, LEASE_WRITE);
2380 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
2382 vattr.va_mode = mode & ALLPERMS;
2383 error = VOP_SETATTR(vp, &vattr, td->td_proc->p_ucred, td);
2384 VOP_UNLOCK(vp, 0, td);
2385 vn_finished_write(mp);
2390 * Change mode of a file given path name.
2392 #ifndef _SYS_SYSPROTO_H_
2402 register struct chmod_args /* {
2403 syscallarg(char *) path;
2404 syscallarg(int) mode;
2408 struct nameidata nd;
2410 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td);
2411 if ((error = namei(&nd)) != 0)
2413 NDFREE(&nd, NDF_ONLY_PNBUF);
2414 error = setfmode(td, nd.ni_vp, SCARG(uap, mode));
2420 * Change mode of a file given path name (don't follow links.)
2422 #ifndef _SYS_SYSPROTO_H_
2423 struct lchmod_args {
2432 register struct lchmod_args /* {
2433 syscallarg(char *) path;
2434 syscallarg(int) mode;
2438 struct nameidata nd;
2440 NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), td);
2441 if ((error = namei(&nd)) != 0)
2443 NDFREE(&nd, NDF_ONLY_PNBUF);
2444 error = setfmode(td, nd.ni_vp, SCARG(uap, mode));
2450 * Change mode of a file given a file descriptor.
2452 #ifndef _SYS_SYSPROTO_H_
2453 struct fchmod_args {
2462 register struct fchmod_args /* {
2464 syscallarg(int) mode;
2471 if ((error = getvnode(td->td_proc->p_fd, SCARG(uap, fd), &fp)) != 0)
2473 vp = (struct vnode *)fp->f_data;
2474 error = setfmode(td, (struct vnode *)fp->f_data, SCARG(uap, mode));
2480 * Common implementation for chown(), lchown(), and fchown()
2483 setfown(td, vp, uid, gid)
2493 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
2495 VOP_LEASE(vp, td, td->td_proc->p_ucred, LEASE_WRITE);
2496 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
2500 error = VOP_SETATTR(vp, &vattr, td->td_proc->p_ucred, td);
2501 VOP_UNLOCK(vp, 0, td);
2502 vn_finished_write(mp);
2507 * Set ownership given a path name.
2509 #ifndef _SYS_SYSPROTO_H_
2520 register struct chown_args /* {
2521 syscallarg(char *) path;
2522 syscallarg(int) uid;
2523 syscallarg(int) gid;
2527 struct nameidata nd;
2529 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td);
2530 if ((error = namei(&nd)) != 0)
2532 NDFREE(&nd, NDF_ONLY_PNBUF);
2533 error = setfown(td, nd.ni_vp, SCARG(uap, uid), SCARG(uap, gid));
2539 * Set ownership given a path name, do not cross symlinks.
2541 #ifndef _SYS_SYSPROTO_H_
2542 struct lchown_args {
2552 register struct lchown_args /* {
2553 syscallarg(char *) path;
2554 syscallarg(int) uid;
2555 syscallarg(int) gid;
2559 struct nameidata nd;
2561 NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), td);
2562 if ((error = namei(&nd)) != 0)
2564 NDFREE(&nd, NDF_ONLY_PNBUF);
2565 error = setfown(td, nd.ni_vp, SCARG(uap, uid), SCARG(uap, gid));
2571 * Set ownership given a file descriptor.
2573 #ifndef _SYS_SYSPROTO_H_
2574 struct fchown_args {
2584 register struct fchown_args /* {
2586 syscallarg(int) uid;
2587 syscallarg(int) gid;
2594 if ((error = getvnode(td->td_proc->p_fd, SCARG(uap, fd), &fp)) != 0)
2596 vp = (struct vnode *)fp->f_data;
2597 error = setfown(td, (struct vnode *)fp->f_data,
2598 SCARG(uap, uid), SCARG(uap, gid));
2604 * Common implementation code for utimes(), lutimes(), and futimes().
2607 getutimes(usrtvp, tsp)
2608 const struct timeval *usrtvp;
2609 struct timespec *tsp;
2611 struct timeval tv[2];
2614 if (usrtvp == NULL) {
2616 TIMEVAL_TO_TIMESPEC(&tv[0], &tsp[0]);
2619 if ((error = copyin(usrtvp, tv, sizeof (tv))) != 0)
2621 TIMEVAL_TO_TIMESPEC(&tv[0], &tsp[0]);
2622 TIMEVAL_TO_TIMESPEC(&tv[1], &tsp[1]);
2628 * Common implementation code for utimes(), lutimes(), and futimes().
2631 setutimes(td, vp, ts, nullflag)
2634 const struct timespec *ts;
2641 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
2643 VOP_LEASE(vp, td, td->td_proc->p_ucred, LEASE_WRITE);
2644 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
2646 vattr.va_atime = ts[0];
2647 vattr.va_mtime = ts[1];
2649 vattr.va_vaflags |= VA_UTIMES_NULL;
2650 error = VOP_SETATTR(vp, &vattr, td->td_proc->p_ucred, td);
2651 VOP_UNLOCK(vp, 0, td);
2652 vn_finished_write(mp);
2657 * Set the access and modification times of a file.
2659 #ifndef _SYS_SYSPROTO_H_
2660 struct utimes_args {
2662 struct timeval *tptr;
2669 register struct utimes_args /* {
2670 syscallarg(char *) path;
2671 syscallarg(struct timeval *) tptr;
2674 struct timespec ts[2];
2675 struct timeval *usrtvp;
2677 struct nameidata nd;
2679 usrtvp = SCARG(uap, tptr);
2680 if ((error = getutimes(usrtvp, ts)) != 0)
2682 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td);
2683 if ((error = namei(&nd)) != 0)
2685 NDFREE(&nd, NDF_ONLY_PNBUF);
2686 error = setutimes(td, nd.ni_vp, ts, usrtvp == NULL);
2692 * Set the access and modification times of a file.
2694 #ifndef _SYS_SYSPROTO_H_
2695 struct lutimes_args {
2697 struct timeval *tptr;
2704 register struct lutimes_args /* {
2705 syscallarg(char *) path;
2706 syscallarg(struct timeval *) tptr;
2709 struct timespec ts[2];
2710 struct timeval *usrtvp;
2712 struct nameidata nd;
2714 usrtvp = SCARG(uap, tptr);
2715 if ((error = getutimes(usrtvp, ts)) != 0)
2717 NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), td);
2718 if ((error = namei(&nd)) != 0)
2720 NDFREE(&nd, NDF_ONLY_PNBUF);
2721 error = setutimes(td, nd.ni_vp, ts, usrtvp == NULL);
2727 * Set the access and modification times of a file.
2729 #ifndef _SYS_SYSPROTO_H_
2730 struct futimes_args {
2732 struct timeval *tptr;
2739 register struct futimes_args /* {
2740 syscallarg(int ) fd;
2741 syscallarg(struct timeval *) tptr;
2744 struct timespec ts[2];
2746 struct timeval *usrtvp;
2749 usrtvp = SCARG(uap, tptr);
2750 if ((error = getutimes(usrtvp, ts)) != 0)
2752 if ((error = getvnode(td->td_proc->p_fd, SCARG(uap, fd), &fp)) != 0)
2754 error = setutimes(td, (struct vnode *)fp->f_data, ts, usrtvp == NULL);
2760 * Truncate a file given its path name.
2762 #ifndef _SYS_SYSPROTO_H_
2763 struct truncate_args {
2773 register struct truncate_args /* {
2774 syscallarg(char *) path;
2775 syscallarg(int) pad;
2776 syscallarg(off_t) length;
2783 struct nameidata nd;
2785 if (uap->length < 0)
2787 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td);
2788 if ((error = namei(&nd)) != 0)
2791 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) {
2795 NDFREE(&nd, NDF_ONLY_PNBUF);
2796 VOP_LEASE(vp, td, td->td_proc->p_ucred, LEASE_WRITE);
2797 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
2798 if (vp->v_type == VDIR)
2800 else if ((error = vn_writechk(vp)) == 0 &&
2801 (error = VOP_ACCESS(vp, VWRITE, td->td_proc->p_ucred, td)) == 0) {
2803 vattr.va_size = SCARG(uap, length);
2804 error = VOP_SETATTR(vp, &vattr, td->td_proc->p_ucred, td);
2807 vn_finished_write(mp);
2812 * Truncate a file given a file descriptor.
2814 #ifndef _SYS_SYSPROTO_H_
2815 struct ftruncate_args {
2825 register struct ftruncate_args /* {
2827 syscallarg(int) pad;
2828 syscallarg(off_t) length;
2837 if (uap->length < 0)
2839 if ((error = getvnode(td->td_proc->p_fd, SCARG(uap, fd), &fp)) != 0)
2841 if ((fp->f_flag & FWRITE) == 0) {
2845 vp = (struct vnode *)fp->f_data;
2846 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) {
2850 VOP_LEASE(vp, td, td->td_proc->p_ucred, LEASE_WRITE);
2851 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
2852 if (vp->v_type == VDIR)
2854 else if ((error = vn_writechk(vp)) == 0) {
2856 vattr.va_size = SCARG(uap, length);
2857 error = VOP_SETATTR(vp, &vattr, fp->f_cred, td);
2859 VOP_UNLOCK(vp, 0, td);
2860 vn_finished_write(mp);
2865 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
2867 * Truncate a file given its path name.
2869 #ifndef _SYS_SYSPROTO_H_
2870 struct otruncate_args {
2879 register struct otruncate_args /* {
2880 syscallarg(char *) path;
2881 syscallarg(long) length;
2884 struct truncate_args /* {
2885 syscallarg(char *) path;
2886 syscallarg(int) pad;
2887 syscallarg(off_t) length;
2890 SCARG(&nuap, path) = SCARG(uap, path);
2891 SCARG(&nuap, length) = SCARG(uap, length);
2892 return (truncate(td, &nuap));
2896 * Truncate a file given a file descriptor.
2898 #ifndef _SYS_SYSPROTO_H_
2899 struct oftruncate_args {
2908 register struct oftruncate_args /* {
2910 syscallarg(long) length;
2913 struct ftruncate_args /* {
2915 syscallarg(int) pad;
2916 syscallarg(off_t) length;
2919 SCARG(&nuap, fd) = SCARG(uap, fd);
2920 SCARG(&nuap, length) = SCARG(uap, length);
2921 return (ftruncate(td, &nuap));
2923 #endif /* COMPAT_43 || COMPAT_SUNOS */
2926 * Sync an open file.
2928 #ifndef _SYS_SYSPROTO_H_
2937 struct fsync_args /* {
2949 if ((error = getvnode(td->td_proc->p_fd, SCARG(uap, fd), &fp)) != 0)
2951 vp = (struct vnode *)fp->f_data;
2952 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) {
2956 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
2957 if (VOP_GETVOBJECT(vp, &obj) == 0) {
2958 vm_object_page_clean(obj, 0, 0, 0);
2960 error = VOP_FSYNC(vp, fp->f_cred, MNT_WAIT, td);
2962 if (error == 0 && vp->v_mount && (vp->v_mount->mnt_flag & MNT_SOFTDEP))
2963 error = softdep_fsync(vp);
2966 VOP_UNLOCK(vp, 0, td);
2967 vn_finished_write(mp);
2973 * Rename files. Source and destination must either both be directories,
2974 * or both not be directories. If target is a directory, it must be empty.
2976 #ifndef _SYS_SYSPROTO_H_
2977 struct rename_args {
2986 register struct rename_args /* {
2987 syscallarg(char *) from;
2988 syscallarg(char *) to;
2992 struct vnode *tvp, *fvp, *tdvp;
2993 struct nameidata fromnd, tond;
2997 NDINIT(&fromnd, DELETE, WANTPARENT | SAVESTART, UIO_USERSPACE,
2998 SCARG(uap, from), td);
2999 if ((error = namei(&fromnd)) != 0)
3002 if ((error = vn_start_write(fvp, &mp, V_WAIT | PCATCH)) != 0) {
3003 NDFREE(&fromnd, NDF_ONLY_PNBUF);
3004 vrele(fromnd.ni_dvp);
3008 NDINIT(&tond, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART | NOOBJ,
3009 UIO_USERSPACE, SCARG(uap, to), td);
3010 if (fromnd.ni_vp->v_type == VDIR)
3011 tond.ni_cnd.cn_flags |= WILLBEDIR;
3012 if ((error = namei(&tond)) != 0) {
3013 /* Translate error code for rename("dir1", "dir2/."). */
3014 if (error == EISDIR && fvp->v_type == VDIR)
3016 NDFREE(&fromnd, NDF_ONLY_PNBUF);
3017 vrele(fromnd.ni_dvp);
3024 if (fvp->v_type == VDIR && tvp->v_type != VDIR) {
3027 } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) {
3035 * If source is the same as the destination (that is the
3036 * same inode number with the same name in the same directory),
3037 * then there is nothing to do.
3039 if (fvp == tvp && fromnd.ni_dvp == tdvp &&
3040 fromnd.ni_cnd.cn_namelen == tond.ni_cnd.cn_namelen &&
3041 !bcmp(fromnd.ni_cnd.cn_nameptr, tond.ni_cnd.cn_nameptr,
3042 fromnd.ni_cnd.cn_namelen))
3046 VOP_LEASE(tdvp, td, td->td_proc->p_ucred, LEASE_WRITE);
3047 if (fromnd.ni_dvp != tdvp) {
3048 VOP_LEASE(fromnd.ni_dvp, td, td->td_proc->p_ucred, LEASE_WRITE);
3051 VOP_LEASE(tvp, td, td->td_proc->p_ucred, LEASE_WRITE);
3053 error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd,
3054 tond.ni_dvp, tond.ni_vp, &tond.ni_cnd);
3055 NDFREE(&fromnd, NDF_ONLY_PNBUF);
3056 NDFREE(&tond, NDF_ONLY_PNBUF);
3058 NDFREE(&fromnd, NDF_ONLY_PNBUF);
3059 NDFREE(&tond, NDF_ONLY_PNBUF);
3066 vrele(fromnd.ni_dvp);
3069 vrele(tond.ni_startdir);
3070 vn_finished_write(mp);
3071 ASSERT_VOP_UNLOCKED(fromnd.ni_dvp, "rename");
3072 ASSERT_VOP_UNLOCKED(fromnd.ni_vp, "rename");
3073 ASSERT_VOP_UNLOCKED(tond.ni_dvp, "rename");
3074 ASSERT_VOP_UNLOCKED(tond.ni_vp, "rename");
3076 if (fromnd.ni_startdir)
3077 vrele(fromnd.ni_startdir);
3084 * Make a directory file.
3086 #ifndef _SYS_SYSPROTO_H_
3096 register struct mkdir_args /* {
3097 syscallarg(char *) path;
3098 syscallarg(int) mode;
3102 return vn_mkdir(uap->path, uap->mode, UIO_USERSPACE, td);
3106 vn_mkdir(path, mode, segflg, td)
3109 enum uio_seg segflg;
3116 struct nameidata nd;
3120 NDINIT(&nd, CREATE, LOCKPARENT, segflg, path, td);
3121 nd.ni_cnd.cn_flags |= WILLBEDIR;
3122 if ((error = namei(&nd)) != 0)
3126 NDFREE(&nd, NDF_ONLY_PNBUF);
3131 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) {
3132 NDFREE(&nd, NDF_ONLY_PNBUF);
3134 if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0)
3139 vattr.va_type = VDIR;
3140 FILEDESC_LOCK(td->td_proc->p_fd);
3141 vattr.va_mode = (mode & ACCESSPERMS) &~ td->td_proc->p_fd->fd_cmask;
3142 FILEDESC_UNLOCK(td->td_proc->p_fd);
3143 VOP_LEASE(nd.ni_dvp, td, td->td_proc->p_ucred, LEASE_WRITE);
3144 error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
3145 NDFREE(&nd, NDF_ONLY_PNBUF);
3149 vn_finished_write(mp);
3150 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "mkdir");
3151 ASSERT_VOP_UNLOCKED(nd.ni_vp, "mkdir");
3156 * Remove a directory file.
3158 #ifndef _SYS_SYSPROTO_H_
3167 struct rmdir_args /* {
3168 syscallarg(char *) path;
3174 struct nameidata nd;
3178 NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF, UIO_USERSPACE,
3179 SCARG(uap, path), td);
3180 if ((error = namei(&nd)) != 0)
3183 if (vp->v_type != VDIR) {
3188 * No rmdir "." please.
3190 if (nd.ni_dvp == vp) {
3195 * The root of a mounted filesystem cannot be deleted.
3197 if (vp->v_flag & VROOT) {
3201 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) {
3202 NDFREE(&nd, NDF_ONLY_PNBUF);
3203 if (nd.ni_dvp == vp)
3208 if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0)
3212 VOP_LEASE(nd.ni_dvp, td, td->td_proc->p_ucred, LEASE_WRITE);
3213 VOP_LEASE(vp, td, td->td_proc->p_ucred, LEASE_WRITE);
3214 error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
3215 vn_finished_write(mp);
3217 NDFREE(&nd, NDF_ONLY_PNBUF);
3218 if (nd.ni_dvp == vp)
3223 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "rmdir");
3224 ASSERT_VOP_UNLOCKED(nd.ni_vp, "rmdir");
3230 * Read a block of directory entries in a file system independent format.
3232 #ifndef _SYS_SYSPROTO_H_
3233 struct ogetdirentries_args {
3241 ogetdirentries(td, uap)
3243 register struct ogetdirentries_args /* {
3245 syscallarg(char *) buf;
3246 syscallarg(u_int) count;
3247 syscallarg(long *) basep;
3252 struct uio auio, kuio;
3253 struct iovec aiov, kiov;
3254 struct dirent *dp, *edp;
3256 int error, eofflag, readcnt;
3259 /* XXX arbitrary sanity limit on `count'. */
3260 if (SCARG(uap, count) > 64 * 1024)
3262 if ((error = getvnode(td->td_proc->p_fd, SCARG(uap, fd), &fp)) != 0)
3264 if ((fp->f_flag & FREAD) == 0) {
3268 vp = (struct vnode *)fp->f_data;
3270 if (vp->v_type != VDIR) {
3274 aiov.iov_base = SCARG(uap, buf);
3275 aiov.iov_len = SCARG(uap, count);
3276 auio.uio_iov = &aiov;
3277 auio.uio_iovcnt = 1;
3278 auio.uio_rw = UIO_READ;
3279 auio.uio_segflg = UIO_USERSPACE;
3281 auio.uio_resid = SCARG(uap, count);
3282 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
3283 loff = auio.uio_offset = fp->f_offset;
3284 # if (BYTE_ORDER != LITTLE_ENDIAN)
3285 if (vp->v_mount->mnt_maxsymlinklen <= 0) {
3286 error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag,
3288 fp->f_offset = auio.uio_offset;
3293 kuio.uio_iov = &kiov;
3294 kuio.uio_segflg = UIO_SYSSPACE;
3295 kiov.iov_len = SCARG(uap, count);
3296 MALLOC(dirbuf, caddr_t, SCARG(uap, count), M_TEMP, M_WAITOK);
3297 kiov.iov_base = dirbuf;
3298 error = VOP_READDIR(vp, &kuio, fp->f_cred, &eofflag,
3300 fp->f_offset = kuio.uio_offset;
3302 readcnt = SCARG(uap, count) - kuio.uio_resid;
3303 edp = (struct dirent *)&dirbuf[readcnt];
3304 for (dp = (struct dirent *)dirbuf; dp < edp; ) {
3305 # if (BYTE_ORDER == LITTLE_ENDIAN)
3307 * The expected low byte of
3308 * dp->d_namlen is our dp->d_type.
3309 * The high MBZ byte of dp->d_namlen
3310 * is our dp->d_namlen.
3312 dp->d_type = dp->d_namlen;
3316 * The dp->d_type is the high byte
3317 * of the expected dp->d_namlen,
3318 * so must be zero'ed.
3322 if (dp->d_reclen > 0) {
3323 dp = (struct dirent *)
3324 ((char *)dp + dp->d_reclen);
3331 error = uiomove(dirbuf, readcnt, &auio);
3333 FREE(dirbuf, M_TEMP);
3335 VOP_UNLOCK(vp, 0, td);
3340 if (SCARG(uap, count) == auio.uio_resid) {
3341 if (union_dircheckp) {
3342 error = union_dircheckp(td, &vp, fp);
3350 if ((vp->v_flag & VROOT) &&
3351 (vp->v_mount->mnt_flag & MNT_UNION)) {
3352 struct vnode *tvp = vp;
3353 vp = vp->v_mount->mnt_vnodecovered;
3355 fp->f_data = (caddr_t) vp;
3361 error = copyout((caddr_t)&loff, (caddr_t)SCARG(uap, basep),
3364 td->td_retval[0] = SCARG(uap, count) - auio.uio_resid;
3367 #endif /* COMPAT_43 */
3370 * Read a block of directory entries in a file system independent format.
3372 #ifndef _SYS_SYSPROTO_H_
3373 struct getdirentries_args {
3381 getdirentries(td, uap)
3383 register struct getdirentries_args /* {
3385 syscallarg(char *) buf;
3386 syscallarg(u_int) count;
3387 syscallarg(long *) basep;
3397 if ((error = getvnode(td->td_proc->p_fd, SCARG(uap, fd), &fp)) != 0)
3399 if ((fp->f_flag & FREAD) == 0) {
3403 vp = (struct vnode *)fp->f_data;
3405 if (vp->v_type != VDIR) {
3409 aiov.iov_base = SCARG(uap, buf);
3410 aiov.iov_len = SCARG(uap, count);
3411 auio.uio_iov = &aiov;
3412 auio.uio_iovcnt = 1;
3413 auio.uio_rw = UIO_READ;
3414 auio.uio_segflg = UIO_USERSPACE;
3416 auio.uio_resid = SCARG(uap, count);
3417 /* vn_lock(vp, LK_SHARED | LK_RETRY, td); */
3418 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
3419 loff = auio.uio_offset = fp->f_offset;
3420 error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, NULL, NULL);
3421 fp->f_offset = auio.uio_offset;
3422 VOP_UNLOCK(vp, 0, td);
3427 if (SCARG(uap, count) == auio.uio_resid) {
3428 if (union_dircheckp) {
3429 error = union_dircheckp(td, &vp, fp);
3437 if ((vp->v_flag & VROOT) &&
3438 (vp->v_mount->mnt_flag & MNT_UNION)) {
3439 struct vnode *tvp = vp;
3440 vp = vp->v_mount->mnt_vnodecovered;
3442 fp->f_data = (caddr_t) vp;
3448 if (SCARG(uap, basep) != NULL) {
3449 error = copyout((caddr_t)&loff, (caddr_t)SCARG(uap, basep),
3452 td->td_retval[0] = SCARG(uap, count) - auio.uio_resid;
3456 #ifndef _SYS_SYSPROTO_H_
3457 struct getdents_args {
3466 register struct getdents_args /* {
3468 syscallarg(char *) buf;
3469 syscallarg(u_int) count;
3472 struct getdirentries_args ap;
3475 ap.count = uap->count;
3477 return getdirentries(td, &ap);
3481 * Set the mode mask for creation of filesystem nodes.
3485 #ifndef _SYS_SYSPROTO_H_
3493 struct umask_args /* {
3494 syscallarg(int) newmask;
3497 register struct filedesc *fdp;
3499 FILEDESC_LOCK(td->td_proc->p_fd);
3500 fdp = td->td_proc->p_fd;
3501 td->td_retval[0] = fdp->fd_cmask;
3502 fdp->fd_cmask = SCARG(uap, newmask) & ALLPERMS;
3503 FILEDESC_UNLOCK(td->td_proc->p_fd);
3508 * Void all references to file by ripping underlying filesystem
3511 #ifndef _SYS_SYSPROTO_H_
3512 struct revoke_args {
3520 register struct revoke_args /* {
3521 syscallarg(char *) path;
3528 struct nameidata nd;
3530 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, SCARG(uap, path),
3532 if ((error = namei(&nd)) != 0)
3535 NDFREE(&nd, NDF_ONLY_PNBUF);
3536 if (vp->v_type != VCHR) {
3540 error = VOP_GETATTR(vp, &vattr, td->td_proc->p_ucred, td);
3545 VOP_UNLOCK(vp, 0, td);
3546 if (td->td_proc->p_ucred->cr_uid != vattr.va_uid) {
3547 error = suser_xxx(0, td->td_proc, PRISON_ROOT);
3551 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
3554 VOP_REVOKE(vp, REVOKEALL);
3555 vn_finished_write(mp);
3562 * Convert a user file descriptor to a kernel file entry.
3563 * The file entry is locked upon returning.
3566 getvnode(fdp, fd, fpp)
3567 struct filedesc *fdp;
3579 if ((u_int)fd >= fdp->fd_nfiles ||
3580 (fp = fdp->fd_ofiles[fd]) == NULL)
3582 else if (fp->f_type != DTYPE_VNODE && fp->f_type != DTYPE_FIFO) {
3589 FILEDESC_UNLOCK(fdp);
3595 * Get (NFS) file handle
3597 #ifndef _SYS_SYSPROTO_H_
3606 register struct getfh_args *uap;
3608 struct nameidata nd;
3610 register struct vnode *vp;
3614 * Must be super user
3616 error = suser_td(td);
3619 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, td);
3623 NDFREE(&nd, NDF_ONLY_PNBUF);
3625 bzero(&fh, sizeof(fh));
3626 fh.fh_fsid = vp->v_mount->mnt_stat.f_fsid;
3627 error = VFS_VPTOFH(vp, &fh.fh_fid);
3631 error = copyout(&fh, uap->fhp, sizeof (fh));
3636 * syscall for the rpc.lockd to use to translate a NFS file handle into
3637 * an open descriptor.
3639 * warning: do not remove the suser() call or this becomes one giant
3642 #ifndef _SYS_SYSPROTO_H_
3643 struct fhopen_args {
3644 const struct fhandle *u_fhp;
3651 struct fhopen_args /* {
3652 syscallarg(const struct fhandle *) u_fhp;
3653 syscallarg(int) flags;
3656 struct proc *p = td->td_proc;
3661 struct vattr *vap = &vat;
3664 register struct filedesc *fdp = p->p_fd;
3665 int fmode, mode, error, type;
3670 * Must be super user
3672 error = suser_td(td);
3676 fmode = FFLAGS(SCARG(uap, flags));
3677 /* why not allow a non-read/write open for our lockd? */
3678 if (((fmode & (FREAD | FWRITE)) == 0) || (fmode & O_CREAT))
3680 error = copyin(SCARG(uap,u_fhp), &fhp, sizeof(fhp));
3683 /* find the mount point */
3684 mp = vfs_getvfs(&fhp.fh_fsid);
3687 /* now give me my vnode, it gets returned to me locked */
3688 error = VFS_FHTOVP(mp, &fhp.fh_fid, &vp);
3692 * from now on we have to make sure not
3693 * to forget about the vnode
3694 * any error that causes an abort must vput(vp)
3695 * just set error = err and 'goto bad;'.
3701 if (vp->v_type == VLNK) {
3705 if (vp->v_type == VSOCK) {
3710 if (fmode & (FWRITE | O_TRUNC)) {
3711 if (vp->v_type == VDIR) {
3715 error = vn_writechk(vp);
3723 error = VOP_ACCESS(vp, mode, p->p_ucred, td);
3727 if (fmode & O_TRUNC) {
3728 VOP_UNLOCK(vp, 0, td); /* XXX */
3729 if ((error = vn_start_write(NULL, &mp, V_WAIT | PCATCH)) != 0) {
3733 VOP_LEASE(vp, td, p->p_ucred, LEASE_WRITE);
3734 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); /* XXX */
3737 error = VOP_SETATTR(vp, vap, p->p_ucred, td);
3738 vn_finished_write(mp);
3742 error = VOP_OPEN(vp, fmode, p->p_ucred, td);
3746 * Make sure that a VM object is created for VMIO support.
3748 if (vn_canvmio(vp) == TRUE) {
3749 if ((error = vfs_object_create(vp, td, p->p_ucred)) != 0)
3756 * end of vn_open code
3759 if ((error = falloc(td, &nfp, &indx)) != 0) {
3767 * Hold an extra reference to avoid having fp ripped out
3768 * from under us while we block in the lock op
3771 nfp->f_data = (caddr_t)vp;
3772 nfp->f_flag = fmode & FMASK;
3773 nfp->f_ops = &vnops;
3774 nfp->f_type = DTYPE_VNODE;
3775 if (fmode & (O_EXLOCK | O_SHLOCK)) {
3776 lf.l_whence = SEEK_SET;
3779 if (fmode & O_EXLOCK)
3780 lf.l_type = F_WRLCK;
3782 lf.l_type = F_RDLCK;
3784 if ((fmode & FNONBLOCK) == 0)
3786 VOP_UNLOCK(vp, 0, td);
3787 if ((error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type)) != 0) {
3789 * The lock request failed. Normally close the
3790 * descriptor but handle the case where someone might
3791 * have dup()d or close()d it when we weren't looking.
3794 if (fdp->fd_ofiles[indx] == fp) {
3795 fdp->fd_ofiles[indx] = NULL;
3796 FILEDESC_UNLOCK(fdp);
3799 FILEDESC_UNLOCK(fdp);
3801 * release our private reference
3806 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
3807 fp->f_flag |= FHASLOCK;
3809 if ((vp->v_type == VREG) && (VOP_GETVOBJECT(vp, NULL) != 0))
3810 vfs_object_create(vp, td, p->p_ucred);
3812 VOP_UNLOCK(vp, 0, td);
3814 td->td_retval[0] = indx;
3823 * Stat an (NFS) file handle.
3825 #ifndef _SYS_SYSPROTO_H_
3826 struct fhstat_args {
3827 struct fhandle *u_fhp;
3834 register struct fhstat_args /* {
3835 syscallarg(struct fhandle *) u_fhp;
3836 syscallarg(struct stat *) sb;
3846 * Must be super user
3848 error = suser_td(td);
3852 error = copyin(SCARG(uap, u_fhp), &fh, sizeof(fhandle_t));
3856 if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL)
3858 if ((error = VFS_FHTOVP(mp, &fh.fh_fid, &vp)))
3860 error = vn_stat(vp, &sb, td);
3864 error = copyout(&sb, SCARG(uap, sb), sizeof(sb));
3869 * Implement fstatfs() for (NFS) file handles.
3871 #ifndef _SYS_SYSPROTO_H_
3872 struct fhstatfs_args {
3873 struct fhandle *u_fhp;
3880 struct fhstatfs_args /* {
3881 syscallarg(struct fhandle) *u_fhp;
3882 syscallarg(struct statfs) *buf;
3893 * Must be super user
3895 error = suser_td(td);
3899 if ((error = copyin(SCARG(uap, u_fhp), &fh, sizeof(fhandle_t))) != 0)
3902 if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL)
3904 if ((error = VFS_FHTOVP(mp, &fh.fh_fid, &vp)))
3909 if ((error = VFS_STATFS(mp, sp, td)) != 0)
3911 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
3912 if (suser_xxx(td->td_proc->p_ucred, 0, 0)) {
3913 bcopy((caddr_t)sp, (caddr_t)&sb, sizeof(sb));
3914 sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0;
3917 return (copyout(sp, SCARG(uap, buf), sizeof(*sp)));
3921 * Syscall to push extended attribute configuration information into the
3922 * VFS. Accepts a path, which it converts to a mountpoint, as well as
3923 * a command (int cmd), and attribute name and misc data. For now, the
3924 * attribute name is left in userspace for consumption by the VFS_op.
3925 * It will probably be changed to be copied into sysspace by the
3926 * syscall in the future, once issues with various consumers of the
3927 * attribute code have raised their hands.
3929 * Currently this is used only by UFS Extended Attributes.
3934 struct extattrctl_args *uap;
3936 struct vnode *filename_vp;
3937 struct nameidata nd;
3938 struct mount *mp, *mp_writable;
3939 char attrname[EXTATTR_MAXNAMELEN];
3943 * SCARG(uap, attrname) not always defined. We check again later
3944 * when we invoke the VFS call so as to pass in NULL there if needed.
3946 if (SCARG(uap, attrname) != NULL) {
3947 error = copyinstr(SCARG(uap, attrname), attrname,
3948 EXTATTR_MAXNAMELEN, NULL);
3954 * SCARG(uap, filename) not always defined. If it is, grab
3955 * a vnode lock, which VFS_EXTATTRCTL() will later release.
3958 if (SCARG(uap, filename) != NULL) {
3959 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
3960 SCARG(uap, filename), td);
3961 if ((error = namei(&nd)) != 0)
3963 filename_vp = nd.ni_vp;
3964 NDFREE(&nd, NDF_NO_VP_RELE | NDF_NO_VP_UNLOCK);
3967 /* SCARG(uap, path) always defined. */
3968 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td);
3969 if ((error = namei(&nd)) != 0) {
3970 if (filename_vp != NULL)
3974 mp = nd.ni_vp->v_mount;
3975 error = vn_start_write(nd.ni_vp, &mp_writable, V_WAIT | PCATCH);
3978 if (filename_vp != NULL)
3983 if (SCARG(uap, attrname) != NULL) {
3984 error = VFS_EXTATTRCTL(mp, SCARG(uap, cmd), filename_vp,
3985 SCARG(uap, attrnamespace), attrname, td);
3987 error = VFS_EXTATTRCTL(mp, SCARG(uap, cmd), filename_vp,
3988 SCARG(uap, attrnamespace), NULL, td);
3991 vn_finished_write(mp_writable);
3993 * VFS_EXTATTRCTL will have unlocked, but not de-ref'd,
3994 * filename_vp, so vrele it if it is defined.
3996 if (filename_vp != NULL)
4003 * Set a named extended attribute on a file or directory
4005 * Arguments: unlocked vnode "vp", attribute namespace "attrnamespace",
4006 * kernelspace string pointer "attrname", userspace buffer
4007 * pointer "data", buffer length "nbytes", thread "td".
4008 * Returns: 0 on success, an error number otherwise
4010 * References: vp must be a valid reference for the duration of the call
4013 extattr_set_vp(struct vnode *vp, int attrnamespace, const char *attrname,
4014 void *data, size_t nbytes, struct thread *td)
4022 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
4024 VOP_LEASE(vp, td, td->td_proc->p_ucred, LEASE_WRITE);
4025 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
4027 aiov.iov_base = data;
4028 aiov.iov_len = nbytes;
4029 auio.uio_iov = &aiov;
4030 auio.uio_iovcnt = 1;
4031 auio.uio_offset = 0;
4032 if (nbytes > INT_MAX) {
4036 auio.uio_resid = nbytes;
4037 auio.uio_rw = UIO_WRITE;
4038 auio.uio_segflg = UIO_USERSPACE;
4042 error = VOP_SETEXTATTR(vp, attrnamespace, attrname, &auio,
4043 td->td_proc->p_ucred, td);
4044 cnt -= auio.uio_resid;
4045 td->td_retval[0] = cnt;
4048 VOP_UNLOCK(vp, 0, td);
4049 vn_finished_write(mp);
4054 extattr_set_file(td, uap)
4056 struct extattr_set_file_args *uap;
4058 struct nameidata nd;
4059 char attrname[EXTATTR_MAXNAMELEN];
4062 error = copyinstr(SCARG(uap, attrname), attrname, EXTATTR_MAXNAMELEN,
4067 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td);
4068 if ((error = namei(&nd)) != 0)
4070 NDFREE(&nd, NDF_ONLY_PNBUF);
4072 error = extattr_set_vp(nd.ni_vp, SCARG(uap, attrnamespace), attrname,
4073 SCARG(uap, data), SCARG(uap, nbytes), td);
4080 extattr_set_fd(td, uap)
4082 struct extattr_set_fd_args *uap;
4085 char attrname[EXTATTR_MAXNAMELEN];
4088 error = copyinstr(SCARG(uap, attrname), attrname, EXTATTR_MAXNAMELEN,
4093 if ((error = getvnode(td->td_proc->p_fd, SCARG(uap, fd), &fp)) != 0)
4096 error = extattr_set_vp((struct vnode *)fp->f_data,
4097 SCARG(uap, attrnamespace), attrname, SCARG(uap, data),
4098 SCARG(uap, nbytes), td);
4105 * Get a named extended attribute on a file or directory
4107 * Arguments: unlocked vnode "vp", attribute namespace "attrnamespace",
4108 * kernelspace string pointer "attrname", userspace buffer
4109 * pointer "data", buffer length "nbytes", thread "td".
4110 * Returns: 0 on success, an error number otherwise
4112 * References: vp must be a valid reference for the duration of the call
4115 extattr_get_vp(struct vnode *vp, int attrnamespace, const char *attrname,
4116 void *data, size_t nbytes, struct thread *td)
4124 VOP_LEASE(vp, td, td->td_proc->p_ucred, LEASE_READ);
4125 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
4128 * Slightly unusual semantics: if the user provides a NULL data
4129 * pointer, they don't want to receive the data, just the
4130 * maximum read length.
4133 aiov.iov_base = data;
4134 aiov.iov_len = nbytes;
4135 auio.uio_iov = &aiov;
4136 auio.uio_offset = 0;
4137 if (nbytes > INT_MAX) {
4141 auio.uio_resid = nbytes;
4142 auio.uio_rw = UIO_READ;
4143 auio.uio_segflg = UIO_USERSPACE;
4146 error = VOP_GETEXTATTR(vp, attrnamespace, attrname, &auio,
4147 NULL, td->td_proc->p_ucred, td);
4148 cnt -= auio.uio_resid;
4149 td->td_retval[0] = cnt;
4151 error = VOP_GETEXTATTR(vp, attrnamespace, attrname, NULL,
4152 &size, td->td_proc->p_ucred, td);
4153 td->td_retval[0] = size;
4156 VOP_UNLOCK(vp, 0, td);
4161 extattr_get_file(td, uap)
4163 struct extattr_get_file_args *uap;
4165 struct nameidata nd;
4166 char attrname[EXTATTR_MAXNAMELEN];
4169 error = copyinstr(SCARG(uap, attrname), attrname, EXTATTR_MAXNAMELEN,
4174 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td);
4175 if ((error = namei(&nd)) != 0)
4177 NDFREE(&nd, NDF_ONLY_PNBUF);
4179 error = extattr_get_vp(nd.ni_vp, SCARG(uap, attrnamespace), attrname,
4180 SCARG(uap, data), SCARG(uap, nbytes), td);
4187 extattr_get_fd(td, uap)
4189 struct extattr_get_fd_args *uap;
4192 char attrname[EXTATTR_MAXNAMELEN];
4195 error = copyinstr(SCARG(uap, attrname), attrname, EXTATTR_MAXNAMELEN,
4200 if ((error = getvnode(td->td_proc->p_fd, SCARG(uap, fd), &fp)) != 0)
4203 error = extattr_get_vp((struct vnode *)fp->f_data,
4204 SCARG(uap, attrnamespace), attrname, SCARG(uap, data),
4205 SCARG(uap, nbytes), td);
4212 * extattr_delete_vp(): Delete a named extended attribute on a file or
4215 * Arguments: unlocked vnode "vp", attribute namespace "attrnamespace",
4216 * kernelspace string pointer "attrname", proc "p"
4217 * Returns: 0 on success, an error number otherwise
4219 * References: vp must be a valid reference for the duration of the call
4222 extattr_delete_vp(struct vnode *vp, int attrnamespace, const char *attrname,
4228 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
4230 VOP_LEASE(vp, td, td->td_proc->p_ucred, LEASE_WRITE);
4231 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
4233 error = VOP_SETEXTATTR(vp, attrnamespace, attrname, NULL,
4234 td->td_proc->p_ucred, td);
4236 VOP_UNLOCK(vp, 0, td);
4237 vn_finished_write(mp);
4242 extattr_delete_file(td, uap)
4244 struct extattr_delete_file_args *uap;
4246 struct nameidata nd;
4247 char attrname[EXTATTR_MAXNAMELEN];
4250 error = copyinstr(SCARG(uap, attrname), attrname, EXTATTR_MAXNAMELEN,
4255 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td);
4256 if ((error = namei(&nd)) != 0)
4258 NDFREE(&nd, NDF_ONLY_PNBUF);
4260 error = extattr_delete_vp(nd.ni_vp, SCARG(uap, attrnamespace),
4268 extattr_delete_fd(td, uap)
4270 struct extattr_delete_fd_args *uap;
4274 char attrname[EXTATTR_MAXNAMELEN];
4277 error = copyinstr(SCARG(uap, attrname), attrname, EXTATTR_MAXNAMELEN,
4282 if ((error = getvnode(td->td_proc->p_fd, SCARG(uap, fd), &fp)) != 0)
4284 vp = (struct vnode *)fp->f_data;
4286 error = extattr_delete_vp((struct vnode *)fp->f_data,
4287 SCARG(uap, attrnamespace), attrname, td);