2 * Copyright (c) 1995-2002 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
23 * Copyright (c) 1989, 1993
24 * The Regents of the University of California. All rights reserved.
25 * (c) UNIX System Laboratories, Inc.
26 * All or some portions of this file are derived from material licensed
27 * to the University of California by American Telephone and Telegraph
28 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
29 * the permission of UNIX System Laboratories, Inc.
31 * Redistribution and use in source and binary forms, with or without
32 * modification, are permitted provided that the following conditions
34 * 1. Redistributions of source code must retain the above copyright
35 * notice, this list of conditions and the following disclaimer.
36 * 2. Redistributions in binary form must reproduce the above copyright
37 * notice, this list of conditions and the following disclaimer in the
38 * documentation and/or other materials provided with the distribution.
39 * 3. All advertising materials mentioning features or use of this software
40 * must display the following acknowledgement:
41 * This product includes software developed by the University of
42 * California, Berkeley and its contributors.
43 * 4. Neither the name of the University nor the names of its contributors
44 * may be used to endorse or promote products derived from this software
45 * without specific prior written permission.
47 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
48 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
49 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
50 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
51 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
52 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
53 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
54 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
55 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
56 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
59 * @(#)vfs_syscalls.c 8.41 (Berkeley) 6/15/95
62 #include <sys/param.h>
63 #include <sys/systm.h>
64 #include <sys/namei.h>
65 #include <sys/filedesc.h>
66 #include <sys/kernel.h>
69 #include <sys/vnode.h>
70 #include <sys/mount.h>
73 #include <sys/malloc.h>
74 #include <sys/dirent.h>
76 #include <sys/sysctl.h>
78 #include <sys/quota.h>
79 #include <machine/cons.h>
80 #include <miscfs/specfs/specdev.h>
82 struct lock__bsd__ exchangelock
;
85 * The currently logged-in user, for ownership of files/directories whose on-disk
86 * permissions are ignored:
90 static int change_dir
__P((struct nameidata
*ndp
, struct proc
*p
));
91 static void checkdirs
__P((struct vnode
*olddp
));
92 static void enablequotas
__P((struct proc
*p
, struct mount
*mp
));
94 /* counts number of mount and unmount operations */
95 unsigned int vfs_nummntops
=0;
98 * Virtual File System System Calls
102 * Mount a file system.
112 mount(p
, uap
, retval
)
114 register struct mount_args
*uap
;
119 struct vfsconf
*vfsp
;
120 int error
, flag
, err2
;
124 char fstypename
[MFSNAMELEN
];
128 * Get vnode to be covered
130 NDINIT(&nd
, LOOKUP
, FOLLOW
| LOCKLEAF
, UIO_USERSPACE
,
132 if (error
= namei(&nd
))
136 if ((vp
->v_flag
& VROOT
) &&
137 (vp
->v_mount
->mnt_flag
& MNT_ROOTFS
))
138 uap
->flags
|= MNT_UPDATE
;
140 if (uap
->flags
& MNT_UPDATE
) {
141 if ((vp
->v_flag
& VROOT
) == 0) {
148 * We only allow the filesystem to be reloaded if it
149 * is currently mounted read-only.
151 if ((uap
->flags
& MNT_RELOAD
) &&
152 ((mp
->mnt_flag
& MNT_RDONLY
) == 0)) {
154 return (EOPNOTSUPP
); /* Needs translation */
157 uap
->flags
& (MNT_RELOAD
| MNT_FORCE
| MNT_UPDATE
);
159 * Only root, or the user that did the original mount is
160 * permitted to update it.
162 if (mp
->mnt_stat
.f_owner
!= p
->p_ucred
->cr_uid
&&
163 (error
= suser(p
->p_ucred
, &p
->p_acflag
))) {
168 * Do not allow NFS export by non-root users. FOr non-root
169 * users, silently enforce MNT_NOSUID and MNT_NODEV, and
170 * MNT_NOEXEC if mount point is already MNT_NOEXEC.
172 if (p
->p_ucred
->cr_uid
!= 0) {
173 if (uap
->flags
& MNT_EXPORTED
) {
177 uap
->flags
|= MNT_NOSUID
| MNT_NODEV
;
178 if (flag
& MNT_NOEXEC
)
179 uap
->flags
|= MNT_NOEXEC
;
181 if (vfs_busy(mp
, LK_NOWAIT
, 0, p
)) {
185 VOP_UNLOCK(vp
, 0, p
);
189 * If the user is not root, ensure that they own the directory
190 * onto which we are attempting to mount.
192 if ((error
= VOP_GETATTR(vp
, &va
, p
->p_ucred
, p
)) ||
193 (va
.va_uid
!= p
->p_ucred
->cr_uid
&&
194 (error
= suser(p
->p_ucred
, &p
->p_acflag
)))) {
199 * Do not allow NFS export by non-root users. FOr non-root
200 * users, silently enforce MNT_NOSUID and MNT_NODEV, and
201 * MNT_NOEXEC if mount point is already MNT_NOEXEC.
203 if (p
->p_ucred
->cr_uid
!= 0) {
204 if (uap
->flags
& MNT_EXPORTED
) {
208 uap
->flags
|= MNT_NOSUID
| MNT_NODEV
;
209 if (vp
->v_mount
->mnt_flag
& MNT_NOEXEC
)
210 uap
->flags
|= MNT_NOEXEC
;
212 if (error
= vinvalbuf(vp
, V_SAVE
, p
->p_ucred
, p
, 0, 0)) {
216 if (vp
->v_type
!= VDIR
) {
222 * Historically filesystem types were identified by number. If we
223 * get an integer for the filesystem type instead of a string, we
224 * check to see if it matches one of the historic filesystem types.
226 fstypenum
= (u_long
)uap
->type
;
227 if (fstypenum
< maxvfsconf
) {
228 for (vfsp
= vfsconf
; vfsp
; vfsp
= vfsp
->vfc_next
)
229 if (vfsp
->vfc_typenum
== fstypenum
)
235 strncpy(fstypename
, vfsp
->vfc_name
, MFSNAMELEN
);
237 #endif /* COMPAT_43 */
238 if (error
= copyinstr(uap
->type
, fstypename
, MFSNAMELEN
, &dummy
)) {
242 for (vfsp
= vfsconf
; vfsp
; vfsp
= vfsp
->vfc_next
)
243 if (!strcmp(vfsp
->vfc_name
, fstypename
))
249 simple_lock(&vp
->v_interlock
);
250 if (ISSET(vp
->v_flag
, VMOUNT
) && (vp
->v_mountedhere
!= NULL
)) {
251 simple_unlock(&vp
->v_interlock
);
255 SET(vp
->v_flag
, VMOUNT
);
256 simple_unlock(&vp
->v_interlock
);
259 * Allocate and initialize the filesystem.
261 mp
= (struct mount
*)_MALLOC_ZONE((u_long
)sizeof(struct mount
),
263 bzero((char *)mp
, (u_long
)sizeof(struct mount
));
265 /* Initialize the default IO constraints */
266 mp
->mnt_maxreadcnt
= mp
->mnt_maxwritecnt
= MAXPHYS
;
267 mp
->mnt_segreadcnt
= mp
->mnt_segwritecnt
= 32;
269 lockinit(&mp
->mnt_lock
, PVFS
, "vfslock", 0, 0);
270 (void)vfs_busy(mp
, LK_NOWAIT
, 0, p
);
271 mp
->mnt_op
= vfsp
->vfc_vfsops
;
273 vfsp
->vfc_refcount
++;
274 mp
->mnt_stat
.f_type
= vfsp
->vfc_typenum
;
275 mp
->mnt_flag
|= vfsp
->vfc_flags
& MNT_VISFLAGMASK
;
276 strncpy(mp
->mnt_stat
.f_fstypename
, vfsp
->vfc_name
, MFSNAMELEN
);
277 mp
->mnt_vnodecovered
= vp
;
278 mp
->mnt_stat
.f_owner
= p
->p_ucred
->cr_uid
;
279 VOP_UNLOCK(vp
, 0, p
);
283 * Set the mount level flags.
285 if (uap
->flags
& MNT_RDONLY
)
286 mp
->mnt_flag
|= MNT_RDONLY
;
287 else if (mp
->mnt_flag
& MNT_RDONLY
)
288 mp
->mnt_kern_flag
|= MNTK_WANTRDWR
;
289 mp
->mnt_flag
&= ~(MNT_NOSUID
| MNT_NOEXEC
| MNT_NODEV
|
290 MNT_SYNCHRONOUS
| MNT_UNION
| MNT_ASYNC
|
291 MNT_UNKNOWNPERMISSIONS
| MNT_DONTBROWSE
| MNT_AUTOMOUNTED
);
292 mp
->mnt_flag
|= uap
->flags
& (MNT_NOSUID
| MNT_NOEXEC
| MNT_NODEV
|
293 MNT_SYNCHRONOUS
| MNT_UNION
| MNT_ASYNC
|
294 MNT_UNKNOWNPERMISSIONS
| MNT_DONTBROWSE
| MNT_AUTOMOUNTED
);
296 * Mount the filesystem.
298 error
= VFS_MOUNT(mp
, uap
->path
, uap
->data
, &nd
, p
);
299 if (mp
->mnt_flag
& MNT_UPDATE
) {
301 if (mp
->mnt_kern_flag
& MNTK_WANTRDWR
)
302 mp
->mnt_flag
&= ~MNT_RDONLY
;
304 (MNT_UPDATE
| MNT_RELOAD
| MNT_FORCE
);
305 mp
->mnt_kern_flag
&=~ MNTK_WANTRDWR
;
314 /* get the vnode lock */
315 err2
= vn_lock(vp
, LK_EXCLUSIVE
|LK_RETRY
, p
);
318 * Put the new filesystem on the mount list after root.
321 if (!error
&& !err2
) {
322 simple_lock(&vp
->v_interlock
);
323 CLR(vp
->v_flag
, VMOUNT
);
324 vp
->v_mountedhere
=mp
;
325 simple_unlock(&vp
->v_interlock
);
326 simple_lock(&mountlist_slock
);
327 CIRCLEQ_INSERT_TAIL(&mountlist
, mp
, mnt_list
);
328 simple_unlock(&mountlist_slock
);
330 VOP_UNLOCK(vp
, 0, p
);
332 if (error
= VFS_START(mp
, 0, p
))
335 /* increment the operations count */
341 simple_lock(&vp
->v_interlock
);
342 CLR(vp
->v_flag
, VMOUNT
);
343 simple_unlock(&vp
->v_interlock
);
344 mp
->mnt_vfc
->vfc_refcount
--;
346 _FREE_ZONE((caddr_t
)mp
, sizeof (struct mount
), M_MOUNT
);
361 struct nameidata qnd
;
363 char qfpath
[MAXPATHLEN
];
364 char *qfname
= QUOTAFILENAME
;
365 char *qfopsname
= QUOTAOPSNAME
;
366 char *qfextension
[] = INITQFNAMES
;
369 if ((strcmp(mp
->mnt_stat
.f_fstypename
, "hfs") != 0 )
370 && (strcmp( mp
->mnt_stat
.f_fstypename
, "ufs") != 0))
374 * Enable filesystem disk quotas if necessary.
375 * We ignore errors as this should not interfere with final mount
377 for (type
=0; type
< MAXQUOTAS
; type
++) {
378 sprintf(qfpath
, "%s/%s.%s", mp
->mnt_stat
.f_mntonname
, qfopsname
, qfextension
[type
]);
379 NDINIT(&qnd
, LOOKUP
, FOLLOW
, UIO_SYSSPACE
, qfpath
, p
);
380 if (namei(&qnd
) != 0)
381 continue; /* option file to trigger quotas is not present */
383 sprintf(qfpath
, "%s/%s.%s", mp
->mnt_stat
.f_mntonname
, qfname
, qfextension
[type
]);
384 if (vp
->v_tag
== VT_HFS
) {
386 (void)hfs_quotaon(p
, mp
, type
, qfpath
, UIO_SYSSPACE
);
387 } else if (vp
->v_tag
== VT_UFS
) {
389 (void)quotaon(p
, mp
, type
, qfpath
, UIO_SYSSPACE
);
398 * Scan all active processes to see if any of them have a current
399 * or root directory onto which the new filesystem has just been
400 * mounted. If so, replace them with the new mount point.
406 struct filedesc
*fdp
;
411 if (olddp
->v_usecount
== 1)
413 if (VFS_ROOT(olddp
->v_mountedhere
, &newdp
))
414 panic("mount: lost mount");
415 for (p
= allproc
.lh_first
; p
!= 0; p
= p
->p_list
.le_next
) {
417 if (fdp
->fd_cdir
== olddp
) {
420 fdp
->fd_cdir
= newdp
;
423 if (fdp
->fd_rdir
== olddp
) {
426 fdp
->fd_rdir
= newdp
;
430 if (rootvnode
== olddp
) {
440 * Unmount a file system.
442 * Note: unmount takes a path to the vnode mounted on as argument,
443 * not special file (as before).
445 struct unmount_args
{
451 unmount(p
, uap
, retval
)
453 register struct unmount_args
*uap
;
456 register struct vnode
*vp
;
461 NDINIT(&nd
, LOOKUP
, FOLLOW
| LOCKLEAF
, UIO_USERSPACE
,
463 if (error
= namei(&nd
))
469 * Only root, or the user that did the original mount is
470 * permitted to unmount this filesystem.
472 if ((mp
->mnt_stat
.f_owner
!= p
->p_ucred
->cr_uid
) &&
473 (error
= suser(p
->p_ucred
, &p
->p_acflag
))) {
479 * Don't allow unmounting the root file system.
481 if (mp
->mnt_flag
& MNT_ROOTFS
) {
483 return (EBUSY
); /* the root is always busy */
487 * Must be the root of the filesystem
489 if ((vp
->v_flag
& VROOT
) == 0) {
494 return (dounmount(mp
, uap
->flags
, p
));
498 * Do the actual file system unmount.
501 dounmount(mp
, flags
, p
)
502 register struct mount
*mp
;
506 struct vnode
*coveredvp
;
509 simple_lock(&mountlist_slock
);
510 /* XXX post jaguar fix LK_DRAIN - then clean this up */
511 if (mp
->mnt_kern_flag
& MNTK_UNMOUNT
) {
512 simple_unlock(&mountlist_slock
);
513 mp
->mnt_kern_flag
|= MNTK_MWAIT
;
514 if ((error
= tsleep((void *)mp
, PRIBIO
, "dounmount", 0)))
517 * The prior unmount attempt has probably succeeded.
518 * Do not dereference mp here - returning EBUSY is safest.
522 mp
->mnt_kern_flag
|= MNTK_UNMOUNT
;
523 error
= lockmgr(&mp
->mnt_lock
, LK_DRAIN
| LK_INTERLOCK
,
524 &mountlist_slock
, p
);
526 mp
->mnt_kern_flag
&= ~MNTK_UNMOUNT
;
529 mp
->mnt_flag
&=~ MNT_ASYNC
;
530 ubc_umount(mp
); /* release cached vnodes */
531 cache_purgevfs(mp
); /* remove cache entries for this file sys */
532 if (((mp
->mnt_flag
& MNT_RDONLY
) ||
533 (error
= VFS_SYNC(mp
, MNT_WAIT
, p
->p_ucred
, p
)) == 0) ||
535 error
= VFS_UNMOUNT(mp
, flags
, p
);
536 simple_lock(&mountlist_slock
);
538 mp
->mnt_kern_flag
&= ~MNTK_UNMOUNT
;
539 lockmgr(&mp
->mnt_lock
, LK_RELEASE
| LK_INTERLOCK
| LK_REENABLE
,
540 &mountlist_slock
, p
);
544 /* increment the operations count */
547 CIRCLEQ_REMOVE(&mountlist
, mp
, mnt_list
);
548 if ((coveredvp
= mp
->mnt_vnodecovered
) != NULLVP
) {
549 coveredvp
->v_mountedhere
= (struct mount
*)0;
550 simple_unlock(&mountlist_slock
);
552 simple_lock(&mountlist_slock
);
554 mp
->mnt_vfc
->vfc_refcount
--;
555 if (mp
->mnt_vnodelist
.lh_first
!= NULL
) {
556 panic("unmount: dangling vnode");
558 lockmgr(&mp
->mnt_lock
, LK_RELEASE
| LK_INTERLOCK
, &mountlist_slock
, p
);
560 if (mp
->mnt_kern_flag
& MNTK_MWAIT
)
563 _FREE_ZONE((caddr_t
)mp
, sizeof (struct mount
), M_MOUNT
);
568 * Sync each mounted filesystem.
572 struct ctldebug debug0
= { "syncprt", &syncprt
};
578 int print_vmpage_stat
=0;
584 struct sync_args
*uap
;
587 register struct mount
*mp
, *nmp
;
590 simple_lock(&mountlist_slock
);
591 for (mp
= mountlist
.cqh_first
; mp
!= (void *)&mountlist
; mp
= nmp
) {
592 if (vfs_busy(mp
, LK_NOWAIT
, &mountlist_slock
, p
)) {
593 nmp
= mp
->mnt_list
.cqe_next
;
596 if ((mp
->mnt_flag
& MNT_RDONLY
) == 0) {
597 asyncflag
= mp
->mnt_flag
& MNT_ASYNC
;
598 mp
->mnt_flag
&= ~MNT_ASYNC
;
599 VFS_SYNC(mp
, MNT_NOWAIT
, p
->p_ucred
, p
);
601 mp
->mnt_flag
|= MNT_ASYNC
;
603 simple_lock(&mountlist_slock
);
604 nmp
= mp
->mnt_list
.cqe_next
;
607 simple_unlock(&mountlist_slock
);
610 extern void vm_countdirtypages(void);
611 extern unsigned int vp_pagein
, vp_pgodirty
, vp_pgoclean
;
612 extern unsigned int dp_pgins
, dp_pgouts
;
613 if(print_vmpage_stat
) {
614 vm_countdirtypages();
615 printf("VP: %d: %d: %d: %d: %d\n", vp_pgodirty
, vp_pgoclean
, vp_pagein
,
616 dp_pgins
, dp_pgouts
);
622 #endif /* DIAGNOSTIC */
627 * Change filesystem quotas.
629 struct quotactl_args
{
637 quotactl(p
, uap
, retval
)
639 register struct quotactl_args
*uap
;
642 register struct mount
*mp
;
646 NDINIT(&nd
, LOOKUP
, FOLLOW
, UIO_USERSPACE
, uap
->path
, p
);
647 if (error
= namei(&nd
))
649 mp
= nd
.ni_vp
->v_mount
;
651 return (VFS_QUOTACTL(mp
, uap
->cmd
, uap
->uid
,
656 * Get filesystem statistics.
664 statfs(p
, uap
, retval
)
666 register struct statfs_args
*uap
;
669 register struct mount
*mp
;
670 register struct statfs
*sp
;
674 NDINIT(&nd
, LOOKUP
, FOLLOW
, UIO_USERSPACE
, uap
->path
, p
);
675 if (error
= namei(&nd
))
677 mp
= nd
.ni_vp
->v_mount
;
680 if (error
= VFS_STATFS(mp
, sp
, p
))
682 sp
->f_flags
= mp
->mnt_flag
& MNT_VISFLAGMASK
;
683 return (copyout((caddr_t
)sp
, (caddr_t
)uap
->buf
,
684 sizeof(*sp
)-sizeof(sp
->f_reserved3
)-sizeof(sp
->f_reserved4
)));
688 * Get filesystem statistics.
690 struct fstatfs_args
{
696 fstatfs(p
, uap
, retval
)
698 register struct fstatfs_args
*uap
;
703 register struct statfs
*sp
;
706 if (error
= getvnode(p
, uap
->fd
, &fp
))
708 mp
= ((struct vnode
*)fp
->f_data
)->v_mount
;
712 if (error
= VFS_STATFS(mp
, sp
, p
))
714 sp
->f_flags
= mp
->mnt_flag
& MNT_VISFLAGMASK
;
715 return (copyout((caddr_t
)sp
, (caddr_t
)uap
->buf
,
716 sizeof(*sp
)-sizeof(sp
->f_reserved3
)-sizeof(sp
->f_reserved4
)));
720 * Get statistics on all filesystems.
722 struct getfsstat_args
{
728 getfsstat(p
, uap
, retval
)
730 register struct getfsstat_args
*uap
;
733 register struct mount
*mp
, *nmp
;
734 register struct statfs
*sp
;
736 long count
, maxcount
, error
;
738 maxcount
= uap
->bufsize
/ sizeof(struct statfs
);
739 sfsp
= (caddr_t
)uap
->buf
;
741 simple_lock(&mountlist_slock
);
742 for (mp
= mountlist
.cqh_first
; mp
!= (void *)&mountlist
; mp
= nmp
) {
743 if (vfs_busy(mp
, LK_NOWAIT
, &mountlist_slock
, p
)) {
744 nmp
= mp
->mnt_list
.cqe_next
;
747 if (sfsp
&& count
< maxcount
) {
750 * If MNT_NOWAIT is specified, do not refresh the
751 * fsstat cache. MNT_WAIT overrides MNT_NOWAIT.
753 if (((uap
->flags
& MNT_NOWAIT
) == 0 ||
754 (uap
->flags
& MNT_WAIT
)) &&
755 (error
= VFS_STATFS(mp
, sp
, p
))) {
756 simple_lock(&mountlist_slock
);
757 nmp
= mp
->mnt_list
.cqe_next
;
761 sp
->f_flags
= mp
->mnt_flag
& MNT_VISFLAGMASK
;
762 if (error
= copyout((caddr_t
)sp
, sfsp
, sizeof(*sp
)))
767 simple_lock(&mountlist_slock
);
768 nmp
= mp
->mnt_list
.cqe_next
;
771 simple_unlock(&mountlist_slock
);
772 if (sfsp
&& count
> maxcount
)
780 ogetfsstat(p
, uap
, retval
)
782 register struct getfsstat_args
*uap
;
785 register struct mount
*mp
, *nmp
;
786 register struct statfs
*sp
;
788 long count
, maxcount
, error
;
790 maxcount
= uap
->bufsize
/ (sizeof(struct statfs
) - sizeof(sp
->f_reserved4
));
791 sfsp
= (caddr_t
)uap
->buf
;
793 simple_lock(&mountlist_slock
);
794 for (mp
= mountlist
.cqh_first
; mp
!= (void *)&mountlist
; mp
= nmp
) {
795 if (vfs_busy(mp
, LK_NOWAIT
, &mountlist_slock
, p
)) {
796 nmp
= mp
->mnt_list
.cqe_next
;
799 if (sfsp
&& count
< maxcount
) {
802 * If MNT_NOWAIT is specified, do not refresh the
803 * fsstat cache. MNT_WAIT overrides MNT_NOWAIT.
805 if (((uap
->flags
& MNT_NOWAIT
) == 0 ||
806 (uap
->flags
& MNT_WAIT
)) &&
807 (error
= VFS_STATFS(mp
, sp
, p
))) {
808 simple_lock(&mountlist_slock
);
809 nmp
= mp
->mnt_list
.cqe_next
;
813 sp
->f_flags
= mp
->mnt_flag
& MNT_VISFLAGMASK
;
814 error
= copyout((caddr_t
)sp
, sfsp
,
815 sizeof(*sp
) - sizeof(sp
->f_reserved3
) - sizeof(sp
->f_reserved4
));
818 sfsp
+= sizeof(*sp
) - sizeof(sp
->f_reserved4
);
821 simple_lock(&mountlist_slock
);
822 nmp
= mp
->mnt_list
.cqe_next
;
825 simple_unlock(&mountlist_slock
);
826 if (sfsp
&& count
> maxcount
)
835 * Change current working directory to a given file descriptor.
842 fchdir(p
, uap
, retval
)
844 struct fchdir_args
*uap
;
847 register struct filedesc
*fdp
= p
->p_fd
;
848 struct vnode
*vp
, *tdp
, *tvp
;
853 if (error
= getvnode(p
, uap
->fd
, &fp
))
855 vp
= (struct vnode
*)fp
->f_data
;
857 vn_lock(vp
, LK_EXCLUSIVE
| LK_RETRY
, p
);
858 if (vp
->v_type
!= VDIR
)
861 error
= VOP_ACCESS(vp
, VEXEC
, p
->p_ucred
, p
);
862 while (!error
&& (mp
= vp
->v_mountedhere
) != NULL
) {
863 if (vfs_busy(mp
, 0, 0, p
))
865 error
= VFS_ROOT(mp
, &tdp
);
876 VOP_UNLOCK(vp
, 0, p
);
884 * Change current working directory (``.'').
891 chdir(p
, uap
, retval
)
893 struct chdir_args
*uap
;
896 register struct filedesc
*fdp
= p
->p_fd
;
901 NDINIT(&nd
, LOOKUP
, FOLLOW
| LOCKLEAF
, UIO_USERSPACE
,
903 if (error
= change_dir(&nd
, p
))
906 fdp
->fd_cdir
= nd
.ni_vp
;
912 * Change notion of root (``/'') directory.
919 chroot(p
, uap
, retval
)
921 struct chroot_args
*uap
;
924 register struct filedesc
*fdp
= p
->p_fd
;
927 boolean_t shared_regions_active
;
930 if (error
= suser(p
->p_ucred
, &p
->p_acflag
))
933 NDINIT(&nd
, LOOKUP
, FOLLOW
| LOCKLEAF
, UIO_USERSPACE
,
935 if (error
= change_dir(&nd
, p
))
938 if(p
->p_flag
& P_NOSHLIB
) {
939 shared_regions_active
= FALSE
;
941 shared_regions_active
= TRUE
;
944 if(error
= clone_system_shared_regions(shared_regions_active
)) {
950 fdp
->fd_rdir
= nd
.ni_vp
;
957 * Common routine for chroot and chdir.
961 register struct nameidata
*ndp
;
967 if (error
= namei(ndp
))
970 if (vp
->v_type
!= VDIR
)
973 error
= VOP_ACCESS(vp
, VEXEC
, p
->p_ucred
, p
);
977 VOP_UNLOCK(vp
, 0, p
);
982 * Check permissions, allocate an open file structure,
983 * and call the device open routine if any.
993 register struct open_args
*uap
;
996 register struct filedesc
*fdp
= p
->p_fd
;
997 register struct file
*fp
;
998 register struct vnode
*vp
;
999 int flags
, cmode
, oflags
;
1001 int type
, indx
, error
;
1003 struct nameidata nd
;
1004 extern struct fileops vnops
;
1006 oflags
= uap
->flags
;
1007 if ((oflags
& O_ACCMODE
) == O_ACCMODE
)
1009 flags
= FFLAGS(uap
->flags
);
1010 if (error
= falloc(p
, &nfp
, &indx
))
1013 cmode
= ((uap
->mode
&~ fdp
->fd_cmask
) & ALLPERMS
) &~ S_ISTXT
;
1014 NDINIT(&nd
, LOOKUP
, FOLLOW
, UIO_USERSPACE
, uap
->path
, p
);
1015 p
->p_dupfd
= -indx
- 1; /* XXX check for fdopen */
1016 if (error
= vn_open(&nd
, flags
, cmode
)) {
1018 if ((error
== ENODEV
|| error
== ENXIO
) &&
1019 p
->p_dupfd
>= 0 && /* XXX from fdopen */
1021 dupfdopen(fdp
, indx
, p
->p_dupfd
, flags
, error
)) == 0) {
1025 if (error
== ERESTART
)
1032 fp
->f_flag
= flags
& FMASK
;
1033 fp
->f_type
= DTYPE_VNODE
;
1035 fp
->f_data
= (caddr_t
)vp
;
1036 if (flags
& (O_EXLOCK
| O_SHLOCK
)) {
1037 lf
.l_whence
= SEEK_SET
;
1040 if (flags
& O_EXLOCK
)
1041 lf
.l_type
= F_WRLCK
;
1043 lf
.l_type
= F_RDLCK
;
1045 if ((flags
& FNONBLOCK
) == 0)
1047 VOP_UNLOCK(vp
, 0, p
);
1048 if (error
= VOP_ADVLOCK(vp
, (caddr_t
)fp
, F_SETLK
, &lf
, type
)) {
1049 (void) vn_close(vp
, fp
->f_flag
, fp
->f_cred
, p
);
1054 vn_lock(vp
, LK_EXCLUSIVE
| LK_RETRY
, p
);
1055 fp
->f_flag
|= FHASLOCK
;
1057 VOP_UNLOCK(vp
, 0, p
);
1058 *fdflags(p
, indx
) &= ~UF_RESERVED
;
1067 struct ocreat_args
{
1072 ocreat(p
, uap
, retval
)
1074 register struct ocreat_args
*uap
;
1077 struct open_args nuap
;
1079 nuap
.path
= uap
->path
;
1080 nuap
.mode
= uap
->mode
;
1081 nuap
.flags
= O_WRONLY
| O_CREAT
| O_TRUNC
;
1082 return (open(p
, &nuap
, retval
));
1084 #endif /* COMPAT_43 */
1087 * Create a special file.
1096 mknod(p
, uap
, retval
)
1098 register struct mknod_args
*uap
;
1101 register struct vnode
*vp
;
1105 struct nameidata nd
;
1107 if (error
= suser(p
->p_ucred
, &p
->p_acflag
))
1110 NDINIT(&nd
, CREATE
, LOCKPARENT
, UIO_USERSPACE
, uap
->path
, p
);
1111 if (error
= namei(&nd
))
1118 vattr
.va_mode
= (uap
->mode
& ALLPERMS
) &~ p
->p_fd
->fd_cmask
;
1119 vattr
.va_rdev
= uap
->dev
;
1122 switch (uap
->mode
& S_IFMT
) {
1123 case S_IFMT
: /* used by badsect to flag bad sectors */
1124 vattr
.va_type
= VBAD
;
1127 vattr
.va_type
= VCHR
;
1130 vattr
.va_type
= VBLK
;
1141 VOP_LEASE(nd
.ni_dvp
, p
, p
->p_ucred
, LEASE_WRITE
);
1143 error
= VOP_WHITEOUT(nd
.ni_dvp
, &nd
.ni_cnd
, CREATE
);
1145 VOP_ABORTOP(nd
.ni_dvp
, &nd
.ni_cnd
);
1148 error
= VOP_MKNOD(nd
.ni_dvp
, &nd
.ni_vp
,
1149 &nd
.ni_cnd
, &vattr
);
1152 VOP_ABORTOP(nd
.ni_dvp
, &nd
.ni_cnd
);
1153 if (nd
.ni_dvp
== vp
)
1164 * Create a named pipe.
1166 struct mkfifo_args
{
1172 mkfifo(p
, uap
, retval
)
1174 register struct mkfifo_args
*uap
;
1179 struct nameidata nd
;
1182 return (EOPNOTSUPP
);
1185 NDINIT(&nd
, CREATE
, LOCKPARENT
, UIO_USERSPACE
, uap
->path
, p
);
1186 if (error
= namei(&nd
))
1188 if (nd
.ni_vp
!= NULL
) {
1189 VOP_ABORTOP(nd
.ni_dvp
, &nd
.ni_cnd
);
1190 if (nd
.ni_dvp
== nd
.ni_vp
)
1198 vattr
.va_type
= VFIFO
;
1199 vattr
.va_mode
= (uap
->mode
& ALLPERMS
) &~ p
->p_fd
->fd_cmask
;
1200 VOP_LEASE(nd
.ni_dvp
, p
, p
->p_ucred
, LEASE_WRITE
);
1201 return (VOP_MKNOD(nd
.ni_dvp
, &nd
.ni_vp
, &nd
.ni_cnd
, &vattr
));
1206 * Make a hard file link.
1214 link(p
, uap
, retval
)
1216 register struct link_args
*uap
;
1219 register struct vnode
*vp
;
1220 struct nameidata nd
;
1224 NDINIT(&nd
, LOOKUP
, FOLLOW
, UIO_USERSPACE
, uap
->path
, p
);
1225 if (error
= namei(&nd
))
1228 if (vp
->v_type
== VDIR
)
1229 error
= EPERM
; /* POSIX */
1231 nd
.ni_cnd
.cn_nameiop
= CREATE
;
1232 nd
.ni_cnd
.cn_flags
= LOCKPARENT
;
1233 nd
.ni_dirp
= uap
->link
;
1234 if ((error
= namei(&nd
)) == 0) {
1235 if (nd
.ni_vp
!= NULL
)
1238 VOP_LEASE(nd
.ni_dvp
, p
, p
->p_ucred
,
1240 VOP_LEASE(vp
, p
, p
->p_ucred
, LEASE_WRITE
);
1241 error
= VOP_LINK(vp
, nd
.ni_dvp
, &nd
.ni_cnd
);
1243 VOP_ABORTOP(nd
.ni_dvp
, &nd
.ni_cnd
);
1244 if (nd
.ni_dvp
== nd
.ni_vp
)
1258 * Make a symbolic link.
1260 struct symlink_args
{
1266 symlink(p
, uap
, retval
)
1268 register struct symlink_args
*uap
;
1274 struct nameidata nd
;
1276 MALLOC_ZONE(path
, char *, MAXPATHLEN
, M_NAMEI
, M_WAITOK
);
1277 if (error
= copyinstr(uap
->path
, path
, MAXPATHLEN
, &dummy
))
1280 NDINIT(&nd
, CREATE
, LOCKPARENT
, UIO_USERSPACE
, uap
->link
, p
);
1281 if (error
= namei(&nd
))
1284 VOP_ABORTOP(nd
.ni_dvp
, &nd
.ni_cnd
);
1285 if (nd
.ni_dvp
== nd
.ni_vp
)
1294 vattr
.va_mode
= ACCESSPERMS
&~ p
->p_fd
->fd_cmask
;
1295 VOP_LEASE(nd
.ni_dvp
, p
, p
->p_ucred
, LEASE_WRITE
);
1296 error
= VOP_SYMLINK(nd
.ni_dvp
, &nd
.ni_vp
, &nd
.ni_cnd
, &vattr
, path
);
1298 FREE_ZONE(path
, MAXPATHLEN
, M_NAMEI
);
1303 * Delete a whiteout from the filesystem.
1305 struct undelete_args
{
1310 undelete(p
, uap
, retval
)
1312 register struct undelete_args
*uap
;
1316 struct nameidata nd
;
1319 NDINIT(&nd
, DELETE
, LOCKPARENT
|DOWHITEOUT
, UIO_USERSPACE
,
1325 if (nd
.ni_vp
!= NULLVP
|| !(nd
.ni_cnd
.cn_flags
& ISWHITEOUT
)) {
1326 VOP_ABORTOP(nd
.ni_dvp
, &nd
.ni_cnd
);
1327 if (nd
.ni_dvp
== nd
.ni_vp
)
1336 VOP_LEASE(nd
.ni_dvp
, p
, p
->p_ucred
, LEASE_WRITE
);
1337 if (error
= VOP_WHITEOUT(nd
.ni_dvp
, &nd
.ni_cnd
, DELETE
))
1338 VOP_ABORTOP(nd
.ni_dvp
, &nd
.ni_cnd
);
1344 * Delete a name from the filesystem.
1346 struct unlink_args
{
1351 _unlink(p
, uap
, retval
, nodelbusy
)
1353 struct unlink_args
*uap
;
1357 register struct vnode
*vp
;
1359 struct nameidata nd
;
1362 NDINIT(&nd
, DELETE
, LOCKPARENT
, UIO_USERSPACE
, uap
->path
, p
);
1363 /* with Carbon semantics, busy files cannot be deleted */
1365 nd
.ni_cnd
.cn_flags
|= NODELETEBUSY
;
1366 if (error
= namei(&nd
))
1369 VOP_LEASE(vp
, p
, p
->p_ucred
, LEASE_WRITE
);
1370 vn_lock(vp
, LK_EXCLUSIVE
| LK_RETRY
, p
);
1372 if (vp
->v_type
== VDIR
)
1373 error
= EPERM
; /* POSIX */
1376 * The root of a mounted filesystem cannot be deleted.
1378 * XXX: can this only be a VDIR case?
1380 if (vp
->v_flag
& VROOT
)
1385 VOP_LEASE(nd
.ni_dvp
, p
, p
->p_ucred
, LEASE_WRITE
);
1386 error
= VOP_REMOVE(nd
.ni_dvp
, nd
.ni_vp
, &nd
.ni_cnd
);
1388 VOP_ABORTOP(nd
.ni_dvp
, &nd
.ni_cnd
);
1389 if (nd
.ni_dvp
== vp
)
1400 * Delete a name from the filesystem using POSIX semantics.
1403 unlink(p
, uap
, retval
)
1405 struct unlink_args
*uap
;
1408 return _unlink(p
, uap
, retval
, 0);
1412 * Delete a name from the filesystem using Carbon semantics.
1415 delete(p
, uap
, retval
)
1417 struct unlink_args
*uap
;
1420 return _unlink(p
, uap
, retval
, 1);
1424 * Reposition read/write file offset.
1428 #ifdef DOUBLE_ALIGN_PARAMS
1435 lseek(p
, uap
, retval
)
1437 register struct lseek_args
*uap
;
1440 struct ucred
*cred
= p
->p_ucred
;
1445 if (error
= fdgetf(p
, uap
->fd
, &fp
))
1447 if (fp
->f_type
!= DTYPE_VNODE
)
1449 switch (uap
->whence
) {
1451 fp
->f_offset
+= uap
->offset
;
1455 VOP_GETATTR((struct vnode
*)fp
->f_data
, &vattr
, cred
, p
))
1457 fp
->f_offset
= uap
->offset
+ vattr
.va_size
;
1460 fp
->f_offset
= uap
->offset
;
1465 *(off_t
*)retval
= fp
->f_offset
;
1471 * Reposition read/write file offset.
1473 struct olseek_args
{
1479 olseek(p
, uap
, retval
)
1481 register struct olseek_args
*uap
;
1484 struct lseek_args
/* {
1486 #ifdef DOUBLE_ALIGN_PARAMS
1487 syscallarg(int) pad;
1489 syscallarg(off_t) offset;
1490 syscallarg(int) whence;
1496 nuap
.offset
= uap
->offset
;
1497 nuap
.whence
= uap
->whence
;
1498 error
= lseek(p
, &nuap
, &qret
);
1499 *(long *)retval
= qret
;
1502 #endif /* COMPAT_43 */
1505 * Check access permissions.
1507 struct access_args
{
1512 access(p
, uap
, retval
)
1514 register struct access_args
*uap
;
1517 register struct ucred
*cred
= p
->p_ucred
;
1518 register struct vnode
*vp
;
1519 int error
, flags
, t_gid
, t_uid
;
1520 struct nameidata nd
;
1522 t_uid
= cred
->cr_uid
;
1523 t_gid
= cred
->cr_groups
[0];
1524 cred
->cr_uid
= p
->p_cred
->p_ruid
;
1525 cred
->cr_groups
[0] = p
->p_cred
->p_rgid
;
1526 NDINIT(&nd
, LOOKUP
, FOLLOW
| LOCKLEAF
, UIO_USERSPACE
,
1528 if (error
= namei(&nd
))
1532 /* Flags == 0 means only check for existence. */
1535 if (uap
->flags
& R_OK
)
1537 if (uap
->flags
& W_OK
)
1539 if (uap
->flags
& X_OK
)
1541 if ((flags
& VWRITE
) == 0 || (error
= vn_writechk(vp
)) == 0)
1542 error
= VOP_ACCESS(vp
, flags
, cred
, p
);
1546 cred
->cr_uid
= t_uid
;
1547 cred
->cr_groups
[0] = t_gid
;
1553 * Get file status; this version follows links.
1561 ostat(p
, uap
, retval
)
1563 register struct ostat_args
*uap
;
1569 struct nameidata nd
;
1571 NDINIT(&nd
, LOOKUP
, FOLLOW
| LOCKLEAF
, UIO_USERSPACE
,
1573 if (error
= namei(&nd
))
1575 error
= vn_stat(nd
.ni_vp
, &sb
, p
);
1580 error
= copyout((caddr_t
)&osb
, (caddr_t
)uap
->ub
, sizeof (osb
));
1585 * Get file status; this version does not follow links.
1587 struct olstat_args
{
1593 olstat(p
, uap
, retval
)
1595 register struct olstat_args
*uap
;
1598 struct vnode
*vp
, *dvp
;
1599 struct stat sb
, sb1
;
1602 struct nameidata nd
;
1604 NDINIT(&nd
, LOOKUP
, NOFOLLOW
| LOCKLEAF
| LOCKPARENT
, UIO_USERSPACE
,
1606 if (error
= namei(&nd
))
1609 * For symbolic links, always return the attributes of its
1610 * containing directory, except for mode, size, and links.
1614 if (vp
->v_type
!= VLNK
) {
1619 error
= vn_stat(vp
, &sb
, p
);
1624 error
= vn_stat(dvp
, &sb
, p
);
1630 error
= vn_stat(vp
, &sb1
, p
);
1634 sb
.st_mode
&= ~S_IFDIR
;
1635 sb
.st_mode
|= S_IFLNK
;
1636 sb
.st_nlink
= sb1
.st_nlink
;
1637 sb
.st_size
= sb1
.st_size
;
1638 sb
.st_blocks
= sb1
.st_blocks
;
1641 error
= copyout((caddr_t
)&osb
, (caddr_t
)uap
->ub
, sizeof (osb
));
1646 * Convert from an old to a new stat structure.
1654 ost
->st_dev
= st
->st_dev
;
1655 ost
->st_ino
= st
->st_ino
;
1656 ost
->st_mode
= st
->st_mode
;
1657 ost
->st_nlink
= st
->st_nlink
;
1658 ost
->st_uid
= st
->st_uid
;
1659 ost
->st_gid
= st
->st_gid
;
1660 ost
->st_rdev
= st
->st_rdev
;
1661 if (st
->st_size
< (quad_t
)1 << 32)
1662 ost
->st_size
= st
->st_size
;
1665 ost
->st_atime
= st
->st_atime
;
1666 ost
->st_mtime
= st
->st_mtime
;
1667 ost
->st_ctime
= st
->st_ctime
;
1668 ost
->st_blksize
= st
->st_blksize
;
1669 ost
->st_blocks
= st
->st_blocks
;
1670 ost
->st_flags
= st
->st_flags
;
1671 ost
->st_gen
= st
->st_gen
;
1673 #endif /* COMPAT_43 */
1676 * Get file status; this version follows links.
1684 stat(p
, uap
, retval
)
1686 register struct stat_args
*uap
;
1691 struct nameidata nd
;
1693 NDINIT(&nd
, LOOKUP
, FOLLOW
| LOCKLEAF
, UIO_USERSPACE
,
1695 if (error
= namei(&nd
))
1697 error
= vn_stat(nd
.ni_vp
, &sb
, p
);
1701 error
= copyout((caddr_t
)&sb
, (caddr_t
)uap
->ub
, sizeof (sb
));
1706 * Get file status; this version does not follow links.
1714 lstat(p
, uap
, retval
)
1716 register struct lstat_args
*uap
;
1720 struct vnode
*vp
, *dvp
;
1721 struct stat sb
, sb1
;
1722 struct nameidata nd
;
1724 NDINIT(&nd
, LOOKUP
, NOFOLLOW
| LOCKLEAF
| LOCKPARENT
, UIO_USERSPACE
,
1726 if (error
= namei(&nd
))
1729 * For symbolic links, always return the attributes of its containing
1730 * directory, except for mode, size, inode number, and links.
1734 if ((vp
->v_type
!= VLNK
) || ((vp
->v_type
== VLNK
) && (vp
->v_tag
== VT_NFS
))) {
1739 error
= vn_stat(vp
, &sb
, p
);
1743 if (vp
->v_type
== VLNK
)
1744 sb
.st_mode
|= S_IFLNK
;
1746 error
= vn_stat(dvp
, &sb
, p
);
1752 error
= vn_stat(vp
, &sb1
, p
);
1756 sb
.st_mode
&= ~S_IFDIR
;
1757 sb
.st_mode
|= S_IFLNK
;
1758 sb
.st_nlink
= sb1
.st_nlink
;
1759 sb
.st_size
= sb1
.st_size
;
1760 sb
.st_blocks
= sb1
.st_blocks
;
1761 sb
.st_ino
= sb1
.st_ino
;
1763 error
= copyout((caddr_t
)&sb
, (caddr_t
)uap
->ub
, sizeof (sb
));
1768 * Get configurable pathname variables.
1770 struct pathconf_args
{
1776 pathconf(p
, uap
, retval
)
1778 register struct pathconf_args
*uap
;
1782 struct nameidata nd
;
1784 NDINIT(&nd
, LOOKUP
, FOLLOW
| LOCKLEAF
, UIO_USERSPACE
,
1786 if (error
= namei(&nd
))
1788 error
= VOP_PATHCONF(nd
.ni_vp
, uap
->name
, retval
);
1794 * Return target name of a symbolic link.
1796 struct readlink_args
{
1803 readlink(p
, uap
, retval
)
1805 register struct readlink_args
*uap
;
1808 register struct vnode
*vp
;
1812 struct nameidata nd
;
1814 NDINIT(&nd
, LOOKUP
, NOFOLLOW
| LOCKLEAF
, UIO_USERSPACE
,
1816 if (error
= namei(&nd
))
1819 if (vp
->v_type
!= VLNK
)
1822 aiov
.iov_base
= uap
->buf
;
1823 aiov
.iov_len
= uap
->count
;
1824 auio
.uio_iov
= &aiov
;
1825 auio
.uio_iovcnt
= 1;
1826 auio
.uio_offset
= 0;
1827 auio
.uio_rw
= UIO_READ
;
1828 auio
.uio_segflg
= UIO_USERSPACE
;
1830 auio
.uio_resid
= uap
->count
;
1831 error
= VOP_READLINK(vp
, &auio
, p
->p_ucred
);
1834 *retval
= uap
->count
- auio
.uio_resid
;
1839 * Change flags of a file given a path name.
1841 struct chflags_args
{
1847 chflags(p
, uap
, retval
)
1849 register struct chflags_args
*uap
;
1852 register struct vnode
*vp
;
1855 struct nameidata nd
;
1857 NDINIT(&nd
, LOOKUP
, FOLLOW
, UIO_USERSPACE
, uap
->path
, p
);
1858 if (error
= namei(&nd
))
1861 VOP_LEASE(vp
, p
, p
->p_ucred
, LEASE_WRITE
);
1862 vn_lock(vp
, LK_EXCLUSIVE
| LK_RETRY
, p
);
1864 vattr
.va_flags
= uap
->flags
;
1865 error
= VOP_SETATTR(vp
, &vattr
, p
->p_ucred
, p
);
1871 * Change flags of a file given a file descriptor.
1873 struct fchflags_args
{
1879 fchflags(p
, uap
, retval
)
1881 register struct fchflags_args
*uap
;
1889 if (error
= getvnode(p
, uap
->fd
, &fp
))
1891 vp
= (struct vnode
*)fp
->f_data
;
1892 VOP_LEASE(vp
, p
, p
->p_ucred
, LEASE_WRITE
);
1893 vn_lock(vp
, LK_EXCLUSIVE
| LK_RETRY
, p
);
1895 vattr
.va_flags
= uap
->flags
;
1896 error
= VOP_SETATTR(vp
, &vattr
, p
->p_ucred
, p
);
1897 VOP_UNLOCK(vp
, 0, p
);
1902 * Change mode of a file given path name.
1910 chmod(p
, uap
, retval
)
1912 register struct chmod_args
*uap
;
1915 register struct vnode
*vp
;
1918 struct nameidata nd
;
1920 NDINIT(&nd
, LOOKUP
, FOLLOW
, UIO_USERSPACE
, uap
->path
, p
);
1921 if (error
= namei(&nd
))
1924 VOP_LEASE(vp
, p
, p
->p_ucred
, LEASE_WRITE
);
1925 vn_lock(vp
, LK_EXCLUSIVE
| LK_RETRY
, p
);
1927 vattr
.va_mode
= uap
->mode
& ALLPERMS
;
1928 error
= VOP_SETATTR(vp
, &vattr
, p
->p_ucred
, p
);
1934 * Change mode of a file given a file descriptor.
1936 struct fchmod_args
{
1942 fchmod(p
, uap
, retval
)
1944 register struct fchmod_args
*uap
;
1952 if (error
= getvnode(p
, uap
->fd
, &fp
))
1954 vp
= (struct vnode
*)fp
->f_data
;
1955 VOP_LEASE(vp
, p
, p
->p_ucred
, LEASE_WRITE
);
1956 vn_lock(vp
, LK_EXCLUSIVE
| LK_RETRY
, p
);
1958 vattr
.va_mode
= uap
->mode
& ALLPERMS
;
1959 error
= VOP_SETATTR(vp
, &vattr
, p
->p_ucred
, p
);
1960 VOP_UNLOCK(vp
, 0, p
);
1965 * Set ownership given a path name.
1974 chown(p
, uap
, retval
)
1976 register struct chown_args
*uap
;
1979 register struct vnode
*vp
;
1982 struct nameidata nd
;
1984 NDINIT(&nd
, LOOKUP
, FOLLOW
, UIO_USERSPACE
, uap
->path
, p
);
1985 if (error
= namei(&nd
))
1990 * XXX A TEMPORARY HACK FOR NOW: Try to track console_user
1991 * by looking for chown() calls on /dev/console from a console process.
1993 if ((vp
) && (vp
->v_specinfo
) &&
1994 (major(vp
->v_specinfo
->si_rdev
) == CONSMAJOR
) &&
1995 (minor(vp
->v_specinfo
->si_rdev
) == 0)) {
1996 console_user
= uap
->uid
;
1999 VOP_LEASE(vp
, p
, p
->p_ucred
, LEASE_WRITE
);
2000 vn_lock(vp
, LK_EXCLUSIVE
| LK_RETRY
, p
);
2002 vattr
.va_uid
= uap
->uid
;
2003 vattr
.va_gid
= uap
->gid
;
2004 error
= VOP_SETATTR(vp
, &vattr
, p
->p_ucred
, p
);
2010 * Set ownership given a file descriptor.
2012 struct fchown_args
{
2019 fchown(p
, uap
, retval
)
2021 register struct fchown_args
*uap
;
2029 if (error
= getvnode(p
, uap
->fd
, &fp
))
2031 vp
= (struct vnode
*)fp
->f_data
;
2032 VOP_LEASE(vp
, p
, p
->p_ucred
, LEASE_WRITE
);
2033 vn_lock(vp
, LK_EXCLUSIVE
| LK_RETRY
, p
);
2035 vattr
.va_uid
= uap
->uid
;
2036 vattr
.va_gid
= uap
->gid
;
2037 error
= VOP_SETATTR(vp
, &vattr
, p
->p_ucred
, p
);
2038 VOP_UNLOCK(vp
, 0, p
);
2043 getutimes(usrtvp
, tsp
)
2044 const struct timeval
*usrtvp
;
2045 struct timespec
*tsp
;
2047 struct timeval tv
[2];
2050 if (usrtvp
== NULL
) {
2052 TIMEVAL_TO_TIMESPEC(&tv
[0], &tsp
[0]);
2055 if ((error
= copyin(usrtvp
, tv
, sizeof (tv
))) != 0)
2057 TIMEVAL_TO_TIMESPEC(&tv
[0], &tsp
[0]);
2058 TIMEVAL_TO_TIMESPEC(&tv
[1], &tsp
[1]);
2064 setutimes(p
, vp
, ts
, nullflag
)
2067 const struct timespec
*ts
;
2073 VOP_LEASE(vp
, p
, p
->p_ucred
, LEASE_WRITE
);
2074 error
= vn_lock(vp
, LK_EXCLUSIVE
| LK_RETRY
, p
);
2078 vattr
.va_atime
= ts
[0];
2079 vattr
.va_mtime
= ts
[1];
2081 vattr
.va_vaflags
|= VA_UTIMES_NULL
;
2082 error
= VOP_SETATTR(vp
, &vattr
, p
->p_ucred
, p
);
2083 VOP_UNLOCK(vp
, 0, p
);
2089 * Set the access and modification times of a file.
2091 struct utimes_args
{
2093 struct timeval
*tptr
;
2097 utimes(p
, uap
, retval
)
2099 register struct utimes_args
*uap
;
2102 struct timespec ts
[2];
2103 struct timeval
*usrtvp
;
2105 struct nameidata nd
;
2108 if ((error
= getutimes(usrtvp
, ts
)) != 0)
2110 NDINIT(&nd
, LOOKUP
, FOLLOW
, UIO_USERSPACE
, uap
->path
, p
);
2111 if ((error
= namei(&nd
)) != 0)
2113 error
= setutimes(p
, nd
.ni_vp
, ts
, usrtvp
== NULL
);
2119 * Set the access and modification times of a file.
2121 struct futimes_args
{
2123 struct timeval
*tptr
;
2127 futimes(p
, uap
, retval
)
2129 register struct futimes_args
*uap
;
2132 struct timespec ts
[2];
2134 struct timeval
*usrtvp
;
2138 if ((error
= getutimes(usrtvp
, ts
)) != 0)
2140 if ((error
= getvnode(p
, uap
->fd
, &fp
)) != 0)
2142 return setutimes(p
, (struct vnode
*)fp
->f_data
, ts
, usrtvp
== NULL
);
2146 * Truncate a file given its path name.
2148 struct truncate_args
{
2150 #ifdef DOUBLE_ALIGN_PARAMS
2157 truncate(p
, uap
, retval
)
2159 register struct truncate_args
*uap
;
2162 register struct vnode
*vp
;
2165 struct nameidata nd
;
2167 if (uap
->length
< 0)
2169 NDINIT(&nd
, LOOKUP
, FOLLOW
, UIO_USERSPACE
, uap
->path
, p
);
2170 if (error
= namei(&nd
))
2173 VOP_LEASE(vp
, p
, p
->p_ucred
, LEASE_WRITE
);
2174 vn_lock(vp
, LK_EXCLUSIVE
| LK_RETRY
, p
);
2175 if (vp
->v_type
== VDIR
)
2177 else if ((error
= vn_writechk(vp
)) == 0 &&
2178 (error
= VOP_ACCESS(vp
, VWRITE
, p
->p_ucred
, p
)) == 0) {
2180 vattr
.va_size
= uap
->length
;
2181 error
= VOP_SETATTR(vp
, &vattr
, p
->p_ucred
, p
);
2188 * Truncate a file given a file descriptor.
2190 struct ftruncate_args
{
2192 #ifdef DOUBLE_ALIGN_PARAMS
2199 ftruncate(p
, uap
, retval
)
2201 register struct ftruncate_args
*uap
;
2209 if (uap
->length
< 0)
2212 if (error
= fdgetf(p
, uap
->fd
, &fp
))
2215 if (fp
->f_type
== DTYPE_PSXSHM
) {
2216 return(pshm_truncate(p
, fp
, uap
->fd
, uap
->length
, retval
));
2218 if (fp
->f_type
!= DTYPE_VNODE
)
2221 if ((fp
->f_flag
& FWRITE
) == 0)
2223 vp
= (struct vnode
*)fp
->f_data
;
2224 VOP_LEASE(vp
, p
, p
->p_ucred
, LEASE_WRITE
);
2225 vn_lock(vp
, LK_EXCLUSIVE
| LK_RETRY
, p
);
2226 if (vp
->v_type
== VDIR
)
2228 else if ((error
= vn_writechk(vp
)) == 0) {
2230 vattr
.va_size
= uap
->length
;
2231 error
= VOP_SETATTR(vp
, &vattr
, fp
->f_cred
, p
);
2233 VOP_UNLOCK(vp
, 0, p
);
2239 * Truncate a file given its path name.
2241 struct otruncate_args
{
2247 otruncate(p
, uap
, retval
)
2249 register struct otruncate_args
*uap
;
2252 struct truncate_args
/* {
2253 syscallarg(char *) path;
2254 #ifdef DOUBLE_ALIGN_PARAMS
2255 syscallarg(int) pad;
2257 syscallarg(off_t) length;
2260 nuap
.path
= uap
->path
;
2261 nuap
.length
= uap
->length
;
2262 return (truncate(p
, &nuap
, retval
));
2266 * Truncate a file given a file descriptor.
2268 struct oftruncate_args
{
2274 oftruncate(p
, uap
, retval
)
2276 register struct oftruncate_args
*uap
;
2279 struct ftruncate_args
/* {
2281 #ifdef DOUBLE_ALIGN_PARAMS
2282 syscallarg(int) pad;
2284 syscallarg(off_t) length;
2288 nuap
.length
= uap
->length
;
2289 return (ftruncate(p
, &nuap
, retval
));
2291 #endif /* COMPAT_43 */
2294 * Sync an open file.
2301 fsync(p
, uap
, retval
)
2303 struct fsync_args
*uap
;
2306 register struct vnode
*vp
;
2310 if (error
= getvnode(p
, uap
->fd
, &fp
))
2312 vp
= (struct vnode
*)fp
->f_data
;
2313 vn_lock(vp
, LK_EXCLUSIVE
| LK_RETRY
, p
);
2314 error
= VOP_FSYNC(vp
, fp
->f_cred
, MNT_WAIT
, p
);
2315 VOP_UNLOCK(vp
, 0, p
);
2320 * Duplicate files. Source must be a file, target must be a file or
2324 struct copyfile_args
{
2332 copyfile(p
, uap
, retval
)
2334 register struct copyfile_args
*uap
;
2337 register struct vnode
*tvp
, *fvp
, *tdvp
;
2338 register struct ucred
*cred
= p
->p_ucred
;
2339 struct nameidata fromnd
, tond
;
2342 /* Check that the flags are valid.
2345 if (uap
->flags
& ~CPF_MASK
) {
2349 NDINIT(&fromnd
, LOOKUP
, SAVESTART
, UIO_USERSPACE
,
2351 if (error
= namei(&fromnd
))
2355 NDINIT(&tond
, CREATE
, LOCKPARENT
| LOCKLEAF
| NOCACHE
| SAVESTART
,
2356 UIO_USERSPACE
, uap
->to
, p
);
2357 if (error
= namei(&tond
)) {
2364 if (!(uap
->flags
& CPF_OVERWRITE
)) {
2370 if (fvp
->v_type
== VDIR
|| (tvp
&& tvp
->v_type
== VDIR
)) {
2375 if (error
= VOP_ACCESS(tdvp
, VWRITE
, cred
, p
))
2381 * If source is the same as the destination (that is the
2382 * same inode number) then there is nothing to do.
2383 * (fixed to have POSIX semantics - CSM 3/2/98)
2389 error
= VOP_COPYFILE(fvp
,tdvp
,tvp
,&tond
.ni_cnd
,uap
->mode
,uap
->flags
);
2391 VOP_ABORTOP(tdvp
, &tond
.ni_cnd
);
2400 vrele(tond
.ni_startdir
);
2401 FREE_ZONE(tond
.ni_cnd
.cn_pnbuf
, tond
.ni_cnd
.cn_pnlen
, M_NAMEI
);
2403 if (fromnd
.ni_startdir
)
2404 vrele(fromnd
.ni_startdir
);
2405 FREE_ZONE(fromnd
.ni_cnd
.cn_pnbuf
, fromnd
.ni_cnd
.cn_pnlen
, M_NAMEI
);
2412 * Rename files. Source and destination must either both be directories,
2413 * or both not be directories. If target is a directory, it must be empty.
2415 struct rename_args
{
2421 rename(p
, uap
, retval
)
2423 register struct rename_args
*uap
;
2426 register struct vnode
*tvp
, *fvp
, *tdvp
;
2427 struct nameidata fromnd
, tond
;
2430 int casesense
,casepres
;
2435 NDINIT(&fromnd
, DELETE
, WANTPARENT
| SAVESTART
, UIO_USERSPACE
,
2437 if (error
= namei(&fromnd
))
2441 NDINIT(&tond
, RENAME
, LOCKPARENT
| LOCKLEAF
| NOCACHE
| SAVESTART
,
2442 UIO_USERSPACE
, uap
->to
, p
);
2443 if (fromnd
.ni_vp
->v_type
== VDIR
)
2444 tond
.ni_cnd
.cn_flags
|= WILLBEDIR
;
2445 if (error
= namei(&tond
)) {
2446 /* Translate error code for rename("dir1", "dir2/."). */
2447 if (error
== EISDIR
&& fvp
->v_type
== VDIR
)
2449 VOP_ABORTOP(fromnd
.ni_dvp
, &fromnd
.ni_cnd
);
2450 vrele(fromnd
.ni_dvp
);
2458 if (fvp
->v_type
== VDIR
&& tvp
->v_type
!= VDIR
) {
2461 } else if (fvp
->v_type
!= VDIR
&& tvp
->v_type
== VDIR
) {
2469 * If source is the same as the destination (that is the
2470 * same inode number) then there is nothing to do... EXCEPT if the
2471 * underlying file system supports case insensitivity and is case
2472 * preserving. Then a special case is made, i.e. foo -> Foo.
2474 * Only file systems that support pathconf selectors _PC_CASE_SENSITIVE
2475 * and _PC_CASE_PRESERVING can have this exception, and they need to
2476 * handle the special case of getting the same vnode as target and
2477 * source. NOTE: Then the target is unlocked going into VOP_RENAME,
2478 * so not to cause locking problems. There is a single reference on tvp.
2480 * NOTE - that fvp == tvp also occurs if they are hard linked - NOTE
2481 * that correct behaviour then is just to remove the source (link)
2483 if (fvp
== tvp
&& fromnd
.ni_dvp
== tdvp
) {
2484 if (fromnd
.ni_cnd
.cn_namelen
== tond
.ni_cnd
.cn_namelen
&&
2485 !bcmp(fromnd
.ni_cnd
.cn_nameptr
, tond
.ni_cnd
.cn_nameptr
,
2486 fromnd
.ni_cnd
.cn_namelen
)) {
2487 error
= -1; /* Default "unix" behavior */
2488 } else { /* probe for file system specifics */
2489 if (VOP_PATHCONF(tdvp
, _PC_CASE_SENSITIVE
, &casesense
))
2491 if (VOP_PATHCONF(tdvp
, _PC_CASE_PRESERVING
, &casepres
))
2493 if (!casesense
&& casepres
)
2494 vput(tvp
); /* Unlock target and drop ref */
2499 * Allow the renaming of mount points.
2500 * - target must not exist
2501 * - target must reside in the same directory as source
2502 * - union mounts cannot be renamed
2503 * - "/" cannot be renamed
2506 (fvp
->v_flag
& VROOT
) &&
2507 (fvp
->v_type
== VDIR
) &&
2509 (fvp
->v_mountedhere
== NULL
) &&
2510 (fromnd
.ni_dvp
== tond
.ni_dvp
) &&
2511 ((fvp
->v_mount
->mnt_flag
& (MNT_UNION
| MNT_ROOTFS
)) == 0) &&
2512 (fvp
->v_mount
->mnt_vnodecovered
!= NULLVP
)) {
2514 /* switch fvp to the covered vnode */
2515 fromnd
.ni_vp
= fvp
->v_mount
->mnt_vnodecovered
;
2523 VOP_LEASE(tdvp
, p
, p
->p_ucred
, LEASE_WRITE
);
2524 if (fromnd
.ni_dvp
!= tdvp
)
2525 VOP_LEASE(fromnd
.ni_dvp
, p
, p
->p_ucred
, LEASE_WRITE
);
2527 VOP_LEASE(tvp
, p
, p
->p_ucred
, LEASE_WRITE
);
2528 error
= VOP_RENAME(fromnd
.ni_dvp
, fvp
, &fromnd
.ni_cnd
,
2529 tond
.ni_dvp
, tvp
, &tond
.ni_cnd
);
2534 * update filesystem's mount point data
2537 char *cp
, *pathend
, *mpname
;
2544 vn_lock(fvp
, LK_EXCLUSIVE
| LK_RETRY
, p
);
2545 mp
= fvp
->v_mountedhere
;
2547 if (vfs_busy(mp
, LK_NOWAIT
, 0, p
)) {
2552 VOP_UNLOCK(fvp
, 0, p
);
2554 MALLOC_ZONE(tobuf
, char *, MAXPATHLEN
, M_NAMEI
, M_WAITOK
);
2555 error
= copyinstr(uap
->to
, tobuf
, MAXPATHLEN
, &len
);
2557 /* find current mount point prefix */
2558 pathend
= &mp
->mnt_stat
.f_mntonname
[0];
2559 for (cp
= pathend
; *cp
!= '\0'; ++cp
) {
2563 /* find last component of target name */
2564 for (mpname
= cp
= tobuf
; *cp
!= '\0'; ++cp
) {
2568 /* append name to prefix */
2569 maxlen
= MNAMELEN
- (pathend
- mp
->mnt_stat
.f_mntonname
);
2570 bzero(pathend
, maxlen
);
2571 strncpy(pathend
, mpname
, maxlen
- 1);
2573 FREE_ZONE(tobuf
, MAXPATHLEN
, M_NAMEI
);
2579 VOP_ABORTOP(tond
.ni_dvp
, &tond
.ni_cnd
);
2586 VOP_ABORTOP(fromnd
.ni_dvp
, &fromnd
.ni_cnd
);
2587 vrele(fromnd
.ni_dvp
);
2591 vrele(tond
.ni_startdir
);
2592 FREE_ZONE(tond
.ni_cnd
.cn_pnbuf
, tond
.ni_cnd
.cn_pnlen
, M_NAMEI
);
2594 if (fromnd
.ni_startdir
)
2595 vrele(fromnd
.ni_startdir
);
2596 FREE_ZONE(fromnd
.ni_cnd
.cn_pnbuf
, fromnd
.ni_cnd
.cn_pnlen
, M_NAMEI
);
2603 * Make a directory file.
2611 mkdir(p
, uap
, retval
)
2613 register struct mkdir_args
*uap
;
2616 register struct vnode
*vp
;
2619 struct nameidata nd
;
2622 NDINIT(&nd
, CREATE
, LOCKPARENT
, UIO_USERSPACE
, uap
->path
, p
);
2623 nd
.ni_cnd
.cn_flags
|= WILLBEDIR
;
2624 if (error
= namei(&nd
))
2628 VOP_ABORTOP(nd
.ni_dvp
, &nd
.ni_cnd
);
2629 if (nd
.ni_dvp
== vp
)
2637 vattr
.va_type
= VDIR
;
2638 vattr
.va_mode
= (uap
->mode
& ACCESSPERMS
) &~ p
->p_fd
->fd_cmask
;
2639 VOP_LEASE(nd
.ni_dvp
, p
, p
->p_ucred
, LEASE_WRITE
);
2640 error
= VOP_MKDIR(nd
.ni_dvp
, &nd
.ni_vp
, &nd
.ni_cnd
, &vattr
);
2647 * Remove a directory file.
2654 rmdir(p
, uap
, retval
)
2656 struct rmdir_args
*uap
;
2659 register struct vnode
*vp
;
2661 struct nameidata nd
;
2664 NDINIT(&nd
, DELETE
, LOCKPARENT
| LOCKLEAF
, UIO_USERSPACE
,
2666 if (error
= namei(&nd
))
2669 if (vp
->v_type
!= VDIR
) {
2674 * No rmdir "." please.
2676 if (nd
.ni_dvp
== vp
) {
2681 * The root of a mounted filesystem cannot be deleted.
2683 if (vp
->v_flag
& VROOT
)
2687 VOP_LEASE(nd
.ni_dvp
, p
, p
->p_ucred
, LEASE_WRITE
);
2688 VOP_LEASE(vp
, p
, p
->p_ucred
, LEASE_WRITE
);
2689 error
= VOP_RMDIR(nd
.ni_dvp
, nd
.ni_vp
, &nd
.ni_cnd
);
2691 VOP_ABORTOP(nd
.ni_dvp
, &nd
.ni_cnd
);
2692 if (nd
.ni_dvp
== vp
)
2703 * Read a block of directory entries in a file system independent format.
2705 struct ogetdirentries_args
{
2712 ogetdirentries(p
, uap
, retval
)
2714 register struct ogetdirentries_args
*uap
;
2717 register struct vnode
*vp
;
2719 struct uio auio
, kuio
;
2720 struct iovec aiov
, kiov
;
2721 struct dirent
*dp
, *edp
;
2723 int error
, eofflag
, readcnt
;
2726 if (error
= getvnode(p
, uap
->fd
, &fp
))
2728 if ((fp
->f_flag
& FREAD
) == 0)
2730 vp
= (struct vnode
*)fp
->f_data
;
2732 if (vp
->v_type
!= VDIR
)
2734 aiov
.iov_base
= uap
->buf
;
2735 aiov
.iov_len
= uap
->count
;
2736 auio
.uio_iov
= &aiov
;
2737 auio
.uio_iovcnt
= 1;
2738 auio
.uio_rw
= UIO_READ
;
2739 auio
.uio_segflg
= UIO_USERSPACE
;
2741 auio
.uio_resid
= uap
->count
;
2742 vn_lock(vp
, LK_EXCLUSIVE
| LK_RETRY
, p
);
2743 loff
= auio
.uio_offset
= fp
->f_offset
;
2744 # if (BYTE_ORDER != LITTLE_ENDIAN)
2745 if (vp
->v_mount
->mnt_maxsymlinklen
<= 0) {
2746 error
= VOP_READDIR(vp
, &auio
, fp
->f_cred
, &eofflag
,
2747 (int *)0, (u_long
*)0);
2748 fp
->f_offset
= auio
.uio_offset
;
2753 kuio
.uio_iov
= &kiov
;
2754 kuio
.uio_segflg
= UIO_SYSSPACE
;
2755 kiov
.iov_len
= uap
->count
;
2756 MALLOC(dirbuf
, caddr_t
, uap
->count
, M_TEMP
, M_WAITOK
);
2757 kiov
.iov_base
= dirbuf
;
2758 error
= VOP_READDIR(vp
, &kuio
, fp
->f_cred
, &eofflag
,
2759 (int *)0, (u_long
*)0);
2760 fp
->f_offset
= kuio
.uio_offset
;
2762 readcnt
= uap
->count
- kuio
.uio_resid
;
2763 edp
= (struct dirent
*)&dirbuf
[readcnt
];
2764 for (dp
= (struct dirent
*)dirbuf
; dp
< edp
; ) {
2765 # if (BYTE_ORDER == LITTLE_ENDIAN)
2767 * The expected low byte of
2768 * dp->d_namlen is our dp->d_type.
2769 * The high MBZ byte of dp->d_namlen
2770 * is our dp->d_namlen.
2772 dp
->d_type
= dp
->d_namlen
;
2776 * The dp->d_type is the high byte
2777 * of the expected dp->d_namlen,
2778 * so must be zero'ed.
2782 if (dp
->d_reclen
> 0) {
2783 dp
= (struct dirent
*)
2784 ((char *)dp
+ dp
->d_reclen
);
2791 error
= uiomove(dirbuf
, readcnt
, &auio
);
2793 FREE(dirbuf
, M_TEMP
);
2795 VOP_UNLOCK(vp
, 0, p
);
2801 extern int (**union_vnodeop_p
)(void *);
2802 extern struct vnode
*union_dircache
__P((struct vnode
*, struct proc
*));
2804 if ((uap
->count
== auio
.uio_resid
) &&
2805 (vp
->v_op
== union_vnodeop_p
)) {
2808 lvp
= union_dircache(vp
, p
);
2809 if (lvp
!= NULLVP
) {
2813 * If the directory is opaque,
2814 * then don't show lower entries
2816 error
= VOP_GETATTR(vp
, &va
, fp
->f_cred
, p
);
2817 if (va
.va_flags
& OPAQUE
) {
2823 if (lvp
!= NULLVP
) {
2824 error
= VOP_OPEN(lvp
, FREAD
, fp
->f_cred
, p
);
2829 VOP_UNLOCK(lvp
, 0, p
);
2830 fp
->f_data
= (caddr_t
) lvp
;
2832 error
= VOP_CLOSE(vp
, FREAD
, fp
->f_cred
, p
);
2843 if ((uap
->count
== auio
.uio_resid
) &&
2844 (vp
->v_flag
& VROOT
) &&
2845 (vp
->v_mount
->mnt_flag
& MNT_UNION
)) {
2846 struct vnode
*tvp
= vp
;
2847 vp
= vp
->v_mount
->mnt_vnodecovered
;
2849 fp
->f_data
= (caddr_t
) vp
;
2854 error
= copyout((caddr_t
)&loff
, (caddr_t
)uap
->basep
,
2856 *retval
= uap
->count
- auio
.uio_resid
;
2859 #endif /* COMPAT_43 */
2862 * Read a block of directory entries in a file system independent format.
2864 struct getdirentries_args
{
2871 getdirentries(p
, uap
, retval
)
2873 register struct getdirentries_args
*uap
;
2876 register struct vnode
*vp
;
2883 if (error
= getvnode(p
, uap
->fd
, &fp
))
2885 if ((fp
->f_flag
& FREAD
) == 0)
2887 vp
= (struct vnode
*)fp
->f_data
;
2889 if (vp
->v_type
!= VDIR
)
2891 aiov
.iov_base
= uap
->buf
;
2892 aiov
.iov_len
= uap
->count
;
2893 auio
.uio_iov
= &aiov
;
2894 auio
.uio_iovcnt
= 1;
2895 auio
.uio_rw
= UIO_READ
;
2896 auio
.uio_segflg
= UIO_USERSPACE
;
2898 auio
.uio_resid
= uap
->count
;
2899 vn_lock(vp
, LK_EXCLUSIVE
| LK_RETRY
, p
);
2900 loff
= auio
.uio_offset
= fp
->f_offset
;
2901 error
= VOP_READDIR(vp
, &auio
, fp
->f_cred
, &eofflag
,
2902 (int *)0, (u_long
*)0);
2903 fp
->f_offset
= auio
.uio_offset
;
2904 VOP_UNLOCK(vp
, 0, p
);
2910 extern int (**union_vnodeop_p
)(void *);
2911 extern struct vnode
*union_dircache
__P((struct vnode
*, struct proc
*));
2913 if ((uap
->count
== auio
.uio_resid
) &&
2914 (vp
->v_op
== union_vnodeop_p
)) {
2917 lvp
= union_dircache(vp
, p
);
2918 if (lvp
!= NULLVP
) {
2922 * If the directory is opaque,
2923 * then don't show lower entries
2925 error
= VOP_GETATTR(vp
, &va
, fp
->f_cred
, p
);
2926 if (va
.va_flags
& OPAQUE
) {
2932 if (lvp
!= NULLVP
) {
2933 error
= VOP_OPEN(lvp
, FREAD
, fp
->f_cred
, p
);
2938 VOP_UNLOCK(lvp
, 0, p
);
2939 fp
->f_data
= (caddr_t
) lvp
;
2941 error
= VOP_CLOSE(vp
, FREAD
, fp
->f_cred
, p
);
2952 if ((uap
->count
== auio
.uio_resid
) &&
2953 (vp
->v_flag
& VROOT
) &&
2954 (vp
->v_mount
->mnt_flag
& MNT_UNION
)) {
2955 struct vnode
*tvp
= vp
;
2956 vp
= vp
->v_mount
->mnt_vnodecovered
;
2958 fp
->f_data
= (caddr_t
) vp
;
2963 error
= copyout((caddr_t
)&loff
, (caddr_t
)uap
->basep
,
2965 *retval
= uap
->count
- auio
.uio_resid
;
2970 * Set the mode mask for creation of filesystem nodes.
2976 umask(p
, uap
, retval
)
2978 struct umask_args
*uap
;
2981 register struct filedesc
*fdp
;
2984 *retval
= fdp
->fd_cmask
;
2985 fdp
->fd_cmask
= uap
->newmask
& ALLPERMS
;
2990 * Void all references to file by ripping underlying filesystem
2993 struct revoke_args
{
2998 revoke(p
, uap
, retval
)
3000 register struct revoke_args
*uap
;
3003 register struct vnode
*vp
;
3006 struct nameidata nd
;
3008 NDINIT(&nd
, LOOKUP
, FOLLOW
, UIO_USERSPACE
, uap
->path
, p
);
3009 if (error
= namei(&nd
))
3012 if (error
= VOP_GETATTR(vp
, &vattr
, p
->p_ucred
, p
))
3014 if (p
->p_ucred
->cr_uid
!= vattr
.va_uid
&&
3015 (error
= suser(p
->p_ucred
, &p
->p_acflag
)))
3017 if (vp
->v_usecount
> 1 || (vp
->v_flag
& VALIASED
))
3018 VOP_REVOKE(vp
, REVOKEALL
);
3025 * Convert a user file descriptor to a kernel file entry.
3028 getvnode(p
, fd
, fpp
)
3036 if (error
= fdgetf(p
, fd
, &fp
))
3038 if (fp
->f_type
!= DTYPE_VNODE
)
3045 * HFS/HFS PlUS SPECIFIC SYSTEM CALLS
3046 * The following system calls are designed to support features
3047 * which are specific to the HFS & HFS Plus volume formats
3050 #ifdef __APPLE_API_OBSOLETE
3052 /************************************************/
3053 /* *** Following calls will be deleted soon *** */
3054 /************************************************/
3057 * Make a complex file. A complex file is one with multiple forks (data streams)
3059 struct mkcomplex_args
{
3060 const char *path
; /* pathname of the file to be created */
3061 mode_t mode
; /* access mode for the newly created file */
3062 u_long type
; /* format of the complex file */
3066 mkcomplex(p
,uap
,retval
)
3068 register struct mkcomplex_args
*uap
;
3074 struct nameidata nd
;
3076 /* mkcomplex wants the directory vnode locked so do that here */
3078 NDINIT(&nd
, CREATE
, FOLLOW
| LOCKPARENT
, UIO_USERSPACE
, (char *)uap
->path
, p
);
3079 if (error
= namei(&nd
))
3082 /* Set the attributes as specified by the user */
3085 vattr
.va_mode
= (uap
->mode
& ACCESSPERMS
);
3086 error
= VOP_MKCOMPLEX(nd
.ni_dvp
, &vp
, &nd
.ni_cnd
, &vattr
, uap
->type
);
3088 /* The mkcomplex call promises to release the parent vnode pointer
3089 * even an an error case so don't do it here unless the operation
3090 * is not supported. In that case, there isn't anyone to unlock the parent
3091 * The vnode pointer to the file will also be released.
3096 if (error
== EOPNOTSUPP
)
3103 } /* end of mkcomplex system call */
3106 * Extended stat call which returns volumeid and vnodeid as well as other info
3109 const char *path
; /* pathname of the target file */
3110 struct vstat
*vsb
; /* vstat structure for returned info */
3116 register struct statv_args
*uap
;
3120 return (EOPNOTSUPP
); /* We'll just return an error for now */
3122 } /* end of statv system call */
3125 * Extended lstat call which returns volumeid and vnodeid as well as other info
3127 struct lstatv_args
{
3128 const char *path
; /* pathname of the target file */
3129 struct vstat
*vsb
; /* vstat structure for returned info */
3133 lstatv(p
,uap
,retval
)
3135 register struct lstatv_args
*uap
;
3139 return (EOPNOTSUPP
); /* We'll just return an error for now */
3140 } /* end of lstatv system call */
3143 * Extended fstat call which returns volumeid and vnodeid as well as other info
3145 struct fstatv_args
{
3146 int fd
; /* file descriptor of the target file */
3147 struct vstat
*vsb
; /* vstat structure for returned info */
3151 fstatv(p
,uap
,retval
)
3153 register struct fstatv_args
*uap
;
3157 return (EOPNOTSUPP
); /* We'll just return an error for now */
3158 } /* end of fstatv system call */
3161 /************************************************/
3162 /* *** Preceding calls will be deleted soon *** */
3163 /************************************************/
3165 #endif /* __APPLE_API_OBSOLETE */
3169 * Obtain attribute information about a file system object
3172 struct getattrlist_args
{
3173 const char *path
; /* pathname of the target object */
3174 struct attrlist
* alist
; /* Attributes desired by the user */
3175 void * attributeBuffer
; /* buffer to hold returned attributes */
3176 size_t bufferSize
; /* size of the return buffer */
3177 unsigned long options
; /* options (follow/don't follow) */
3181 getattrlist (p
,uap
,retval
)
3183 register struct getattrlist_args
*uap
;
3188 struct nameidata nd
;
3191 struct attrlist attributelist
;
3194 /* Get the attributes desire and do our parameter checking */
3196 if (error
= copyin((caddr_t
)uap
->alist
, (caddr_t
) &attributelist
,
3197 sizeof (attributelist
)))
3202 if (attributelist
.bitmapcount
!= ATTR_BIT_MAP_COUNT
3204 || attributelist
.commonattr
& ~ATTR_CMN_VALIDMASK
||
3205 attributelist
.volattr
& ~ATTR_VOL_VALIDMASK
||
3206 attributelist
.dirattr
& ~ATTR_DIR_VALIDMASK
||
3207 attributelist
.fileattr
& ~ATTR_FILE_VALIDMASK
||
3208 attributelist
.forkattr
& ~ATTR_FORK_VALIDMASK
3215 /* Get the vnode for the file we are getting info on. */
3216 nameiflags
= LOCKLEAF
;
3217 if ((uap
->options
& FSOPT_NOFOLLOW
) == 0) nameiflags
|= FOLLOW
;
3218 NDINIT(&nd
, LOOKUP
, nameiflags
, UIO_USERSPACE
, (char *)uap
->path
, p
);
3220 if (error
= namei(&nd
))
3223 /* Set up the UIO structure for use by the vfs routine */
3226 aiov
.iov_base
= uap
->attributeBuffer
;
3227 aiov
.iov_len
= uap
->bufferSize
;
3228 auio
.uio_iov
= &aiov
;
3229 auio
.uio_iovcnt
= 1;
3230 auio
.uio_offset
= 0;
3231 auio
.uio_rw
= UIO_READ
;
3232 auio
.uio_segflg
= UIO_USERSPACE
;
3234 auio
.uio_resid
= uap
->bufferSize
;
3237 error
= VOP_GETATTRLIST(nd
.ni_vp
, &attributelist
, &auio
, p
->p_ucred
, p
);
3239 /* Unlock and release the vnode which will have been locked by namei */
3243 /* return the effort if we got one, otherwise return success */
3252 } /* end of getattrlist system call */
3257 * Set attribute information about a file system object
3260 struct setattrlist_args
{
3261 const char *path
; /* pathname of the target object */
3262 struct attrlist
* alist
; /* Attributes being set by the user */
3263 void * attributeBuffer
; /* buffer with attribute values to be set */
3264 size_t bufferSize
; /* size of the return buffer */
3265 unsigned long options
; /* options (follow/don't follow) */
3269 setattrlist (p
,uap
,retval
)
3271 register struct setattrlist_args
*uap
;
3276 struct nameidata nd
;
3279 struct attrlist alist
;
3282 /* Get the attributes desired and do our parameter checking */
3284 if ((error
= copyin((caddr_t
)uap
->alist
, (caddr_t
) &alist
,
3289 if (alist
.bitmapcount
!= ATTR_BIT_MAP_COUNT
)
3292 /* Get the vnode for the file whose attributes are being set. */
3293 nameiflags
= LOCKLEAF
;
3294 if ((uap
->options
& FSOPT_NOFOLLOW
) == 0) nameiflags
|= FOLLOW
;
3295 NDINIT(&nd
, LOOKUP
, nameiflags
, UIO_USERSPACE
, (char *)uap
->path
, p
);
3296 if (error
= namei(&nd
))
3299 /* Set up the UIO structure for use by the vfs routine */
3300 aiov
.iov_base
= uap
->attributeBuffer
;
3301 aiov
.iov_len
= uap
->bufferSize
;
3302 auio
.uio_iov
= &aiov
;
3303 auio
.uio_iovcnt
= 1;
3304 auio
.uio_offset
= 0;
3305 auio
.uio_rw
= UIO_WRITE
;
3306 auio
.uio_segflg
= UIO_USERSPACE
;
3308 auio
.uio_resid
= uap
->bufferSize
;
3310 error
= VOP_SETATTRLIST(nd
.ni_vp
, &alist
, &auio
, p
->p_ucred
, p
);
3316 } /* end of setattrlist system call */
3320 * Obtain attribute information on objects in a directory while enumerating
3321 * the directory. This call does not yet support union mounted directories.
3323 * 1.union mounted directories.
3326 struct getdirentriesattr_args
{
3327 int fd
; /* file descriptor */
3328 struct attrlist
*alist
; /* bit map of requested attributes */
3329 void *buffer
; /* buffer to hold returned attribute info */
3330 size_t buffersize
; /* size of the return buffer */
3331 u_long
*count
; /* the count of entries requested/returned */
3332 u_long
*basep
; /* the offset of where we are leaving off in buffer */
3333 u_long
*newstate
; /* a flag to inform of changes in directory */
3334 u_long options
; /* maybe unused for now */
3338 getdirentriesattr (p
,uap
,retval
)
3340 register struct getdirentriesattr_args
*uap
;
3344 register struct vnode
*vp
;
3352 struct attrlist attributelist
;
3354 /* Get the attributes into kernel space */
3355 if (error
= copyin((caddr_t
)uap
->alist
, (caddr_t
) &attributelist
, sizeof (attributelist
)))
3357 if (error
= copyin((caddr_t
)uap
->count
, (caddr_t
) &actualcount
, sizeof (u_long
)))
3360 if (error
= getvnode(p
, uap
->fd
, &fp
))
3362 if ((fp
->f_flag
& FREAD
) == 0)
3364 vp
= (struct vnode
*)fp
->f_data
;
3366 if (vp
->v_type
!= VDIR
)
3369 /* set up the uio structure which will contain the users return buffer */
3370 aiov
.iov_base
= uap
->buffer
;
3371 aiov
.iov_len
= uap
->buffersize
;
3372 auio
.uio_iov
= &aiov
;
3373 auio
.uio_iovcnt
= 1;
3374 auio
.uio_rw
= UIO_READ
;
3375 auio
.uio_segflg
= UIO_USERSPACE
;
3377 auio
.uio_resid
= uap
->buffersize
;
3379 loff
= auio
.uio_offset
= fp
->f_offset
;
3380 vn_lock(vp
, LK_EXCLUSIVE
| LK_RETRY
, p
);
3381 error
= VOP_READDIRATTR (vp
, &attributelist
, &auio
,
3382 actualcount
, uap
->options
, &newstate
, &eofflag
,
3383 &actualcount
, ((u_long
**)0), p
->p_cred
);
3385 VOP_UNLOCK(vp
, 0, p
);
3386 if (error
) return (error
);
3387 fp
->f_offset
= auio
.uio_offset
; /* should be multiple of dirent, not variable */
3389 if (error
= copyout((caddr_t
) &actualcount
, (caddr_t
) uap
->count
, sizeof(u_long
)))
3391 if (error
= copyout((caddr_t
) &newstate
, (caddr_t
) uap
->newstate
, sizeof(u_long
)))
3393 if (error
= copyout((caddr_t
)&loff
, (caddr_t
)uap
->basep
, sizeof(long)))
3396 *retval
= eofflag
; /* similar to getdirentries */
3397 return (0); /* return error earlier, an retval of 0 or 1 now */
3399 } /* end of getdirentryattr system call */
3402 * Exchange data between two files
3405 struct exchangedata_args
{
3406 const char *path1
; /* pathname of the first swapee */
3407 const char *path2
; /* pathname of the second swapee */
3408 unsigned long options
; /* options */
3412 exchangedata (p
,uap
,retval
)
3414 register struct exchangedata_args
*uap
;
3419 struct nameidata fnd
, snd
;
3420 struct vnode
*fvp
, *svp
;
3425 if ((uap
->options
& FSOPT_NOFOLLOW
) == 0) nameiflags
|= FOLLOW
;
3427 /* Global lock, to prevent race condition, only one exchange at a time */
3428 lockmgr(&exchangelock
, LK_EXCLUSIVE
, (struct slock
*)0, p
);
3430 NDINIT(&fnd
, LOOKUP
, nameiflags
, UIO_USERSPACE
, (char *) uap
->path1
, p
);
3432 if (error
= namei(&fnd
))
3437 NDINIT(&snd
, LOOKUP
, nameiflags
, UIO_USERSPACE
, (char *)uap
->path2
, p
);
3439 if (error
= namei(&snd
)) {
3446 /* if the files are the same, return an inval error */
3454 vn_lock(fvp
, LK_EXCLUSIVE
| LK_RETRY
, p
);
3455 vn_lock(svp
, LK_EXCLUSIVE
| LK_RETRY
, p
);
3457 error
= VOP_ACCESS(fvp
, VWRITE
, p
->p_ucred
, p
);
3458 if (error
) goto out
;
3460 error
= VOP_ACCESS(svp
, VWRITE
, p
->p_ucred
, p
);
3461 if (error
) goto out
;
3463 /* Ok, make the call */
3464 error
= VOP_EXCHANGE (fvp
, svp
, p
->p_ucred
, p
);
3471 lockmgr(&exchangelock
, LK_RELEASE
, (struct slock
*)0, p
);
3479 } /* end of exchangedata system call */
3481 #ifdef __APPLE_API_OBSOLETE
3483 /************************************************/
3484 /* *** Following calls will be deleted soon *** */
3485 /************************************************/
3488 * Check users access to a file
3491 struct checkuseraccess_args
{
3492 const char *path
; /* pathname of the target file */
3493 uid_t userid
; /* user for whom we are checking access */
3494 gid_t
*groups
; /* Group that we are checking for */
3495 int ngroups
; /* Number of groups being checked */
3496 int accessrequired
; /* needed access to the file */
3497 unsigned long options
; /* options */
3502 checkuseraccess (p
,uap
,retval
)
3504 register struct checkuseraccess_args
*uap
;
3508 register struct vnode
*vp
;
3510 struct nameidata nd
;
3512 int flags
; /*what will actually get passed to access*/
3515 /* Make sure that the number of groups is correct before we do anything */
3517 if ((uap
->ngroups
<= 0) || (uap
->ngroups
> NGROUPS
))
3520 /* Verify that the caller is root */
3522 if (error
= suser(p
->p_ucred
, &p
->p_acflag
))
3525 /* Fill in the credential structure */
3528 cred
.cr_uid
= uap
->userid
;
3529 cred
.cr_ngroups
= uap
->ngroups
;
3530 if (error
= copyin((caddr_t
) uap
->groups
, (caddr_t
) &(cred
.cr_groups
), (sizeof(gid_t
))*uap
->ngroups
))
3533 /* Get our hands on the file */
3535 nameiflags
= LOCKLEAF
;
3536 if ((uap
->options
& FSOPT_NOFOLLOW
) == 0) nameiflags
|= FOLLOW
;
3537 NDINIT(&nd
, LOOKUP
, nameiflags
, UIO_USERSPACE
, (char *)uap
->path
, p
);
3539 if (error
= namei(&nd
))
3543 /* Flags == 0 means only check for existence. */
3547 if (uap
->accessrequired
) {
3548 if (uap
->accessrequired
& R_OK
)
3550 if (uap
->accessrequired
& W_OK
)
3552 if (uap
->accessrequired
& X_OK
)
3555 error
= VOP_ACCESS(vp
, flags
, &cred
, p
);
3564 } /* end of checkuseraccess system call */
3566 /************************************************/
3567 /* *** Preceding calls will be deleted soon *** */
3568 /************************************************/
3570 #endif /* __APPLE_API_OBSOLETE */
3574 struct searchfs_args
{
3576 struct fssearchblock
*searchblock
;
3580 struct searchstate
*state
;
3585 searchfs (p
,uap
,retval
)
3587 register struct searchfs_args
*uap
;
3591 register struct vnode
*vp
;
3594 struct nameidata nd
;
3595 struct fssearchblock searchblock
;
3596 struct searchstate
*state
;
3597 struct attrlist
*returnattrs
;
3598 void *searchparams1
,*searchparams2
;
3606 /* Start by copying in fsearchblock paramater list */
3608 if (error
= copyin((caddr_t
) uap
->searchblock
, (caddr_t
) &searchblock
,sizeof(struct fssearchblock
)))
3611 /* Now malloc a big bunch of space to hold the search parameters, the attrlists and the search state. */
3612 /* It all has to do into local memory and it's not that big so we might as well put it all together. */
3613 /* Searchparams1 shall be first so we might as well use that to hold the base address of the allocated*/
3616 mallocsize
= searchblock
.sizeofsearchparams1
+searchblock
.sizeofsearchparams2
+
3617 sizeof(struct attrlist
) + sizeof(struct searchstate
);
3619 MALLOC(searchparams1
, void *, mallocsize
, M_TEMP
, M_WAITOK
);
3621 /* Now set up the various pointers to the correct place in our newly allocated memory */
3623 searchparams2
= (void *) (((caddr_t
) searchparams1
) + searchblock
.sizeofsearchparams1
);
3624 returnattrs
= (struct attrlist
*) (((caddr_t
) searchparams2
) + searchblock
.sizeofsearchparams2
);
3625 state
= (struct searchstate
*) (((caddr_t
) returnattrs
) + sizeof (struct attrlist
));
3627 /* Now copy in the stuff given our local variables. */
3629 if (error
= copyin((caddr_t
) searchblock
.searchparams1
, searchparams1
,searchblock
.sizeofsearchparams1
))
3632 if (error
= copyin((caddr_t
) searchblock
.searchparams2
, searchparams2
,searchblock
.sizeofsearchparams2
))
3635 if (error
= copyin((caddr_t
) searchblock
.returnattrs
, (caddr_t
) returnattrs
, sizeof(struct attrlist
)))
3638 if (error
= copyin((caddr_t
) uap
->state
, (caddr_t
) state
, sizeof(struct searchstate
)))
3641 /* set up the uio structure which will contain the users return buffer */
3643 aiov
.iov_base
= searchblock
.returnbuffer
;
3644 aiov
.iov_len
= searchblock
.returnbuffersize
;
3645 auio
.uio_iov
= &aiov
;
3646 auio
.uio_iovcnt
= 1;
3647 auio
.uio_rw
= UIO_READ
;
3648 auio
.uio_segflg
= UIO_USERSPACE
;
3650 auio
.uio_resid
= searchblock
.returnbuffersize
;
3652 nameiflags
= LOCKLEAF
;
3653 if ((uap
->options
& FSOPT_NOFOLLOW
) == 0) nameiflags
|= FOLLOW
;
3654 NDINIT(&nd
, LOOKUP
, nameiflags
, UIO_USERSPACE
, (char *)uap
->path
, p
);
3656 if (error
= namei(&nd
))
3663 * If searchblock.maxmatches == 0, then skip the search. This has happened
3664 * before and sometimes the underlyning code doesnt deal with it well.
3666 if (searchblock
.maxmatches
== 0) {
3672 Allright, we have everything we need, so lets make that call.
3674 We keep special track of the return value from the file system:
3675 EAGAIN is an acceptable error condition that shouldn't keep us
3676 from copying out any results...
3679 fserror
= VOP_SEARCHFS(vp
,
3682 &searchblock
.searchattrs
,
3683 searchblock
.maxmatches
,
3684 &searchblock
.timelimit
,
3696 /* Now copy out the stuff that needs copying out. That means the number of matches, the
3697 search state. Everything was already put into he return buffer by the vop call. */
3699 if (error
= copyout((caddr_t
) state
, (caddr_t
) uap
->state
, sizeof(struct searchstate
)))
3702 if (error
= copyout((caddr_t
) &nummatches
, (caddr_t
) uap
->nummatches
, sizeof(u_long
)))
3709 FREE(searchparams1
,M_TEMP
);
3714 } /* end of searchfs system call */
3718 * Make a filesystem-specific control call:
3721 const char *path
; /* pathname of the target object */
3722 u_long cmd
; /* cmd (also encodes size/direction of arguments a la ioctl) */
3723 caddr_t data
; /* pointer to argument buffer */
3724 u_long options
; /* options for fsctl processing */
3728 fsctl (p
,uap
,retval
)
3730 struct fsctl_args
*uap
;
3735 struct nameidata nd
;
3737 u_long cmd
= uap
->cmd
;
3738 register u_int size
;
3739 #define STK_PARAMS 128
3740 char stkbuf
[STK_PARAMS
];
3743 size
= IOCPARM_LEN(cmd
);
3744 if (size
> IOCPARM_MAX
) return (EINVAL
);
3747 if (size
> sizeof (stkbuf
)) {
3748 if ((memp
= (caddr_t
)kalloc(size
)) == 0) return ENOMEM
;
3756 error
= copyin(uap
->data
, data
, (u_int
)size
);
3757 if (error
) goto FSCtl_Exit
;
3759 *(caddr_t
*)data
= uap
->data
;
3761 } else if ((cmd
& IOC_OUT
) && size
) {
3763 * Zero the buffer so the user always
3764 * gets back something deterministic.
3767 } else if (cmd
& IOC_VOID
)
3768 *(caddr_t
*)data
= uap
->data
;
3770 /* Get the vnode for the file we are getting info on: */
3771 nameiflags
= LOCKLEAF
;
3772 if ((uap
->options
& FSOPT_NOFOLLOW
) == 0) nameiflags
|= FOLLOW
;
3773 NDINIT(&nd
, LOOKUP
, nameiflags
, UIO_USERSPACE
, (char *)uap
->path
, p
);
3774 if (error
= namei(&nd
)) goto FSCtl_Exit
;
3776 /* Invoke the filesystem-specific code */
3777 error
= VOP_IOCTL(nd
.ni_vp
, IOCBASECMD(cmd
), data
, uap
->options
, p
->p_ucred
, p
);
3782 * Copy any data to user, size was
3783 * already set and checked above.
3785 if (error
== 0 && (cmd
& IOC_OUT
) && size
) error
= copyout(data
, uap
->data
, (u_int
)size
);
3788 if (memp
) kfree(memp
, size
);
3792 /* end of fsctl system call */
3795 * An in-kernel sync for power management to call.
3797 __private_extern__
int
3800 boolean_t funnel_state
;
3803 struct sync_args data
;
3807 funnel_state
= thread_funnel_set(kernel_flock
, TRUE
);
3809 error
= sync(current_proc(), &data
, &retval
);
3811 thread_funnel_set(kernel_flock
, funnel_state
);
3814 } /* end of sync_internal call */