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>
73 #include <security/audit/audit.h>
76 #include <vm/vm_object.h>
77 #include <vm/vm_page.h>
80 static int chroot_refuse_vdir_fds(struct filedesc *fdp);
81 static int getutimes(const struct timeval *, enum uio_seg, 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, int);
87 static int vn_access(struct vnode *vp, int user_flags, struct ucred *cred,
90 static int extattr_list_vp(struct vnode *vp, int attrnamespace, void *data,
91 size_t nbytes, struct thread *td);
93 int (*union_dircheckp)(struct thread *td, struct vnode **, struct file *);
96 * The module initialization routine for POSIX asynchronous I/O will
97 * set this to the version of AIO that it implements. (Zero means
98 * that it is not implemented.) This value is used here by pathconf()
99 * and in kern_descrip.c by fpathconf().
101 int async_io_version;
104 * Sync each mounted filesystem.
106 #ifndef _SYS_SYSPROTO_H_
113 static int syncprt = 0;
114 SYSCTL_INT(_debug, OID_AUTO, syncprt, CTLFLAG_RW, &syncprt, 0, "");
121 struct sync_args *uap;
123 struct mount *mp, *nmp;
127 mtx_lock(&mountlist_mtx);
128 for (mp = TAILQ_FIRST(&mountlist); mp != NULL; mp = nmp) {
129 if (vfs_busy(mp, LK_NOWAIT, &mountlist_mtx, td)) {
130 nmp = TAILQ_NEXT(mp, mnt_list);
133 vfslocked = VFS_LOCK_GIANT(mp);
134 if ((mp->mnt_flag & MNT_RDONLY) == 0 &&
135 vn_start_write(NULL, &mp, V_NOWAIT) == 0) {
136 asyncflag = mp->mnt_flag & MNT_ASYNC;
137 mp->mnt_flag &= ~MNT_ASYNC;
138 vfs_msync(mp, MNT_NOWAIT);
139 VFS_SYNC(mp, MNT_NOWAIT, td);
140 mp->mnt_flag |= asyncflag;
141 vn_finished_write(mp);
143 VFS_UNLOCK_GIANT(vfslocked);
144 mtx_lock(&mountlist_mtx);
145 nmp = TAILQ_NEXT(mp, mnt_list);
148 mtx_unlock(&mountlist_mtx);
152 /* XXX PRISON: could be per prison flag */
153 static int prison_quotas;
155 SYSCTL_INT(_kern_prison, OID_AUTO, quotas, CTLFLAG_RW, &prison_quotas, 0, "");
159 * Change filesystem quotas.
163 #ifndef _SYS_SYSPROTO_H_
164 struct quotactl_args {
174 register struct quotactl_args /* {
181 struct mount *mp, *vmp;
186 if (jailed(td->td_ucred) && !prison_quotas)
188 NDINIT(&nd, LOOKUP, FOLLOW | MPSAFE | AUDITVNODE1,
189 UIO_USERSPACE, uap->path, td);
190 if ((error = namei(&nd)) != 0)
192 vfslocked = NDHASGIANT(&nd);
193 NDFREE(&nd, NDF_ONLY_PNBUF);
194 error = vn_start_write(nd.ni_vp, &vmp, V_WAIT | PCATCH);
195 mp = nd.ni_vp->v_mount;
199 error = VFS_QUOTACTL(mp, uap->cmd, uap->uid, uap->arg, td);
200 vn_finished_write(vmp);
202 VFS_UNLOCK_GIANT(vfslocked);
207 * Get filesystem statistics.
209 #ifndef _SYS_SYSPROTO_H_
218 register struct statfs_args /* {
226 error = kern_statfs(td, uap->path, UIO_USERSPACE, &sf);
228 error = copyout(&sf, uap->buf, sizeof(sf));
233 kern_statfs(struct thread *td, char *path, enum uio_seg pathseg,
237 struct statfs *sp, sb;
242 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | MPSAFE | AUDITVNODE1,
247 vfslocked = NDHASGIANT(&nd);
248 mp = nd.ni_vp->v_mount;
250 NDFREE(&nd, NDF_ONLY_PNBUF);
253 error = mac_check_mount_stat(td->td_ucred, mp);
260 * Set these in case the underlying filesystem fails to do so.
263 sp->f_version = STATFS_VERSION;
264 sp->f_namemax = NAME_MAX;
265 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
266 error = VFS_STATFS(mp, sp, td);
271 bcopy(sp, &sb, sizeof(sb));
272 sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0;
273 prison_enforce_statfs(td->td_ucred, mp, &sb);
278 VFS_UNLOCK_GIANT(vfslocked);
283 * Get filesystem statistics.
285 #ifndef _SYS_SYSPROTO_H_
286 struct fstatfs_args {
294 register struct fstatfs_args /* {
302 error = kern_fstatfs(td, uap->fd, &sf);
304 error = copyout(&sf, uap->buf, sizeof(sf));
309 kern_fstatfs(struct thread *td, int fd, struct statfs *buf)
313 struct statfs *sp, sb;
319 error = getvnode(td->td_proc->p_fd, fd, &fp);
323 vfslocked = VFS_LOCK_GIANT(vp->v_mount);
324 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
326 AUDIT_ARG(vnode, vp, ARG_VNODE1);
331 VOP_UNLOCK(vp, 0, td);
333 if (vp->v_iflag & VI_DOOMED) {
340 error = mac_check_mount_stat(td->td_ucred, mp);
347 * Set these in case the underlying filesystem fails to do so.
350 sp->f_version = STATFS_VERSION;
351 sp->f_namemax = NAME_MAX;
352 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
353 error = VFS_STATFS(mp, sp, td);
358 bcopy(sp, &sb, sizeof(sb));
359 sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0;
360 prison_enforce_statfs(td->td_ucred, mp, &sb);
365 VFS_UNLOCK_GIANT(vfslocked);
370 * Get statistics on all filesystems.
372 #ifndef _SYS_SYSPROTO_H_
373 struct getfsstat_args {
382 register struct getfsstat_args /* {
389 return (kern_getfsstat(td, &uap->buf, uap->bufsize, UIO_USERSPACE,
394 * If (bufsize > 0 && bufseg == UIO_SYSSPACE)
395 * The caller is responsible for freeing memory which will be allocated
399 kern_getfsstat(struct thread *td, struct statfs **buf, size_t bufsize,
400 enum uio_seg bufseg, int flags)
402 struct mount *mp, *nmp;
403 struct statfs *sfsp, *sp, sb;
404 size_t count, maxcount;
408 maxcount = bufsize / sizeof(struct statfs);
411 else if (bufseg == UIO_USERSPACE)
413 else /* if (bufseg == UIO_SYSSPACE) */ {
415 mtx_lock(&mountlist_mtx);
416 TAILQ_FOREACH(mp, &mountlist, mnt_list) {
419 mtx_unlock(&mountlist_mtx);
420 if (maxcount > count)
422 sfsp = *buf = malloc(maxcount * sizeof(struct statfs), M_TEMP,
426 mtx_lock(&mountlist_mtx);
427 for (mp = TAILQ_FIRST(&mountlist); mp != NULL; mp = nmp) {
428 if (prison_canseemount(td->td_ucred, mp) != 0) {
429 nmp = TAILQ_NEXT(mp, mnt_list);
433 if (mac_check_mount_stat(td->td_ucred, mp) != 0) {
434 nmp = TAILQ_NEXT(mp, mnt_list);
438 if (vfs_busy(mp, LK_NOWAIT, &mountlist_mtx, td)) {
439 nmp = TAILQ_NEXT(mp, mnt_list);
442 vfslocked = VFS_LOCK_GIANT(mp);
443 if (sfsp && count < maxcount) {
446 * Set these in case the underlying filesystem
449 sp->f_version = STATFS_VERSION;
450 sp->f_namemax = NAME_MAX;
451 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
453 * If MNT_NOWAIT or MNT_LAZY is specified, do not
454 * refresh the fsstat cache. MNT_NOWAIT or MNT_LAZY
455 * overrides MNT_WAIT.
457 if (((flags & (MNT_LAZY|MNT_NOWAIT)) == 0 ||
458 (flags & MNT_WAIT)) &&
459 (error = VFS_STATFS(mp, sp, td))) {
460 VFS_UNLOCK_GIANT(vfslocked);
461 mtx_lock(&mountlist_mtx);
462 nmp = TAILQ_NEXT(mp, mnt_list);
467 bcopy(sp, &sb, sizeof(sb));
468 sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0;
469 prison_enforce_statfs(td->td_ucred, mp, &sb);
472 if (bufseg == UIO_SYSSPACE)
473 bcopy(sp, sfsp, sizeof(*sp));
474 else /* if (bufseg == UIO_USERSPACE) */ {
475 error = copyout(sp, sfsp, sizeof(*sp));
478 VFS_UNLOCK_GIANT(vfslocked);
484 VFS_UNLOCK_GIANT(vfslocked);
486 mtx_lock(&mountlist_mtx);
487 nmp = TAILQ_NEXT(mp, mnt_list);
490 mtx_unlock(&mountlist_mtx);
491 if (sfsp && count > maxcount)
492 td->td_retval[0] = maxcount;
494 td->td_retval[0] = count;
498 #ifdef COMPAT_FREEBSD4
500 * Get old format filesystem statistics.
502 static void cvtstatfs(struct statfs *, struct ostatfs *);
504 #ifndef _SYS_SYSPROTO_H_
505 struct freebsd4_statfs_args {
511 freebsd4_statfs(td, uap)
513 struct freebsd4_statfs_args /* {
522 error = kern_statfs(td, uap->path, UIO_USERSPACE, &sf);
525 cvtstatfs(&sf, &osb);
526 return (copyout(&osb, uap->buf, sizeof(osb)));
530 * Get filesystem statistics.
532 #ifndef _SYS_SYSPROTO_H_
533 struct freebsd4_fstatfs_args {
539 freebsd4_fstatfs(td, uap)
541 struct freebsd4_fstatfs_args /* {
550 error = kern_fstatfs(td, uap->fd, &sf);
553 cvtstatfs(&sf, &osb);
554 return (copyout(&osb, uap->buf, sizeof(osb)));
558 * Get statistics on all filesystems.
560 #ifndef _SYS_SYSPROTO_H_
561 struct freebsd4_getfsstat_args {
568 freebsd4_getfsstat(td, uap)
570 register struct freebsd4_getfsstat_args /* {
576 struct statfs *buf, *sp;
581 count = uap->bufsize / sizeof(struct ostatfs);
582 size = count * sizeof(struct statfs);
583 error = kern_getfsstat(td, &buf, size, UIO_SYSSPACE, uap->flags);
585 count = td->td_retval[0];
587 while (count > 0 && error == 0) {
589 error = copyout(&osb, uap->buf, sizeof(osb));
600 * Implement fstatfs() for (NFS) file handles.
602 #ifndef _SYS_SYSPROTO_H_
603 struct freebsd4_fhstatfs_args {
604 struct fhandle *u_fhp;
609 freebsd4_fhstatfs(td, uap)
611 struct freebsd4_fhstatfs_args /* {
612 struct fhandle *u_fhp;
621 error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t));
624 error = kern_fhstatfs(td, fh, &sf);
627 cvtstatfs(&sf, &osb);
628 return (copyout(&osb, uap->buf, sizeof(osb)));
632 * Convert a new format statfs structure to an old format statfs structure.
640 bzero(osp, sizeof(*osp));
641 osp->f_bsize = MIN(nsp->f_bsize, LONG_MAX);
642 osp->f_iosize = MIN(nsp->f_iosize, LONG_MAX);
643 osp->f_blocks = MIN(nsp->f_blocks, LONG_MAX);
644 osp->f_bfree = MIN(nsp->f_bfree, LONG_MAX);
645 osp->f_bavail = MIN(nsp->f_bavail, LONG_MAX);
646 osp->f_files = MIN(nsp->f_files, LONG_MAX);
647 osp->f_ffree = MIN(nsp->f_ffree, LONG_MAX);
648 osp->f_owner = nsp->f_owner;
649 osp->f_type = nsp->f_type;
650 osp->f_flags = nsp->f_flags;
651 osp->f_syncwrites = MIN(nsp->f_syncwrites, LONG_MAX);
652 osp->f_asyncwrites = MIN(nsp->f_asyncwrites, LONG_MAX);
653 osp->f_syncreads = MIN(nsp->f_syncreads, LONG_MAX);
654 osp->f_asyncreads = MIN(nsp->f_asyncreads, LONG_MAX);
655 strlcpy(osp->f_fstypename, nsp->f_fstypename,
656 MIN(MFSNAMELEN, OMFSNAMELEN));
657 strlcpy(osp->f_mntonname, nsp->f_mntonname,
658 MIN(MNAMELEN, OMNAMELEN));
659 strlcpy(osp->f_mntfromname, nsp->f_mntfromname,
660 MIN(MNAMELEN, OMNAMELEN));
661 osp->f_fsid = nsp->f_fsid;
663 #endif /* COMPAT_FREEBSD4 */
666 * Change current working directory to a given file descriptor.
668 #ifndef _SYS_SYSPROTO_H_
676 struct fchdir_args /* {
680 register struct filedesc *fdp = td->td_proc->p_fd;
681 struct vnode *vp, *tdp, *vpold;
687 AUDIT_ARG(fd, uap->fd);
688 if ((error = getvnode(fdp, uap->fd, &fp)) != 0)
693 vfslocked = VFS_LOCK_GIANT(vp->v_mount);
694 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
695 AUDIT_ARG(vnode, vp, ARG_VNODE1);
696 if (vp->v_type != VDIR)
699 else if ((error = mac_check_vnode_chdir(td->td_ucred, vp)) != 0) {
703 error = VOP_ACCESS(vp, VEXEC, td->td_ucred, td);
704 while (!error && (mp = vp->v_mountedhere) != NULL) {
706 if (vfs_busy(mp, 0, 0, td))
708 tvfslocked = VFS_LOCK_GIANT(mp);
709 error = VFS_ROOT(mp, LK_EXCLUSIVE, &tdp, td);
712 VFS_UNLOCK_GIANT(tvfslocked);
716 VFS_UNLOCK_GIANT(vfslocked);
718 vfslocked = tvfslocked;
722 VFS_UNLOCK_GIANT(vfslocked);
725 VOP_UNLOCK(vp, 0, td);
726 VFS_UNLOCK_GIANT(vfslocked);
727 FILEDESC_LOCK_FAST(fdp);
728 vpold = fdp->fd_cdir;
730 FILEDESC_UNLOCK_FAST(fdp);
731 vfslocked = VFS_LOCK_GIANT(vpold->v_mount);
733 VFS_UNLOCK_GIANT(vfslocked);
738 * Change current working directory (``.'').
740 #ifndef _SYS_SYSPROTO_H_
748 struct chdir_args /* {
753 return (kern_chdir(td, uap->path, UIO_USERSPACE));
757 kern_chdir(struct thread *td, char *path, enum uio_seg pathseg)
759 register struct filedesc *fdp = td->td_proc->p_fd;
765 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | AUDITVNODE1 | MPSAFE,
767 if ((error = namei(&nd)) != 0)
769 vfslocked = NDHASGIANT(&nd);
770 if ((error = change_dir(nd.ni_vp, td)) != 0) {
772 VFS_UNLOCK_GIANT(vfslocked);
773 NDFREE(&nd, NDF_ONLY_PNBUF);
776 VOP_UNLOCK(nd.ni_vp, 0, td);
777 VFS_UNLOCK_GIANT(vfslocked);
778 NDFREE(&nd, NDF_ONLY_PNBUF);
779 FILEDESC_LOCK_FAST(fdp);
781 fdp->fd_cdir = nd.ni_vp;
782 FILEDESC_UNLOCK_FAST(fdp);
783 vfslocked = VFS_LOCK_GIANT(vp->v_mount);
785 VFS_UNLOCK_GIANT(vfslocked);
790 * Helper function for raised chroot(2) security function: Refuse if
791 * any filedescriptors are open directories.
794 chroot_refuse_vdir_fds(fdp)
795 struct filedesc *fdp;
801 FILEDESC_LOCK_ASSERT(fdp, MA_OWNED);
802 for (fd = 0; fd < fdp->fd_nfiles ; fd++) {
803 fp = fget_locked(fdp, fd);
806 if (fp->f_type == DTYPE_VNODE) {
808 if (vp->v_type == VDIR)
816 * This sysctl determines if we will allow a process to chroot(2) if it
817 * has a directory open:
818 * 0: disallowed for all processes.
819 * 1: allowed for processes that were not already chroot(2)'ed.
820 * 2: allowed for all processes.
823 static int chroot_allow_open_directories = 1;
825 SYSCTL_INT(_kern, OID_AUTO, chroot_allow_open_directories, CTLFLAG_RW,
826 &chroot_allow_open_directories, 0, "");
829 * Change notion of root (``/'') directory.
831 #ifndef _SYS_SYSPROTO_H_
839 struct chroot_args /* {
847 error = suser_cred(td->td_ucred, SUSER_ALLOWJAIL);
850 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | MPSAFE | AUDITVNODE1,
851 UIO_USERSPACE, uap->path, td);
855 vfslocked = NDHASGIANT(&nd);
856 if ((error = change_dir(nd.ni_vp, td)) != 0)
859 if ((error = mac_check_vnode_chroot(td->td_ucred, nd.ni_vp)))
862 VOP_UNLOCK(nd.ni_vp, 0, td);
863 error = change_root(nd.ni_vp, td);
865 VFS_UNLOCK_GIANT(vfslocked);
866 NDFREE(&nd, NDF_ONLY_PNBUF);
870 VFS_UNLOCK_GIANT(vfslocked);
872 NDFREE(&nd, NDF_ONLY_PNBUF);
877 * Common routine for chroot and chdir. Callers must provide a locked vnode
887 ASSERT_VOP_LOCKED(vp, "change_dir(): vp not locked");
888 if (vp->v_type != VDIR)
891 error = mac_check_vnode_chdir(td->td_ucred, vp);
895 error = VOP_ACCESS(vp, VEXEC, td->td_ucred, td);
900 * Common routine for kern_chroot() and jail_attach(). The caller is
901 * responsible for invoking suser() and mac_check_chroot() to authorize this
909 struct filedesc *fdp;
914 VFS_ASSERT_GIANT(vp->v_mount);
915 fdp = td->td_proc->p_fd;
917 if (chroot_allow_open_directories == 0 ||
918 (chroot_allow_open_directories == 1 && fdp->fd_rdir != rootvnode)) {
919 error = chroot_refuse_vdir_fds(fdp);
921 FILEDESC_UNLOCK(fdp);
925 oldvp = fdp->fd_rdir;
932 FILEDESC_UNLOCK(fdp);
933 vfslocked = VFS_LOCK_GIANT(oldvp->v_mount);
935 VFS_UNLOCK_GIANT(vfslocked);
940 * Check permissions, allocate an open file structure,
941 * and call the device open routine if any.
945 #ifndef _SYS_SYSPROTO_H_
955 register struct open_args /* {
962 return kern_open(td, uap->path, UIO_USERSPACE, uap->flags, uap->mode);
966 kern_open(struct thread *td, char *path, enum uio_seg pathseg, int flags,
969 struct proc *p = td->td_proc;
970 struct filedesc *fdp = p->p_fd;
977 int type, indx, error;
982 AUDIT_ARG(fflags, flags);
983 AUDIT_ARG(mode, mode);
984 if ((flags & O_ACCMODE) == O_ACCMODE)
986 flags = FFLAGS(flags);
987 error = falloc(td, &nfp, &indx);
990 /* An extra reference on `nfp' has been held for us by falloc(). */
992 cmode = ((mode &~ fdp->fd_cmask) & ALLPERMS) &~ S_ISTXT;
993 NDINIT(&nd, LOOKUP, FOLLOW | AUDITVNODE1, pathseg, path, td);
994 td->td_dupfd = -1; /* XXX check for fdopen */
995 error = vn_open(&nd, &flags, cmode, indx);
998 * If the vn_open replaced the method vector, something
999 * wonderous happened deep below and we just pass it up
1000 * pretending we know what we do.
1002 if (error == ENXIO && fp->f_ops != &badfileops) {
1004 td->td_retval[0] = indx;
1009 * release our own reference
1014 * handle special fdopen() case. bleh. dupfdopen() is
1015 * responsible for dropping the old contents of ofiles[indx]
1018 if ((error == ENODEV || error == ENXIO) &&
1019 td->td_dupfd >= 0 && /* XXX from fdopen */
1021 dupfdopen(td, fdp, indx, td->td_dupfd, flags, error)) == 0) {
1022 td->td_retval[0] = indx;
1026 * Clean up the descriptor, but only if another thread hadn't
1027 * replaced or closed it.
1029 fdclose(fdp, fp, indx, td);
1031 if (error == ERESTART)
1036 vfslocked = NDHASGIANT(&nd);
1037 NDFREE(&nd, NDF_ONLY_PNBUF);
1041 * There should be 2 references on the file, one from the descriptor
1042 * table, and one for us.
1044 * Handle the case where someone closed the file (via its file
1045 * descriptor) while we were blocked. The end result should look
1046 * like opening the file succeeded but it was immediately closed.
1047 * We call vn_close() manually because we haven't yet hooked up
1048 * the various 'struct file' fields.
1052 if (fp->f_count == 1) {
1054 KASSERT(fdp->fd_ofiles[indx] != fp,
1055 ("Open file descriptor lost all refs"));
1057 FILEDESC_UNLOCK(fdp);
1058 VOP_UNLOCK(vp, 0, td);
1059 vn_close(vp, flags & FMASK, fp->f_cred, td);
1060 VFS_UNLOCK_GIANT(vfslocked);
1062 td->td_retval[0] = indx;
1066 if (fp->f_data == NULL)
1068 fp->f_flag = flags & FMASK;
1069 if (fp->f_ops == &badfileops)
1072 fp->f_type = (vp->v_type == VFIFO ? DTYPE_FIFO : DTYPE_VNODE);
1074 FILEDESC_UNLOCK(fdp);
1076 VOP_UNLOCK(vp, 0, td);
1077 if (flags & (O_EXLOCK | O_SHLOCK)) {
1078 lf.l_whence = SEEK_SET;
1081 if (flags & O_EXLOCK)
1082 lf.l_type = F_WRLCK;
1084 lf.l_type = F_RDLCK;
1086 if ((flags & FNONBLOCK) == 0)
1088 if ((error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf,
1091 fp->f_flag |= FHASLOCK;
1093 if (flags & O_TRUNC) {
1094 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
1096 VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
1099 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
1101 error = mac_check_vnode_write(td->td_ucred, fp->f_cred, vp);
1104 error = VOP_SETATTR(vp, &vat, td->td_ucred, td);
1105 VOP_UNLOCK(vp, 0, td);
1106 vn_finished_write(mp);
1110 VFS_UNLOCK_GIANT(vfslocked);
1112 * Release our private reference, leaving the one associated with
1113 * the descriptor table intact.
1116 td->td_retval[0] = indx;
1119 VFS_UNLOCK_GIANT(vfslocked);
1120 fdclose(fdp, fp, indx, td);
1131 #ifndef _SYS_SYSPROTO_H_
1132 struct ocreat_args {
1140 register struct ocreat_args /* {
1146 return (kern_open(td, uap->path, UIO_USERSPACE,
1147 O_WRONLY | O_CREAT | O_TRUNC, uap->mode));
1149 #endif /* COMPAT_43 */
1152 * Create a special file.
1154 #ifndef _SYS_SYSPROTO_H_
1164 register struct mknod_args /* {
1171 return (kern_mknod(td, uap->path, UIO_USERSPACE, uap->mode, uap->dev));
1175 kern_mknod(struct thread *td, char *path, enum uio_seg pathseg, int mode,
1183 struct nameidata nd;
1186 AUDIT_ARG(mode, mode);
1187 AUDIT_ARG(dev, dev);
1188 switch (mode & S_IFMT) {
1194 error = suser_cred(td->td_ucred, SUSER_ALLOWJAIL);
1201 NDINIT(&nd, CREATE, LOCKPARENT | SAVENAME | MPSAFE | AUDITVNODE1,
1203 if ((error = namei(&nd)) != 0)
1205 vfslocked = NDHASGIANT(&nd);
1208 NDFREE(&nd, NDF_ONLY_PNBUF);
1209 if (vp == nd.ni_dvp)
1214 VFS_UNLOCK_GIANT(vfslocked);
1218 FILEDESC_LOCK_FAST(td->td_proc->p_fd);
1219 vattr.va_mode = (mode & ALLPERMS) &
1220 ~td->td_proc->p_fd->fd_cmask;
1221 FILEDESC_UNLOCK_FAST(td->td_proc->p_fd);
1222 vattr.va_rdev = dev;
1225 switch (mode & S_IFMT) {
1226 case S_IFMT: /* used by badsect to flag bad sectors */
1227 vattr.va_type = VBAD;
1230 vattr.va_type = VCHR;
1233 vattr.va_type = VBLK;
1243 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) {
1244 NDFREE(&nd, NDF_ONLY_PNBUF);
1246 VFS_UNLOCK_GIANT(vfslocked);
1247 if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0)
1252 if (error == 0 && !whiteout)
1253 error = mac_check_vnode_create(td->td_ucred, nd.ni_dvp,
1254 &nd.ni_cnd, &vattr);
1257 VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
1259 error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, CREATE);
1261 error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp,
1262 &nd.ni_cnd, &vattr);
1267 NDFREE(&nd, NDF_ONLY_PNBUF);
1269 vn_finished_write(mp);
1270 VFS_UNLOCK_GIANT(vfslocked);
1275 * Create a named pipe.
1277 #ifndef _SYS_SYSPROTO_H_
1278 struct mkfifo_args {
1286 register struct mkfifo_args /* {
1292 return (kern_mkfifo(td, uap->path, UIO_USERSPACE, uap->mode));
1296 kern_mkfifo(struct thread *td, char *path, enum uio_seg pathseg, int mode)
1301 struct nameidata nd;
1306 NDINIT(&nd, CREATE, LOCKPARENT | SAVENAME | MPSAFE | AUDITVNODE1,
1308 if ((error = namei(&nd)) != 0)
1310 vfslocked = NDHASGIANT(&nd);
1311 if (nd.ni_vp != NULL) {
1312 NDFREE(&nd, NDF_ONLY_PNBUF);
1313 if (nd.ni_vp == nd.ni_dvp)
1318 VFS_UNLOCK_GIANT(vfslocked);
1321 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) {
1322 NDFREE(&nd, NDF_ONLY_PNBUF);
1324 VFS_UNLOCK_GIANT(vfslocked);
1325 if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0)
1330 vattr.va_type = VFIFO;
1331 FILEDESC_LOCK_FAST(td->td_proc->p_fd);
1332 vattr.va_mode = (mode & ALLPERMS) & ~td->td_proc->p_fd->fd_cmask;
1333 FILEDESC_UNLOCK_FAST(td->td_proc->p_fd);
1335 error = mac_check_vnode_create(td->td_ucred, nd.ni_dvp, &nd.ni_cnd,
1340 VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
1341 error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
1348 vn_finished_write(mp);
1349 VFS_UNLOCK_GIANT(vfslocked);
1350 NDFREE(&nd, NDF_ONLY_PNBUF);
1355 * Make a hard file link.
1357 #ifndef _SYS_SYSPROTO_H_
1366 register struct link_args /* {
1373 error = kern_link(td, uap->path, uap->link, UIO_USERSPACE);
1377 SYSCTL_DECL(_security_bsd);
1379 static int hardlink_check_uid = 0;
1380 SYSCTL_INT(_security_bsd, OID_AUTO, hardlink_check_uid, CTLFLAG_RW,
1381 &hardlink_check_uid, 0,
1382 "Unprivileged processes cannot create hard links to files owned by other "
1384 static int hardlink_check_gid = 0;
1385 SYSCTL_INT(_security_bsd, OID_AUTO, hardlink_check_gid, CTLFLAG_RW,
1386 &hardlink_check_gid, 0,
1387 "Unprivileged processes cannot create hard links to files owned by other "
1391 can_hardlink(struct vnode *vp, struct thread *td, struct ucred *cred)
1396 if (suser_cred(cred, SUSER_ALLOWJAIL) == 0)
1399 if (!hardlink_check_uid && !hardlink_check_gid)
1402 error = VOP_GETATTR(vp, &va, cred, td);
1406 if (hardlink_check_uid) {
1407 if (cred->cr_uid != va.va_uid)
1411 if (hardlink_check_gid) {
1412 if (!groupmember(va.va_gid, cred))
1420 kern_link(struct thread *td, char *path, char *link, enum uio_seg segflg)
1424 struct nameidata nd;
1430 NDINIT(&nd, LOOKUP, FOLLOW | MPSAFE | AUDITVNODE1, segflg, path, td);
1431 if ((error = namei(&nd)) != 0)
1433 vfslocked = NDHASGIANT(&nd);
1434 NDFREE(&nd, NDF_ONLY_PNBUF);
1436 if (vp->v_type == VDIR) {
1438 VFS_UNLOCK_GIANT(vfslocked);
1439 return (EPERM); /* POSIX */
1441 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) {
1443 VFS_UNLOCK_GIANT(vfslocked);
1446 NDINIT(&nd, CREATE, LOCKPARENT | SAVENAME | MPSAFE | AUDITVNODE2,
1448 if ((error = namei(&nd)) == 0) {
1449 lvfslocked = NDHASGIANT(&nd);
1450 if (nd.ni_vp != NULL) {
1451 if (nd.ni_dvp == nd.ni_vp)
1457 } else if ((error = vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td))
1459 VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
1460 VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
1461 error = can_hardlink(vp, td, td->td_ucred);
1464 error = mac_check_vnode_link(td->td_ucred,
1465 nd.ni_dvp, vp, &nd.ni_cnd);
1468 error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd);
1469 VOP_UNLOCK(vp, 0, td);
1472 NDFREE(&nd, NDF_ONLY_PNBUF);
1473 VFS_UNLOCK_GIANT(lvfslocked);
1476 vn_finished_write(mp);
1477 VFS_UNLOCK_GIANT(vfslocked);
1482 * Make a symbolic link.
1484 #ifndef _SYS_SYSPROTO_H_
1485 struct symlink_args {
1493 register struct symlink_args /* {
1499 return (kern_symlink(td, uap->path, uap->link, UIO_USERSPACE));
1503 kern_symlink(struct thread *td, char *path, char *link, enum uio_seg segflg)
1509 struct nameidata nd;
1512 if (segflg == UIO_SYSSPACE) {
1515 syspath = uma_zalloc(namei_zone, M_WAITOK);
1516 if ((error = copyinstr(path, syspath, MAXPATHLEN, NULL)) != 0)
1521 NDINIT(&nd, CREATE, LOCKPARENT | SAVENAME | MPSAFE | AUDITVNODE1,
1523 if ((error = namei(&nd)) != 0)
1525 vfslocked = NDHASGIANT(&nd);
1527 NDFREE(&nd, NDF_ONLY_PNBUF);
1528 if (nd.ni_vp == nd.ni_dvp)
1533 VFS_UNLOCK_GIANT(vfslocked);
1537 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) {
1538 NDFREE(&nd, NDF_ONLY_PNBUF);
1540 VFS_UNLOCK_GIANT(vfslocked);
1541 if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0)
1546 FILEDESC_LOCK_FAST(td->td_proc->p_fd);
1547 vattr.va_mode = ACCESSPERMS &~ td->td_proc->p_fd->fd_cmask;
1548 FILEDESC_UNLOCK_FAST(td->td_proc->p_fd);
1550 vattr.va_type = VLNK;
1551 error = mac_check_vnode_create(td->td_ucred, nd.ni_dvp, &nd.ni_cnd,
1556 VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
1557 error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr, syspath);
1563 NDFREE(&nd, NDF_ONLY_PNBUF);
1565 vn_finished_write(mp);
1566 VFS_UNLOCK_GIANT(vfslocked);
1568 if (segflg != UIO_SYSSPACE)
1569 uma_zfree(namei_zone, syspath);
1574 * Delete a whiteout from the filesystem.
1579 register struct undelete_args /* {
1585 struct nameidata nd;
1590 NDINIT(&nd, DELETE, LOCKPARENT | DOWHITEOUT | MPSAFE | AUDITVNODE1,
1591 UIO_USERSPACE, uap->path, td);
1595 vfslocked = NDHASGIANT(&nd);
1597 if (nd.ni_vp != NULLVP || !(nd.ni_cnd.cn_flags & ISWHITEOUT)) {
1598 NDFREE(&nd, NDF_ONLY_PNBUF);
1599 if (nd.ni_vp == nd.ni_dvp)
1605 VFS_UNLOCK_GIANT(vfslocked);
1608 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) {
1609 NDFREE(&nd, NDF_ONLY_PNBUF);
1611 VFS_UNLOCK_GIANT(vfslocked);
1612 if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0)
1616 VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
1617 error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, DELETE);
1618 NDFREE(&nd, NDF_ONLY_PNBUF);
1620 vn_finished_write(mp);
1621 VFS_UNLOCK_GIANT(vfslocked);
1626 * Delete a name from the filesystem.
1628 #ifndef _SYS_SYSPROTO_H_
1629 struct unlink_args {
1636 struct unlink_args /* {
1642 error = kern_unlink(td, uap->path, UIO_USERSPACE);
1647 kern_unlink(struct thread *td, char *path, enum uio_seg pathseg)
1652 struct nameidata nd;
1657 NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF | MPSAFE | AUDITVNODE1,
1659 if ((error = namei(&nd)) != 0)
1660 return (error == EINVAL ? EPERM : error);
1661 vfslocked = NDHASGIANT(&nd);
1663 if (vp->v_type == VDIR)
1664 error = EPERM; /* POSIX */
1667 * The root of a mounted filesystem cannot be deleted.
1669 * XXX: can this only be a VDIR case?
1671 if (vp->v_vflag & VV_ROOT)
1675 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) {
1676 NDFREE(&nd, NDF_ONLY_PNBUF);
1678 if (vp == nd.ni_dvp)
1682 VFS_UNLOCK_GIANT(vfslocked);
1683 if ((error = vn_start_write(NULL, &mp,
1684 V_XSLEEP | PCATCH)) != 0)
1689 error = mac_check_vnode_delete(td->td_ucred, nd.ni_dvp, vp,
1694 VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
1695 error = VOP_REMOVE(nd.ni_dvp, vp, &nd.ni_cnd);
1699 vn_finished_write(mp);
1701 NDFREE(&nd, NDF_ONLY_PNBUF);
1703 if (vp == nd.ni_dvp)
1707 VFS_UNLOCK_GIANT(vfslocked);
1712 * Reposition read/write file offset.
1714 #ifndef _SYS_SYSPROTO_H_
1725 register struct lseek_args /* {
1732 struct ucred *cred = td->td_ucred;
1740 if ((error = fget(td, uap->fd, &fp)) != 0)
1742 if (!(fp->f_ops->fo_flags & DFLAG_SEEKABLE)) {
1747 vfslocked = VFS_LOCK_GIANT(vp->v_mount);
1748 noneg = (vp->v_type != VCHR);
1749 offset = uap->offset;
1750 switch (uap->whence) {
1753 (fp->f_offset < 0 ||
1754 (offset > 0 && fp->f_offset > OFF_MAX - offset))) {
1758 offset += fp->f_offset;
1761 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
1762 error = VOP_GETATTR(vp, &vattr, cred, td);
1763 VOP_UNLOCK(vp, 0, td);
1767 (vattr.va_size > OFF_MAX ||
1768 (offset > 0 && vattr.va_size > OFF_MAX - offset))) {
1772 offset += vattr.va_size;
1779 if (error == 0 && noneg && offset < 0)
1783 fp->f_offset = offset;
1784 *(off_t *)(td->td_retval) = fp->f_offset;
1787 VFS_UNLOCK_GIANT(vfslocked);
1791 #if defined(COMPAT_43)
1793 * Reposition read/write file offset.
1795 #ifndef _SYS_SYSPROTO_H_
1796 struct olseek_args {
1805 register struct olseek_args /* {
1811 struct lseek_args /* {
1820 nuap.offset = uap->offset;
1821 nuap.whence = uap->whence;
1822 error = lseek(td, &nuap);
1825 #endif /* COMPAT_43 */
1828 * Check access permissions using passed credentials.
1831 vn_access(vp, user_flags, cred, td)
1839 /* Flags == 0 means only check for existence. */
1843 if (user_flags & R_OK)
1845 if (user_flags & W_OK)
1847 if (user_flags & X_OK)
1850 error = mac_check_vnode_access(cred, vp, flags);
1854 if ((flags & VWRITE) == 0 || (error = vn_writechk(vp)) == 0)
1855 error = VOP_ACCESS(vp, flags, cred, td);
1861 * Check access permissions using "real" credentials.
1863 #ifndef _SYS_SYSPROTO_H_
1864 struct access_args {
1872 register struct access_args /* {
1878 return (kern_access(td, uap->path, UIO_USERSPACE, uap->flags));
1882 kern_access(struct thread *td, char *path, enum uio_seg pathseg, int flags)
1884 struct ucred *cred, *tmpcred;
1885 register struct vnode *vp;
1886 struct nameidata nd;
1891 * Create and modify a temporary credential instead of one that
1892 * is potentially shared. This could also mess up socket
1893 * buffer accounting which can run in an interrupt context.
1895 cred = td->td_ucred;
1896 tmpcred = crdup(cred);
1897 tmpcred->cr_uid = cred->cr_ruid;
1898 tmpcred->cr_groups[0] = cred->cr_rgid;
1899 td->td_ucred = tmpcred;
1900 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | MPSAFE | AUDITVNODE1,
1902 if ((error = namei(&nd)) != 0)
1904 vfslocked = NDHASGIANT(&nd);
1907 error = vn_access(vp, flags, tmpcred, td);
1908 NDFREE(&nd, NDF_ONLY_PNBUF);
1910 VFS_UNLOCK_GIANT(vfslocked);
1912 td->td_ucred = cred;
1918 * Check access permissions using "effective" credentials.
1920 #ifndef _SYS_SYSPROTO_H_
1921 struct eaccess_args {
1929 register struct eaccess_args /* {
1935 return (kern_eaccess(td, uap->path, UIO_USERSPACE, uap->flags));
1939 kern_eaccess(struct thread *td, char *path, enum uio_seg pathseg, int flags)
1941 struct nameidata nd;
1946 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | MPSAFE | AUDITVNODE1,
1948 if ((error = namei(&nd)) != 0)
1951 vfslocked = NDHASGIANT(&nd);
1952 error = vn_access(vp, flags, td->td_ucred, td);
1953 NDFREE(&nd, NDF_ONLY_PNBUF);
1955 VFS_UNLOCK_GIANT(vfslocked);
1959 #if defined(COMPAT_43)
1961 * Get file status; this version follows links.
1963 #ifndef _SYS_SYSPROTO_H_
1972 register struct ostat_args /* {
1981 error = kern_stat(td, uap->path, UIO_USERSPACE, &sb);
1985 error = copyout(&osb, uap->ub, sizeof (osb));
1990 * Get file status; this version does not follow links.
1992 #ifndef _SYS_SYSPROTO_H_
1993 struct olstat_args {
2001 register struct olstat_args /* {
2010 error = kern_lstat(td, uap->path, UIO_USERSPACE, &sb);
2014 error = copyout(&osb, uap->ub, sizeof (osb));
2019 * Convert from an old to a new stat structure.
2027 ost->st_dev = st->st_dev;
2028 ost->st_ino = st->st_ino;
2029 ost->st_mode = st->st_mode;
2030 ost->st_nlink = st->st_nlink;
2031 ost->st_uid = st->st_uid;
2032 ost->st_gid = st->st_gid;
2033 ost->st_rdev = st->st_rdev;
2034 if (st->st_size < (quad_t)1 << 32)
2035 ost->st_size = st->st_size;
2038 ost->st_atime = st->st_atime;
2039 ost->st_mtime = st->st_mtime;
2040 ost->st_ctime = st->st_ctime;
2041 ost->st_blksize = st->st_blksize;
2042 ost->st_blocks = st->st_blocks;
2043 ost->st_flags = st->st_flags;
2044 ost->st_gen = st->st_gen;
2046 #endif /* COMPAT_43 */
2049 * Get file status; this version follows links.
2051 #ifndef _SYS_SYSPROTO_H_
2060 register struct stat_args /* {
2068 error = kern_stat(td, uap->path, UIO_USERSPACE, &sb);
2070 error = copyout(&sb, uap->ub, sizeof (sb));
2075 kern_stat(struct thread *td, char *path, enum uio_seg pathseg, struct stat *sbp)
2077 struct nameidata nd;
2079 int error, vfslocked;
2082 FOLLOW | LOCKSHARED | LOCKLEAF | MPSAFE | AUDITVNODE1,
2084 if ((error = namei(&nd)) != 0)
2086 vfslocked = NDHASGIANT(&nd);
2087 error = vn_stat(nd.ni_vp, &sb, td->td_ucred, NOCRED, td);
2088 NDFREE(&nd, NDF_ONLY_PNBUF);
2090 VFS_UNLOCK_GIANT(vfslocked);
2098 * Get file status; this version does not follow links.
2100 #ifndef _SYS_SYSPROTO_H_
2109 register struct lstat_args /* {
2117 error = kern_lstat(td, uap->path, UIO_USERSPACE, &sb);
2119 error = copyout(&sb, uap->ub, sizeof (sb));
2124 kern_lstat(struct thread *td, char *path, enum uio_seg pathseg, struct stat *sbp)
2128 struct nameidata nd;
2129 int error, vfslocked;
2132 NOFOLLOW | LOCKLEAF | LOCKSHARED | MPSAFE | AUDITVNODE1,
2134 if ((error = namei(&nd)) != 0)
2136 vfslocked = NDHASGIANT(&nd);
2138 error = vn_stat(vp, &sb, td->td_ucred, NOCRED, td);
2139 NDFREE(&nd, NDF_ONLY_PNBUF);
2141 VFS_UNLOCK_GIANT(vfslocked);
2149 * Implementation of the NetBSD [l]stat() functions.
2156 bzero(nsb, sizeof *nsb);
2157 nsb->st_dev = sb->st_dev;
2158 nsb->st_ino = sb->st_ino;
2159 nsb->st_mode = sb->st_mode;
2160 nsb->st_nlink = sb->st_nlink;
2161 nsb->st_uid = sb->st_uid;
2162 nsb->st_gid = sb->st_gid;
2163 nsb->st_rdev = sb->st_rdev;
2164 nsb->st_atimespec = sb->st_atimespec;
2165 nsb->st_mtimespec = sb->st_mtimespec;
2166 nsb->st_ctimespec = sb->st_ctimespec;
2167 nsb->st_size = sb->st_size;
2168 nsb->st_blocks = sb->st_blocks;
2169 nsb->st_blksize = sb->st_blksize;
2170 nsb->st_flags = sb->st_flags;
2171 nsb->st_gen = sb->st_gen;
2172 nsb->st_birthtimespec = sb->st_birthtimespec;
2175 #ifndef _SYS_SYSPROTO_H_
2184 register struct nstat_args /* {
2193 error = kern_stat(td, uap->path, UIO_USERSPACE, &sb);
2196 cvtnstat(&sb, &nsb);
2197 error = copyout(&nsb, uap->ub, sizeof (nsb));
2202 * NetBSD lstat. Get file status; this version does not follow links.
2204 #ifndef _SYS_SYSPROTO_H_
2213 register struct nlstat_args /* {
2222 error = kern_lstat(td, uap->path, UIO_USERSPACE, &sb);
2225 cvtnstat(&sb, &nsb);
2226 error = copyout(&nsb, uap->ub, sizeof (nsb));
2231 * Get configurable pathname variables.
2233 #ifndef _SYS_SYSPROTO_H_
2234 struct pathconf_args {
2242 register struct pathconf_args /* {
2248 return (kern_pathconf(td, uap->path, UIO_USERSPACE, uap->name));
2252 kern_pathconf(struct thread *td, char *path, enum uio_seg pathseg, int name)
2254 struct nameidata nd;
2255 int error, vfslocked;
2257 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | MPSAFE | AUDITVNODE1,
2259 if ((error = namei(&nd)) != 0)
2261 vfslocked = NDHASGIANT(&nd);
2262 NDFREE(&nd, NDF_ONLY_PNBUF);
2264 /* If asynchronous I/O is available, it works for all files. */
2265 if (name == _PC_ASYNC_IO)
2266 td->td_retval[0] = async_io_version;
2268 error = VOP_PATHCONF(nd.ni_vp, name, td->td_retval);
2270 VFS_UNLOCK_GIANT(vfslocked);
2275 * Return target name of a symbolic link.
2277 #ifndef _SYS_SYSPROTO_H_
2278 struct readlink_args {
2287 register struct readlink_args /* {
2294 return (kern_readlink(td, uap->path, UIO_USERSPACE, uap->buf,
2295 UIO_USERSPACE, uap->count));
2299 kern_readlink(struct thread *td, char *path, enum uio_seg pathseg, char *buf,
2300 enum uio_seg bufseg, int count)
2302 register struct vnode *vp;
2306 struct nameidata nd;
2309 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | MPSAFE | AUDITVNODE1,
2311 if ((error = namei(&nd)) != 0)
2313 NDFREE(&nd, NDF_ONLY_PNBUF);
2314 vfslocked = NDHASGIANT(&nd);
2317 error = mac_check_vnode_readlink(td->td_ucred, vp);
2320 VFS_UNLOCK_GIANT(vfslocked);
2324 if (vp->v_type != VLNK)
2327 aiov.iov_base = buf;
2328 aiov.iov_len = count;
2329 auio.uio_iov = &aiov;
2330 auio.uio_iovcnt = 1;
2331 auio.uio_offset = 0;
2332 auio.uio_rw = UIO_READ;
2333 auio.uio_segflg = bufseg;
2335 auio.uio_resid = count;
2336 error = VOP_READLINK(vp, &auio, td->td_ucred);
2339 VFS_UNLOCK_GIANT(vfslocked);
2340 td->td_retval[0] = count - auio.uio_resid;
2345 * Common implementation code for chflags() and fchflags().
2348 setfflags(td, vp, flags)
2358 * Prevent non-root users from setting flags on devices. When
2359 * a device is reused, users can retain ownership of the device
2360 * if they are allowed to set flags and programs assume that
2361 * chown can't fail when done as root.
2363 if (vp->v_type == VCHR || vp->v_type == VBLK) {
2364 error = suser_cred(td->td_ucred, SUSER_ALLOWJAIL);
2369 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
2371 VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
2372 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
2374 vattr.va_flags = flags;
2376 error = mac_check_vnode_setflags(td->td_ucred, vp, vattr.va_flags);
2379 error = VOP_SETATTR(vp, &vattr, td->td_ucred, td);
2380 VOP_UNLOCK(vp, 0, td);
2381 vn_finished_write(mp);
2386 * Change flags of a file given a path name.
2388 #ifndef _SYS_SYSPROTO_H_
2389 struct chflags_args {
2397 register struct chflags_args /* {
2403 struct nameidata nd;
2406 AUDIT_ARG(fflags, uap->flags);
2407 NDINIT(&nd, LOOKUP, FOLLOW | MPSAFE | AUDITVNODE1, UIO_USERSPACE,
2409 if ((error = namei(&nd)) != 0)
2411 NDFREE(&nd, NDF_ONLY_PNBUF);
2412 vfslocked = NDHASGIANT(&nd);
2413 error = setfflags(td, nd.ni_vp, uap->flags);
2415 VFS_UNLOCK_GIANT(vfslocked);
2420 * Same as chflags() but doesn't follow symlinks.
2425 register struct lchflags_args /* {
2431 struct nameidata nd;
2434 AUDIT_ARG(fflags, uap->flags);
2435 NDINIT(&nd, LOOKUP, NOFOLLOW | MPSAFE | AUDITVNODE1, UIO_USERSPACE,
2437 if ((error = namei(&nd)) != 0)
2439 vfslocked = NDHASGIANT(&nd);
2440 NDFREE(&nd, NDF_ONLY_PNBUF);
2441 error = setfflags(td, nd.ni_vp, uap->flags);
2443 VFS_UNLOCK_GIANT(vfslocked);
2448 * Change flags of a file given a file descriptor.
2450 #ifndef _SYS_SYSPROTO_H_
2451 struct fchflags_args {
2459 register struct fchflags_args /* {
2468 AUDIT_ARG(fd, uap->fd);
2469 AUDIT_ARG(fflags, uap->flags);
2470 if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0)
2472 vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount);
2474 vn_lock(fp->f_vnode, LK_EXCLUSIVE | LK_RETRY, td);
2475 AUDIT_ARG(vnode, fp->f_vnode, ARG_VNODE1);
2476 VOP_UNLOCK(fp->f_vnode, 0, td);
2478 error = setfflags(td, fp->f_vnode, uap->flags);
2479 VFS_UNLOCK_GIANT(vfslocked);
2485 * Common implementation code for chmod(), lchmod() and fchmod().
2488 setfmode(td, vp, mode)
2497 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
2499 VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
2500 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
2502 vattr.va_mode = mode & ALLPERMS;
2504 error = mac_check_vnode_setmode(td->td_ucred, vp, vattr.va_mode);
2507 error = VOP_SETATTR(vp, &vattr, td->td_ucred, td);
2508 VOP_UNLOCK(vp, 0, td);
2509 vn_finished_write(mp);
2514 * Change mode of a file given path name.
2516 #ifndef _SYS_SYSPROTO_H_
2525 register struct chmod_args /* {
2531 return (kern_chmod(td, uap->path, UIO_USERSPACE, uap->mode));
2535 kern_chmod(struct thread *td, char *path, enum uio_seg pathseg, int mode)
2538 struct nameidata nd;
2541 AUDIT_ARG(mode, mode);
2542 NDINIT(&nd, LOOKUP, FOLLOW | MPSAFE | AUDITVNODE1, pathseg, path, td);
2543 if ((error = namei(&nd)) != 0)
2545 vfslocked = NDHASGIANT(&nd);
2546 NDFREE(&nd, NDF_ONLY_PNBUF);
2547 error = setfmode(td, nd.ni_vp, mode);
2549 VFS_UNLOCK_GIANT(vfslocked);
2554 * Change mode of a file given path name (don't follow links.)
2556 #ifndef _SYS_SYSPROTO_H_
2557 struct lchmod_args {
2565 register struct lchmod_args /* {
2571 struct nameidata nd;
2574 AUDIT_ARG(mode, (mode_t)uap->mode);
2575 NDINIT(&nd, LOOKUP, NOFOLLOW | MPSAFE | AUDITVNODE1, UIO_USERSPACE,
2577 if ((error = namei(&nd)) != 0)
2579 vfslocked = NDHASGIANT(&nd);
2580 NDFREE(&nd, NDF_ONLY_PNBUF);
2581 error = setfmode(td, nd.ni_vp, uap->mode);
2583 VFS_UNLOCK_GIANT(vfslocked);
2588 * Change mode of a file given a file descriptor.
2590 #ifndef _SYS_SYSPROTO_H_
2591 struct fchmod_args {
2599 register struct fchmod_args /* {
2608 AUDIT_ARG(fd, uap->fd);
2609 AUDIT_ARG(mode, uap->mode);
2610 if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0)
2612 vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount);
2614 vn_lock(fp->f_vnode, LK_EXCLUSIVE | LK_RETRY, td);
2615 AUDIT_ARG(vnode, fp->f_vnode, ARG_VNODE1);
2616 VOP_UNLOCK(fp->f_vnode, 0, td);
2618 error = setfmode(td, fp->f_vnode, uap->mode);
2619 VFS_UNLOCK_GIANT(vfslocked);
2625 * Common implementation for chown(), lchown(), and fchown()
2628 setfown(td, vp, uid, gid)
2638 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
2640 VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
2641 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
2646 error = mac_check_vnode_setowner(td->td_ucred, vp, vattr.va_uid,
2650 error = VOP_SETATTR(vp, &vattr, td->td_ucred, td);
2651 VOP_UNLOCK(vp, 0, td);
2652 vn_finished_write(mp);
2657 * Set ownership given a path name.
2659 #ifndef _SYS_SYSPROTO_H_
2669 register struct chown_args /* {
2676 return (kern_chown(td, uap->path, UIO_USERSPACE, uap->uid, uap->gid));
2680 kern_chown(struct thread *td, char *path, enum uio_seg pathseg, int uid,
2684 struct nameidata nd;
2687 AUDIT_ARG(owner, uid, gid);
2688 NDINIT(&nd, LOOKUP, FOLLOW | MPSAFE | AUDITVNODE1, pathseg, path, td);
2689 if ((error = namei(&nd)) != 0)
2691 vfslocked = NDHASGIANT(&nd);
2692 NDFREE(&nd, NDF_ONLY_PNBUF);
2693 error = setfown(td, nd.ni_vp, uid, gid);
2695 VFS_UNLOCK_GIANT(vfslocked);
2700 * Set ownership given a path name, do not cross symlinks.
2702 #ifndef _SYS_SYSPROTO_H_
2703 struct lchown_args {
2712 register struct lchown_args /* {
2719 return (kern_lchown(td, uap->path, UIO_USERSPACE, uap->uid, uap->gid));
2723 kern_lchown(struct thread *td, char *path, enum uio_seg pathseg, int uid,
2727 struct nameidata nd;
2730 AUDIT_ARG(owner, uid, gid);
2731 NDINIT(&nd, LOOKUP, NOFOLLOW | MPSAFE | AUDITVNODE1, pathseg, path, td);
2732 if ((error = namei(&nd)) != 0)
2734 vfslocked = NDHASGIANT(&nd);
2735 NDFREE(&nd, NDF_ONLY_PNBUF);
2736 error = setfown(td, nd.ni_vp, uid, gid);
2738 VFS_UNLOCK_GIANT(vfslocked);
2743 * Set ownership given a file descriptor.
2745 #ifndef _SYS_SYSPROTO_H_
2746 struct fchown_args {
2755 register struct fchown_args /* {
2765 AUDIT_ARG(fd, uap->fd);
2766 AUDIT_ARG(owner, uap->uid, uap->gid);
2767 if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0)
2769 vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount);
2771 vn_lock(fp->f_vnode, LK_EXCLUSIVE | LK_RETRY, td);
2772 AUDIT_ARG(vnode, fp->f_vnode, ARG_VNODE1);
2773 VOP_UNLOCK(fp->f_vnode, 0, td);
2775 error = setfown(td, fp->f_vnode, uap->uid, uap->gid);
2776 VFS_UNLOCK_GIANT(vfslocked);
2782 * Common implementation code for utimes(), lutimes(), and futimes().
2785 getutimes(usrtvp, tvpseg, tsp)
2786 const struct timeval *usrtvp;
2787 enum uio_seg tvpseg;
2788 struct timespec *tsp;
2790 struct timeval tv[2];
2791 const struct timeval *tvp;
2794 if (usrtvp == NULL) {
2796 TIMEVAL_TO_TIMESPEC(&tv[0], &tsp[0]);
2799 if (tvpseg == UIO_SYSSPACE) {
2802 if ((error = copyin(usrtvp, tv, sizeof(tv))) != 0)
2807 if (tvp[0].tv_usec < 0 || tvp[0].tv_usec >= 1000000 ||
2808 tvp[1].tv_usec < 0 || tvp[1].tv_usec >= 1000000)
2810 TIMEVAL_TO_TIMESPEC(&tvp[0], &tsp[0]);
2811 TIMEVAL_TO_TIMESPEC(&tvp[1], &tsp[1]);
2817 * Common implementation code for utimes(), lutimes(), and futimes().
2820 setutimes(td, vp, ts, numtimes, nullflag)
2823 const struct timespec *ts;
2827 int error, setbirthtime;
2831 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
2833 VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
2834 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
2836 if (numtimes < 3 && VOP_GETATTR(vp, &vattr, td->td_ucred, td) == 0 &&
2837 timespeccmp(&ts[1], &vattr.va_birthtime, < ))
2840 vattr.va_atime = ts[0];
2841 vattr.va_mtime = ts[1];
2843 vattr.va_birthtime = ts[1];
2845 vattr.va_birthtime = ts[2];
2847 vattr.va_vaflags |= VA_UTIMES_NULL;
2849 error = mac_check_vnode_setutimes(td->td_ucred, vp, vattr.va_atime,
2853 error = VOP_SETATTR(vp, &vattr, td->td_ucred, td);
2854 VOP_UNLOCK(vp, 0, td);
2855 vn_finished_write(mp);
2860 * Set the access and modification times of a file.
2862 #ifndef _SYS_SYSPROTO_H_
2863 struct utimes_args {
2865 struct timeval *tptr;
2871 register struct utimes_args /* {
2873 struct timeval *tptr;
2877 return (kern_utimes(td, uap->path, UIO_USERSPACE, uap->tptr,
2882 kern_utimes(struct thread *td, char *path, enum uio_seg pathseg,
2883 struct timeval *tptr, enum uio_seg tptrseg)
2885 struct timespec ts[2];
2887 struct nameidata nd;
2890 if ((error = getutimes(tptr, tptrseg, ts)) != 0)
2892 NDINIT(&nd, LOOKUP, FOLLOW | MPSAFE | AUDITVNODE1, pathseg, path, td);
2893 if ((error = namei(&nd)) != 0)
2895 vfslocked = NDHASGIANT(&nd);
2896 NDFREE(&nd, NDF_ONLY_PNBUF);
2897 error = setutimes(td, nd.ni_vp, ts, 2, tptr == NULL);
2899 VFS_UNLOCK_GIANT(vfslocked);
2904 * Set the access and modification times of a file.
2906 #ifndef _SYS_SYSPROTO_H_
2907 struct lutimes_args {
2909 struct timeval *tptr;
2915 register struct lutimes_args /* {
2917 struct timeval *tptr;
2921 return (kern_lutimes(td, uap->path, UIO_USERSPACE, uap->tptr,
2926 kern_lutimes(struct thread *td, char *path, enum uio_seg pathseg,
2927 struct timeval *tptr, enum uio_seg tptrseg)
2929 struct timespec ts[2];
2931 struct nameidata nd;
2934 if ((error = getutimes(tptr, tptrseg, ts)) != 0)
2936 NDINIT(&nd, LOOKUP, NOFOLLOW | MPSAFE | AUDITVNODE1, pathseg, path, td);
2937 if ((error = namei(&nd)) != 0)
2939 vfslocked = NDHASGIANT(&nd);
2940 NDFREE(&nd, NDF_ONLY_PNBUF);
2941 error = setutimes(td, nd.ni_vp, ts, 2, tptr == NULL);
2943 VFS_UNLOCK_GIANT(vfslocked);
2948 * Set the access and modification times of a file.
2950 #ifndef _SYS_SYSPROTO_H_
2951 struct futimes_args {
2953 struct timeval *tptr;
2959 register struct futimes_args /* {
2961 struct timeval *tptr;
2965 return (kern_futimes(td, uap->fd, uap->tptr, UIO_USERSPACE));
2969 kern_futimes(struct thread *td, int fd, struct timeval *tptr,
2970 enum uio_seg tptrseg)
2972 struct timespec ts[2];
2978 if ((error = getutimes(tptr, tptrseg, ts)) != 0)
2980 if ((error = getvnode(td->td_proc->p_fd, fd, &fp)) != 0)
2982 vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount);
2984 vn_lock(fp->f_vnode, LK_EXCLUSIVE | LK_RETRY, td);
2985 AUDIT_ARG(vnode, fp->f_vnode, ARG_VNODE1);
2986 VOP_UNLOCK(fp->f_vnode, 0, td);
2988 error = setutimes(td, fp->f_vnode, ts, 2, tptr == NULL);
2989 VFS_UNLOCK_GIANT(vfslocked);
2995 * Truncate a file given its path name.
2997 #ifndef _SYS_SYSPROTO_H_
2998 struct truncate_args {
3007 register struct truncate_args /* {
3014 return (kern_truncate(td, uap->path, UIO_USERSPACE, uap->length));
3018 kern_truncate(struct thread *td, char *path, enum uio_seg pathseg, off_t length)
3024 struct nameidata nd;
3029 NDINIT(&nd, LOOKUP, FOLLOW | MPSAFE | AUDITVNODE1, pathseg, path, td);
3030 if ((error = namei(&nd)) != 0)
3032 vfslocked = NDHASGIANT(&nd);
3034 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) {
3036 VFS_UNLOCK_GIANT(vfslocked);
3039 NDFREE(&nd, NDF_ONLY_PNBUF);
3040 VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
3041 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
3042 if (vp->v_type == VDIR)
3045 else if ((error = mac_check_vnode_write(td->td_ucred, NOCRED, vp))) {
3048 else if ((error = vn_writechk(vp)) == 0 &&
3049 (error = VOP_ACCESS(vp, VWRITE, td->td_ucred, td)) == 0) {
3051 vattr.va_size = length;
3052 error = VOP_SETATTR(vp, &vattr, td->td_ucred, td);
3055 vn_finished_write(mp);
3056 VFS_UNLOCK_GIANT(vfslocked);
3061 * Truncate a file given a file descriptor.
3063 #ifndef _SYS_SYSPROTO_H_
3064 struct ftruncate_args {
3073 register struct ftruncate_args /* {
3086 AUDIT_ARG(fd, uap->fd);
3087 if (uap->length < 0)
3089 if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0)
3091 if ((fp->f_flag & FWRITE) == 0) {
3096 vfslocked = VFS_LOCK_GIANT(vp->v_mount);
3097 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
3099 VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
3100 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
3101 AUDIT_ARG(vnode, vp, ARG_VNODE1);
3102 if (vp->v_type == VDIR)
3105 else if ((error = mac_check_vnode_write(td->td_ucred, fp->f_cred,
3109 else if ((error = vn_writechk(vp)) == 0) {
3111 vattr.va_size = uap->length;
3112 error = VOP_SETATTR(vp, &vattr, fp->f_cred, td);
3114 VOP_UNLOCK(vp, 0, td);
3115 vn_finished_write(mp);
3117 VFS_UNLOCK_GIANT(vfslocked);
3122 #if defined(COMPAT_43)
3124 * Truncate a file given its path name.
3126 #ifndef _SYS_SYSPROTO_H_
3127 struct otruncate_args {
3135 register struct otruncate_args /* {
3140 struct truncate_args /* {
3146 nuap.path = uap->path;
3147 nuap.length = uap->length;
3148 return (truncate(td, &nuap));
3152 * Truncate a file given a file descriptor.
3154 #ifndef _SYS_SYSPROTO_H_
3155 struct oftruncate_args {
3163 register struct oftruncate_args /* {
3168 struct ftruncate_args /* {
3175 nuap.length = uap->length;
3176 return (ftruncate(td, &nuap));
3178 #endif /* COMPAT_43 */
3181 * Sync an open file.
3183 #ifndef _SYS_SYSPROTO_H_
3191 struct fsync_args /* {
3201 AUDIT_ARG(fd, uap->fd);
3202 if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0)
3205 vfslocked = VFS_LOCK_GIANT(vp->v_mount);
3206 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
3208 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
3209 AUDIT_ARG(vnode, vp, ARG_VNODE1);
3210 if (vp->v_object != NULL) {
3211 VM_OBJECT_LOCK(vp->v_object);
3212 vm_object_page_clean(vp->v_object, 0, 0, 0);
3213 VM_OBJECT_UNLOCK(vp->v_object);
3215 error = VOP_FSYNC(vp, MNT_WAIT, td);
3217 VOP_UNLOCK(vp, 0, td);
3218 vn_finished_write(mp);
3220 VFS_UNLOCK_GIANT(vfslocked);
3226 * Rename files. Source and destination must either both be directories,
3227 * or both not be directories. If target is a directory, it must be empty.
3229 #ifndef _SYS_SYSPROTO_H_
3230 struct rename_args {
3238 register struct rename_args /* {
3244 return (kern_rename(td, uap->from, uap->to, UIO_USERSPACE));
3248 kern_rename(struct thread *td, char *from, char *to, enum uio_seg pathseg)
3250 struct mount *mp = NULL;
3251 struct vnode *tvp, *fvp, *tdvp;
3252 struct nameidata fromnd, tond;
3259 NDINIT(&fromnd, DELETE, LOCKPARENT | LOCKLEAF | SAVESTART | MPSAFE |
3260 AUDITVNODE1, pathseg, from, td);
3262 NDINIT(&fromnd, DELETE, WANTPARENT | SAVESTART | MPSAFE |
3263 AUDITVNODE1, pathseg, from, td);
3265 if ((error = namei(&fromnd)) != 0)
3267 fvfslocked = NDHASGIANT(&fromnd);
3270 error = mac_check_vnode_rename_from(td->td_ucred, fromnd.ni_dvp,
3271 fromnd.ni_vp, &fromnd.ni_cnd);
3272 VOP_UNLOCK(fromnd.ni_dvp, 0, td);
3273 VOP_UNLOCK(fromnd.ni_vp, 0, td);
3277 error = vn_start_write(fvp, &mp, V_WAIT | PCATCH);
3279 NDFREE(&fromnd, NDF_ONLY_PNBUF);
3280 vrele(fromnd.ni_dvp);
3284 NDINIT(&tond, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART |
3285 MPSAFE | AUDITVNODE2, pathseg, to, td);
3286 if (fromnd.ni_vp->v_type == VDIR)
3287 tond.ni_cnd.cn_flags |= WILLBEDIR;
3288 if ((error = namei(&tond)) != 0) {
3289 /* Translate error code for rename("dir1", "dir2/."). */
3290 if (error == EISDIR && fvp->v_type == VDIR)
3292 NDFREE(&fromnd, NDF_ONLY_PNBUF);
3293 vrele(fromnd.ni_dvp);
3295 vn_finished_write(mp);
3298 tvfslocked = NDHASGIANT(&tond);
3302 if (fvp->v_type == VDIR && tvp->v_type != VDIR) {
3305 } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) {
3313 * If the source is the same as the destination (that is, if they
3314 * are links to the same vnode), then there is nothing to do.
3320 error = mac_check_vnode_rename_to(td->td_ucred, tdvp,
3321 tond.ni_vp, fromnd.ni_dvp == tdvp, &tond.ni_cnd);
3325 VOP_LEASE(tdvp, td, td->td_ucred, LEASE_WRITE);
3326 if (fromnd.ni_dvp != tdvp) {
3327 VOP_LEASE(fromnd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
3330 VOP_LEASE(tvp, td, td->td_ucred, LEASE_WRITE);
3332 error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd,
3333 tond.ni_dvp, tond.ni_vp, &tond.ni_cnd);
3334 NDFREE(&fromnd, NDF_ONLY_PNBUF);
3335 NDFREE(&tond, NDF_ONLY_PNBUF);
3337 NDFREE(&fromnd, NDF_ONLY_PNBUF);
3338 NDFREE(&tond, NDF_ONLY_PNBUF);
3345 vrele(fromnd.ni_dvp);
3348 vrele(tond.ni_startdir);
3349 vn_finished_write(mp);
3351 if (fromnd.ni_startdir)
3352 vrele(fromnd.ni_startdir);
3353 VFS_UNLOCK_GIANT(fvfslocked);
3354 VFS_UNLOCK_GIANT(tvfslocked);
3361 * Make a directory file.
3363 #ifndef _SYS_SYSPROTO_H_
3372 register struct mkdir_args /* {
3378 return (kern_mkdir(td, uap->path, UIO_USERSPACE, uap->mode));
3382 kern_mkdir(struct thread *td, char *path, enum uio_seg segflg, int mode)
3388 struct nameidata nd;
3391 AUDIT_ARG(mode, mode);
3394 NDINIT(&nd, CREATE, LOCKPARENT | SAVENAME | MPSAFE | AUDITVNODE1,
3396 nd.ni_cnd.cn_flags |= WILLBEDIR;
3397 if ((error = namei(&nd)) != 0)
3399 vfslocked = NDHASGIANT(&nd);
3402 NDFREE(&nd, NDF_ONLY_PNBUF);
3404 * XXX namei called with LOCKPARENT but not LOCKLEAF has
3405 * the strange behaviour of leaving the vnode unlocked
3406 * if the target is the same vnode as the parent.
3408 if (vp == nd.ni_dvp)
3413 VFS_UNLOCK_GIANT(vfslocked);
3416 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) {
3417 NDFREE(&nd, NDF_ONLY_PNBUF);
3419 VFS_UNLOCK_GIANT(vfslocked);
3420 if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0)
3425 vattr.va_type = VDIR;
3426 FILEDESC_LOCK_FAST(td->td_proc->p_fd);
3427 vattr.va_mode = (mode & ACCESSPERMS) &~ td->td_proc->p_fd->fd_cmask;
3428 FILEDESC_UNLOCK_FAST(td->td_proc->p_fd);
3430 error = mac_check_vnode_create(td->td_ucred, nd.ni_dvp, &nd.ni_cnd,
3435 VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
3436 error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
3440 NDFREE(&nd, NDF_ONLY_PNBUF);
3444 vn_finished_write(mp);
3445 VFS_UNLOCK_GIANT(vfslocked);
3450 * Remove a directory file.
3452 #ifndef _SYS_SYSPROTO_H_
3460 struct rmdir_args /* {
3465 return (kern_rmdir(td, uap->path, UIO_USERSPACE));
3469 kern_rmdir(struct thread *td, char *path, enum uio_seg pathseg)
3474 struct nameidata nd;
3479 NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF | MPSAFE | AUDITVNODE1,
3481 if ((error = namei(&nd)) != 0)
3483 vfslocked = NDHASGIANT(&nd);
3485 if (vp->v_type != VDIR) {
3490 * No rmdir "." please.
3492 if (nd.ni_dvp == vp) {
3497 * The root of a mounted filesystem cannot be deleted.
3499 if (vp->v_vflag & VV_ROOT) {
3504 error = mac_check_vnode_delete(td->td_ucred, nd.ni_dvp, vp,
3509 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) {
3510 NDFREE(&nd, NDF_ONLY_PNBUF);
3512 if (nd.ni_dvp == vp)
3516 VFS_UNLOCK_GIANT(vfslocked);
3517 if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0)
3521 VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
3522 VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
3523 error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
3524 vn_finished_write(mp);
3526 NDFREE(&nd, NDF_ONLY_PNBUF);
3528 if (nd.ni_dvp == vp)
3532 VFS_UNLOCK_GIANT(vfslocked);
3538 * Read a block of directory entries in a filesystem independent format.
3540 #ifndef _SYS_SYSPROTO_H_
3541 struct ogetdirentries_args {
3549 ogetdirentries(td, uap)
3551 register struct ogetdirentries_args /* {
3560 struct uio auio, kuio;
3561 struct iovec aiov, kiov;
3562 struct dirent *dp, *edp;
3564 int error, eofflag, readcnt;
3567 /* XXX arbitrary sanity limit on `count'. */
3568 if (uap->count > 64 * 1024)
3570 if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0)
3572 if ((fp->f_flag & FREAD) == 0) {
3578 if (vp->v_type != VDIR) {
3582 aiov.iov_base = uap->buf;
3583 aiov.iov_len = uap->count;
3584 auio.uio_iov = &aiov;
3585 auio.uio_iovcnt = 1;
3586 auio.uio_rw = UIO_READ;
3587 auio.uio_segflg = UIO_USERSPACE;
3589 auio.uio_resid = uap->count;
3590 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
3591 loff = auio.uio_offset = fp->f_offset;
3593 error = mac_check_vnode_readdir(td->td_ucred, vp);
3595 VOP_UNLOCK(vp, 0, td);
3600 # if (BYTE_ORDER != LITTLE_ENDIAN)
3601 if (vp->v_mount->mnt_maxsymlinklen <= 0) {
3602 error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag,
3604 fp->f_offset = auio.uio_offset;
3609 kuio.uio_iov = &kiov;
3610 kuio.uio_segflg = UIO_SYSSPACE;
3611 kiov.iov_len = uap->count;
3612 MALLOC(dirbuf, caddr_t, uap->count, M_TEMP, M_WAITOK);
3613 kiov.iov_base = dirbuf;
3614 error = VOP_READDIR(vp, &kuio, fp->f_cred, &eofflag,
3616 fp->f_offset = kuio.uio_offset;
3618 readcnt = uap->count - kuio.uio_resid;
3619 edp = (struct dirent *)&dirbuf[readcnt];
3620 for (dp = (struct dirent *)dirbuf; dp < edp; ) {
3621 # if (BYTE_ORDER == LITTLE_ENDIAN)
3623 * The expected low byte of
3624 * dp->d_namlen is our dp->d_type.
3625 * The high MBZ byte of dp->d_namlen
3626 * is our dp->d_namlen.
3628 dp->d_type = dp->d_namlen;
3632 * The dp->d_type is the high byte
3633 * of the expected dp->d_namlen,
3634 * so must be zero'ed.
3638 if (dp->d_reclen > 0) {
3639 dp = (struct dirent *)
3640 ((char *)dp + dp->d_reclen);
3647 error = uiomove(dirbuf, readcnt, &auio);
3649 FREE(dirbuf, M_TEMP);
3651 VOP_UNLOCK(vp, 0, td);
3656 if (uap->count == auio.uio_resid) {
3657 if (union_dircheckp) {
3658 error = union_dircheckp(td, &vp, fp);
3667 * XXX We could delay dropping the lock above but
3668 * union_dircheckp complicates things.
3670 vn_lock(vp, LK_EXCLUSIVE|LK_RETRY, td);
3671 if ((vp->v_vflag & VV_ROOT) &&
3672 (vp->v_mount->mnt_flag & MNT_UNION)) {
3673 struct vnode *tvp = vp;
3674 vp = vp->v_mount->mnt_vnodecovered;
3682 VOP_UNLOCK(vp, 0, td);
3684 error = copyout(&loff, uap->basep, sizeof(long));
3686 td->td_retval[0] = uap->count - auio.uio_resid;
3689 #endif /* COMPAT_43 */
3692 * Read a block of directory entries in a filesystem independent format.
3694 #ifndef _SYS_SYSPROTO_H_
3695 struct getdirentries_args {
3703 getdirentries(td, uap)
3705 register struct getdirentries_args /* {
3720 AUDIT_ARG(fd, uap->fd);
3721 if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0)
3723 if ((fp->f_flag & FREAD) == 0) {
3729 vfslocked = VFS_LOCK_GIANT(vp->v_mount);
3730 if (vp->v_type != VDIR) {
3734 aiov.iov_base = uap->buf;
3735 aiov.iov_len = uap->count;
3736 auio.uio_iov = &aiov;
3737 auio.uio_iovcnt = 1;
3738 auio.uio_rw = UIO_READ;
3739 auio.uio_segflg = UIO_USERSPACE;
3741 auio.uio_resid = uap->count;
3742 /* vn_lock(vp, LK_SHARED | LK_RETRY, td); */
3743 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
3744 AUDIT_ARG(vnode, vp, ARG_VNODE1);
3745 loff = auio.uio_offset = fp->f_offset;
3747 error = mac_check_vnode_readdir(td->td_ucred, vp);
3750 error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, NULL,
3752 fp->f_offset = auio.uio_offset;
3753 VOP_UNLOCK(vp, 0, td);
3756 if (uap->count == auio.uio_resid) {
3757 if (union_dircheckp) {
3758 error = union_dircheckp(td, &vp, fp);
3760 VFS_UNLOCK_GIANT(vfslocked);
3767 * XXX We could delay dropping the lock above but
3768 * union_dircheckp complicates things.
3770 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
3771 if ((vp->v_vflag & VV_ROOT) &&
3772 (vp->v_mount->mnt_flag & MNT_UNION)) {
3773 struct vnode *tvp = vp;
3774 vp = vp->v_mount->mnt_vnodecovered;
3780 VFS_UNLOCK_GIANT(vfslocked);
3783 VOP_UNLOCK(vp, 0, td);
3785 if (uap->basep != NULL) {
3786 error = copyout(&loff, uap->basep, sizeof(long));
3788 td->td_retval[0] = uap->count - auio.uio_resid;
3790 VFS_UNLOCK_GIANT(vfslocked);
3794 #ifndef _SYS_SYSPROTO_H_
3795 struct getdents_args {
3804 register struct getdents_args /* {
3810 struct getdirentries_args ap;
3813 ap.count = uap->count;
3815 return (getdirentries(td, &ap));
3819 * Set the mode mask for creation of filesystem nodes.
3823 #ifndef _SYS_SYSPROTO_H_
3831 struct umask_args /* {
3835 register struct filedesc *fdp;
3837 FILEDESC_LOCK_FAST(td->td_proc->p_fd);
3838 fdp = td->td_proc->p_fd;
3839 td->td_retval[0] = fdp->fd_cmask;
3840 fdp->fd_cmask = uap->newmask & ALLPERMS;
3841 FILEDESC_UNLOCK_FAST(td->td_proc->p_fd);
3846 * Void all references to file by ripping underlying filesystem
3849 #ifndef _SYS_SYSPROTO_H_
3850 struct revoke_args {
3857 register struct revoke_args /* {
3864 struct nameidata nd;
3867 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | MPSAFE | AUDITVNODE1,
3868 UIO_USERSPACE, uap->path, td);
3869 if ((error = namei(&nd)) != 0)
3871 vfslocked = NDHASGIANT(&nd);
3873 NDFREE(&nd, NDF_ONLY_PNBUF);
3874 if (vp->v_type != VCHR) {
3879 error = mac_check_vnode_revoke(td->td_ucred, vp);
3883 error = VOP_GETATTR(vp, &vattr, td->td_ucred, td);
3886 if (td->td_ucred->cr_uid != vattr.va_uid) {
3887 error = suser_cred(td->td_ucred, SUSER_ALLOWJAIL);
3892 VOP_REVOKE(vp, REVOKEALL);
3895 VFS_UNLOCK_GIANT(vfslocked);
3900 * Convert a user file descriptor to a kernel file entry.
3901 * A reference on the file entry is held upon returning.
3904 getvnode(fdp, fd, fpp)
3905 struct filedesc *fdp;
3917 if ((u_int)fd >= fdp->fd_nfiles ||
3918 (fp = fdp->fd_ofiles[fd]) == NULL)
3920 else if (fp->f_vnode == NULL) {
3927 FILEDESC_UNLOCK(fdp);
3934 * Get (NFS) file handle
3936 #ifndef _SYS_SYSPROTO_H_
3937 struct lgetfh_args {
3945 register struct lgetfh_args *uap;
3947 struct nameidata nd;
3949 register struct vnode *vp;
3956 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | MPSAFE | AUDITVNODE1,
3957 UIO_USERSPACE, uap->fname, td);
3961 vfslocked = NDHASGIANT(&nd);
3962 NDFREE(&nd, NDF_ONLY_PNBUF);
3964 bzero(&fh, sizeof(fh));
3965 fh.fh_fsid = vp->v_mount->mnt_stat.f_fsid;
3966 error = VFS_VPTOFH(vp, &fh.fh_fid);
3968 VFS_UNLOCK_GIANT(vfslocked);
3971 error = copyout(&fh, uap->fhp, sizeof (fh));
3975 #ifndef _SYS_SYSPROTO_H_
3984 register struct getfh_args *uap;
3986 struct nameidata nd;
3988 register struct vnode *vp;
3995 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | MPSAFE | AUDITVNODE1,
3996 UIO_USERSPACE, uap->fname, td);
4000 vfslocked = NDHASGIANT(&nd);
4001 NDFREE(&nd, NDF_ONLY_PNBUF);
4003 bzero(&fh, sizeof(fh));
4004 fh.fh_fsid = vp->v_mount->mnt_stat.f_fsid;
4005 error = VFS_VPTOFH(vp, &fh.fh_fid);
4007 VFS_UNLOCK_GIANT(vfslocked);
4010 error = copyout(&fh, uap->fhp, sizeof (fh));
4015 * syscall for the rpc.lockd to use to translate a NFS file handle into
4016 * an open descriptor.
4018 * warning: do not remove the suser() call or this becomes one giant
4023 #ifndef _SYS_SYSPROTO_H_
4024 struct fhopen_args {
4025 const struct fhandle *u_fhp;
4032 struct fhopen_args /* {
4033 const struct fhandle *u_fhp;
4037 struct proc *p = td->td_proc;
4042 struct vattr *vap = &vat;
4045 register struct filedesc *fdp = p->p_fd;
4046 int fmode, mode, error, type;
4054 fmode = FFLAGS(uap->flags);
4055 /* why not allow a non-read/write open for our lockd? */
4056 if (((fmode & (FREAD | FWRITE)) == 0) || (fmode & O_CREAT))
4058 error = copyin(uap->u_fhp, &fhp, sizeof(fhp));
4061 /* find the mount point */
4063 mp = vfs_getvfs(&fhp.fh_fsid);
4068 vfslocked = VFS_LOCK_GIANT(mp);
4069 /* now give me my vnode, it gets returned to me locked */
4070 error = VFS_FHTOVP(mp, &fhp.fh_fid, &vp);
4074 * from now on we have to make sure not
4075 * to forget about the vnode
4076 * any error that causes an abort must vput(vp)
4077 * just set error = err and 'goto bad;'.
4083 if (vp->v_type == VLNK) {
4087 if (vp->v_type == VSOCK) {
4092 if (fmode & (FWRITE | O_TRUNC)) {
4093 if (vp->v_type == VDIR) {
4097 error = vn_writechk(vp);
4104 if (fmode & O_APPEND)
4107 error = mac_check_vnode_open(td->td_ucred, vp, mode);
4112 error = VOP_ACCESS(vp, mode, td->td_ucred, td);
4116 if (fmode & O_TRUNC) {
4117 VOP_UNLOCK(vp, 0, td); /* XXX */
4118 if ((error = vn_start_write(NULL, &mp, V_WAIT | PCATCH)) != 0) {
4122 VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
4123 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); /* XXX */
4126 * We don't yet have fp->f_cred, so use td->td_ucred, which
4129 error = mac_check_vnode_write(td->td_ucred, td->td_ucred, vp);
4134 error = VOP_SETATTR(vp, vap, td->td_ucred, td);
4138 vn_finished_write(mp);
4142 error = VOP_OPEN(vp, fmode, td->td_ucred, td, -1);
4150 * end of vn_open code
4153 if ((error = falloc(td, &nfp, &indx)) != 0) {
4158 /* An extra reference on `nfp' has been held for us by falloc(). */
4163 nfp->f_flag = fmode & FMASK;
4164 nfp->f_ops = &vnops;
4165 nfp->f_type = DTYPE_VNODE;
4166 if (fmode & (O_EXLOCK | O_SHLOCK)) {
4167 lf.l_whence = SEEK_SET;
4170 if (fmode & O_EXLOCK)
4171 lf.l_type = F_WRLCK;
4173 lf.l_type = F_RDLCK;
4175 if ((fmode & FNONBLOCK) == 0)
4177 VOP_UNLOCK(vp, 0, td);
4178 if ((error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf,
4181 * The lock request failed. Normally close the
4182 * descriptor but handle the case where someone might
4183 * have dup()d or close()d it when we weren't looking.
4185 fdclose(fdp, fp, indx, td);
4188 * release our private reference
4193 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
4194 fp->f_flag |= FHASLOCK;
4197 VOP_UNLOCK(vp, 0, td);
4199 VFS_UNLOCK_GIANT(vfslocked);
4200 td->td_retval[0] = indx;
4206 VFS_UNLOCK_GIANT(vfslocked);
4211 * Stat an (NFS) file handle.
4215 #ifndef _SYS_SYSPROTO_H_
4216 struct fhstat_args {
4217 struct fhandle *u_fhp;
4224 register struct fhstat_args /* {
4225 struct fhandle *u_fhp;
4239 error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t));
4242 if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL)
4244 vfslocked = VFS_LOCK_GIANT(mp);
4245 if ((error = VFS_FHTOVP(mp, &fh.fh_fid, &vp))) {
4246 VFS_UNLOCK_GIANT(vfslocked);
4249 error = vn_stat(vp, &sb, td->td_ucred, NOCRED, td);
4251 VFS_UNLOCK_GIANT(vfslocked);
4254 error = copyout(&sb, uap->sb, sizeof(sb));
4259 * Implement fstatfs() for (NFS) file handles.
4263 #ifndef _SYS_SYSPROTO_H_
4264 struct fhstatfs_args {
4265 struct fhandle *u_fhp;
4272 struct fhstatfs_args /* {
4273 struct fhandle *u_fhp;
4281 error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t));
4284 error = kern_fhstatfs(td, fh, &sf);
4287 return (copyout(&sf, uap->buf, sizeof(sf)));
4291 kern_fhstatfs(struct thread *td, fhandle_t fh, struct statfs *buf)
4302 if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL)
4304 vfslocked = VFS_LOCK_GIANT(mp);
4305 error = VFS_FHTOVP(mp, &fh.fh_fid, &vp);
4307 VFS_UNLOCK_GIANT(vfslocked);
4316 VFS_UNLOCK_GIANT(vfslocked);
4319 error = prison_canseemount(td->td_ucred, mp);
4323 error = mac_check_mount_stat(td->td_ucred, mp);
4328 * Set these in case the underlying filesystem fails to do so.
4331 sp->f_version = STATFS_VERSION;
4332 sp->f_namemax = NAME_MAX;
4333 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
4334 error = VFS_STATFS(mp, sp, td);
4337 VFS_UNLOCK_GIANT(vfslocked);
4344 * Syscall to push extended attribute configuration information into the
4345 * VFS. Accepts a path, which it converts to a mountpoint, as well as
4346 * a command (int cmd), and attribute name and misc data. For now, the
4347 * attribute name is left in userspace for consumption by the VFS_op.
4348 * It will probably be changed to be copied into sysspace by the
4349 * syscall in the future, once issues with various consumers of the
4350 * attribute code have raised their hands.
4352 * Currently this is used only by UFS Extended Attributes.
4357 struct extattrctl_args /* {
4360 const char *filename;
4362 const char *attrname;
4365 struct vnode *filename_vp;
4366 struct nameidata nd;
4367 struct mount *mp, *mp_writable;
4368 char attrname[EXTATTR_MAXNAMELEN];
4369 int vfslocked, fnvfslocked, error;
4372 * uap->attrname is not always defined. We check again later when we
4373 * invoke the VFS call so as to pass in NULL there if needed.
4375 if (uap->attrname != NULL) {
4376 error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN,
4382 vfslocked = fnvfslocked = 0;
4384 * uap->filename is not always defined. If it is, grab a vnode lock,
4385 * which VFS_EXTATTRCTL() will later release.
4388 if (uap->filename != NULL) {
4389 NDINIT(&nd, LOOKUP, MPSAFE | FOLLOW | LOCKLEAF |
4390 AUDITVNODE2, UIO_USERSPACE, uap->filename, td);
4394 fnvfslocked = NDHASGIANT(&nd);
4395 filename_vp = nd.ni_vp;
4396 NDFREE(&nd, NDF_NO_VP_RELE | NDF_NO_VP_UNLOCK);
4399 /* uap->path is always defined. */
4400 NDINIT(&nd, LOOKUP, MPSAFE | FOLLOW | AUDITVNODE1, UIO_USERSPACE,
4404 if (filename_vp != NULL)
4408 vfslocked = NDHASGIANT(&nd);
4409 mp = nd.ni_vp->v_mount;
4410 error = vn_start_write(nd.ni_vp, &mp_writable, V_WAIT | PCATCH);
4413 if (filename_vp != NULL)
4418 error = VFS_EXTATTRCTL(mp, uap->cmd, filename_vp, uap->attrnamespace,
4419 uap->attrname != NULL ? attrname : NULL, td);
4421 vn_finished_write(mp_writable);
4423 * VFS_EXTATTRCTL will have unlocked, but not de-ref'd,
4424 * filename_vp, so vrele it if it is defined.
4426 if (filename_vp != NULL)
4429 VFS_UNLOCK_GIANT(fnvfslocked);
4430 VFS_UNLOCK_GIANT(vfslocked);
4435 * Set a named extended attribute on a file or directory
4437 * Arguments: unlocked vnode "vp", attribute namespace "attrnamespace",
4438 * kernelspace string pointer "attrname", userspace buffer
4439 * pointer "data", buffer length "nbytes", thread "td".
4440 * Returns: 0 on success, an error number otherwise
4442 * References: vp must be a valid reference for the duration of the call
4445 extattr_set_vp(struct vnode *vp, int attrnamespace, const char *attrname,
4446 void *data, size_t nbytes, struct thread *td)
4454 VFS_ASSERT_GIANT(vp->v_mount);
4455 error = vn_start_write(vp, &mp, V_WAIT | PCATCH);
4458 VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
4459 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
4461 aiov.iov_base = data;
4462 aiov.iov_len = nbytes;
4463 auio.uio_iov = &aiov;
4464 auio.uio_iovcnt = 1;
4465 auio.uio_offset = 0;
4466 if (nbytes > INT_MAX) {
4470 auio.uio_resid = nbytes;
4471 auio.uio_rw = UIO_WRITE;
4472 auio.uio_segflg = UIO_USERSPACE;
4477 error = mac_check_vnode_setextattr(td->td_ucred, vp, attrnamespace,
4483 error = VOP_SETEXTATTR(vp, attrnamespace, attrname, &auio,
4485 cnt -= auio.uio_resid;
4486 td->td_retval[0] = cnt;
4489 VOP_UNLOCK(vp, 0, td);
4490 vn_finished_write(mp);
4495 extattr_set_fd(td, uap)
4497 struct extattr_set_fd_args /* {
4500 const char *attrname;
4506 char attrname[EXTATTR_MAXNAMELEN];
4507 int vfslocked, error;
4509 error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
4513 error = getvnode(td->td_proc->p_fd, uap->fd, &fp);
4517 vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount);
4518 error = extattr_set_vp(fp->f_vnode, uap->attrnamespace,
4519 attrname, uap->data, uap->nbytes, td);
4521 VFS_UNLOCK_GIANT(vfslocked);
4527 extattr_set_file(td, uap)
4529 struct extattr_set_file_args /* {
4532 const char *attrname;
4537 struct nameidata nd;
4538 char attrname[EXTATTR_MAXNAMELEN];
4539 int vfslocked, error;
4541 error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
4545 NDINIT(&nd, LOOKUP, MPSAFE | FOLLOW | AUDITVNODE1, UIO_USERSPACE,
4550 NDFREE(&nd, NDF_ONLY_PNBUF);
4552 vfslocked = NDHASGIANT(&nd);
4553 error = extattr_set_vp(nd.ni_vp, uap->attrnamespace, attrname,
4554 uap->data, uap->nbytes, td);
4557 VFS_UNLOCK_GIANT(vfslocked);
4562 extattr_set_link(td, uap)
4564 struct extattr_set_link_args /* {
4567 const char *attrname;
4572 struct nameidata nd;
4573 char attrname[EXTATTR_MAXNAMELEN];
4574 int vfslocked, error;
4576 error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
4580 NDINIT(&nd, LOOKUP, MPSAFE | NOFOLLOW | AUDITVNODE1, UIO_USERSPACE,
4585 NDFREE(&nd, NDF_ONLY_PNBUF);
4587 vfslocked = NDHASGIANT(&nd);
4588 error = extattr_set_vp(nd.ni_vp, uap->attrnamespace, attrname,
4589 uap->data, uap->nbytes, td);
4592 VFS_UNLOCK_GIANT(vfslocked);
4597 * Get a named extended attribute on a file or directory
4599 * Arguments: unlocked vnode "vp", attribute namespace "attrnamespace",
4600 * kernelspace string pointer "attrname", userspace buffer
4601 * pointer "data", buffer length "nbytes", thread "td".
4602 * Returns: 0 on success, an error number otherwise
4604 * References: vp must be a valid reference for the duration of the call
4607 extattr_get_vp(struct vnode *vp, int attrnamespace, const char *attrname,
4608 void *data, size_t nbytes, struct thread *td)
4610 struct uio auio, *auiop;
4613 size_t size, *sizep;
4616 VFS_ASSERT_GIANT(vp->v_mount);
4617 VOP_LEASE(vp, td, td->td_ucred, LEASE_READ);
4618 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
4621 * Slightly unusual semantics: if the user provides a NULL data
4622 * pointer, they don't want to receive the data, just the
4623 * maximum read length.
4629 aiov.iov_base = data;
4630 aiov.iov_len = nbytes;
4631 auio.uio_iov = &aiov;
4632 auio.uio_iovcnt = 1;
4633 auio.uio_offset = 0;
4634 if (nbytes > INT_MAX) {
4638 auio.uio_resid = nbytes;
4639 auio.uio_rw = UIO_READ;
4640 auio.uio_segflg = UIO_USERSPACE;
4648 error = mac_check_vnode_getextattr(td->td_ucred, vp, attrnamespace,
4654 error = VOP_GETEXTATTR(vp, attrnamespace, attrname, auiop, sizep,
4657 if (auiop != NULL) {
4658 cnt -= auio.uio_resid;
4659 td->td_retval[0] = cnt;
4661 td->td_retval[0] = size;
4664 VOP_UNLOCK(vp, 0, td);
4669 extattr_get_fd(td, uap)
4671 struct extattr_get_fd_args /* {
4674 const char *attrname;
4680 char attrname[EXTATTR_MAXNAMELEN];
4681 int vfslocked, error;
4683 error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
4687 error = getvnode(td->td_proc->p_fd, uap->fd, &fp);
4691 vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount);
4692 error = extattr_get_vp(fp->f_vnode, uap->attrnamespace,
4693 attrname, uap->data, uap->nbytes, td);
4696 VFS_UNLOCK_GIANT(vfslocked);
4701 extattr_get_file(td, uap)
4703 struct extattr_get_file_args /* {
4706 const char *attrname;
4711 struct nameidata nd;
4712 char attrname[EXTATTR_MAXNAMELEN];
4713 int vfslocked, error;
4715 error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
4719 NDINIT(&nd, LOOKUP, MPSAFE | FOLLOW | AUDITVNODE1, UIO_USERSPACE,
4724 NDFREE(&nd, NDF_ONLY_PNBUF);
4726 vfslocked = NDHASGIANT(&nd);
4727 error = extattr_get_vp(nd.ni_vp, uap->attrnamespace, attrname,
4728 uap->data, uap->nbytes, td);
4731 VFS_UNLOCK_GIANT(vfslocked);
4736 extattr_get_link(td, uap)
4738 struct extattr_get_link_args /* {
4741 const char *attrname;
4746 struct nameidata nd;
4747 char attrname[EXTATTR_MAXNAMELEN];
4748 int vfslocked, error;
4750 error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
4754 NDINIT(&nd, LOOKUP, MPSAFE | NOFOLLOW | AUDITVNODE1, UIO_USERSPACE,
4759 NDFREE(&nd, NDF_ONLY_PNBUF);
4761 vfslocked = NDHASGIANT(&nd);
4762 error = extattr_get_vp(nd.ni_vp, uap->attrnamespace, attrname,
4763 uap->data, uap->nbytes, td);
4766 VFS_UNLOCK_GIANT(vfslocked);
4771 * extattr_delete_vp(): Delete a named extended attribute on a file or
4774 * Arguments: unlocked vnode "vp", attribute namespace "attrnamespace",
4775 * kernelspace string pointer "attrname", proc "p"
4776 * Returns: 0 on success, an error number otherwise
4778 * References: vp must be a valid reference for the duration of the call
4781 extattr_delete_vp(struct vnode *vp, int attrnamespace, const char *attrname,
4787 VFS_ASSERT_GIANT(vp->v_mount);
4788 error = vn_start_write(vp, &mp, V_WAIT | PCATCH);
4791 VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
4792 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
4795 error = mac_check_vnode_deleteextattr(td->td_ucred, vp, attrnamespace,
4801 error = VOP_DELETEEXTATTR(vp, attrnamespace, attrname, td->td_ucred,
4803 if (error == EOPNOTSUPP)
4804 error = VOP_SETEXTATTR(vp, attrnamespace, attrname, NULL,
4809 VOP_UNLOCK(vp, 0, td);
4810 vn_finished_write(mp);
4815 extattr_delete_fd(td, uap)
4817 struct extattr_delete_fd_args /* {
4820 const char *attrname;
4824 char attrname[EXTATTR_MAXNAMELEN];
4825 int vfslocked, error;
4827 error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
4831 error = getvnode(td->td_proc->p_fd, uap->fd, &fp);
4835 vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount);
4836 error = extattr_delete_vp(fp->f_vnode, uap->attrnamespace,
4839 VFS_UNLOCK_GIANT(vfslocked);
4844 extattr_delete_file(td, uap)
4846 struct extattr_delete_file_args /* {
4849 const char *attrname;
4852 struct nameidata nd;
4853 char attrname[EXTATTR_MAXNAMELEN];
4854 int vfslocked, error;
4856 error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
4860 NDINIT(&nd, LOOKUP, MPSAFE | FOLLOW | AUDITVNODE1, UIO_USERSPACE,
4865 NDFREE(&nd, NDF_ONLY_PNBUF);
4867 vfslocked = NDHASGIANT(&nd);
4868 error = extattr_delete_vp(nd.ni_vp, uap->attrnamespace, attrname, td);
4870 VFS_UNLOCK_GIANT(vfslocked);
4875 extattr_delete_link(td, uap)
4877 struct extattr_delete_link_args /* {
4880 const char *attrname;
4883 struct nameidata nd;
4884 char attrname[EXTATTR_MAXNAMELEN];
4885 int vfslocked, error;
4887 error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
4891 NDINIT(&nd, LOOKUP, MPSAFE | NOFOLLOW | AUDITVNODE1, UIO_USERSPACE,
4896 NDFREE(&nd, NDF_ONLY_PNBUF);
4898 vfslocked = NDHASGIANT(&nd);
4899 error = extattr_delete_vp(nd.ni_vp, uap->attrnamespace, attrname, td);
4901 VFS_UNLOCK_GIANT(vfslocked);
4906 * Retrieve a list of extended attributes on a file or directory.
4908 * Arguments: unlocked vnode "vp", attribute namespace 'attrnamespace",
4909 * userspace buffer pointer "data", buffer length "nbytes",
4911 * Returns: 0 on success, an error number otherwise
4913 * References: vp must be a valid reference for the duration of the call
4916 extattr_list_vp(struct vnode *vp, int attrnamespace, void *data,
4917 size_t nbytes, struct thread *td)
4919 struct uio auio, *auiop;
4920 size_t size, *sizep;
4925 VFS_ASSERT_GIANT(vp->v_mount);
4926 VOP_LEASE(vp, td, td->td_ucred, LEASE_READ);
4927 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
4933 aiov.iov_base = data;
4934 aiov.iov_len = nbytes;
4935 auio.uio_iov = &aiov;
4936 auio.uio_iovcnt = 1;
4937 auio.uio_offset = 0;
4938 if (nbytes > INT_MAX) {
4942 auio.uio_resid = nbytes;
4943 auio.uio_rw = UIO_READ;
4944 auio.uio_segflg = UIO_USERSPACE;
4952 error = mac_check_vnode_listextattr(td->td_ucred, vp, attrnamespace);
4957 error = VOP_LISTEXTATTR(vp, attrnamespace, auiop, sizep,
4960 if (auiop != NULL) {
4961 cnt -= auio.uio_resid;
4962 td->td_retval[0] = cnt;
4964 td->td_retval[0] = size;
4967 VOP_UNLOCK(vp, 0, td);
4973 extattr_list_fd(td, uap)
4975 struct extattr_list_fd_args /* {
4983 int vfslocked, error;
4985 error = getvnode(td->td_proc->p_fd, uap->fd, &fp);
4989 vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount);
4990 error = extattr_list_vp(fp->f_vnode, uap->attrnamespace, uap->data,
4994 VFS_UNLOCK_GIANT(vfslocked);
4999 extattr_list_file(td, uap)
5001 struct extattr_list_file_args /* {
5008 struct nameidata nd;
5009 int vfslocked, error;
5011 NDINIT(&nd, LOOKUP, MPSAFE | FOLLOW | AUDITVNODE1, UIO_USERSPACE,
5016 NDFREE(&nd, NDF_ONLY_PNBUF);
5018 vfslocked = NDHASGIANT(&nd);
5019 error = extattr_list_vp(nd.ni_vp, uap->attrnamespace, uap->data,
5023 VFS_UNLOCK_GIANT(vfslocked);
5028 extattr_list_link(td, uap)
5030 struct extattr_list_link_args /* {
5037 struct nameidata nd;
5038 int vfslocked, error;
5040 NDINIT(&nd, LOOKUP, MPSAFE | NOFOLLOW | AUDITVNODE1, UIO_USERSPACE,
5045 NDFREE(&nd, NDF_ONLY_PNBUF);
5047 vfslocked = NDHASGIANT(&nd);
5048 error = extattr_list_vp(nd.ni_vp, uap->attrnamespace, uap->data,
5052 VFS_UNLOCK_GIANT(vfslocked);