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_page.h>
78 static int change_dir(struct nameidata *ndp, struct thread *td);
79 static void checkdirs(struct vnode *olddp, struct vnode *newdp);
80 static int chroot_refuse_vdir_fds(struct filedesc *fdp);
81 static int getutimes(const struct timeval *, struct timespec *);
82 static int setfown(struct thread *td, struct vnode *, uid_t, gid_t);
83 static int setfmode(struct thread *td, struct vnode *, int);
84 static int setfflags(struct thread *td, struct vnode *, int);
85 static int setutimes(struct thread *td, struct vnode *,
86 const struct timespec *, int);
87 static int vn_access(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)(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_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_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_ucred, td);
282 if (va.va_uid != td->td_ucred->cr_uid) {
283 error = suser_td(td);
289 if ((error = vinvalbuf(vp, V_SAVE, td->td_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 = securelevel_gt(td->td_ucred, 0);
315 error = linker_load_file(fstype, &lf);
316 if (error || lf == NULL) {
323 /* lookup again, see if the VFS was loaded */
324 for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next)
325 if (!strcmp(vfsp->vfc_name, fstype))
329 linker_file_unload(lf);
334 mtx_lock(&vp->v_interlock);
335 if ((vp->v_flag & VMOUNT) != 0 ||
336 vp->v_mountedhere != NULL) {
337 mtx_unlock(&vp->v_interlock);
341 vp->v_flag |= VMOUNT;
342 mtx_unlock(&vp->v_interlock);
345 * Allocate and initialize the filesystem.
347 mp = malloc(sizeof(struct mount), M_MOUNT, M_WAITOK | M_ZERO);
348 TAILQ_INIT(&mp->mnt_nvnodelist);
349 TAILQ_INIT(&mp->mnt_reservedvnlist);
350 lockinit(&mp->mnt_lock, PVFS, "vfslock", 0, LK_NOPAUSE);
351 (void)vfs_busy(mp, LK_NOWAIT, 0, td);
352 mp->mnt_op = vfsp->vfc_vfsops;
354 vfsp->vfc_refcount++;
355 mp->mnt_stat.f_type = vfsp->vfc_typenum;
356 mp->mnt_flag |= vfsp->vfc_flags & MNT_VISFLAGMASK;
357 strncpy(mp->mnt_stat.f_fstypename, fstype, MFSNAMELEN);
358 mp->mnt_stat.f_fstypename[MFSNAMELEN - 1] = '\0';
359 mp->mnt_vnodecovered = vp;
360 mp->mnt_stat.f_owner = td->td_ucred->cr_uid;
361 strncpy(mp->mnt_stat.f_mntonname, fspath, MNAMELEN);
362 mp->mnt_stat.f_mntonname[MNAMELEN - 1] = '\0';
363 mp->mnt_iosize_max = DFLTPHYS;
364 VOP_UNLOCK(vp, 0, td);
367 * Set the mount level flags.
369 if (fsflags & MNT_RDONLY)
370 mp->mnt_flag |= MNT_RDONLY;
371 else if (mp->mnt_flag & MNT_RDONLY)
372 mp->mnt_kern_flag |= MNTK_WANTRDWR;
373 mp->mnt_flag &=~ MNT_UPDATEMASK;
374 mp->mnt_flag |= fsflags & (MNT_UPDATEMASK | MNT_FORCE);
376 * Mount the filesystem.
377 * XXX The final recipients of VFS_MOUNT just overwrite the ndp they
378 * get. No freeing of cn_pnbuf.
380 error = VFS_MOUNT(mp, fspath, fsdata, &nd, td);
381 if (mp->mnt_flag & MNT_UPDATE) {
382 if (mp->mnt_kern_flag & MNTK_WANTRDWR)
383 mp->mnt_flag &= ~MNT_RDONLY;
385 (MNT_UPDATE | MNT_RELOAD | MNT_FORCE | MNT_SNAPSHOT);
386 mp->mnt_kern_flag &=~ MNTK_WANTRDWR;
389 mp->mnt_kern_flag = flag2;
391 if ((mp->mnt_flag & MNT_RDONLY) == 0) {
392 if (mp->mnt_syncer == NULL)
393 error = vfs_allocate_syncvnode(mp);
395 if (mp->mnt_syncer != NULL)
396 vrele(mp->mnt_syncer);
397 mp->mnt_syncer = NULL;
400 mtx_lock(&vp->v_interlock);
401 vp->v_flag &= ~VMOUNT;
402 mtx_unlock(&vp->v_interlock);
406 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
408 * Put the new filesystem on the mount list after root.
414 mtx_lock(&vp->v_interlock);
415 vp->v_flag &= ~VMOUNT;
416 vp->v_mountedhere = mp;
417 mtx_unlock(&vp->v_interlock);
418 mtx_lock(&mountlist_mtx);
419 TAILQ_INSERT_TAIL(&mountlist, mp, mnt_list);
420 mtx_unlock(&mountlist_mtx);
421 if (VFS_ROOT(mp, &newdp))
422 panic("mount: lost mount");
423 checkdirs(vp, newdp);
425 VOP_UNLOCK(vp, 0, td);
426 if ((mp->mnt_flag & MNT_RDONLY) == 0)
427 error = vfs_allocate_syncvnode(mp);
429 if ((error = VFS_START(mp, 0, td)) != 0)
432 mtx_lock(&vp->v_interlock);
433 vp->v_flag &= ~VMOUNT;
434 mtx_unlock(&vp->v_interlock);
435 mp->mnt_vfc->vfc_refcount--;
437 free((caddr_t)mp, M_MOUNT);
444 * Scan all active processes to see if any of them have a current
445 * or root directory of `olddp'. If so, replace them with the new
449 checkdirs(olddp, newdp)
450 struct vnode *olddp, *newdp;
452 struct filedesc *fdp;
456 if (olddp->v_usecount == 1)
458 sx_slock(&allproc_lock);
459 LIST_FOREACH(p, &allproc, p_list) {
468 if (fdp->fd_cdir == olddp) {
470 fdp->fd_cdir = newdp;
473 if (fdp->fd_rdir == olddp) {
475 fdp->fd_rdir = newdp;
478 FILEDESC_UNLOCK(fdp);
483 sx_sunlock(&allproc_lock);
484 if (rootvnode == olddp) {
492 * Unmount a file system.
494 * Note: unmount takes a path to the vnode mounted on as argument,
495 * not special file (as before).
497 #ifndef _SYS_SYSPROTO_H_
498 struct unmount_args {
507 register struct unmount_args /* {
508 syscallarg(char *) path;
509 syscallarg(int) flags;
512 register struct vnode *vp;
517 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
518 SCARG(uap, path), td);
519 if ((error = namei(&nd)) != 0)
522 NDFREE(&nd, NDF_ONLY_PNBUF);
526 * Only root, or the user that did the original mount is
527 * permitted to unmount this filesystem.
529 if (mp->mnt_stat.f_owner != td->td_ucred->cr_uid) {
530 error = suser_td(td);
538 * Don't allow unmounting the root file system.
540 if (mp->mnt_flag & MNT_ROOTFS) {
546 * Must be the root of the filesystem
548 if ((vp->v_flag & VROOT) == 0) {
553 return (dounmount(mp, SCARG(uap, flags), td));
557 * Do the actual file system unmount.
560 dounmount(mp, flags, td)
565 struct vnode *coveredvp, *fsrootvp;
569 mtx_lock(&mountlist_mtx);
570 mp->mnt_kern_flag |= MNTK_UNMOUNT;
571 error = lockmgr(&mp->mnt_lock, LK_DRAIN | LK_INTERLOCK |
572 ((flags & MNT_FORCE) ? 0 : LK_NOWAIT), &mountlist_mtx, td);
574 mp->mnt_kern_flag &= ~MNTK_UNMOUNT;
575 if (mp->mnt_kern_flag & MNTK_MWAIT)
579 vn_start_write(NULL, &mp, V_WAIT);
581 if (mp->mnt_flag & MNT_EXPUBLIC)
582 vfs_setpublicfs(NULL, NULL, NULL);
584 vfs_msync(mp, MNT_WAIT);
585 async_flag = mp->mnt_flag & MNT_ASYNC;
586 mp->mnt_flag &=~ MNT_ASYNC;
587 cache_purgevfs(mp); /* remove cache entries for this file sys */
588 if (mp->mnt_syncer != NULL)
589 vrele(mp->mnt_syncer);
590 /* Move process cdir/rdir refs on fs root to underlying vnode. */
591 if (VFS_ROOT(mp, &fsrootvp) == 0) {
592 if (mp->mnt_vnodecovered != NULL)
593 checkdirs(fsrootvp, mp->mnt_vnodecovered);
594 if (fsrootvp == rootvnode) {
600 if (((mp->mnt_flag & MNT_RDONLY) ||
601 (error = VFS_SYNC(mp, MNT_WAIT, td->td_ucred, td)) == 0) ||
602 (flags & MNT_FORCE)) {
603 error = VFS_UNMOUNT(mp, flags, td);
605 vn_finished_write(mp);
607 /* Undo cdir/rdir and rootvnode changes made above. */
608 if (VFS_ROOT(mp, &fsrootvp) == 0) {
609 if (mp->mnt_vnodecovered != NULL)
610 checkdirs(mp->mnt_vnodecovered, fsrootvp);
611 if (rootvnode == NULL) {
612 rootvnode = fsrootvp;
617 if ((mp->mnt_flag & MNT_RDONLY) == 0 && mp->mnt_syncer == NULL)
618 (void) vfs_allocate_syncvnode(mp);
619 mtx_lock(&mountlist_mtx);
620 mp->mnt_kern_flag &= ~MNTK_UNMOUNT;
621 mp->mnt_flag |= async_flag;
622 lockmgr(&mp->mnt_lock, LK_RELEASE | LK_INTERLOCK,
624 if (mp->mnt_kern_flag & MNTK_MWAIT)
628 mtx_lock(&mountlist_mtx);
629 TAILQ_REMOVE(&mountlist, mp, mnt_list);
630 if ((coveredvp = mp->mnt_vnodecovered) != NULL)
631 coveredvp->v_mountedhere = NULL;
632 mp->mnt_vfc->vfc_refcount--;
633 if (!TAILQ_EMPTY(&mp->mnt_nvnodelist))
634 panic("unmount: dangling vnode");
635 lockmgr(&mp->mnt_lock, LK_RELEASE | LK_INTERLOCK, &mountlist_mtx, td);
636 lockdestroy(&mp->mnt_lock);
637 if (coveredvp != NULL)
639 if (mp->mnt_kern_flag & MNTK_MWAIT)
641 free((caddr_t)mp, M_MOUNT);
646 * Sync each mounted filesystem.
648 #ifndef _SYS_SYSPROTO_H_
655 static int syncprt = 0;
656 SYSCTL_INT(_debug, OID_AUTO, syncprt, CTLFLAG_RW, &syncprt, 0, "");
663 struct sync_args *uap;
665 struct mount *mp, *nmp;
668 mtx_lock(&mountlist_mtx);
669 for (mp = TAILQ_FIRST(&mountlist); mp != NULL; mp = nmp) {
670 if (vfs_busy(mp, LK_NOWAIT, &mountlist_mtx, td)) {
671 nmp = TAILQ_NEXT(mp, mnt_list);
674 if ((mp->mnt_flag & MNT_RDONLY) == 0 &&
675 vn_start_write(NULL, &mp, V_NOWAIT) == 0) {
676 asyncflag = mp->mnt_flag & MNT_ASYNC;
677 mp->mnt_flag &= ~MNT_ASYNC;
678 vfs_msync(mp, MNT_NOWAIT);
679 VFS_SYNC(mp, MNT_NOWAIT,
680 ((td != NULL) ? td->td_ucred : NOCRED), td);
681 mp->mnt_flag |= asyncflag;
682 vn_finished_write(mp);
684 mtx_lock(&mountlist_mtx);
685 nmp = TAILQ_NEXT(mp, mnt_list);
688 mtx_unlock(&mountlist_mtx);
691 * XXX don't call vfs_bufstats() yet because that routine
692 * was not imported in the Lite2 merge.
697 #endif /* DIAGNOSTIC */
702 /* XXX PRISON: could be per prison flag */
703 static int prison_quotas;
705 SYSCTL_INT(_kern_prison, OID_AUTO, quotas, CTLFLAG_RW, &prison_quotas, 0, "");
709 * Change filesystem quotas.
711 #ifndef _SYS_SYSPROTO_H_
712 struct quotactl_args {
723 register struct quotactl_args /* {
724 syscallarg(char *) path;
727 syscallarg(caddr_t) arg;
734 if (jailed(td->td_ucred) && !prison_quotas)
736 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td);
737 if ((error = namei(&nd)) != 0)
739 NDFREE(&nd, NDF_ONLY_PNBUF);
740 error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH);
744 error = VFS_QUOTACTL(mp, SCARG(uap, cmd), SCARG(uap, uid),
745 SCARG(uap, arg), td);
746 vn_finished_write(mp);
751 * Get filesystem statistics.
753 #ifndef _SYS_SYSPROTO_H_
763 register struct statfs_args /* {
764 syscallarg(char *) path;
765 syscallarg(struct statfs *) buf;
768 register struct mount *mp;
769 register struct statfs *sp;
774 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td);
775 if ((error = namei(&nd)) != 0)
777 mp = nd.ni_vp->v_mount;
779 NDFREE(&nd, NDF_ONLY_PNBUF);
781 error = VFS_STATFS(mp, sp, td);
784 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
785 if (suser_xxx(td->td_ucred, 0, 0)) {
786 bcopy((caddr_t)sp, (caddr_t)&sb, sizeof(sb));
787 sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0;
790 return (copyout((caddr_t)sp, (caddr_t)SCARG(uap, buf), sizeof(*sp)));
794 * Get filesystem statistics.
796 #ifndef _SYS_SYSPROTO_H_
797 struct fstatfs_args {
806 register struct fstatfs_args /* {
808 syscallarg(struct statfs *) buf;
813 register struct statfs *sp;
817 if ((error = getvnode(td->td_proc->p_fd, SCARG(uap, fd), &fp)) != 0)
819 mp = ((struct vnode *)fp->f_data)->v_mount;
824 error = VFS_STATFS(mp, sp, td);
827 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
828 if (suser_xxx(td->td_ucred, 0, 0)) {
829 bcopy((caddr_t)sp, (caddr_t)&sb, sizeof(sb));
830 sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0;
833 return (copyout((caddr_t)sp, (caddr_t)SCARG(uap, buf), sizeof(*sp)));
837 * Get statistics on all filesystems.
839 #ifndef _SYS_SYSPROTO_H_
840 struct getfsstat_args {
849 register struct getfsstat_args /* {
850 syscallarg(struct statfs *) buf;
851 syscallarg(long) bufsize;
852 syscallarg(int) flags;
855 register struct mount *mp, *nmp;
856 register struct statfs *sp;
858 long count, maxcount, error;
860 maxcount = SCARG(uap, bufsize) / sizeof(struct statfs);
861 sfsp = (caddr_t)SCARG(uap, buf);
863 mtx_lock(&mountlist_mtx);
864 for (mp = TAILQ_FIRST(&mountlist); mp != NULL; mp = nmp) {
865 if (vfs_busy(mp, LK_NOWAIT, &mountlist_mtx, td)) {
866 nmp = TAILQ_NEXT(mp, mnt_list);
869 if (sfsp && count < maxcount) {
872 * If MNT_NOWAIT or MNT_LAZY is specified, do not
873 * refresh the fsstat cache. MNT_NOWAIT or MNT_LAZY
874 * overrides MNT_WAIT.
876 if (((SCARG(uap, flags) & (MNT_LAZY|MNT_NOWAIT)) == 0 ||
877 (SCARG(uap, flags) & MNT_WAIT)) &&
878 (error = VFS_STATFS(mp, sp, td))) {
879 mtx_lock(&mountlist_mtx);
880 nmp = TAILQ_NEXT(mp, mnt_list);
884 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
885 error = copyout((caddr_t)sp, sfsp, sizeof(*sp));
893 mtx_lock(&mountlist_mtx);
894 nmp = TAILQ_NEXT(mp, mnt_list);
897 mtx_unlock(&mountlist_mtx);
898 if (sfsp && count > maxcount)
899 td->td_retval[0] = maxcount;
901 td->td_retval[0] = count;
906 * Change current working directory to a given file descriptor.
908 #ifndef _SYS_SYSPROTO_H_
917 struct fchdir_args /* {
921 register struct filedesc *fdp = td->td_proc->p_fd;
922 struct vnode *vp, *tdp, *vpold;
927 if ((error = getvnode(fdp, SCARG(uap, fd), &fp)) != 0)
929 vp = (struct vnode *)fp->f_data;
932 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
933 if (vp->v_type != VDIR)
936 error = VOP_ACCESS(vp, VEXEC, td->td_ucred, td);
937 while (!error && (mp = vp->v_mountedhere) != NULL) {
938 if (vfs_busy(mp, 0, 0, td))
940 error = VFS_ROOT(mp, &tdp);
951 VOP_UNLOCK(vp, 0, td);
953 vpold = fdp->fd_cdir;
955 FILEDESC_UNLOCK(fdp);
961 * Change current working directory (``.'').
963 #ifndef _SYS_SYSPROTO_H_
972 struct chdir_args /* {
973 syscallarg(char *) path;
976 register struct filedesc *fdp = td->td_proc->p_fd;
981 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
982 SCARG(uap, path), td);
983 if ((error = change_dir(&nd, td)) != 0)
985 NDFREE(&nd, NDF_ONLY_PNBUF);
988 fdp->fd_cdir = nd.ni_vp;
989 FILEDESC_UNLOCK(fdp);
995 * Helper function for raised chroot(2) security function: Refuse if
996 * any filedescriptors are open directories.
999 chroot_refuse_vdir_fds(fdp)
1000 struct filedesc *fdp;
1007 for (fd = 0; fd < fdp->fd_nfiles ; fd++) {
1008 fp = fget_locked(fdp, fd);
1011 if (fp->f_type == DTYPE_VNODE) {
1012 vp = (struct vnode *)fp->f_data;
1013 if (vp->v_type == VDIR) {
1014 FILEDESC_UNLOCK(fdp);
1019 FILEDESC_UNLOCK(fdp);
1024 * This sysctl determines if we will allow a process to chroot(2) if it
1025 * has a directory open:
1026 * 0: disallowed for all processes.
1027 * 1: allowed for processes that were not already chroot(2)'ed.
1028 * 2: allowed for all processes.
1031 static int chroot_allow_open_directories = 1;
1033 SYSCTL_INT(_kern, OID_AUTO, chroot_allow_open_directories, CTLFLAG_RW,
1034 &chroot_allow_open_directories, 0, "");
1037 * Change notion of root (``/'') directory.
1039 #ifndef _SYS_SYSPROTO_H_
1040 struct chroot_args {
1048 struct chroot_args /* {
1049 syscallarg(char *) path;
1052 register struct filedesc *fdp = td->td_proc->p_fd;
1054 struct nameidata nd;
1057 error = suser_xxx(0, td->td_proc, PRISON_ROOT);
1061 if (chroot_allow_open_directories == 0 ||
1062 (chroot_allow_open_directories == 1 && fdp->fd_rdir != rootvnode)) {
1063 FILEDESC_UNLOCK(fdp);
1064 error = chroot_refuse_vdir_fds(fdp);
1066 FILEDESC_UNLOCK(fdp);
1069 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
1070 SCARG(uap, path), td);
1071 if ((error = change_dir(&nd, td)) != 0)
1073 NDFREE(&nd, NDF_ONLY_PNBUF);
1076 fdp->fd_rdir = nd.ni_vp;
1077 if (!fdp->fd_jdir) {
1078 fdp->fd_jdir = nd.ni_vp;
1081 FILEDESC_UNLOCK(fdp);
1087 * Common routine for chroot and chdir.
1091 register struct nameidata *ndp;
1101 if (vp->v_type != VDIR)
1104 error = VOP_ACCESS(vp, VEXEC, td->td_ucred, td);
1108 VOP_UNLOCK(vp, 0, td);
1113 * Check permissions, allocate an open file structure,
1114 * and call the device open routine if any.
1116 #ifndef _SYS_SYSPROTO_H_
1126 register struct open_args /* {
1127 syscallarg(char *) path;
1128 syscallarg(int) flags;
1129 syscallarg(int) mode;
1132 struct proc *p = td->td_proc;
1133 struct filedesc *fdp = p->p_fd;
1138 int cmode, flags, oflags;
1140 int type, indx, error;
1142 struct nameidata nd;
1144 oflags = SCARG(uap, flags);
1145 if ((oflags & O_ACCMODE) == O_ACCMODE)
1147 flags = FFLAGS(oflags);
1148 error = falloc(td, &nfp, &indx);
1153 cmode = ((SCARG(uap, mode) &~ fdp->fd_cmask) & ALLPERMS) &~ S_ISTXT;
1154 FILEDESC_UNLOCK(fdp);
1155 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td);
1156 td->td_dupfd = -indx - 1; /* XXX check for fdopen */
1158 * Bump the ref count to prevent another process from closing
1159 * the descriptor while we are blocked in vn_open()
1162 error = vn_open(&nd, &flags, cmode);
1165 * release our own reference
1170 * handle special fdopen() case. bleh. dupfdopen() is
1171 * responsible for dropping the old contents of ofiles[indx]
1174 if ((error == ENODEV || error == ENXIO) &&
1175 td->td_dupfd >= 0 && /* XXX from fdopen */
1177 dupfdopen(td, fdp, indx, td->td_dupfd, flags, error)) == 0) {
1178 td->td_retval[0] = indx;
1182 * Clean up the descriptor, but only if another thread hadn't
1183 * replaced or closed it.
1186 if (fdp->fd_ofiles[indx] == fp) {
1187 fdp->fd_ofiles[indx] = NULL;
1188 FILEDESC_UNLOCK(fdp);
1191 FILEDESC_UNLOCK(fdp);
1193 if (error == ERESTART)
1198 NDFREE(&nd, NDF_ONLY_PNBUF);
1202 * There should be 2 references on the file, one from the descriptor
1203 * table, and one for us.
1205 * Handle the case where someone closed the file (via its file
1206 * descriptor) while we were blocked. The end result should look
1207 * like opening the file succeeded but it was immediately closed.
1211 if (fp->f_count == 1) {
1212 KASSERT(fdp->fd_ofiles[indx] != fp,
1213 ("Open file descriptor lost all refs"));
1214 FILEDESC_UNLOCK(fdp);
1216 VOP_UNLOCK(vp, 0, td);
1217 vn_close(vp, flags & FMASK, fp->f_cred, td);
1219 td->td_retval[0] = indx;
1223 fp->f_data = (caddr_t)vp;
1224 fp->f_flag = flags & FMASK;
1226 fp->f_type = (vp->v_type == VFIFO ? DTYPE_FIFO : DTYPE_VNODE);
1227 FILEDESC_UNLOCK(fdp);
1229 VOP_UNLOCK(vp, 0, td);
1230 if (flags & (O_EXLOCK | O_SHLOCK)) {
1231 lf.l_whence = SEEK_SET;
1234 if (flags & O_EXLOCK)
1235 lf.l_type = F_WRLCK;
1237 lf.l_type = F_RDLCK;
1239 if ((flags & FNONBLOCK) == 0)
1241 if ((error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type)) != 0)
1243 fp->f_flag |= FHASLOCK;
1245 if (flags & O_TRUNC) {
1246 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
1248 VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
1251 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
1252 error = VOP_SETATTR(vp, &vat, td->td_ucred, td);
1253 VOP_UNLOCK(vp, 0, td);
1254 vn_finished_write(mp);
1258 /* assert that vn_open created a backing object if one is needed */
1259 KASSERT(!vn_canvmio(vp) || VOP_GETVOBJECT(vp, NULL) == 0,
1260 ("open: vmio vnode has no backing object after vn_open"));
1262 * Release our private reference, leaving the one associated with
1263 * the descriptor table intact.
1266 td->td_retval[0] = indx;
1270 if (fdp->fd_ofiles[indx] == fp) {
1271 fdp->fd_ofiles[indx] = NULL;
1272 FILEDESC_UNLOCK(fdp);
1275 FILEDESC_UNLOCK(fdp);
1283 #ifndef _SYS_SYSPROTO_H_
1284 struct ocreat_args {
1292 register struct ocreat_args /* {
1293 syscallarg(char *) path;
1294 syscallarg(int) mode;
1297 struct open_args /* {
1298 syscallarg(char *) path;
1299 syscallarg(int) flags;
1300 syscallarg(int) mode;
1303 SCARG(&nuap, path) = SCARG(uap, path);
1304 SCARG(&nuap, mode) = SCARG(uap, mode);
1305 SCARG(&nuap, flags) = O_WRONLY | O_CREAT | O_TRUNC;
1306 return (open(td, &nuap));
1308 #endif /* COMPAT_43 */
1311 * Create a special file.
1313 #ifndef _SYS_SYSPROTO_H_
1324 register struct mknod_args /* {
1325 syscallarg(char *) path;
1326 syscallarg(int) mode;
1327 syscallarg(int) dev;
1335 struct nameidata nd;
1337 switch (SCARG(uap, mode) & S_IFMT) {
1340 error = suser_td(td);
1343 error = suser_xxx(0, td->td_proc, PRISON_ROOT);
1350 NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), td);
1351 if ((error = namei(&nd)) != 0)
1359 FILEDESC_LOCK(td->td_proc->p_fd);
1360 vattr.va_mode = (SCARG(uap, mode) & ALLPERMS) &~ td->td_proc->p_fd->fd_cmask;
1361 FILEDESC_UNLOCK(td->td_proc->p_fd);
1362 vattr.va_rdev = SCARG(uap, dev);
1365 switch (SCARG(uap, mode) & S_IFMT) {
1366 case S_IFMT: /* used by badsect to flag bad sectors */
1367 vattr.va_type = VBAD;
1370 vattr.va_type = VCHR;
1373 vattr.va_type = VBLK;
1383 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) {
1384 NDFREE(&nd, NDF_ONLY_PNBUF);
1386 if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0)
1391 VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
1393 error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, CREATE);
1395 error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp,
1396 &nd.ni_cnd, &vattr);
1401 NDFREE(&nd, NDF_ONLY_PNBUF);
1403 vn_finished_write(mp);
1404 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "mknod");
1405 ASSERT_VOP_UNLOCKED(nd.ni_vp, "mknod");
1410 * Create a named pipe.
1412 #ifndef _SYS_SYSPROTO_H_
1413 struct mkfifo_args {
1422 register struct mkfifo_args /* {
1423 syscallarg(char *) path;
1424 syscallarg(int) mode;
1430 struct nameidata nd;
1434 NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), td);
1435 if ((error = namei(&nd)) != 0)
1437 if (nd.ni_vp != NULL) {
1438 NDFREE(&nd, NDF_ONLY_PNBUF);
1443 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) {
1444 NDFREE(&nd, NDF_ONLY_PNBUF);
1446 if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0)
1451 vattr.va_type = VFIFO;
1452 FILEDESC_LOCK(td->td_proc->p_fd);
1453 vattr.va_mode = (SCARG(uap, mode) & ALLPERMS) &~ td->td_proc->p_fd->fd_cmask;
1454 FILEDESC_UNLOCK(td->td_proc->p_fd);
1455 VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
1456 error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
1459 NDFREE(&nd, NDF_ONLY_PNBUF);
1461 vn_finished_write(mp);
1466 * Make a hard file link.
1468 #ifndef _SYS_SYSPROTO_H_
1478 register struct link_args /* {
1479 syscallarg(char *) path;
1480 syscallarg(char *) link;
1485 struct nameidata nd;
1489 NDINIT(&nd, LOOKUP, FOLLOW|NOOBJ, UIO_USERSPACE, SCARG(uap, path), td);
1490 if ((error = namei(&nd)) != 0)
1492 NDFREE(&nd, NDF_ONLY_PNBUF);
1494 if (vp->v_type == VDIR) {
1496 return (EPERM); /* POSIX */
1498 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) {
1502 NDINIT(&nd, CREATE, LOCKPARENT|NOOBJ, UIO_USERSPACE, SCARG(uap, link), td);
1503 if ((error = namei(&nd)) == 0) {
1504 if (nd.ni_vp != NULL) {
1508 VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
1509 VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
1510 error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd);
1512 NDFREE(&nd, NDF_ONLY_PNBUF);
1516 vn_finished_write(mp);
1517 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "link");
1518 ASSERT_VOP_UNLOCKED(nd.ni_vp, "link");
1523 * Make a symbolic link.
1525 #ifndef _SYS_SYSPROTO_H_
1526 struct symlink_args {
1535 register struct symlink_args /* {
1536 syscallarg(char *) path;
1537 syscallarg(char *) link;
1544 struct nameidata nd;
1546 path = uma_zalloc(namei_zone, M_WAITOK);
1547 if ((error = copyinstr(SCARG(uap, path), path, MAXPATHLEN, NULL)) != 0)
1551 NDINIT(&nd, CREATE, LOCKPARENT|NOOBJ, UIO_USERSPACE, SCARG(uap, link), td);
1552 if ((error = namei(&nd)) != 0)
1555 NDFREE(&nd, NDF_ONLY_PNBUF);
1561 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) {
1562 NDFREE(&nd, NDF_ONLY_PNBUF);
1564 if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0)
1569 FILEDESC_LOCK(td->td_proc->p_fd);
1570 vattr.va_mode = ACCESSPERMS &~ td->td_proc->p_fd->fd_cmask;
1571 FILEDESC_UNLOCK(td->td_proc->p_fd);
1572 VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
1573 error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr, path);
1574 NDFREE(&nd, NDF_ONLY_PNBUF);
1578 vn_finished_write(mp);
1579 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "symlink");
1580 ASSERT_VOP_UNLOCKED(nd.ni_vp, "symlink");
1582 uma_zfree(namei_zone, path);
1587 * Delete a whiteout from the filesystem.
1593 register struct undelete_args /* {
1594 syscallarg(char *) path;
1599 struct nameidata nd;
1603 NDINIT(&nd, DELETE, LOCKPARENT|DOWHITEOUT, UIO_USERSPACE,
1604 SCARG(uap, path), td);
1609 if (nd.ni_vp != NULLVP || !(nd.ni_cnd.cn_flags & ISWHITEOUT)) {
1610 NDFREE(&nd, NDF_ONLY_PNBUF);
1616 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) {
1617 NDFREE(&nd, NDF_ONLY_PNBUF);
1619 if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0)
1623 VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
1624 error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, DELETE);
1625 NDFREE(&nd, NDF_ONLY_PNBUF);
1627 vn_finished_write(mp);
1628 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "undelete");
1629 ASSERT_VOP_UNLOCKED(nd.ni_vp, "undelete");
1634 * Delete a name from the filesystem.
1636 #ifndef _SYS_SYSPROTO_H_
1637 struct unlink_args {
1645 struct unlink_args /* {
1646 syscallarg(char *) path;
1652 struct nameidata nd;
1656 NDINIT(&nd, DELETE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), td);
1657 if ((error = namei(&nd)) != 0)
1660 if (vp->v_type == VDIR)
1661 error = EPERM; /* POSIX */
1664 * The root of a mounted filesystem cannot be deleted.
1666 * XXX: can this only be a VDIR case?
1668 if (vp->v_flag & VROOT)
1671 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) {
1672 NDFREE(&nd, NDF_ONLY_PNBUF);
1675 if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0)
1679 VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
1680 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
1682 VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
1683 error = VOP_REMOVE(nd.ni_dvp, vp, &nd.ni_cnd);
1685 NDFREE(&nd, NDF_ONLY_PNBUF);
1688 vn_finished_write(mp);
1689 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "unlink");
1690 ASSERT_VOP_UNLOCKED(nd.ni_vp, "unlink");
1695 * Reposition read/write file offset.
1697 #ifndef _SYS_SYSPROTO_H_
1708 register struct lseek_args /* {
1710 syscallarg(int) pad;
1711 syscallarg(off_t) offset;
1712 syscallarg(int) whence;
1715 struct ucred *cred = td->td_ucred;
1722 if ((error = fget(td, uap->fd, &fp)) != 0)
1724 if (fp->f_type != DTYPE_VNODE) {
1728 vp = (struct vnode *)fp->f_data;
1729 noneg = (vp->v_type != VCHR);
1730 offset = SCARG(uap, offset);
1731 switch (SCARG(uap, whence)) {
1734 (fp->f_offset < 0 ||
1735 (offset > 0 && fp->f_offset > OFF_MAX - offset)))
1737 offset += fp->f_offset;
1740 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
1741 error = VOP_GETATTR(vp, &vattr, cred, td);
1742 VOP_UNLOCK(vp, 0, td);
1746 (vattr.va_size > OFF_MAX ||
1747 (offset > 0 && vattr.va_size > OFF_MAX - offset)))
1749 offset += vattr.va_size;
1757 if (noneg && offset < 0)
1759 fp->f_offset = offset;
1760 *(off_t *)(td->td_retval) = fp->f_offset;
1765 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
1767 * Reposition read/write file offset.
1769 #ifndef _SYS_SYSPROTO_H_
1770 struct olseek_args {
1779 register struct olseek_args /* {
1781 syscallarg(long) offset;
1782 syscallarg(int) whence;
1785 struct lseek_args /* {
1787 syscallarg(int) pad;
1788 syscallarg(off_t) offset;
1789 syscallarg(int) whence;
1793 SCARG(&nuap, fd) = SCARG(uap, fd);
1794 SCARG(&nuap, offset) = SCARG(uap, offset);
1795 SCARG(&nuap, whence) = SCARG(uap, whence);
1796 error = lseek(td, &nuap);
1799 #endif /* COMPAT_43 */
1802 * Check access permissions using passed credentials.
1805 vn_access(vp, user_flags, cred, td)
1813 /* Flags == 0 means only check for existence. */
1817 if (user_flags & R_OK)
1819 if (user_flags & W_OK)
1821 if (user_flags & X_OK)
1823 if ((flags & VWRITE) == 0 || (error = vn_writechk(vp)) == 0)
1824 error = VOP_ACCESS(vp, flags, cred, td);
1830 * Check access permissions using "real" credentials.
1832 #ifndef _SYS_SYSPROTO_H_
1833 struct access_args {
1841 register struct access_args /* {
1842 syscallarg(char *) path;
1843 syscallarg(int) flags;
1846 struct ucred *cred, *tmpcred;
1847 register struct vnode *vp;
1849 struct nameidata nd;
1852 * Create and modify a temporary credential instead of one that
1853 * is potentially shared. This could also mess up socket
1854 * buffer accounting which can run in an interrupt context.
1856 * XXX - Depending on how "threads" are finally implemented, it
1857 * may be better to explicitly pass the credential to namei()
1858 * rather than to modify the potentially shared process structure.
1860 cred = td->td_ucred;
1861 tmpcred = crdup(cred);
1862 tmpcred->cr_uid = cred->cr_ruid;
1863 tmpcred->cr_groups[0] = cred->cr_rgid;
1864 td->td_ucred = tmpcred;
1865 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
1866 SCARG(uap, path), td);
1867 if ((error = namei(&nd)) != 0)
1871 error = vn_access(vp, SCARG(uap, flags), tmpcred, td);
1872 NDFREE(&nd, NDF_ONLY_PNBUF);
1875 td->td_ucred = cred;
1881 * Check access permissions using "effective" credentials.
1883 #ifndef _SYS_SYSPROTO_H_
1884 struct eaccess_args {
1892 register struct eaccess_args /* {
1893 syscallarg(char *) path;
1894 syscallarg(int) flags;
1897 struct nameidata nd;
1901 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
1902 SCARG(uap, path), td);
1903 if ((error = namei(&nd)) != 0)
1907 error = vn_access(vp, SCARG(uap, flags), td->td_ucred, td);
1908 NDFREE(&nd, NDF_ONLY_PNBUF);
1913 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
1915 * Get file status; this version follows links.
1917 #ifndef _SYS_SYSPROTO_H_
1927 register struct ostat_args /* {
1928 syscallarg(char *) path;
1929 syscallarg(struct ostat *) ub;
1935 struct nameidata nd;
1937 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
1938 SCARG(uap, path), td);
1939 if ((error = namei(&nd)) != 0)
1941 NDFREE(&nd, NDF_ONLY_PNBUF);
1942 error = vn_stat(nd.ni_vp, &sb, td);
1947 error = copyout((caddr_t)&osb, (caddr_t)SCARG(uap, ub), sizeof (osb));
1952 * Get file status; this version does not follow links.
1954 #ifndef _SYS_SYSPROTO_H_
1955 struct olstat_args {
1964 register struct olstat_args /* {
1965 syscallarg(char *) path;
1966 syscallarg(struct ostat *) ub;
1973 struct nameidata nd;
1975 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
1976 SCARG(uap, path), td);
1977 if ((error = namei(&nd)) != 0)
1980 error = vn_stat(vp, &sb, td);
1981 NDFREE(&nd, NDF_ONLY_PNBUF);
1986 error = copyout((caddr_t)&osb, (caddr_t)SCARG(uap, ub), sizeof (osb));
1991 * Convert from an old to a new stat structure.
1999 ost->st_dev = st->st_dev;
2000 ost->st_ino = st->st_ino;
2001 ost->st_mode = st->st_mode;
2002 ost->st_nlink = st->st_nlink;
2003 ost->st_uid = st->st_uid;
2004 ost->st_gid = st->st_gid;
2005 ost->st_rdev = st->st_rdev;
2006 if (st->st_size < (quad_t)1 << 32)
2007 ost->st_size = st->st_size;
2010 ost->st_atime = st->st_atime;
2011 ost->st_mtime = st->st_mtime;
2012 ost->st_ctime = st->st_ctime;
2013 ost->st_blksize = st->st_blksize;
2014 ost->st_blocks = st->st_blocks;
2015 ost->st_flags = st->st_flags;
2016 ost->st_gen = st->st_gen;
2018 #endif /* COMPAT_43 || COMPAT_SUNOS */
2021 * Get file status; this version follows links.
2023 #ifndef _SYS_SYSPROTO_H_
2033 register struct stat_args /* {
2034 syscallarg(char *) path;
2035 syscallarg(struct stat *) ub;
2040 struct nameidata nd;
2042 #ifdef LOOKUP_SHARED
2043 NDINIT(&nd, LOOKUP, FOLLOW | LOCKSHARED | LOCKLEAF | NOOBJ,
2044 UIO_USERSPACE, SCARG(uap, path), td);
2046 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
2047 SCARG(uap, path), td);
2049 if ((error = namei(&nd)) != 0)
2051 error = vn_stat(nd.ni_vp, &sb, td);
2052 NDFREE(&nd, NDF_ONLY_PNBUF);
2056 error = copyout((caddr_t)&sb, (caddr_t)SCARG(uap, ub), sizeof (sb));
2061 * Get file status; this version does not follow links.
2063 #ifndef _SYS_SYSPROTO_H_
2073 register struct lstat_args /* {
2074 syscallarg(char *) path;
2075 syscallarg(struct stat *) ub;
2081 struct nameidata nd;
2083 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
2084 SCARG(uap, path), td);
2085 if ((error = namei(&nd)) != 0)
2088 error = vn_stat(vp, &sb, td);
2089 NDFREE(&nd, NDF_ONLY_PNBUF);
2093 error = copyout((caddr_t)&sb, (caddr_t)SCARG(uap, ub), sizeof (sb));
2098 * Implementation of the NetBSD stat() function.
2099 * XXX This should probably be collapsed with the FreeBSD version,
2100 * as the differences are only due to vn_stat() clearing spares at
2101 * the end of the structures. vn_stat could be split to avoid this,
2102 * and thus collapse the following to close to zero code.
2109 nsb->st_dev = sb->st_dev;
2110 nsb->st_ino = sb->st_ino;
2111 nsb->st_mode = sb->st_mode;
2112 nsb->st_nlink = sb->st_nlink;
2113 nsb->st_uid = sb->st_uid;
2114 nsb->st_gid = sb->st_gid;
2115 nsb->st_rdev = sb->st_rdev;
2116 nsb->st_atimespec = sb->st_atimespec;
2117 nsb->st_mtimespec = sb->st_mtimespec;
2118 nsb->st_ctimespec = sb->st_ctimespec;
2119 nsb->st_size = sb->st_size;
2120 nsb->st_blocks = sb->st_blocks;
2121 nsb->st_blksize = sb->st_blksize;
2122 nsb->st_flags = sb->st_flags;
2123 nsb->st_gen = sb->st_gen;
2124 nsb->st_qspare[0] = sb->st_qspare[0];
2125 nsb->st_qspare[1] = sb->st_qspare[1];
2128 #ifndef _SYS_SYSPROTO_H_
2138 register struct nstat_args /* {
2139 syscallarg(char *) path;
2140 syscallarg(struct nstat *) ub;
2146 struct nameidata nd;
2148 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
2149 SCARG(uap, path), td);
2150 if ((error = namei(&nd)) != 0)
2152 NDFREE(&nd, NDF_ONLY_PNBUF);
2153 error = vn_stat(nd.ni_vp, &sb, td);
2157 cvtnstat(&sb, &nsb);
2158 error = copyout((caddr_t)&nsb, (caddr_t)SCARG(uap, ub), sizeof (nsb));
2163 * NetBSD lstat. Get file status; this version does not follow links.
2165 #ifndef _SYS_SYSPROTO_H_
2175 register struct nlstat_args /* {
2176 syscallarg(char *) path;
2177 syscallarg(struct nstat *) ub;
2184 struct nameidata nd;
2186 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
2187 SCARG(uap, path), td);
2188 if ((error = namei(&nd)) != 0)
2191 NDFREE(&nd, NDF_ONLY_PNBUF);
2192 error = vn_stat(vp, &sb, td);
2196 cvtnstat(&sb, &nsb);
2197 error = copyout((caddr_t)&nsb, (caddr_t)SCARG(uap, ub), sizeof (nsb));
2202 * Get configurable pathname variables.
2204 #ifndef _SYS_SYSPROTO_H_
2205 struct pathconf_args {
2214 register struct pathconf_args /* {
2215 syscallarg(char *) path;
2216 syscallarg(int) name;
2220 struct nameidata nd;
2222 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
2223 SCARG(uap, path), td);
2224 if ((error = namei(&nd)) != 0)
2226 NDFREE(&nd, NDF_ONLY_PNBUF);
2227 error = VOP_PATHCONF(nd.ni_vp, SCARG(uap, name), td->td_retval);
2233 * Return target name of a symbolic link.
2235 #ifndef _SYS_SYSPROTO_H_
2236 struct readlink_args {
2246 register struct readlink_args /* {
2247 syscallarg(char *) path;
2248 syscallarg(char *) buf;
2249 syscallarg(int) count;
2252 register struct vnode *vp;
2256 struct nameidata nd;
2258 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
2259 SCARG(uap, path), td);
2260 if ((error = namei(&nd)) != 0)
2262 NDFREE(&nd, NDF_ONLY_PNBUF);
2264 if (vp->v_type != VLNK)
2267 aiov.iov_base = SCARG(uap, buf);
2268 aiov.iov_len = SCARG(uap, count);
2269 auio.uio_iov = &aiov;
2270 auio.uio_iovcnt = 1;
2271 auio.uio_offset = 0;
2272 auio.uio_rw = UIO_READ;
2273 auio.uio_segflg = UIO_USERSPACE;
2275 auio.uio_resid = SCARG(uap, count);
2276 error = VOP_READLINK(vp, &auio, td->td_ucred);
2279 td->td_retval[0] = SCARG(uap, count) - auio.uio_resid;
2284 * Common implementation code for chflags() and fchflags().
2287 setfflags(td, vp, flags)
2297 * Prevent non-root users from setting flags on devices. When
2298 * a device is reused, users can retain ownership of the device
2299 * if they are allowed to set flags and programs assume that
2300 * chown can't fail when done as root.
2302 if (vp->v_type == VCHR || vp->v_type == VBLK) {
2303 error = suser_xxx(td->td_ucred, td->td_proc, PRISON_ROOT);
2308 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
2310 VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
2311 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
2313 vattr.va_flags = flags;
2314 error = VOP_SETATTR(vp, &vattr, td->td_ucred, td);
2315 VOP_UNLOCK(vp, 0, td);
2316 vn_finished_write(mp);
2321 * Change flags of a file given a path name.
2323 #ifndef _SYS_SYSPROTO_H_
2324 struct chflags_args {
2333 register struct chflags_args /* {
2334 syscallarg(char *) path;
2335 syscallarg(int) flags;
2339 struct nameidata nd;
2341 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td);
2342 if ((error = namei(&nd)) != 0)
2344 NDFREE(&nd, NDF_ONLY_PNBUF);
2345 error = setfflags(td, nd.ni_vp, SCARG(uap, flags));
2351 * Change flags of a file given a file descriptor.
2353 #ifndef _SYS_SYSPROTO_H_
2354 struct fchflags_args {
2363 register struct fchflags_args /* {
2365 syscallarg(int) flags;
2371 if ((error = getvnode(td->td_proc->p_fd, SCARG(uap, fd), &fp)) != 0)
2373 error = setfflags(td, (struct vnode *) fp->f_data, SCARG(uap, flags));
2379 * Common implementation code for chmod(), lchmod() and fchmod().
2382 setfmode(td, vp, mode)
2391 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
2393 VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
2394 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
2396 vattr.va_mode = mode & ALLPERMS;
2397 error = VOP_SETATTR(vp, &vattr, td->td_ucred, td);
2398 VOP_UNLOCK(vp, 0, td);
2399 vn_finished_write(mp);
2404 * Change mode of a file given path name.
2406 #ifndef _SYS_SYSPROTO_H_
2416 register struct chmod_args /* {
2417 syscallarg(char *) path;
2418 syscallarg(int) mode;
2422 struct nameidata nd;
2424 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td);
2425 if ((error = namei(&nd)) != 0)
2427 NDFREE(&nd, NDF_ONLY_PNBUF);
2428 error = setfmode(td, nd.ni_vp, SCARG(uap, mode));
2434 * Change mode of a file given path name (don't follow links.)
2436 #ifndef _SYS_SYSPROTO_H_
2437 struct lchmod_args {
2446 register struct lchmod_args /* {
2447 syscallarg(char *) path;
2448 syscallarg(int) mode;
2452 struct nameidata nd;
2454 NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), td);
2455 if ((error = namei(&nd)) != 0)
2457 NDFREE(&nd, NDF_ONLY_PNBUF);
2458 error = setfmode(td, nd.ni_vp, SCARG(uap, mode));
2464 * Change mode of a file given a file descriptor.
2466 #ifndef _SYS_SYSPROTO_H_
2467 struct fchmod_args {
2476 register struct fchmod_args /* {
2478 syscallarg(int) mode;
2485 if ((error = getvnode(td->td_proc->p_fd, SCARG(uap, fd), &fp)) != 0)
2487 vp = (struct vnode *)fp->f_data;
2488 error = setfmode(td, (struct vnode *)fp->f_data, SCARG(uap, mode));
2494 * Common implementation for chown(), lchown(), and fchown()
2497 setfown(td, vp, uid, gid)
2507 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
2509 VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
2510 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
2514 error = VOP_SETATTR(vp, &vattr, td->td_ucred, td);
2515 VOP_UNLOCK(vp, 0, td);
2516 vn_finished_write(mp);
2521 * Set ownership given a path name.
2523 #ifndef _SYS_SYSPROTO_H_
2534 register struct chown_args /* {
2535 syscallarg(char *) path;
2536 syscallarg(int) uid;
2537 syscallarg(int) gid;
2541 struct nameidata nd;
2543 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td);
2544 if ((error = namei(&nd)) != 0)
2546 NDFREE(&nd, NDF_ONLY_PNBUF);
2547 error = setfown(td, nd.ni_vp, SCARG(uap, uid), SCARG(uap, gid));
2553 * Set ownership given a path name, do not cross symlinks.
2555 #ifndef _SYS_SYSPROTO_H_
2556 struct lchown_args {
2566 register struct lchown_args /* {
2567 syscallarg(char *) path;
2568 syscallarg(int) uid;
2569 syscallarg(int) gid;
2573 struct nameidata nd;
2575 NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), td);
2576 if ((error = namei(&nd)) != 0)
2578 NDFREE(&nd, NDF_ONLY_PNBUF);
2579 error = setfown(td, nd.ni_vp, SCARG(uap, uid), SCARG(uap, gid));
2585 * Set ownership given a file descriptor.
2587 #ifndef _SYS_SYSPROTO_H_
2588 struct fchown_args {
2598 register struct fchown_args /* {
2600 syscallarg(int) uid;
2601 syscallarg(int) gid;
2608 if ((error = getvnode(td->td_proc->p_fd, SCARG(uap, fd), &fp)) != 0)
2610 vp = (struct vnode *)fp->f_data;
2611 error = setfown(td, (struct vnode *)fp->f_data,
2612 SCARG(uap, uid), SCARG(uap, gid));
2618 * Common implementation code for utimes(), lutimes(), and futimes().
2621 getutimes(usrtvp, tsp)
2622 const struct timeval *usrtvp;
2623 struct timespec *tsp;
2625 struct timeval tv[2];
2628 if (usrtvp == NULL) {
2630 TIMEVAL_TO_TIMESPEC(&tv[0], &tsp[0]);
2633 if ((error = copyin(usrtvp, tv, sizeof (tv))) != 0)
2635 TIMEVAL_TO_TIMESPEC(&tv[0], &tsp[0]);
2636 TIMEVAL_TO_TIMESPEC(&tv[1], &tsp[1]);
2642 * Common implementation code for utimes(), lutimes(), and futimes().
2645 setutimes(td, vp, ts, nullflag)
2648 const struct timespec *ts;
2655 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
2657 VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
2658 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
2660 vattr.va_atime = ts[0];
2661 vattr.va_mtime = ts[1];
2663 vattr.va_vaflags |= VA_UTIMES_NULL;
2664 error = VOP_SETATTR(vp, &vattr, td->td_ucred, td);
2665 VOP_UNLOCK(vp, 0, td);
2666 vn_finished_write(mp);
2671 * Set the access and modification times of a file.
2673 #ifndef _SYS_SYSPROTO_H_
2674 struct utimes_args {
2676 struct timeval *tptr;
2683 register struct utimes_args /* {
2684 syscallarg(char *) path;
2685 syscallarg(struct timeval *) tptr;
2688 struct timespec ts[2];
2689 struct timeval *usrtvp;
2691 struct nameidata nd;
2693 usrtvp = SCARG(uap, tptr);
2694 if ((error = getutimes(usrtvp, ts)) != 0)
2696 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td);
2697 if ((error = namei(&nd)) != 0)
2699 NDFREE(&nd, NDF_ONLY_PNBUF);
2700 error = setutimes(td, nd.ni_vp, ts, usrtvp == NULL);
2706 * Set the access and modification times of a file.
2708 #ifndef _SYS_SYSPROTO_H_
2709 struct lutimes_args {
2711 struct timeval *tptr;
2718 register struct lutimes_args /* {
2719 syscallarg(char *) path;
2720 syscallarg(struct timeval *) tptr;
2723 struct timespec ts[2];
2724 struct timeval *usrtvp;
2726 struct nameidata nd;
2728 usrtvp = SCARG(uap, tptr);
2729 if ((error = getutimes(usrtvp, ts)) != 0)
2731 NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), td);
2732 if ((error = namei(&nd)) != 0)
2734 NDFREE(&nd, NDF_ONLY_PNBUF);
2735 error = setutimes(td, nd.ni_vp, ts, usrtvp == NULL);
2741 * Set the access and modification times of a file.
2743 #ifndef _SYS_SYSPROTO_H_
2744 struct futimes_args {
2746 struct timeval *tptr;
2753 register struct futimes_args /* {
2754 syscallarg(int ) fd;
2755 syscallarg(struct timeval *) tptr;
2758 struct timespec ts[2];
2760 struct timeval *usrtvp;
2763 usrtvp = SCARG(uap, tptr);
2764 if ((error = getutimes(usrtvp, ts)) != 0)
2766 if ((error = getvnode(td->td_proc->p_fd, SCARG(uap, fd), &fp)) != 0)
2768 error = setutimes(td, (struct vnode *)fp->f_data, ts, usrtvp == NULL);
2774 * Truncate a file given its path name.
2776 #ifndef _SYS_SYSPROTO_H_
2777 struct truncate_args {
2787 register struct truncate_args /* {
2788 syscallarg(char *) path;
2789 syscallarg(int) pad;
2790 syscallarg(off_t) length;
2797 struct nameidata nd;
2799 if (uap->length < 0)
2801 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td);
2802 if ((error = namei(&nd)) != 0)
2805 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) {
2809 NDFREE(&nd, NDF_ONLY_PNBUF);
2810 VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
2811 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
2812 if (vp->v_type == VDIR)
2814 else if ((error = vn_writechk(vp)) == 0 &&
2815 (error = VOP_ACCESS(vp, VWRITE, td->td_ucred, td)) == 0) {
2817 vattr.va_size = SCARG(uap, length);
2818 error = VOP_SETATTR(vp, &vattr, td->td_ucred, td);
2821 vn_finished_write(mp);
2826 * Truncate a file given a file descriptor.
2828 #ifndef _SYS_SYSPROTO_H_
2829 struct ftruncate_args {
2839 register struct ftruncate_args /* {
2841 syscallarg(int) pad;
2842 syscallarg(off_t) length;
2851 if (uap->length < 0)
2853 if ((error = getvnode(td->td_proc->p_fd, SCARG(uap, fd), &fp)) != 0)
2855 if ((fp->f_flag & FWRITE) == 0) {
2859 vp = (struct vnode *)fp->f_data;
2860 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) {
2864 VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
2865 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
2866 if (vp->v_type == VDIR)
2868 else if ((error = vn_writechk(vp)) == 0) {
2870 vattr.va_size = SCARG(uap, length);
2871 error = VOP_SETATTR(vp, &vattr, fp->f_cred, td);
2873 VOP_UNLOCK(vp, 0, td);
2874 vn_finished_write(mp);
2879 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
2881 * Truncate a file given its path name.
2883 #ifndef _SYS_SYSPROTO_H_
2884 struct otruncate_args {
2893 register struct otruncate_args /* {
2894 syscallarg(char *) path;
2895 syscallarg(long) length;
2898 struct truncate_args /* {
2899 syscallarg(char *) path;
2900 syscallarg(int) pad;
2901 syscallarg(off_t) length;
2904 SCARG(&nuap, path) = SCARG(uap, path);
2905 SCARG(&nuap, length) = SCARG(uap, length);
2906 return (truncate(td, &nuap));
2910 * Truncate a file given a file descriptor.
2912 #ifndef _SYS_SYSPROTO_H_
2913 struct oftruncate_args {
2922 register struct oftruncate_args /* {
2924 syscallarg(long) length;
2927 struct ftruncate_args /* {
2929 syscallarg(int) pad;
2930 syscallarg(off_t) length;
2933 SCARG(&nuap, fd) = SCARG(uap, fd);
2934 SCARG(&nuap, length) = SCARG(uap, length);
2935 return (ftruncate(td, &nuap));
2937 #endif /* COMPAT_43 || COMPAT_SUNOS */
2940 * Sync an open file.
2942 #ifndef _SYS_SYSPROTO_H_
2951 struct fsync_args /* {
2963 if ((error = getvnode(td->td_proc->p_fd, SCARG(uap, fd), &fp)) != 0)
2965 vp = (struct vnode *)fp->f_data;
2966 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) {
2970 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
2971 if (VOP_GETVOBJECT(vp, &obj) == 0) {
2972 vm_object_page_clean(obj, 0, 0, 0);
2974 error = VOP_FSYNC(vp, fp->f_cred, MNT_WAIT, td);
2976 if (error == 0 && vp->v_mount && (vp->v_mount->mnt_flag & MNT_SOFTDEP))
2977 error = softdep_fsync(vp);
2980 VOP_UNLOCK(vp, 0, td);
2981 vn_finished_write(mp);
2987 * Rename files. Source and destination must either both be directories,
2988 * or both not be directories. If target is a directory, it must be empty.
2990 #ifndef _SYS_SYSPROTO_H_
2991 struct rename_args {
3000 register struct rename_args /* {
3001 syscallarg(char *) from;
3002 syscallarg(char *) to;
3006 struct vnode *tvp, *fvp, *tdvp;
3007 struct nameidata fromnd, tond;
3011 NDINIT(&fromnd, DELETE, WANTPARENT | SAVESTART, UIO_USERSPACE,
3012 SCARG(uap, from), td);
3013 if ((error = namei(&fromnd)) != 0)
3016 if ((error = vn_start_write(fvp, &mp, V_WAIT | PCATCH)) != 0) {
3017 NDFREE(&fromnd, NDF_ONLY_PNBUF);
3018 vrele(fromnd.ni_dvp);
3022 NDINIT(&tond, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART | NOOBJ,
3023 UIO_USERSPACE, SCARG(uap, to), td);
3024 if (fromnd.ni_vp->v_type == VDIR)
3025 tond.ni_cnd.cn_flags |= WILLBEDIR;
3026 if ((error = namei(&tond)) != 0) {
3027 /* Translate error code for rename("dir1", "dir2/."). */
3028 if (error == EISDIR && fvp->v_type == VDIR)
3030 NDFREE(&fromnd, NDF_ONLY_PNBUF);
3031 vrele(fromnd.ni_dvp);
3038 if (fvp->v_type == VDIR && tvp->v_type != VDIR) {
3041 } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) {
3049 * If source is the same as the destination (that is the
3050 * same inode number with the same name in the same directory),
3051 * then there is nothing to do.
3053 if (fvp == tvp && fromnd.ni_dvp == tdvp &&
3054 fromnd.ni_cnd.cn_namelen == tond.ni_cnd.cn_namelen &&
3055 !bcmp(fromnd.ni_cnd.cn_nameptr, tond.ni_cnd.cn_nameptr,
3056 fromnd.ni_cnd.cn_namelen))
3060 VOP_LEASE(tdvp, td, td->td_ucred, LEASE_WRITE);
3061 if (fromnd.ni_dvp != tdvp) {
3062 VOP_LEASE(fromnd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
3065 VOP_LEASE(tvp, td, td->td_ucred, LEASE_WRITE);
3067 error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd,
3068 tond.ni_dvp, tond.ni_vp, &tond.ni_cnd);
3069 NDFREE(&fromnd, NDF_ONLY_PNBUF);
3070 NDFREE(&tond, NDF_ONLY_PNBUF);
3072 NDFREE(&fromnd, NDF_ONLY_PNBUF);
3073 NDFREE(&tond, NDF_ONLY_PNBUF);
3080 vrele(fromnd.ni_dvp);
3083 vrele(tond.ni_startdir);
3084 vn_finished_write(mp);
3085 ASSERT_VOP_UNLOCKED(fromnd.ni_dvp, "rename");
3086 ASSERT_VOP_UNLOCKED(fromnd.ni_vp, "rename");
3087 ASSERT_VOP_UNLOCKED(tond.ni_dvp, "rename");
3088 ASSERT_VOP_UNLOCKED(tond.ni_vp, "rename");
3090 if (fromnd.ni_startdir)
3091 vrele(fromnd.ni_startdir);
3098 * Make a directory file.
3100 #ifndef _SYS_SYSPROTO_H_
3110 register struct mkdir_args /* {
3111 syscallarg(char *) path;
3112 syscallarg(int) mode;
3116 return vn_mkdir(uap->path, uap->mode, UIO_USERSPACE, td);
3120 vn_mkdir(path, mode, segflg, td)
3123 enum uio_seg segflg;
3130 struct nameidata nd;
3134 NDINIT(&nd, CREATE, LOCKPARENT, segflg, path, td);
3135 nd.ni_cnd.cn_flags |= WILLBEDIR;
3136 if ((error = namei(&nd)) != 0)
3140 NDFREE(&nd, NDF_ONLY_PNBUF);
3145 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) {
3146 NDFREE(&nd, NDF_ONLY_PNBUF);
3148 if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0)
3153 vattr.va_type = VDIR;
3154 FILEDESC_LOCK(td->td_proc->p_fd);
3155 vattr.va_mode = (mode & ACCESSPERMS) &~ td->td_proc->p_fd->fd_cmask;
3156 FILEDESC_UNLOCK(td->td_proc->p_fd);
3157 VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
3158 error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
3159 NDFREE(&nd, NDF_ONLY_PNBUF);
3163 vn_finished_write(mp);
3164 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "mkdir");
3165 ASSERT_VOP_UNLOCKED(nd.ni_vp, "mkdir");
3170 * Remove a directory file.
3172 #ifndef _SYS_SYSPROTO_H_
3181 struct rmdir_args /* {
3182 syscallarg(char *) path;
3188 struct nameidata nd;
3192 NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF, UIO_USERSPACE,
3193 SCARG(uap, path), td);
3194 if ((error = namei(&nd)) != 0)
3197 if (vp->v_type != VDIR) {
3202 * No rmdir "." please.
3204 if (nd.ni_dvp == vp) {
3209 * The root of a mounted filesystem cannot be deleted.
3211 if (vp->v_flag & VROOT) {
3215 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) {
3216 NDFREE(&nd, NDF_ONLY_PNBUF);
3217 if (nd.ni_dvp == vp)
3222 if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0)
3226 VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
3227 VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
3228 error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
3229 vn_finished_write(mp);
3231 NDFREE(&nd, NDF_ONLY_PNBUF);
3232 if (nd.ni_dvp == vp)
3237 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "rmdir");
3238 ASSERT_VOP_UNLOCKED(nd.ni_vp, "rmdir");
3244 * Read a block of directory entries in a file system independent format.
3246 #ifndef _SYS_SYSPROTO_H_
3247 struct ogetdirentries_args {
3255 ogetdirentries(td, uap)
3257 register struct ogetdirentries_args /* {
3259 syscallarg(char *) buf;
3260 syscallarg(u_int) count;
3261 syscallarg(long *) basep;
3266 struct uio auio, kuio;
3267 struct iovec aiov, kiov;
3268 struct dirent *dp, *edp;
3270 int error, eofflag, readcnt;
3273 /* XXX arbitrary sanity limit on `count'. */
3274 if (SCARG(uap, count) > 64 * 1024)
3276 if ((error = getvnode(td->td_proc->p_fd, SCARG(uap, fd), &fp)) != 0)
3278 if ((fp->f_flag & FREAD) == 0) {
3282 vp = (struct vnode *)fp->f_data;
3284 if (vp->v_type != VDIR) {
3288 aiov.iov_base = SCARG(uap, buf);
3289 aiov.iov_len = SCARG(uap, count);
3290 auio.uio_iov = &aiov;
3291 auio.uio_iovcnt = 1;
3292 auio.uio_rw = UIO_READ;
3293 auio.uio_segflg = UIO_USERSPACE;
3295 auio.uio_resid = SCARG(uap, count);
3296 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
3297 loff = auio.uio_offset = fp->f_offset;
3298 # if (BYTE_ORDER != LITTLE_ENDIAN)
3299 if (vp->v_mount->mnt_maxsymlinklen <= 0) {
3300 error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag,
3302 fp->f_offset = auio.uio_offset;
3307 kuio.uio_iov = &kiov;
3308 kuio.uio_segflg = UIO_SYSSPACE;
3309 kiov.iov_len = SCARG(uap, count);
3310 MALLOC(dirbuf, caddr_t, SCARG(uap, count), M_TEMP, M_WAITOK);
3311 kiov.iov_base = dirbuf;
3312 error = VOP_READDIR(vp, &kuio, fp->f_cred, &eofflag,
3314 fp->f_offset = kuio.uio_offset;
3316 readcnt = SCARG(uap, count) - kuio.uio_resid;
3317 edp = (struct dirent *)&dirbuf[readcnt];
3318 for (dp = (struct dirent *)dirbuf; dp < edp; ) {
3319 # if (BYTE_ORDER == LITTLE_ENDIAN)
3321 * The expected low byte of
3322 * dp->d_namlen is our dp->d_type.
3323 * The high MBZ byte of dp->d_namlen
3324 * is our dp->d_namlen.
3326 dp->d_type = dp->d_namlen;
3330 * The dp->d_type is the high byte
3331 * of the expected dp->d_namlen,
3332 * so must be zero'ed.
3336 if (dp->d_reclen > 0) {
3337 dp = (struct dirent *)
3338 ((char *)dp + dp->d_reclen);
3345 error = uiomove(dirbuf, readcnt, &auio);
3347 FREE(dirbuf, M_TEMP);
3349 VOP_UNLOCK(vp, 0, td);
3354 if (SCARG(uap, count) == auio.uio_resid) {
3355 if (union_dircheckp) {
3356 error = union_dircheckp(td, &vp, fp);
3364 if ((vp->v_flag & VROOT) &&
3365 (vp->v_mount->mnt_flag & MNT_UNION)) {
3366 struct vnode *tvp = vp;
3367 vp = vp->v_mount->mnt_vnodecovered;
3369 fp->f_data = (caddr_t) vp;
3375 error = copyout((caddr_t)&loff, (caddr_t)SCARG(uap, basep),
3378 td->td_retval[0] = SCARG(uap, count) - auio.uio_resid;
3381 #endif /* COMPAT_43 */
3384 * Read a block of directory entries in a file system independent format.
3386 #ifndef _SYS_SYSPROTO_H_
3387 struct getdirentries_args {
3395 getdirentries(td, uap)
3397 register struct getdirentries_args /* {
3399 syscallarg(char *) buf;
3400 syscallarg(u_int) count;
3401 syscallarg(long *) basep;
3411 if ((error = getvnode(td->td_proc->p_fd, SCARG(uap, fd), &fp)) != 0)
3413 if ((fp->f_flag & FREAD) == 0) {
3417 vp = (struct vnode *)fp->f_data;
3419 if (vp->v_type != VDIR) {
3423 aiov.iov_base = SCARG(uap, buf);
3424 aiov.iov_len = SCARG(uap, count);
3425 auio.uio_iov = &aiov;
3426 auio.uio_iovcnt = 1;
3427 auio.uio_rw = UIO_READ;
3428 auio.uio_segflg = UIO_USERSPACE;
3430 auio.uio_resid = SCARG(uap, count);
3431 /* vn_lock(vp, LK_SHARED | LK_RETRY, td); */
3432 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
3433 loff = auio.uio_offset = fp->f_offset;
3434 error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, NULL, NULL);
3435 fp->f_offset = auio.uio_offset;
3436 VOP_UNLOCK(vp, 0, td);
3441 if (SCARG(uap, count) == auio.uio_resid) {
3442 if (union_dircheckp) {
3443 error = union_dircheckp(td, &vp, fp);
3451 if ((vp->v_flag & VROOT) &&
3452 (vp->v_mount->mnt_flag & MNT_UNION)) {
3453 struct vnode *tvp = vp;
3454 vp = vp->v_mount->mnt_vnodecovered;
3456 fp->f_data = (caddr_t) vp;
3462 if (SCARG(uap, basep) != NULL) {
3463 error = copyout((caddr_t)&loff, (caddr_t)SCARG(uap, basep),
3466 td->td_retval[0] = SCARG(uap, count) - auio.uio_resid;
3470 #ifndef _SYS_SYSPROTO_H_
3471 struct getdents_args {
3480 register struct getdents_args /* {
3482 syscallarg(char *) buf;
3483 syscallarg(u_int) count;
3486 struct getdirentries_args ap;
3489 ap.count = uap->count;
3491 return getdirentries(td, &ap);
3495 * Set the mode mask for creation of filesystem nodes.
3499 #ifndef _SYS_SYSPROTO_H_
3507 struct umask_args /* {
3508 syscallarg(int) newmask;
3511 register struct filedesc *fdp;
3513 FILEDESC_LOCK(td->td_proc->p_fd);
3514 fdp = td->td_proc->p_fd;
3515 td->td_retval[0] = fdp->fd_cmask;
3516 fdp->fd_cmask = SCARG(uap, newmask) & ALLPERMS;
3517 FILEDESC_UNLOCK(td->td_proc->p_fd);
3522 * Void all references to file by ripping underlying filesystem
3525 #ifndef _SYS_SYSPROTO_H_
3526 struct revoke_args {
3534 register struct revoke_args /* {
3535 syscallarg(char *) path;
3542 struct nameidata nd;
3544 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, SCARG(uap, path),
3546 if ((error = namei(&nd)) != 0)
3549 NDFREE(&nd, NDF_ONLY_PNBUF);
3550 if (vp->v_type != VCHR) {
3554 error = VOP_GETATTR(vp, &vattr, td->td_ucred, td);
3559 VOP_UNLOCK(vp, 0, td);
3560 if (td->td_ucred->cr_uid != vattr.va_uid) {
3561 error = suser_xxx(0, td->td_proc, PRISON_ROOT);
3565 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
3568 VOP_REVOKE(vp, REVOKEALL);
3569 vn_finished_write(mp);
3576 * Convert a user file descriptor to a kernel file entry.
3577 * The file entry is locked upon returning.
3580 getvnode(fdp, fd, fpp)
3581 struct filedesc *fdp;
3593 if ((u_int)fd >= fdp->fd_nfiles ||
3594 (fp = fdp->fd_ofiles[fd]) == NULL)
3596 else if (fp->f_type != DTYPE_VNODE && fp->f_type != DTYPE_FIFO) {
3603 FILEDESC_UNLOCK(fdp);
3609 * Get (NFS) file handle
3611 #ifndef _SYS_SYSPROTO_H_
3620 register struct getfh_args *uap;
3622 struct nameidata nd;
3624 register struct vnode *vp;
3628 * Must be super user
3630 error = suser_td(td);
3633 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, td);
3637 NDFREE(&nd, NDF_ONLY_PNBUF);
3639 bzero(&fh, sizeof(fh));
3640 fh.fh_fsid = vp->v_mount->mnt_stat.f_fsid;
3641 error = VFS_VPTOFH(vp, &fh.fh_fid);
3645 error = copyout(&fh, uap->fhp, sizeof (fh));
3650 * syscall for the rpc.lockd to use to translate a NFS file handle into
3651 * an open descriptor.
3653 * warning: do not remove the suser() call or this becomes one giant
3656 #ifndef _SYS_SYSPROTO_H_
3657 struct fhopen_args {
3658 const struct fhandle *u_fhp;
3665 struct fhopen_args /* {
3666 syscallarg(const struct fhandle *) u_fhp;
3667 syscallarg(int) flags;
3670 struct proc *p = td->td_proc;
3675 struct vattr *vap = &vat;
3678 register struct filedesc *fdp = p->p_fd;
3679 int fmode, mode, error, type;
3684 * Must be super user
3686 error = suser_td(td);
3690 fmode = FFLAGS(SCARG(uap, flags));
3691 /* why not allow a non-read/write open for our lockd? */
3692 if (((fmode & (FREAD | FWRITE)) == 0) || (fmode & O_CREAT))
3694 error = copyin(SCARG(uap,u_fhp), &fhp, sizeof(fhp));
3697 /* find the mount point */
3698 mp = vfs_getvfs(&fhp.fh_fsid);
3701 /* now give me my vnode, it gets returned to me locked */
3702 error = VFS_FHTOVP(mp, &fhp.fh_fid, &vp);
3706 * from now on we have to make sure not
3707 * to forget about the vnode
3708 * any error that causes an abort must vput(vp)
3709 * just set error = err and 'goto bad;'.
3715 if (vp->v_type == VLNK) {
3719 if (vp->v_type == VSOCK) {
3724 if (fmode & (FWRITE | O_TRUNC)) {
3725 if (vp->v_type == VDIR) {
3729 error = vn_writechk(vp);
3737 error = VOP_ACCESS(vp, mode, td->td_ucred, td);
3741 if (fmode & O_TRUNC) {
3742 VOP_UNLOCK(vp, 0, td); /* XXX */
3743 if ((error = vn_start_write(NULL, &mp, V_WAIT | PCATCH)) != 0) {
3747 VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
3748 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); /* XXX */
3751 error = VOP_SETATTR(vp, vap, td->td_ucred, td);
3752 vn_finished_write(mp);
3756 error = VOP_OPEN(vp, fmode, td->td_ucred, td);
3760 * Make sure that a VM object is created for VMIO support.
3762 if (vn_canvmio(vp) == TRUE) {
3763 if ((error = vfs_object_create(vp, td, td->td_ucred)) != 0)
3770 * end of vn_open code
3773 if ((error = falloc(td, &nfp, &indx)) != 0) {
3781 * Hold an extra reference to avoid having fp ripped out
3782 * from under us while we block in the lock op
3785 nfp->f_data = (caddr_t)vp;
3786 nfp->f_flag = fmode & FMASK;
3787 nfp->f_ops = &vnops;
3788 nfp->f_type = DTYPE_VNODE;
3789 if (fmode & (O_EXLOCK | O_SHLOCK)) {
3790 lf.l_whence = SEEK_SET;
3793 if (fmode & O_EXLOCK)
3794 lf.l_type = F_WRLCK;
3796 lf.l_type = F_RDLCK;
3798 if ((fmode & FNONBLOCK) == 0)
3800 VOP_UNLOCK(vp, 0, td);
3801 if ((error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type)) != 0) {
3803 * The lock request failed. Normally close the
3804 * descriptor but handle the case where someone might
3805 * have dup()d or close()d it when we weren't looking.
3808 if (fdp->fd_ofiles[indx] == fp) {
3809 fdp->fd_ofiles[indx] = NULL;
3810 FILEDESC_UNLOCK(fdp);
3813 FILEDESC_UNLOCK(fdp);
3815 * release our private reference
3820 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
3821 fp->f_flag |= FHASLOCK;
3823 if ((vp->v_type == VREG) && (VOP_GETVOBJECT(vp, NULL) != 0))
3824 vfs_object_create(vp, td, td->td_ucred);
3826 VOP_UNLOCK(vp, 0, td);
3828 td->td_retval[0] = indx;
3837 * Stat an (NFS) file handle.
3839 #ifndef _SYS_SYSPROTO_H_
3840 struct fhstat_args {
3841 struct fhandle *u_fhp;
3848 register struct fhstat_args /* {
3849 syscallarg(struct fhandle *) u_fhp;
3850 syscallarg(struct stat *) sb;
3860 * Must be super user
3862 error = suser_td(td);
3866 error = copyin(SCARG(uap, u_fhp), &fh, sizeof(fhandle_t));
3870 if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL)
3872 if ((error = VFS_FHTOVP(mp, &fh.fh_fid, &vp)))
3874 error = vn_stat(vp, &sb, td);
3878 error = copyout(&sb, SCARG(uap, sb), sizeof(sb));
3883 * Implement fstatfs() for (NFS) file handles.
3885 #ifndef _SYS_SYSPROTO_H_
3886 struct fhstatfs_args {
3887 struct fhandle *u_fhp;
3894 struct fhstatfs_args /* {
3895 syscallarg(struct fhandle) *u_fhp;
3896 syscallarg(struct statfs) *buf;
3907 * Must be super user
3909 error = suser_td(td);
3913 if ((error = copyin(SCARG(uap, u_fhp), &fh, sizeof(fhandle_t))) != 0)
3916 if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL)
3918 if ((error = VFS_FHTOVP(mp, &fh.fh_fid, &vp)))
3923 if ((error = VFS_STATFS(mp, sp, td)) != 0)
3925 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
3926 if (suser_xxx(td->td_ucred, 0, 0)) {
3927 bcopy((caddr_t)sp, (caddr_t)&sb, sizeof(sb));
3928 sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0;
3931 return (copyout(sp, SCARG(uap, buf), sizeof(*sp)));
3935 * Syscall to push extended attribute configuration information into the
3936 * VFS. Accepts a path, which it converts to a mountpoint, as well as
3937 * a command (int cmd), and attribute name and misc data. For now, the
3938 * attribute name is left in userspace for consumption by the VFS_op.
3939 * It will probably be changed to be copied into sysspace by the
3940 * syscall in the future, once issues with various consumers of the
3941 * attribute code have raised their hands.
3943 * Currently this is used only by UFS Extended Attributes.
3948 struct extattrctl_args *uap;
3950 struct vnode *filename_vp;
3951 struct nameidata nd;
3952 struct mount *mp, *mp_writable;
3953 char attrname[EXTATTR_MAXNAMELEN];
3957 * SCARG(uap, attrname) not always defined. We check again later
3958 * when we invoke the VFS call so as to pass in NULL there if needed.
3960 if (SCARG(uap, attrname) != NULL) {
3961 error = copyinstr(SCARG(uap, attrname), attrname,
3962 EXTATTR_MAXNAMELEN, NULL);
3968 * SCARG(uap, filename) not always defined. If it is, grab
3969 * a vnode lock, which VFS_EXTATTRCTL() will later release.
3972 if (SCARG(uap, filename) != NULL) {
3973 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
3974 SCARG(uap, filename), td);
3975 if ((error = namei(&nd)) != 0)
3977 filename_vp = nd.ni_vp;
3978 NDFREE(&nd, NDF_NO_VP_RELE | NDF_NO_VP_UNLOCK);
3981 /* SCARG(uap, path) always defined. */
3982 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td);
3983 if ((error = namei(&nd)) != 0) {
3984 if (filename_vp != NULL)
3988 mp = nd.ni_vp->v_mount;
3989 error = vn_start_write(nd.ni_vp, &mp_writable, V_WAIT | PCATCH);
3992 if (filename_vp != NULL)
3997 if (SCARG(uap, attrname) != NULL) {
3998 error = VFS_EXTATTRCTL(mp, SCARG(uap, cmd), filename_vp,
3999 SCARG(uap, attrnamespace), attrname, td);
4001 error = VFS_EXTATTRCTL(mp, SCARG(uap, cmd), filename_vp,
4002 SCARG(uap, attrnamespace), NULL, td);
4005 vn_finished_write(mp_writable);
4007 * VFS_EXTATTRCTL will have unlocked, but not de-ref'd,
4008 * filename_vp, so vrele it if it is defined.
4010 if (filename_vp != NULL)
4017 * Set a named extended attribute on a file or directory
4019 * Arguments: unlocked vnode "vp", attribute namespace "attrnamespace",
4020 * kernelspace string pointer "attrname", userspace buffer
4021 * pointer "data", buffer length "nbytes", thread "td".
4022 * Returns: 0 on success, an error number otherwise
4024 * References: vp must be a valid reference for the duration of the call
4027 extattr_set_vp(struct vnode *vp, int attrnamespace, const char *attrname,
4028 void *data, size_t nbytes, struct thread *td)
4036 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
4038 VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
4039 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
4041 aiov.iov_base = data;
4042 aiov.iov_len = nbytes;
4043 auio.uio_iov = &aiov;
4044 auio.uio_iovcnt = 1;
4045 auio.uio_offset = 0;
4046 if (nbytes > INT_MAX) {
4050 auio.uio_resid = nbytes;
4051 auio.uio_rw = UIO_WRITE;
4052 auio.uio_segflg = UIO_USERSPACE;
4056 error = VOP_SETEXTATTR(vp, attrnamespace, attrname, &auio,
4058 cnt -= auio.uio_resid;
4059 td->td_retval[0] = cnt;
4062 VOP_UNLOCK(vp, 0, td);
4063 vn_finished_write(mp);
4068 extattr_set_file(td, uap)
4070 struct extattr_set_file_args *uap;
4072 struct nameidata nd;
4073 char attrname[EXTATTR_MAXNAMELEN];
4076 error = copyinstr(SCARG(uap, attrname), attrname, EXTATTR_MAXNAMELEN,
4081 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td);
4082 if ((error = namei(&nd)) != 0)
4084 NDFREE(&nd, NDF_ONLY_PNBUF);
4086 error = extattr_set_vp(nd.ni_vp, SCARG(uap, attrnamespace), attrname,
4087 SCARG(uap, data), SCARG(uap, nbytes), td);
4094 extattr_set_fd(td, uap)
4096 struct extattr_set_fd_args *uap;
4099 char attrname[EXTATTR_MAXNAMELEN];
4102 error = copyinstr(SCARG(uap, attrname), attrname, EXTATTR_MAXNAMELEN,
4107 if ((error = getvnode(td->td_proc->p_fd, SCARG(uap, fd), &fp)) != 0)
4110 error = extattr_set_vp((struct vnode *)fp->f_data,
4111 SCARG(uap, attrnamespace), attrname, SCARG(uap, data),
4112 SCARG(uap, nbytes), td);
4119 * Get a named extended attribute on a file or directory
4121 * Arguments: unlocked vnode "vp", attribute namespace "attrnamespace",
4122 * kernelspace string pointer "attrname", userspace buffer
4123 * pointer "data", buffer length "nbytes", thread "td".
4124 * Returns: 0 on success, an error number otherwise
4126 * References: vp must be a valid reference for the duration of the call
4129 extattr_get_vp(struct vnode *vp, int attrnamespace, const char *attrname,
4130 void *data, size_t nbytes, struct thread *td)
4138 VOP_LEASE(vp, td, td->td_ucred, LEASE_READ);
4139 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
4142 * Slightly unusual semantics: if the user provides a NULL data
4143 * pointer, they don't want to receive the data, just the
4144 * maximum read length.
4147 aiov.iov_base = data;
4148 aiov.iov_len = nbytes;
4149 auio.uio_iov = &aiov;
4150 auio.uio_offset = 0;
4151 if (nbytes > INT_MAX) {
4155 auio.uio_resid = nbytes;
4156 auio.uio_rw = UIO_READ;
4157 auio.uio_segflg = UIO_USERSPACE;
4160 error = VOP_GETEXTATTR(vp, attrnamespace, attrname, &auio,
4161 NULL, td->td_ucred, td);
4162 cnt -= auio.uio_resid;
4163 td->td_retval[0] = cnt;
4165 error = VOP_GETEXTATTR(vp, attrnamespace, attrname, NULL,
4166 &size, td->td_ucred, td);
4167 td->td_retval[0] = size;
4170 VOP_UNLOCK(vp, 0, td);
4175 extattr_get_file(td, uap)
4177 struct extattr_get_file_args *uap;
4179 struct nameidata nd;
4180 char attrname[EXTATTR_MAXNAMELEN];
4183 error = copyinstr(SCARG(uap, attrname), attrname, EXTATTR_MAXNAMELEN,
4188 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td);
4189 if ((error = namei(&nd)) != 0)
4191 NDFREE(&nd, NDF_ONLY_PNBUF);
4193 error = extattr_get_vp(nd.ni_vp, SCARG(uap, attrnamespace), attrname,
4194 SCARG(uap, data), SCARG(uap, nbytes), td);
4201 extattr_get_fd(td, uap)
4203 struct extattr_get_fd_args *uap;
4206 char attrname[EXTATTR_MAXNAMELEN];
4209 error = copyinstr(SCARG(uap, attrname), attrname, EXTATTR_MAXNAMELEN,
4214 if ((error = getvnode(td->td_proc->p_fd, SCARG(uap, fd), &fp)) != 0)
4217 error = extattr_get_vp((struct vnode *)fp->f_data,
4218 SCARG(uap, attrnamespace), attrname, SCARG(uap, data),
4219 SCARG(uap, nbytes), td);
4226 * extattr_delete_vp(): Delete a named extended attribute on a file or
4229 * Arguments: unlocked vnode "vp", attribute namespace "attrnamespace",
4230 * kernelspace string pointer "attrname", proc "p"
4231 * Returns: 0 on success, an error number otherwise
4233 * References: vp must be a valid reference for the duration of the call
4236 extattr_delete_vp(struct vnode *vp, int attrnamespace, const char *attrname,
4242 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
4244 VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
4245 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
4247 error = VOP_SETEXTATTR(vp, attrnamespace, attrname, NULL, td->td_ucred,
4250 VOP_UNLOCK(vp, 0, td);
4251 vn_finished_write(mp);
4256 extattr_delete_file(td, uap)
4258 struct extattr_delete_file_args *uap;
4260 struct nameidata nd;
4261 char attrname[EXTATTR_MAXNAMELEN];
4264 error = copyinstr(SCARG(uap, attrname), attrname, EXTATTR_MAXNAMELEN,
4269 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td);
4270 if ((error = namei(&nd)) != 0)
4272 NDFREE(&nd, NDF_ONLY_PNBUF);
4274 error = extattr_delete_vp(nd.ni_vp, SCARG(uap, attrnamespace),
4282 extattr_delete_fd(td, uap)
4284 struct extattr_delete_fd_args *uap;
4288 char attrname[EXTATTR_MAXNAMELEN];
4291 error = copyinstr(SCARG(uap, attrname), attrname, EXTATTR_MAXNAMELEN,
4296 if ((error = getvnode(td->td_proc->p_fd, SCARG(uap, fd), &fp)) != 0)
4298 vp = (struct vnode *)fp->f_data;
4300 error = extattr_delete_vp((struct vnode *)fp->f_data,
4301 SCARG(uap, attrnamespace), attrname, td);