2 * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_OSREFERENCE_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
10 * License may not be used to create, or enable the creation or
11 * redistribution of, unlawful or unlicensed copies of an Apple operating
12 * system, or to circumvent, violate, or enable the circumvention or
13 * violation of, any terms of an Apple operating system software license
16 * Please obtain a copy of the License at
17 * http://www.opensource.apple.com/apsl/ and read it before using this
20 * The Original Code and all software distributed under the License are
21 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
22 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
23 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
25 * Please see the License for the specific language governing rights and
26 * limitations under the License.
28 * @APPLE_LICENSE_OSREFERENCE_HEADER_END@
30 /* Copyright (c) 1995, 1997 Apple Computer, Inc. All Rights Reserved */
32 * Copyright (c) 1982, 1986, 1989, 1991, 1993
33 * The Regents of the University of California. All rights reserved.
34 * (c) UNIX System Laboratories, Inc.
35 * All or some portions of this file are derived from material licensed
36 * to the University of California by American Telephone and Telegraph
37 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
38 * the permission of UNIX System Laboratories, Inc.
40 * Redistribution and use in source and binary forms, with or without
41 * modification, are permitted provided that the following conditions
43 * 1. Redistributions of source code must retain the above copyright
44 * notice, this list of conditions and the following disclaimer.
45 * 2. Redistributions in binary form must reproduce the above copyright
46 * notice, this list of conditions and the following disclaimer in the
47 * documentation and/or other materials provided with the distribution.
48 * 3. All advertising materials mentioning features or use of this software
49 * must display the following acknowledgement:
50 * This product includes software developed by the University of
51 * California, Berkeley and its contributors.
52 * 4. Neither the name of the University nor the names of its contributors
53 * may be used to endorse or promote products derived from this software
54 * without specific prior written permission.
56 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
57 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
58 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
59 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
60 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
61 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
62 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
63 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
64 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
65 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
68 * @(#)kern_descrip.c 8.8 (Berkeley) 2/14/95
71 #include <sys/param.h>
72 #include <sys/systm.h>
73 #include <sys/filedesc.h>
74 #include <sys/kernel.h>
75 #include <sys/vnode_internal.h>
76 #include <sys/proc_internal.h>
77 #include <sys/kauth.h>
78 #include <sys/file_internal.h>
79 #include <sys/socket.h>
80 #include <sys/socketvar.h>
82 #include <sys/ioctl.h>
83 #include <sys/fcntl.h>
84 #include <sys/malloc.h>
86 #include <sys/syslog.h>
87 #include <sys/unistd.h>
88 #include <sys/resourcevar.h>
89 #include <sys/aio_kern.h>
91 #include <kern/lock.h>
93 #include <bsm/audit_kernel.h>
95 #include <sys/mount_internal.h>
96 #include <sys/kdebug.h>
97 #include <sys/sysproto.h>
99 #include <kern/kern_types.h>
100 #include <kern/kalloc.h>
101 #include <libkern/OSAtomic.h>
106 int fdopen(dev_t dev
, int mode
, int type
, struct proc
*p
);
107 int ogetdtablesize(struct proc
*p
, void *uap
, register_t
*retval
);
108 int finishdup(struct proc
* p
, struct filedesc
*fdp
, int old
, int new, register_t
*retval
);
110 int closef(struct fileglob
*fg
, struct proc
*p
);
111 int falloc_locked(struct proc
*p
, struct fileproc
**resultfp
, int *resultfd
, int locked
);
112 void fddrop(struct proc
*p
, int fd
);
113 int fdgetf_noref(struct proc
*p
, int fd
, struct fileproc
**resultfp
);
114 void fg_drop(struct fileproc
* fp
);
115 void fg_free(struct fileglob
*fg
);
116 void fg_ref(struct fileproc
* fp
);
118 static int closef_finish(struct fileproc
*fp
, struct fileglob
*fg
, struct proc
*p
);
120 extern void file_lock_init(void);
121 extern int is_suser(void);
122 extern int kqueue_stat(struct fileproc
*fp
, struct stat
*st
, struct proc
*p
);
123 extern int soo_stat(struct socket
*so
, struct stat
*ub
);
124 extern int vn_path_package_check(vnode_t vp
, char *path
, int pathlen
, int *component
);
126 extern kauth_scope_t kauth_scope_fileop
;
128 #define f_flag f_fglob->fg_flag
129 #define f_type f_fglob->fg_type
130 #define f_msgcount f_fglob->fg_msgcount
131 #define f_cred f_fglob->fg_cred
132 #define f_ops f_fglob->fg_ops
133 #define f_offset f_fglob->fg_offset
134 #define f_data f_fglob->fg_data
136 * Descriptor management.
138 struct filelist filehead
; /* head of list of open files */
139 struct fmsglist fmsghead
; /* head of list of open files */
140 struct fmsglist fmsg_ithead
; /* head of list of open files */
141 int nfiles
; /* actual number of open files */
144 lck_grp_attr_t
* file_lck_grp_attr
;
145 lck_grp_t
* file_lck_grp
;
146 lck_attr_t
* file_lck_attr
;
148 lck_mtx_t
* uipc_lock
;
149 lck_mtx_t
* file_iterate_lcok
;
150 lck_mtx_t
* file_flist_lock
;
157 /* allocate file lock group attribute and group */
158 file_lck_grp_attr
= lck_grp_attr_alloc_init();
160 file_lck_grp
= lck_grp_alloc_init("file", file_lck_grp_attr
);
162 /* Allocate file lock attribute */
163 file_lck_attr
= lck_attr_alloc_init();
165 uipc_lock
= lck_mtx_alloc_init(file_lck_grp
, file_lck_attr
);
166 file_iterate_lcok
= lck_mtx_alloc_init(file_lck_grp
, file_lck_attr
);
167 file_flist_lock
= lck_mtx_alloc_init(file_lck_grp
, file_lck_attr
);
175 proc_fdlock(struct proc
*p
)
177 lck_mtx_lock(&p
->p_fdmlock
);
181 proc_fdunlock(struct proc
*p
)
183 lck_mtx_unlock(&p
->p_fdmlock
);
187 * System calls on descriptors.
191 getdtablesize(struct proc
*p
, __unused
struct getdtablesize_args
*uap
, register_t
*retval
)
194 *retval
= min((int)p
->p_rlimit
[RLIMIT_NOFILE
].rlim_cur
, maxfiles
);
201 ogetdtablesize(struct proc
*p
, __unused
void *uap
, register_t
*retval
)
204 *retval
= min((int)p
->p_rlimit
[RLIMIT_NOFILE
].rlim_cur
, NOFILE
);
210 static __inline__
void
211 _fdrelse(struct filedesc
*fdp
, int fd
)
213 if (fd
< fdp
->fd_freefile
)
214 fdp
->fd_freefile
= fd
;
216 if (fd
> fdp
->fd_lastfile
)
217 panic("fdrelse: fd_lastfile inconsistent");
219 fdp
->fd_ofiles
[fd
] = NULL
;
220 fdp
->fd_ofileflags
[fd
] = 0;
222 while ((fd
= fdp
->fd_lastfile
) > 0 &&
223 fdp
->fd_ofiles
[fd
] == NULL
&&
224 !(fdp
->fd_ofileflags
[fd
] & UF_RESERVED
))
229 * Duplicate a file descriptor.
235 struct dup_args
*uap
;
238 register struct filedesc
*fdp
= p
->p_fd
;
239 register int old
= uap
->fd
;
244 if ( (error
= fp_lookup(p
, old
, &fp
, 1)) ) {
248 if ( (error
= fdalloc(p
, 0, &new)) ) {
249 fp_drop(p
, old
, fp
, 1);
253 error
= finishdup(p
, fdp
, old
, new, retval
);
254 fp_drop(p
, old
, fp
, 1);
261 * Duplicate a file descriptor to a particular value.
267 struct dup2_args
*uap
;
270 register struct filedesc
*fdp
= p
->p_fd
;
271 register int old
= uap
->from
, new = uap
->to
;
277 if ( (error
= fp_lookup(p
, old
, &fp
, 1)) ) {
282 new >= p
->p_rlimit
[RLIMIT_NOFILE
].rlim_cur
||
284 fp_drop(p
, old
, fp
, 1);
289 fp_drop(p
, old
, fp
, 1);
294 if (new < 0 || new >= fdp
->fd_nfiles
) {
295 if ( (error
= fdalloc(p
, new, &i
)) ) {
296 fp_drop(p
, old
, fp
, 1);
305 struct fileproc
**fpp
;
308 flags
= fdp
->fd_ofileflags
[new];
309 if ((flags
& (UF_RESERVED
| UF_CLOSING
)) == UF_RESERVED
) {
310 fp_drop(p
, old
, fp
, 1);
316 * dup2() must succeed even if the close has an error.
318 if (*(fpp
= &fdp
->fd_ofiles
[new])) {
319 struct fileproc
*nfp
= *fpp
;
321 close_internal(p
, new, nfp
, (CLOSEINT_LOCKED
| CLOSEINT_WAITONCLOSE
| CLOSEINT_NOFDRELSE
| CLOSEINT_NOFDNOREF
));
325 error
= finishdup(p
, fdp
, old
, new, retval
);
326 fp_drop(p
, old
, fp
, 1);
333 * The file control system call.
336 fcntl(p
, uap
, retval
)
338 struct fcntl_args
*uap
;
342 struct filedesc
*fdp
= p
->p_fd
;
346 int i
, tmp
, error
, error2
, flg
= F_POSIX
;
348 struct vfs_context context
;
352 int devBlockSize
= 0;
356 AUDIT_ARG(fd
, uap
->fd
);
357 AUDIT_ARG(cmd
, uap
->cmd
);
360 if ( (error
= fp_lookup(p
, fd
, &fp
, 1)) ) {
365 context
.vc_ucred
= fp
->f_cred
;
366 if (proc_is64bit(p
)) {
370 /* since the arg parameter is defined as a long but may be either
371 * a long or a pointer we must take care to handle sign extension
372 * issues. Our sys call munger will sign extend a long when we are
373 * called from a 32-bit process. Since we can never have an address
374 * greater than 32-bits from a 32-bit process we lop off the top
375 * 32-bits to avoid getting the wrong address
377 argp
= CAST_USER_ADDR_T(uap
->arg
);
380 pop
= &fdp
->fd_ofileflags
[fd
];
385 newmin
= CAST_DOWN(int, uap
->arg
);
386 if ((u_int
)newmin
>= p
->p_rlimit
[RLIMIT_NOFILE
].rlim_cur
||
387 newmin
>= maxfiles
) {
391 if ( (error
= fdalloc(p
, newmin
, &i
)) )
393 error
= finishdup(p
, fdp
, fd
, i
, retval
);
397 *retval
= (*pop
& UF_EXCLOSE
)? 1 : 0;
402 *pop
= (*pop
&~ UF_EXCLOSE
) |
403 (uap
->arg
& 1)? UF_EXCLOSE
: 0;
408 *retval
= OFLAGS(fp
->f_flag
);
413 fp
->f_flag
&= ~FCNTLFLAGS
;
414 tmp
= CAST_DOWN(int, uap
->arg
);
415 fp
->f_flag
|= FFLAGS(tmp
) & FCNTLFLAGS
;
416 tmp
= fp
->f_flag
& FNONBLOCK
;
417 error
= fo_ioctl(fp
, FIONBIO
, (caddr_t
)&tmp
, p
);
420 tmp
= fp
->f_flag
& FASYNC
;
421 error
= fo_ioctl(fp
, FIOASYNC
, (caddr_t
)&tmp
, p
);
424 fp
->f_flag
&= ~FNONBLOCK
;
426 (void)fo_ioctl(fp
, FIONBIO
, (caddr_t
)&tmp
, p
);
430 if (fp
->f_type
== DTYPE_SOCKET
) {
431 *retval
= ((struct socket
*)fp
->f_data
)->so_pgid
;
435 error
= fo_ioctl(fp
, (int)TIOCGPGRP
, (caddr_t
)retval
, p
);
440 tmp
= CAST_DOWN(pid_t
, uap
->arg
);
441 if (fp
->f_type
== DTYPE_SOCKET
) {
442 ((struct socket
*)fp
->f_data
)->so_pgid
= tmp
;
446 if (fp
->f_type
== DTYPE_PIPE
) {
447 error
= fo_ioctl(fp
, (int)TIOCSPGRP
, (caddr_t
)&tmp
, p
);
454 struct proc
*p1
= pfind(tmp
);
459 tmp
= (int)p1
->p_pgrp
->pg_id
;
461 error
= fo_ioctl(fp
, (int)TIOCSPGRP
, (caddr_t
)&tmp
, p
);
466 /* Fall into F_SETLK */
469 if (fp
->f_type
!= DTYPE_VNODE
) {
473 vp
= (struct vnode
*)fp
->f_data
;
476 offset
= fp
->f_offset
;
479 /* Copy in the lock structure */
480 error
= copyin(argp
, (caddr_t
)&fl
, sizeof (fl
));
484 if ( (error
= vnode_getwithref(vp
)) ) {
487 if (fl
.l_whence
== SEEK_CUR
)
488 fl
.l_start
+= offset
;
493 if ((fflag
& FREAD
) == 0) {
498 OSBitOrAtomic(P_LADVLOCK
, &p
->p_ladvflag
);
499 error
= VNOP_ADVLOCK(vp
, (caddr_t
)p
, F_SETLK
, &fl
, flg
, &context
);
504 if ((fflag
& FWRITE
) == 0) {
509 OSBitOrAtomic(P_LADVLOCK
, &p
->p_ladvflag
);
510 error
= VNOP_ADVLOCK(vp
, (caddr_t
)p
, F_SETLK
, &fl
, flg
, &context
);
515 error
= VNOP_ADVLOCK(vp
, (caddr_t
)p
, F_UNLCK
, &fl
,
527 if (fp
->f_type
!= DTYPE_VNODE
) {
531 vp
= (struct vnode
*)fp
->f_data
;
533 offset
= fp
->f_offset
;
536 /* Copy in the lock structure */
537 error
= copyin(argp
, (caddr_t
)&fl
, sizeof (fl
));
541 if ( (error
= vnode_getwithref(vp
)) == 0 ) {
542 if (fl
.l_whence
== SEEK_CUR
)
543 fl
.l_start
+= offset
;
545 error
= VNOP_ADVLOCK(vp
, (caddr_t
)p
, F_GETLK
, &fl
, F_POSIX
, &context
);
550 error
= copyout((caddr_t
)&fl
, argp
, sizeof (fl
));
554 case F_PREALLOCATE
: {
555 fstore_t alloc_struct
; /* structure for allocate command */
556 u_int32_t alloc_flags
= 0;
558 if (fp
->f_type
!= DTYPE_VNODE
) {
563 vp
= (struct vnode
*)fp
->f_data
;
566 /* make sure that we have write permission */
567 if ((fp
->f_flag
& FWRITE
) == 0) {
572 error
= copyin(argp
, (caddr_t
)&alloc_struct
, sizeof (alloc_struct
));
576 /* now set the space allocated to 0 */
577 alloc_struct
.fst_bytesalloc
= 0;
580 * Do some simple parameter checking
583 /* set up the flags */
585 alloc_flags
|= PREALLOCATE
;
587 if (alloc_struct
.fst_flags
& F_ALLOCATECONTIG
)
588 alloc_flags
|= ALLOCATECONTIG
;
590 if (alloc_struct
.fst_flags
& F_ALLOCATEALL
)
591 alloc_flags
|= ALLOCATEALL
;
594 * Do any position mode specific stuff. The only
595 * position mode supported now is PEOFPOSMODE
598 switch (alloc_struct
.fst_posmode
) {
601 if (alloc_struct
.fst_offset
!= 0) {
606 alloc_flags
|= ALLOCATEFROMPEOF
;
610 if (alloc_struct
.fst_offset
<= 0) {
615 alloc_flags
|= ALLOCATEFROMVOL
;
623 if ( (error
= vnode_getwithref(vp
)) == 0 ) {
625 * call allocate to get the space
627 error
= VNOP_ALLOCATE(vp
,alloc_struct
.fst_length
,alloc_flags
,
628 &alloc_struct
.fst_bytesalloc
, alloc_struct
.fst_offset
,
632 error2
= copyout((caddr_t
)&alloc_struct
, argp
, sizeof (alloc_struct
));
641 if (fp
->f_type
!= DTYPE_VNODE
) {
647 error
= copyin(argp
, (caddr_t
)&offset
, sizeof (off_t
));
652 * Make sure that we are root. Growing a file
653 * without zero filling the data is a security hole
654 * root would have access anyway so we'll allow it
661 vp
= (struct vnode
*)fp
->f_data
;
663 if ( (error
= vnode_getwithref(vp
)) == 0 ) {
667 error
= vnode_setsize(vp
, offset
, IO_NOZEROFILL
, &context
);
674 if (fp
->f_type
!= DTYPE_VNODE
) {
678 vp
= (struct vnode
*)fp
->f_data
;
681 if ( (error
= vnode_getwithref(vp
)) == 0) {
683 vnode_clearnoreadahead(vp
);
685 vnode_setnoreadahead(vp
);
692 if (fp
->f_type
!= DTYPE_VNODE
) {
696 vp
= (struct vnode
*)fp
->f_data
;
699 if ( (error
= vnode_getwithref(vp
)) == 0 ) {
701 vnode_setnocache(vp
);
703 vnode_clearnocache(vp
);
709 case F_GLOBAL_NOCACHE
:
710 if (fp
->f_type
!= DTYPE_VNODE
) {
714 vp
= (struct vnode
*)fp
->f_data
;
717 if ( (error
= vnode_getwithref(vp
)) == 0 ) {
719 *retval
= vnode_isnocache(vp
);
722 vnode_setnocache(vp
);
724 vnode_clearnocache(vp
);
731 struct radvisory ra_struct
;
733 if (fp
->f_type
!= DTYPE_VNODE
) {
737 vp
= (struct vnode
*)fp
->f_data
;
740 if ( (error
= copyin(argp
, (caddr_t
)&ra_struct
, sizeof (ra_struct
))) )
742 if ( (error
= vnode_getwithref(vp
)) == 0 ) {
743 error
= VNOP_IOCTL(vp
, F_RDADVISE
, (caddr_t
)&ra_struct
, 0, &context
);
750 case F_READBOOTSTRAP
:
751 case F_WRITEBOOTSTRAP
: {
752 fbootstraptransfer_t fbt_struct
;
753 user_fbootstraptransfer_t user_fbt_struct
;
755 caddr_t boot_structp
;
757 if (fp
->f_type
!= DTYPE_VNODE
) {
761 vp
= (struct vnode
*)fp
->f_data
;
764 if (IS_64BIT_PROCESS(p
)) {
765 sizeof_struct
= sizeof(user_fbt_struct
);
766 boot_structp
= (caddr_t
) &user_fbt_struct
;
769 sizeof_struct
= sizeof(fbt_struct
);
770 boot_structp
= (caddr_t
) &fbt_struct
;
772 error
= copyin(argp
, boot_structp
, sizeof_struct
);
775 if ( (error
= vnode_getwithref(vp
)) ) {
778 if (uap
->cmd
== F_WRITEBOOTSTRAP
) {
780 * Make sure that we are root. Updating the
781 * bootstrap on a disk could be a security hole
789 if (strcmp(vnode_mount(vp
)->mnt_vfsstat
.f_fstypename
, "hfs") != 0) {
793 * call vnop_ioctl to handle the I/O
795 error
= VNOP_IOCTL(vp
, uap
->cmd
, boot_structp
, 0, &context
);
801 struct log2phys l2p_struct
; /* structure for allocate command */
803 if (fp
->f_type
!= DTYPE_VNODE
) {
807 vp
= (struct vnode
*)fp
->f_data
;
809 if ( (error
= vnode_getwithref(vp
)) ) {
812 error
= VNOP_OFFTOBLK(vp
, fp
->f_offset
, &lbn
);
817 error
= VNOP_BLKTOOFF(vp
, lbn
, &offset
);
822 devBlockSize
= vfs_devblocksize(vnode_mount(vp
));
824 error
= VNOP_BLOCKMAP(vp
, offset
, devBlockSize
, &bn
, NULL
, NULL
, 0, &context
);
829 l2p_struct
.l2p_flags
= 0; /* for now */
830 l2p_struct
.l2p_contigbytes
= 0; /* for now */
831 l2p_struct
.l2p_devoffset
= bn
* devBlockSize
;
832 l2p_struct
.l2p_devoffset
+= fp
->f_offset
- offset
;
833 error
= copyout((caddr_t
)&l2p_struct
, argp
, sizeof (l2p_struct
));
841 if (fp
->f_type
!= DTYPE_VNODE
) {
845 vp
= (struct vnode
*)fp
->f_data
;
848 pathlen
= MAXPATHLEN
;
849 MALLOC(pathbufp
, char *, pathlen
, M_TEMP
, M_WAITOK
);
850 if (pathbufp
== NULL
) {
854 if ( (error
= vnode_getwithref(vp
)) == 0 ) {
855 error
= vn_getpath(vp
, pathbufp
, &pathlen
);
859 error
= copyout((caddr_t
)pathbufp
, argp
, pathlen
);
861 FREE(pathbufp
, M_TEMP
);
865 case F_PATHPKG_CHECK
: {
869 if (fp
->f_type
!= DTYPE_VNODE
) {
873 vp
= (struct vnode
*)fp
->f_data
;
876 pathlen
= MAXPATHLEN
;
877 pathbufp
= kalloc(MAXPATHLEN
);
879 if ( (error
= copyinstr(argp
, pathbufp
, MAXPATHLEN
, &pathlen
)) == 0 ) {
880 if ( (error
= vnode_getwithref(vp
)) == 0 ) {
881 error
= vn_path_package_check(vp
, pathbufp
, pathlen
, retval
);
886 kfree(pathbufp
, MAXPATHLEN
);
890 case F_CHKCLEAN
: // used by regression tests to see if all dirty pages got cleaned by fsync()
891 case F_FULLFSYNC
: // fsync + flush the journal + DKIOCSYNCHRONIZECACHE
892 case F_FREEZE_FS
: // freeze all other fs operations for the fs of this fd
893 case F_THAW_FS
: { // thaw all frozen fs operations for the fs of this fd
894 if (fp
->f_type
!= DTYPE_VNODE
) {
898 vp
= (struct vnode
*)fp
->f_data
;
901 if ( (error
= vnode_getwithref(vp
)) == 0 ) {
902 error
= VNOP_IOCTL(vp
, uap
->cmd
, (caddr_t
)NULL
, 0, &context
);
910 if (uap
->cmd
< FCNTL_FS_SPECIFIC_BASE
) {
915 // if it's a fs-specific fcntl() then just pass it through
917 if (fp
->f_type
!= DTYPE_VNODE
) {
921 vp
= (struct vnode
*)fp
->f_data
;
924 if ( (error
= vnode_getwithref(vp
)) == 0 ) {
925 error
= VNOP_IOCTL(vp
, uap
->cmd
, CAST_DOWN(caddr_t
, argp
), 0, &context
);
934 AUDIT_ARG(vnpath_withref
, vp
, ARG_VNODE1
);
935 fp_drop(p
, fd
, fp
, 0);
938 fp_drop(p
, fd
, fp
, 1);
944 * Common code for dup, dup2, and fcntl(F_DUPFD).
947 finishdup(struct proc
* p
, struct filedesc
*fdp
, int old
, int new, register_t
*retval
)
949 struct fileproc
*nfp
;
950 struct fileproc
*ofp
;
952 if ((ofp
= fdp
->fd_ofiles
[old
]) == NULL
||
953 (fdp
->fd_ofileflags
[old
] & UF_RESERVED
)) {
960 MALLOC_ZONE(nfp
, struct fileproc
*, sizeof(struct fileproc
), M_FILEPROC
, M_WAITOK
);
961 bzero(nfp
, sizeof(struct fileproc
));
964 nfp
->f_flags
= ofp
->f_flags
;
965 nfp
->f_fglob
= ofp
->f_fglob
;
968 fdp
->fd_ofiles
[new] = nfp
;
969 fdp
->fd_ofileflags
[new] = fdp
->fd_ofileflags
[old
] &~ UF_EXCLOSE
;
970 if (new > fdp
->fd_lastfile
)
971 fdp
->fd_lastfile
= new;
978 close(struct proc
*p
, struct close_args
*uap
, __unused register_t
*retval
)
984 AUDIT_SYSCLOSE(p
, fd
);
988 if ( (error
= fp_lookup(p
,fd
,&fp
, 1)) ) {
993 error
= close_internal(p
, fd
, fp
, CLOSEINT_LOCKED
| CLOSEINT_WAITONCLOSE
);
1002 * Close a file descriptor.
1005 close_internal(struct proc
*p
, int fd
, struct fileproc
*fp
, int flags
)
1007 struct filedesc
*fdp
= p
->p_fd
;
1009 int locked
= flags
& CLOSEINT_LOCKED
;
1010 int waitonclose
= flags
& CLOSEINT_WAITONCLOSE
;
1011 int norelse
= flags
& CLOSEINT_NOFDRELSE
;
1012 int nofdref
= flags
& CLOSEINT_NOFDNOREF
;
1013 int slpstate
= PRIBIO
;
1018 /* Keep people from using the filedesc while we are closing it */
1019 fdp
->fd_ofileflags
[fd
] |= UF_RESERVED
;
1021 fdp
->fd_ofileflags
[fd
] |= UF_CLOSING
;
1024 if ((waitonclose
&& ((fp
->f_flags
& FP_CLOSING
) == FP_CLOSING
))) {
1026 fp_drop(p
, fd
, fp
, 1);
1027 fp
->f_flags
|= FP_WAITCLOSE
;
1030 msleep(&fp
->f_flags
, &p
->p_fdmlock
, slpstate
, "close wait",0) ;
1034 fp
->f_flags
|= FP_CLOSING
;
1038 if ( (fp
->f_flags
& FP_AIOISSUED
) || kauth_authorize_fileop_has_listeners() ) {
1042 if ( (fp
->f_type
== DTYPE_VNODE
) && kauth_authorize_fileop_has_listeners() ) {
1044 * call out to allow 3rd party notification of close.
1045 * Ignore result of kauth_authorize_fileop call.
1047 if (vnode_getwithref((vnode_t
)fp
->f_data
) == 0) {
1048 u_int fileop_flags
= 0;
1049 if ((fp
->f_flags
& FP_WRITTEN
) != 0)
1050 fileop_flags
|= KAUTH_FILEOP_CLOSE_MODIFIED
;
1051 kauth_authorize_fileop(fp
->f_fglob
->fg_cred
, KAUTH_FILEOP_CLOSE
,
1052 (uintptr_t)fp
->f_data
, (uintptr_t)fileop_flags
);
1053 vnode_put((vnode_t
)fp
->f_data
);
1056 if (fp
->f_flags
& FP_AIOISSUED
)
1058 * cancel all async IO requests that can be cancelled.
1060 _aio_close( p
, fd
);
1065 if (fd
< fdp
->fd_knlistsize
)
1066 knote_fdclose(p
, fd
);
1068 if (fp
->f_flags
& FP_WAITEVENT
)
1069 (void)waitevent_close(p
, fp
);
1071 if ((fp
->f_flags
& FP_INCHRREAD
) == 0)
1072 fileproc_drain(p
, fp
);
1075 error
= closef_locked(fp
, fp
->f_fglob
, p
);
1076 if ((fp
->f_flags
& FP_WAITCLOSE
) == FP_WAITCLOSE
)
1077 wakeup(&fp
->f_flags
);
1078 fp
->f_flags
&= ~(FP_WAITCLOSE
| FP_CLOSING
);
1083 FREE_ZONE(fp
, sizeof *fp
, M_FILEPROC
);
1088 * Return status information about a file descriptor.
1090 * XXX switch on node type is bogus; need a stat in struct fileops instead.
1093 fstat1(struct proc
*p
, int fd
, user_addr_t ub
, user_addr_t xsecurity
, user_addr_t xsecurity_size
)
1095 struct fileproc
*fp
;
1097 struct user_stat user_sb
;
1102 kauth_filesec_t fsec
;
1103 ssize_t xsecurity_bufsize
;
1105 struct vfs_context context
;
1110 if ((error
= fp_lookup(p
, fd
, &fp
, 0)) != 0)
1114 fsec
= KAUTH_FILESEC_NONE
;
1119 context
.vc_proc
= current_proc();
1120 context
.vc_ucred
= kauth_cred_get();
1121 if ((error
= vnode_getwithref((vnode_t
)data
)) == 0) {
1123 * If the caller has the file open, and is not requesting extended security,
1124 * we are going to let them get the basic stat information.
1126 if (xsecurity
== USER_ADDR_NULL
) {
1127 error
= vn_stat_noauth((vnode_t
)data
, &sb
, NULL
, &context
);
1129 error
= vn_stat((vnode_t
)data
, &sb
, &fsec
, &context
);
1132 AUDIT_ARG(vnpath
, (struct vnode
*)data
, ARG_VNODE1
);
1133 (void)vnode_put((vnode_t
)data
);
1138 error
= soo_stat((struct socket
*)data
, &sb
);
1142 error
= pipe_stat((void *)data
, &sb
);
1146 error
= pshm_stat((void *)data
, &sb
);
1150 funnel_state
= thread_funnel_set(kernel_flock
, TRUE
);
1151 error
= kqueue_stat(fp
, &sb
, p
);
1152 thread_funnel_set(kernel_flock
, funnel_state
);
1159 /* Zap spare fields */
1161 sb
.st_qspare
[0] = 0LL;
1162 sb
.st_qspare
[1] = 0LL;
1165 if (IS_64BIT_PROCESS(current_proc())) {
1166 munge_stat(&sb
, &user_sb
);
1167 my_size
= sizeof(user_sb
);
1168 sbp
= (caddr_t
)&user_sb
;
1171 my_size
= sizeof(sb
);
1174 error
= copyout(sbp
, ub
, my_size
);
1177 /* caller wants extended security information? */
1178 if (xsecurity
!= USER_ADDR_NULL
) {
1180 /* did we get any? */
1181 if (fsec
== KAUTH_FILESEC_NONE
) {
1182 if (susize(xsecurity_size
, 0) != 0) {
1187 /* find the user buffer size */
1188 xsecurity_bufsize
= fusize(xsecurity_size
);
1190 /* copy out the actual data size */
1191 if (susize(xsecurity_size
, KAUTH_FILESEC_COPYSIZE(fsec
)) != 0) {
1196 /* if the caller supplied enough room, copy out to it */
1197 if (xsecurity_bufsize
>= KAUTH_FILESEC_COPYSIZE(fsec
))
1198 error
= copyout(fsec
, xsecurity
, KAUTH_FILESEC_COPYSIZE(fsec
));
1202 fp_drop(p
, fd
, fp
, 0);
1204 kauth_filesec_free(fsec
);
1209 fstat_extended(struct proc
*p
, struct fstat_extended_args
*uap
, __unused register_t
*retval
)
1211 return(fstat1(p
, uap
->fd
, uap
->ub
, uap
->xsecurity
, uap
->xsecurity_size
));
1215 fstat(struct proc
*p
, register struct fstat_args
*uap
, __unused register_t
*retval
)
1217 return(fstat1(p
, uap
->fd
, uap
->ub
, 0, 0));
1221 * Return pathconf information about a file descriptor.
1224 fpathconf(p
, uap
, retval
)
1226 register struct fpathconf_args
*uap
;
1230 struct fileproc
*fp
;
1232 struct vfs_context context
;
1238 AUDIT_ARG(fd
, uap
->fd
);
1239 if ( (error
= fp_lookup(p
, fd
, &fp
, 0)) )
1247 if (uap
->name
!= _PC_PIPE_BUF
) {
1261 vp
= (struct vnode
*)data
;
1263 if ( (error
= vnode_getwithref(vp
)) == 0) {
1264 AUDIT_ARG(vnpath
, vp
, ARG_VNODE1
);
1266 context
.vc_proc
= p
;
1267 context
.vc_ucred
= kauth_cred_get();
1269 error
= vn_pathconf(vp
, uap
->name
, retval
, &context
);
1271 (void)vnode_put(vp
);
1281 panic("fpathconf (unrecognized - %d)", type
);
1285 fp_drop(p
, fd
, fp
, 0);
1290 * Allocate a file descriptor for the process.
1295 fdalloc(p
, want
, result
)
1300 register struct filedesc
*fdp
= p
->p_fd
;
1302 int lim
, last
, numfiles
, oldnfiles
;
1303 struct fileproc
**newofiles
, **ofiles
;
1304 char *newofileflags
, *ofileflags
;
1307 * Search for a free descriptor starting at the higher
1308 * of want or fd_freefile. If that fails, consider
1309 * expanding the ofile array.
1311 lim
= min((int)p
->p_rlimit
[RLIMIT_NOFILE
].rlim_cur
, maxfiles
);
1313 last
= min(fdp
->fd_nfiles
, lim
);
1314 if ((i
= want
) < fdp
->fd_freefile
)
1315 i
= fdp
->fd_freefile
;
1316 ofiles
= &fdp
->fd_ofiles
[i
];
1317 ofileflags
= &fdp
->fd_ofileflags
[i
];
1318 for (; i
< last
; i
++) {
1319 if (*ofiles
== NULL
&& !(*ofileflags
& UF_RESERVED
)) {
1320 *ofileflags
= UF_RESERVED
;
1321 if (i
> fdp
->fd_lastfile
)
1322 fdp
->fd_lastfile
= i
;
1323 if (want
<= fdp
->fd_freefile
)
1324 fdp
->fd_freefile
= i
;
1328 ofiles
++; ofileflags
++;
1332 * No space in current array. Expand?
1334 if (fdp
->fd_nfiles
>= lim
)
1336 if (fdp
->fd_nfiles
< NDEXTENT
)
1337 numfiles
= NDEXTENT
;
1339 numfiles
= 2 * fdp
->fd_nfiles
;
1344 MALLOC_ZONE(newofiles
, struct fileproc
**,
1345 numfiles
* OFILESIZE
, M_OFILETABL
, M_WAITOK
);
1347 if (newofiles
== NULL
) {
1350 if (fdp
->fd_nfiles
>= numfiles
) {
1351 FREE_ZONE(newofiles
, numfiles
* OFILESIZE
, M_OFILETABL
);
1354 newofileflags
= (char *) &newofiles
[numfiles
];
1356 * Copy the existing ofile and ofileflags arrays
1357 * and zero the new portion of each array.
1359 oldnfiles
= fdp
->fd_nfiles
;
1360 (void) memcpy(newofiles
, fdp
->fd_ofiles
,
1361 oldnfiles
* sizeof *fdp
->fd_ofiles
);
1362 (void) memset(&newofiles
[oldnfiles
], 0,
1363 (numfiles
- oldnfiles
) * sizeof *fdp
->fd_ofiles
);
1365 (void) memcpy(newofileflags
, fdp
->fd_ofileflags
,
1366 oldnfiles
* sizeof *fdp
->fd_ofileflags
);
1367 (void) memset(&newofileflags
[oldnfiles
], 0,
1368 (numfiles
- oldnfiles
) *
1369 sizeof *fdp
->fd_ofileflags
);
1370 ofiles
= fdp
->fd_ofiles
;
1371 fdp
->fd_ofiles
= newofiles
;
1372 fdp
->fd_ofileflags
= newofileflags
;
1373 fdp
->fd_nfiles
= numfiles
;
1374 FREE_ZONE(ofiles
, oldnfiles
* OFILESIZE
, M_OFILETABL
);
1380 * Check to see whether n user file descriptors
1381 * are available to the process p.
1388 struct filedesc
*fdp
= p
->p_fd
;
1389 struct fileproc
**fpp
;
1393 lim
= min((int)p
->p_rlimit
[RLIMIT_NOFILE
].rlim_cur
, maxfiles
);
1394 if ((i
= lim
- fdp
->fd_nfiles
) > 0 && (n
-= i
) <= 0)
1396 fpp
= &fdp
->fd_ofiles
[fdp
->fd_freefile
];
1397 flags
= &fdp
->fd_ofileflags
[fdp
->fd_freefile
];
1398 for (i
= fdp
->fd_nfiles
- fdp
->fd_freefile
; --i
>= 0; fpp
++, flags
++)
1399 if (*fpp
== NULL
&& !(*flags
& UF_RESERVED
) && --n
<= 0)
1409 _fdrelse(p
->p_fd
, fd
);
1417 struct filedesc
*fdp
= p
->p_fd
;
1418 struct fileproc
*fp
;
1420 if (fd
< fdp
->fd_freefile
)
1421 fdp
->fd_freefile
= fd
;
1423 if (fd
> fdp
->fd_lastfile
)
1424 panic("fdrelse: fd_lastfile inconsistent");
1426 fp
= fdp
->fd_ofiles
[fd
];
1427 fdp
->fd_ofiles
[fd
] = NULL
;
1428 fdp
->fd_ofileflags
[fd
] = 0;
1430 while ((fd
= fdp
->fd_lastfile
) > 0 &&
1431 fdp
->fd_ofiles
[fd
] == NULL
&&
1432 !(fdp
->fd_ofileflags
[fd
] & UF_RESERVED
))
1434 FREE_ZONE(fp
, sizeof *fp
, M_FILEPROC
);
1439 fdgetf_noref(p
, fd
, resultfp
)
1442 struct fileproc
**resultfp
;
1444 struct filedesc
*fdp
= p
->p_fd
;
1445 struct fileproc
*fp
;
1447 if (fd
< 0 || fd
>= fdp
->fd_nfiles
||
1448 (fp
= fdp
->fd_ofiles
[fd
]) == NULL
||
1449 (fdp
->fd_ofileflags
[fd
] & UF_RESERVED
)) {
1458 /* should be called only when proc_fdlock is held */
1460 fp_setflags(proc_t p
, struct fileproc
* fp
, int flags
)
1463 fp
->f_flags
|= flags
;
1468 fp_clearflags(proc_t p
, struct fileproc
* fp
, int flags
)
1473 fp
->f_flags
&= ~flags
;
1478 fp_getfvp(p
, fd
, resultfp
, resultvp
)
1481 struct fileproc
**resultfp
;
1482 struct vnode
**resultvp
;
1484 struct filedesc
*fdp
= p
->p_fd
;
1485 struct fileproc
*fp
;
1488 if (fd
< 0 || fd
>= fdp
->fd_nfiles
||
1489 (fp
= fdp
->fd_ofiles
[fd
]) == NULL
||
1490 (fdp
->fd_ofileflags
[fd
] & UF_RESERVED
)) {
1494 if (fp
->f_type
!= DTYPE_VNODE
) {
1503 *resultvp
= (struct vnode
*)fp
->f_data
;
1512 fp_getfvpandvid(p
, fd
, resultfp
, resultvp
, vidp
)
1515 struct fileproc
**resultfp
;
1516 struct vnode
**resultvp
;
1519 struct filedesc
*fdp
= p
->p_fd
;
1520 struct fileproc
*fp
;
1523 if (fd
< 0 || fd
>= fdp
->fd_nfiles
||
1524 (fp
= fdp
->fd_ofiles
[fd
]) == NULL
||
1525 (fdp
->fd_ofileflags
[fd
] & UF_RESERVED
)) {
1529 if (fp
->f_type
!= DTYPE_VNODE
) {
1538 *resultvp
= (struct vnode
*)fp
->f_data
;
1540 *vidp
= (uint32_t)vnode_vid((struct vnode
*)fp
->f_data
);
1547 * Returns: EBADF The file descriptor is invalid
1548 * EOPNOTSUPP The file descriptor is not a socket
1551 * Notes: EOPNOTSUPP should probably be ENOTSOCK; this function is only
1552 * ever called from accept1().
1555 fp_getfsock(p
, fd
, resultfp
, results
)
1558 struct fileproc
**resultfp
;
1559 struct socket
**results
;
1561 struct filedesc
*fdp
= p
->p_fd
;
1562 struct fileproc
*fp
;
1565 if (fd
< 0 || fd
>= fdp
->fd_nfiles
||
1566 (fp
= fdp
->fd_ofiles
[fd
]) == NULL
||
1567 (fdp
->fd_ofileflags
[fd
] & UF_RESERVED
)) {
1571 if (fp
->f_type
!= DTYPE_SOCKET
) {
1580 *results
= (struct socket
*)fp
->f_data
;
1588 fp_getfkq(p
, fd
, resultfp
, resultkq
)
1591 struct fileproc
**resultfp
;
1592 struct kqueue
**resultkq
;
1594 struct filedesc
*fdp
= p
->p_fd
;
1595 struct fileproc
*fp
;
1598 if ( fd
< 0 || fd
>= fdp
->fd_nfiles
||
1599 (fp
= fdp
->fd_ofiles
[fd
]) == NULL
||
1600 (fdp
->fd_ofileflags
[fd
] & UF_RESERVED
)) {
1604 if (fp
->f_type
!= DTYPE_KQUEUE
) {
1613 *resultkq
= (struct kqueue
*)fp
->f_data
;
1620 fp_getfpshm(p
, fd
, resultfp
, resultpshm
)
1623 struct fileproc
**resultfp
;
1624 struct pshmnode
**resultpshm
;
1626 struct filedesc
*fdp
= p
->p_fd
;
1627 struct fileproc
*fp
;
1630 if (fd
< 0 || fd
>= fdp
->fd_nfiles
||
1631 (fp
= fdp
->fd_ofiles
[fd
]) == NULL
||
1632 (fdp
->fd_ofileflags
[fd
] & UF_RESERVED
)) {
1636 if (fp
->f_type
!= DTYPE_PSXSHM
) {
1646 *resultpshm
= (struct pshmnode
*)fp
->f_data
;
1654 fp_getfpsem(p
, fd
, resultfp
, resultpsem
)
1657 struct fileproc
**resultfp
;
1658 struct psemnode
**resultpsem
;
1660 struct filedesc
*fdp
= p
->p_fd
;
1661 struct fileproc
*fp
;
1664 if (fd
< 0 || fd
>= fdp
->fd_nfiles
||
1665 (fp
= fdp
->fd_ofiles
[fd
]) == NULL
||
1666 (fdp
->fd_ofileflags
[fd
] & UF_RESERVED
)) {
1670 if (fp
->f_type
!= DTYPE_PSXSEM
) {
1679 *resultpsem
= (struct psemnode
*)fp
->f_data
;
1687 fp_getfpipe(p
, fd
, resultfp
, resultpipe
)
1690 struct fileproc
**resultfp
;
1691 struct pipe
**resultpipe
;
1693 struct filedesc
*fdp
= p
->p_fd
;
1694 struct fileproc
*fp
;
1697 if (fd
< 0 || fd
>= fdp
->fd_nfiles
||
1698 (fp
= fdp
->fd_ofiles
[fd
]) == NULL
||
1699 (fdp
->fd_ofileflags
[fd
] & UF_RESERVED
)) {
1703 if (fp
->f_type
!= DTYPE_PIPE
) {
1712 *resultpipe
= (struct pipe
*)fp
->f_data
;
1719 #define DTYPE_ATALK -1
1721 fp_getfatalk(p
, fd
, resultfp
, resultatalk
)
1724 struct fileproc
**resultfp
;
1725 struct atalk
**resultatalk
;
1727 struct filedesc
*fdp
= p
->p_fd
;
1728 struct fileproc
*fp
;
1731 if (fd
< 0 || fd
>= fdp
->fd_nfiles
||
1732 (fp
= fdp
->fd_ofiles
[fd
]) == NULL
||
1733 (fdp
->fd_ofileflags
[fd
] & UF_RESERVED
)) {
1737 if (fp
->f_type
!= (DTYPE_ATALK
+1)) {
1746 *resultatalk
= (struct atalk
*)fp
->f_data
;
1753 fp_lookup(p
, fd
, resultfp
, locked
)
1756 struct fileproc
**resultfp
;
1759 struct filedesc
*fdp
= p
->p_fd
;
1760 struct fileproc
*fp
;
1764 if (fd
< 0 || fd
>= fdp
->fd_nfiles
||
1765 (fp
= fdp
->fd_ofiles
[fd
]) == NULL
||
1766 (fdp
->fd_ofileflags
[fd
] & UF_RESERVED
)) {
1782 fp_drop_written(proc_t p
, int fd
, struct fileproc
*fp
)
1788 fp
->f_flags
|= FP_WRITTEN
;
1790 error
= fp_drop(p
, fd
, fp
, 1);
1799 fp_drop_event(proc_t p
, int fd
, struct fileproc
*fp
)
1805 fp
->f_flags
|= FP_WAITEVENT
;
1807 error
= fp_drop(p
, fd
, fp
, 1);
1815 fp_drop(p
, fd
, fp
, locked
)
1818 struct fileproc
*fp
;
1821 struct filedesc
*fdp
= p
->p_fd
;
1825 if ((fp
== FILEPROC_NULL
) && (fd
< 0 || fd
>= fdp
->fd_nfiles
||
1826 (fp
= fdp
->fd_ofiles
[fd
]) == NULL
||
1827 ((fdp
->fd_ofileflags
[fd
] & UF_RESERVED
) &&
1828 !(fdp
->fd_ofileflags
[fd
] & UF_CLOSING
)))) {
1835 if (p
->p_fpdrainwait
&& fp
->f_iocount
== 0) {
1836 p
->p_fpdrainwait
= 0;
1837 wakeup(&p
->p_fpdrainwait
);
1846 file_vnode(int fd
, struct vnode
**vpp
)
1848 struct proc
* p
= current_proc();
1849 struct fileproc
*fp
;
1853 if ( (error
= fp_lookup(p
, fd
, &fp
, 1)) ) {
1857 if (fp
->f_type
!= DTYPE_VNODE
) {
1858 fp_drop(p
, fd
, fp
,1);
1862 *vpp
= (struct vnode
*)fp
->f_data
;
1870 file_socket(int fd
, struct socket
**sp
)
1872 struct proc
* p
= current_proc();
1873 struct fileproc
*fp
;
1877 if ( (error
= fp_lookup(p
, fd
, &fp
, 1)) ) {
1881 if (fp
->f_type
!= DTYPE_SOCKET
) {
1882 fp_drop(p
, fd
, fp
,1);
1886 *sp
= (struct socket
*)fp
->f_data
;
1893 file_flags(int fd
, int * flags
)
1896 struct proc
* p
= current_proc();
1897 struct fileproc
*fp
;
1901 if ( (error
= fp_lookup(p
, fd
, &fp
, 1)) ) {
1905 *flags
= (int)fp
->f_flag
;
1906 fp_drop(p
, fd
, fp
,1);
1916 struct fileproc
*fp
;
1917 struct proc
*p
= current_proc();
1920 if (fd
< 0 || fd
>= p
->p_fd
->fd_nfiles
||
1921 (fp
= p
->p_fd
->fd_ofiles
[fd
]) == NULL
||
1922 ((p
->p_fd
->fd_ofileflags
[fd
] & UF_RESERVED
) &&
1923 !(p
->p_fd
->fd_ofileflags
[fd
] & UF_CLOSING
))) {
1929 if (p
->p_fpdrainwait
&& fp
->f_iocount
== 0) {
1930 p
->p_fpdrainwait
= 0;
1931 wakeup(&p
->p_fpdrainwait
);
1940 falloc(p
, resultfp
, resultfd
)
1942 struct fileproc
**resultfp
;
1948 error
= falloc_locked(p
, resultfp
, resultfd
, 1);
1954 * Create a new open file structure and allocate
1955 * a file decriptor for the process that refers to it.
1958 falloc_locked(p
, resultfp
, resultfd
, locked
)
1960 struct fileproc
**resultfp
;
1964 struct fileproc
*fp
, *fq
;
1965 struct fileglob
*fg
;
1970 if ( (error
= fdalloc(p
, 0, &nfd
)) ) {
1975 if (nfiles
>= maxfiles
) {
1982 * Allocate a new file descriptor.
1983 * If the process has file descriptor zero open, add to the list
1984 * of open files at that point, otherwise put it at the front of
1985 * the list of open files.
1989 MALLOC_ZONE(fp
, struct fileproc
*, sizeof(struct fileproc
), M_FILEPROC
, M_WAITOK
);
1990 MALLOC_ZONE(fg
, struct fileglob
*, sizeof(struct fileglob
), M_FILEGLOB
, M_WAITOK
);
1991 bzero(fp
, sizeof(struct fileproc
));
1992 bzero(fg
, sizeof(struct fileglob
));
1993 lck_mtx_init(&fg
->fg_lock
, file_lck_grp
, file_lck_attr
);
2001 fp
->f_cred
= kauth_cred_proc_ref(p
);
2003 lck_mtx_lock(file_flist_lock
);
2007 if ( (fq
= p
->p_fd
->fd_ofiles
[0]) ) {
2008 LIST_INSERT_AFTER(fq
->f_fglob
, fg
, f_list
);
2010 LIST_INSERT_HEAD(&filehead
, fg
, f_list
);
2012 lck_mtx_unlock(file_flist_lock
);
2014 p
->p_fd
->fd_ofiles
[nfd
] = fp
;
2028 * Free a file structure.
2032 struct fileglob
*fg
;
2036 lck_mtx_lock(file_flist_lock
);
2037 LIST_REMOVE(fg
, f_list
);
2039 lck_mtx_unlock(file_flist_lock
);
2042 if (cred
!= NOCRED
) {
2043 fg
->fg_cred
= NOCRED
;
2044 kauth_cred_rele(cred
);
2046 lck_mtx_destroy(&fg
->fg_lock
, file_lck_grp
);
2048 FREE_ZONE(fg
, sizeof *fg
, M_FILEGLOB
);
2055 struct filedesc
*fdp
= p
->p_fd
;
2056 int i
= fdp
->fd_lastfile
;
2057 struct fileproc
**fpp
= &fdp
->fd_ofiles
[i
];
2058 char *flags
= &fdp
->fd_ofileflags
[i
];
2061 funnel_state
= thread_funnel_set(kernel_flock
, FALSE
);
2065 if ((*flags
& (UF_RESERVED
|UF_EXCLOSE
)) == UF_EXCLOSE
) {
2066 struct fileproc
*fp
= *fpp
;
2068 if (i
< fdp
->fd_knlistsize
)
2069 knote_fdclose(p
, i
);
2071 *fpp
= NULL
; *flags
= 0;
2072 if (i
== fdp
->fd_lastfile
&& i
> 0)
2074 closef_locked(fp
, fp
->f_fglob
, p
);
2075 FREE_ZONE(fp
, sizeof *fp
, M_FILEPROC
);
2078 i
--; fpp
--; flags
--;
2081 thread_funnel_set(kernel_flock
, funnel_state
);
2085 * Copy a filedesc structure.
2091 struct filedesc
*newfdp
, *fdp
= p
->p_fd
;
2093 struct fileproc
*ofp
, *fp
;
2096 MALLOC_ZONE(newfdp
, struct filedesc
*,
2097 sizeof *newfdp
, M_FILEDESC
, M_WAITOK
);
2104 * the FD_CHROOT flag will be inherited via this copy
2106 (void) memcpy(newfdp
, fdp
, sizeof *newfdp
);
2109 * for both fd_cdir and fd_rdir make sure we get
2110 * a valid reference... if we can't, than set
2111 * set the pointer(s) to NULL in the child... this
2112 * will keep us from using a non-referenced vp
2113 * and allows us to do the vnode_rele only on
2114 * a properly referenced vp
2116 if ( (v_dir
= newfdp
->fd_cdir
) ) {
2117 if (vnode_getwithref(v_dir
) == 0) {
2118 if ( (vnode_ref(v_dir
)) )
2119 newfdp
->fd_cdir
= NULL
;
2122 newfdp
->fd_cdir
= NULL
;
2124 if (newfdp
->fd_cdir
== NULL
&& fdp
->fd_cdir
) {
2126 * we couldn't get a new reference on
2127 * the current working directory being
2128 * inherited... we might as well drop
2129 * our reference from the parent also
2130 * since the vnode has gone DEAD making
2131 * it useless... by dropping it we'll
2132 * be that much closer to recyling it
2134 vnode_rele(fdp
->fd_cdir
);
2135 fdp
->fd_cdir
= NULL
;
2138 if ( (v_dir
= newfdp
->fd_rdir
) ) {
2139 if (vnode_getwithref(v_dir
) == 0) {
2140 if ( (vnode_ref(v_dir
)) )
2141 newfdp
->fd_rdir
= NULL
;
2144 newfdp
->fd_rdir
= NULL
;
2146 if (newfdp
->fd_rdir
== NULL
&& fdp
->fd_rdir
) {
2148 * we couldn't get a new reference on
2149 * the root directory being
2150 * inherited... we might as well drop
2151 * our reference from the parent also
2152 * since the vnode has gone DEAD making
2153 * it useless... by dropping it we'll
2154 * be that much closer to recyling it
2156 vnode_rele(fdp
->fd_rdir
);
2157 fdp
->fd_rdir
= NULL
;
2159 newfdp
->fd_refcnt
= 1;
2162 * If the number of open files fits in the internal arrays
2163 * of the open file structure, use them, otherwise allocate
2164 * additional memory for the number of descriptors currently
2167 if (newfdp
->fd_lastfile
< NDFILE
)
2171 * Compute the smallest multiple of NDEXTENT needed
2172 * for the file descriptors currently in use,
2173 * allowing the table to shrink.
2175 i
= newfdp
->fd_nfiles
;
2176 while (i
> 2 * NDEXTENT
&& i
> newfdp
->fd_lastfile
* 2)
2181 MALLOC_ZONE(newfdp
->fd_ofiles
, struct fileproc
**,
2182 i
* OFILESIZE
, M_OFILETABL
, M_WAITOK
);
2183 if (newfdp
->fd_ofiles
== NULL
) {
2184 if (newfdp
->fd_cdir
)
2185 vnode_rele(newfdp
->fd_cdir
);
2186 if (newfdp
->fd_rdir
)
2187 vnode_rele(newfdp
->fd_rdir
);
2189 FREE_ZONE(newfdp
, sizeof *newfdp
, M_FILEDESC
);
2194 newfdp
->fd_ofileflags
= (char *) &newfdp
->fd_ofiles
[i
];
2195 newfdp
->fd_nfiles
= i
;
2197 if (fdp
->fd_nfiles
> 0) {
2198 struct fileproc
**fpp
;
2201 (void) memcpy(newfdp
->fd_ofiles
, fdp
->fd_ofiles
,
2202 i
* sizeof *fdp
->fd_ofiles
);
2203 (void) memcpy(newfdp
->fd_ofileflags
, fdp
->fd_ofileflags
,
2204 i
* sizeof *fdp
->fd_ofileflags
);
2207 * kq descriptors cannot be copied.
2209 if (newfdp
->fd_knlistsize
!= -1) {
2210 fpp
= &newfdp
->fd_ofiles
[newfdp
->fd_lastfile
];
2211 for (i
= newfdp
->fd_lastfile
; i
>= 0; i
--, fpp
--) {
2212 if (*fpp
!= NULL
&& (*fpp
)->f_type
== DTYPE_KQUEUE
) {
2214 if (i
< newfdp
->fd_freefile
)
2215 newfdp
->fd_freefile
= i
;
2217 if (*fpp
== NULL
&& i
== newfdp
->fd_lastfile
&& i
> 0)
2218 newfdp
->fd_lastfile
--;
2220 newfdp
->fd_knlist
= NULL
;
2221 newfdp
->fd_knlistsize
= -1;
2222 newfdp
->fd_knhash
= NULL
;
2223 newfdp
->fd_knhashmask
= 0;
2225 fpp
= newfdp
->fd_ofiles
;
2226 flags
= newfdp
->fd_ofileflags
;
2228 for (i
= newfdp
->fd_lastfile
; i
-- >= 0; fpp
++, flags
++)
2229 if ((ofp
= *fpp
) != NULL
&& !(*flags
& UF_RESERVED
)) {
2230 MALLOC_ZONE(fp
, struct fileproc
*, sizeof(struct fileproc
), M_FILEPROC
, M_WAITOK
);
2231 bzero(fp
, sizeof(struct fileproc
));
2232 fp
->f_flags
= ofp
->f_flags
;
2233 //fp->f_iocount = ofp->f_iocount;
2235 fp
->f_fglob
= ofp
->f_fglob
;
2243 (void) memset(newfdp
->fd_ofiles
, 0, i
* OFILESIZE
);
2250 * Release a filedesc structure.
2256 struct filedesc
*fdp
;
2257 struct fileproc
*fp
;
2262 /* Certain daemons might not have file descriptors */
2265 if ((fdp
== NULL
) || (--fdp
->fd_refcnt
> 0)) {
2269 if (fdp
->fd_refcnt
== 0xffff)
2270 panic("fdfree: bad fd_refcnt");
2272 /* Last reference: the structure can't change out from under us */
2274 if (fdp
->fd_nfiles
> 0 && fdp
->fd_ofiles
) {
2275 for (i
= fdp
->fd_lastfile
; i
>= 0; i
--) {
2276 if ((fp
= fdp
->fd_ofiles
[i
]) != NULL
) {
2278 if (fdp
->fd_ofileflags
[i
] & UF_RESERVED
)
2279 panic("fdfree: found fp with UF_RESERVED\n");
2281 /* closef drops the iocount ... */
2282 if ((fp
->f_flags
& FP_INCHRREAD
) != 0)
2284 fdp
->fd_ofiles
[i
] = NULL
;
2285 fdp
->fd_ofileflags
[i
] |= UF_RESERVED
;
2287 if (i
< fdp
->fd_knlistsize
)
2288 knote_fdclose(p
, i
);
2289 if (fp
->f_flags
& FP_WAITEVENT
)
2290 (void)waitevent_close(p
, fp
);
2291 (void) closef_locked(fp
, fp
->f_fglob
, p
);
2292 FREE_ZONE(fp
, sizeof *fp
, M_FILEPROC
);
2295 FREE_ZONE(fdp
->fd_ofiles
, fdp
->fd_nfiles
* OFILESIZE
, M_OFILETABL
);
2296 fdp
->fd_ofiles
= NULL
;
2303 vnode_rele(fdp
->fd_cdir
);
2305 vnode_rele(fdp
->fd_rdir
);
2312 FREE(fdp
->fd_knlist
, M_KQUEUE
);
2314 FREE(fdp
->fd_knhash
, M_KQUEUE
);
2316 FREE_ZONE(fdp
, sizeof *fdp
, M_FILEDESC
);
2320 closef_finish(fp
, fg
, p
)
2321 struct fileproc
*fp
;
2322 struct fileglob
*fg
;
2328 struct vfs_context context
;
2330 if ((fg
->fg_flag
& FHASLOCK
) && fg
->fg_type
== DTYPE_VNODE
) {
2331 lf
.l_whence
= SEEK_SET
;
2334 lf
.l_type
= F_UNLCK
;
2335 vp
= (struct vnode
*)fg
->fg_data
;
2336 context
.vc_proc
= p
;
2337 context
.vc_ucred
= fg
->fg_cred
;
2339 (void) VNOP_ADVLOCK(vp
, (caddr_t
)fg
, F_UNLCK
, &lf
, F_FLOCK
, &context
);
2342 error
= fo_close(fg
, p
);
2346 if (((fp
!= (struct fileproc
*)0) && ((fp
->f_flags
& FP_INCHRREAD
) != 0))) {
2348 if ( ((fp
->f_flags
& FP_INCHRREAD
) != 0) ) {
2349 fileproc_drain(p
, fp
);
2360 struct fileglob
*fg
;
2366 error
= closef_locked((struct fileproc
*)0, fg
, p
);
2372 * Internal form of close.
2373 * Decrement reference count on file structure.
2374 * Note: p may be NULL when closing a file
2375 * that was being passed in a message.
2378 closef_locked(fp
, fg
, p
)
2379 struct fileproc
*fp
;
2380 struct fileglob
*fg
;
2385 struct vfs_context context
;
2392 * POSIX record locking dictates that any close releases ALL
2393 * locks owned by this process. This is handled by setting
2394 * a flag in the unlock to free ONLY locks obeying POSIX
2395 * semantics, and not to free BSD-style file locks.
2396 * If the descriptor was in a message, POSIX-style locks
2397 * aren't passed with the descriptor.
2399 if (p
&& (p
->p_ladvflag
& P_LADVLOCK
) && fg
->fg_type
== DTYPE_VNODE
) {
2402 lf
.l_whence
= SEEK_SET
;
2405 lf
.l_type
= F_UNLCK
;
2406 vp
= (struct vnode
*)fg
->fg_data
;
2408 if ( (error
= vnode_getwithref(vp
)) == 0 ) {
2409 context
.vc_proc
= p
;
2410 context
.vc_ucred
= fg
->fg_cred
;
2411 (void) VNOP_ADVLOCK(vp
, (caddr_t
)p
, F_UNLCK
, &lf
, F_POSIX
, &context
);
2413 (void)vnode_put(vp
);
2417 lck_mtx_lock(&fg
->fg_lock
);
2420 if (fg
->fg_count
> 0) {
2421 lck_mtx_unlock(&fg
->fg_lock
);
2424 if (fg
->fg_count
!= 0)
2425 panic("fg: being freed with bad fg_count (%d)", fg
, fg
->fg_count
);
2427 if (fp
&& (fp
->f_flags
& FP_WRITTEN
))
2428 fg
->fg_flag
|= FWASWRITTEN
;
2430 fg
->fg_lflags
|= FG_TERM
;
2431 lck_mtx_unlock(&fg
->fg_lock
);
2434 error
= closef_finish(fp
, fg
, p
);
2443 fileproc_drain(struct proc
*p
, struct fileproc
* fp
)
2445 fp
->f_iocount
-- ; /* (the one the close holds) */
2447 while (fp
->f_iocount
) {
2448 if (((fp
->f_flags
& FP_INSELECT
)== FP_INSELECT
)) {
2449 wait_queue_wakeup_all((wait_queue_t
)fp
->f_waddr
, &selwait
, THREAD_INTERRUPTED
);
2451 if (fp
->f_fglob
->fg_ops
->fo_drain
) {
2452 (*fp
->f_fglob
->fg_ops
->fo_drain
)(fp
, p
);
2455 p
->p_fpdrainwait
= 1;
2457 msleep(&p
->p_fpdrainwait
, &p
->p_fdmlock
, PRIBIO
, "fpdrain",0);
2459 //panic("successful wait after drain\n");
2464 fp_free(struct proc
* p
, int fd
, struct fileproc
* fp
)
2470 fg_free(fp
->f_fglob
);
2471 FREE_ZONE(fp
, sizeof *fp
, M_FILEPROC
);
2476 * Apply an advisory lock on a file descriptor.
2478 * Just attempt to get a record lock of the requested type on
2479 * the entire file (l_whence = SEEK_SET, l_start = 0, l_len = 0).
2482 flock(struct proc
*p
, register struct flock_args
*uap
, __unused register_t
*retval
)
2486 struct fileproc
*fp
;
2489 struct vfs_context context
;
2492 AUDIT_ARG(fd
, uap
->fd
);
2493 if ( (error
= fp_getfvp(p
, fd
, &fp
, &vp
)) ) {
2496 if ( (error
= vnode_getwithref(vp
)) ) {
2499 AUDIT_ARG(vnpath
, vp
, ARG_VNODE1
);
2501 context
.vc_proc
= p
;
2502 context
.vc_ucred
= fp
->f_cred
;
2504 lf
.l_whence
= SEEK_SET
;
2507 if (how
& LOCK_UN
) {
2508 lf
.l_type
= F_UNLCK
;
2509 fp
->f_flag
&= ~FHASLOCK
;
2510 error
= VNOP_ADVLOCK(vp
, (caddr_t
)fp
->f_fglob
, F_UNLCK
, &lf
, F_FLOCK
, &context
);
2514 lf
.l_type
= F_WRLCK
;
2515 else if (how
& LOCK_SH
)
2516 lf
.l_type
= F_RDLCK
;
2521 fp
->f_flag
|= FHASLOCK
;
2522 if (how
& LOCK_NB
) {
2523 error
= VNOP_ADVLOCK(vp
, (caddr_t
)fp
->f_fglob
, F_SETLK
, &lf
, F_FLOCK
, &context
);
2526 error
= VNOP_ADVLOCK(vp
, (caddr_t
)fp
->f_fglob
, F_SETLK
, &lf
, F_FLOCK
|F_WAIT
, &context
);
2528 (void)vnode_put(vp
);
2530 fp_drop(p
, fd
, fp
, 0);
2536 * File Descriptor pseudo-device driver (/dev/fd/).
2538 * Opening minor device N dup()s the file (if any) connected to file
2539 * descriptor N belonging to the calling process. Note that this driver
2540 * consists of only the ``open()'' routine, because all subsequent
2541 * references to this file will be direct to the other driver.
2544 fdopen(dev_t dev
, __unused
int mode
, __unused
int type
, struct proc
*p
)
2548 * XXX Kludge: set curproc->p_dupfd to contain the value of the
2549 * the file descriptor being sought for duplication. The error
2550 * return ensures that the vnode for this device will be released
2551 * by vn_open. Open will detect this special error and take the
2552 * actions in dupfdopen below. Other callers of vn_open or vnop_open
2553 * will simply report the error.
2555 p
->p_dupfd
= minor(dev
);
2560 * Duplicate the specified descriptor to a free descriptor.
2563 dupfdopen(fdp
, indx
, dfd
, mode
, error
)
2564 register struct filedesc
*fdp
;
2565 register int indx
, dfd
;
2569 struct fileproc
*wfp
;
2570 struct fileproc
*fp
;
2571 struct proc
* p
= current_proc();
2574 * If the to-be-dup'd fd number is greater than the allowed number
2575 * of file descriptors, or the fd to be dup'd has already been
2576 * closed, reject. Note, check for new == old is necessary as
2577 * falloc could allocate an already closed to-be-dup'd descriptor
2578 * as the new descriptor.
2582 fp
= fdp
->fd_ofiles
[indx
];
2583 if (dfd
< 0 || dfd
>= fdp
->fd_nfiles
||
2584 (wfp
= fdp
->fd_ofiles
[dfd
]) == NULL
|| wfp
== fp
||
2585 (fdp
->fd_ofileflags
[dfd
] & UF_RESERVED
)) {
2591 * There are two cases of interest here.
2593 * For ENODEV simply dup (dfd) to file descriptor
2594 * (indx) and return.
2596 * For ENXIO steal away the file structure from (dfd) and
2597 * store it in (indx). (dfd) is effectively closed by
2600 * Any other error code is just returned.
2605 * Check that the mode the file is being opened for is a
2606 * subset of the mode of the existing descriptor.
2608 if (((mode
& (FREAD
|FWRITE
)) | wfp
->f_flag
) != wfp
->f_flag
) {
2612 if (indx
> fdp
->fd_lastfile
)
2613 fdp
->fd_lastfile
= indx
;
2617 fg_free(fp
->f_fglob
);
2618 fp
->f_fglob
= wfp
->f_fglob
;
2620 fdp
->fd_ofileflags
[indx
] = fdp
->fd_ofileflags
[dfd
];
2627 * Steal away the file pointer from dfd, and stuff it into indx.
2629 if (indx
> fdp
->fd_lastfile
)
2630 fdp
->fd_lastfile
= indx
;
2633 fg_free(fp
->f_fglob
);
2634 fp
->f_fglob
= wfp
->f_fglob
;
2636 fdp
->fd_ofileflags
[indx
] = fdp
->fd_ofileflags
[dfd
];
2641 FREE_ZONE(wfp
, sizeof *fp
, M_FILEPROC
);
2653 fg_ref(struct fileproc
* fp
)
2655 struct fileglob
*fg
;
2659 lck_mtx_lock(&fg
->fg_lock
);
2661 lck_mtx_unlock(&fg
->fg_lock
);
2665 fg_drop(struct fileproc
* fp
)
2667 struct fileglob
*fg
;
2670 lck_mtx_lock(&fg
->fg_lock
);
2672 lck_mtx_unlock(&fg
->fg_lock
);
2677 fg_insertuipc(struct fileglob
* fg
)
2681 lck_mtx_lock(&fg
->fg_lock
);
2683 while (fg
->fg_lflags
& FG_RMMSGQ
) {
2684 fg
->fg_lflags
|= FG_WRMMSGQ
;
2685 msleep(&fg
->fg_lflags
, &fg
->fg_lock
, 0, "fg_insertuipc", 0);
2690 if (fg
->fg_msgcount
== 1) {
2691 fg
->fg_lflags
|= FG_INSMSGQ
;
2694 lck_mtx_unlock(&fg
->fg_lock
);
2697 lck_mtx_lock(uipc_lock
);
2698 LIST_INSERT_HEAD(&fmsghead
, fg
, f_msglist
);
2699 lck_mtx_unlock(uipc_lock
);
2700 lck_mtx_lock(&fg
->fg_lock
);
2701 fg
->fg_lflags
&= ~FG_INSMSGQ
;
2702 if (fg
->fg_lflags
& FG_WINSMSGQ
) {
2703 fg
->fg_lflags
&= ~FG_WINSMSGQ
;
2704 wakeup(&fg
->fg_lflags
);
2706 lck_mtx_unlock(&fg
->fg_lock
);
2712 fg_removeuipc(struct fileglob
* fg
)
2716 lck_mtx_lock(&fg
->fg_lock
);
2717 while (fg
->fg_lflags
& FG_INSMSGQ
) {
2718 fg
->fg_lflags
|= FG_WINSMSGQ
;
2719 msleep(&fg
->fg_lflags
, &fg
->fg_lock
, 0, "fg_removeuipc", 0);
2722 if (fg
->fg_msgcount
== 0) {
2723 fg
->fg_lflags
|= FG_RMMSGQ
;
2726 lck_mtx_unlock(&fg
->fg_lock
);
2729 lck_mtx_lock(uipc_lock
);
2730 LIST_REMOVE(fg
, f_msglist
);
2731 lck_mtx_unlock(uipc_lock
);
2732 lck_mtx_lock(&fg
->fg_lock
);
2733 fg
->fg_lflags
&= ~FG_RMMSGQ
;
2734 if (fg
->fg_lflags
& FG_WRMMSGQ
) {
2735 fg
->fg_lflags
&= ~FG_WRMMSGQ
;
2736 wakeup(&fg
->fg_lflags
);
2738 lck_mtx_unlock(&fg
->fg_lock
);
2744 fo_read(struct fileproc
*fp
, struct uio
*uio
, kauth_cred_t cred
, int flags
, struct proc
*p
)
2746 return ((*fp
->f_ops
->fo_read
)(fp
, uio
, cred
, flags
, p
));
2750 fo_write(struct fileproc
*fp
, struct uio
*uio
, kauth_cred_t cred
, int flags
, struct proc
*p
)
2752 return((*fp
->f_ops
->fo_write
)(fp
, uio
, cred
, flags
, p
));
2756 fo_ioctl(struct fileproc
*fp
, u_long com
, caddr_t data
, struct proc
*p
)
2761 error
= (*fp
->f_ops
->fo_ioctl
)(fp
, com
, data
, p
);
2767 fo_select(struct fileproc
*fp
, int which
, void *wql
, struct proc
*p
)
2769 return((*fp
->f_ops
->fo_select
)(fp
, which
, wql
, p
));
2773 fo_close(struct fileglob
*fg
, struct proc
*p
)
2775 return((*fg
->fg_ops
->fo_close
)(fg
, p
));
2779 fo_kqfilter(struct fileproc
*fp
, struct knote
*kn
, struct proc
*p
)
2781 return ((*fp
->f_ops
->fo_kqfilter
)(fp
, kn
, p
));