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"
41 #include "opt_ktrace.h"
44 #include <sys/param.h>
45 #include <sys/systm.h>
48 #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/filio.h>
59 #include <sys/limits.h>
60 #include <sys/linker.h>
63 #include <sys/unistd.h>
64 #include <sys/vnode.h>
67 #include <sys/dirent.h>
69 #include <sys/syscallsubr.h>
70 #include <sys/sysctl.h>
72 #include <sys/ktrace.h>
75 #include <machine/stdarg.h>
77 #include <security/audit/audit.h>
78 #include <security/mac/mac_framework.h>
81 #include <vm/vm_object.h>
82 #include <vm/vm_page.h>
85 static int chroot_refuse_vdir_fds(struct filedesc
*fdp
);
86 static int getutimes(const struct timeval
*, enum uio_seg
, struct timespec
*);
87 static int setfown(struct thread
*td
, struct vnode
*, uid_t
, gid_t
);
88 static int setfmode(struct thread
*td
, struct vnode
*, int);
89 static int setfflags(struct thread
*td
, struct vnode
*, int);
90 static int setutimes(struct thread
*td
, struct vnode
*,
91 const struct timespec
*, int, int);
92 static int vn_access(struct vnode
*vp
, int user_flags
, struct ucred
*cred
,
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 static int syncprt
= 0;
105 SYSCTL_INT(_debug
, OID_AUTO
, syncprt
, CTLFLAG_RW
, &syncprt
, 0, "");
109 * Sync each mounted filesystem.
111 #ifndef _SYS_SYSPROTO_H_
120 struct sync_args
*uap
;
122 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
)) {
128 nmp
= TAILQ_NEXT(mp
, mnt_list
);
131 vfslocked
= VFS_LOCK_GIANT(mp
);
132 if ((mp
->mnt_flag
& MNT_RDONLY
) == 0 &&
133 vn_start_write(NULL
, &mp
, V_NOWAIT
) == 0) {
136 mp
->mnt_kern_flag
&= ~MNTK_ASYNC
;
138 vfs_msync(mp
, MNT_NOWAIT
);
139 VFS_SYNC(mp
, MNT_NOWAIT
, td
);
142 if ((mp
->mnt_flag
& MNT_ASYNC
) != 0 &&
143 mp
->mnt_noasync
== 0)
144 mp
->mnt_kern_flag
|= MNTK_ASYNC
;
146 vn_finished_write(mp
);
148 VFS_UNLOCK_GIANT(vfslocked
);
149 mtx_lock(&mountlist_mtx
);
150 nmp
= TAILQ_NEXT(mp
, mnt_list
);
153 mtx_unlock(&mountlist_mtx
);
157 /* XXX PRISON: could be per prison flag */
158 static int prison_quotas
;
160 SYSCTL_INT(_kern_prison
, OID_AUTO
, quotas
, CTLFLAG_RW
, &prison_quotas
, 0, "");
164 * Change filesystem quotas.
166 #ifndef _SYS_SYSPROTO_H_
167 struct quotactl_args
{
177 register struct quotactl_args
/* {
189 AUDIT_ARG(cmd
, uap
->cmd
);
190 AUDIT_ARG(uid
, uap
->uid
);
191 if (jailed(td
->td_ucred
) && !prison_quotas
)
193 NDINIT(&nd
, LOOKUP
, FOLLOW
| MPSAFE
| AUDITVNODE1
,
194 UIO_USERSPACE
, uap
->path
, td
);
195 if ((error
= namei(&nd
)) != 0)
197 vfslocked
= NDHASGIANT(&nd
);
198 NDFREE(&nd
, NDF_ONLY_PNBUF
);
199 mp
= nd
.ni_vp
->v_mount
;
200 if ((error
= vfs_busy(mp
, 0, NULL
))) {
202 VFS_UNLOCK_GIANT(vfslocked
);
206 error
= VFS_QUOTACTL(mp
, uap
->cmd
, uap
->uid
, uap
->arg
, td
);
208 VFS_UNLOCK_GIANT(vfslocked
);
213 * Used by statfs conversion routines to scale the block size up if
214 * necessary so that all of the block counts are <= 'max_size'. Note
215 * that 'max_size' should be a bitmask, i.e. 2^n - 1 for some non-zero
219 statfs_scale_blocks(struct statfs
*sf
, long max_size
)
224 KASSERT(powerof2(max_size
+ 1), ("%s: invalid max_size", __func__
));
227 * Attempt to scale the block counts to give a more accurate
228 * overview to userland of the ratio of free space to used
229 * space. To do this, find the largest block count and compute
230 * a divisor that lets it fit into a signed integer <= max_size.
232 if (sf
->f_bavail
< 0)
233 count
= -sf
->f_bavail
;
235 count
= sf
->f_bavail
;
236 count
= MAX(sf
->f_blocks
, MAX(sf
->f_bfree
, count
));
237 if (count
<= max_size
)
240 count
>>= flsl(max_size
);
247 sf
->f_bsize
<<= shift
;
248 sf
->f_blocks
>>= shift
;
249 sf
->f_bfree
>>= shift
;
250 sf
->f_bavail
>>= shift
;
254 * Get filesystem statistics.
256 #ifndef _SYS_SYSPROTO_H_
265 register struct statfs_args
/* {
273 error
= kern_statfs(td
, uap
->path
, UIO_USERSPACE
, &sf
);
275 error
= copyout(&sf
, uap
->buf
, sizeof(sf
));
280 kern_statfs(struct thread
*td
, char *path
, enum uio_seg pathseg
,
284 struct statfs
*sp
, sb
;
289 NDINIT(&nd
, LOOKUP
, FOLLOW
| LOCKLEAF
| MPSAFE
| AUDITVNODE1
,
294 vfslocked
= NDHASGIANT(&nd
);
295 mp
= nd
.ni_vp
->v_mount
;
297 NDFREE(&nd
, NDF_ONLY_PNBUF
);
300 error
= mac_mount_check_stat(td
->td_ucred
, mp
);
305 * Set these in case the underlying filesystem fails to do so.
308 sp
->f_version
= STATFS_VERSION
;
309 sp
->f_namemax
= NAME_MAX
;
310 sp
->f_flags
= mp
->mnt_flag
& MNT_VISFLAGMASK
;
311 error
= VFS_STATFS(mp
, sp
, td
);
314 if (priv_check(td
, PRIV_VFS_GENERATION
)) {
315 bcopy(sp
, &sb
, sizeof(sb
));
316 sb
.f_fsid
.val
[0] = sb
.f_fsid
.val
[1] = 0;
317 prison_enforce_statfs(td
->td_ucred
, mp
, &sb
);
323 VFS_UNLOCK_GIANT(vfslocked
);
324 if (mtx_owned(&Giant
))
325 printf("statfs(%d): %s: %d\n", vfslocked
, path
, error
);
330 * Get filesystem statistics.
332 #ifndef _SYS_SYSPROTO_H_
333 struct fstatfs_args
{
341 register struct fstatfs_args
/* {
349 error
= kern_fstatfs(td
, uap
->fd
, &sf
);
351 error
= copyout(&sf
, uap
->buf
, sizeof(sf
));
356 kern_fstatfs(struct thread
*td
, int fd
, struct statfs
*buf
)
360 struct statfs
*sp
, sb
;
366 error
= getvnode(td
->td_proc
->p_fd
, fd
, &fp
);
370 vfslocked
= VFS_LOCK_GIANT(vp
->v_mount
);
371 vn_lock(vp
, LK_EXCLUSIVE
| LK_RETRY
);
373 AUDIT_ARG(vnode
, vp
, ARG_VNODE1
);
380 if (vp
->v_iflag
& VI_DOOMED
) {
385 error
= mac_mount_check_stat(td
->td_ucred
, mp
);
390 * Set these in case the underlying filesystem fails to do so.
393 sp
->f_version
= STATFS_VERSION
;
394 sp
->f_namemax
= NAME_MAX
;
395 sp
->f_flags
= mp
->mnt_flag
& MNT_VISFLAGMASK
;
396 error
= VFS_STATFS(mp
, sp
, td
);
399 if (priv_check(td
, PRIV_VFS_GENERATION
)) {
400 bcopy(sp
, &sb
, sizeof(sb
));
401 sb
.f_fsid
.val
[0] = sb
.f_fsid
.val
[1] = 0;
402 prison_enforce_statfs(td
->td_ucred
, mp
, &sb
);
409 VFS_UNLOCK_GIANT(vfslocked
);
414 * Get statistics on all filesystems.
416 #ifndef _SYS_SYSPROTO_H_
417 struct getfsstat_args
{
426 register struct getfsstat_args
/* {
433 return (kern_getfsstat(td
, &uap
->buf
, uap
->bufsize
, UIO_USERSPACE
,
438 * If (bufsize > 0 && bufseg == UIO_SYSSPACE)
439 * The caller is responsible for freeing memory which will be allocated
443 kern_getfsstat(struct thread
*td
, struct statfs
**buf
, size_t bufsize
,
444 enum uio_seg bufseg
, int flags
)
446 struct mount
*mp
, *nmp
;
447 struct statfs
*sfsp
, *sp
, sb
;
448 size_t count
, maxcount
;
452 maxcount
= bufsize
/ sizeof(struct statfs
);
455 else if (bufseg
== UIO_USERSPACE
)
457 else /* if (bufseg == UIO_SYSSPACE) */ {
459 mtx_lock(&mountlist_mtx
);
460 TAILQ_FOREACH(mp
, &mountlist
, mnt_list
) {
463 mtx_unlock(&mountlist_mtx
);
464 if (maxcount
> count
)
466 sfsp
= *buf
= malloc(maxcount
* sizeof(struct statfs
), M_TEMP
,
470 mtx_lock(&mountlist_mtx
);
471 for (mp
= TAILQ_FIRST(&mountlist
); mp
!= NULL
; mp
= nmp
) {
472 if (prison_canseemount(td
->td_ucred
, mp
) != 0) {
473 nmp
= TAILQ_NEXT(mp
, mnt_list
);
477 if (mac_mount_check_stat(td
->td_ucred
, mp
) != 0) {
478 nmp
= TAILQ_NEXT(mp
, mnt_list
);
482 if (vfs_busy(mp
, LK_NOWAIT
, &mountlist_mtx
)) {
483 nmp
= TAILQ_NEXT(mp
, mnt_list
);
486 vfslocked
= VFS_LOCK_GIANT(mp
);
487 if (sfsp
&& count
< maxcount
) {
490 * Set these in case the underlying filesystem
493 sp
->f_version
= STATFS_VERSION
;
494 sp
->f_namemax
= NAME_MAX
;
495 sp
->f_flags
= mp
->mnt_flag
& MNT_VISFLAGMASK
;
497 * If MNT_NOWAIT or MNT_LAZY is specified, do not
498 * refresh the fsstat cache. MNT_NOWAIT or MNT_LAZY
499 * overrides MNT_WAIT.
501 if (((flags
& (MNT_LAZY
|MNT_NOWAIT
)) == 0 ||
502 (flags
& MNT_WAIT
)) &&
503 (error
= VFS_STATFS(mp
, sp
, td
))) {
504 VFS_UNLOCK_GIANT(vfslocked
);
505 mtx_lock(&mountlist_mtx
);
506 nmp
= TAILQ_NEXT(mp
, mnt_list
);
510 if (priv_check(td
, PRIV_VFS_GENERATION
)) {
511 bcopy(sp
, &sb
, sizeof(sb
));
512 sb
.f_fsid
.val
[0] = sb
.f_fsid
.val
[1] = 0;
513 prison_enforce_statfs(td
->td_ucred
, mp
, &sb
);
516 if (bufseg
== UIO_SYSSPACE
)
517 bcopy(sp
, sfsp
, sizeof(*sp
));
518 else /* if (bufseg == UIO_USERSPACE) */ {
519 error
= copyout(sp
, sfsp
, sizeof(*sp
));
522 VFS_UNLOCK_GIANT(vfslocked
);
528 VFS_UNLOCK_GIANT(vfslocked
);
530 mtx_lock(&mountlist_mtx
);
531 nmp
= TAILQ_NEXT(mp
, mnt_list
);
534 mtx_unlock(&mountlist_mtx
);
535 if (sfsp
&& count
> maxcount
)
536 td
->td_retval
[0] = maxcount
;
538 td
->td_retval
[0] = count
;
542 #ifdef COMPAT_FREEBSD4
544 * Get old format filesystem statistics.
546 static void cvtstatfs(struct statfs
*, struct ostatfs
*);
548 #ifndef _SYS_SYSPROTO_H_
549 struct freebsd4_statfs_args
{
555 freebsd4_statfs(td
, uap
)
557 struct freebsd4_statfs_args
/* {
566 error
= kern_statfs(td
, uap
->path
, UIO_USERSPACE
, &sf
);
569 cvtstatfs(&sf
, &osb
);
570 return (copyout(&osb
, uap
->buf
, sizeof(osb
)));
574 * Get filesystem statistics.
576 #ifndef _SYS_SYSPROTO_H_
577 struct freebsd4_fstatfs_args
{
583 freebsd4_fstatfs(td
, uap
)
585 struct freebsd4_fstatfs_args
/* {
594 error
= kern_fstatfs(td
, uap
->fd
, &sf
);
597 cvtstatfs(&sf
, &osb
);
598 return (copyout(&osb
, uap
->buf
, sizeof(osb
)));
602 * Get statistics on all filesystems.
604 #ifndef _SYS_SYSPROTO_H_
605 struct freebsd4_getfsstat_args
{
612 freebsd4_getfsstat(td
, uap
)
614 register struct freebsd4_getfsstat_args
/* {
620 struct statfs
*buf
, *sp
;
625 count
= uap
->bufsize
/ sizeof(struct ostatfs
);
626 size
= count
* sizeof(struct statfs
);
627 error
= kern_getfsstat(td
, &buf
, size
, UIO_SYSSPACE
, uap
->flags
);
629 count
= td
->td_retval
[0];
631 while (count
> 0 && error
== 0) {
633 error
= copyout(&osb
, uap
->buf
, sizeof(osb
));
644 * Implement fstatfs() for (NFS) file handles.
646 #ifndef _SYS_SYSPROTO_H_
647 struct freebsd4_fhstatfs_args
{
648 struct fhandle
*u_fhp
;
653 freebsd4_fhstatfs(td
, uap
)
655 struct freebsd4_fhstatfs_args
/* {
656 struct fhandle *u_fhp;
665 error
= copyin(uap
->u_fhp
, &fh
, sizeof(fhandle_t
));
668 error
= kern_fhstatfs(td
, fh
, &sf
);
671 cvtstatfs(&sf
, &osb
);
672 return (copyout(&osb
, uap
->buf
, sizeof(osb
)));
676 * Convert a new format statfs structure to an old format statfs structure.
684 statfs_scale_blocks(nsp
, LONG_MAX
);
685 bzero(osp
, sizeof(*osp
));
686 osp
->f_bsize
= nsp
->f_bsize
;
687 osp
->f_iosize
= MIN(nsp
->f_iosize
, LONG_MAX
);
688 osp
->f_blocks
= nsp
->f_blocks
;
689 osp
->f_bfree
= nsp
->f_bfree
;
690 osp
->f_bavail
= nsp
->f_bavail
;
691 osp
->f_files
= MIN(nsp
->f_files
, LONG_MAX
);
692 osp
->f_ffree
= MIN(nsp
->f_ffree
, LONG_MAX
);
693 osp
->f_owner
= nsp
->f_owner
;
694 osp
->f_type
= nsp
->f_type
;
695 osp
->f_flags
= nsp
->f_flags
;
696 osp
->f_syncwrites
= MIN(nsp
->f_syncwrites
, LONG_MAX
);
697 osp
->f_asyncwrites
= MIN(nsp
->f_asyncwrites
, LONG_MAX
);
698 osp
->f_syncreads
= MIN(nsp
->f_syncreads
, LONG_MAX
);
699 osp
->f_asyncreads
= MIN(nsp
->f_asyncreads
, LONG_MAX
);
700 strlcpy(osp
->f_fstypename
, nsp
->f_fstypename
,
701 MIN(MFSNAMELEN
, OMFSNAMELEN
));
702 strlcpy(osp
->f_mntonname
, nsp
->f_mntonname
,
703 MIN(MNAMELEN
, OMNAMELEN
));
704 strlcpy(osp
->f_mntfromname
, nsp
->f_mntfromname
,
705 MIN(MNAMELEN
, OMNAMELEN
));
706 osp
->f_fsid
= nsp
->f_fsid
;
708 #endif /* COMPAT_FREEBSD4 */
711 * Change current working directory to a given file descriptor.
713 #ifndef _SYS_SYSPROTO_H_
721 struct fchdir_args
/* {
725 register struct filedesc
*fdp
= td
->td_proc
->p_fd
;
726 struct vnode
*vp
, *tdp
, *vpold
;
732 AUDIT_ARG(fd
, uap
->fd
);
733 if ((error
= getvnode(fdp
, uap
->fd
, &fp
)) != 0)
738 vfslocked
= VFS_LOCK_GIANT(vp
->v_mount
);
739 vn_lock(vp
, LK_EXCLUSIVE
| LK_RETRY
);
740 AUDIT_ARG(vnode
, vp
, ARG_VNODE1
);
741 error
= change_dir(vp
, td
);
742 while (!error
&& (mp
= vp
->v_mountedhere
) != NULL
) {
744 if (vfs_busy(mp
, 0, 0))
746 tvfslocked
= VFS_LOCK_GIANT(mp
);
747 error
= VFS_ROOT(mp
, LK_EXCLUSIVE
, &tdp
, td
);
750 VFS_UNLOCK_GIANT(tvfslocked
);
754 VFS_UNLOCK_GIANT(vfslocked
);
756 vfslocked
= tvfslocked
;
760 VFS_UNLOCK_GIANT(vfslocked
);
764 VFS_UNLOCK_GIANT(vfslocked
);
766 vpold
= fdp
->fd_cdir
;
768 FILEDESC_XUNLOCK(fdp
);
769 vfslocked
= VFS_LOCK_GIANT(vpold
->v_mount
);
771 VFS_UNLOCK_GIANT(vfslocked
);
776 * Change current working directory (``.'').
778 #ifndef _SYS_SYSPROTO_H_
786 struct chdir_args
/* {
791 return (kern_chdir(td
, uap
->path
, UIO_USERSPACE
));
795 kern_chdir(struct thread
*td
, char *path
, enum uio_seg pathseg
)
797 register struct filedesc
*fdp
= td
->td_proc
->p_fd
;
803 NDINIT(&nd
, LOOKUP
, FOLLOW
| LOCKLEAF
| AUDITVNODE1
| MPSAFE
,
805 if ((error
= namei(&nd
)) != 0)
807 vfslocked
= NDHASGIANT(&nd
);
808 if ((error
= change_dir(nd
.ni_vp
, td
)) != 0) {
810 VFS_UNLOCK_GIANT(vfslocked
);
811 NDFREE(&nd
, NDF_ONLY_PNBUF
);
814 VOP_UNLOCK(nd
.ni_vp
, 0);
815 VFS_UNLOCK_GIANT(vfslocked
);
816 NDFREE(&nd
, NDF_ONLY_PNBUF
);
819 fdp
->fd_cdir
= nd
.ni_vp
;
820 FILEDESC_XUNLOCK(fdp
);
821 vfslocked
= VFS_LOCK_GIANT(vp
->v_mount
);
823 VFS_UNLOCK_GIANT(vfslocked
);
828 * Helper function for raised chroot(2) security function: Refuse if
829 * any filedescriptors are open directories.
832 chroot_refuse_vdir_fds(fdp
)
833 struct filedesc
*fdp
;
839 FILEDESC_LOCK_ASSERT(fdp
);
841 for (fd
= 0; fd
< fdp
->fd_nfiles
; fd
++) {
842 fp
= fget_locked(fdp
, fd
);
845 if (fp
->f_type
== DTYPE_VNODE
) {
847 if (vp
->v_type
== VDIR
)
855 * This sysctl determines if we will allow a process to chroot(2) if it
856 * has a directory open:
857 * 0: disallowed for all processes.
858 * 1: allowed for processes that were not already chroot(2)'ed.
859 * 2: allowed for all processes.
862 static int chroot_allow_open_directories
= 1;
864 SYSCTL_INT(_kern
, OID_AUTO
, chroot_allow_open_directories
, CTLFLAG_RW
,
865 &chroot_allow_open_directories
, 0, "");
868 * Change notion of root (``/'') directory.
870 #ifndef _SYS_SYSPROTO_H_
878 struct chroot_args
/* {
886 error
= priv_check(td
, PRIV_VFS_CHROOT
);
889 NDINIT(&nd
, LOOKUP
, FOLLOW
| LOCKLEAF
| MPSAFE
| AUDITVNODE1
,
890 UIO_USERSPACE
, uap
->path
, td
);
894 vfslocked
= NDHASGIANT(&nd
);
895 if ((error
= change_dir(nd
.ni_vp
, td
)) != 0)
898 if ((error
= mac_vnode_check_chroot(td
->td_ucred
, nd
.ni_vp
)))
901 VOP_UNLOCK(nd
.ni_vp
, 0);
902 error
= change_root(nd
.ni_vp
, td
);
904 VFS_UNLOCK_GIANT(vfslocked
);
905 NDFREE(&nd
, NDF_ONLY_PNBUF
);
909 VFS_UNLOCK_GIANT(vfslocked
);
911 NDFREE(&nd
, NDF_ONLY_PNBUF
);
916 * Common routine for chroot and chdir. Callers must provide a locked vnode
926 ASSERT_VOP_LOCKED(vp
, "change_dir(): vp not locked");
927 if (vp
->v_type
!= VDIR
)
930 error
= mac_vnode_check_chdir(td
->td_ucred
, vp
);
934 error
= VOP_ACCESS(vp
, VEXEC
, td
->td_ucred
, td
);
939 * Common routine for kern_chroot() and jail_attach(). The caller is
940 * responsible for invoking priv_check() and mac_vnode_check_chroot() to
941 * authorize this operation.
948 struct filedesc
*fdp
;
953 VFS_ASSERT_GIANT(vp
->v_mount
);
954 fdp
= td
->td_proc
->p_fd
;
956 if (chroot_allow_open_directories
== 0 ||
957 (chroot_allow_open_directories
== 1 && fdp
->fd_rdir
!= rootvnode
)) {
958 error
= chroot_refuse_vdir_fds(fdp
);
960 FILEDESC_XUNLOCK(fdp
);
964 oldvp
= fdp
->fd_rdir
;
971 FILEDESC_XUNLOCK(fdp
);
972 vfslocked
= VFS_LOCK_GIANT(oldvp
->v_mount
);
974 VFS_UNLOCK_GIANT(vfslocked
);
979 * Check permissions, allocate an open file structure, and call the device
980 * open routine if any.
982 #ifndef _SYS_SYSPROTO_H_
992 register struct open_args
/* {
999 return (kern_open(td
, uap
->path
, UIO_USERSPACE
, uap
->flags
, uap
->mode
));
1002 #ifndef _SYS_SYSPROTO_H_
1003 struct openat_args
{
1011 openat(struct thread
*td
, struct openat_args
*uap
)
1014 return (kern_openat(td
, uap
->fd
, uap
->path
, UIO_USERSPACE
, uap
->flag
,
1019 kern_open(struct thread
*td
, char *path
, enum uio_seg pathseg
, int flags
,
1023 return (kern_openat(td
, AT_FDCWD
, path
, pathseg
, flags
, mode
));
1027 kern_openat(struct thread
*td
, int fd
, char *path
, enum uio_seg pathseg
,
1028 int flags
, int mode
)
1030 struct proc
*p
= td
->td_proc
;
1031 struct filedesc
*fdp
= p
->p_fd
;
1038 int type
, indx
, error
;
1040 struct nameidata nd
;
1043 AUDIT_ARG(fflags
, flags
);
1044 AUDIT_ARG(mode
, mode
);
1045 /* XXX: audit dirfd */
1047 * Only one of the O_EXEC, O_RDONLY, O_WRONLY and O_RDWR may
1050 if (flags
& O_EXEC
) {
1051 if (flags
& O_ACCMODE
)
1053 } else if ((flags
& O_ACCMODE
) == O_ACCMODE
)
1056 flags
= FFLAGS(flags
);
1058 error
= falloc(td
, &nfp
, &indx
);
1061 /* An extra reference on `nfp' has been held for us by falloc(). */
1063 /* Set the flags early so the finit in devfs can pick them up. */
1064 fp
->f_flag
= flags
& FMASK
;
1065 cmode
= ((mode
&~ fdp
->fd_cmask
) & ALLPERMS
) &~ S_ISTXT
;
1066 NDINIT_AT(&nd
, LOOKUP
, FOLLOW
| AUDITVNODE1
| MPSAFE
, pathseg
, path
, fd
,
1068 td
->td_dupfd
= -1; /* XXX check for fdopen */
1069 error
= vn_open(&nd
, &flags
, cmode
, fp
);
1072 * If the vn_open replaced the method vector, something
1073 * wonderous happened deep below and we just pass it up
1074 * pretending we know what we do.
1076 if (error
== ENXIO
&& fp
->f_ops
!= &badfileops
) {
1078 td
->td_retval
[0] = indx
;
1083 * handle special fdopen() case. bleh. dupfdopen() is
1084 * responsible for dropping the old contents of ofiles[indx]
1087 if ((error
== ENODEV
|| error
== ENXIO
) &&
1088 td
->td_dupfd
>= 0 && /* XXX from fdopen */
1090 dupfdopen(td
, fdp
, indx
, td
->td_dupfd
, flags
, error
)) == 0) {
1091 td
->td_retval
[0] = indx
;
1096 * Clean up the descriptor, but only if another thread hadn't
1097 * replaced or closed it.
1099 fdclose(fdp
, fp
, indx
, td
);
1102 if (error
== ERESTART
)
1107 vfslocked
= NDHASGIANT(&nd
);
1108 NDFREE(&nd
, NDF_ONLY_PNBUF
);
1111 fp
->f_vnode
= vp
; /* XXX Does devfs need this? */
1113 * If the file wasn't claimed by devfs bind it to the normal
1114 * vnode operations here.
1116 if (fp
->f_ops
== &badfileops
) {
1117 KASSERT(vp
->v_type
!= VFIFO
, ("Unexpected fifo."));
1119 finit(fp
, flags
& FMASK
, DTYPE_VNODE
, vp
, &vnops
);
1123 if (flags
& (O_EXLOCK
| O_SHLOCK
)) {
1124 lf
.l_whence
= SEEK_SET
;
1127 if (flags
& O_EXLOCK
)
1128 lf
.l_type
= F_WRLCK
;
1130 lf
.l_type
= F_RDLCK
;
1132 if ((flags
& FNONBLOCK
) == 0)
1134 if ((error
= VOP_ADVLOCK(vp
, (caddr_t
)fp
, F_SETLK
, &lf
,
1137 atomic_set_int(&fp
->f_flag
, FHASLOCK
);
1139 if (flags
& O_TRUNC
) {
1140 if ((error
= vn_start_write(vp
, &mp
, V_WAIT
| PCATCH
)) != 0)
1142 VOP_LEASE(vp
, td
, td
->td_ucred
, LEASE_WRITE
);
1145 vn_lock(vp
, LK_EXCLUSIVE
| LK_RETRY
);
1147 error
= mac_vnode_check_write(td
->td_ucred
, fp
->f_cred
, vp
);
1150 error
= VOP_SETATTR(vp
, &vat
, td
->td_ucred
);
1152 vn_finished_write(mp
);
1156 VFS_UNLOCK_GIANT(vfslocked
);
1158 * Release our private reference, leaving the one associated with
1159 * the descriptor table intact.
1162 td
->td_retval
[0] = indx
;
1165 VFS_UNLOCK_GIANT(vfslocked
);
1166 fdclose(fdp
, fp
, indx
, td
);
1175 #ifndef _SYS_SYSPROTO_H_
1176 struct ocreat_args
{
1184 register struct ocreat_args
/* {
1190 return (kern_open(td
, uap
->path
, UIO_USERSPACE
,
1191 O_WRONLY
| O_CREAT
| O_TRUNC
, uap
->mode
));
1193 #endif /* COMPAT_43 */
1196 * Create a special file.
1198 #ifndef _SYS_SYSPROTO_H_
1208 register struct mknod_args
/* {
1215 return (kern_mknod(td
, uap
->path
, UIO_USERSPACE
, uap
->mode
, uap
->dev
));
1218 #ifndef _SYS_SYSPROTO_H_
1219 struct mknodat_args
{
1227 mknodat(struct thread
*td
, struct mknodat_args
*uap
)
1230 return (kern_mknodat(td
, uap
->fd
, uap
->path
, UIO_USERSPACE
, uap
->mode
,
1235 kern_mknod(struct thread
*td
, char *path
, enum uio_seg pathseg
, int mode
,
1239 return (kern_mknodat(td
, AT_FDCWD
, path
, pathseg
, mode
, dev
));
1243 kern_mknodat(struct thread
*td
, int fd
, char *path
, enum uio_seg pathseg
,
1251 struct nameidata nd
;
1254 AUDIT_ARG(mode
, mode
);
1255 AUDIT_ARG(dev
, dev
);
1256 switch (mode
& S_IFMT
) {
1259 error
= priv_check(td
, PRIV_VFS_MKNOD_DEV
);
1262 error
= priv_check(td
, PRIV_VFS_MKNOD_BAD
);
1265 error
= priv_check(td
, PRIV_VFS_MKNOD_WHT
);
1269 return (kern_mkfifoat(td
, fd
, path
, pathseg
, mode
));
1279 NDINIT_AT(&nd
, CREATE
, LOCKPARENT
| SAVENAME
| MPSAFE
| AUDITVNODE1
,
1280 pathseg
, path
, fd
, td
);
1281 if ((error
= namei(&nd
)) != 0)
1283 vfslocked
= NDHASGIANT(&nd
);
1286 NDFREE(&nd
, NDF_ONLY_PNBUF
);
1287 if (vp
== nd
.ni_dvp
)
1292 VFS_UNLOCK_GIANT(vfslocked
);
1296 FILEDESC_SLOCK(td
->td_proc
->p_fd
);
1297 vattr
.va_mode
= (mode
& ALLPERMS
) &
1298 ~td
->td_proc
->p_fd
->fd_cmask
;
1299 FILEDESC_SUNLOCK(td
->td_proc
->p_fd
);
1300 vattr
.va_rdev
= dev
;
1303 switch (mode
& S_IFMT
) {
1304 case S_IFMT
: /* used by badsect to flag bad sectors */
1305 vattr
.va_type
= VBAD
;
1308 vattr
.va_type
= VCHR
;
1311 vattr
.va_type
= VBLK
;
1317 panic("kern_mknod: invalid mode");
1320 if (vn_start_write(nd
.ni_dvp
, &mp
, V_NOWAIT
) != 0) {
1321 NDFREE(&nd
, NDF_ONLY_PNBUF
);
1323 VFS_UNLOCK_GIANT(vfslocked
);
1324 if ((error
= vn_start_write(NULL
, &mp
, V_XSLEEP
| PCATCH
)) != 0)
1329 if (error
== 0 && !whiteout
)
1330 error
= mac_vnode_check_create(td
->td_ucred
, nd
.ni_dvp
,
1331 &nd
.ni_cnd
, &vattr
);
1334 VOP_LEASE(nd
.ni_dvp
, td
, td
->td_ucred
, LEASE_WRITE
);
1336 error
= VOP_WHITEOUT(nd
.ni_dvp
, &nd
.ni_cnd
, CREATE
);
1338 error
= VOP_MKNOD(nd
.ni_dvp
, &nd
.ni_vp
,
1339 &nd
.ni_cnd
, &vattr
);
1344 NDFREE(&nd
, NDF_ONLY_PNBUF
);
1346 vn_finished_write(mp
);
1347 VFS_UNLOCK_GIANT(vfslocked
);
1352 * Create a named pipe.
1354 #ifndef _SYS_SYSPROTO_H_
1355 struct mkfifo_args
{
1363 register struct mkfifo_args
/* {
1369 return (kern_mkfifo(td
, uap
->path
, UIO_USERSPACE
, uap
->mode
));
1372 #ifndef _SYS_SYSPROTO_H_
1373 struct mkfifoat_args
{
1380 mkfifoat(struct thread
*td
, struct mkfifoat_args
*uap
)
1383 return (kern_mkfifoat(td
, uap
->fd
, uap
->path
, UIO_USERSPACE
,
1388 kern_mkfifo(struct thread
*td
, char *path
, enum uio_seg pathseg
, int mode
)
1391 return (kern_mkfifoat(td
, AT_FDCWD
, path
, pathseg
, mode
));
1395 kern_mkfifoat(struct thread
*td
, int fd
, char *path
, enum uio_seg pathseg
,
1401 struct nameidata nd
;
1404 AUDIT_ARG(mode
, mode
);
1407 NDINIT_AT(&nd
, CREATE
, LOCKPARENT
| SAVENAME
| MPSAFE
| AUDITVNODE1
,
1408 pathseg
, path
, fd
, td
);
1409 if ((error
= namei(&nd
)) != 0)
1411 vfslocked
= NDHASGIANT(&nd
);
1412 if (nd
.ni_vp
!= NULL
) {
1413 NDFREE(&nd
, NDF_ONLY_PNBUF
);
1414 if (nd
.ni_vp
== nd
.ni_dvp
)
1419 VFS_UNLOCK_GIANT(vfslocked
);
1422 if (vn_start_write(nd
.ni_dvp
, &mp
, V_NOWAIT
) != 0) {
1423 NDFREE(&nd
, NDF_ONLY_PNBUF
);
1425 VFS_UNLOCK_GIANT(vfslocked
);
1426 if ((error
= vn_start_write(NULL
, &mp
, V_XSLEEP
| PCATCH
)) != 0)
1431 vattr
.va_type
= VFIFO
;
1432 FILEDESC_SLOCK(td
->td_proc
->p_fd
);
1433 vattr
.va_mode
= (mode
& ALLPERMS
) & ~td
->td_proc
->p_fd
->fd_cmask
;
1434 FILEDESC_SUNLOCK(td
->td_proc
->p_fd
);
1436 error
= mac_vnode_check_create(td
->td_ucred
, nd
.ni_dvp
, &nd
.ni_cnd
,
1441 VOP_LEASE(nd
.ni_dvp
, td
, td
->td_ucred
, LEASE_WRITE
);
1442 error
= VOP_MKNOD(nd
.ni_dvp
, &nd
.ni_vp
, &nd
.ni_cnd
, &vattr
);
1449 vn_finished_write(mp
);
1450 VFS_UNLOCK_GIANT(vfslocked
);
1451 NDFREE(&nd
, NDF_ONLY_PNBUF
);
1456 * Make a hard file link.
1458 #ifndef _SYS_SYSPROTO_H_
1467 register struct link_args
/* {
1473 return (kern_link(td
, uap
->path
, uap
->link
, UIO_USERSPACE
));
1476 #ifndef _SYS_SYSPROTO_H_
1477 struct linkat_args
{
1486 linkat(struct thread
*td
, struct linkat_args
*uap
)
1491 if (flag
& ~AT_SYMLINK_FOLLOW
)
1494 return (kern_linkat(td
, uap
->fd1
, uap
->fd2
, uap
->path1
, uap
->path2
,
1495 UIO_USERSPACE
, (flag
& AT_SYMLINK_FOLLOW
) ? FOLLOW
: NOFOLLOW
));
1498 static int hardlink_check_uid
= 0;
1499 SYSCTL_INT(_security_bsd
, OID_AUTO
, hardlink_check_uid
, CTLFLAG_RW
,
1500 &hardlink_check_uid
, 0,
1501 "Unprivileged processes cannot create hard links to files owned by other "
1503 static int hardlink_check_gid
= 0;
1504 SYSCTL_INT(_security_bsd
, OID_AUTO
, hardlink_check_gid
, CTLFLAG_RW
,
1505 &hardlink_check_gid
, 0,
1506 "Unprivileged processes cannot create hard links to files owned by other "
1510 can_hardlink(struct vnode
*vp
, struct ucred
*cred
)
1515 if (!hardlink_check_uid
&& !hardlink_check_gid
)
1518 error
= VOP_GETATTR(vp
, &va
, cred
);
1522 if (hardlink_check_uid
&& cred
->cr_uid
!= va
.va_uid
) {
1523 error
= priv_check_cred(cred
, PRIV_VFS_LINK
, 0);
1528 if (hardlink_check_gid
&& !groupmember(va
.va_gid
, cred
)) {
1529 error
= priv_check_cred(cred
, PRIV_VFS_LINK
, 0);
1538 kern_link(struct thread
*td
, char *path
, char *link
, enum uio_seg segflg
)
1541 return (kern_linkat(td
, AT_FDCWD
, AT_FDCWD
, path
,link
, segflg
, FOLLOW
));
1545 kern_linkat(struct thread
*td
, int fd1
, int fd2
, char *path1
, char *path2
,
1546 enum uio_seg segflg
, int follow
)
1550 struct nameidata nd
;
1556 NDINIT_AT(&nd
, LOOKUP
, follow
| MPSAFE
| AUDITVNODE1
, segflg
, path1
,
1559 if ((error
= namei(&nd
)) != 0)
1561 vfslocked
= NDHASGIANT(&nd
);
1562 NDFREE(&nd
, NDF_ONLY_PNBUF
);
1564 if (vp
->v_type
== VDIR
) {
1566 VFS_UNLOCK_GIANT(vfslocked
);
1567 return (EPERM
); /* POSIX */
1569 if ((error
= vn_start_write(vp
, &mp
, V_WAIT
| PCATCH
)) != 0) {
1571 VFS_UNLOCK_GIANT(vfslocked
);
1574 NDINIT_AT(&nd
, CREATE
, LOCKPARENT
| SAVENAME
| MPSAFE
| AUDITVNODE1
,
1575 segflg
, path2
, fd2
, td
);
1576 if ((error
= namei(&nd
)) == 0) {
1577 lvfslocked
= NDHASGIANT(&nd
);
1578 if (nd
.ni_vp
!= NULL
) {
1579 if (nd
.ni_dvp
== nd
.ni_vp
)
1585 } else if ((error
= vn_lock(vp
, LK_EXCLUSIVE
| LK_RETRY
))
1587 VOP_LEASE(nd
.ni_dvp
, td
, td
->td_ucred
, LEASE_WRITE
);
1588 VOP_LEASE(vp
, td
, td
->td_ucred
, LEASE_WRITE
);
1589 error
= can_hardlink(vp
, td
->td_ucred
);
1592 error
= mac_vnode_check_link(td
->td_ucred
,
1593 nd
.ni_dvp
, vp
, &nd
.ni_cnd
);
1596 error
= VOP_LINK(nd
.ni_dvp
, vp
, &nd
.ni_cnd
);
1600 NDFREE(&nd
, NDF_ONLY_PNBUF
);
1601 VFS_UNLOCK_GIANT(lvfslocked
);
1604 vn_finished_write(mp
);
1605 VFS_UNLOCK_GIANT(vfslocked
);
1610 * Make a symbolic link.
1612 #ifndef _SYS_SYSPROTO_H_
1613 struct symlink_args
{
1621 register struct symlink_args
/* {
1627 return (kern_symlink(td
, uap
->path
, uap
->link
, UIO_USERSPACE
));
1630 #ifndef _SYS_SYSPROTO_H_
1631 struct symlinkat_args
{
1638 symlinkat(struct thread
*td
, struct symlinkat_args
*uap
)
1641 return (kern_symlinkat(td
, uap
->path1
, uap
->fd
, uap
->path2
,
1646 kern_symlink(struct thread
*td
, char *path
, char *link
, enum uio_seg segflg
)
1649 return (kern_symlinkat(td
, path
, AT_FDCWD
, link
, segflg
));
1653 kern_symlinkat(struct thread
*td
, char *path1
, int fd
, char *path2
,
1654 enum uio_seg segflg
)
1660 struct nameidata nd
;
1663 if (segflg
== UIO_SYSSPACE
) {
1666 syspath
= uma_zalloc(namei_zone
, M_WAITOK
);
1667 if ((error
= copyinstr(path1
, syspath
, MAXPATHLEN
, NULL
)) != 0)
1670 AUDIT_ARG(text
, syspath
);
1673 NDINIT_AT(&nd
, CREATE
, LOCKPARENT
| SAVENAME
| MPSAFE
| AUDITVNODE1
,
1674 segflg
, path2
, fd
, td
);
1675 if ((error
= namei(&nd
)) != 0)
1677 vfslocked
= NDHASGIANT(&nd
);
1679 NDFREE(&nd
, NDF_ONLY_PNBUF
);
1680 if (nd
.ni_vp
== nd
.ni_dvp
)
1685 VFS_UNLOCK_GIANT(vfslocked
);
1689 if (vn_start_write(nd
.ni_dvp
, &mp
, V_NOWAIT
) != 0) {
1690 NDFREE(&nd
, NDF_ONLY_PNBUF
);
1692 VFS_UNLOCK_GIANT(vfslocked
);
1693 if ((error
= vn_start_write(NULL
, &mp
, V_XSLEEP
| PCATCH
)) != 0)
1698 FILEDESC_SLOCK(td
->td_proc
->p_fd
);
1699 vattr
.va_mode
= ACCESSPERMS
&~ td
->td_proc
->p_fd
->fd_cmask
;
1700 FILEDESC_SUNLOCK(td
->td_proc
->p_fd
);
1702 vattr
.va_type
= VLNK
;
1703 error
= mac_vnode_check_create(td
->td_ucred
, nd
.ni_dvp
, &nd
.ni_cnd
,
1708 VOP_LEASE(nd
.ni_dvp
, td
, td
->td_ucred
, LEASE_WRITE
);
1709 error
= VOP_SYMLINK(nd
.ni_dvp
, &nd
.ni_vp
, &nd
.ni_cnd
, &vattr
, syspath
);
1715 NDFREE(&nd
, NDF_ONLY_PNBUF
);
1717 vn_finished_write(mp
);
1718 VFS_UNLOCK_GIANT(vfslocked
);
1720 if (segflg
!= UIO_SYSSPACE
)
1721 uma_zfree(namei_zone
, syspath
);
1726 * Delete a whiteout from the filesystem.
1731 register struct undelete_args
/* {
1737 struct nameidata nd
;
1742 NDINIT(&nd
, DELETE
, LOCKPARENT
| DOWHITEOUT
| MPSAFE
| AUDITVNODE1
,
1743 UIO_USERSPACE
, uap
->path
, td
);
1747 vfslocked
= NDHASGIANT(&nd
);
1749 if (nd
.ni_vp
!= NULLVP
|| !(nd
.ni_cnd
.cn_flags
& ISWHITEOUT
)) {
1750 NDFREE(&nd
, NDF_ONLY_PNBUF
);
1751 if (nd
.ni_vp
== nd
.ni_dvp
)
1757 VFS_UNLOCK_GIANT(vfslocked
);
1760 if (vn_start_write(nd
.ni_dvp
, &mp
, V_NOWAIT
) != 0) {
1761 NDFREE(&nd
, NDF_ONLY_PNBUF
);
1763 VFS_UNLOCK_GIANT(vfslocked
);
1764 if ((error
= vn_start_write(NULL
, &mp
, V_XSLEEP
| PCATCH
)) != 0)
1768 VOP_LEASE(nd
.ni_dvp
, td
, td
->td_ucred
, LEASE_WRITE
);
1769 error
= VOP_WHITEOUT(nd
.ni_dvp
, &nd
.ni_cnd
, DELETE
);
1770 NDFREE(&nd
, NDF_ONLY_PNBUF
);
1772 vn_finished_write(mp
);
1773 VFS_UNLOCK_GIANT(vfslocked
);
1778 * Delete a name from the filesystem.
1780 #ifndef _SYS_SYSPROTO_H_
1781 struct unlink_args
{
1788 struct unlink_args
/* {
1793 return (kern_unlink(td
, uap
->path
, UIO_USERSPACE
));
1796 #ifndef _SYS_SYSPROTO_H_
1797 struct unlinkat_args
{
1804 unlinkat(struct thread
*td
, struct unlinkat_args
*uap
)
1806 int flag
= uap
->flag
;
1808 char *path
= uap
->path
;
1810 if (flag
& ~AT_REMOVEDIR
)
1813 if (flag
& AT_REMOVEDIR
)
1814 return (kern_rmdirat(td
, fd
, path
, UIO_USERSPACE
));
1816 return (kern_unlinkat(td
, fd
, path
, UIO_USERSPACE
));
1820 kern_unlink(struct thread
*td
, char *path
, enum uio_seg pathseg
)
1823 return (kern_unlinkat(td
, AT_FDCWD
, path
, pathseg
));
1827 kern_unlinkat(struct thread
*td
, int fd
, char *path
, enum uio_seg pathseg
)
1832 struct nameidata nd
;
1837 NDINIT_AT(&nd
, DELETE
, LOCKPARENT
| LOCKLEAF
| MPSAFE
| AUDITVNODE1
,
1838 pathseg
, path
, fd
, td
);
1839 if ((error
= namei(&nd
)) != 0)
1840 return (error
== EINVAL
? EPERM
: error
);
1841 vfslocked
= NDHASGIANT(&nd
);
1843 if (vp
->v_type
== VDIR
)
1844 error
= EPERM
; /* POSIX */
1847 * The root of a mounted filesystem cannot be deleted.
1849 * XXX: can this only be a VDIR case?
1851 if (vp
->v_vflag
& VV_ROOT
)
1855 if (vn_start_write(nd
.ni_dvp
, &mp
, V_NOWAIT
) != 0) {
1856 NDFREE(&nd
, NDF_ONLY_PNBUF
);
1858 if (vp
== nd
.ni_dvp
)
1862 VFS_UNLOCK_GIANT(vfslocked
);
1863 if ((error
= vn_start_write(NULL
, &mp
,
1864 V_XSLEEP
| PCATCH
)) != 0)
1869 error
= mac_vnode_check_unlink(td
->td_ucred
, nd
.ni_dvp
, vp
,
1874 VOP_LEASE(nd
.ni_dvp
, td
, td
->td_ucred
, LEASE_WRITE
);
1875 error
= VOP_REMOVE(nd
.ni_dvp
, vp
, &nd
.ni_cnd
);
1879 vn_finished_write(mp
);
1881 NDFREE(&nd
, NDF_ONLY_PNBUF
);
1883 if (vp
== nd
.ni_dvp
)
1887 VFS_UNLOCK_GIANT(vfslocked
);
1892 * Reposition read/write file offset.
1894 #ifndef _SYS_SYSPROTO_H_
1905 register struct lseek_args
/* {
1912 struct ucred
*cred
= td
->td_ucred
;
1920 if ((error
= fget(td
, uap
->fd
, &fp
)) != 0)
1922 if (!(fp
->f_ops
->fo_flags
& DFLAG_SEEKABLE
)) {
1927 vfslocked
= VFS_LOCK_GIANT(vp
->v_mount
);
1928 noneg
= (vp
->v_type
!= VCHR
);
1929 offset
= uap
->offset
;
1930 switch (uap
->whence
) {
1933 (fp
->f_offset
< 0 ||
1934 (offset
> 0 && fp
->f_offset
> OFF_MAX
- offset
))) {
1938 offset
+= fp
->f_offset
;
1941 vn_lock(vp
, LK_EXCLUSIVE
| LK_RETRY
);
1942 error
= VOP_GETATTR(vp
, &vattr
, cred
);
1947 (vattr
.va_size
> OFF_MAX
||
1948 (offset
> 0 && vattr
.va_size
> OFF_MAX
- offset
))) {
1952 offset
+= vattr
.va_size
;
1957 error
= fo_ioctl(fp
, FIOSEEKDATA
, &offset
, cred
, td
);
1960 error
= fo_ioctl(fp
, FIOSEEKHOLE
, &offset
, cred
, td
);
1965 if (error
== 0 && noneg
&& offset
< 0)
1969 fp
->f_offset
= offset
;
1970 *(off_t
*)(td
->td_retval
) = fp
->f_offset
;
1973 VFS_UNLOCK_GIANT(vfslocked
);
1977 #if defined(COMPAT_43)
1979 * Reposition read/write file offset.
1981 #ifndef _SYS_SYSPROTO_H_
1982 struct olseek_args
{
1991 register struct olseek_args
/* {
1997 struct lseek_args
/* {
2005 nuap
.offset
= uap
->offset
;
2006 nuap
.whence
= uap
->whence
;
2007 return (lseek(td
, &nuap
));
2009 #endif /* COMPAT_43 */
2011 /* Version with the 'pad' argument */
2013 freebsd6_lseek(td
, uap
)
2015 register struct freebsd6_lseek_args
*uap
;
2017 struct lseek_args ouap
;
2020 ouap
.offset
= uap
->offset
;
2021 ouap
.whence
= uap
->whence
;
2022 return (lseek(td
, &ouap
));
2026 * Check access permissions using passed credentials.
2029 vn_access(vp
, user_flags
, cred
, td
)
2037 /* Flags == 0 means only check for existence. */
2041 if (user_flags
& R_OK
)
2043 if (user_flags
& W_OK
)
2045 if (user_flags
& X_OK
)
2048 error
= mac_vnode_check_access(cred
, vp
, flags
);
2052 if ((flags
& VWRITE
) == 0 || (error
= vn_writechk(vp
)) == 0)
2053 error
= VOP_ACCESS(vp
, flags
, cred
, td
);
2059 * Check access permissions using "real" credentials.
2061 #ifndef _SYS_SYSPROTO_H_
2062 struct access_args
{
2070 register struct access_args
/* {
2076 return (kern_access(td
, uap
->path
, UIO_USERSPACE
, uap
->flags
));
2079 #ifndef _SYS_SYSPROTO_H_
2080 struct faccessat_args
{
2087 int faccessat(struct thread
*td
, struct faccessat_args
*uap
)
2090 if (uap
->flag
& ~AT_EACCESS
)
2092 return (kern_accessat(td
, uap
->fd
, uap
->path
, UIO_USERSPACE
, uap
->flag
,
2097 kern_access(struct thread
*td
, char *path
, enum uio_seg pathseg
, int mode
)
2100 return (kern_accessat(td
, AT_FDCWD
, path
, pathseg
, 0, mode
));
2104 kern_accessat(struct thread
*td
, int fd
, char *path
, enum uio_seg pathseg
,
2105 int flags
, int mode
)
2107 struct ucred
*cred
, *tmpcred
;
2109 struct nameidata nd
;
2114 * Create and modify a temporary credential instead of one that
2115 * is potentially shared. This could also mess up socket
2116 * buffer accounting which can run in an interrupt context.
2118 if (!(flags
& AT_EACCESS
)) {
2119 cred
= td
->td_ucred
;
2120 tmpcred
= crdup(cred
);
2121 tmpcred
->cr_uid
= cred
->cr_ruid
;
2122 tmpcred
->cr_groups
[0] = cred
->cr_rgid
;
2123 td
->td_ucred
= tmpcred
;
2125 cred
= tmpcred
= td
->td_ucred
;
2126 NDINIT_AT(&nd
, LOOKUP
, FOLLOW
| LOCKLEAF
| MPSAFE
| AUDITVNODE1
,
2127 pathseg
, path
, fd
, td
);
2128 if ((error
= namei(&nd
)) != 0)
2130 vfslocked
= NDHASGIANT(&nd
);
2133 error
= vn_access(vp
, mode
, tmpcred
, td
);
2134 NDFREE(&nd
, NDF_ONLY_PNBUF
);
2136 VFS_UNLOCK_GIANT(vfslocked
);
2138 if (!(flags
& AT_EACCESS
)) {
2139 td
->td_ucred
= cred
;
2146 * Check access permissions using "effective" credentials.
2148 #ifndef _SYS_SYSPROTO_H_
2149 struct eaccess_args
{
2157 register struct eaccess_args
/* {
2163 return (kern_eaccess(td
, uap
->path
, UIO_USERSPACE
, uap
->flags
));
2167 kern_eaccess(struct thread
*td
, char *path
, enum uio_seg pathseg
, int flags
)
2170 return (kern_accessat(td
, AT_FDCWD
, path
, pathseg
, AT_EACCESS
, flags
));
2173 #if defined(COMPAT_43)
2175 * Get file status; this version follows links.
2177 #ifndef _SYS_SYSPROTO_H_
2186 register struct ostat_args
/* {
2195 error
= kern_stat(td
, uap
->path
, UIO_USERSPACE
, &sb
);
2199 error
= copyout(&osb
, uap
->ub
, sizeof (osb
));
2204 * Get file status; this version does not follow links.
2206 #ifndef _SYS_SYSPROTO_H_
2207 struct olstat_args
{
2215 register struct olstat_args
/* {
2224 error
= kern_lstat(td
, uap
->path
, UIO_USERSPACE
, &sb
);
2228 error
= copyout(&osb
, uap
->ub
, sizeof (osb
));
2233 * Convert from an old to a new stat structure.
2241 ost
->st_dev
= st
->st_dev
;
2242 ost
->st_ino
= st
->st_ino
;
2243 ost
->st_mode
= st
->st_mode
;
2244 ost
->st_nlink
= st
->st_nlink
;
2245 ost
->st_uid
= st
->st_uid
;
2246 ost
->st_gid
= st
->st_gid
;
2247 ost
->st_rdev
= st
->st_rdev
;
2248 if (st
->st_size
< (quad_t
)1 << 32)
2249 ost
->st_size
= st
->st_size
;
2252 ost
->st_atime
= st
->st_atime
;
2253 ost
->st_mtime
= st
->st_mtime
;
2254 ost
->st_ctime
= st
->st_ctime
;
2255 ost
->st_blksize
= st
->st_blksize
;
2256 ost
->st_blocks
= st
->st_blocks
;
2257 ost
->st_flags
= st
->st_flags
;
2258 ost
->st_gen
= st
->st_gen
;
2260 #endif /* COMPAT_43 */
2263 * Get file status; this version follows links.
2265 #ifndef _SYS_SYSPROTO_H_
2274 register struct stat_args
/* {
2282 error
= kern_stat(td
, uap
->path
, UIO_USERSPACE
, &sb
);
2284 error
= copyout(&sb
, uap
->ub
, sizeof (sb
));
2288 #ifndef _SYS_SYSPROTO_H_
2289 struct fstatat_args
{
2297 fstatat(struct thread
*td
, struct fstatat_args
*uap
)
2302 error
= kern_statat(td
, uap
->flag
, uap
->fd
, uap
->path
,
2303 UIO_USERSPACE
, &sb
);
2305 error
= copyout(&sb
, uap
->buf
, sizeof (sb
));
2310 kern_stat(struct thread
*td
, char *path
, enum uio_seg pathseg
, struct stat
*sbp
)
2313 return (kern_statat(td
, 0, AT_FDCWD
, path
, pathseg
, sbp
));
2317 kern_statat(struct thread
*td
, int flag
, int fd
, char *path
,
2318 enum uio_seg pathseg
, struct stat
*sbp
)
2320 struct nameidata nd
;
2322 int error
, vfslocked
;
2324 if (flag
& ~AT_SYMLINK_NOFOLLOW
)
2327 NDINIT_AT(&nd
, LOOKUP
, ((flag
& AT_SYMLINK_NOFOLLOW
) ? NOFOLLOW
:
2328 FOLLOW
) | LOCKSHARED
| LOCKLEAF
| AUDITVNODE1
| MPSAFE
, pathseg
,
2331 if ((error
= namei(&nd
)) != 0)
2333 vfslocked
= NDHASGIANT(&nd
);
2334 error
= vn_stat(nd
.ni_vp
, &sb
, td
->td_ucred
, NOCRED
, td
);
2335 NDFREE(&nd
, NDF_ONLY_PNBUF
);
2337 VFS_UNLOCK_GIANT(vfslocked
);
2338 if (mtx_owned(&Giant
))
2339 printf("stat(%d): %s\n", vfslocked
, path
);
2344 if (KTRPOINT(td
, KTR_STRUCT
))
2351 * Get file status; this version does not follow links.
2353 #ifndef _SYS_SYSPROTO_H_
2362 register struct lstat_args
/* {
2370 error
= kern_lstat(td
, uap
->path
, UIO_USERSPACE
, &sb
);
2372 error
= copyout(&sb
, uap
->ub
, sizeof (sb
));
2377 kern_lstat(struct thread
*td
, char *path
, enum uio_seg pathseg
, struct stat
*sbp
)
2380 return (kern_statat(td
, AT_SYMLINK_NOFOLLOW
, AT_FDCWD
, path
, pathseg
,
2385 * Implementation of the NetBSD [l]stat() functions.
2392 bzero(nsb
, sizeof *nsb
);
2393 nsb
->st_dev
= sb
->st_dev
;
2394 nsb
->st_ino
= sb
->st_ino
;
2395 nsb
->st_mode
= sb
->st_mode
;
2396 nsb
->st_nlink
= sb
->st_nlink
;
2397 nsb
->st_uid
= sb
->st_uid
;
2398 nsb
->st_gid
= sb
->st_gid
;
2399 nsb
->st_rdev
= sb
->st_rdev
;
2400 nsb
->st_atimespec
= sb
->st_atimespec
;
2401 nsb
->st_mtimespec
= sb
->st_mtimespec
;
2402 nsb
->st_ctimespec
= sb
->st_ctimespec
;
2403 nsb
->st_size
= sb
->st_size
;
2404 nsb
->st_blocks
= sb
->st_blocks
;
2405 nsb
->st_blksize
= sb
->st_blksize
;
2406 nsb
->st_flags
= sb
->st_flags
;
2407 nsb
->st_gen
= sb
->st_gen
;
2408 nsb
->st_birthtimespec
= sb
->st_birthtimespec
;
2411 #ifndef _SYS_SYSPROTO_H_
2420 register struct nstat_args
/* {
2429 error
= kern_stat(td
, uap
->path
, UIO_USERSPACE
, &sb
);
2432 cvtnstat(&sb
, &nsb
);
2433 error
= copyout(&nsb
, uap
->ub
, sizeof (nsb
));
2438 * NetBSD lstat. Get file status; this version does not follow links.
2440 #ifndef _SYS_SYSPROTO_H_
2449 register struct nlstat_args
/* {
2458 error
= kern_lstat(td
, uap
->path
, UIO_USERSPACE
, &sb
);
2461 cvtnstat(&sb
, &nsb
);
2462 error
= copyout(&nsb
, uap
->ub
, sizeof (nsb
));
2467 * Get configurable pathname variables.
2469 #ifndef _SYS_SYSPROTO_H_
2470 struct pathconf_args
{
2478 register struct pathconf_args
/* {
2484 return (kern_pathconf(td
, uap
->path
, UIO_USERSPACE
, uap
->name
));
2488 kern_pathconf(struct thread
*td
, char *path
, enum uio_seg pathseg
, int name
)
2490 struct nameidata nd
;
2491 int error
, vfslocked
;
2493 NDINIT(&nd
, LOOKUP
, FOLLOW
| LOCKLEAF
| MPSAFE
| AUDITVNODE1
,
2495 if ((error
= namei(&nd
)) != 0)
2497 vfslocked
= NDHASGIANT(&nd
);
2498 NDFREE(&nd
, NDF_ONLY_PNBUF
);
2500 /* If asynchronous I/O is available, it works for all files. */
2501 if (name
== _PC_ASYNC_IO
)
2502 td
->td_retval
[0] = async_io_version
;
2504 error
= VOP_PATHCONF(nd
.ni_vp
, name
, td
->td_retval
);
2506 VFS_UNLOCK_GIANT(vfslocked
);
2511 * Return target name of a symbolic link.
2513 #ifndef _SYS_SYSPROTO_H_
2514 struct readlink_args
{
2523 register struct readlink_args
/* {
2530 return (kern_readlink(td
, uap
->path
, UIO_USERSPACE
, uap
->buf
,
2531 UIO_USERSPACE
, uap
->count
));
2533 #ifndef _SYS_SYSPROTO_H_
2534 struct readlinkat_args
{
2542 readlinkat(struct thread
*td
, struct readlinkat_args
*uap
)
2545 return (kern_readlinkat(td
, uap
->fd
, uap
->path
, UIO_USERSPACE
,
2546 uap
->buf
, UIO_USERSPACE
, uap
->bufsize
));
2550 kern_readlink(struct thread
*td
, char *path
, enum uio_seg pathseg
, char *buf
,
2551 enum uio_seg bufseg
, size_t count
)
2554 return (kern_readlinkat(td
, AT_FDCWD
, path
, pathseg
, buf
, bufseg
,
2559 kern_readlinkat(struct thread
*td
, int fd
, char *path
, enum uio_seg pathseg
,
2560 char *buf
, enum uio_seg bufseg
, size_t count
)
2566 struct nameidata nd
;
2569 NDINIT_AT(&nd
, LOOKUP
, NOFOLLOW
| LOCKLEAF
| MPSAFE
| AUDITVNODE1
,
2570 pathseg
, path
, fd
, td
);
2572 if ((error
= namei(&nd
)) != 0)
2574 NDFREE(&nd
, NDF_ONLY_PNBUF
);
2575 vfslocked
= NDHASGIANT(&nd
);
2578 error
= mac_vnode_check_readlink(td
->td_ucred
, vp
);
2581 VFS_UNLOCK_GIANT(vfslocked
);
2585 if (vp
->v_type
!= VLNK
)
2588 aiov
.iov_base
= buf
;
2589 aiov
.iov_len
= count
;
2590 auio
.uio_iov
= &aiov
;
2591 auio
.uio_iovcnt
= 1;
2592 auio
.uio_offset
= 0;
2593 auio
.uio_rw
= UIO_READ
;
2594 auio
.uio_segflg
= bufseg
;
2596 auio
.uio_resid
= count
;
2597 error
= VOP_READLINK(vp
, &auio
, td
->td_ucred
);
2600 VFS_UNLOCK_GIANT(vfslocked
);
2601 td
->td_retval
[0] = count
- auio
.uio_resid
;
2606 * Common implementation code for chflags() and fchflags().
2609 setfflags(td
, vp
, flags
)
2619 * Prevent non-root users from setting flags on devices. When
2620 * a device is reused, users can retain ownership of the device
2621 * if they are allowed to set flags and programs assume that
2622 * chown can't fail when done as root.
2624 if (vp
->v_type
== VCHR
|| vp
->v_type
== VBLK
) {
2625 error
= priv_check(td
, PRIV_VFS_CHFLAGS_DEV
);
2630 if ((error
= vn_start_write(vp
, &mp
, V_WAIT
| PCATCH
)) != 0)
2632 VOP_LEASE(vp
, td
, td
->td_ucred
, LEASE_WRITE
);
2633 vn_lock(vp
, LK_EXCLUSIVE
| LK_RETRY
);
2635 vattr
.va_flags
= flags
;
2637 error
= mac_vnode_check_setflags(td
->td_ucred
, vp
, vattr
.va_flags
);
2640 error
= VOP_SETATTR(vp
, &vattr
, td
->td_ucred
);
2642 vn_finished_write(mp
);
2647 * Change flags of a file given a path name.
2649 #ifndef _SYS_SYSPROTO_H_
2650 struct chflags_args
{
2658 register struct chflags_args
/* {
2664 struct nameidata nd
;
2667 AUDIT_ARG(fflags
, uap
->flags
);
2668 NDINIT(&nd
, LOOKUP
, FOLLOW
| MPSAFE
| AUDITVNODE1
, UIO_USERSPACE
,
2670 if ((error
= namei(&nd
)) != 0)
2672 NDFREE(&nd
, NDF_ONLY_PNBUF
);
2673 vfslocked
= NDHASGIANT(&nd
);
2674 error
= setfflags(td
, nd
.ni_vp
, uap
->flags
);
2676 VFS_UNLOCK_GIANT(vfslocked
);
2681 * Same as chflags() but doesn't follow symlinks.
2686 register struct lchflags_args
/* {
2692 struct nameidata nd
;
2695 AUDIT_ARG(fflags
, uap
->flags
);
2696 NDINIT(&nd
, LOOKUP
, NOFOLLOW
| MPSAFE
| AUDITVNODE1
, UIO_USERSPACE
,
2698 if ((error
= namei(&nd
)) != 0)
2700 vfslocked
= NDHASGIANT(&nd
);
2701 NDFREE(&nd
, NDF_ONLY_PNBUF
);
2702 error
= setfflags(td
, nd
.ni_vp
, uap
->flags
);
2704 VFS_UNLOCK_GIANT(vfslocked
);
2709 * Change flags of a file given a file descriptor.
2711 #ifndef _SYS_SYSPROTO_H_
2712 struct fchflags_args
{
2720 register struct fchflags_args
/* {
2729 AUDIT_ARG(fd
, uap
->fd
);
2730 AUDIT_ARG(fflags
, uap
->flags
);
2731 if ((error
= getvnode(td
->td_proc
->p_fd
, uap
->fd
, &fp
)) != 0)
2733 vfslocked
= VFS_LOCK_GIANT(fp
->f_vnode
->v_mount
);
2735 vn_lock(fp
->f_vnode
, LK_EXCLUSIVE
| LK_RETRY
);
2736 AUDIT_ARG(vnode
, fp
->f_vnode
, ARG_VNODE1
);
2737 VOP_UNLOCK(fp
->f_vnode
, 0);
2739 error
= setfflags(td
, fp
->f_vnode
, uap
->flags
);
2740 VFS_UNLOCK_GIANT(vfslocked
);
2746 * Common implementation code for chmod(), lchmod() and fchmod().
2749 setfmode(td
, vp
, mode
)
2758 if ((error
= vn_start_write(vp
, &mp
, V_WAIT
| PCATCH
)) != 0)
2760 VOP_LEASE(vp
, td
, td
->td_ucred
, LEASE_WRITE
);
2761 vn_lock(vp
, LK_EXCLUSIVE
| LK_RETRY
);
2763 vattr
.va_mode
= mode
& ALLPERMS
;
2765 error
= mac_vnode_check_setmode(td
->td_ucred
, vp
, vattr
.va_mode
);
2768 error
= VOP_SETATTR(vp
, &vattr
, td
->td_ucred
);
2770 vn_finished_write(mp
);
2775 * Change mode of a file given path name.
2777 #ifndef _SYS_SYSPROTO_H_
2786 register struct chmod_args
/* {
2792 return (kern_chmod(td
, uap
->path
, UIO_USERSPACE
, uap
->mode
));
2795 #ifndef _SYS_SYSPROTO_H_
2796 struct fchmodat_args
{
2804 fchmodat(struct thread
*td
, struct fchmodat_args
*uap
)
2806 int flag
= uap
->flag
;
2808 char *path
= uap
->path
;
2809 mode_t mode
= uap
->mode
;
2811 if (flag
& ~AT_SYMLINK_NOFOLLOW
)
2814 return (kern_fchmodat(td
, fd
, path
, UIO_USERSPACE
, mode
, flag
));
2818 kern_chmod(struct thread
*td
, char *path
, enum uio_seg pathseg
, int mode
)
2821 return (kern_fchmodat(td
, AT_FDCWD
, path
, pathseg
, mode
, 0));
2825 * Change mode of a file given path name (don't follow links.)
2827 #ifndef _SYS_SYSPROTO_H_
2828 struct lchmod_args
{
2836 register struct lchmod_args
/* {
2842 return (kern_fchmodat(td
, AT_FDCWD
, uap
->path
, UIO_USERSPACE
,
2843 uap
->mode
, AT_SYMLINK_NOFOLLOW
));
2848 kern_fchmodat(struct thread
*td
, int fd
, char *path
, enum uio_seg pathseg
,
2849 mode_t mode
, int flag
)
2852 struct nameidata nd
;
2856 AUDIT_ARG(mode
, mode
);
2857 follow
= (flag
& AT_SYMLINK_NOFOLLOW
) ? NOFOLLOW
: FOLLOW
;
2858 NDINIT_AT(&nd
, LOOKUP
, follow
| MPSAFE
| AUDITVNODE1
, pathseg
, path
,
2860 if ((error
= namei(&nd
)) != 0)
2862 vfslocked
= NDHASGIANT(&nd
);
2863 NDFREE(&nd
, NDF_ONLY_PNBUF
);
2864 error
= setfmode(td
, nd
.ni_vp
, mode
);
2866 VFS_UNLOCK_GIANT(vfslocked
);
2871 * Change mode of a file given a file descriptor.
2873 #ifndef _SYS_SYSPROTO_H_
2874 struct fchmod_args
{
2882 register struct fchmod_args
/* {
2891 AUDIT_ARG(fd
, uap
->fd
);
2892 AUDIT_ARG(mode
, uap
->mode
);
2893 if ((error
= getvnode(td
->td_proc
->p_fd
, uap
->fd
, &fp
)) != 0)
2895 vfslocked
= VFS_LOCK_GIANT(fp
->f_vnode
->v_mount
);
2897 vn_lock(fp
->f_vnode
, LK_EXCLUSIVE
| LK_RETRY
);
2898 AUDIT_ARG(vnode
, fp
->f_vnode
, ARG_VNODE1
);
2899 VOP_UNLOCK(fp
->f_vnode
, 0);
2901 error
= setfmode(td
, fp
->f_vnode
, uap
->mode
);
2902 VFS_UNLOCK_GIANT(vfslocked
);
2908 * Common implementation for chown(), lchown(), and fchown()
2911 setfown(td
, vp
, uid
, gid
)
2921 if ((error
= vn_start_write(vp
, &mp
, V_WAIT
| PCATCH
)) != 0)
2923 VOP_LEASE(vp
, td
, td
->td_ucred
, LEASE_WRITE
);
2924 vn_lock(vp
, LK_EXCLUSIVE
| LK_RETRY
);
2929 error
= mac_vnode_check_setowner(td
->td_ucred
, vp
, vattr
.va_uid
,
2933 error
= VOP_SETATTR(vp
, &vattr
, td
->td_ucred
);
2935 vn_finished_write(mp
);
2940 * Set ownership given a path name.
2942 #ifndef _SYS_SYSPROTO_H_
2952 register struct chown_args
/* {
2959 return (kern_chown(td
, uap
->path
, UIO_USERSPACE
, uap
->uid
, uap
->gid
));
2962 #ifndef _SYS_SYSPROTO_H_
2963 struct fchownat_args
{
2972 fchownat(struct thread
*td
, struct fchownat_args
*uap
)
2977 if (flag
& ~AT_SYMLINK_NOFOLLOW
)
2980 return (kern_fchownat(td
, uap
->fd
, uap
->path
, UIO_USERSPACE
, uap
->uid
,
2981 uap
->gid
, uap
->flag
));
2985 kern_chown(struct thread
*td
, char *path
, enum uio_seg pathseg
, int uid
,
2989 return (kern_fchownat(td
, AT_FDCWD
, path
, pathseg
, uid
, gid
, 0));
2993 kern_fchownat(struct thread
*td
, int fd
, char *path
, enum uio_seg pathseg
,
2994 int uid
, int gid
, int flag
)
2996 struct nameidata nd
;
2997 int error
, vfslocked
, follow
;
2999 AUDIT_ARG(owner
, uid
, gid
);
3000 follow
= (flag
& AT_SYMLINK_NOFOLLOW
) ? NOFOLLOW
: FOLLOW
;
3001 NDINIT_AT(&nd
, LOOKUP
, follow
| MPSAFE
| AUDITVNODE1
, pathseg
, path
,
3004 if ((error
= namei(&nd
)) != 0)
3006 vfslocked
= NDHASGIANT(&nd
);
3007 NDFREE(&nd
, NDF_ONLY_PNBUF
);
3008 error
= setfown(td
, nd
.ni_vp
, uid
, gid
);
3010 VFS_UNLOCK_GIANT(vfslocked
);
3015 * Set ownership given a path name, do not cross symlinks.
3017 #ifndef _SYS_SYSPROTO_H_
3018 struct lchown_args
{
3027 register struct lchown_args
/* {
3034 return (kern_lchown(td
, uap
->path
, UIO_USERSPACE
, uap
->uid
, uap
->gid
));
3038 kern_lchown(struct thread
*td
, char *path
, enum uio_seg pathseg
, int uid
,
3042 return (kern_fchownat(td
, AT_FDCWD
, path
, pathseg
, uid
, gid
,
3043 AT_SYMLINK_NOFOLLOW
));
3047 * Set ownership given a file descriptor.
3049 #ifndef _SYS_SYSPROTO_H_
3050 struct fchown_args
{
3059 register struct fchown_args
/* {
3069 AUDIT_ARG(fd
, uap
->fd
);
3070 AUDIT_ARG(owner
, uap
->uid
, uap
->gid
);
3071 if ((error
= getvnode(td
->td_proc
->p_fd
, uap
->fd
, &fp
)) != 0)
3073 vfslocked
= VFS_LOCK_GIANT(fp
->f_vnode
->v_mount
);
3075 vn_lock(fp
->f_vnode
, LK_EXCLUSIVE
| LK_RETRY
);
3076 AUDIT_ARG(vnode
, fp
->f_vnode
, ARG_VNODE1
);
3077 VOP_UNLOCK(fp
->f_vnode
, 0);
3079 error
= setfown(td
, fp
->f_vnode
, uap
->uid
, uap
->gid
);
3080 VFS_UNLOCK_GIANT(vfslocked
);
3086 * Common implementation code for utimes(), lutimes(), and futimes().
3089 getutimes(usrtvp
, tvpseg
, tsp
)
3090 const struct timeval
*usrtvp
;
3091 enum uio_seg tvpseg
;
3092 struct timespec
*tsp
;
3094 struct timeval tv
[2];
3095 const struct timeval
*tvp
;
3098 if (usrtvp
== NULL
) {
3100 TIMEVAL_TO_TIMESPEC(&tv
[0], &tsp
[0]);
3103 if (tvpseg
== UIO_SYSSPACE
) {
3106 if ((error
= copyin(usrtvp
, tv
, sizeof(tv
))) != 0)
3111 if (tvp
[0].tv_usec
< 0 || tvp
[0].tv_usec
>= 1000000 ||
3112 tvp
[1].tv_usec
< 0 || tvp
[1].tv_usec
>= 1000000)
3114 TIMEVAL_TO_TIMESPEC(&tvp
[0], &tsp
[0]);
3115 TIMEVAL_TO_TIMESPEC(&tvp
[1], &tsp
[1]);
3121 * Common implementation code for utimes(), lutimes(), and futimes().
3124 setutimes(td
, vp
, ts
, numtimes
, nullflag
)
3127 const struct timespec
*ts
;
3131 int error
, setbirthtime
;
3135 if ((error
= vn_start_write(vp
, &mp
, V_WAIT
| PCATCH
)) != 0)
3137 VOP_LEASE(vp
, td
, td
->td_ucred
, LEASE_WRITE
);
3138 vn_lock(vp
, LK_EXCLUSIVE
| LK_RETRY
);
3140 if (numtimes
< 3 && !VOP_GETATTR(vp
, &vattr
, td
->td_ucred
) &&
3141 timespeccmp(&ts
[1], &vattr
.va_birthtime
, < ))
3144 vattr
.va_atime
= ts
[0];
3145 vattr
.va_mtime
= ts
[1];
3147 vattr
.va_birthtime
= ts
[1];
3149 vattr
.va_birthtime
= ts
[2];
3151 vattr
.va_vaflags
|= VA_UTIMES_NULL
;
3153 error
= mac_vnode_check_setutimes(td
->td_ucred
, vp
, vattr
.va_atime
,
3157 error
= VOP_SETATTR(vp
, &vattr
, td
->td_ucred
);
3159 vn_finished_write(mp
);
3164 * Set the access and modification times of a file.
3166 #ifndef _SYS_SYSPROTO_H_
3167 struct utimes_args
{
3169 struct timeval
*tptr
;
3175 register struct utimes_args
/* {
3177 struct timeval *tptr;
3181 return (kern_utimes(td
, uap
->path
, UIO_USERSPACE
, uap
->tptr
,
3185 #ifndef _SYS_SYSPROTO_H_
3186 struct futimesat_args
{
3189 const struct timeval
* times
;
3193 futimesat(struct thread
*td
, struct futimesat_args
*uap
)
3196 return (kern_utimesat(td
, uap
->fd
, uap
->path
, UIO_USERSPACE
,
3197 uap
->times
, UIO_USERSPACE
));
3201 kern_utimes(struct thread
*td
, char *path
, enum uio_seg pathseg
,
3202 struct timeval
*tptr
, enum uio_seg tptrseg
)
3205 return (kern_utimesat(td
, AT_FDCWD
, path
, pathseg
, tptr
, tptrseg
));
3209 kern_utimesat(struct thread
*td
, int fd
, char *path
, enum uio_seg pathseg
,
3210 struct timeval
*tptr
, enum uio_seg tptrseg
)
3212 struct nameidata nd
;
3213 struct timespec ts
[2];
3214 int error
, vfslocked
;
3216 if ((error
= getutimes(tptr
, tptrseg
, ts
)) != 0)
3218 NDINIT_AT(&nd
, LOOKUP
, FOLLOW
| MPSAFE
| AUDITVNODE1
, pathseg
, path
,
3221 if ((error
= namei(&nd
)) != 0)
3223 vfslocked
= NDHASGIANT(&nd
);
3224 NDFREE(&nd
, NDF_ONLY_PNBUF
);
3225 error
= setutimes(td
, nd
.ni_vp
, ts
, 2, tptr
== NULL
);
3227 VFS_UNLOCK_GIANT(vfslocked
);
3232 * Set the access and modification times of a file.
3234 #ifndef _SYS_SYSPROTO_H_
3235 struct lutimes_args
{
3237 struct timeval
*tptr
;
3243 register struct lutimes_args
/* {
3245 struct timeval *tptr;
3249 return (kern_lutimes(td
, uap
->path
, UIO_USERSPACE
, uap
->tptr
,
3254 kern_lutimes(struct thread
*td
, char *path
, enum uio_seg pathseg
,
3255 struct timeval
*tptr
, enum uio_seg tptrseg
)
3257 struct timespec ts
[2];
3259 struct nameidata nd
;
3262 if ((error
= getutimes(tptr
, tptrseg
, ts
)) != 0)
3264 NDINIT(&nd
, LOOKUP
, NOFOLLOW
| MPSAFE
| AUDITVNODE1
, pathseg
, path
, td
);
3265 if ((error
= namei(&nd
)) != 0)
3267 vfslocked
= NDHASGIANT(&nd
);
3268 NDFREE(&nd
, NDF_ONLY_PNBUF
);
3269 error
= setutimes(td
, nd
.ni_vp
, ts
, 2, tptr
== NULL
);
3271 VFS_UNLOCK_GIANT(vfslocked
);
3276 * Set the access and modification times of a file.
3278 #ifndef _SYS_SYSPROTO_H_
3279 struct futimes_args
{
3281 struct timeval
*tptr
;
3287 register struct futimes_args
/* {
3289 struct timeval *tptr;
3293 return (kern_futimes(td
, uap
->fd
, uap
->tptr
, UIO_USERSPACE
));
3297 kern_futimes(struct thread
*td
, int fd
, struct timeval
*tptr
,
3298 enum uio_seg tptrseg
)
3300 struct timespec ts
[2];
3306 if ((error
= getutimes(tptr
, tptrseg
, ts
)) != 0)
3308 if ((error
= getvnode(td
->td_proc
->p_fd
, fd
, &fp
)) != 0)
3310 vfslocked
= VFS_LOCK_GIANT(fp
->f_vnode
->v_mount
);
3312 vn_lock(fp
->f_vnode
, LK_EXCLUSIVE
| LK_RETRY
);
3313 AUDIT_ARG(vnode
, fp
->f_vnode
, ARG_VNODE1
);
3314 VOP_UNLOCK(fp
->f_vnode
, 0);
3316 error
= setutimes(td
, fp
->f_vnode
, ts
, 2, tptr
== NULL
);
3317 VFS_UNLOCK_GIANT(vfslocked
);
3323 * Truncate a file given its path name.
3325 #ifndef _SYS_SYSPROTO_H_
3326 struct truncate_args
{
3335 register struct truncate_args
/* {
3342 return (kern_truncate(td
, uap
->path
, UIO_USERSPACE
, uap
->length
));
3346 kern_truncate(struct thread
*td
, char *path
, enum uio_seg pathseg
, off_t length
)
3352 struct nameidata nd
;
3357 NDINIT(&nd
, LOOKUP
, FOLLOW
| MPSAFE
| AUDITVNODE1
, pathseg
, path
, td
);
3358 if ((error
= namei(&nd
)) != 0)
3360 vfslocked
= NDHASGIANT(&nd
);
3362 if ((error
= vn_start_write(vp
, &mp
, V_WAIT
| PCATCH
)) != 0) {
3364 VFS_UNLOCK_GIANT(vfslocked
);
3367 NDFREE(&nd
, NDF_ONLY_PNBUF
);
3368 VOP_LEASE(vp
, td
, td
->td_ucred
, LEASE_WRITE
);
3369 vn_lock(vp
, LK_EXCLUSIVE
| LK_RETRY
);
3370 if (vp
->v_type
== VDIR
)
3373 else if ((error
= mac_vnode_check_write(td
->td_ucred
, NOCRED
, vp
))) {
3376 else if ((error
= vn_writechk(vp
)) == 0 &&
3377 (error
= VOP_ACCESS(vp
, VWRITE
, td
->td_ucred
, td
)) == 0) {
3379 vattr
.va_size
= length
;
3380 error
= VOP_SETATTR(vp
, &vattr
, td
->td_ucred
);
3383 vn_finished_write(mp
);
3384 VFS_UNLOCK_GIANT(vfslocked
);
3388 #if defined(COMPAT_43)
3390 * Truncate a file given its path name.
3392 #ifndef _SYS_SYSPROTO_H_
3393 struct otruncate_args
{
3401 register struct otruncate_args
/* {
3406 struct truncate_args
/* {
3412 nuap
.path
= uap
->path
;
3413 nuap
.length
= uap
->length
;
3414 return (truncate(td
, &nuap
));
3416 #endif /* COMPAT_43 */
3418 /* Versions with the pad argument */
3420 freebsd6_truncate(struct thread
*td
, struct freebsd6_truncate_args
*uap
)
3422 struct truncate_args ouap
;
3424 ouap
.path
= uap
->path
;
3425 ouap
.length
= uap
->length
;
3426 return (truncate(td
, &ouap
));
3430 freebsd6_ftruncate(struct thread
*td
, struct freebsd6_ftruncate_args
*uap
)
3432 struct ftruncate_args ouap
;
3435 ouap
.length
= uap
->length
;
3436 return (ftruncate(td
, &ouap
));
3440 * Sync an open file.
3442 #ifndef _SYS_SYSPROTO_H_
3450 struct fsync_args
/* {
3460 AUDIT_ARG(fd
, uap
->fd
);
3461 if ((error
= getvnode(td
->td_proc
->p_fd
, uap
->fd
, &fp
)) != 0)
3464 vfslocked
= VFS_LOCK_GIANT(vp
->v_mount
);
3465 if ((error
= vn_start_write(vp
, &mp
, V_WAIT
| PCATCH
)) != 0)
3467 vn_lock(vp
, LK_EXCLUSIVE
| LK_RETRY
);
3468 AUDIT_ARG(vnode
, vp
, ARG_VNODE1
);
3469 if (vp
->v_object
!= NULL
) {
3470 VM_OBJECT_LOCK(vp
->v_object
);
3471 vm_object_page_clean(vp
->v_object
, 0, 0, 0);
3472 VM_OBJECT_UNLOCK(vp
->v_object
);
3474 error
= VOP_FSYNC(vp
, MNT_WAIT
, td
);
3477 vn_finished_write(mp
);
3479 VFS_UNLOCK_GIANT(vfslocked
);
3485 * Rename files. Source and destination must either both be directories, or
3486 * both not be directories. If target is a directory, it must be empty.
3488 #ifndef _SYS_SYSPROTO_H_
3489 struct rename_args
{
3497 register struct rename_args
/* {
3503 return (kern_rename(td
, uap
->from
, uap
->to
, UIO_USERSPACE
));
3506 #ifndef _SYS_SYSPROTO_H_
3507 struct renameat_args
{
3515 renameat(struct thread
*td
, struct renameat_args
*uap
)
3518 return (kern_renameat(td
, uap
->oldfd
, uap
->old
, uap
->newfd
, uap
->new,
3523 kern_rename(struct thread
*td
, char *from
, char *to
, enum uio_seg pathseg
)
3526 return (kern_renameat(td
, AT_FDCWD
, from
, AT_FDCWD
, to
, pathseg
));
3530 kern_renameat(struct thread
*td
, int oldfd
, char *old
, int newfd
, char *new,
3531 enum uio_seg pathseg
)
3533 struct mount
*mp
= NULL
;
3534 struct vnode
*tvp
, *fvp
, *tdvp
;
3535 struct nameidata fromnd
, tond
;
3542 NDINIT_AT(&fromnd
, DELETE
, LOCKPARENT
| LOCKLEAF
| SAVESTART
| MPSAFE
|
3543 AUDITVNODE1
, pathseg
, old
, oldfd
, td
);
3545 NDINIT_AT(&fromnd
, DELETE
, WANTPARENT
| SAVESTART
| MPSAFE
|
3546 AUDITVNODE1
, pathseg
, old
, oldfd
, td
);
3549 if ((error
= namei(&fromnd
)) != 0)
3551 fvfslocked
= NDHASGIANT(&fromnd
);
3554 error
= mac_vnode_check_rename_from(td
->td_ucred
, fromnd
.ni_dvp
,
3555 fromnd
.ni_vp
, &fromnd
.ni_cnd
);
3556 VOP_UNLOCK(fromnd
.ni_dvp
, 0);
3557 if (fromnd
.ni_dvp
!= fromnd
.ni_vp
)
3558 VOP_UNLOCK(fromnd
.ni_vp
, 0);
3562 error
= vn_start_write(fvp
, &mp
, V_WAIT
| PCATCH
);
3564 NDFREE(&fromnd
, NDF_ONLY_PNBUF
);
3565 vrele(fromnd
.ni_dvp
);
3569 NDINIT_AT(&tond
, RENAME
, LOCKPARENT
| LOCKLEAF
| NOCACHE
| SAVESTART
|
3570 MPSAFE
| AUDITVNODE2
, pathseg
, new, newfd
, td
);
3571 if (fromnd
.ni_vp
->v_type
== VDIR
)
3572 tond
.ni_cnd
.cn_flags
|= WILLBEDIR
;
3573 if ((error
= namei(&tond
)) != 0) {
3574 /* Translate error code for rename("dir1", "dir2/."). */
3575 if (error
== EISDIR
&& fvp
->v_type
== VDIR
)
3577 NDFREE(&fromnd
, NDF_ONLY_PNBUF
);
3578 vrele(fromnd
.ni_dvp
);
3580 vn_finished_write(mp
);
3583 tvfslocked
= NDHASGIANT(&tond
);
3587 if (fvp
->v_type
== VDIR
&& tvp
->v_type
!= VDIR
) {
3590 } else if (fvp
->v_type
!= VDIR
&& tvp
->v_type
== VDIR
) {
3600 * If the source is the same as the destination (that is, if they
3601 * are links to the same vnode), then there is nothing to do.
3607 error
= mac_vnode_check_rename_to(td
->td_ucred
, tdvp
,
3608 tond
.ni_vp
, fromnd
.ni_dvp
== tdvp
, &tond
.ni_cnd
);
3612 VOP_LEASE(tdvp
, td
, td
->td_ucred
, LEASE_WRITE
);
3613 if (fromnd
.ni_dvp
!= tdvp
) {
3614 VOP_LEASE(fromnd
.ni_dvp
, td
, td
->td_ucred
, LEASE_WRITE
);
3617 VOP_LEASE(tvp
, td
, td
->td_ucred
, LEASE_WRITE
);
3619 error
= VOP_RENAME(fromnd
.ni_dvp
, fromnd
.ni_vp
, &fromnd
.ni_cnd
,
3620 tond
.ni_dvp
, tond
.ni_vp
, &tond
.ni_cnd
);
3621 NDFREE(&fromnd
, NDF_ONLY_PNBUF
);
3622 NDFREE(&tond
, NDF_ONLY_PNBUF
);
3624 NDFREE(&fromnd
, NDF_ONLY_PNBUF
);
3625 NDFREE(&tond
, NDF_ONLY_PNBUF
);
3632 vrele(fromnd
.ni_dvp
);
3635 vrele(tond
.ni_startdir
);
3636 vn_finished_write(mp
);
3638 if (fromnd
.ni_startdir
)
3639 vrele(fromnd
.ni_startdir
);
3640 VFS_UNLOCK_GIANT(fvfslocked
);
3641 VFS_UNLOCK_GIANT(tvfslocked
);
3648 * Make a directory file.
3650 #ifndef _SYS_SYSPROTO_H_
3659 register struct mkdir_args
/* {
3665 return (kern_mkdir(td
, uap
->path
, UIO_USERSPACE
, uap
->mode
));
3668 #ifndef _SYS_SYSPROTO_H_
3669 struct mkdirat_args
{
3676 mkdirat(struct thread
*td
, struct mkdirat_args
*uap
)
3679 return (kern_mkdirat(td
, uap
->fd
, uap
->path
, UIO_USERSPACE
, uap
->mode
));
3683 kern_mkdir(struct thread
*td
, char *path
, enum uio_seg segflg
, int mode
)
3686 return (kern_mkdirat(td
, AT_FDCWD
, path
, segflg
, mode
));
3690 kern_mkdirat(struct thread
*td
, int fd
, char *path
, enum uio_seg segflg
,
3697 struct nameidata nd
;
3700 AUDIT_ARG(mode
, mode
);
3703 NDINIT_AT(&nd
, CREATE
, LOCKPARENT
| SAVENAME
| MPSAFE
| AUDITVNODE1
,
3704 segflg
, path
, fd
, td
);
3705 nd
.ni_cnd
.cn_flags
|= WILLBEDIR
;
3706 if ((error
= namei(&nd
)) != 0)
3708 vfslocked
= NDHASGIANT(&nd
);
3711 NDFREE(&nd
, NDF_ONLY_PNBUF
);
3713 * XXX namei called with LOCKPARENT but not LOCKLEAF has
3714 * the strange behaviour of leaving the vnode unlocked
3715 * if the target is the same vnode as the parent.
3717 if (vp
== nd
.ni_dvp
)
3722 VFS_UNLOCK_GIANT(vfslocked
);
3725 if (vn_start_write(nd
.ni_dvp
, &mp
, V_NOWAIT
) != 0) {
3726 NDFREE(&nd
, NDF_ONLY_PNBUF
);
3728 VFS_UNLOCK_GIANT(vfslocked
);
3729 if ((error
= vn_start_write(NULL
, &mp
, V_XSLEEP
| PCATCH
)) != 0)
3734 vattr
.va_type
= VDIR
;
3735 FILEDESC_SLOCK(td
->td_proc
->p_fd
);
3736 vattr
.va_mode
= (mode
& ACCESSPERMS
) &~ td
->td_proc
->p_fd
->fd_cmask
;
3737 FILEDESC_SUNLOCK(td
->td_proc
->p_fd
);
3739 error
= mac_vnode_check_create(td
->td_ucred
, nd
.ni_dvp
, &nd
.ni_cnd
,
3744 VOP_LEASE(nd
.ni_dvp
, td
, td
->td_ucred
, LEASE_WRITE
);
3745 error
= VOP_MKDIR(nd
.ni_dvp
, &nd
.ni_vp
, &nd
.ni_cnd
, &vattr
);
3749 NDFREE(&nd
, NDF_ONLY_PNBUF
);
3753 vn_finished_write(mp
);
3754 VFS_UNLOCK_GIANT(vfslocked
);
3759 * Remove a directory file.
3761 #ifndef _SYS_SYSPROTO_H_
3769 struct rmdir_args
/* {
3774 return (kern_rmdir(td
, uap
->path
, UIO_USERSPACE
));
3778 kern_rmdir(struct thread
*td
, char *path
, enum uio_seg pathseg
)
3781 return (kern_rmdirat(td
, AT_FDCWD
, path
, pathseg
));
3785 kern_rmdirat(struct thread
*td
, int fd
, char *path
, enum uio_seg pathseg
)
3790 struct nameidata nd
;
3795 NDINIT_AT(&nd
, DELETE
, LOCKPARENT
| LOCKLEAF
| MPSAFE
| AUDITVNODE1
,
3796 pathseg
, path
, fd
, td
);
3797 if ((error
= namei(&nd
)) != 0)
3799 vfslocked
= NDHASGIANT(&nd
);
3801 if (vp
->v_type
!= VDIR
) {
3806 * No rmdir "." please.
3808 if (nd
.ni_dvp
== vp
) {
3813 * The root of a mounted filesystem cannot be deleted.
3815 if (vp
->v_vflag
& VV_ROOT
) {
3820 error
= mac_vnode_check_unlink(td
->td_ucred
, nd
.ni_dvp
, vp
,
3825 if (vn_start_write(nd
.ni_dvp
, &mp
, V_NOWAIT
) != 0) {
3826 NDFREE(&nd
, NDF_ONLY_PNBUF
);
3828 if (nd
.ni_dvp
== vp
)
3832 VFS_UNLOCK_GIANT(vfslocked
);
3833 if ((error
= vn_start_write(NULL
, &mp
, V_XSLEEP
| PCATCH
)) != 0)
3837 VOP_LEASE(nd
.ni_dvp
, td
, td
->td_ucred
, LEASE_WRITE
);
3838 VOP_LEASE(vp
, td
, td
->td_ucred
, LEASE_WRITE
);
3839 error
= VOP_RMDIR(nd
.ni_dvp
, nd
.ni_vp
, &nd
.ni_cnd
);
3840 vn_finished_write(mp
);
3842 NDFREE(&nd
, NDF_ONLY_PNBUF
);
3844 if (nd
.ni_dvp
== vp
)
3848 VFS_UNLOCK_GIANT(vfslocked
);
3854 * Read a block of directory entries in a filesystem independent format.
3856 #ifndef _SYS_SYSPROTO_H_
3857 struct ogetdirentries_args
{
3865 ogetdirentries(td
, uap
)
3867 register struct ogetdirentries_args
/* {
3876 struct uio auio
, kuio
;
3877 struct iovec aiov
, kiov
;
3878 struct dirent
*dp
, *edp
;
3880 int error
, eofflag
, readcnt
, vfslocked
;
3883 /* XXX arbitrary sanity limit on `count'. */
3884 if (uap
->count
> 64 * 1024)
3886 if ((error
= getvnode(td
->td_proc
->p_fd
, uap
->fd
, &fp
)) != 0)
3888 if ((fp
->f_flag
& FREAD
) == 0) {
3894 vfslocked
= VFS_LOCK_GIANT(vp
->v_mount
);
3895 if (vp
->v_type
!= VDIR
) {
3896 VFS_UNLOCK_GIANT(vfslocked
);
3900 aiov
.iov_base
= uap
->buf
;
3901 aiov
.iov_len
= uap
->count
;
3902 auio
.uio_iov
= &aiov
;
3903 auio
.uio_iovcnt
= 1;
3904 auio
.uio_rw
= UIO_READ
;
3905 auio
.uio_segflg
= UIO_USERSPACE
;
3907 auio
.uio_resid
= uap
->count
;
3908 vn_lock(vp
, LK_EXCLUSIVE
| LK_RETRY
);
3909 loff
= auio
.uio_offset
= fp
->f_offset
;
3911 error
= mac_vnode_check_readdir(td
->td_ucred
, vp
);
3914 VFS_UNLOCK_GIANT(vfslocked
);
3919 # if (BYTE_ORDER != LITTLE_ENDIAN)
3920 if (vp
->v_mount
->mnt_maxsymlinklen
<= 0) {
3921 error
= VOP_READDIR(vp
, &auio
, fp
->f_cred
, &eofflag
,
3923 fp
->f_offset
= auio
.uio_offset
;
3928 kuio
.uio_iov
= &kiov
;
3929 kuio
.uio_segflg
= UIO_SYSSPACE
;
3930 kiov
.iov_len
= uap
->count
;
3931 MALLOC(dirbuf
, caddr_t
, uap
->count
, M_TEMP
, M_WAITOK
);
3932 kiov
.iov_base
= dirbuf
;
3933 error
= VOP_READDIR(vp
, &kuio
, fp
->f_cred
, &eofflag
,
3935 fp
->f_offset
= kuio
.uio_offset
;
3937 readcnt
= uap
->count
- kuio
.uio_resid
;
3938 edp
= (struct dirent
*)&dirbuf
[readcnt
];
3939 for (dp
= (struct dirent
*)dirbuf
; dp
< edp
; ) {
3940 # if (BYTE_ORDER == LITTLE_ENDIAN)
3942 * The expected low byte of
3943 * dp->d_namlen is our dp->d_type.
3944 * The high MBZ byte of dp->d_namlen
3945 * is our dp->d_namlen.
3947 dp
->d_type
= dp
->d_namlen
;
3951 * The dp->d_type is the high byte
3952 * of the expected dp->d_namlen,
3953 * so must be zero'ed.
3957 if (dp
->d_reclen
> 0) {
3958 dp
= (struct dirent
*)
3959 ((char *)dp
+ dp
->d_reclen
);
3966 error
= uiomove(dirbuf
, readcnt
, &auio
);
3968 FREE(dirbuf
, M_TEMP
);
3972 VFS_UNLOCK_GIANT(vfslocked
);
3976 if (uap
->count
== auio
.uio_resid
&&
3977 (vp
->v_vflag
& VV_ROOT
) &&
3978 (vp
->v_mount
->mnt_flag
& MNT_UNION
)) {
3979 struct vnode
*tvp
= vp
;
3980 vp
= vp
->v_mount
->mnt_vnodecovered
;
3986 VFS_UNLOCK_GIANT(vfslocked
);
3990 VFS_UNLOCK_GIANT(vfslocked
);
3991 error
= copyout(&loff
, uap
->basep
, sizeof(long));
3993 td
->td_retval
[0] = uap
->count
- auio
.uio_resid
;
3996 #endif /* COMPAT_43 */
3999 * Read a block of directory entries in a filesystem independent format.
4001 #ifndef _SYS_SYSPROTO_H_
4002 struct getdirentries_args
{
4010 getdirentries(td
, uap
)
4012 register struct getdirentries_args
/* {
4027 AUDIT_ARG(fd
, uap
->fd
);
4028 if ((error
= getvnode(td
->td_proc
->p_fd
, uap
->fd
, &fp
)) != 0)
4030 if ((fp
->f_flag
& FREAD
) == 0) {
4036 vfslocked
= VFS_LOCK_GIANT(vp
->v_mount
);
4037 if (vp
->v_type
!= VDIR
) {
4038 VFS_UNLOCK_GIANT(vfslocked
);
4042 aiov
.iov_base
= uap
->buf
;
4043 aiov
.iov_len
= uap
->count
;
4044 auio
.uio_iov
= &aiov
;
4045 auio
.uio_iovcnt
= 1;
4046 auio
.uio_rw
= UIO_READ
;
4047 auio
.uio_segflg
= UIO_USERSPACE
;
4049 auio
.uio_resid
= uap
->count
;
4050 /* vn_lock(vp, LK_SHARED | LK_RETRY); */
4051 vn_lock(vp
, LK_EXCLUSIVE
| LK_RETRY
);
4052 AUDIT_ARG(vnode
, vp
, ARG_VNODE1
);
4053 loff
= auio
.uio_offset
= fp
->f_offset
;
4055 error
= mac_vnode_check_readdir(td
->td_ucred
, vp
);
4058 error
= VOP_READDIR(vp
, &auio
, fp
->f_cred
, &eofflag
, NULL
,
4060 fp
->f_offset
= auio
.uio_offset
;
4063 VFS_UNLOCK_GIANT(vfslocked
);
4066 if (uap
->count
== auio
.uio_resid
&&
4067 (vp
->v_vflag
& VV_ROOT
) &&
4068 (vp
->v_mount
->mnt_flag
& MNT_UNION
)) {
4069 struct vnode
*tvp
= vp
;
4070 vp
= vp
->v_mount
->mnt_vnodecovered
;
4076 VFS_UNLOCK_GIANT(vfslocked
);
4080 VFS_UNLOCK_GIANT(vfslocked
);
4081 if (uap
->basep
!= NULL
) {
4082 error
= copyout(&loff
, uap
->basep
, sizeof(long));
4084 td
->td_retval
[0] = uap
->count
- auio
.uio_resid
;
4090 #ifndef _SYS_SYSPROTO_H_
4091 struct getdents_args
{
4100 register struct getdents_args
/* {
4106 struct getdirentries_args ap
;
4109 ap
.count
= uap
->count
;
4111 return (getdirentries(td
, &ap
));
4115 * Set the mode mask for creation of filesystem nodes.
4117 #ifndef _SYS_SYSPROTO_H_
4125 struct umask_args
/* {
4129 register struct filedesc
*fdp
;
4131 FILEDESC_XLOCK(td
->td_proc
->p_fd
);
4132 fdp
= td
->td_proc
->p_fd
;
4133 td
->td_retval
[0] = fdp
->fd_cmask
;
4134 fdp
->fd_cmask
= uap
->newmask
& ALLPERMS
;
4135 FILEDESC_XUNLOCK(td
->td_proc
->p_fd
);
4140 * Void all references to file by ripping underlying filesystem away from
4143 #ifndef _SYS_SYSPROTO_H_
4144 struct revoke_args
{
4151 register struct revoke_args
/* {
4158 struct nameidata nd
;
4161 NDINIT(&nd
, LOOKUP
, FOLLOW
| LOCKLEAF
| MPSAFE
| AUDITVNODE1
,
4162 UIO_USERSPACE
, uap
->path
, td
);
4163 if ((error
= namei(&nd
)) != 0)
4165 vfslocked
= NDHASGIANT(&nd
);
4167 NDFREE(&nd
, NDF_ONLY_PNBUF
);
4168 if (vp
->v_type
!= VCHR
) {
4173 error
= mac_vnode_check_revoke(td
->td_ucred
, vp
);
4177 error
= VOP_GETATTR(vp
, &vattr
, td
->td_ucred
);
4180 if (td
->td_ucred
->cr_uid
!= vattr
.va_uid
) {
4181 error
= priv_check(td
, PRIV_VFS_ADMIN
);
4186 VOP_REVOKE(vp
, REVOKEALL
);
4189 VFS_UNLOCK_GIANT(vfslocked
);
4194 * Convert a user file descriptor to a kernel file entry.
4195 * A reference on the file entry is held upon returning.
4198 getvnode(fdp
, fd
, fpp
)
4199 struct filedesc
*fdp
;
4210 FILEDESC_SLOCK(fdp
);
4211 if ((u_int
)fd
>= fdp
->fd_nfiles
||
4212 (fp
= fdp
->fd_ofiles
[fd
]) == NULL
)
4214 else if (fp
->f_vnode
== NULL
) {
4221 FILEDESC_SUNLOCK(fdp
);
4228 * Get an (NFS) file handle.
4230 #ifndef _SYS_SYSPROTO_H_
4231 struct lgetfh_args
{
4239 register struct lgetfh_args
*uap
;
4241 struct nameidata nd
;
4243 register struct vnode
*vp
;
4247 error
= priv_check(td
, PRIV_VFS_GETFH
);
4250 NDINIT(&nd
, LOOKUP
, NOFOLLOW
| LOCKLEAF
| MPSAFE
| AUDITVNODE1
,
4251 UIO_USERSPACE
, uap
->fname
, td
);
4255 vfslocked
= NDHASGIANT(&nd
);
4256 NDFREE(&nd
, NDF_ONLY_PNBUF
);
4258 bzero(&fh
, sizeof(fh
));
4259 fh
.fh_fsid
= vp
->v_mount
->mnt_stat
.f_fsid
;
4260 error
= VOP_VPTOFH(vp
, &fh
.fh_fid
);
4262 VFS_UNLOCK_GIANT(vfslocked
);
4265 error
= copyout(&fh
, uap
->fhp
, sizeof (fh
));
4269 #ifndef _SYS_SYSPROTO_H_
4278 register struct getfh_args
*uap
;
4280 struct nameidata nd
;
4282 register struct vnode
*vp
;
4286 error
= priv_check(td
, PRIV_VFS_GETFH
);
4289 NDINIT(&nd
, LOOKUP
, FOLLOW
| LOCKLEAF
| MPSAFE
| AUDITVNODE1
,
4290 UIO_USERSPACE
, uap
->fname
, td
);
4294 vfslocked
= NDHASGIANT(&nd
);
4295 NDFREE(&nd
, NDF_ONLY_PNBUF
);
4297 bzero(&fh
, sizeof(fh
));
4298 fh
.fh_fsid
= vp
->v_mount
->mnt_stat
.f_fsid
;
4299 error
= VOP_VPTOFH(vp
, &fh
.fh_fid
);
4301 VFS_UNLOCK_GIANT(vfslocked
);
4304 error
= copyout(&fh
, uap
->fhp
, sizeof (fh
));
4309 * syscall for the rpc.lockd to use to translate a NFS file handle into an
4312 * warning: do not remove the priv_check() call or this becomes one giant
4315 #ifndef _SYS_SYSPROTO_H_
4316 struct fhopen_args
{
4317 const struct fhandle
*u_fhp
;
4324 struct fhopen_args
/* {
4325 const struct fhandle *u_fhp;
4329 struct proc
*p
= td
->td_proc
;
4334 struct vattr
*vap
= &vat
;
4337 register struct filedesc
*fdp
= p
->p_fd
;
4338 int fmode
, mode
, error
, type
;
4343 error
= priv_check(td
, PRIV_VFS_FHOPEN
);
4346 fmode
= FFLAGS(uap
->flags
);
4347 /* why not allow a non-read/write open for our lockd? */
4348 if (((fmode
& (FREAD
| FWRITE
)) == 0) || (fmode
& O_CREAT
))
4350 error
= copyin(uap
->u_fhp
, &fhp
, sizeof(fhp
));
4353 /* find the mount point */
4354 mp
= vfs_getvfs(&fhp
.fh_fsid
);
4357 vfslocked
= VFS_LOCK_GIANT(mp
);
4358 /* now give me my vnode, it gets returned to me locked */
4359 error
= VFS_FHTOVP(mp
, &fhp
.fh_fid
, &vp
);
4363 * from now on we have to make sure not
4364 * to forget about the vnode
4365 * any error that causes an abort must vput(vp)
4366 * just set error = err and 'goto bad;'.
4372 if (vp
->v_type
== VLNK
) {
4376 if (vp
->v_type
== VSOCK
) {
4381 if (fmode
& (FWRITE
| O_TRUNC
)) {
4382 if (vp
->v_type
== VDIR
) {
4386 error
= vn_writechk(vp
);
4393 if (fmode
& O_APPEND
)
4396 error
= mac_vnode_check_open(td
->td_ucred
, vp
, mode
);
4401 error
= VOP_ACCESS(vp
, mode
, td
->td_ucred
, td
);
4405 if (fmode
& O_TRUNC
) {
4406 VOP_UNLOCK(vp
, 0); /* XXX */
4407 if ((error
= vn_start_write(NULL
, &mp
, V_WAIT
| PCATCH
)) != 0) {
4411 VOP_LEASE(vp
, td
, td
->td_ucred
, LEASE_WRITE
);
4412 vn_lock(vp
, LK_EXCLUSIVE
| LK_RETRY
); /* XXX */
4415 * We don't yet have fp->f_cred, so use td->td_ucred, which
4418 error
= mac_vnode_check_write(td
->td_ucred
, td
->td_ucred
, vp
);
4423 error
= VOP_SETATTR(vp
, vap
, td
->td_ucred
);
4427 vn_finished_write(mp
);
4431 error
= VOP_OPEN(vp
, fmode
, td
->td_ucred
, td
, NULL
);
4439 * end of vn_open code
4442 if ((error
= falloc(td
, &nfp
, &indx
)) != 0) {
4447 /* An extra reference on `nfp' has been held for us by falloc(). */
4450 finit(nfp
, fmode
& FMASK
, DTYPE_VNODE
, vp
, &vnops
);
4451 if (fmode
& (O_EXLOCK
| O_SHLOCK
)) {
4452 lf
.l_whence
= SEEK_SET
;
4455 if (fmode
& O_EXLOCK
)
4456 lf
.l_type
= F_WRLCK
;
4458 lf
.l_type
= F_RDLCK
;
4460 if ((fmode
& FNONBLOCK
) == 0)
4463 if ((error
= VOP_ADVLOCK(vp
, (caddr_t
)fp
, F_SETLK
, &lf
,
4466 * The lock request failed. Normally close the
4467 * descriptor but handle the case where someone might
4468 * have dup()d or close()d it when we weren't looking.
4470 fdclose(fdp
, fp
, indx
, td
);
4473 * release our private reference
4478 vn_lock(vp
, LK_EXCLUSIVE
| LK_RETRY
);
4479 atomic_set_int(&fp
->f_flag
, FHASLOCK
);
4485 VFS_UNLOCK_GIANT(vfslocked
);
4486 td
->td_retval
[0] = indx
;
4493 VFS_UNLOCK_GIANT(vfslocked
);
4498 * Stat an (NFS) file handle.
4500 #ifndef _SYS_SYSPROTO_H_
4501 struct fhstat_args
{
4502 struct fhandle
*u_fhp
;
4509 register struct fhstat_args
/* {
4510 struct fhandle *u_fhp;
4521 error
= priv_check(td
, PRIV_VFS_FHSTAT
);
4524 error
= copyin(uap
->u_fhp
, &fh
, sizeof(fhandle_t
));
4527 if ((mp
= vfs_getvfs(&fh
.fh_fsid
)) == NULL
)
4529 vfslocked
= VFS_LOCK_GIANT(mp
);
4530 if ((error
= VFS_FHTOVP(mp
, &fh
.fh_fid
, &vp
))) {
4532 VFS_UNLOCK_GIANT(vfslocked
);
4535 error
= vn_stat(vp
, &sb
, td
->td_ucred
, NOCRED
, td
);
4538 VFS_UNLOCK_GIANT(vfslocked
);
4541 error
= copyout(&sb
, uap
->sb
, sizeof(sb
));
4546 * Implement fstatfs() for (NFS) file handles.
4548 #ifndef _SYS_SYSPROTO_H_
4549 struct fhstatfs_args
{
4550 struct fhandle
*u_fhp
;
4557 struct fhstatfs_args
/* {
4558 struct fhandle *u_fhp;
4566 error
= copyin(uap
->u_fhp
, &fh
, sizeof(fhandle_t
));
4569 error
= kern_fhstatfs(td
, fh
, &sf
);
4572 return (copyout(&sf
, uap
->buf
, sizeof(sf
)));
4576 kern_fhstatfs(struct thread
*td
, fhandle_t fh
, struct statfs
*buf
)
4584 error
= priv_check(td
, PRIV_VFS_FHSTATFS
);
4587 if ((mp
= vfs_getvfs(&fh
.fh_fsid
)) == NULL
)
4589 vfslocked
= VFS_LOCK_GIANT(mp
);
4590 error
= VFS_FHTOVP(mp
, &fh
.fh_fid
, &vp
);
4592 VFS_UNLOCK_GIANT(vfslocked
);
4597 error
= prison_canseemount(td
->td_ucred
, mp
);
4601 error
= mac_mount_check_stat(td
->td_ucred
, mp
);
4606 * Set these in case the underlying filesystem fails to do so.
4609 sp
->f_version
= STATFS_VERSION
;
4610 sp
->f_namemax
= NAME_MAX
;
4611 sp
->f_flags
= mp
->mnt_flag
& MNT_VISFLAGMASK
;
4612 error
= VFS_STATFS(mp
, sp
, td
);
4617 VFS_UNLOCK_GIANT(vfslocked
);