2  * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved. 
   4  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 
   6  * This file contains Original Code and/or Modifications of Original Code 
   7  * as defined in and that are subject to the Apple Public Source License 
   8  * Version 2.0 (the 'License'). You may not use this file except in 
   9  * compliance with the License. The rights granted to you under the License 
  10  * may not be used to create, or enable the creation or redistribution of, 
  11  * unlawful or unlicensed copies of an Apple operating system, or to 
  12  * circumvent, violate, or enable the circumvention or violation of, any 
  13  * terms of an Apple operating system software license agreement. 
  15  * Please obtain a copy of the License at 
  16  * http://www.opensource.apple.com/apsl/ and read it before using this file. 
  18  * The Original Code and all software distributed under the License are 
  19  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 
  20  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 
  21  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 
  22  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 
  23  * Please see the License for the specific language governing rights and 
  24  * limitations under the License. 
  26  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 
  28 /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */ 
  30  * Copyright (c) 1982, 1986, 1989, 1993 
  31  *      The Regents of the University of California.  All rights reserved. 
  32  * (c) UNIX System Laboratories, Inc. 
  33  * All or some portions of this file are derived from material licensed 
  34  * to the University of California by American Telephone and Telegraph 
  35  * Co. or Unix System Laboratories, Inc. and are reproduced herein with 
  36  * the permission of UNIX System Laboratories, Inc. 
  38  * Redistribution and use in source and binary forms, with or without 
  39  * modification, are permitted provided that the following conditions 
  41  * 1. Redistributions of source code must retain the above copyright 
  42  *    notice, this list of conditions and the following disclaimer. 
  43  * 2. Redistributions in binary form must reproduce the above copyright 
  44  *    notice, this list of conditions and the following disclaimer in the 
  45  *    documentation and/or other materials provided with the distribution. 
  46  * 3. All advertising materials mentioning features or use of this software 
  47  *    must display the following acknowledgement: 
  48  *      This product includes software developed by the University of 
  49  *      California, Berkeley and its contributors. 
  50  * 4. Neither the name of the University nor the names of its contributors 
  51  *    may be used to endorse or promote products derived from this software 
  52  *    without specific prior written permission. 
  54  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 
  55  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
  56  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
  57  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 
  58  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
  59  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
  60  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
  61  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
  62  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
  63  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
  66  *      @(#)vfs_vnops.c 8.14 (Berkeley) 6/15/95 
  70 #include <sys/param.h> 
  71 #include <sys/types.h> 
  72 #include <sys/systm.h> 
  73 #include <sys/kernel.h> 
  74 #include <sys/file_internal.h> 
  76 #include <sys/proc_internal.h> 
  77 #include <sys/kauth.h> 
  78 #include <sys/mount_internal.h> 
  79 #include <sys/namei.h> 
  80 #include <sys/vnode_internal.h> 
  81 #include <sys/ioctl.h> 
  86 #include <sys/fsevents.h> 
  87 #include <sys/kdebug.h> 
  88 #include <sys/xattr.h> 
  89 #include <sys/ubc_internal.h> 
  90 #include <sys/uio_internal.h> 
  91 #include <sys/resourcevar.h> 
  93 #include <vm/vm_kern.h> 
  94 #include <vm/vm_map.h> 
  96 #include <miscfs/specfs/specdev.h> 
 100 static int vn_closefile(struct fileglob 
*fp
, struct proc 
*p
); 
 101 static int vn_ioctl(struct fileproc 
*fp
, u_long com
, caddr_t data
, struct proc 
*p
); 
 102 static int vn_read(struct fileproc 
*fp
, struct uio 
*uio
, 
 103                 kauth_cred_t cred
, int flags
, struct proc 
*p
); 
 104 static int vn_write(struct fileproc 
*fp
, struct uio 
*uio
, 
 105                 kauth_cred_t cred
, int flags
, struct proc 
*p
); 
 106 static int vn_select( struct fileproc 
*fp
, int which
, void * wql
, struct proc 
*p
); 
 107 static int vn_kqfilt_add(struct fileproc 
*fp
, struct knote 
*kn
, struct proc 
*p
); 
 109 static int vn_kqfilt_remove(struct vnode 
*vp
, uintptr_t ident
, struct proc 
*p
); 
 112 struct  fileops vnops 
= 
 113         { vn_read
, vn_write
, vn_ioctl
, vn_select
, vn_closefile
, vn_kqfilt_add
, 0 }; 
 116  * Common code for vnode open operations. 
 117  * Check permissions, and call the VNOP_OPEN or VNOP_CREATE routine. 
 119  * XXX the profusion of interfaces here is probably a bad thing. 
 122 vn_open(struct nameidata 
*ndp
, int fmode
, int cmode
) 
 124         return(vn_open_modflags(ndp
, &fmode
, cmode
)); 
 128 vn_open_modflags(struct nameidata 
*ndp
, int *fmodep
, int cmode
) 
 130         struct vnode_attr va
; 
 133         VATTR_SET(&va
, va_mode
, cmode
); 
 135         return(vn_open_auth(ndp
, fmodep
, &va
)); 
 139  * Open a file with authorization, updating the contents of the structures 
 140  * pointed to by ndp, fmodep, and vap as necessary to perform the requested 
 141  * operation.  This function is used for both opens of existing files, and 
 142  * creation of new files. 
 144  * Parameters:  ndp                     The nami data pointer describing the 
 146  *              fmodep                  A pointer to an int containg the mode 
 147  *                                      information to be used for the open 
 148  *              vap                     A pointer to the vnode attribute 
 149  *                                      descriptor to be used for the open 
 151  * Indirect:    *                       Contents of the data structures pointed 
 152  *                                      to by the parameters are modified as 
 153  *                                      necessary to the requested operation. 
 158  * Notes:       The kauth_filesec_t in 'vap', if any, is in host byte order. 
 160  *              The contents of '*ndp' will be modified, based on the other 
 161  *              arguments to this function, and to return file and directory 
 162  *              data necessary to satisfy the requested operation. 
 164  *              If the file does not exist and we are creating it, then the 
 165  *              O_TRUNC flag will be cleared in '*fmodep' to indicate to the 
 166  *              caller that the file was not truncated. 
 168  *              If the file exists and the O_EXCL flag was not specified, then 
 169  *              the O_CREAT flag will be cleared in '*fmodep' to indicate to 
 170  *              the caller that the existing file was merely opened rather 
 173  *              The contents of '*vap' will be modified as necessary to 
 174  *              complete the operation, including setting of supported 
 175  *              attribute, clearing of fields containing unsupported attributes 
 176  *              in the request, if the request proceeds without them, etc.. 
 178  * XXX:         This function is too complicated in actings on its arguments 
 180  * XXX:         We should enummerate the possible errno values here, and where 
 181  *              in the code they originated. 
 184 vn_open_auth(struct nameidata 
*ndp
, int *fmodep
, struct vnode_attr 
*vap
) 
 188         vfs_context_t ctx 
= ndp
->ni_cnd
.cn_context
; 
 191         kauth_action_t action
; 
 197         if (fmode 
& O_CREAT
) { 
 198                 if ( (fmode 
& O_DIRECTORY
) ) { 
 202                 ndp
->ni_cnd
.cn_nameiop 
= CREATE
; 
 203                 ndp
->ni_cnd
.cn_flags 
= LOCKPARENT 
| LOCKLEAF 
| AUDITVNPATH1
; 
 205                 if ((fmode 
& O_EXCL
) == 0) 
 206                         ndp
->ni_cnd
.cn_flags 
|= FOLLOW
; 
 207                 if ( (error 
= namei(ndp
)) ) 
 212                 /* not found, create */ 
 214                         /* must have attributes for a new file */ 
 220                         /* authorize before creating */ 
 221                         if ((error 
= vnode_authorize(dvp
, NULL
, KAUTH_VNODE_ADD_FILE
, ctx
)) != 0) 
 224                         VATTR_SET(vap
, va_type
, VREG
); 
 226                                 vap
->va_vaflags 
|= VA_EXCLUSIVE
; 
 228                         if ((error 
= vn_create(dvp
, &ndp
->ni_vp
, &ndp
->ni_cnd
, vap
, 0, ctx
)) != 0) 
 234                                 int     update_flags 
= 0; 
 236                                 // Make sure the name & parent pointers are hooked up 
 237                                 if (vp
->v_name 
== NULL
) 
 238                                         update_flags 
|= VNODE_UPDATE_NAME
; 
 239                                 if (vp
->v_parent 
== NULLVP
) 
 240                                         update_flags 
|= VNODE_UPDATE_PARENT
; 
 243                                         vnode_update_identity(vp
, dvp
, ndp
->ni_cnd
.cn_nameptr
, ndp
->ni_cnd
.cn_namelen
, ndp
->ni_cnd
.cn_hash
, update_flags
); 
 245                                 if (need_fsevent(FSE_CREATE_FILE
, vp
)) { 
 246                                         add_fsevent(FSE_CREATE_FILE
, ctx
, 
 252                          * nameidone has to happen before we vnode_put(dvp) 
 253                          * and clear the ni_dvp field, since it may need 
 254                          * to release the fs_nodelock on the dvp 
 263                                  * Check for a creation race. 
 265                                 if ((error 
== EEXIST
) && !(fmode 
& O_EXCL
)) { 
 276                         if (fmode 
& O_EXCL
) { 
 283                 ndp
->ni_cnd
.cn_nameiop 
= LOOKUP
; 
 284                 ndp
->ni_cnd
.cn_flags 
= FOLLOW 
| LOCKLEAF 
| AUDITVNPATH1
; 
 285                 if ( (error 
= namei(ndp
)) ) 
 291                 if ( (fmode 
& O_DIRECTORY
) && vp
->v_type 
!= VDIR 
) { 
 296         if (vp
->v_type 
== VSOCK 
&& vp
->v_tag 
!= VT_FDESC
) { 
 297                 error 
= EOPNOTSUPP
;     /* Operation not supported on socket */ 
 302         if (UBCINFOMISSING(vp
)) 
 303                 panic("vn_open: ubc_info_init"); 
 304 #endif /* DIAGNOSTIC */ 
 306         /* authorize open of an existing file */ 
 307         if ((fmode 
& O_CREAT
) == 0) { 
 309                 /* disallow write operations on directories */ 
 310                 if (vnode_isdir(vp
) && (fmode 
& (FWRITE 
| O_TRUNC
))) { 
 315                 /* compute action to be authorized */ 
 318                         action 
|= KAUTH_VNODE_READ_DATA
; 
 319                 if (fmode 
& (FWRITE 
| O_TRUNC
)) 
 320                         action 
|= KAUTH_VNODE_WRITE_DATA
; 
 321                 if ((error 
= vnode_authorize(vp
, NULL
, action
, ctx
)) != 0) 
 326         if ( (error 
= VNOP_OPEN(vp
, fmode
, ctx
)) ) { 
 329         if ( (error 
= vnode_ref_ext(vp
, fmode
)) ) 
 332         /* call out to allow 3rd party notification of open.  
 333          * Ignore result of kauth_authorize_fileop call. 
 335         kauth_authorize_fileop(vfs_context_ucred(ctx
), KAUTH_FILEOP_OPEN
,  
 345                  * Check for a race against unlink.  We had a vnode 
 346                  * but according to vnode_authorize or VNOP_OPEN it 
 349                 if ((error 
== ENOENT
) && (*fmodep 
& O_CREAT
)) { 
 358  * Authorize an action against a vnode.  This has been the canonical way to 
 359  * ensure that the credential/process/etc. referenced by a vfs_context 
 360  * is granted the rights called out in 'mode' against the vnode 'vp'. 
 362  * Unfortunately, the use of VREAD/VWRITE/VEXEC makes it very difficult 
 363  * to add support for more rights.  As such, this interface will be deprecated 
 364  * and callers will use vnode_authorize instead. 
 366 #warning vn_access is deprecated 
 368 vn_access(vnode_t vp
, int mode
, vfs_context_t context
) 
 370         kauth_action_t  action
; 
 374                 action 
|= KAUTH_VNODE_READ_DATA
; 
 376                 action 
|= KAUTH_VNODE_WRITE_DATA
; 
 378                 action 
|= KAUTH_VNODE_EXECUTE
; 
 380         return(vnode_authorize(vp
, NULL
, action
, context
)); 
 387 vn_close(struct vnode 
*vp
, int flags
, kauth_cred_t cred
, struct proc 
*p
) 
 389         struct vfs_context context
; 
 393         context
.vc_ucred 
= cred
; 
 395         if (flags 
& FWASWRITTEN
) { 
 396                 if (need_fsevent(FSE_CONTENT_MODIFIED
, vp
)) { 
 397                         add_fsevent(FSE_CONTENT_MODIFIED
, &context
, 
 403         error 
= VNOP_CLOSE(vp
, flags
, &context
); 
 404         (void)vnode_rele_ext(vp
, flags
, 0); 
 414         static char *swap_read_zero_page 
= NULL
; 
 416         off_t   swap_count
, this_count
; 
 417         off_t   file_end
, read_end
; 
 421          * Reading from a swap file will get you all zeroes. 
 424         swap_count 
= uio_resid(uio
); 
 426         file_end 
= ubc_getsize(vp
); 
 427         read_end 
= uio
->uio_offset 
+ uio_resid(uio
); 
 428         if (uio
->uio_offset 
>= file_end
) { 
 429                 /* uio starts after end of file: nothing to read */ 
 431         } else if (read_end 
> file_end
) { 
 432                 /* uio extends beyond end of file: stop before that */ 
 433                 swap_count 
-= (read_end 
- file_end
); 
 436         while (swap_count 
> 0) { 
 437                 if (swap_read_zero_page 
== NULL
) { 
 442                          * Take kernel funnel so that only one thread 
 443                          * sets up "swap_read_zero_page". 
 445                         funnel_state 
= thread_funnel_set(kernel_flock
, TRUE
); 
 447                         if (swap_read_zero_page 
== NULL
) { 
 448                                 MALLOC(my_zero_page
, char *, PAGE_SIZE
, 
 450                                 memset(my_zero_page
, '?', PAGE_SIZE
); 
 452                                  * Adding a newline character here 
 453                                  * and there prevents "less(1)", for 
 454                                  * example, from getting too confused 
 455                                  * about a file with one really really 
 458                                 my_zero_page
[PAGE_SIZE
-1] = '\n'; 
 459                                 if (swap_read_zero_page 
== NULL
) { 
 460                                         swap_read_zero_page 
= my_zero_page
; 
 462                                         FREE(my_zero_page
, M_TEMP
); 
 466                                  * Someone else raced us here and won; 
 467                                  * just use their page. 
 470                         thread_funnel_set(kernel_flock
, funnel_state
); 
 473                 this_count 
= swap_count
; 
 474                 if (this_count 
> PAGE_SIZE
) { 
 475                         this_count 
= PAGE_SIZE
; 
 478                 prev_resid 
= uio_resid(uio
); 
 479                 error 
= uiomove((caddr_t
) swap_read_zero_page
, 
 485                 swap_count 
-= (prev_resid 
- uio_resid(uio
)); 
 491  * Package up an I/O request on a vnode into a uio and do it. 
 506         return vn_rdwr_64(rw
, 
 508                         (uint64_t)(uintptr_t)base
, 
 534         struct vfs_context context
; 
 536         char uio_buf
[ UIO_SIZEOF(1) ]; 
 539         context
.vc_ucred 
= cred
; 
 541         if (UIO_SEG_IS_USER_SPACE(segflg
)) { 
 542                 spacetype 
= proc_is64bit(p
) ? UIO_USERSPACE64 
: UIO_USERSPACE32
; 
 545                 spacetype 
= UIO_SYSSPACE
; 
 547         auio 
= uio_createwithbuffer(1, offset
, spacetype
, rw
,  
 548                                                                   &uio_buf
[0], sizeof(uio_buf
)); 
 549         uio_addiov(auio
, base
, len
); 
 551         if (rw 
== UIO_READ
) { 
 552                 if (vp
->v_flag 
& VSWAP
) { 
 553                         error 
= vn_read_swapfile(vp
, auio
); 
 555                         error 
= VNOP_READ(vp
, auio
, ioflg
, &context
); 
 558                 error 
= VNOP_WRITE(vp
, auio
, ioflg
, &context
); 
 562                 // LP64todo - fix this 
 563                 *aresid 
= uio_resid(auio
); 
 565                 if (uio_resid(auio
) && error 
== 0) 
 571  * File table vnode read routine. 
 574 vn_read(struct fileproc 
*fp
, struct uio 
*uio
, kauth_cred_t cred
, 
 575         int flags
, struct proc 
*p
) 
 580         struct vfs_context context
; 
 583         context
.vc_ucred 
= cred
; 
 585         vp 
= (struct vnode 
*)fp
->f_fglob
->fg_data
; 
 586         if ( (error 
= vnode_getwithref(vp
)) ) { 
 590         if (fp
->f_fglob
->fg_flag 
& FNONBLOCK
) 
 593         if ((flags 
& FOF_OFFSET
) == 0) 
 594                 uio
->uio_offset 
= fp
->f_fglob
->fg_offset
; 
 595         count 
= uio_resid(uio
); 
 597         if (vp
->v_flag 
& VSWAP
) { 
 598                 /* special case for swap files */ 
 599                 error 
= vn_read_swapfile(vp
, uio
); 
 601                 error 
= VNOP_READ(vp
, uio
, ioflag
, &context
); 
 603         if ((flags 
& FOF_OFFSET
) == 0) 
 604                 fp
->f_fglob
->fg_offset 
+= count 
- uio_resid(uio
); 
 612  * File table vnode write routine. 
 615 vn_write(struct fileproc 
*fp
, struct uio 
*uio
, kauth_cred_t cred
, 
 616         int flags
, struct proc 
*p
) 
 621         struct vfs_context context
; 
 624         context
.vc_ucred 
= cred
; 
 626         vp 
= (struct vnode 
*)fp
->f_fglob
->fg_data
; 
 627         if ( (error 
= vnode_getwithref(vp
)) ) { 
 631         if (vp
->v_type 
== VREG 
&& (fp
->f_fglob
->fg_flag 
& O_APPEND
)) 
 633         if (fp
->f_fglob
->fg_flag 
& FNONBLOCK
) 
 635         if ((fp
->f_fglob
->fg_flag 
& O_FSYNC
) || 
 636                 (vp
->v_mount 
&& (vp
->v_mount
->mnt_flag 
& MNT_SYNCHRONOUS
))) 
 639         if ((flags 
& FOF_OFFSET
) == 0) { 
 640                 uio
->uio_offset 
= fp
->f_fglob
->fg_offset
; 
 641                 count 
= uio_resid(uio
); 
 643         if (p 
&& (vp
->v_type 
== VREG
) && 
 644             (((uio
->uio_offset 
+ uio_uio_resid(uio
)) > p
->p_rlimit
[RLIMIT_FSIZE
].rlim_cur
) || 
 645              (uio_uio_resid(uio
) > (p
->p_rlimit
[RLIMIT_FSIZE
].rlim_cur 
- uio
->uio_offset
)))) { 
 651         error 
= VNOP_WRITE(vp
, uio
, ioflag
, &context
); 
 653         if ((flags 
& FOF_OFFSET
) == 0) { 
 654                 if (ioflag 
& IO_APPEND
) 
 655                         fp
->f_fglob
->fg_offset 
= uio
->uio_offset
; 
 657                         fp
->f_fglob
->fg_offset 
+= count 
- uio_resid(uio
); 
 661          * Set the credentials on successful writes 
 663         if ((error 
== 0) && (vp
->v_tag 
== VT_NFS
) && (UBCINFOEXISTS(vp
))) { 
 665                  * When called from aio subsystem, we only have the proc from 
 666                  * which to get the credential, at this point, so use that 
 667                  * instead.  This means aio functions are incompatible with 
 668                  * per-thread credentials (aio operations are proxied).  We 
 669                  * can't easily correct the aio vs. settid race in this case 
 670                  * anyway, so we disallow it. 
 672                 if ((flags 
& FOF_PCRED
) == 0) { 
 673                         ubc_setthreadcred(vp
, p
, current_thread()); 
 683  * File table vnode stat routine. 
 686 vn_stat_noauth(struct vnode 
*vp
, struct stat 
*sb
, kauth_filesec_t 
*xsec
, vfs_context_t ctx
) 
 688         struct vnode_attr va
; 
 691         kauth_filesec_t fsec
; 
 694         VATTR_WANTED(&va
, va_fsid
); 
 695         VATTR_WANTED(&va
, va_fileid
); 
 696         VATTR_WANTED(&va
, va_mode
); 
 697         VATTR_WANTED(&va
, va_type
); 
 698         VATTR_WANTED(&va
, va_nlink
); 
 699         VATTR_WANTED(&va
, va_uid
); 
 700         VATTR_WANTED(&va
, va_gid
); 
 701         VATTR_WANTED(&va
, va_rdev
); 
 702         VATTR_WANTED(&va
, va_data_size
); 
 703         VATTR_WANTED(&va
, va_access_time
); 
 704         VATTR_WANTED(&va
, va_modify_time
); 
 705         VATTR_WANTED(&va
, va_change_time
); 
 706         VATTR_WANTED(&va
, va_flags
); 
 707         VATTR_WANTED(&va
, va_gen
); 
 708         VATTR_WANTED(&va
, va_iosize
); 
 709         /* lower layers will synthesise va_total_alloc from va_data_size if required */ 
 710         VATTR_WANTED(&va
, va_total_alloc
); 
 712                 VATTR_WANTED(&va
, va_uuuid
); 
 713                 VATTR_WANTED(&va
, va_guuid
); 
 714                 VATTR_WANTED(&va
, va_acl
); 
 716         error 
= vnode_getattr(vp
, &va
, ctx
); 
 720          * Copy from vattr table 
 722         sb
->st_dev 
= va
.va_fsid
; 
 723         sb
->st_ino 
= (ino_t
)va
.va_fileid
; 
 725         switch (vp
->v_type
) { 
 752         sb
->st_nlink 
= VATTR_IS_SUPPORTED(&va
, va_nlink
) ? (u_int16_t
)va
.va_nlink 
: 1; 
 753         sb
->st_uid 
= va
.va_uid
; 
 754         sb
->st_gid 
= va
.va_gid
; 
 755         sb
->st_rdev 
= va
.va_rdev
; 
 756         sb
->st_size 
= va
.va_data_size
; 
 757         sb
->st_atimespec 
= va
.va_access_time
; 
 758         sb
->st_mtimespec 
= va
.va_modify_time
; 
 759         sb
->st_ctimespec 
= va
.va_change_time
; 
 760         sb
->st_blksize 
= va
.va_iosize
; 
 761         sb
->st_flags 
= va
.va_flags
; 
 762         sb
->st_blocks 
= roundup(va
.va_total_alloc
, 512) / 512; 
 764         /* if we're interested in exended security data and we got an ACL */ 
 766                 if (!VATTR_IS_SUPPORTED(&va
, va_acl
) && 
 767                     !VATTR_IS_SUPPORTED(&va
, va_uuuid
) && 
 768                     !VATTR_IS_SUPPORTED(&va
, va_guuid
)) { 
 769                         *xsec 
= KAUTH_FILESEC_NONE
; 
 772                         if (VATTR_IS_SUPPORTED(&va
, va_acl
) && (va
.va_acl 
!= NULL
)) { 
 773                                 fsec 
= kauth_filesec_alloc(va
.va_acl
->acl_entrycount
); 
 775                                 fsec 
= kauth_filesec_alloc(0); 
 781                         fsec
->fsec_magic 
= KAUTH_FILESEC_MAGIC
; 
 782                         if (VATTR_IS_SUPPORTED(&va
, va_uuuid
)) { 
 783                                 fsec
->fsec_owner 
= va
.va_uuuid
; 
 785                                 fsec
->fsec_owner 
= kauth_null_guid
; 
 787                         if (VATTR_IS_SUPPORTED(&va
, va_guuid
)) { 
 788                                 fsec
->fsec_group 
= va
.va_guuid
; 
 790                                 fsec
->fsec_group 
= kauth_null_guid
; 
 792                         if (VATTR_IS_SUPPORTED(&va
, va_acl
) && (va
.va_acl 
!= NULL
)) { 
 793                                 bcopy(va
.va_acl
, &(fsec
->fsec_acl
), KAUTH_ACL_COPYSIZE(va
.va_acl
)); 
 795                                 fsec
->fsec_acl
.acl_entrycount 
= KAUTH_FILESEC_NOACL
; 
 801         /* Do not give the generation number out to unpriviledged users */ 
 802         if (va
.va_gen 
&& !vfs_context_issuser(ctx
)) 
 805                 sb
->st_gen 
= va
.va_gen
; 
 809         if (VATTR_IS_SUPPORTED(&va
, va_acl
) && va
.va_acl 
!= NULL
) 
 810                 kauth_acl_free(va
.va_acl
); 
 815 vn_stat(struct vnode 
*vp
, struct stat 
*sb
, kauth_filesec_t 
*xsec
, vfs_context_t ctx
) 
 820         if ((error 
= vnode_authorize(vp
, NULL
, KAUTH_VNODE_READ_ATTRIBUTES 
| KAUTH_VNODE_READ_SECURITY
, ctx
)) != 0) 
 824         return(vn_stat_noauth(vp
, sb
, xsec
, ctx
)); 
 829  * File table vnode ioctl routine. 
 832 vn_ioctl(fp
, com
, data
, p
) 
 838         register struct vnode 
*vp 
= ((struct vnode 
*)fp
->f_fglob
->fg_data
); 
 839         struct vfs_context context
; 
 845         if ( (error 
= vnode_getwithref(vp
)) ) { 
 849         context
.vc_ucred 
= kauth_cred_proc_ref(p
);      /* XXX kauth_cred_get() ??? */ 
 851         switch (vp
->v_type
) { 
 855                 if (com 
== FIONREAD
) { 
 856                         if ((error 
= vnode_size(vp
, &file_size
, &context
)) != 0) 
 858                         *(int *)data 
= file_size 
- fp
->f_fglob
->fg_offset
; 
 861                 if (com 
== FIONBIO 
|| com 
== FIOASYNC
) {        /* XXX */ 
 874                 /* Should not be able to set block size from user space */ 
 875                 if (com 
== DKIOCSETBLOCKSIZE
) { 
 880                 if (com 
== FIODTYPE
) { 
 881                         if (vp
->v_type 
== VBLK
) { 
 882                                 if (major(vp
->v_rdev
) >= nblkdev
) { 
 886                                 *(int *)data 
= bdevsw
[major(vp
->v_rdev
)].d_type
; 
 888                         } else if (vp
->v_type 
== VCHR
) { 
 889                                 if (major(vp
->v_rdev
) >= nchrdev
) { 
 893                                 *(int *)data 
= cdevsw
[major(vp
->v_rdev
)].d_type
; 
 900                 error 
= VNOP_IOCTL(vp
, com
, data
, fp
->f_fglob
->fg_flag
, &context
); 
 902                 if (error 
== 0 && com 
== TIOCSCTTY
) { 
 905                         funnel_state 
= thread_funnel_set(kernel_flock
, TRUE
); 
 906                         ttyvp 
= p
->p_session
->s_ttyvp
; 
 907                         p
->p_session
->s_ttyvp 
= vp
; 
 908                         thread_funnel_set(kernel_flock
, funnel_state
); 
 916         kauth_cred_unref(&context
.vc_ucred
); 
 921  * File table vnode select routine. 
 924 vn_select(fp
, which
, wql
, p
) 
 931         struct vnode 
* vp 
= (struct vnode 
*)fp
->f_fglob
->fg_data
; 
 932         struct vfs_context context
; 
 934         if ( (error 
= vnode_getwithref(vp
)) == 0 ) { 
 936                 context
.vc_ucred 
= fp
->f_fglob
->fg_cred
; 
 938                 error 
= VNOP_SELECT(vp
, which
, fp
->f_fglob
->fg_flag
, wql
, &context
); 
 947  * Check that the vnode is still valid, and if so 
 948  * acquire requested lock. 
 951 vn_lock(__unused vnode_t vp
, __unused 
int flags
, __unused proc_t p
) 
 957  * File table vnode close routine. 
 964         struct vnode 
*vp 
= (struct vnode 
*)fg
->fg_data
; 
 967         if ( (error 
= vnode_getwithref(vp
)) == 0 ) { 
 968                 error 
= vn_close(vp
, fg
->fg_flag
, fg
->fg_cred
, p
); 
 976 vn_pathconf(vnode_t vp
, int name
, register_t 
*retval
, vfs_context_t ctx
) 
 981         case _PC_EXTENDED_SECURITY_NP
: 
 982                 *retval 
= vfs_extendedsecurity(vnode_mount(vp
)); 
 984         case _PC_AUTH_OPAQUE_NP
: 
 985                 *retval 
= vfs_authopaque(vnode_mount(vp
)); 
 988                 error 
= VNOP_PATHCONF(vp
, name
, retval
, ctx
); 
 996 vn_kqfilt_add(fp
, kn
, p
) 
1001         struct vnode 
*vp 
= (struct vnode 
*)fp
->f_fglob
->fg_data
; 
1002         struct vfs_context context
; 
1006         if ( (error 
= vnode_getwithref(vp
)) == 0 ) { 
1007                 context
.vc_proc 
= p
; 
1008                 context
.vc_ucred 
= kauth_cred_proc_ref(p
);      /* XXX kauth_cred_get() ??? */ 
1010                 funnel_state 
= thread_funnel_set(kernel_flock
, TRUE
); 
1011                 error 
= VNOP_KQFILT_ADD(vp
, kn
, &context
); 
1012                 thread_funnel_set(kernel_flock
, funnel_state
); 
1014                 (void)vnode_put(vp
); 
1015                 kauth_cred_unref(&context
.vc_ucred
); 
1021 /* No one calls this yet. */ 
1023 vn_kqfilt_remove(vp
, ident
, p
) 
1028         struct vfs_context context
; 
1032         if ( (error 
= vnode_getwithref(vp
)) == 0 ) { 
1033                 context
.vc_proc 
= p
; 
1034                 context
.vc_ucred 
= kauth_cred_proc_ref(p
);      /* XXX kauth_cred_get() ??? */ 
1036                 funnel_state 
= thread_funnel_set(kernel_flock
, TRUE
); 
1037                 error 
= VNOP_KQFILT_REMOVE(vp
, ident
, &context
); 
1038                 thread_funnel_set(kernel_flock
, funnel_state
); 
1040                 (void)vnode_put(vp
); 
1041                 kauth_cred_unref(&context
.vc_ucred
);