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 * 4. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * @(#)vfs_syscalls.c 8.13 (Berkeley) 4/15/94
37 #include <sys/cdefs.h>
38 __FBSDID("$FreeBSD$");
40 #include "opt_compat.h"
43 #include <sys/param.h>
44 #include <sys/systm.h>
47 #include <sys/sysent.h>
49 #include <sys/malloc.h>
50 #include <sys/mount.h>
51 #include <sys/mutex.h>
52 #include <sys/sysproto.h>
53 #include <sys/namei.h>
54 #include <sys/filedesc.h>
55 #include <sys/kernel.h>
56 #include <sys/fcntl.h>
58 #include <sys/limits.h>
59 #include <sys/linker.h>
62 #include <sys/unistd.h>
63 #include <sys/vnode.h>
65 #include <sys/dirent.h>
66 #include <sys/extattr.h>
68 #include <sys/syscallsubr.h>
69 #include <sys/sysctl.h>
71 #include <machine/stdarg.h>
74 #include <vm/vm_object.h>
75 #include <vm/vm_page.h>
78 static int chroot_refuse_vdir_fds(struct filedesc *fdp);
79 static int getutimes(const struct timeval *, enum uio_seg, struct timespec *);
80 static int setfown(struct thread *td, struct vnode *, uid_t, gid_t);
81 static int setfmode(struct thread *td, struct vnode *, int);
82 static int setfflags(struct thread *td, struct vnode *, int);
83 static int setutimes(struct thread *td, struct vnode *,
84 const struct timespec *, int, int);
85 static int vn_access(struct vnode *vp, int user_flags, struct ucred *cred,
88 static int extattr_list_vp(struct vnode *vp, int attrnamespace, void *data,
89 size_t nbytes, struct thread *td);
91 int (*union_dircheckp)(struct thread *td, struct vnode **, struct file *);
94 * The module initialization routine for POSIX asynchronous I/O will
95 * set this to the version of AIO that it implements. (Zero means
96 * that it is not implemented.) This value is used here by pathconf()
97 * and in kern_descrip.c by fpathconf().
102 * Sync each mounted filesystem.
104 #ifndef _SYS_SYSPROTO_H_
111 static int syncprt = 0;
112 SYSCTL_INT(_debug, OID_AUTO, syncprt, CTLFLAG_RW, &syncprt, 0, "");
119 struct sync_args *uap;
121 struct mount *mp, *nmp;
125 mtx_lock(&mountlist_mtx);
126 for (mp = TAILQ_FIRST(&mountlist); mp != NULL; mp = nmp) {
127 if (vfs_busy(mp, LK_NOWAIT, &mountlist_mtx, td)) {
128 nmp = TAILQ_NEXT(mp, mnt_list);
131 if ((mp->mnt_flag & MNT_RDONLY) == 0 &&
132 vn_start_write(NULL, &mp, V_NOWAIT) == 0) {
133 asyncflag = mp->mnt_flag & MNT_ASYNC;
134 mp->mnt_flag &= ~MNT_ASYNC;
135 vfs_msync(mp, MNT_NOWAIT);
136 VFS_SYNC(mp, MNT_NOWAIT, td);
137 mp->mnt_flag |= asyncflag;
138 vn_finished_write(mp);
140 mtx_lock(&mountlist_mtx);
141 nmp = TAILQ_NEXT(mp, mnt_list);
144 mtx_unlock(&mountlist_mtx);
147 * XXX don't call vfs_bufstats() yet because that routine
148 * was not imported in the Lite2 merge.
153 #endif /* DIAGNOSTIC */
159 /* XXX PRISON: could be per prison flag */
160 static int prison_quotas;
162 SYSCTL_INT(_kern_prison, OID_AUTO, quotas, CTLFLAG_RW, &prison_quotas, 0, "");
166 * Change filesystem quotas.
170 #ifndef _SYS_SYSPROTO_H_
171 struct quotactl_args {
181 register struct quotactl_args /* {
188 struct mount *mp, *vmp;
192 if (jailed(td->td_ucred) && !prison_quotas)
195 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, td);
196 if ((error = namei(&nd)) != 0) {
200 NDFREE(&nd, NDF_ONLY_PNBUF);
201 error = vn_start_write(nd.ni_vp, &vmp, V_WAIT | PCATCH);
202 mp = nd.ni_vp->v_mount;
208 error = VFS_QUOTACTL(mp, uap->cmd, uap->uid, uap->arg, td);
209 vn_finished_write(vmp);
215 * Get filesystem statistics.
217 #ifndef _SYS_SYSPROTO_H_
226 register struct statfs_args /* {
234 error = kern_statfs(td, uap->path, UIO_USERSPACE, &sf);
236 error = copyout(&sf, uap->buf, sizeof(sf));
241 kern_statfs(struct thread *td, char *path, enum uio_seg pathseg,
245 struct statfs *sp, sb;
250 NDINIT(&nd, LOOKUP, FOLLOW, pathseg, path, td);
256 mp = nd.ni_vp->v_mount;
258 NDFREE(&nd, NDF_ONLY_PNBUF);
261 error = mac_check_mount_stat(td->td_ucred, mp);
268 * Set these in case the underlying filesystem fails to do so.
270 sp->f_version = STATFS_VERSION;
271 sp->f_namemax = NAME_MAX;
272 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
273 error = VFS_STATFS(mp, sp, td);
278 bcopy(sp, &sb, sizeof(sb));
279 sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0;
287 * Get filesystem statistics.
289 #ifndef _SYS_SYSPROTO_H_
290 struct fstatfs_args {
298 register struct fstatfs_args /* {
306 error = kern_fstatfs(td, uap->fd, &sf);
308 error = copyout(&sf, uap->buf, sizeof(sf));
313 kern_fstatfs(struct thread *td, int fd, struct statfs *buf)
317 struct statfs *sp, sb;
320 error = getvnode(td->td_proc->p_fd, fd, &fp);
324 mp = fp->f_vnode->v_mount;
331 error = mac_check_mount_stat(td->td_ucred, mp);
339 * Set these in case the underlying filesystem fails to do so.
341 sp->f_version = STATFS_VERSION;
342 sp->f_namemax = NAME_MAX;
343 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
344 error = VFS_STATFS(mp, sp, td);
349 bcopy(sp, &sb, sizeof(sb));
350 sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0;
358 * Get statistics on all filesystems.
360 #ifndef _SYS_SYSPROTO_H_
361 struct getfsstat_args {
370 register struct getfsstat_args /* {
376 struct mount *mp, *nmp;
377 struct statfs *sp, sb;
379 long count, maxcount, error;
381 maxcount = uap->bufsize / sizeof(struct statfs);
382 sfsp = (caddr_t)uap->buf;
385 mtx_lock(&mountlist_mtx);
386 for (mp = TAILQ_FIRST(&mountlist); mp != NULL; mp = nmp) {
387 if (!prison_check_mount(td->td_ucred, mp)) {
388 nmp = TAILQ_NEXT(mp, mnt_list);
392 if (mac_check_mount_stat(td->td_ucred, mp) != 0) {
393 nmp = TAILQ_NEXT(mp, mnt_list);
397 if (vfs_busy(mp, LK_NOWAIT, &mountlist_mtx, td)) {
398 nmp = TAILQ_NEXT(mp, mnt_list);
401 if (sfsp && count < maxcount) {
404 * Set these in case the underlying filesystem
407 sp->f_version = STATFS_VERSION;
408 sp->f_namemax = NAME_MAX;
409 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
411 * If MNT_NOWAIT or MNT_LAZY is specified, do not
412 * refresh the fsstat cache. MNT_NOWAIT or MNT_LAZY
413 * overrides MNT_WAIT.
415 if (((uap->flags & (MNT_LAZY|MNT_NOWAIT)) == 0 ||
416 (uap->flags & MNT_WAIT)) &&
417 (error = VFS_STATFS(mp, sp, td))) {
418 mtx_lock(&mountlist_mtx);
419 nmp = TAILQ_NEXT(mp, mnt_list);
424 bcopy(sp, &sb, sizeof(sb));
425 sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0;
428 error = copyout(sp, sfsp, sizeof(*sp));
437 mtx_lock(&mountlist_mtx);
438 nmp = TAILQ_NEXT(mp, mnt_list);
441 mtx_unlock(&mountlist_mtx);
443 if (sfsp && count > maxcount)
444 td->td_retval[0] = maxcount;
446 td->td_retval[0] = count;
450 #ifdef COMPAT_FREEBSD4
452 * Get old format filesystem statistics.
454 static void cvtstatfs(struct statfs *, struct ostatfs *);
456 #ifndef _SYS_SYSPROTO_H_
457 struct freebsd4_statfs_args {
463 freebsd4_statfs(td, uap)
465 struct freebsd4_statfs_args /* {
474 error = kern_statfs(td, uap->path, UIO_USERSPACE, &sf);
477 cvtstatfs(&sf, &osb);
478 return (copyout(&osb, uap->buf, sizeof(osb)));
482 * Get filesystem statistics.
484 #ifndef _SYS_SYSPROTO_H_
485 struct freebsd4_fstatfs_args {
491 freebsd4_fstatfs(td, uap)
493 struct freebsd4_fstatfs_args /* {
502 error = kern_fstatfs(td, uap->fd, &sf);
505 cvtstatfs(&sf, &osb);
506 return (copyout(&osb, uap->buf, sizeof(osb)));
510 * Get statistics on all filesystems.
512 #ifndef _SYS_SYSPROTO_H_
513 struct freebsd4_getfsstat_args {
520 freebsd4_getfsstat(td, uap)
522 register struct freebsd4_getfsstat_args /* {
528 struct mount *mp, *nmp;
529 struct statfs *sp, sb;
532 long count, maxcount, error;
534 maxcount = uap->bufsize / sizeof(struct ostatfs);
535 sfsp = (caddr_t)uap->buf;
538 mtx_lock(&mountlist_mtx);
539 for (mp = TAILQ_FIRST(&mountlist); mp != NULL; mp = nmp) {
540 if (!prison_check_mount(td->td_ucred, mp)) {
541 nmp = TAILQ_NEXT(mp, mnt_list);
545 if (mac_check_mount_stat(td->td_ucred, mp) != 0) {
546 nmp = TAILQ_NEXT(mp, mnt_list);
550 if (vfs_busy(mp, LK_NOWAIT, &mountlist_mtx, td)) {
551 nmp = TAILQ_NEXT(mp, mnt_list);
554 if (sfsp && count < maxcount) {
557 * If MNT_NOWAIT or MNT_LAZY is specified, do not
558 * refresh the fsstat cache. MNT_NOWAIT or MNT_LAZY
559 * overrides MNT_WAIT.
561 if (((uap->flags & (MNT_LAZY|MNT_NOWAIT)) == 0 ||
562 (uap->flags & MNT_WAIT)) &&
563 (error = VFS_STATFS(mp, sp, td))) {
564 mtx_lock(&mountlist_mtx);
565 nmp = TAILQ_NEXT(mp, mnt_list);
569 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
571 bcopy(sp, &sb, sizeof(sb));
572 sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0;
576 error = copyout(&osb, sfsp, sizeof(osb));
585 mtx_lock(&mountlist_mtx);
586 nmp = TAILQ_NEXT(mp, mnt_list);
589 mtx_unlock(&mountlist_mtx);
591 if (sfsp && count > maxcount)
592 td->td_retval[0] = maxcount;
594 td->td_retval[0] = count;
599 * Implement fstatfs() for (NFS) file handles.
601 #ifndef _SYS_SYSPROTO_H_
602 struct freebsd4_fhstatfs_args {
603 struct fhandle *u_fhp;
608 freebsd4_fhstatfs(td, uap)
610 struct freebsd4_fhstatfs_args /* {
611 struct fhandle *u_fhp;
620 error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t));
623 error = kern_fhstatfs(td, fh, &sf);
626 cvtstatfs(&sf, &osb);
627 return (copyout(&osb, uap->buf, sizeof(osb)));
631 * Convert a new format statfs structure to an old format statfs structure.
639 bzero(osp, sizeof(*osp));
640 osp->f_bsize = MIN(nsp->f_bsize, LONG_MAX);
641 osp->f_iosize = MIN(nsp->f_iosize, LONG_MAX);
642 osp->f_blocks = MIN(nsp->f_blocks, LONG_MAX);
643 osp->f_bfree = MIN(nsp->f_bfree, LONG_MAX);
644 osp->f_bavail = MIN(nsp->f_bavail, LONG_MAX);
645 osp->f_files = MIN(nsp->f_files, LONG_MAX);
646 osp->f_ffree = MIN(nsp->f_ffree, LONG_MAX);
647 osp->f_owner = nsp->f_owner;
648 osp->f_type = nsp->f_type;
649 osp->f_flags = nsp->f_flags;
650 osp->f_syncwrites = MIN(nsp->f_syncwrites, LONG_MAX);
651 osp->f_asyncwrites = MIN(nsp->f_asyncwrites, LONG_MAX);
652 osp->f_syncreads = MIN(nsp->f_syncreads, LONG_MAX);
653 osp->f_asyncreads = MIN(nsp->f_asyncreads, LONG_MAX);
654 bcopy(nsp->f_fstypename, osp->f_fstypename,
655 MIN(MFSNAMELEN, OMNAMELEN));
656 bcopy(nsp->f_mntonname, osp->f_mntonname,
657 MIN(MFSNAMELEN, OMNAMELEN));
658 bcopy(nsp->f_mntfromname, osp->f_mntfromname,
659 MIN(MFSNAMELEN, OMNAMELEN));
660 osp->f_fsid = nsp->f_fsid;
662 #endif /* COMPAT_FREEBSD4 */
665 * Change current working directory to a given file descriptor.
667 #ifndef _SYS_SYSPROTO_H_
675 struct fchdir_args /* {
679 register struct filedesc *fdp = td->td_proc->p_fd;
680 struct vnode *vp, *tdp, *vpold;
686 if ((error = getvnode(fdp, uap->fd, &fp)) != 0)
689 vfslocked = VFS_LOCK_GIANT(vp->v_mount);
692 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
693 if (vp->v_type != VDIR)
696 else if ((error = mac_check_vnode_chdir(td->td_ucred, vp)) != 0) {
700 error = VOP_ACCESS(vp, VEXEC, td->td_ucred, td);
701 while (!error && (mp = vp->v_mountedhere) != NULL) {
703 if (vfs_busy(mp, 0, 0, td))
705 tvfslocked = VFS_LOCK_GIANT(mp);
706 error = VFS_ROOT(mp, LK_EXCLUSIVE, &tdp, td);
709 VFS_UNLOCK_GIANT(tvfslocked);
713 VFS_UNLOCK_GIANT(vfslocked);
715 vfslocked = tvfslocked;
719 VFS_UNLOCK_GIANT(vfslocked);
722 VOP_UNLOCK(vp, 0, td);
723 FILEDESC_LOCK_FAST(fdp);
724 vpold = fdp->fd_cdir;
726 FILEDESC_UNLOCK_FAST(fdp);
728 VFS_UNLOCK_GIANT(vfslocked);
733 * Change current working directory (``.'').
735 #ifndef _SYS_SYSPROTO_H_
743 struct chdir_args /* {
748 return (kern_chdir(td, uap->path, UIO_USERSPACE));
752 kern_chdir(struct thread *td, char *path, enum uio_seg pathseg)
754 register struct filedesc *fdp = td->td_proc->p_fd;
760 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | MPSAFE, pathseg, path, td);
761 if ((error = namei(&nd)) != 0)
763 vfslocked = NDHASGIANT(&nd);
764 if ((error = change_dir(nd.ni_vp, td)) != 0) {
766 VFS_UNLOCK_GIANT(vfslocked);
767 NDFREE(&nd, NDF_ONLY_PNBUF);
770 VOP_UNLOCK(nd.ni_vp, 0, td);
771 NDFREE(&nd, NDF_ONLY_PNBUF);
772 FILEDESC_LOCK_FAST(fdp);
774 fdp->fd_cdir = nd.ni_vp;
775 FILEDESC_UNLOCK_FAST(fdp);
777 VFS_UNLOCK_GIANT(vfslocked);
782 * Helper function for raised chroot(2) security function: Refuse if
783 * any filedescriptors are open directories.
786 chroot_refuse_vdir_fds(fdp)
787 struct filedesc *fdp;
793 FILEDESC_LOCK_ASSERT(fdp, MA_OWNED);
794 for (fd = 0; fd < fdp->fd_nfiles ; fd++) {
795 fp = fget_locked(fdp, fd);
798 if (fp->f_type == DTYPE_VNODE) {
800 if (vp->v_type == VDIR)
808 * This sysctl determines if we will allow a process to chroot(2) if it
809 * has a directory open:
810 * 0: disallowed for all processes.
811 * 1: allowed for processes that were not already chroot(2)'ed.
812 * 2: allowed for all processes.
815 static int chroot_allow_open_directories = 1;
817 SYSCTL_INT(_kern, OID_AUTO, chroot_allow_open_directories, CTLFLAG_RW,
818 &chroot_allow_open_directories, 0, "");
821 * Change notion of root (``/'') directory.
823 #ifndef _SYS_SYSPROTO_H_
831 struct chroot_args /* {
839 error = suser_cred(td->td_ucred, SUSER_ALLOWJAIL);
842 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | MPSAFE,
843 UIO_USERSPACE, uap->path, td);
847 vfslocked = NDHASGIANT(&nd);
848 if ((error = change_dir(nd.ni_vp, td)) != 0)
851 if ((error = mac_check_vnode_chroot(td->td_ucred, nd.ni_vp)))
854 VOP_UNLOCK(nd.ni_vp, 0, td);
855 error = change_root(nd.ni_vp, td);
857 VFS_UNLOCK_GIANT(vfslocked);
858 NDFREE(&nd, NDF_ONLY_PNBUF);
862 VFS_UNLOCK_GIANT(vfslocked);
864 NDFREE(&nd, NDF_ONLY_PNBUF);
869 * Common routine for chroot and chdir. Callers must provide a locked vnode
879 ASSERT_VOP_LOCKED(vp, "change_dir(): vp not locked");
880 if (vp->v_type != VDIR)
883 error = mac_check_vnode_chdir(td->td_ucred, vp);
887 error = VOP_ACCESS(vp, VEXEC, td->td_ucred, td);
892 * Common routine for kern_chroot() and jail_attach(). The caller is
893 * responsible for invoking suser() and mac_check_chroot() to authorize this
901 struct filedesc *fdp;
905 VFS_ASSERT_GIANT(vp->v_mount);
906 fdp = td->td_proc->p_fd;
908 if (chroot_allow_open_directories == 0 ||
909 (chroot_allow_open_directories == 1 && fdp->fd_rdir != rootvnode)) {
910 error = chroot_refuse_vdir_fds(fdp);
912 FILEDESC_UNLOCK(fdp);
916 oldvp = fdp->fd_rdir;
923 FILEDESC_UNLOCK(fdp);
929 * Check permissions, allocate an open file structure,
930 * and call the device open routine if any.
934 #ifndef _SYS_SYSPROTO_H_
944 register struct open_args /* {
952 error = kern_open(td, uap->path, UIO_USERSPACE, uap->flags, uap->mode);
953 if (mtx_owned(&Giant))
954 printf("open: %s: %d\n", uap->path, error);
959 kern_open(struct thread *td, char *path, enum uio_seg pathseg, int flags,
962 struct proc *p = td->td_proc;
963 struct filedesc *fdp = p->p_fd;
970 int type, indx, error;
975 if ((flags & O_ACCMODE) == O_ACCMODE)
977 flags = FFLAGS(flags);
978 error = falloc(td, &nfp, &indx);
981 /* An extra reference on `nfp' has been held for us by falloc(). */
983 cmode = ((mode &~ fdp->fd_cmask) & ALLPERMS) &~ S_ISTXT;
984 NDINIT(&nd, LOOKUP, FOLLOW, pathseg, path, td);
985 td->td_dupfd = -1; /* XXX check for fdopen */
986 error = vn_open(&nd, &flags, cmode, indx);
989 * If the vn_open replaced the method vector, something
990 * wonderous happened deep below and we just pass it up
991 * pretending we know what we do.
993 if (error == ENXIO && fp->f_ops != &badfileops) {
995 td->td_retval[0] = indx;
1000 * release our own reference
1005 * handle special fdopen() case. bleh. dupfdopen() is
1006 * responsible for dropping the old contents of ofiles[indx]
1009 if ((error == ENODEV || error == ENXIO) &&
1010 td->td_dupfd >= 0 && /* XXX from fdopen */
1012 dupfdopen(td, fdp, indx, td->td_dupfd, flags, error)) == 0) {
1013 td->td_retval[0] = indx;
1017 * Clean up the descriptor, but only if another thread hadn't
1018 * replaced or closed it.
1020 fdclose(fdp, fp, indx, td);
1022 if (error == ERESTART)
1027 vfslocked = NDHASGIANT(&nd);
1028 NDFREE(&nd, NDF_ONLY_PNBUF);
1032 * There should be 2 references on the file, one from the descriptor
1033 * table, and one for us.
1035 * Handle the case where someone closed the file (via its file
1036 * descriptor) while we were blocked. The end result should look
1037 * like opening the file succeeded but it was immediately closed.
1038 * We call vn_close() manually because we haven't yet hooked up
1039 * the various 'struct file' fields.
1043 if (fp->f_count == 1) {
1045 KASSERT(fdp->fd_ofiles[indx] != fp,
1046 ("Open file descriptor lost all refs"));
1048 FILEDESC_UNLOCK(fdp);
1049 VOP_UNLOCK(vp, 0, td);
1050 vn_close(vp, flags & FMASK, fp->f_cred, td);
1051 VFS_UNLOCK_GIANT(vfslocked);
1053 td->td_retval[0] = indx;
1057 if (fp->f_data == NULL)
1059 fp->f_flag = flags & FMASK;
1060 if (fp->f_ops == &badfileops)
1063 fp->f_type = (vp->v_type == VFIFO ? DTYPE_FIFO : DTYPE_VNODE);
1065 FILEDESC_UNLOCK(fdp);
1067 VOP_UNLOCK(vp, 0, td);
1068 if (flags & (O_EXLOCK | O_SHLOCK)) {
1069 lf.l_whence = SEEK_SET;
1072 if (flags & O_EXLOCK)
1073 lf.l_type = F_WRLCK;
1075 lf.l_type = F_RDLCK;
1077 if ((flags & FNONBLOCK) == 0)
1079 if ((error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf,
1082 fp->f_flag |= FHASLOCK;
1084 if (flags & O_TRUNC) {
1085 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
1087 VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
1090 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
1092 error = mac_check_vnode_write(td->td_ucred, fp->f_cred, vp);
1095 error = VOP_SETATTR(vp, &vat, td->td_ucred, td);
1096 VOP_UNLOCK(vp, 0, td);
1097 vn_finished_write(mp);
1101 VFS_UNLOCK_GIANT(vfslocked);
1103 * Release our private reference, leaving the one associated with
1104 * the descriptor table intact.
1107 td->td_retval[0] = indx;
1110 VFS_UNLOCK_GIANT(vfslocked);
1111 fdclose(fdp, fp, indx, td);
1122 #ifndef _SYS_SYSPROTO_H_
1123 struct ocreat_args {
1131 register struct ocreat_args /* {
1137 return (kern_open(td, uap->path, UIO_USERSPACE,
1138 O_WRONLY | O_CREAT | O_TRUNC, uap->mode));
1140 #endif /* COMPAT_43 */
1143 * Create a special file.
1145 #ifndef _SYS_SYSPROTO_H_
1155 register struct mknod_args /* {
1162 return (kern_mknod(td, uap->path, UIO_USERSPACE, uap->mode, uap->dev));
1166 kern_mknod(struct thread *td, char *path, enum uio_seg pathseg, int mode,
1174 struct nameidata nd;
1177 switch (mode & S_IFMT) {
1183 error = suser_cred(td->td_ucred, SUSER_ALLOWJAIL);
1190 NDINIT(&nd, CREATE, LOCKPARENT | SAVENAME | MPSAFE, pathseg, path, td);
1191 if ((error = namei(&nd)) != 0)
1193 vfslocked = NDHASGIANT(&nd);
1196 NDFREE(&nd, NDF_ONLY_PNBUF);
1198 if (vp == nd.ni_dvp)
1202 VFS_UNLOCK_GIANT(vfslocked);
1206 FILEDESC_LOCK_FAST(td->td_proc->p_fd);
1207 vattr.va_mode = (mode & ALLPERMS) &
1208 ~td->td_proc->p_fd->fd_cmask;
1209 FILEDESC_UNLOCK_FAST(td->td_proc->p_fd);
1210 vattr.va_rdev = dev;
1213 switch (mode & S_IFMT) {
1214 case S_IFMT: /* used by badsect to flag bad sectors */
1215 vattr.va_type = VBAD;
1218 vattr.va_type = VCHR;
1221 vattr.va_type = VBLK;
1231 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) {
1232 NDFREE(&nd, NDF_ONLY_PNBUF);
1234 VFS_UNLOCK_GIANT(vfslocked);
1235 if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0)
1240 if (error == 0 && !whiteout)
1241 error = mac_check_vnode_create(td->td_ucred, nd.ni_dvp,
1242 &nd.ni_cnd, &vattr);
1245 VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
1247 error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, CREATE);
1249 error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp,
1250 &nd.ni_cnd, &vattr);
1255 NDFREE(&nd, NDF_ONLY_PNBUF);
1257 vn_finished_write(mp);
1258 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "mknod");
1259 ASSERT_VOP_UNLOCKED(nd.ni_vp, "mknod");
1260 VFS_UNLOCK_GIANT(vfslocked);
1265 * Create a named pipe.
1267 #ifndef _SYS_SYSPROTO_H_
1268 struct mkfifo_args {
1276 register struct mkfifo_args /* {
1282 return (kern_mkfifo(td, uap->path, UIO_USERSPACE, uap->mode));
1286 kern_mkfifo(struct thread *td, char *path, enum uio_seg pathseg, int mode)
1291 struct nameidata nd;
1296 NDINIT(&nd, CREATE, LOCKPARENT | SAVENAME | MPSAFE, pathseg, path, td);
1297 if ((error = namei(&nd)) != 0)
1299 vfslocked = NDHASGIANT(&nd);
1300 if (nd.ni_vp != NULL) {
1301 NDFREE(&nd, NDF_ONLY_PNBUF);
1303 if (nd.ni_vp == nd.ni_dvp)
1307 VFS_UNLOCK_GIANT(vfslocked);
1310 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) {
1311 NDFREE(&nd, NDF_ONLY_PNBUF);
1313 VFS_UNLOCK_GIANT(vfslocked);
1314 if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0)
1319 vattr.va_type = VFIFO;
1320 FILEDESC_LOCK_FAST(td->td_proc->p_fd);
1321 vattr.va_mode = (mode & ALLPERMS) & ~td->td_proc->p_fd->fd_cmask;
1322 FILEDESC_UNLOCK_FAST(td->td_proc->p_fd);
1324 error = mac_check_vnode_create(td->td_ucred, nd.ni_dvp, &nd.ni_cnd,
1329 VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
1330 error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
1337 vn_finished_write(mp);
1338 VFS_UNLOCK_GIANT(vfslocked);
1339 NDFREE(&nd, NDF_ONLY_PNBUF);
1344 * Make a hard file link.
1346 #ifndef _SYS_SYSPROTO_H_
1355 register struct link_args /* {
1362 error = kern_link(td, uap->path, uap->link, UIO_USERSPACE);
1366 SYSCTL_DECL(_security_bsd);
1368 static int hardlink_check_uid = 0;
1369 SYSCTL_INT(_security_bsd, OID_AUTO, hardlink_check_uid, CTLFLAG_RW,
1370 &hardlink_check_uid, 0,
1371 "Unprivileged processes cannot create hard links to files owned by other "
1373 static int hardlink_check_gid = 0;
1374 SYSCTL_INT(_security_bsd, OID_AUTO, hardlink_check_gid, CTLFLAG_RW,
1375 &hardlink_check_gid, 0,
1376 "Unprivileged processes cannot create hard links to files owned by other "
1380 can_hardlink(struct vnode *vp, struct thread *td, struct ucred *cred)
1385 if (suser_cred(cred, SUSER_ALLOWJAIL) == 0)
1388 if (!hardlink_check_uid && !hardlink_check_gid)
1391 error = VOP_GETATTR(vp, &va, cred, td);
1395 if (hardlink_check_uid) {
1396 if (cred->cr_uid != va.va_uid)
1400 if (hardlink_check_gid) {
1401 if (!groupmember(va.va_gid, cred))
1409 kern_link(struct thread *td, char *path, char *link, enum uio_seg segflg)
1413 struct nameidata nd;
1419 NDINIT(&nd, LOOKUP, FOLLOW | MPSAFE, segflg, path, td);
1420 if ((error = namei(&nd)) != 0)
1422 vfslocked = NDHASGIANT(&nd);
1423 NDFREE(&nd, NDF_ONLY_PNBUF);
1425 if (vp->v_type == VDIR) {
1427 VFS_UNLOCK_GIANT(vfslocked);
1428 return (EPERM); /* POSIX */
1430 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) {
1432 VFS_UNLOCK_GIANT(vfslocked);
1435 NDINIT(&nd, CREATE, LOCKPARENT | SAVENAME, segflg, link, td);
1436 if ((error = namei(&nd)) == 0) {
1437 lvfslocked = NDHASGIANT(&nd);
1438 if (nd.ni_vp != NULL) {
1440 if (nd.ni_dvp == nd.ni_vp)
1445 } else if ((error = vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td))
1447 VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
1448 VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
1449 error = can_hardlink(vp, td, td->td_ucred);
1452 error = mac_check_vnode_link(td->td_ucred,
1453 nd.ni_dvp, vp, &nd.ni_cnd);
1456 error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd);
1457 VOP_UNLOCK(vp, 0, td);
1460 NDFREE(&nd, NDF_ONLY_PNBUF);
1461 VFS_UNLOCK_GIANT(lvfslocked);
1464 vn_finished_write(mp);
1465 VFS_UNLOCK_GIANT(vfslocked);
1466 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "link");
1467 ASSERT_VOP_UNLOCKED(nd.ni_vp, "link");
1472 * Make a symbolic link.
1474 #ifndef _SYS_SYSPROTO_H_
1475 struct symlink_args {
1483 register struct symlink_args /* {
1489 return (kern_symlink(td, uap->path, uap->link, UIO_USERSPACE));
1493 kern_symlink(struct thread *td, char *path, char *link, enum uio_seg segflg)
1499 struct nameidata nd;
1502 if (segflg == UIO_SYSSPACE) {
1505 syspath = uma_zalloc(namei_zone, M_WAITOK);
1506 if ((error = copyinstr(path, syspath, MAXPATHLEN, NULL)) != 0)
1511 NDINIT(&nd, CREATE, LOCKPARENT | SAVENAME | MPSAFE,
1513 if ((error = namei(&nd)) != 0)
1515 vfslocked = NDHASGIANT(&nd);
1517 NDFREE(&nd, NDF_ONLY_PNBUF);
1519 if (nd.ni_vp == nd.ni_dvp)
1523 VFS_UNLOCK_GIANT(vfslocked);
1527 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) {
1528 NDFREE(&nd, NDF_ONLY_PNBUF);
1530 VFS_UNLOCK_GIANT(vfslocked);
1531 if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0)
1536 FILEDESC_LOCK_FAST(td->td_proc->p_fd);
1537 vattr.va_mode = ACCESSPERMS &~ td->td_proc->p_fd->fd_cmask;
1538 FILEDESC_UNLOCK_FAST(td->td_proc->p_fd);
1540 vattr.va_type = VLNK;
1541 error = mac_check_vnode_create(td->td_ucred, nd.ni_dvp, &nd.ni_cnd,
1546 VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
1547 error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr, syspath);
1553 NDFREE(&nd, NDF_ONLY_PNBUF);
1555 vn_finished_write(mp);
1556 VFS_UNLOCK_GIANT(vfslocked);
1557 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "symlink");
1558 ASSERT_VOP_UNLOCKED(nd.ni_vp, "symlink");
1560 if (segflg != UIO_SYSSPACE)
1561 uma_zfree(namei_zone, syspath);
1566 * Delete a whiteout from the filesystem.
1571 register struct undelete_args /* {
1577 struct nameidata nd;
1582 NDINIT(&nd, DELETE, LOCKPARENT | DOWHITEOUT | MPSAFE, UIO_USERSPACE,
1587 vfslocked = NDHASGIANT(&nd);
1589 if (nd.ni_vp != NULLVP || !(nd.ni_cnd.cn_flags & ISWHITEOUT)) {
1590 NDFREE(&nd, NDF_ONLY_PNBUF);
1593 if (nd.ni_vp == nd.ni_dvp)
1597 VFS_UNLOCK_GIANT(vfslocked);
1600 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) {
1601 NDFREE(&nd, NDF_ONLY_PNBUF);
1603 VFS_UNLOCK_GIANT(vfslocked);
1604 if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0)
1608 VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
1609 error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, DELETE);
1610 NDFREE(&nd, NDF_ONLY_PNBUF);
1612 vn_finished_write(mp);
1613 VFS_UNLOCK_GIANT(vfslocked);
1614 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "undelete");
1615 ASSERT_VOP_UNLOCKED(nd.ni_vp, "undelete");
1620 * Delete a name from the filesystem.
1622 #ifndef _SYS_SYSPROTO_H_
1623 struct unlink_args {
1630 struct unlink_args /* {
1636 error = kern_unlink(td, uap->path, UIO_USERSPACE);
1641 kern_unlink(struct thread *td, char *path, enum uio_seg pathseg)
1646 struct nameidata nd;
1651 NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF | MPSAFE, pathseg, path, td);
1652 if ((error = namei(&nd)) != 0)
1654 vfslocked = NDHASGIANT(&nd);
1656 if (vp->v_type == VDIR)
1657 error = EPERM; /* POSIX */
1660 * The root of a mounted filesystem cannot be deleted.
1662 * XXX: can this only be a VDIR case?
1664 if (vp->v_vflag & VV_ROOT)
1668 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) {
1669 NDFREE(&nd, NDF_ONLY_PNBUF);
1670 if (vp == nd.ni_dvp)
1675 VFS_UNLOCK_GIANT(vfslocked);
1676 if ((error = vn_start_write(NULL, &mp,
1677 V_XSLEEP | PCATCH)) != 0)
1682 error = mac_check_vnode_delete(td->td_ucred, nd.ni_dvp, vp,
1687 VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
1688 error = VOP_REMOVE(nd.ni_dvp, vp, &nd.ni_cnd);
1692 vn_finished_write(mp);
1694 NDFREE(&nd, NDF_ONLY_PNBUF);
1695 if (vp == nd.ni_dvp)
1700 VFS_UNLOCK_GIANT(vfslocked);
1701 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "unlink");
1702 ASSERT_VOP_UNLOCKED(nd.ni_vp, "unlink");
1707 * Reposition read/write file offset.
1709 #ifndef _SYS_SYSPROTO_H_
1720 register struct lseek_args /* {
1727 struct ucred *cred = td->td_ucred;
1735 if ((error = fget(td, uap->fd, &fp)) != 0)
1737 if (!(fp->f_ops->fo_flags & DFLAG_SEEKABLE)) {
1742 vfslocked = VFS_LOCK_GIANT(vp->v_mount);
1743 noneg = (vp->v_type != VCHR);
1744 offset = uap->offset;
1745 switch (uap->whence) {
1748 (fp->f_offset < 0 ||
1749 (offset > 0 && fp->f_offset > OFF_MAX - offset))) {
1753 offset += fp->f_offset;
1756 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
1757 error = VOP_GETATTR(vp, &vattr, cred, td);
1758 VOP_UNLOCK(vp, 0, td);
1762 (vattr.va_size > OFF_MAX ||
1763 (offset > 0 && vattr.va_size > OFF_MAX - offset))) {
1767 offset += vattr.va_size;
1774 if (error == 0 && noneg && offset < 0)
1778 fp->f_offset = offset;
1779 *(off_t *)(td->td_retval) = fp->f_offset;
1782 VFS_UNLOCK_GIANT(vfslocked);
1786 #if defined(COMPAT_43)
1788 * Reposition read/write file offset.
1790 #ifndef _SYS_SYSPROTO_H_
1791 struct olseek_args {
1800 register struct olseek_args /* {
1806 struct lseek_args /* {
1815 nuap.offset = uap->offset;
1816 nuap.whence = uap->whence;
1817 error = lseek(td, &nuap);
1820 #endif /* COMPAT_43 */
1823 * Check access permissions using passed credentials.
1826 vn_access(vp, user_flags, cred, td)
1834 /* Flags == 0 means only check for existence. */
1838 if (user_flags & R_OK)
1840 if (user_flags & W_OK)
1842 if (user_flags & X_OK)
1845 error = mac_check_vnode_access(cred, vp, flags);
1849 if ((flags & VWRITE) == 0 || (error = vn_writechk(vp)) == 0)
1850 error = VOP_ACCESS(vp, flags, cred, td);
1856 * Check access permissions using "real" credentials.
1858 #ifndef _SYS_SYSPROTO_H_
1859 struct access_args {
1867 register struct access_args /* {
1873 return (kern_access(td, uap->path, UIO_USERSPACE, uap->flags));
1877 kern_access(struct thread *td, char *path, enum uio_seg pathseg, int flags)
1879 struct ucred *cred, *tmpcred;
1880 register struct vnode *vp;
1881 struct nameidata nd;
1886 * Create and modify a temporary credential instead of one that
1887 * is potentially shared. This could also mess up socket
1888 * buffer accounting which can run in an interrupt context.
1890 cred = td->td_ucred;
1891 tmpcred = crdup(cred);
1892 tmpcred->cr_uid = cred->cr_ruid;
1893 tmpcred->cr_groups[0] = cred->cr_rgid;
1894 td->td_ucred = tmpcred;
1895 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | MPSAFE, pathseg, path, td);
1896 if ((error = namei(&nd)) != 0)
1898 vfslocked = NDHASGIANT(&nd);
1901 error = vn_access(vp, flags, tmpcred, td);
1902 NDFREE(&nd, NDF_ONLY_PNBUF);
1904 VFS_UNLOCK_GIANT(vfslocked);
1906 td->td_ucred = cred;
1912 * Check access permissions using "effective" credentials.
1914 #ifndef _SYS_SYSPROTO_H_
1915 struct eaccess_args {
1923 register struct eaccess_args /* {
1928 struct nameidata nd;
1933 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | MPSAFE, UIO_USERSPACE,
1935 if ((error = namei(&nd)) != 0)
1938 vfslocked = NDHASGIANT(&nd);
1939 error = vn_access(vp, uap->flags, td->td_ucred, td);
1940 NDFREE(&nd, NDF_ONLY_PNBUF);
1942 VFS_UNLOCK_GIANT(vfslocked);
1946 #if defined(COMPAT_43)
1948 * Get file status; this version follows links.
1950 #ifndef _SYS_SYSPROTO_H_
1959 register struct ostat_args /* {
1968 error = kern_stat(td, uap->path, UIO_USERSPACE, &sb);
1972 error = copyout(&osb, uap->ub, sizeof (osb));
1977 * Get file status; this version does not follow links.
1979 #ifndef _SYS_SYSPROTO_H_
1980 struct olstat_args {
1988 register struct olstat_args /* {
1997 error = kern_lstat(td, uap->path, UIO_USERSPACE, &sb);
2001 error = copyout(&osb, uap->ub, sizeof (osb));
2006 * Convert from an old to a new stat structure.
2014 ost->st_dev = st->st_dev;
2015 ost->st_ino = st->st_ino;
2016 ost->st_mode = st->st_mode;
2017 ost->st_nlink = st->st_nlink;
2018 ost->st_uid = st->st_uid;
2019 ost->st_gid = st->st_gid;
2020 ost->st_rdev = st->st_rdev;
2021 if (st->st_size < (quad_t)1 << 32)
2022 ost->st_size = st->st_size;
2025 ost->st_atime = st->st_atime;
2026 ost->st_mtime = st->st_mtime;
2027 ost->st_ctime = st->st_ctime;
2028 ost->st_blksize = st->st_blksize;
2029 ost->st_blocks = st->st_blocks;
2030 ost->st_flags = st->st_flags;
2031 ost->st_gen = st->st_gen;
2033 #endif /* COMPAT_43 */
2036 * Get file status; this version follows links.
2038 #ifndef _SYS_SYSPROTO_H_
2047 register struct stat_args /* {
2055 error = kern_stat(td, uap->path, UIO_USERSPACE, &sb);
2057 error = copyout(&sb, uap->ub, sizeof (sb));
2062 kern_stat(struct thread *td, char *path, enum uio_seg pathseg, struct stat *sbp)
2064 struct nameidata nd;
2066 int error, vfslocked;
2068 NDINIT(&nd, LOOKUP, FOLLOW | LOCKSHARED | LOCKLEAF | MPSAFE,
2070 if ((error = namei(&nd)) != 0)
2072 vfslocked = NDHASGIANT(&nd);
2073 error = vn_stat(nd.ni_vp, &sb, td->td_ucred, NOCRED, td);
2074 NDFREE(&nd, NDF_ONLY_PNBUF);
2076 VFS_UNLOCK_GIANT(vfslocked);
2084 * Get file status; this version does not follow links.
2086 #ifndef _SYS_SYSPROTO_H_
2095 register struct lstat_args /* {
2103 error = kern_lstat(td, uap->path, UIO_USERSPACE, &sb);
2105 error = copyout(&sb, uap->ub, sizeof (sb));
2110 kern_lstat(struct thread *td, char *path, enum uio_seg pathseg, struct stat *sbp)
2114 struct nameidata nd;
2115 int error, vfslocked;
2117 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | LOCKSHARED | MPSAFE,
2119 if ((error = namei(&nd)) != 0)
2121 vfslocked = NDHASGIANT(&nd);
2123 error = vn_stat(vp, &sb, td->td_ucred, NOCRED, td);
2124 NDFREE(&nd, NDF_ONLY_PNBUF);
2126 VFS_UNLOCK_GIANT(vfslocked);
2134 * Implementation of the NetBSD [l]stat() functions.
2141 bzero(nsb, sizeof *nsb);
2142 nsb->st_dev = sb->st_dev;
2143 nsb->st_ino = sb->st_ino;
2144 nsb->st_mode = sb->st_mode;
2145 nsb->st_nlink = sb->st_nlink;
2146 nsb->st_uid = sb->st_uid;
2147 nsb->st_gid = sb->st_gid;
2148 nsb->st_rdev = sb->st_rdev;
2149 nsb->st_atimespec = sb->st_atimespec;
2150 nsb->st_mtimespec = sb->st_mtimespec;
2151 nsb->st_ctimespec = sb->st_ctimespec;
2152 nsb->st_size = sb->st_size;
2153 nsb->st_blocks = sb->st_blocks;
2154 nsb->st_blksize = sb->st_blksize;
2155 nsb->st_flags = sb->st_flags;
2156 nsb->st_gen = sb->st_gen;
2157 nsb->st_birthtimespec = sb->st_birthtimespec;
2160 #ifndef _SYS_SYSPROTO_H_
2169 register struct nstat_args /* {
2178 error = kern_stat(td, uap->path, UIO_USERSPACE, &sb);
2181 cvtnstat(&sb, &nsb);
2182 error = copyout(&nsb, uap->ub, sizeof (nsb));
2187 * NetBSD lstat. Get file status; this version does not follow links.
2189 #ifndef _SYS_SYSPROTO_H_
2198 register struct nlstat_args /* {
2207 error = kern_lstat(td, uap->path, UIO_USERSPACE, &sb);
2210 cvtnstat(&sb, &nsb);
2211 error = copyout(&nsb, uap->ub, sizeof (nsb));
2216 * Get configurable pathname variables.
2218 #ifndef _SYS_SYSPROTO_H_
2219 struct pathconf_args {
2227 register struct pathconf_args /* {
2233 return (kern_pathconf(td, uap->path, UIO_USERSPACE, uap->name));
2237 kern_pathconf(struct thread *td, char *path, enum uio_seg pathseg, int name)
2239 struct nameidata nd;
2240 int error, vfslocked;
2242 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | MPSAFE, pathseg, path, td);
2243 if ((error = namei(&nd)) != 0)
2245 vfslocked = NDHASGIANT(&nd);
2246 NDFREE(&nd, NDF_ONLY_PNBUF);
2248 /* If asynchronous I/O is available, it works for all files. */
2249 if (name == _PC_ASYNC_IO)
2250 td->td_retval[0] = async_io_version;
2252 error = VOP_PATHCONF(nd.ni_vp, name, td->td_retval);
2254 VFS_UNLOCK_GIANT(vfslocked);
2259 * Return target name of a symbolic link.
2261 #ifndef _SYS_SYSPROTO_H_
2262 struct readlink_args {
2271 register struct readlink_args /* {
2278 return (kern_readlink(td, uap->path, UIO_USERSPACE, uap->buf,
2279 UIO_USERSPACE, uap->count));
2283 kern_readlink(struct thread *td, char *path, enum uio_seg pathseg, char *buf,
2284 enum uio_seg bufseg, int count)
2286 register struct vnode *vp;
2290 struct nameidata nd;
2293 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | MPSAFE, pathseg, path, td);
2294 if ((error = namei(&nd)) != 0)
2296 NDFREE(&nd, NDF_ONLY_PNBUF);
2297 vfslocked = NDHASGIANT(&nd);
2300 error = mac_check_vnode_readlink(td->td_ucred, vp);
2303 VFS_UNLOCK_GIANT(vfslocked);
2307 if (vp->v_type != VLNK)
2310 aiov.iov_base = buf;
2311 aiov.iov_len = count;
2312 auio.uio_iov = &aiov;
2313 auio.uio_iovcnt = 1;
2314 auio.uio_offset = 0;
2315 auio.uio_rw = UIO_READ;
2316 auio.uio_segflg = bufseg;
2318 auio.uio_resid = count;
2319 error = VOP_READLINK(vp, &auio, td->td_ucred);
2322 VFS_UNLOCK_GIANT(vfslocked);
2323 td->td_retval[0] = count - auio.uio_resid;
2328 * Common implementation code for chflags() and fchflags().
2331 setfflags(td, vp, flags)
2341 * Prevent non-root users from setting flags on devices. When
2342 * a device is reused, users can retain ownership of the device
2343 * if they are allowed to set flags and programs assume that
2344 * chown can't fail when done as root.
2346 if (vp->v_type == VCHR || vp->v_type == VBLK) {
2347 error = suser_cred(td->td_ucred, SUSER_ALLOWJAIL);
2352 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
2354 VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
2355 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
2357 vattr.va_flags = flags;
2359 error = mac_check_vnode_setflags(td->td_ucred, vp, vattr.va_flags);
2362 error = VOP_SETATTR(vp, &vattr, td->td_ucred, td);
2363 VOP_UNLOCK(vp, 0, td);
2364 vn_finished_write(mp);
2369 * Change flags of a file given a path name.
2371 #ifndef _SYS_SYSPROTO_H_
2372 struct chflags_args {
2380 register struct chflags_args /* {
2386 struct nameidata nd;
2389 NDINIT(&nd, LOOKUP, FOLLOW | MPSAFE, UIO_USERSPACE, uap->path, td);
2390 if ((error = namei(&nd)) != 0)
2392 NDFREE(&nd, NDF_ONLY_PNBUF);
2393 vfslocked = NDHASGIANT(&nd);
2394 error = setfflags(td, nd.ni_vp, uap->flags);
2396 VFS_UNLOCK_GIANT(vfslocked);
2401 * Same as chflags() but doesn't follow symlinks.
2406 register struct lchflags_args /* {
2412 struct nameidata nd;
2415 NDINIT(&nd, LOOKUP, NOFOLLOW | MPSAFE, UIO_USERSPACE, uap->path, td);
2416 if ((error = namei(&nd)) != 0)
2418 vfslocked = NDHASGIANT(&nd);
2419 NDFREE(&nd, NDF_ONLY_PNBUF);
2420 error = setfflags(td, nd.ni_vp, uap->flags);
2422 VFS_UNLOCK_GIANT(vfslocked);
2427 * Change flags of a file given a file descriptor.
2429 #ifndef _SYS_SYSPROTO_H_
2430 struct fchflags_args {
2438 register struct fchflags_args /* {
2447 if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0)
2449 vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount);
2450 error = setfflags(td, fp->f_vnode, uap->flags);
2452 VFS_UNLOCK_GIANT(vfslocked);
2457 * Common implementation code for chmod(), lchmod() and fchmod().
2460 setfmode(td, vp, mode)
2469 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
2471 VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
2472 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
2474 vattr.va_mode = mode & ALLPERMS;
2476 error = mac_check_vnode_setmode(td->td_ucred, vp, vattr.va_mode);
2479 error = VOP_SETATTR(vp, &vattr, td->td_ucred, td);
2480 VOP_UNLOCK(vp, 0, td);
2481 vn_finished_write(mp);
2486 * Change mode of a file given path name.
2488 #ifndef _SYS_SYSPROTO_H_
2497 register struct chmod_args /* {
2503 return (kern_chmod(td, uap->path, UIO_USERSPACE, uap->mode));
2507 kern_chmod(struct thread *td, char *path, enum uio_seg pathseg, int mode)
2510 struct nameidata nd;
2513 NDINIT(&nd, LOOKUP, FOLLOW | MPSAFE, pathseg, path, td);
2514 if ((error = namei(&nd)) != 0)
2516 vfslocked = NDHASGIANT(&nd);
2517 NDFREE(&nd, NDF_ONLY_PNBUF);
2518 error = setfmode(td, nd.ni_vp, mode);
2520 VFS_UNLOCK_GIANT(vfslocked);
2525 * Change mode of a file given path name (don't follow links.)
2527 #ifndef _SYS_SYSPROTO_H_
2528 struct lchmod_args {
2536 register struct lchmod_args /* {
2542 struct nameidata nd;
2545 NDINIT(&nd, LOOKUP, NOFOLLOW | MPSAFE, UIO_USERSPACE, uap->path, td);
2546 if ((error = namei(&nd)) != 0)
2548 vfslocked = NDHASGIANT(&nd);
2549 NDFREE(&nd, NDF_ONLY_PNBUF);
2550 error = setfmode(td, nd.ni_vp, uap->mode);
2552 VFS_UNLOCK_GIANT(vfslocked);
2557 * Change mode of a file given a file descriptor.
2559 #ifndef _SYS_SYSPROTO_H_
2560 struct fchmod_args {
2568 register struct fchmod_args /* {
2577 if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0)
2579 vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount);
2580 error = setfmode(td, fp->f_vnode, uap->mode);
2582 VFS_UNLOCK_GIANT(vfslocked);
2587 * Common implementation for chown(), lchown(), and fchown()
2590 setfown(td, vp, uid, gid)
2600 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
2602 VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
2603 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
2608 error = mac_check_vnode_setowner(td->td_ucred, vp, vattr.va_uid,
2612 error = VOP_SETATTR(vp, &vattr, td->td_ucred, td);
2613 VOP_UNLOCK(vp, 0, td);
2614 vn_finished_write(mp);
2619 * Set ownership given a path name.
2621 #ifndef _SYS_SYSPROTO_H_
2631 register struct chown_args /* {
2638 return (kern_chown(td, uap->path, UIO_USERSPACE, uap->uid, uap->gid));
2642 kern_chown(struct thread *td, char *path, enum uio_seg pathseg, int uid,
2646 struct nameidata nd;
2649 NDINIT(&nd, LOOKUP, FOLLOW | MPSAFE, pathseg, path, td);
2650 if ((error = namei(&nd)) != 0)
2652 vfslocked = NDHASGIANT(&nd);
2653 NDFREE(&nd, NDF_ONLY_PNBUF);
2654 error = setfown(td, nd.ni_vp, uid, gid);
2656 VFS_UNLOCK_GIANT(vfslocked);
2661 * Set ownership given a path name, do not cross symlinks.
2663 #ifndef _SYS_SYSPROTO_H_
2664 struct lchown_args {
2673 register struct lchown_args /* {
2680 return (kern_lchown(td, uap->path, UIO_USERSPACE, uap->uid, uap->gid));
2684 kern_lchown(struct thread *td, char *path, enum uio_seg pathseg, int uid,
2688 struct nameidata nd;
2691 NDINIT(&nd, LOOKUP, NOFOLLOW | MPSAFE, pathseg, path, td);
2692 if ((error = namei(&nd)) != 0)
2694 vfslocked = NDHASGIANT(&nd);
2695 NDFREE(&nd, NDF_ONLY_PNBUF);
2696 error = setfown(td, nd.ni_vp, uid, gid);
2698 VFS_UNLOCK_GIANT(vfslocked);
2703 * Set ownership given a file descriptor.
2705 #ifndef _SYS_SYSPROTO_H_
2706 struct fchown_args {
2715 register struct fchown_args /* {
2725 if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0)
2727 vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount);
2728 error = setfown(td, fp->f_vnode, uap->uid, uap->gid);
2730 VFS_UNLOCK_GIANT(vfslocked);
2735 * Common implementation code for utimes(), lutimes(), and futimes().
2738 getutimes(usrtvp, tvpseg, tsp)
2739 const struct timeval *usrtvp;
2740 enum uio_seg tvpseg;
2741 struct timespec *tsp;
2743 struct timeval tv[2];
2744 const struct timeval *tvp;
2747 if (usrtvp == NULL) {
2749 TIMEVAL_TO_TIMESPEC(&tv[0], &tsp[0]);
2752 if (tvpseg == UIO_SYSSPACE) {
2755 if ((error = copyin(usrtvp, tv, sizeof(tv))) != 0)
2760 TIMEVAL_TO_TIMESPEC(&tvp[0], &tsp[0]);
2761 TIMEVAL_TO_TIMESPEC(&tvp[1], &tsp[1]);
2767 * Common implementation code for utimes(), lutimes(), and futimes().
2770 setutimes(td, vp, ts, numtimes, nullflag)
2773 const struct timespec *ts;
2777 int error, setbirthtime;
2781 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
2783 VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
2784 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
2786 if (numtimes < 3 && VOP_GETATTR(vp, &vattr, td->td_ucred, td) == 0 &&
2787 timespeccmp(&ts[1], &vattr.va_birthtime, < ))
2790 vattr.va_atime = ts[0];
2791 vattr.va_mtime = ts[1];
2793 vattr.va_birthtime = ts[1];
2795 vattr.va_birthtime = ts[2];
2797 vattr.va_vaflags |= VA_UTIMES_NULL;
2799 error = mac_check_vnode_setutimes(td->td_ucred, vp, vattr.va_atime,
2803 error = VOP_SETATTR(vp, &vattr, td->td_ucred, td);
2804 VOP_UNLOCK(vp, 0, td);
2805 vn_finished_write(mp);
2810 * Set the access and modification times of a file.
2812 #ifndef _SYS_SYSPROTO_H_
2813 struct utimes_args {
2815 struct timeval *tptr;
2821 register struct utimes_args /* {
2823 struct timeval *tptr;
2827 return (kern_utimes(td, uap->path, UIO_USERSPACE, uap->tptr,
2832 kern_utimes(struct thread *td, char *path, enum uio_seg pathseg,
2833 struct timeval *tptr, enum uio_seg tptrseg)
2835 struct timespec ts[2];
2837 struct nameidata nd;
2840 if ((error = getutimes(tptr, tptrseg, ts)) != 0)
2842 NDINIT(&nd, LOOKUP, FOLLOW | MPSAFE, pathseg, path, td);
2843 if ((error = namei(&nd)) != 0)
2845 vfslocked = NDHASGIANT(&nd);
2846 NDFREE(&nd, NDF_ONLY_PNBUF);
2847 error = setutimes(td, nd.ni_vp, ts, 2, tptr == NULL);
2849 VFS_UNLOCK_GIANT(vfslocked);
2854 * Set the access and modification times of a file.
2856 #ifndef _SYS_SYSPROTO_H_
2857 struct lutimes_args {
2859 struct timeval *tptr;
2865 register struct lutimes_args /* {
2867 struct timeval *tptr;
2871 return (kern_lutimes(td, uap->path, UIO_USERSPACE, uap->tptr,
2876 kern_lutimes(struct thread *td, char *path, enum uio_seg pathseg,
2877 struct timeval *tptr, enum uio_seg tptrseg)
2879 struct timespec ts[2];
2881 struct nameidata nd;
2884 if ((error = getutimes(tptr, tptrseg, ts)) != 0)
2886 NDINIT(&nd, LOOKUP, NOFOLLOW | MPSAFE, pathseg, path, td);
2887 if ((error = namei(&nd)) != 0)
2889 vfslocked = NDHASGIANT(&nd);
2890 NDFREE(&nd, NDF_ONLY_PNBUF);
2891 error = setutimes(td, nd.ni_vp, ts, 2, tptr == NULL);
2893 VFS_UNLOCK_GIANT(vfslocked);
2898 * Set the access and modification times of a file.
2900 #ifndef _SYS_SYSPROTO_H_
2901 struct futimes_args {
2903 struct timeval *tptr;
2909 register struct futimes_args /* {
2911 struct timeval *tptr;
2915 return (kern_futimes(td, uap->fd, uap->tptr, UIO_USERSPACE));
2919 kern_futimes(struct thread *td, int fd, struct timeval *tptr,
2920 enum uio_seg tptrseg)
2922 struct timespec ts[2];
2927 if ((error = getutimes(tptr, tptrseg, ts)) != 0)
2929 if ((error = getvnode(td->td_proc->p_fd, fd, &fp)) != 0)
2931 vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount);
2932 error = setutimes(td, fp->f_vnode, ts, 2, tptr == NULL);
2934 VFS_UNLOCK_GIANT(vfslocked);
2939 * Truncate a file given its path name.
2941 #ifndef _SYS_SYSPROTO_H_
2942 struct truncate_args {
2951 register struct truncate_args /* {
2958 return (kern_truncate(td, uap->path, UIO_USERSPACE, uap->length));
2962 kern_truncate(struct thread *td, char *path, enum uio_seg pathseg, off_t length)
2968 struct nameidata nd;
2973 NDINIT(&nd, LOOKUP, FOLLOW | MPSAFE, pathseg, path, td);
2974 if ((error = namei(&nd)) != 0)
2976 vfslocked = NDHASGIANT(&nd);
2978 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) {
2980 VFS_UNLOCK_GIANT(vfslocked);
2983 NDFREE(&nd, NDF_ONLY_PNBUF);
2984 VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
2985 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
2986 if (vp->v_type == VDIR)
2989 else if ((error = mac_check_vnode_write(td->td_ucred, NOCRED, vp))) {
2992 else if ((error = vn_writechk(vp)) == 0 &&
2993 (error = VOP_ACCESS(vp, VWRITE, td->td_ucred, td)) == 0) {
2995 vattr.va_size = length;
2996 error = VOP_SETATTR(vp, &vattr, td->td_ucred, td);
2999 vn_finished_write(mp);
3000 VFS_UNLOCK_GIANT(vfslocked);
3005 * Truncate a file given a file descriptor.
3007 #ifndef _SYS_SYSPROTO_H_
3008 struct ftruncate_args {
3017 register struct ftruncate_args /* {
3030 if (uap->length < 0)
3032 if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0)
3034 if ((fp->f_flag & FWRITE) == 0) {
3039 vfslocked = VFS_LOCK_GIANT(vp->v_mount);
3040 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
3042 VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
3043 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
3044 if (vp->v_type == VDIR)
3047 else if ((error = mac_check_vnode_write(td->td_ucred, fp->f_cred,
3051 else if ((error = vn_writechk(vp)) == 0) {
3053 vattr.va_size = uap->length;
3054 error = VOP_SETATTR(vp, &vattr, fp->f_cred, td);
3056 VOP_UNLOCK(vp, 0, td);
3057 vn_finished_write(mp);
3059 VFS_UNLOCK_GIANT(vfslocked);
3064 #if defined(COMPAT_43)
3066 * Truncate a file given its path name.
3068 #ifndef _SYS_SYSPROTO_H_
3069 struct otruncate_args {
3077 register struct otruncate_args /* {
3082 struct truncate_args /* {
3088 nuap.path = uap->path;
3089 nuap.length = uap->length;
3090 return (truncate(td, &nuap));
3094 * Truncate a file given a file descriptor.
3096 #ifndef _SYS_SYSPROTO_H_
3097 struct oftruncate_args {
3105 register struct oftruncate_args /* {
3110 struct ftruncate_args /* {
3117 nuap.length = uap->length;
3118 return (ftruncate(td, &nuap));
3120 #endif /* COMPAT_43 */
3123 * Sync an open file.
3125 #ifndef _SYS_SYSPROTO_H_
3133 struct fsync_args /* {
3143 if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0)
3146 vfslocked = VFS_LOCK_GIANT(vp->v_mount);
3147 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
3149 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
3150 if (vp->v_object != NULL) {
3151 VM_OBJECT_LOCK(vp->v_object);
3152 vm_object_page_clean(vp->v_object, 0, 0, 0);
3153 VM_OBJECT_UNLOCK(vp->v_object);
3155 error = VOP_FSYNC(vp, MNT_WAIT, td);
3157 VOP_UNLOCK(vp, 0, td);
3158 vn_finished_write(mp);
3160 VFS_UNLOCK_GIANT(vfslocked);
3166 * Rename files. Source and destination must either both be directories,
3167 * or both not be directories. If target is a directory, it must be empty.
3169 #ifndef _SYS_SYSPROTO_H_
3170 struct rename_args {
3178 register struct rename_args /* {
3184 return (kern_rename(td, uap->from, uap->to, UIO_USERSPACE));
3188 kern_rename(struct thread *td, char *from, char *to, enum uio_seg pathseg)
3190 struct mount *mp = NULL;
3191 struct vnode *tvp, *fvp, *tdvp;
3192 struct nameidata fromnd, tond;
3199 NDINIT(&fromnd, DELETE, LOCKPARENT | LOCKLEAF | SAVESTART | MPSAFE,
3202 NDINIT(&fromnd, DELETE, WANTPARENT | SAVESTART | MPSAFE,
3205 if ((error = namei(&fromnd)) != 0)
3207 fvfslocked = NDHASGIANT(&fromnd);
3210 error = mac_check_vnode_rename_from(td->td_ucred, fromnd.ni_dvp,
3211 fromnd.ni_vp, &fromnd.ni_cnd);
3212 VOP_UNLOCK(fromnd.ni_dvp, 0, td);
3213 VOP_UNLOCK(fromnd.ni_vp, 0, td);
3217 error = vn_start_write(fvp, &mp, V_WAIT | PCATCH);
3219 NDFREE(&fromnd, NDF_ONLY_PNBUF);
3220 vrele(fromnd.ni_dvp);
3224 NDINIT(&tond, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART |
3225 MPSAFE, pathseg, to, td);
3226 if (fromnd.ni_vp->v_type == VDIR)
3227 tond.ni_cnd.cn_flags |= WILLBEDIR;
3228 if ((error = namei(&tond)) != 0) {
3229 /* Translate error code for rename("dir1", "dir2/."). */
3230 if (error == EISDIR && fvp->v_type == VDIR)
3232 NDFREE(&fromnd, NDF_ONLY_PNBUF);
3233 vrele(fromnd.ni_dvp);
3237 tvfslocked = NDHASGIANT(&tond);
3241 if (fvp->v_type == VDIR && tvp->v_type != VDIR) {
3244 } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) {
3252 * If the source is the same as the destination (that is, if they
3253 * are links to the same vnode), then there is nothing to do.
3259 error = mac_check_vnode_rename_to(td->td_ucred, tdvp,
3260 tond.ni_vp, fromnd.ni_dvp == tdvp, &tond.ni_cnd);
3264 VOP_LEASE(tdvp, td, td->td_ucred, LEASE_WRITE);
3265 if (fromnd.ni_dvp != tdvp) {
3266 VOP_LEASE(fromnd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
3269 VOP_LEASE(tvp, td, td->td_ucred, LEASE_WRITE);
3271 error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd,
3272 tond.ni_dvp, tond.ni_vp, &tond.ni_cnd);
3273 NDFREE(&fromnd, NDF_ONLY_PNBUF);
3274 NDFREE(&tond, NDF_ONLY_PNBUF);
3276 NDFREE(&fromnd, NDF_ONLY_PNBUF);
3277 NDFREE(&tond, NDF_ONLY_PNBUF);
3284 vrele(fromnd.ni_dvp);
3287 vrele(tond.ni_startdir);
3288 ASSERT_VOP_UNLOCKED(fromnd.ni_dvp, "rename");
3289 ASSERT_VOP_UNLOCKED(fromnd.ni_vp, "rename");
3290 ASSERT_VOP_UNLOCKED(tond.ni_dvp, "rename");
3291 ASSERT_VOP_UNLOCKED(tond.ni_vp, "rename");
3293 vn_finished_write(mp);
3294 if (fromnd.ni_startdir)
3295 vrele(fromnd.ni_startdir);
3296 VFS_UNLOCK_GIANT(fvfslocked);
3297 VFS_UNLOCK_GIANT(tvfslocked);
3304 * Make a directory file.
3306 #ifndef _SYS_SYSPROTO_H_
3315 register struct mkdir_args /* {
3321 return (kern_mkdir(td, uap->path, UIO_USERSPACE, uap->mode));
3325 kern_mkdir(struct thread *td, char *path, enum uio_seg segflg, int mode)
3331 struct nameidata nd;
3336 NDINIT(&nd, CREATE, LOCKPARENT | SAVENAME | MPSAFE, segflg, path, td);
3337 nd.ni_cnd.cn_flags |= WILLBEDIR;
3338 if ((error = namei(&nd)) != 0)
3340 vfslocked = NDHASGIANT(&nd);
3343 NDFREE(&nd, NDF_ONLY_PNBUF);
3346 * XXX namei called with LOCKPARENT but not LOCKLEAF has
3347 * the strange behaviour of leaving the vnode unlocked
3348 * if the target is the same vnode as the parent.
3350 if (vp == nd.ni_dvp)
3354 VFS_UNLOCK_GIANT(vfslocked);
3357 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) {
3358 NDFREE(&nd, NDF_ONLY_PNBUF);
3360 VFS_UNLOCK_GIANT(vfslocked);
3361 if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0)
3366 vattr.va_type = VDIR;
3367 FILEDESC_LOCK_FAST(td->td_proc->p_fd);
3368 vattr.va_mode = (mode & ACCESSPERMS) &~ td->td_proc->p_fd->fd_cmask;
3369 FILEDESC_UNLOCK_FAST(td->td_proc->p_fd);
3371 error = mac_check_vnode_create(td->td_ucred, nd.ni_dvp, &nd.ni_cnd,
3376 VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
3377 error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
3381 NDFREE(&nd, NDF_ONLY_PNBUF);
3385 vn_finished_write(mp);
3386 VFS_UNLOCK_GIANT(vfslocked);
3387 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "mkdir");
3388 ASSERT_VOP_UNLOCKED(nd.ni_vp, "mkdir");
3393 * Remove a directory file.
3395 #ifndef _SYS_SYSPROTO_H_
3403 struct rmdir_args /* {
3408 return (kern_rmdir(td, uap->path, UIO_USERSPACE));
3412 kern_rmdir(struct thread *td, char *path, enum uio_seg pathseg)
3417 struct nameidata nd;
3422 NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF | MPSAFE, pathseg, path, td);
3423 if ((error = namei(&nd)) != 0)
3425 vfslocked = NDHASGIANT(&nd);
3427 if (vp->v_type != VDIR) {
3432 * No rmdir "." please.
3434 if (nd.ni_dvp == vp) {
3439 * The root of a mounted filesystem cannot be deleted.
3441 if (vp->v_vflag & VV_ROOT) {
3446 error = mac_check_vnode_delete(td->td_ucred, nd.ni_dvp, vp,
3451 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) {
3452 NDFREE(&nd, NDF_ONLY_PNBUF);
3453 if (nd.ni_dvp == vp)
3458 VFS_UNLOCK_GIANT(vfslocked);
3459 if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0)
3463 VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
3464 VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
3465 error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
3466 vn_finished_write(mp);
3468 NDFREE(&nd, NDF_ONLY_PNBUF);
3469 if (nd.ni_dvp == vp)
3474 VFS_UNLOCK_GIANT(vfslocked);
3475 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "rmdir");
3476 ASSERT_VOP_UNLOCKED(nd.ni_vp, "rmdir");
3482 * Read a block of directory entries in a filesystem independent format.
3484 #ifndef _SYS_SYSPROTO_H_
3485 struct ogetdirentries_args {
3493 ogetdirentries(td, uap)
3495 register struct ogetdirentries_args /* {
3504 struct uio auio, kuio;
3505 struct iovec aiov, kiov;
3506 struct dirent *dp, *edp;
3508 int error, eofflag, readcnt;
3511 /* XXX arbitrary sanity limit on `count'. */
3512 if (uap->count > 64 * 1024)
3514 if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0)
3516 if ((fp->f_flag & FREAD) == 0) {
3522 if (vp->v_type != VDIR) {
3526 aiov.iov_base = uap->buf;
3527 aiov.iov_len = uap->count;
3528 auio.uio_iov = &aiov;
3529 auio.uio_iovcnt = 1;
3530 auio.uio_rw = UIO_READ;
3531 auio.uio_segflg = UIO_USERSPACE;
3533 auio.uio_resid = uap->count;
3534 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
3535 loff = auio.uio_offset = fp->f_offset;
3537 error = mac_check_vnode_readdir(td->td_ucred, vp);
3539 VOP_UNLOCK(vp, 0, td);
3544 # if (BYTE_ORDER != LITTLE_ENDIAN)
3545 if (vp->v_mount->mnt_maxsymlinklen <= 0) {
3546 error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag,
3548 fp->f_offset = auio.uio_offset;
3553 kuio.uio_iov = &kiov;
3554 kuio.uio_segflg = UIO_SYSSPACE;
3555 kiov.iov_len = uap->count;
3556 MALLOC(dirbuf, caddr_t, uap->count, M_TEMP, M_WAITOK);
3557 kiov.iov_base = dirbuf;
3558 error = VOP_READDIR(vp, &kuio, fp->f_cred, &eofflag,
3560 fp->f_offset = kuio.uio_offset;
3562 readcnt = uap->count - kuio.uio_resid;
3563 edp = (struct dirent *)&dirbuf[readcnt];
3564 for (dp = (struct dirent *)dirbuf; dp < edp; ) {
3565 # if (BYTE_ORDER == LITTLE_ENDIAN)
3567 * The expected low byte of
3568 * dp->d_namlen is our dp->d_type.
3569 * The high MBZ byte of dp->d_namlen
3570 * is our dp->d_namlen.
3572 dp->d_type = dp->d_namlen;
3576 * The dp->d_type is the high byte
3577 * of the expected dp->d_namlen,
3578 * so must be zero'ed.
3582 if (dp->d_reclen > 0) {
3583 dp = (struct dirent *)
3584 ((char *)dp + dp->d_reclen);
3591 error = uiomove(dirbuf, readcnt, &auio);
3593 FREE(dirbuf, M_TEMP);
3595 VOP_UNLOCK(vp, 0, td);
3600 if (uap->count == auio.uio_resid) {
3601 if (union_dircheckp) {
3602 error = union_dircheckp(td, &vp, fp);
3611 * XXX We could delay dropping the lock above but
3612 * union_dircheckp complicates things.
3614 vn_lock(vp, LK_EXCLUSIVE|LK_RETRY, td);
3615 if ((vp->v_vflag & VV_ROOT) &&
3616 (vp->v_mount->mnt_flag & MNT_UNION)) {
3617 struct vnode *tvp = vp;
3618 vp = vp->v_mount->mnt_vnodecovered;
3626 VOP_UNLOCK(vp, 0, td);
3628 error = copyout(&loff, uap->basep, sizeof(long));
3630 td->td_retval[0] = uap->count - auio.uio_resid;
3633 #endif /* COMPAT_43 */
3636 * Read a block of directory entries in a filesystem independent format.
3638 #ifndef _SYS_SYSPROTO_H_
3639 struct getdirentries_args {
3647 getdirentries(td, uap)
3649 register struct getdirentries_args /* {
3664 if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0)
3666 if ((fp->f_flag & FREAD) == 0) {
3672 vfslocked = VFS_LOCK_GIANT(vp->v_mount);
3673 if (vp->v_type != VDIR) {
3677 aiov.iov_base = uap->buf;
3678 aiov.iov_len = uap->count;
3679 auio.uio_iov = &aiov;
3680 auio.uio_iovcnt = 1;
3681 auio.uio_rw = UIO_READ;
3682 auio.uio_segflg = UIO_USERSPACE;
3684 auio.uio_resid = uap->count;
3685 /* vn_lock(vp, LK_SHARED | LK_RETRY, td); */
3686 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
3687 loff = auio.uio_offset = fp->f_offset;
3689 error = mac_check_vnode_readdir(td->td_ucred, vp);
3692 error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, NULL,
3694 fp->f_offset = auio.uio_offset;
3695 VOP_UNLOCK(vp, 0, td);
3698 if (uap->count == auio.uio_resid) {
3699 if (union_dircheckp) {
3700 error = union_dircheckp(td, &vp, fp);
3702 VFS_UNLOCK_GIANT(vfslocked);
3709 * XXX We could delay dropping the lock above but
3710 * union_dircheckp complicates things.
3712 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
3713 if ((vp->v_vflag & VV_ROOT) &&
3714 (vp->v_mount->mnt_flag & MNT_UNION)) {
3715 struct vnode *tvp = vp;
3716 vp = vp->v_mount->mnt_vnodecovered;
3722 VFS_UNLOCK_GIANT(vfslocked);
3725 VOP_UNLOCK(vp, 0, td);
3727 if (uap->basep != NULL) {
3728 error = copyout(&loff, uap->basep, sizeof(long));
3730 td->td_retval[0] = uap->count - auio.uio_resid;
3732 VFS_UNLOCK_GIANT(vfslocked);
3736 #ifndef _SYS_SYSPROTO_H_
3737 struct getdents_args {
3746 register struct getdents_args /* {
3752 struct getdirentries_args ap;
3755 ap.count = uap->count;
3757 return (getdirentries(td, &ap));
3761 * Set the mode mask for creation of filesystem nodes.
3765 #ifndef _SYS_SYSPROTO_H_
3773 struct umask_args /* {
3777 register struct filedesc *fdp;
3779 FILEDESC_LOCK_FAST(td->td_proc->p_fd);
3780 fdp = td->td_proc->p_fd;
3781 td->td_retval[0] = fdp->fd_cmask;
3782 fdp->fd_cmask = uap->newmask & ALLPERMS;
3783 FILEDESC_UNLOCK_FAST(td->td_proc->p_fd);
3788 * Void all references to file by ripping underlying filesystem
3791 #ifndef _SYS_SYSPROTO_H_
3792 struct revoke_args {
3799 register struct revoke_args /* {
3806 struct nameidata nd;
3809 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | MPSAFE, UIO_USERSPACE,
3811 if ((error = namei(&nd)) != 0)
3813 vfslocked = NDHASGIANT(&nd);
3815 NDFREE(&nd, NDF_ONLY_PNBUF);
3816 if (vp->v_type != VCHR) {
3821 error = mac_check_vnode_revoke(td->td_ucred, vp);
3825 error = VOP_GETATTR(vp, &vattr, td->td_ucred, td);
3828 if (td->td_ucred->cr_uid != vattr.va_uid) {
3829 error = suser_cred(td->td_ucred, SUSER_ALLOWJAIL);
3834 VOP_REVOKE(vp, REVOKEALL);
3837 VFS_UNLOCK_GIANT(vfslocked);
3842 * Convert a user file descriptor to a kernel file entry.
3843 * A reference on the file entry is held upon returning.
3846 getvnode(fdp, fd, fpp)
3847 struct filedesc *fdp;
3859 if ((u_int)fd >= fdp->fd_nfiles ||
3860 (fp = fdp->fd_ofiles[fd]) == NULL)
3862 else if (fp->f_vnode == NULL) {
3869 FILEDESC_UNLOCK(fdp);
3876 * Get (NFS) file handle
3878 #ifndef _SYS_SYSPROTO_H_
3879 struct lgetfh_args {
3887 register struct lgetfh_args *uap;
3889 struct nameidata nd;
3891 register struct vnode *vp;
3898 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | MPSAFE,
3899 UIO_USERSPACE, uap->fname, td);
3903 vfslocked = NDHASGIANT(&nd);
3904 NDFREE(&nd, NDF_ONLY_PNBUF);
3906 bzero(&fh, sizeof(fh));
3907 fh.fh_fsid = vp->v_mount->mnt_stat.f_fsid;
3908 error = VFS_VPTOFH(vp, &fh.fh_fid);
3910 VFS_UNLOCK_GIANT(vfslocked);
3913 error = copyout(&fh, uap->fhp, sizeof (fh));
3917 #ifndef _SYS_SYSPROTO_H_
3926 register struct getfh_args *uap;
3928 struct nameidata nd;
3930 register struct vnode *vp;
3937 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | MPSAFE,
3938 UIO_USERSPACE, uap->fname, td);
3942 vfslocked = NDHASGIANT(&nd);
3943 NDFREE(&nd, NDF_ONLY_PNBUF);
3945 bzero(&fh, sizeof(fh));
3946 fh.fh_fsid = vp->v_mount->mnt_stat.f_fsid;
3947 error = VFS_VPTOFH(vp, &fh.fh_fid);
3949 VFS_UNLOCK_GIANT(vfslocked);
3952 error = copyout(&fh, uap->fhp, sizeof (fh));
3957 * syscall for the rpc.lockd to use to translate a NFS file handle into
3958 * an open descriptor.
3960 * warning: do not remove the suser() call or this becomes one giant
3965 #ifndef _SYS_SYSPROTO_H_
3966 struct fhopen_args {
3967 const struct fhandle *u_fhp;
3974 struct fhopen_args /* {
3975 const struct fhandle *u_fhp;
3979 struct proc *p = td->td_proc;
3984 struct vattr *vap = &vat;
3987 register struct filedesc *fdp = p->p_fd;
3988 int fmode, mode, error, type;
3995 fmode = FFLAGS(uap->flags);
3996 /* why not allow a non-read/write open for our lockd? */
3997 if (((fmode & (FREAD | FWRITE)) == 0) || (fmode & O_CREAT))
3999 error = copyin(uap->u_fhp, &fhp, sizeof(fhp));
4002 /* find the mount point */
4004 mp = vfs_getvfs(&fhp.fh_fsid);
4009 /* now give me my vnode, it gets returned to me locked */
4010 error = VFS_FHTOVP(mp, &fhp.fh_fid, &vp);
4014 * from now on we have to make sure not
4015 * to forget about the vnode
4016 * any error that causes an abort must vput(vp)
4017 * just set error = err and 'goto bad;'.
4023 if (vp->v_type == VLNK) {
4027 if (vp->v_type == VSOCK) {
4032 if (fmode & (FWRITE | O_TRUNC)) {
4033 if (vp->v_type == VDIR) {
4037 error = vn_writechk(vp);
4044 if (fmode & O_APPEND)
4047 error = mac_check_vnode_open(td->td_ucred, vp, mode);
4052 error = VOP_ACCESS(vp, mode, td->td_ucred, td);
4056 if (fmode & O_TRUNC) {
4057 VOP_UNLOCK(vp, 0, td); /* XXX */
4058 if ((error = vn_start_write(NULL, &mp, V_WAIT | PCATCH)) != 0) {
4062 VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
4063 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); /* XXX */
4066 * We don't yet have fp->f_cred, so use td->td_ucred, which
4069 error = mac_check_vnode_write(td->td_ucred, td->td_ucred, vp);
4074 error = VOP_SETATTR(vp, vap, td->td_ucred, td);
4078 vn_finished_write(mp);
4082 error = VOP_OPEN(vp, fmode, td->td_ucred, td, -1);
4090 * end of vn_open code
4093 if ((error = falloc(td, &nfp, &indx)) != 0) {
4098 /* An extra reference on `nfp' has been held for us by falloc(). */
4103 nfp->f_flag = fmode & FMASK;
4104 nfp->f_ops = &vnops;
4105 nfp->f_type = DTYPE_VNODE;
4106 if (fmode & (O_EXLOCK | O_SHLOCK)) {
4107 lf.l_whence = SEEK_SET;
4110 if (fmode & O_EXLOCK)
4111 lf.l_type = F_WRLCK;
4113 lf.l_type = F_RDLCK;
4115 if ((fmode & FNONBLOCK) == 0)
4117 VOP_UNLOCK(vp, 0, td);
4118 if ((error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf,
4121 * The lock request failed. Normally close the
4122 * descriptor but handle the case where someone might
4123 * have dup()d or close()d it when we weren't looking.
4125 fdclose(fdp, fp, indx, td);
4128 * release our private reference
4133 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
4134 fp->f_flag |= FHASLOCK;
4137 VOP_UNLOCK(vp, 0, td);
4140 td->td_retval[0] = indx;
4151 * Stat an (NFS) file handle.
4155 #ifndef _SYS_SYSPROTO_H_
4156 struct fhstat_args {
4157 struct fhandle *u_fhp;
4164 register struct fhstat_args /* {
4165 struct fhandle *u_fhp;
4178 error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t));
4182 if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL) {
4186 if ((error = VFS_FHTOVP(mp, &fh.fh_fid, &vp))) {
4190 error = vn_stat(vp, &sb, td->td_ucred, NOCRED, td);
4195 error = copyout(&sb, uap->sb, sizeof(sb));
4200 * Implement fstatfs() for (NFS) file handles.
4204 #ifndef _SYS_SYSPROTO_H_
4205 struct fhstatfs_args {
4206 struct fhandle *u_fhp;
4213 struct fhstatfs_args /* {
4214 struct fhandle *u_fhp;
4222 error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t));
4225 error = kern_fhstatfs(td, fh, &sf);
4228 return (copyout(&sf, uap->buf, sizeof(sf)));
4232 kern_fhstatfs(struct thread *td, fhandle_t fh, struct statfs *buf)
4243 if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL) {
4247 error = VFS_FHTOVP(mp, &fh.fh_fid, &vp);
4256 error = mac_check_mount_stat(td->td_ucred, mp);
4263 * Set these in case the underlying filesystem fails to do so.
4265 sp->f_version = STATFS_VERSION;
4266 sp->f_namemax = NAME_MAX;
4267 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
4268 error = VFS_STATFS(mp, sp, td);
4277 * Syscall to push extended attribute configuration information into the
4278 * VFS. Accepts a path, which it converts to a mountpoint, as well as
4279 * a command (int cmd), and attribute name and misc data. For now, the
4280 * attribute name is left in userspace for consumption by the VFS_op.
4281 * It will probably be changed to be copied into sysspace by the
4282 * syscall in the future, once issues with various consumers of the
4283 * attribute code have raised their hands.
4285 * Currently this is used only by UFS Extended Attributes.
4290 struct extattrctl_args /* {
4293 const char *filename;
4295 const char *attrname;
4298 struct vnode *filename_vp;
4299 struct nameidata nd;
4300 struct mount *mp, *mp_writable;
4301 char attrname[EXTATTR_MAXNAMELEN];
4305 * uap->attrname is not always defined. We check again later when we
4306 * invoke the VFS call so as to pass in NULL there if needed.
4308 if (uap->attrname != NULL) {
4309 error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN,
4316 * uap->filename is not always defined. If it is, grab a vnode lock,
4317 * which VFS_EXTATTRCTL() will later release.
4320 if (uap->filename != NULL) {
4321 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
4326 filename_vp = nd.ni_vp;
4327 NDFREE(&nd, NDF_NO_VP_RELE | NDF_NO_VP_UNLOCK);
4330 /* uap->path is always defined. */
4331 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, td);
4334 if (filename_vp != NULL)
4338 mp = nd.ni_vp->v_mount;
4339 error = vn_start_write(nd.ni_vp, &mp_writable, V_WAIT | PCATCH);
4342 if (filename_vp != NULL)
4347 error = VFS_EXTATTRCTL(mp, uap->cmd, filename_vp, uap->attrnamespace,
4348 uap->attrname != NULL ? attrname : NULL, td);
4350 vn_finished_write(mp_writable);
4352 * VFS_EXTATTRCTL will have unlocked, but not de-ref'd,
4353 * filename_vp, so vrele it if it is defined.
4355 if (filename_vp != NULL)
4361 * Set a named extended attribute on a file or directory
4363 * Arguments: unlocked vnode "vp", attribute namespace "attrnamespace",
4364 * kernelspace string pointer "attrname", userspace buffer
4365 * pointer "data", buffer length "nbytes", thread "td".
4366 * Returns: 0 on success, an error number otherwise
4368 * References: vp must be a valid reference for the duration of the call
4371 extattr_set_vp(struct vnode *vp, int attrnamespace, const char *attrname,
4372 void *data, size_t nbytes, struct thread *td)
4380 error = vn_start_write(vp, &mp, V_WAIT | PCATCH);
4383 VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
4384 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
4386 aiov.iov_base = data;
4387 aiov.iov_len = nbytes;
4388 auio.uio_iov = &aiov;
4389 auio.uio_iovcnt = 1;
4390 auio.uio_offset = 0;
4391 if (nbytes > INT_MAX) {
4395 auio.uio_resid = nbytes;
4396 auio.uio_rw = UIO_WRITE;
4397 auio.uio_segflg = UIO_USERSPACE;
4402 error = mac_check_vnode_setextattr(td->td_ucred, vp, attrnamespace,
4408 error = VOP_SETEXTATTR(vp, attrnamespace, attrname, &auio,
4410 cnt -= auio.uio_resid;
4411 td->td_retval[0] = cnt;
4414 VOP_UNLOCK(vp, 0, td);
4415 vn_finished_write(mp);
4420 extattr_set_fd(td, uap)
4422 struct extattr_set_fd_args /* {
4425 const char *attrname;
4431 char attrname[EXTATTR_MAXNAMELEN];
4434 error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
4438 error = getvnode(td->td_proc->p_fd, uap->fd, &fp);
4442 error = extattr_set_vp(fp->f_vnode, uap->attrnamespace,
4443 attrname, uap->data, uap->nbytes, td);
4450 extattr_set_file(td, uap)
4452 struct extattr_set_file_args /* {
4455 const char *attrname;
4460 struct nameidata nd;
4461 char attrname[EXTATTR_MAXNAMELEN];
4464 error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
4468 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, td);
4472 NDFREE(&nd, NDF_ONLY_PNBUF);
4474 error = extattr_set_vp(nd.ni_vp, uap->attrnamespace, attrname,
4475 uap->data, uap->nbytes, td);
4482 extattr_set_link(td, uap)
4484 struct extattr_set_link_args /* {
4487 const char *attrname;
4492 struct nameidata nd;
4493 char attrname[EXTATTR_MAXNAMELEN];
4496 error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
4500 NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, uap->path, td);
4504 NDFREE(&nd, NDF_ONLY_PNBUF);
4506 error = extattr_set_vp(nd.ni_vp, uap->attrnamespace, attrname,
4507 uap->data, uap->nbytes, td);
4514 * Get a named extended attribute on a file or directory
4516 * Arguments: unlocked vnode "vp", attribute namespace "attrnamespace",
4517 * kernelspace string pointer "attrname", userspace buffer
4518 * pointer "data", buffer length "nbytes", thread "td".
4519 * Returns: 0 on success, an error number otherwise
4521 * References: vp must be a valid reference for the duration of the call
4524 extattr_get_vp(struct vnode *vp, int attrnamespace, const char *attrname,
4525 void *data, size_t nbytes, struct thread *td)
4527 struct uio auio, *auiop;
4530 size_t size, *sizep;
4533 VOP_LEASE(vp, td, td->td_ucred, LEASE_READ);
4534 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
4537 * Slightly unusual semantics: if the user provides a NULL data
4538 * pointer, they don't want to receive the data, just the
4539 * maximum read length.
4545 aiov.iov_base = data;
4546 aiov.iov_len = nbytes;
4547 auio.uio_iov = &aiov;
4548 auio.uio_iovcnt = 1;
4549 auio.uio_offset = 0;
4550 if (nbytes > INT_MAX) {
4554 auio.uio_resid = nbytes;
4555 auio.uio_rw = UIO_READ;
4556 auio.uio_segflg = UIO_USERSPACE;
4564 error = mac_check_vnode_getextattr(td->td_ucred, vp, attrnamespace,
4570 error = VOP_GETEXTATTR(vp, attrnamespace, attrname, auiop, sizep,
4573 if (auiop != NULL) {
4574 cnt -= auio.uio_resid;
4575 td->td_retval[0] = cnt;
4577 td->td_retval[0] = size;
4580 VOP_UNLOCK(vp, 0, td);
4585 extattr_get_fd(td, uap)
4587 struct extattr_get_fd_args /* {
4590 const char *attrname;
4596 char attrname[EXTATTR_MAXNAMELEN];
4599 error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
4603 error = getvnode(td->td_proc->p_fd, uap->fd, &fp);
4607 error = extattr_get_vp(fp->f_vnode, uap->attrnamespace,
4608 attrname, uap->data, uap->nbytes, td);
4615 extattr_get_file(td, uap)
4617 struct extattr_get_file_args /* {
4620 const char *attrname;
4625 struct nameidata nd;
4626 char attrname[EXTATTR_MAXNAMELEN];
4629 error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
4633 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, td);
4637 NDFREE(&nd, NDF_ONLY_PNBUF);
4639 error = extattr_get_vp(nd.ni_vp, uap->attrnamespace, attrname,
4640 uap->data, uap->nbytes, td);
4647 extattr_get_link(td, uap)
4649 struct extattr_get_link_args /* {
4652 const char *attrname;
4657 struct nameidata nd;
4658 char attrname[EXTATTR_MAXNAMELEN];
4661 error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
4665 NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, uap->path, td);
4669 NDFREE(&nd, NDF_ONLY_PNBUF);
4671 error = extattr_get_vp(nd.ni_vp, uap->attrnamespace, attrname,
4672 uap->data, uap->nbytes, td);
4679 * extattr_delete_vp(): Delete a named extended attribute on a file or
4682 * Arguments: unlocked vnode "vp", attribute namespace "attrnamespace",
4683 * kernelspace string pointer "attrname", proc "p"
4684 * Returns: 0 on success, an error number otherwise
4686 * References: vp must be a valid reference for the duration of the call
4689 extattr_delete_vp(struct vnode *vp, int attrnamespace, const char *attrname,
4695 error = vn_start_write(vp, &mp, V_WAIT | PCATCH);
4698 VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
4699 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
4702 error = mac_check_vnode_deleteextattr(td->td_ucred, vp, attrnamespace,
4708 error = VOP_DELETEEXTATTR(vp, attrnamespace, attrname, td->td_ucred,
4710 if (error == EOPNOTSUPP)
4711 error = VOP_SETEXTATTR(vp, attrnamespace, attrname, NULL,
4716 VOP_UNLOCK(vp, 0, td);
4717 vn_finished_write(mp);
4722 extattr_delete_fd(td, uap)
4724 struct extattr_delete_fd_args /* {
4727 const char *attrname;
4732 char attrname[EXTATTR_MAXNAMELEN];
4735 error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
4739 error = getvnode(td->td_proc->p_fd, uap->fd, &fp);
4744 error = extattr_delete_vp(vp, uap->attrnamespace, attrname, td);
4750 extattr_delete_file(td, uap)
4752 struct extattr_delete_file_args /* {
4755 const char *attrname;
4758 struct nameidata nd;
4759 char attrname[EXTATTR_MAXNAMELEN];
4762 error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
4766 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, td);
4770 NDFREE(&nd, NDF_ONLY_PNBUF);
4772 error = extattr_delete_vp(nd.ni_vp, uap->attrnamespace, attrname, td);
4778 extattr_delete_link(td, uap)
4780 struct extattr_delete_link_args /* {
4783 const char *attrname;
4786 struct nameidata nd;
4787 char attrname[EXTATTR_MAXNAMELEN];
4790 error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
4794 NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, uap->path, td);
4798 NDFREE(&nd, NDF_ONLY_PNBUF);
4800 error = extattr_delete_vp(nd.ni_vp, uap->attrnamespace, attrname, td);
4806 * Retrieve a list of extended attributes on a file or directory.
4808 * Arguments: unlocked vnode "vp", attribute namespace 'attrnamespace",
4809 * userspace buffer pointer "data", buffer length "nbytes",
4811 * Returns: 0 on success, an error number otherwise
4813 * References: vp must be a valid reference for the duration of the call
4816 extattr_list_vp(struct vnode *vp, int attrnamespace, void *data,
4817 size_t nbytes, struct thread *td)
4819 struct uio auio, *auiop;
4820 size_t size, *sizep;
4825 VOP_LEASE(vp, td, td->td_ucred, LEASE_READ);
4826 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
4832 aiov.iov_base = data;
4833 aiov.iov_len = nbytes;
4834 auio.uio_iov = &aiov;
4835 auio.uio_iovcnt = 1;
4836 auio.uio_offset = 0;
4837 if (nbytes > INT_MAX) {
4841 auio.uio_resid = nbytes;
4842 auio.uio_rw = UIO_READ;
4843 auio.uio_segflg = UIO_USERSPACE;
4851 error = mac_check_vnode_listextattr(td->td_ucred, vp, attrnamespace);
4856 error = VOP_LISTEXTATTR(vp, attrnamespace, auiop, sizep,
4859 if (auiop != NULL) {
4860 cnt -= auio.uio_resid;
4861 td->td_retval[0] = cnt;
4863 td->td_retval[0] = size;
4866 VOP_UNLOCK(vp, 0, td);
4872 extattr_list_fd(td, uap)
4874 struct extattr_list_fd_args /* {
4884 error = getvnode(td->td_proc->p_fd, uap->fd, &fp);
4888 error = extattr_list_vp(fp->f_vnode, uap->attrnamespace, uap->data,
4896 extattr_list_file(td, uap)
4898 struct extattr_list_file_args /* {
4905 struct nameidata nd;
4908 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, td);
4912 NDFREE(&nd, NDF_ONLY_PNBUF);
4914 error = extattr_list_vp(nd.ni_vp, uap->attrnamespace, uap->data,
4922 extattr_list_link(td, uap)
4924 struct extattr_list_link_args /* {
4931 struct nameidata nd;
4934 NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, uap->path, td);
4938 NDFREE(&nd, NDF_ONLY_PNBUF);
4940 error = extattr_list_vp(nd.ni_vp, uap->attrnamespace, uap->data,