]> git.saurik.com Git - apple/xnu.git/blame - bsd/kern/kern_descrip.c
xnu-792.2.4.tar.gz
[apple/xnu.git] / bsd / kern / kern_descrip.c
CommitLineData
1c79356b 1/*
e5568f75 2 * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
1c79356b
A
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
e5568f75
A
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.
1c79356b 11 *
e5568f75
A
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
1c79356b
A
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
e5568f75
A
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
18 * under the License.
1c79356b
A
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22/* Copyright (c) 1995, 1997 Apple Computer, Inc. All Rights Reserved */
23/*
24 * Copyright (c) 1982, 1986, 1989, 1991, 1993
25 * The Regents of the University of California. All rights reserved.
26 * (c) UNIX System Laboratories, Inc.
27 * All or some portions of this file are derived from material licensed
28 * to the University of California by American Telephone and Telegraph
29 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
30 * the permission of UNIX System Laboratories, Inc.
31 *
32 * Redistribution and use in source and binary forms, with or without
33 * modification, are permitted provided that the following conditions
34 * are met:
35 * 1. Redistributions of source code must retain the above copyright
36 * notice, this list of conditions and the following disclaimer.
37 * 2. Redistributions in binary form must reproduce the above copyright
38 * notice, this list of conditions and the following disclaimer in the
39 * documentation and/or other materials provided with the distribution.
40 * 3. All advertising materials mentioning features or use of this software
41 * must display the following acknowledgement:
42 * This product includes software developed by the University of
43 * California, Berkeley and its contributors.
44 * 4. Neither the name of the University nor the names of its contributors
45 * may be used to endorse or promote products derived from this software
46 * without specific prior written permission.
47 *
48 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
49 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
50 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
51 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
52 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
53 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
54 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
55 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
56 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
57 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
58 * SUCH DAMAGE.
59 *
60 * @(#)kern_descrip.c 8.8 (Berkeley) 2/14/95
1c79356b
A
61 */
62
63#include <sys/param.h>
64#include <sys/systm.h>
65#include <sys/filedesc.h>
66#include <sys/kernel.h>
91447636
A
67#include <sys/vnode_internal.h>
68#include <sys/proc_internal.h>
69#include <sys/kauth.h>
70#include <sys/file_internal.h>
1c79356b
A
71#include <sys/socket.h>
72#include <sys/socketvar.h>
73#include <sys/stat.h>
74#include <sys/ioctl.h>
75#include <sys/fcntl.h>
76#include <sys/malloc.h>
91447636 77#include <sys/mman.h>
1c79356b
A
78#include <sys/syslog.h>
79#include <sys/unistd.h>
80#include <sys/resourcevar.h>
55e303ae 81#include <sys/aio_kern.h>
91447636
A
82#include <sys/ev.h>
83#include <kern/lock.h>
e5568f75
A
84
85#include <bsm/audit_kernel.h>
1c79356b 86
91447636
A
87#include <sys/mount_internal.h>
88#include <sys/kdebug.h>
89#include <sys/sysproto.h>
90#include <sys/pipe.h>
91#include <kern/kern_types.h>
92#include <kern/kalloc.h>
b36670ce 93#include <libkern/OSAtomic.h>
91447636
A
94
95struct psemnode;
96struct pshmnode;
97
98int fdopen(dev_t dev, int mode, int type, struct proc *p);
99int ogetdtablesize(struct proc *p, void *uap, register_t *retval);
100int finishdup(struct proc * p, struct filedesc *fdp, int old, int new, register_t *retval);
101
102int closef(struct fileglob *fg, struct proc *p);
103int falloc_locked(struct proc *p, struct fileproc **resultfp, int *resultfd, int locked);
104void fddrop(struct proc *p, int fd);
105int fdgetf_noref(struct proc *p, int fd, struct fileproc **resultfp);
106void fg_drop(struct fileproc * fp);
107void fg_free(struct fileglob *fg);
108void fg_ref(struct fileproc * fp);
109int fp_getfpshm(struct proc *p, int fd, struct fileproc **resultfp, struct pshmnode **resultpshm);
110
111static int closef_finish(struct fileproc *fp, struct fileglob *fg, struct proc *p);
112
113extern void file_lock_init(void);
114extern int is_suser(void);
115extern int kqueue_stat(struct fileproc *fp, struct stat *st, struct proc *p);
116extern int soo_stat(struct socket *so, struct stat *ub);
117extern int vn_path_package_check(vnode_t vp, char *path, int pathlen, int *component);
118
119extern kauth_scope_t kauth_scope_fileop;
120
121#define f_flag f_fglob->fg_flag
122#define f_type f_fglob->fg_type
123#define f_msgcount f_fglob->fg_msgcount
124#define f_cred f_fglob->fg_cred
125#define f_ops f_fglob->fg_ops
126#define f_offset f_fglob->fg_offset
127#define f_data f_fglob->fg_data
1c79356b
A
128/*
129 * Descriptor management.
130 */
131struct filelist filehead; /* head of list of open files */
91447636
A
132struct fmsglist fmsghead; /* head of list of open files */
133struct fmsglist fmsg_ithead; /* head of list of open files */
1c79356b
A
134int nfiles; /* actual number of open files */
135
91447636
A
136
137lck_grp_attr_t * file_lck_grp_attr;
138lck_grp_t * file_lck_grp;
139lck_attr_t * file_lck_attr;
140
141lck_mtx_t * uipc_lock;
142lck_mtx_t * file_iterate_lcok;
143lck_mtx_t * file_flist_lock;
144
145
146void
147file_lock_init(void)
148{
149
150 /* allocate file lock group attribute and group */
151 file_lck_grp_attr= lck_grp_attr_alloc_init();
152 lck_grp_attr_setstat(file_lck_grp_attr);
153
154 file_lck_grp = lck_grp_alloc_init("file", file_lck_grp_attr);
155
156 /* Allocate file lock attribute */
157 file_lck_attr = lck_attr_alloc_init();
158 //lck_attr_setdebug(file_lck_attr);
159
160 uipc_lock = lck_mtx_alloc_init(file_lck_grp, file_lck_attr);
161 file_iterate_lcok = lck_mtx_alloc_init(file_lck_grp, file_lck_attr);
162 file_flist_lock = lck_mtx_alloc_init(file_lck_grp, file_lck_attr);
163
164
165
166}
167
168
169void
170proc_fdlock(struct proc *p)
171{
172 lck_mtx_lock(&p->p_fdmlock);
173}
174
175void
176proc_fdunlock(struct proc *p)
177{
178 lck_mtx_unlock(&p->p_fdmlock);
179}
9bccf70c 180
1c79356b
A
181/*
182 * System calls on descriptors.
183 */
91447636 184
1c79356b 185int
91447636 186getdtablesize(struct proc *p, __unused struct getdtablesize_args *uap, register_t *retval)
1c79356b 187{
91447636 188 proc_fdlock(p);
1c79356b 189 *retval = min((int)p->p_rlimit[RLIMIT_NOFILE].rlim_cur, maxfiles);
91447636
A
190 proc_fdunlock(p);
191
1c79356b
A
192 return (0);
193}
194
1c79356b 195int
91447636 196ogetdtablesize(struct proc *p, __unused void *uap, register_t *retval)
1c79356b 197{
91447636 198 proc_fdlock(p);
1c79356b 199 *retval = min((int)p->p_rlimit[RLIMIT_NOFILE].rlim_cur, NOFILE);
91447636
A
200 proc_fdunlock(p);
201
1c79356b
A
202 return (0);
203}
204
91447636
A
205static __inline__ void
206_fdrelse(struct filedesc *fdp, int fd)
1c79356b
A
207{
208 if (fd < fdp->fd_freefile)
209 fdp->fd_freefile = fd;
210#if DIAGNOSTIC
211 if (fd > fdp->fd_lastfile)
212 panic("fdrelse: fd_lastfile inconsistent");
213#endif
214 fdp->fd_ofiles[fd] = NULL;
215 fdp->fd_ofileflags[fd] = 0;
91447636 216
1c79356b
A
217 while ((fd = fdp->fd_lastfile) > 0 &&
218 fdp->fd_ofiles[fd] == NULL &&
219 !(fdp->fd_ofileflags[fd] & UF_RESERVED))
220 fdp->fd_lastfile--;
221}
222
223/*
224 * Duplicate a file descriptor.
225 */
1c79356b
A
226/* ARGSUSED */
227int
228dup(p, uap, retval)
229 struct proc *p;
230 struct dup_args *uap;
231 register_t *retval;
232{
233 register struct filedesc *fdp = p->p_fd;
234 register int old = uap->fd;
235 int new, error;
91447636 236 struct fileproc *fp;
1c79356b 237
91447636
A
238 proc_fdlock(p);
239 if ( (error = fp_lookup(p, old, &fp, 1)) ) {
240 proc_fdunlock(p);
241 return(error);
242 }
243 if ( (error = fdalloc(p, 0, &new)) ) {
244 fp_drop(p, old, fp, 1);
245 proc_fdunlock(p);
1c79356b 246 return (error);
91447636
A
247 }
248 error = finishdup(p, fdp, old, new, retval);
249 fp_drop(p, old, fp, 1);
250 proc_fdunlock(p);
251
252 return (error);
1c79356b
A
253}
254
255/*
256 * Duplicate a file descriptor to a particular value.
257 */
1c79356b
A
258/* ARGSUSED */
259int
260dup2(p, uap, retval)
261 struct proc *p;
262 struct dup2_args *uap;
263 register_t *retval;
264{
265 register struct filedesc *fdp = p->p_fd;
266 register int old = uap->from, new = uap->to;
267 int i, error;
91447636 268 struct fileproc *fp;
1c79356b 269
91447636
A
270 proc_fdlock(p);
271
272 if ( (error = fp_lookup(p, old, &fp, 1)) ) {
273 proc_fdunlock(p);
274 return(error);
275 }
276 if (new < 0 ||
277 new >= p->p_rlimit[RLIMIT_NOFILE].rlim_cur ||
278 new >= maxfiles) {
279 fp_drop(p, old, fp, 1);
280 proc_fdunlock(p);
1c79356b 281 return (EBADF);
91447636 282 }
1c79356b 283 if (old == new) {
91447636 284 fp_drop(p, old, fp, 1);
1c79356b 285 *retval = new;
91447636 286 proc_fdunlock(p);
1c79356b
A
287 return (0);
288 }
91447636
A
289 if (new < 0 || new >= fdp->fd_nfiles) {
290 if ( (error = fdalloc(p, new, &i)) ) {
291 fp_drop(p, old, fp, 1);
292 proc_fdunlock(p);
1c79356b 293 return (error);
91447636 294 }
1c79356b
A
295 if (new != i) {
296 _fdrelse(fdp, i);
297 goto closeit;
298 }
fa4905b1 299 } else {
91447636 300 struct fileproc **fpp;
1c79356b
A
301 char flags;
302closeit:
91447636
A
303 flags = fdp->fd_ofileflags[new];
304 if ((flags & (UF_RESERVED | UF_CLOSING)) == UF_RESERVED) {
305 fp_drop(p, old, fp, 1);
306 proc_fdunlock(p);
1c79356b 307 return (EBADF);
91447636
A
308 }
309
1c79356b
A
310 /*
311 * dup2() must succeed even if the close has an error.
312 */
313 if (*(fpp = &fdp->fd_ofiles[new])) {
91447636 314 struct fileproc *nfp = *fpp;
1c79356b 315
91447636 316 close_internal(p, new, nfp, (CLOSEINT_LOCKED | CLOSEINT_WAITONCLOSE | CLOSEINT_NOFDRELSE | CLOSEINT_NOFDNOREF));
fa4905b1 317 *fpp = NULL;
1c79356b
A
318 }
319 }
91447636
A
320 error = finishdup(p, fdp, old, new, retval);
321 fp_drop(p, old, fp, 1);
322 proc_fdunlock(p);
323
324 return(error);
1c79356b
A
325}
326
327/*
328 * The file control system call.
329 */
1c79356b
A
330int
331fcntl(p, uap, retval)
332 struct proc *p;
91447636 333 struct fcntl_args *uap;
1c79356b
A
334 register_t *retval;
335{
336 int fd = uap->fd;
91447636
A
337 struct filedesc *fdp = p->p_fd;
338 struct fileproc *fp;
339 char *pop;
340 struct vnode *vp;
1c79356b
A
341 int i, tmp, error, error2, flg = F_POSIX;
342 struct flock fl;
91447636
A
343 struct vfs_context context;
344 off_t offset;
1c79356b 345 int newmin;
91447636 346 daddr64_t lbn, bn;
1c79356b 347 int devBlockSize = 0;
91447636
A
348 unsigned int fflag;
349 user_addr_t argp;
1c79356b 350
55e303ae
A
351 AUDIT_ARG(fd, uap->fd);
352 AUDIT_ARG(cmd, uap->cmd);
91447636
A
353
354 proc_fdlock(p);
355 if ( (error = fp_lookup(p, fd, &fp, 1)) ) {
356 proc_fdunlock(p);
357 return(error);
358 }
359 context.vc_proc = p;
360 context.vc_ucred = fp->f_cred;
361 if (proc_is64bit(p)) {
362 argp = uap->arg;
363 }
364 else {
365 /* since the arg parameter is defined as a long but may be either
366 * a long or a pointer we must take care to handle sign extension
367 * issues. Our sys call munger will sign extend a long when we are
368 * called from a 32-bit process. Since we can never have an address
369 * greater than 32-bits from a 32-bit process we lop off the top
370 * 32-bits to avoid getting the wrong address
371 */
372 argp = CAST_USER_ADDR_T(uap->arg);
373 }
374
1c79356b 375 pop = &fdp->fd_ofileflags[fd];
55e303ae 376
1c79356b
A
377 switch (uap->cmd) {
378
379 case F_DUPFD:
91447636 380 newmin = CAST_DOWN(int, uap->arg);
1c79356b 381 if ((u_int)newmin >= p->p_rlimit[RLIMIT_NOFILE].rlim_cur ||
91447636
A
382 newmin >= maxfiles) {
383 error = EINVAL;
384 goto out;
385 }
386 if ( (error = fdalloc(p, newmin, &i)) )
387 goto out;
388 error = finishdup(p, fdp, fd, i, retval);
389 goto out;
1c79356b
A
390
391 case F_GETFD:
392 *retval = (*pop & UF_EXCLOSE)? 1 : 0;
91447636
A
393 error = 0;
394 goto out;
1c79356b
A
395
396 case F_SETFD:
397 *pop = (*pop &~ UF_EXCLOSE) |
91447636
A
398 (uap->arg & 1)? UF_EXCLOSE : 0;
399 error = 0;
400 goto out;
1c79356b
A
401
402 case F_GETFL:
403 *retval = OFLAGS(fp->f_flag);
91447636
A
404 error = 0;
405 goto out;
1c79356b
A
406
407 case F_SETFL:
408 fp->f_flag &= ~FCNTLFLAGS;
91447636
A
409 tmp = CAST_DOWN(int, uap->arg);
410 fp->f_flag |= FFLAGS(tmp) & FCNTLFLAGS;
1c79356b 411 tmp = fp->f_flag & FNONBLOCK;
9bccf70c 412 error = fo_ioctl(fp, FIONBIO, (caddr_t)&tmp, p);
1c79356b 413 if (error)
91447636 414 goto out;
1c79356b 415 tmp = fp->f_flag & FASYNC;
9bccf70c 416 error = fo_ioctl(fp, FIOASYNC, (caddr_t)&tmp, p);
1c79356b 417 if (!error)
91447636 418 goto out;
1c79356b
A
419 fp->f_flag &= ~FNONBLOCK;
420 tmp = 0;
9bccf70c 421 (void)fo_ioctl(fp, FIONBIO, (caddr_t)&tmp, p);
91447636 422 goto out;
1c79356b
A
423
424 case F_GETOWN:
425 if (fp->f_type == DTYPE_SOCKET) {
426 *retval = ((struct socket *)fp->f_data)->so_pgid;
91447636
A
427 error = 0;
428 goto out;
1c79356b 429 }
9bccf70c 430 error = fo_ioctl(fp, (int)TIOCGPGRP, (caddr_t)retval, p);
1c79356b 431 *retval = -*retval;
91447636 432 goto out;
1c79356b
A
433
434 case F_SETOWN:
91447636 435 tmp = CAST_DOWN(pid_t, uap->arg);
1c79356b 436 if (fp->f_type == DTYPE_SOCKET) {
91447636
A
437 ((struct socket *)fp->f_data)->so_pgid = tmp;
438 error =0;
439 goto out;
1c79356b 440 }
91447636
A
441 if (fp->f_type == DTYPE_PIPE) {
442 error = fo_ioctl(fp, (int)TIOCSPGRP, (caddr_t)&tmp, p);
443 goto out;
444 }
445
446 if (tmp <= 0) {
447 tmp = -tmp;
1c79356b 448 } else {
91447636
A
449 struct proc *p1 = pfind(tmp);
450 if (p1 == 0) {
451 error = ESRCH;
452 goto out;
453 }
454 tmp = (int)p1->p_pgrp->pg_id;
1c79356b 455 }
91447636
A
456 error = fo_ioctl(fp, (int)TIOCSPGRP, (caddr_t)&tmp, p);
457 goto out;
1c79356b
A
458
459 case F_SETLKW:
460 flg |= F_WAIT;
461 /* Fall into F_SETLK */
462
463 case F_SETLK:
91447636
A
464 if (fp->f_type != DTYPE_VNODE) {
465 error = EBADF;
466 goto out;
467 }
1c79356b 468 vp = (struct vnode *)fp->f_data;
ccc36f2f 469
91447636
A
470 fflag = fp->f_flag;
471 offset = fp->f_offset;
472 proc_fdunlock(p);
473
1c79356b 474 /* Copy in the lock structure */
91447636
A
475 error = copyin(argp, (caddr_t)&fl, sizeof (fl));
476 if (error) {
477 goto outdrop;
478 }
479 if ( (error = vnode_getwithref(vp)) ) {
480 goto outdrop;
481 }
1c79356b 482 if (fl.l_whence == SEEK_CUR)
91447636
A
483 fl.l_start += offset;
484
1c79356b
A
485 switch (fl.l_type) {
486
487 case F_RDLCK:
91447636
A
488 if ((fflag & FREAD) == 0) {
489 (void)vnode_put(vp);
ccc36f2f 490 error = EBADF;
91447636
A
491 goto outdrop;
492 }
b36670ce 493 OSBitOrAtomic(P_LADVLOCK, &p->p_ladvflag);
91447636
A
494 error = VNOP_ADVLOCK(vp, (caddr_t)p, F_SETLK, &fl, flg, &context);
495 (void)vnode_put(vp);
496 goto outdrop;
1c79356b
A
497
498 case F_WRLCK:
91447636
A
499 if ((fflag & FWRITE) == 0) {
500 (void)vnode_put(vp);
ccc36f2f 501 error = EBADF;
91447636
A
502 goto outdrop;
503 }
b36670ce 504 OSBitOrAtomic(P_LADVLOCK, &p->p_ladvflag);
91447636
A
505 error = VNOP_ADVLOCK(vp, (caddr_t)p, F_SETLK, &fl, flg, &context);
506 (void)vnode_put(vp);
507 goto outdrop;
1c79356b
A
508
509 case F_UNLCK:
91447636
A
510 error = VNOP_ADVLOCK(vp, (caddr_t)p, F_UNLCK, &fl,
511 F_POSIX, &context);
512 (void)vnode_put(vp);
513 goto outdrop;
1c79356b
A
514
515 default:
91447636 516 (void)vnode_put(vp);
ccc36f2f 517 error = EINVAL;
91447636 518 goto outdrop;
1c79356b
A
519 }
520
521 case F_GETLK:
91447636
A
522 if (fp->f_type != DTYPE_VNODE) {
523 error = EBADF;
524 goto out;
525 }
1c79356b 526 vp = (struct vnode *)fp->f_data;
ccc36f2f 527
91447636
A
528 offset = fp->f_offset;
529 proc_fdunlock(p);
530
1c79356b 531 /* Copy in the lock structure */
91447636 532 error = copyin(argp, (caddr_t)&fl, sizeof (fl));
1c79356b 533 if (error)
91447636
A
534 goto outdrop;
535
536 if ( (error = vnode_getwithref(vp)) == 0 ) {
537 if (fl.l_whence == SEEK_CUR)
538 fl.l_start += offset;
539
540 error = VNOP_ADVLOCK(vp, (caddr_t)p, F_GETLK, &fl, F_POSIX, &context);
541
542 (void)vnode_put(vp);
543
544 if (error == 0)
545 error = copyout((caddr_t)&fl, argp, sizeof (fl));
546 }
547 goto outdrop;
548
549 case F_PREALLOCATE: {
550 fstore_t alloc_struct; /* structure for allocate command */
551 u_int32_t alloc_flags = 0;
552
553 if (fp->f_type != DTYPE_VNODE) {
554 error = EBADF;
555 goto out;
556 }
1c79356b 557
ccc36f2f 558 vp = (struct vnode *)fp->f_data;
91447636 559 proc_fdunlock(p);
9bccf70c
A
560
561 /* make sure that we have write permission */
ccc36f2f
A
562 if ((fp->f_flag & FWRITE) == 0) {
563 error = EBADF;
91447636 564 goto outdrop;
ccc36f2f 565 }
1c79356b 566
91447636 567 error = copyin(argp, (caddr_t)&alloc_struct, sizeof (alloc_struct));
1c79356b 568 if (error)
91447636 569 goto outdrop;
1c79356b 570
9bccf70c 571 /* now set the space allocated to 0 */
1c79356b
A
572 alloc_struct.fst_bytesalloc = 0;
573
9bccf70c
A
574 /*
575 * Do some simple parameter checking
576 */
1c79356b
A
577
578 /* set up the flags */
579
580 alloc_flags |= PREALLOCATE;
581
9bccf70c 582 if (alloc_struct.fst_flags & F_ALLOCATECONTIG)
1c79356b 583 alloc_flags |= ALLOCATECONTIG;
1c79356b 584
9bccf70c
A
585 if (alloc_struct.fst_flags & F_ALLOCATEALL)
586 alloc_flags |= ALLOCATEALL;
1c79356b 587
9bccf70c
A
588 /*
589 * Do any position mode specific stuff. The only
590 * position mode supported now is PEOFPOSMODE
591 */
1c79356b
A
592
593 switch (alloc_struct.fst_posmode) {
594
595 case F_PEOFPOSMODE:
91447636 596 if (alloc_struct.fst_offset != 0) {
ccc36f2f 597 error = EINVAL;
91447636
A
598 goto outdrop;
599 }
600
601 alloc_flags |= ALLOCATEFROMPEOF;
1c79356b
A
602 break;
603
0b4e3aa0 604 case F_VOLPOSMODE:
91447636 605 if (alloc_struct.fst_offset <= 0) {
ccc36f2f 606 error = EINVAL;
91447636
A
607 goto outdrop;
608 }
609
610 alloc_flags |= ALLOCATEFROMVOL;
0b4e3aa0
A
611 break;
612
91447636 613 default: {
ccc36f2f 614 error = EINVAL;
91447636
A
615 goto outdrop;
616 }
1c79356b 617 }
91447636
A
618 if ( (error = vnode_getwithref(vp)) == 0 ) {
619 /*
620 * call allocate to get the space
621 */
622 error = VNOP_ALLOCATE(vp,alloc_struct.fst_length,alloc_flags,
623 &alloc_struct.fst_bytesalloc, alloc_struct.fst_offset,
624 &context);
625 (void)vnode_put(vp);
1c79356b 626
91447636 627 error2 = copyout((caddr_t)&alloc_struct, argp, sizeof (alloc_struct));
1c79356b 628
91447636 629 if (error == 0)
ccc36f2f 630 error = error2;
1c79356b 631 }
91447636 632 goto outdrop;
1c79356b 633
91447636 634 }
9bccf70c 635 case F_SETSIZE:
91447636
A
636 if (fp->f_type != DTYPE_VNODE) {
637 error = EBADF;
638 goto out;
639 }
640 proc_fdunlock(p);
ccc36f2f 641
91447636 642 error = copyin(argp, (caddr_t)&offset, sizeof (off_t));
1c79356b 643 if (error)
91447636 644 goto outdrop;
1c79356b 645
9bccf70c
A
646 /*
647 * Make sure that we are root. Growing a file
648 * without zero filling the data is a security hole
649 * root would have access anyway so we'll allow it
650 */
1c79356b 651
ccc36f2f
A
652 if (!is_suser()) {
653 error = EACCES;
91447636 654 goto outdrop;
ccc36f2f 655 }
91447636 656 vp = (struct vnode *)fp->f_data;
1c79356b 657
91447636
A
658 if ( (error = vnode_getwithref(vp)) == 0 ) {
659 /*
660 * set the file size
661 */
662 error = vnode_setsize(vp, offset, IO_NOZEROFILL, &context);
663
664 (void)vnode_put(vp);
665 }
666 goto outdrop;
9bccf70c
A
667
668 case F_RDAHEAD:
91447636
A
669 if (fp->f_type != DTYPE_VNODE) {
670 error = EBADF;
671 goto out;
672 }
9bccf70c 673 vp = (struct vnode *)fp->f_data;
91447636 674 proc_fdunlock(p);
9bccf70c 675
91447636
A
676 if ( (error = vnode_getwithref(vp)) == 0) {
677 if (uap->arg)
678 vnode_clearnoreadahead(vp);
679 else
680 vnode_setnoreadahead(vp);
681
682 (void)vnode_put(vp);
683 }
684 goto outdrop;
1c79356b 685
9bccf70c 686 case F_NOCACHE:
91447636
A
687 if (fp->f_type != DTYPE_VNODE) {
688 error = EBADF;
689 goto out;
690 }
9bccf70c 691 vp = (struct vnode *)fp->f_data;
91447636 692 proc_fdunlock(p);
9bccf70c 693
91447636
A
694 if ( (error = vnode_getwithref(vp)) == 0 ) {
695 if (uap->arg)
696 vnode_setnocache(vp);
697 else
698 vnode_clearnocache(vp);
1c79356b 699
91447636
A
700 (void)vnode_put(vp);
701 }
702 goto outdrop;
1c79356b 703
91447636
A
704 case F_RDADVISE: {
705 struct radvisory ra_struct;
9bccf70c 706
91447636
A
707 if (fp->f_type != DTYPE_VNODE) {
708 error = EBADF;
709 goto out;
710 }
55e303ae 711 vp = (struct vnode *)fp->f_data;
91447636 712 proc_fdunlock(p);
55e303ae 713
91447636
A
714 if ( (error = copyin(argp, (caddr_t)&ra_struct, sizeof (ra_struct))) )
715 goto outdrop;
716 if ( (error = vnode_getwithref(vp)) == 0 ) {
717 error = VNOP_IOCTL(vp, F_RDADVISE, (caddr_t)&ra_struct, 0, &context);
718
719 (void)vnode_put(vp);
720 }
721 goto outdrop;
722 }
55e303ae 723
1c79356b 724 case F_READBOOTSTRAP:
91447636
A
725 case F_WRITEBOOTSTRAP: {
726 fbootstraptransfer_t fbt_struct;
727 user_fbootstraptransfer_t user_fbt_struct;
728 int sizeof_struct;
729 caddr_t boot_structp;
730
731 if (fp->f_type != DTYPE_VNODE) {
732 error = EBADF;
733 goto out;
734 }
ccc36f2f 735 vp = (struct vnode *)fp->f_data;
91447636 736 proc_fdunlock(p);
1c79356b 737
91447636
A
738 if (IS_64BIT_PROCESS(p)) {
739 sizeof_struct = sizeof(user_fbt_struct);
740 boot_structp = (caddr_t) &user_fbt_struct;
741 }
742 else {
743 sizeof_struct = sizeof(fbt_struct);
744 boot_structp = (caddr_t) &fbt_struct;
745 }
746 error = copyin(argp, boot_structp, sizeof_struct);
1c79356b 747 if (error)
91447636
A
748 goto outdrop;
749 if ( (error = vnode_getwithref(vp)) ) {
750 goto outdrop;
751 }
1c79356b 752 if (uap->cmd == F_WRITEBOOTSTRAP) {
91447636
A
753 /*
754 * Make sure that we are root. Updating the
755 * bootstrap on a disk could be a security hole
756 */
ccc36f2f 757 if (!is_suser()) {
91447636 758 (void)vnode_put(vp);
ccc36f2f 759 error = EACCES;
91447636 760 goto outdrop;
ccc36f2f 761 }
9bccf70c 762 }
91447636 763 if (strcmp(vnode_mount(vp)->mnt_vfsstat.f_fstypename, "hfs") != 0) {
9bccf70c 764 error = EINVAL;
91447636
A
765 } else {
766 /*
767 * call vnop_ioctl to handle the I/O
768 */
769 error = VNOP_IOCTL(vp, uap->cmd, boot_structp, 0, &context);
9bccf70c 770 }
91447636
A
771 (void)vnode_put(vp);
772 goto outdrop;
773 }
774 case F_LOG2PHYS: {
775 struct log2phys l2p_struct; /* structure for allocate command */
9bccf70c 776
91447636
A
777 if (fp->f_type != DTYPE_VNODE) {
778 error = EBADF;
779 goto out;
780 }
1c79356b 781 vp = (struct vnode *)fp->f_data;
91447636
A
782 proc_fdunlock(p);
783 if ( (error = vnode_getwithref(vp)) ) {
784 goto outdrop;
785 }
786 error = VNOP_OFFTOBLK(vp, fp->f_offset, &lbn);
787 if (error) {
788 (void)vnode_put(vp);
789 goto outdrop;
790 }
791 error = VNOP_BLKTOOFF(vp, lbn, &offset);
792 if (error) {
793 (void)vnode_put(vp);
794 goto outdrop;
795 }
796 devBlockSize = vfs_devblocksize(vnode_mount(vp));
797
798 error = VNOP_BLOCKMAP(vp, offset, devBlockSize, &bn, NULL, NULL, 0, &context);
799
800 (void)vnode_put(vp);
ccc36f2f 801
1c79356b
A
802 if (!error) {
803 l2p_struct.l2p_flags = 0; /* for now */
804 l2p_struct.l2p_contigbytes = 0; /* for now */
805 l2p_struct.l2p_devoffset = bn * devBlockSize;
806 l2p_struct.l2p_devoffset += fp->f_offset - offset;
91447636
A
807 error = copyout((caddr_t)&l2p_struct, argp, sizeof (l2p_struct));
808 }
809 goto outdrop;
1c79356b 810 }
55e303ae 811 case F_GETPATH: {
91447636
A
812 char *pathbufp;
813 int pathlen;
55e303ae 814
91447636
A
815 if (fp->f_type != DTYPE_VNODE) {
816 error = EBADF;
817 goto out;
818 }
55e303ae 819 vp = (struct vnode *)fp->f_data;
91447636 820 proc_fdunlock(p);
55e303ae 821
91447636
A
822 pathlen = MAXPATHLEN;
823 MALLOC(pathbufp, char *, pathlen, M_TEMP, M_WAITOK);
824 if (pathbufp == NULL) {
825 error = ENOMEM;
826 goto outdrop;
827 }
828 if ( (error = vnode_getwithref(vp)) == 0 ) {
829 error = vn_getpath(vp, pathbufp, &pathlen);
830 (void)vnode_put(vp);
4a249263 831
91447636
A
832 if (error == 0)
833 error = copyout((caddr_t)pathbufp, argp, pathlen);
834 }
835 FREE(pathbufp, M_TEMP);
836 goto outdrop;
55e303ae
A
837 }
838
91447636
A
839 case F_PATHPKG_CHECK: {
840 char *pathbufp;
841 size_t pathlen;
842
843 if (fp->f_type != DTYPE_VNODE) {
844 error = EBADF;
845 goto out;
846 }
55e303ae 847 vp = (struct vnode *)fp->f_data;
91447636 848 proc_fdunlock(p);
55e303ae 849
91447636
A
850 pathlen = MAXPATHLEN;
851 pathbufp = kalloc(MAXPATHLEN);
852
853 if ( (error = copyinstr(argp, pathbufp, MAXPATHLEN, &pathlen)) == 0 ) {
854 if ( (error = vnode_getwithref(vp)) == 0 ) {
855 error = vn_path_package_check(vp, pathbufp, pathlen, retval);
856
857 (void)vnode_put(vp);
858 }
859 }
860 kfree(pathbufp, MAXPATHLEN);
861 goto outdrop;
862 }
863
864 case F_CHKCLEAN: // used by regression tests to see if all dirty pages got cleaned by fsync()
865 case F_FULLFSYNC: // fsync + flush the journal + DKIOCSYNCHRONIZECACHE
866 case F_FREEZE_FS: // freeze all other fs operations for the fs of this fd
867 case F_THAW_FS: { // thaw all frozen fs operations for the fs of this fd
868 if (fp->f_type != DTYPE_VNODE) {
869 error = EBADF;
870 goto out;
871 }
872 vp = (struct vnode *)fp->f_data;
873 proc_fdunlock(p);
ccc36f2f 874
91447636
A
875 if ( (error = vnode_getwithref(vp)) == 0 ) {
876 error = VNOP_IOCTL(vp, uap->cmd, (caddr_t)NULL, 0, &context);
877
878 (void)vnode_put(vp);
879 }
ccc36f2f 880 break;
55e303ae
A
881 }
882
1c79356b 883 default:
91447636
A
884 if (uap->cmd < FCNTL_FS_SPECIFIC_BASE) {
885 error = EINVAL;
886 goto out;
887 }
888
889 // if it's a fs-specific fcntl() then just pass it through
890
891 if (fp->f_type != DTYPE_VNODE) {
892 error = EBADF;
893 goto out;
894 }
895 vp = (struct vnode *)fp->f_data;
896 proc_fdunlock(p);
897
898 if ( (error = vnode_getwithref(vp)) == 0 ) {
899 error = VNOP_IOCTL(vp, uap->cmd, CAST_DOWN(caddr_t, argp), 0, &context);
900
901 (void)vnode_put(vp);
902 }
903 break;
904
1c79356b 905 }
ccc36f2f 906
91447636
A
907outdrop:
908 AUDIT_ARG(vnpath_withref, vp, ARG_VNODE1);
909 fp_drop(p, fd, fp, 0);
910 return(error);
911out:
912 fp_drop(p, fd, fp, 1);
913 proc_fdunlock(p);
914 return(error);
1c79356b
A
915}
916
917/*
918 * Common code for dup, dup2, and fcntl(F_DUPFD).
919 */
920int
91447636 921finishdup(struct proc * p, struct filedesc *fdp, int old, int new, register_t *retval)
1c79356b 922{
91447636
A
923 struct fileproc *nfp;
924 struct fileproc *ofp;
1c79356b 925
91447636 926 if ((ofp = fdp->fd_ofiles[old]) == NULL ||
1c79356b
A
927 (fdp->fd_ofileflags[old] & UF_RESERVED)) {
928 _fdrelse(fdp, new);
929 return (EBADF);
930 }
91447636
A
931 fg_ref(ofp);
932 proc_fdunlock(p);
933
934 MALLOC_ZONE(nfp, struct fileproc *, sizeof(struct fileproc), M_FILEPROC, M_WAITOK);
935 bzero(nfp, sizeof(struct fileproc));
936
937 proc_fdlock(p);
938 nfp->f_flags = ofp->f_flags;
939 nfp->f_fglob = ofp->f_fglob;
940 nfp->f_iocount = 0;
941
942 fdp->fd_ofiles[new] = nfp;
1c79356b 943 fdp->fd_ofileflags[new] = fdp->fd_ofileflags[old] &~ UF_EXCLOSE;
1c79356b
A
944 if (new > fdp->fd_lastfile)
945 fdp->fd_lastfile = new;
946 *retval = new;
947 return (0);
948}
949
91447636 950
1c79356b 951int
91447636 952close(struct proc *p, struct close_args *uap, __unused register_t *retval)
1c79356b 953{
91447636 954 struct fileproc *fp;
1c79356b 955 int fd = uap->fd;
91447636 956 int error =0;
1c79356b 957
e5568f75 958 AUDIT_SYSCLOSE(p, fd);
91447636
A
959
960 proc_fdlock(p);
961
962 if ( (error = fp_lookup(p,fd,&fp, 1)) ) {
963 proc_fdunlock(p);
964 return(error);
965 }
966
967 error = close_internal(p, fd, fp, CLOSEINT_LOCKED | CLOSEINT_WAITONCLOSE);
968
969 proc_fdunlock(p);
970
971 return(error);
972}
973
974
975/*
976 * Close a file descriptor.
977 */
978int
979close_internal(struct proc *p, int fd, struct fileproc *fp, int flags)
980{
981 struct filedesc *fdp = p->p_fd;
982 int error =0;
983 int locked = flags & CLOSEINT_LOCKED;
984 int waitonclose = flags & CLOSEINT_WAITONCLOSE;
985 int norelse = flags & CLOSEINT_NOFDRELSE;
986 int nofdref = flags & CLOSEINT_NOFDNOREF;
987 int slpstate = PRIBIO;
988
989 if (!locked)
990 proc_fdlock(p);
55e303ae
A
991
992 /* Keep people from using the filedesc while we are closing it */
993 fdp->fd_ofileflags[fd] |= UF_RESERVED;
55e303ae 994
91447636
A
995 fdp->fd_ofileflags[fd] |= UF_CLOSING;
996
997
998 if ((waitonclose && ((fp->f_flags & FP_CLOSING) == FP_CLOSING))) {
999 if (nofdref == 0)
1000 fp_drop(p, fd, fp, 1);
1001 fp->f_flags |= FP_WAITCLOSE;
1002 if (!locked)
1003 slpstate |= PDROP;
1004 msleep(&fp->f_flags, &p->p_fdmlock, slpstate, "close wait",0) ;
1005 return(EBADF);
1006 }
1007
1008 fp->f_flags |= FP_CLOSING;
1009 if (nofdref)
1010 fp->f_iocount++;
1011
1012 if ( (fp->f_flags & FP_AIOISSUED) || kauth_authorize_fileop_has_listeners() ) {
1013
1014 proc_fdunlock(p);
1015
1016 if ( (fp->f_type == DTYPE_VNODE) && kauth_authorize_fileop_has_listeners() ) {
1017 /*
1018 * call out to allow 3rd party notification of close.
1019 * Ignore result of kauth_authorize_fileop call.
1020 */
1021 if (vnode_getwithref((vnode_t)fp->f_data) == 0) {
1022 u_int fileop_flags = 0;
1023 if ((fp->f_flags & FP_WRITTEN) != 0)
1024 fileop_flags |= KAUTH_FILEOP_CLOSE_MODIFIED;
1025 kauth_authorize_fileop(fp->f_fglob->fg_cred, KAUTH_FILEOP_CLOSE,
1026 (uintptr_t)fp->f_data, (uintptr_t)fileop_flags);
1027 vnode_put((vnode_t)fp->f_data);
1028 }
1029 }
1030 if (fp->f_flags & FP_AIOISSUED)
1031 /*
1032 * cancel all async IO requests that can be cancelled.
1033 */
1034 _aio_close( p, fd );
1035
1036 proc_fdlock(p);
1037 }
1038
1039 if (fd < fdp->fd_knlistsize)
55e303ae
A
1040 knote_fdclose(p, fd);
1041
91447636
A
1042 if (fp->f_flags & FP_WAITEVENT)
1043 (void)waitevent_close(p, fp);
1044
1045 if ((fp->f_flags & FP_INCHRREAD) == 0)
1046 fileproc_drain(p, fp);
1047 if (norelse == 0)
1048 _fdrelse(fdp, fd);
1049 error = closef_locked(fp, fp->f_fglob, p);
1050 if ((fp->f_flags & FP_WAITCLOSE) == FP_WAITCLOSE)
1051 wakeup(&fp->f_flags);
1052 fp->f_flags &= ~(FP_WAITCLOSE | FP_CLOSING);
1053
1054 if (!locked)
1055 proc_fdunlock(p);
1056
1057 FREE_ZONE(fp, sizeof *fp, M_FILEPROC);
1058 return(error);
1c79356b
A
1059}
1060
1061/*
1062 * Return status information about a file descriptor.
91447636
A
1063 *
1064 * XXX switch on node type is bogus; need a stat in struct fileops instead.
1c79356b 1065 */
91447636
A
1066static int
1067fstat1(struct proc *p, int fd, user_addr_t ub, user_addr_t xsecurity, user_addr_t xsecurity_size)
1c79356b 1068{
91447636
A
1069 struct fileproc *fp;
1070 struct stat sb;
1071 struct user_stat user_sb;
1072 int error, my_size;
1073 int funnel_state;
1074 short type;
1075 caddr_t data;
1076 kauth_filesec_t fsec;
1077 ssize_t xsecurity_bufsize;
1078 int entrycount;
1079 struct vfs_context context;
1c79356b 1080
91447636
A
1081
1082 AUDIT_ARG(fd, fd);
1083
1084 if ((error = fp_lookup(p, fd, &fp, 0)) != 0)
1085 return(error);
1086 type = fp->f_type;
1087 data = fp->f_data;
1088 fsec = KAUTH_FILESEC_NONE;
1089
1090 switch (type) {
1c79356b
A
1091
1092 case DTYPE_VNODE:
91447636
A
1093 context.vc_proc = current_proc();
1094 context.vc_ucred = kauth_cred_get();
1095 if ((error = vnode_getwithref((vnode_t)data)) == 0) {
1096 /*
1097 * If the caller has the file open, and is not requesting extended security,
1098 * we are going to let them get the basic stat information.
1099 */
1100 if (xsecurity == USER_ADDR_NULL) {
1101 error = vn_stat_noauth((vnode_t)data, &sb, NULL, &context);
1102 } else {
1103 error = vn_stat((vnode_t)data, &sb, &fsec, &context);
1104 }
1105
1106 AUDIT_ARG(vnpath, (struct vnode *)data, ARG_VNODE1);
1107 (void)vnode_put((vnode_t)data);
55e303ae 1108 }
1c79356b
A
1109 break;
1110
1111 case DTYPE_SOCKET:
91447636
A
1112 error = soo_stat((struct socket *)data, &sb);
1113 break;
1114
1115 case DTYPE_PIPE:
1116 error = pipe_stat((void *)data, &sb);
1c79356b
A
1117 break;
1118
1119 case DTYPE_PSXSHM:
91447636 1120 error = pshm_stat((void *)data, &sb);
1c79356b 1121 break;
55e303ae
A
1122
1123 case DTYPE_KQUEUE:
91447636
A
1124 funnel_state = thread_funnel_set(kernel_flock, TRUE);
1125 error = kqueue_stat(fp, &sb, p);
1126 thread_funnel_set(kernel_flock, funnel_state);
1127 break;
55e303ae 1128
1c79356b 1129 default:
91447636
A
1130 error = EBADF;
1131 goto out;
1132 }
1133 /* Zap spare fields */
1134 sb.st_lspare = 0;
1135 sb.st_qspare[0] = 0LL;
1136 sb.st_qspare[1] = 0LL;
1137 if (error == 0) {
1138 caddr_t sbp;
1139 if (IS_64BIT_PROCESS(current_proc())) {
1140 munge_stat(&sb, &user_sb);
1141 my_size = sizeof(user_sb);
1142 sbp = (caddr_t)&user_sb;
1143 }
1144 else {
1145 my_size = sizeof(sb);
1146 sbp = (caddr_t)&sb;
1147 }
1148 error = copyout(sbp, ub, my_size);
1c79356b 1149 }
1c79356b 1150
91447636
A
1151 /* caller wants extended security information? */
1152 if (xsecurity != USER_ADDR_NULL) {
1c79356b 1153
91447636
A
1154 /* did we get any? */
1155 if (fsec == KAUTH_FILESEC_NONE) {
1156 if (susize(xsecurity_size, 0) != 0) {
1157 error = EFAULT;
1158 goto out;
1159 }
1160 } else {
1161 /* find the user buffer size */
1162 xsecurity_bufsize = fusize(xsecurity_size);
1c79356b 1163
91447636
A
1164 /* copy out the actual data size */
1165 if (susize(xsecurity_size, KAUTH_FILESEC_COPYSIZE(fsec)) != 0) {
1166 error = EFAULT;
1167 goto out;
1168 }
1c79356b 1169
91447636
A
1170 /* if the caller supplied enough room, copy out to it */
1171 if (xsecurity_bufsize >= KAUTH_FILESEC_COPYSIZE(fsec))
1172 error = copyout(fsec, xsecurity, KAUTH_FILESEC_COPYSIZE(fsec));
1173 }
1c79356b 1174 }
91447636
A
1175out:
1176 fp_drop(p, fd, fp, 0);
1177 if (fsec != NULL)
1178 kauth_filesec_free(fsec);
1c79356b
A
1179 return (error);
1180}
91447636
A
1181
1182int
1183fstat_extended(struct proc *p, struct fstat_extended_args *uap, __unused register_t *retval)
1184{
1185 return(fstat1(p, uap->fd, uap->ub, uap->xsecurity, uap->xsecurity_size));
1186}
1187
1188int
1189fstat(struct proc *p, register struct fstat_args *uap, __unused register_t *retval)
1190{
1191 return(fstat1(p, uap->fd, uap->ub, 0, 0));
1192}
1c79356b
A
1193
1194/*
1195 * Return pathconf information about a file descriptor.
1196 */
91447636 1197int
1c79356b
A
1198fpathconf(p, uap, retval)
1199 struct proc *p;
1200 register struct fpathconf_args *uap;
1201 register_t *retval;
1202{
1203 int fd = uap->fd;
91447636 1204 struct fileproc *fp;
1c79356b 1205 struct vnode *vp;
91447636
A
1206 struct vfs_context context;
1207 int error = 0;
1208 short type;
1209 caddr_t data;
1210
1c79356b 1211
55e303ae 1212 AUDIT_ARG(fd, uap->fd);
91447636
A
1213 if ( (error = fp_lookup(p, fd, &fp, 0)) )
1214 return(error);
1215 type = fp->f_type;
1216 data = fp->f_data;
1217
1218 switch (type) {
1c79356b
A
1219
1220 case DTYPE_SOCKET:
91447636
A
1221 if (uap->name != _PC_PIPE_BUF) {
1222 error = EINVAL;
1223 goto out;
1224 }
1c79356b 1225 *retval = PIPE_BUF;
91447636
A
1226 error = 0;
1227 goto out;
1228
1229 case DTYPE_PIPE:
1230 *retval = PIPE_BUF;
1231 error = 0;
1232 goto out;
1c79356b
A
1233
1234 case DTYPE_VNODE:
91447636
A
1235 vp = (struct vnode *)data;
1236
1237 if ( (error = vnode_getwithref(vp)) == 0) {
1238 AUDIT_ARG(vnpath, vp, ARG_VNODE1);
1239
1240 context.vc_proc = p;
1241 context.vc_ucred = kauth_cred_get();
1242
1243 error = vn_pathconf(vp, uap->name, retval, &context);
1244
1245 (void)vnode_put(vp);
1246 }
1247 goto out;
55e303ae 1248
91447636
A
1249 case DTYPE_PSXSHM:
1250 case DTYPE_KQUEUE:
1251 error = EINVAL;
1252 goto out;
1c79356b
A
1253
1254 default:
91447636 1255 panic("fpathconf (unrecognized - %d)", type);
1c79356b
A
1256 }
1257 /*NOTREACHED*/
91447636
A
1258out:
1259 fp_drop(p, fd, fp, 0);
1260 return(error);
1c79356b
A
1261}
1262
1263/*
1264 * Allocate a file descriptor for the process.
1265 */
1266int fdexpand;
1267
1268int
1269fdalloc(p, want, result)
1270 struct proc *p;
1271 int want;
1272 int *result;
1273{
1274 register struct filedesc *fdp = p->p_fd;
1275 register int i;
91447636
A
1276 int lim, last, numfiles, oldnfiles;
1277 struct fileproc **newofiles, **ofiles;
1c79356b
A
1278 char *newofileflags, *ofileflags;
1279
1280 /*
1281 * Search for a free descriptor starting at the higher
1282 * of want or fd_freefile. If that fails, consider
1283 * expanding the ofile array.
1284 */
1285 lim = min((int)p->p_rlimit[RLIMIT_NOFILE].rlim_cur, maxfiles);
1286 for (;;) {
1287 last = min(fdp->fd_nfiles, lim);
1288 if ((i = want) < fdp->fd_freefile)
1289 i = fdp->fd_freefile;
1290 ofiles = &fdp->fd_ofiles[i];
1291 ofileflags = &fdp->fd_ofileflags[i];
1292 for (; i < last; i++) {
1293 if (*ofiles == NULL && !(*ofileflags & UF_RESERVED)) {
1294 *ofileflags = UF_RESERVED;
1295 if (i > fdp->fd_lastfile)
1296 fdp->fd_lastfile = i;
1297 if (want <= fdp->fd_freefile)
1298 fdp->fd_freefile = i;
1299 *result = i;
1300 return (0);
1301 }
1302 ofiles++; ofileflags++;
1303 }
1304
1305 /*
1306 * No space in current array. Expand?
1307 */
1308 if (fdp->fd_nfiles >= lim)
1309 return (EMFILE);
1310 if (fdp->fd_nfiles < NDEXTENT)
91447636 1311 numfiles = NDEXTENT;
1c79356b 1312 else
91447636 1313 numfiles = 2 * fdp->fd_nfiles;
1c79356b 1314 /* Enforce lim */
91447636
A
1315 if (numfiles > lim)
1316 numfiles = lim;
1317 proc_fdunlock(p);
1318 MALLOC_ZONE(newofiles, struct fileproc **,
1319 numfiles * OFILESIZE, M_OFILETABL, M_WAITOK);
1320 proc_fdlock(p);
1321 if (newofiles == NULL) {
1322 return (ENOMEM);
1323 }
1324 if (fdp->fd_nfiles >= numfiles) {
1325 FREE_ZONE(newofiles, numfiles * OFILESIZE, M_OFILETABL);
1c79356b
A
1326 continue;
1327 }
91447636 1328 newofileflags = (char *) &newofiles[numfiles];
1c79356b
A
1329 /*
1330 * Copy the existing ofile and ofileflags arrays
1331 * and zero the new portion of each array.
1332 */
1333 oldnfiles = fdp->fd_nfiles;
1334 (void) memcpy(newofiles, fdp->fd_ofiles,
1335 oldnfiles * sizeof *fdp->fd_ofiles);
1336 (void) memset(&newofiles[oldnfiles], 0,
91447636 1337 (numfiles - oldnfiles) * sizeof *fdp->fd_ofiles);
1c79356b
A
1338
1339 (void) memcpy(newofileflags, fdp->fd_ofileflags,
1340 oldnfiles * sizeof *fdp->fd_ofileflags);
1341 (void) memset(&newofileflags[oldnfiles], 0,
91447636 1342 (numfiles - oldnfiles) *
1c79356b
A
1343 sizeof *fdp->fd_ofileflags);
1344 ofiles = fdp->fd_ofiles;
1345 fdp->fd_ofiles = newofiles;
1346 fdp->fd_ofileflags = newofileflags;
91447636 1347 fdp->fd_nfiles = numfiles;
1c79356b
A
1348 FREE_ZONE(ofiles, oldnfiles * OFILESIZE, M_OFILETABL);
1349 fdexpand++;
1350 }
1351}
1352
91447636
A
1353/*
1354 * Check to see whether n user file descriptors
1355 * are available to the process p.
1356 */
1357int
1358fdavail(p, n)
1359 struct proc *p;
1360 int n;
1361{
1362 struct filedesc *fdp = p->p_fd;
1363 struct fileproc **fpp;
1364 char *flags;
1365 int i, lim;
1366
1367 lim = min((int)p->p_rlimit[RLIMIT_NOFILE].rlim_cur, maxfiles);
1368 if ((i = lim - fdp->fd_nfiles) > 0 && (n -= i) <= 0)
1369 return (1);
1370 fpp = &fdp->fd_ofiles[fdp->fd_freefile];
1371 flags = &fdp->fd_ofileflags[fdp->fd_freefile];
1372 for (i = fdp->fd_nfiles - fdp->fd_freefile; --i >= 0; fpp++, flags++)
1373 if (*fpp == NULL && !(*flags & UF_RESERVED) && --n <= 0)
1374 return (1);
1375 return (0);
1376}
1377
1378void
1379fdrelse(p, fd)
1380 struct proc *p;
1381 int fd;
1382{
1383 _fdrelse(p->p_fd, fd);
1384}
1385
1386void
1387fddrop(p, fd)
1388 struct proc *p;
1389 int fd;
1390{
1391 struct filedesc *fdp = p->p_fd;
1392 struct fileproc *fp;
1393
1394 if (fd < fdp->fd_freefile)
1395 fdp->fd_freefile = fd;
1396#if DIAGNOSTIC
1397 if (fd > fdp->fd_lastfile)
1398 panic("fdrelse: fd_lastfile inconsistent");
1399#endif
1400 fp = fdp->fd_ofiles[fd];
1401 fdp->fd_ofiles[fd] = NULL;
1402 fdp->fd_ofileflags[fd] = 0;
1403
1404 while ((fd = fdp->fd_lastfile) > 0 &&
1405 fdp->fd_ofiles[fd] == NULL &&
1406 !(fdp->fd_ofileflags[fd] & UF_RESERVED))
1407 fdp->fd_lastfile--;
1408 FREE_ZONE(fp, sizeof *fp, M_FILEPROC);
1409}
1410
1411
1412int
1413fdgetf_noref(p, fd, resultfp)
1414 struct proc *p;
1415 int fd;
1416 struct fileproc **resultfp;
1417{
1418 struct filedesc *fdp = p->p_fd;
1419 struct fileproc *fp;
1420
1421 if (fd < 0 || fd >= fdp->fd_nfiles ||
1422 (fp = fdp->fd_ofiles[fd]) == NULL ||
1423 (fdp->fd_ofileflags[fd] & UF_RESERVED)) {
1424 return (EBADF);
1425 }
1426 if (resultfp)
1427 *resultfp = fp;
1428 return (0);
1429}
1430
1431
1432/* should be called only when proc_fdlock is held */
1433void
1434fp_setflags(proc_t p, struct fileproc * fp, int flags)
1435{
1436 proc_fdlock(p);
1437 fp->f_flags |= flags;
1438 proc_fdunlock(p);
1439}
1440
1441void
1442fp_clearflags(proc_t p, struct fileproc * fp, int flags)
1443{
1444
1445 proc_fdlock(p);
1446 if (fp)
1447 fp->f_flags &= ~flags;
1448 proc_fdunlock(p);
1449}
1450
1451int
1452fp_getfvp(p, fd, resultfp, resultvp)
1453 struct proc *p;
1454 int fd;
1455 struct fileproc **resultfp;
1456 struct vnode **resultvp;
1457{
1458 struct filedesc *fdp = p->p_fd;
1459 struct fileproc *fp;
1460
1461 proc_fdlock(p);
1462 if (fd < 0 || fd >= fdp->fd_nfiles ||
1463 (fp = fdp->fd_ofiles[fd]) == NULL ||
1464 (fdp->fd_ofileflags[fd] & UF_RESERVED)) {
1465 proc_fdunlock(p);
1466 return (EBADF);
1467 }
1468 if (fp->f_type != DTYPE_VNODE) {
1469 proc_fdunlock(p);
1470 return(ENOTSUP);
1471 }
1472 fp->f_iocount++;
1473
1474 if (resultfp)
1475 *resultfp = fp;
1476 if (resultvp)
1477 *resultvp = (struct vnode *)fp->f_data;
1478 proc_fdunlock(p);
1479
1480 return (0);
1481}
1482
1483
1484/*
1485 * Returns: EBADF The file descriptor is invalid
1486 * EOPNOTSUPP The file descriptor is not a socket
1487 * 0 Success
1488 *
1489 * Notes: EOPNOTSUPP should probably be ENOTSOCK; this function is only
1490 * ever called from accept1().
1491 */
1492int
1493fp_getfsock(p, fd, resultfp, results)
1494 struct proc *p;
1495 int fd;
1496 struct fileproc **resultfp;
1497 struct socket **results;
1498{
1499 struct filedesc *fdp = p->p_fd;
1500 struct fileproc *fp;
1501
1502 proc_fdlock(p);
1503 if (fd < 0 || fd >= fdp->fd_nfiles ||
1504 (fp = fdp->fd_ofiles[fd]) == NULL ||
1505 (fdp->fd_ofileflags[fd] & UF_RESERVED)) {
1506 proc_fdunlock(p);
1507 return (EBADF);
1508 }
1509 if (fp->f_type != DTYPE_SOCKET) {
1510 proc_fdunlock(p);
1511 return(EOPNOTSUPP);
1512 }
1513 fp->f_iocount++;
1514
1515 if (resultfp)
1516 *resultfp = fp;
1517 if (results)
1518 *results = (struct socket *)fp->f_data;
1519 proc_fdunlock(p);
1520
1521 return (0);
1522}
1523
1524
1525int
1526fp_getfkq(p, fd, resultfp, resultkq)
1527 struct proc *p;
1528 int fd;
1529 struct fileproc **resultfp;
1530 struct kqueue **resultkq;
1531{
1532 struct filedesc *fdp = p->p_fd;
1533 struct fileproc *fp;
1534
1535 proc_fdlock(p);
1536 if ( fd < 0 || fd >= fdp->fd_nfiles ||
1537 (fp = fdp->fd_ofiles[fd]) == NULL ||
1538 (fdp->fd_ofileflags[fd] & UF_RESERVED)) {
1539 proc_fdunlock(p);
1540 return (EBADF);
1541 }
1542 if (fp->f_type != DTYPE_KQUEUE) {
1543 proc_fdunlock(p);
1544 return(EBADF);
1545 }
1546 fp->f_iocount++;
1547
1548 if (resultfp)
1549 *resultfp = fp;
1550 if (resultkq)
1551 *resultkq = (struct kqueue *)fp->f_data;
1552 proc_fdunlock(p);
1553
1554 return (0);
1555}
1556
1557int
1558fp_getfpshm(p, fd, resultfp, resultpshm)
1559 struct proc *p;
1560 int fd;
1561 struct fileproc **resultfp;
1562 struct pshmnode **resultpshm;
1563{
1564 struct filedesc *fdp = p->p_fd;
1565 struct fileproc *fp;
1566
1567 proc_fdlock(p);
1568 if (fd < 0 || fd >= fdp->fd_nfiles ||
1569 (fp = fdp->fd_ofiles[fd]) == NULL ||
1570 (fdp->fd_ofileflags[fd] & UF_RESERVED)) {
1571 proc_fdunlock(p);
1572 return (EBADF);
1573 }
1574 if (fp->f_type != DTYPE_PSXSHM) {
1575
1576 proc_fdunlock(p);
1577 return(EBADF);
1578 }
1579 fp->f_iocount++;
1580
1581 if (resultfp)
1582 *resultfp = fp;
1583 if (resultpshm)
1584 *resultpshm = (struct pshmnode *)fp->f_data;
1585 proc_fdunlock(p);
1586
1587 return (0);
1588}
1589
1590
1591int
1592fp_getfpsem(p, fd, resultfp, resultpsem)
1593 struct proc *p;
1594 int fd;
1595 struct fileproc **resultfp;
1596 struct psemnode **resultpsem;
1597{
1598 struct filedesc *fdp = p->p_fd;
1599 struct fileproc *fp;
1600
1601 proc_fdlock(p);
1602 if (fd < 0 || fd >= fdp->fd_nfiles ||
1603 (fp = fdp->fd_ofiles[fd]) == NULL ||
1604 (fdp->fd_ofileflags[fd] & UF_RESERVED)) {
1605 proc_fdunlock(p);
1606 return (EBADF);
1607 }
1608 if (fp->f_type != DTYPE_PSXSEM) {
1609 proc_fdunlock(p);
1610 return(EBADF);
1611 }
1612 fp->f_iocount++;
1613
1614 if (resultfp)
1615 *resultfp = fp;
1616 if (resultpsem)
1617 *resultpsem = (struct psemnode *)fp->f_data;
1618 proc_fdunlock(p);
1619
1620 return (0);
1621}
1622int
1623fp_lookup(p, fd, resultfp, locked)
1624 struct proc *p;
1625 int fd;
1626 struct fileproc **resultfp;
1627 int locked;
1628{
1629 struct filedesc *fdp = p->p_fd;
1630 struct fileproc *fp;
1631
1632 if (!locked)
1633 proc_fdlock(p);
1634 if (fd < 0 || fd >= fdp->fd_nfiles ||
1635 (fp = fdp->fd_ofiles[fd]) == NULL ||
1636 (fdp->fd_ofileflags[fd] & UF_RESERVED)) {
1637 if (!locked)
1638 proc_fdunlock(p);
1639 return (EBADF);
1640 }
1641 fp->f_iocount++;
1642
1643 if (resultfp)
1644 *resultfp = fp;
1645 if (!locked)
1646 proc_fdunlock(p);
1647
1648 return (0);
1649}
1650
1651int
1652fp_drop_written(proc_t p, int fd, struct fileproc *fp)
1653{
1654 int error;
1655
1656 proc_fdlock(p);
1657
1658 fp->f_flags |= FP_WRITTEN;
1659
1660 error = fp_drop(p, fd, fp, 1);
1661
1662 proc_fdunlock(p);
1663
1664 return (error);
1665}
1666
1667
1668int
1669fp_drop_event(proc_t p, int fd, struct fileproc *fp)
1670{
1671 int error;
1672
1673 proc_fdlock(p);
1674
1675 fp->f_flags |= FP_WAITEVENT;
1676
1677 error = fp_drop(p, fd, fp, 1);
1678
1679 proc_fdunlock(p);
1680
1681 return (error);
1682}
1683
1c79356b 1684int
91447636 1685fp_drop(p, fd, fp, locked)
1c79356b 1686 struct proc *p;
91447636
A
1687 int fd;
1688 struct fileproc *fp;
1689 int locked;
1c79356b 1690{
91447636 1691 struct filedesc *fdp = p->p_fd;
1c79356b 1692
91447636
A
1693 if (!locked)
1694 proc_fdlock(p);
1695 if ((fp == FILEPROC_NULL) && (fd < 0 || fd >= fdp->fd_nfiles ||
1696 (fp = fdp->fd_ofiles[fd]) == NULL ||
1697 ((fdp->fd_ofileflags[fd] & UF_RESERVED) &&
1698 !(fdp->fd_ofileflags[fd] & UF_CLOSING)))) {
1699 if (!locked)
1700 proc_fdunlock(p);
1701 return (EBADF);
1702 }
1703 fp->f_iocount--;
1704
1705 if (p->p_fpdrainwait && fp->f_iocount == 0) {
1706 p->p_fpdrainwait = 0;
1707 wakeup(&p->p_fpdrainwait);
1708 }
1709 if (!locked)
1710 proc_fdunlock(p);
1711
1c79356b
A
1712 return (0);
1713}
1714
91447636
A
1715int
1716file_vnode(int fd, struct vnode **vpp)
1c79356b 1717{
91447636
A
1718 struct proc * p = current_proc();
1719 struct fileproc *fp;
1720 int error;
1721
1722 proc_fdlock(p);
1723 if ( (error = fp_lookup(p, fd, &fp, 1)) ) {
1724 proc_fdunlock(p);
1725 return(error);
1726 }
1727 if (fp->f_type != DTYPE_VNODE) {
1728 fp_drop(p, fd, fp,1);
1729 proc_fdunlock(p);
1730 return(EINVAL);
1731 }
1732 *vpp = (struct vnode *)fp->f_data;
1733 proc_fdunlock(p);
1734
1735 return(0);
1c79356b
A
1736}
1737
91447636 1738
1c79356b 1739int
91447636 1740file_socket(int fd, struct socket **sp)
1c79356b 1741{
91447636
A
1742 struct proc * p = current_proc();
1743 struct fileproc *fp;
1744 int error;
1745
1746 proc_fdlock(p);
1747 if ( (error = fp_lookup(p, fd, &fp, 1)) ) {
1748 proc_fdunlock(p);
1749 return(error);
1750 }
1751 if (fp->f_type != DTYPE_SOCKET) {
1752 fp_drop(p, fd, fp,1);
1753 proc_fdunlock(p);
1754 return(ENOTSOCK);
1755 }
1756 *sp = (struct socket *)fp->f_data;
1757 proc_fdunlock(p);
1c79356b 1758
91447636
A
1759 return(0);
1760}
1761
1762int
1763file_flags(int fd, int * flags)
1764{
1765
1766 struct proc * p = current_proc();
1767 struct fileproc *fp;
1768 int error;
1769
1770 proc_fdlock(p);
1771 if ( (error = fp_lookup(p, fd, &fp, 1)) ) {
1772 proc_fdunlock(p);
1773 return(error);
1774 }
1775 *flags = (int)fp->f_flag;
1776 fp_drop(p, fd, fp,1);
1777 proc_fdunlock(p);
1778
1779 return(0);
1780}
1781
1782
1783int
1784file_drop(int fd)
1785{
1786 struct fileproc *fp;
1787 struct proc *p = current_proc();
1788
1789 proc_fdlock(p);
1790 if (fd < 0 || fd >= p->p_fd->fd_nfiles ||
1791 (fp = p->p_fd->fd_ofiles[fd]) == NULL ||
1792 ((p->p_fd->fd_ofileflags[fd] & UF_RESERVED) &&
1793 !(p->p_fd->fd_ofileflags[fd] & UF_CLOSING))) {
1794 proc_fdunlock(p);
1c79356b 1795 return (EBADF);
91447636
A
1796 }
1797 fp->f_iocount --;
1798
1799 if (p->p_fpdrainwait && fp->f_iocount == 0) {
1800 p->p_fpdrainwait = 0;
1801 wakeup(&p->p_fpdrainwait);
1802 }
1803 proc_fdunlock(p);
1804 return(0);
1805
1c79356b 1806
1c79356b
A
1807}
1808
91447636
A
1809int
1810falloc(p, resultfp, resultfd )
1811 struct proc *p;
1812 struct fileproc **resultfp;
1813 int *resultfd;
1814{
1815 int error;
1816
1817 proc_fdlock(p);
1818 error = falloc_locked(p, resultfp, resultfd, 1);
1819 proc_fdunlock(p);
1820
1821 return(error);
1822}
1c79356b
A
1823/*
1824 * Create a new open file structure and allocate
1825 * a file decriptor for the process that refers to it.
1826 */
1827int
91447636
A
1828falloc_locked(p, resultfp, resultfd, locked)
1829 struct proc *p;
1830 struct fileproc **resultfp;
1c79356b 1831 int *resultfd;
91447636 1832 int locked;
1c79356b 1833{
91447636
A
1834 struct fileproc *fp, *fq;
1835 struct fileglob *fg;
1836 int error, nfd;
1837
1838 if (!locked)
1839 proc_fdlock(p);
1840 if ( (error = fdalloc(p, 0, &nfd)) ) {
1841 if (!locked)
1842 proc_fdunlock(p);
1c79356b 1843 return (error);
91447636 1844 }
1c79356b 1845 if (nfiles >= maxfiles) {
91447636
A
1846 if (!locked)
1847 proc_fdunlock(p);
1c79356b
A
1848 tablefull("file");
1849 return (ENFILE);
1850 }
1851 /*
1852 * Allocate a new file descriptor.
1853 * If the process has file descriptor zero open, add to the list
1854 * of open files at that point, otherwise put it at the front of
1855 * the list of open files.
1856 */
91447636
A
1857 proc_fdunlock(p);
1858
1859 MALLOC_ZONE(fp, struct fileproc *, sizeof(struct fileproc), M_FILEPROC, M_WAITOK);
1860 MALLOC_ZONE(fg, struct fileglob *, sizeof(struct fileglob), M_FILEGLOB, M_WAITOK);
1861 bzero(fp, sizeof(struct fileproc));
1862 bzero(fg, sizeof(struct fileglob));
1863 lck_mtx_init(&fg->fg_lock, file_lck_grp, file_lck_attr);
1864
1865 fp->f_iocount = 1;
1866 fg->fg_count = 1;
1867 fp->f_fglob = fg;
1868
1869 proc_fdlock(p);
1870
1871 fp->f_cred = kauth_cred_proc_ref(p);
1872
1873 lck_mtx_lock(file_flist_lock);
1874
1c79356b 1875 nfiles++;
91447636
A
1876
1877 if ( (fq = p->p_fd->fd_ofiles[0]) ) {
1878 LIST_INSERT_AFTER(fq->f_fglob, fg, f_list);
1879 } else {
1880 LIST_INSERT_HEAD(&filehead, fg, f_list);
1881 }
1882 lck_mtx_unlock(file_flist_lock);
1883
1884 p->p_fd->fd_ofiles[nfd] = fp;
1885
1886 if (!locked)
1887 proc_fdunlock(p);
1888
1c79356b
A
1889 if (resultfp)
1890 *resultfp = fp;
1891 if (resultfd)
91447636
A
1892 *resultfd = nfd;
1893
1c79356b
A
1894 return (0);
1895}
1896
1897/*
1898 * Free a file structure.
1899 */
1900void
91447636
A
1901fg_free(fg)
1902 struct fileglob *fg;
1c79356b 1903{
91447636
A
1904 kauth_cred_t cred;
1905
1906 lck_mtx_lock(file_flist_lock);
1907 LIST_REMOVE(fg, f_list);
1908 nfiles--;
1909 lck_mtx_unlock(file_flist_lock);
1c79356b 1910
91447636 1911 cred = fg->fg_cred;
1c79356b 1912 if (cred != NOCRED) {
91447636
A
1913 fg->fg_cred = NOCRED;
1914 kauth_cred_rele(cred);
1c79356b 1915 }
91447636 1916 lck_mtx_destroy(&fg->fg_lock, file_lck_grp);
fa4905b1 1917
91447636 1918 FREE_ZONE(fg, sizeof *fg, M_FILEGLOB);
1c79356b
A
1919}
1920
1921void
1922fdexec(p)
1923 struct proc *p;
1924{
91447636
A
1925 struct filedesc *fdp = p->p_fd;
1926 int i = fdp->fd_lastfile;
1927 struct fileproc **fpp = &fdp->fd_ofiles[i];
1928 char *flags = &fdp->fd_ofileflags[i];
1929 int funnel_state;
1930
1931 funnel_state = thread_funnel_set(kernel_flock, FALSE);
1932 proc_fdlock(p);
1c79356b
A
1933
1934 while (i >= 0) {
1935 if ((*flags & (UF_RESERVED|UF_EXCLOSE)) == UF_EXCLOSE) {
91447636 1936 struct fileproc *fp = *fpp;
1c79356b 1937
55e303ae
A
1938 if (i < fdp->fd_knlistsize)
1939 knote_fdclose(p, i);
1940
1c79356b
A
1941 *fpp = NULL; *flags = 0;
1942 if (i == fdp->fd_lastfile && i > 0)
1943 fdp->fd_lastfile--;
91447636
A
1944 closef_locked(fp, fp->f_fglob, p);
1945 FREE_ZONE(fp, sizeof *fp, M_FILEPROC);
1c79356b 1946 }
1c79356b
A
1947
1948 i--; fpp--; flags--;
1949 }
91447636
A
1950 proc_fdunlock(p);
1951 thread_funnel_set(kernel_flock, funnel_state);
1c79356b
A
1952}
1953
1954/*
1955 * Copy a filedesc structure.
1956 */
1957struct filedesc *
1958fdcopy(p)
1959 struct proc *p;
1960{
91447636
A
1961 struct filedesc *newfdp, *fdp = p->p_fd;
1962 int i;
1963 struct fileproc *ofp, *fp;
1964 vnode_t v_dir;
1c79356b
A
1965
1966 MALLOC_ZONE(newfdp, struct filedesc *,
1967 sizeof *newfdp, M_FILEDESC, M_WAITOK);
91447636
A
1968 if (newfdp == NULL)
1969 return(NULL);
1970
1971 proc_fdlock(p);
1972
1973 /*
1974 * the FD_CHROOT flag will be inherited via this copy
1975 */
1c79356b 1976 (void) memcpy(newfdp, fdp, sizeof *newfdp);
91447636
A
1977
1978 /*
1979 * for both fd_cdir and fd_rdir make sure we get
1980 * a valid reference... if we can't, than set
1981 * set the pointer(s) to NULL in the child... this
1982 * will keep us from using a non-referenced vp
1983 * and allows us to do the vnode_rele only on
1984 * a properly referenced vp
1985 */
1986 if ( (v_dir = newfdp->fd_cdir) ) {
1987 if (vnode_getwithref(v_dir) == 0) {
1988 if ( (vnode_ref(v_dir)) )
1989 newfdp->fd_cdir = NULL;
1990 vnode_put(v_dir);
1991 } else
1992 newfdp->fd_cdir = NULL;
1993 }
1994 if (newfdp->fd_cdir == NULL && fdp->fd_cdir) {
1995 /*
1996 * we couldn't get a new reference on
1997 * the current working directory being
1998 * inherited... we might as well drop
1999 * our reference from the parent also
2000 * since the vnode has gone DEAD making
2001 * it useless... by dropping it we'll
2002 * be that much closer to recyling it
2003 */
2004 vnode_rele(fdp->fd_cdir);
2005 fdp->fd_cdir = NULL;
2006 }
2007
2008 if ( (v_dir = newfdp->fd_rdir) ) {
2009 if (vnode_getwithref(v_dir) == 0) {
2010 if ( (vnode_ref(v_dir)) )
2011 newfdp->fd_rdir = NULL;
2012 vnode_put(v_dir);
2013 } else
2014 newfdp->fd_rdir = NULL;
2015 }
2016 if (newfdp->fd_rdir == NULL && fdp->fd_rdir) {
2017 /*
2018 * we couldn't get a new reference on
2019 * the root directory being
2020 * inherited... we might as well drop
2021 * our reference from the parent also
2022 * since the vnode has gone DEAD making
2023 * it useless... by dropping it we'll
2024 * be that much closer to recyling it
2025 */
2026 vnode_rele(fdp->fd_rdir);
2027 fdp->fd_rdir = NULL;
2028 }
1c79356b
A
2029 newfdp->fd_refcnt = 1;
2030
2031 /*
2032 * If the number of open files fits in the internal arrays
2033 * of the open file structure, use them, otherwise allocate
2034 * additional memory for the number of descriptors currently
2035 * in use.
2036 */
2037 if (newfdp->fd_lastfile < NDFILE)
2038 i = NDFILE;
2039 else {
2040 /*
2041 * Compute the smallest multiple of NDEXTENT needed
2042 * for the file descriptors currently in use,
2043 * allowing the table to shrink.
2044 */
2045 i = newfdp->fd_nfiles;
2046 while (i > 2 * NDEXTENT && i > newfdp->fd_lastfile * 2)
2047 i /= 2;
2048 }
91447636
A
2049 proc_fdunlock(p);
2050
2051 MALLOC_ZONE(newfdp->fd_ofiles, struct fileproc **,
1c79356b 2052 i * OFILESIZE, M_OFILETABL, M_WAITOK);
91447636
A
2053 if (newfdp->fd_ofiles == NULL) {
2054 if (newfdp->fd_cdir)
2055 vnode_rele(newfdp->fd_cdir);
2056 if (newfdp->fd_rdir)
2057 vnode_rele(newfdp->fd_rdir);
2058
2059 FREE_ZONE(newfdp, sizeof *newfdp, M_FILEDESC);
2060 return(NULL);
2061 }
2062 proc_fdlock(p);
2063
1c79356b
A
2064 newfdp->fd_ofileflags = (char *) &newfdp->fd_ofiles[i];
2065 newfdp->fd_nfiles = i;
91447636 2066
1c79356b 2067 if (fdp->fd_nfiles > 0) {
91447636
A
2068 struct fileproc **fpp;
2069 char *flags;
1c79356b
A
2070
2071 (void) memcpy(newfdp->fd_ofiles, fdp->fd_ofiles,
2072 i * sizeof *fdp->fd_ofiles);
2073 (void) memcpy(newfdp->fd_ofileflags, fdp->fd_ofileflags,
2074 i * sizeof *fdp->fd_ofileflags);
2075
55e303ae
A
2076 /*
2077 * kq descriptors cannot be copied.
2078 */
2079 if (newfdp->fd_knlistsize != -1) {
2080 fpp = &newfdp->fd_ofiles[newfdp->fd_lastfile];
2081 for (i = newfdp->fd_lastfile; i >= 0; i--, fpp--) {
2082 if (*fpp != NULL && (*fpp)->f_type == DTYPE_KQUEUE) {
2083 *fpp = NULL;
2084 if (i < newfdp->fd_freefile)
2085 newfdp->fd_freefile = i;
2086 }
2087 if (*fpp == NULL && i == newfdp->fd_lastfile && i > 0)
2088 newfdp->fd_lastfile--;
2089 }
2090 newfdp->fd_knlist = NULL;
2091 newfdp->fd_knlistsize = -1;
2092 newfdp->fd_knhash = NULL;
2093 newfdp->fd_knhashmask = 0;
2094 }
1c79356b
A
2095 fpp = newfdp->fd_ofiles;
2096 flags = newfdp->fd_ofileflags;
91447636 2097
1c79356b 2098 for (i = newfdp->fd_lastfile; i-- >= 0; fpp++, flags++)
91447636
A
2099 if ((ofp = *fpp) != NULL && !(*flags & UF_RESERVED)) {
2100 MALLOC_ZONE(fp, struct fileproc *, sizeof(struct fileproc), M_FILEPROC, M_WAITOK);
2101 bzero(fp, sizeof(struct fileproc));
2102 fp->f_flags = ofp->f_flags;
2103 //fp->f_iocount = ofp->f_iocount;
2104 fp->f_iocount = 0;
2105 fp->f_fglob = ofp->f_fglob;
2106 (void)fg_ref(fp);
2107 *fpp = fp;
1c79356b
A
2108 } else {
2109 *fpp = NULL;
2110 *flags = 0;
2111 }
fa4905b1 2112 } else
1c79356b
A
2113 (void) memset(newfdp->fd_ofiles, 0, i * OFILESIZE);
2114
91447636 2115 proc_fdunlock(p);
1c79356b
A
2116 return (newfdp);
2117}
2118
2119/*
2120 * Release a filedesc structure.
2121 */
2122void
2123fdfree(p)
2124 struct proc *p;
2125{
fa4905b1 2126 struct filedesc *fdp;
91447636 2127 struct fileproc *fp;
fa4905b1 2128 int i;
91447636
A
2129
2130 proc_fdlock(p);
1c79356b 2131
55e303ae 2132 /* Certain daemons might not have file descriptors */
91447636 2133 fdp = p->p_fd;
55e303ae 2134
91447636
A
2135 if ((fdp == NULL) || (--fdp->fd_refcnt > 0)) {
2136 proc_fdunlock(p);
1c79356b 2137 return;
91447636
A
2138 }
2139 if (fdp->fd_refcnt == 0xffff)
2140 panic("fdfree: bad fd_refcnt");
55e303ae
A
2141
2142 /* Last reference: the structure can't change out from under us */
91447636
A
2143
2144 if (fdp->fd_nfiles > 0 && fdp->fd_ofiles) {
2145 for (i = fdp->fd_lastfile; i >= 0; i--) {
55e303ae 2146 if ((fp = fdp->fd_ofiles[i]) != NULL) {
91447636
A
2147
2148 if (fdp->fd_ofileflags[i] & UF_RESERVED)
2149 panic("fdfree: found fp with UF_RESERVED\n");
2150
2151 /* closef drops the iocount ... */
2152 if ((fp->f_flags & FP_INCHRREAD) != 0)
2153 fp->f_iocount++;
2154 fdp->fd_ofiles[i] = NULL;
2155 fdp->fd_ofileflags[i] |= UF_RESERVED;
2156
55e303ae
A
2157 if (i < fdp->fd_knlistsize)
2158 knote_fdclose(p, i);
91447636
A
2159 if (fp->f_flags & FP_WAITEVENT)
2160 (void)waitevent_close(p, fp);
2161 (void) closef_locked(fp, fp->f_fglob, p);
2162 FREE_ZONE(fp, sizeof *fp, M_FILEPROC);
55e303ae 2163 }
91447636
A
2164 }
2165 FREE_ZONE(fdp->fd_ofiles, fdp->fd_nfiles * OFILESIZE, M_OFILETABL);
2166 fdp->fd_ofiles = NULL;
2167 fdp->fd_nfiles = 0;
2168 }
55e303ae 2169
91447636
A
2170 proc_fdunlock(p);
2171
2172 if (fdp->fd_cdir)
2173 vnode_rele(fdp->fd_cdir);
2174 if (fdp->fd_rdir)
2175 vnode_rele(fdp->fd_rdir);
55e303ae 2176
91447636
A
2177 proc_fdlock(p);
2178 p->p_fd = NULL;
2179 proc_fdunlock(p);
55e303ae
A
2180
2181 if (fdp->fd_knlist)
2182 FREE(fdp->fd_knlist, M_KQUEUE);
2183 if (fdp->fd_knhash)
2184 FREE(fdp->fd_knhash, M_KQUEUE);
2185
1c79356b
A
2186 FREE_ZONE(fdp, sizeof *fdp, M_FILEDESC);
2187}
2188
9bccf70c 2189static int
91447636
A
2190closef_finish(fp, fg, p)
2191 struct fileproc *fp;
2192 struct fileglob *fg;
2193 struct proc *p;
9bccf70c
A
2194{
2195 struct vnode *vp;
2196 struct flock lf;
2197 int error;
91447636 2198 struct vfs_context context;
9bccf70c 2199
91447636 2200 if ((fg->fg_flag & FHASLOCK) && fg->fg_type == DTYPE_VNODE) {
9bccf70c
A
2201 lf.l_whence = SEEK_SET;
2202 lf.l_start = 0;
2203 lf.l_len = 0;
2204 lf.l_type = F_UNLCK;
91447636
A
2205 vp = (struct vnode *)fg->fg_data;
2206 context.vc_proc = p;
2207 context.vc_ucred = fg->fg_cred;
2208
2209 (void) VNOP_ADVLOCK(vp, (caddr_t)fg, F_UNLCK, &lf, F_FLOCK, &context);
9bccf70c 2210 }
91447636
A
2211 if (fg->fg_ops)
2212 error = fo_close(fg, p);
9bccf70c
A
2213 else
2214 error = 0;
91447636
A
2215
2216 if (((fp != (struct fileproc *)0) && ((fp->f_flags & FP_INCHRREAD) != 0))) {
2217 proc_fdlock(p);
2218 if ( ((fp->f_flags & FP_INCHRREAD) != 0) ) {
2219 fileproc_drain(p, fp);
2220 }
2221 proc_fdunlock(p);
2222 }
2223 fg_free(fg);
2224
9bccf70c
A
2225 return (error);
2226}
2227
91447636
A
2228int
2229closef(fg, p)
2230 struct fileglob *fg;
2231 struct proc *p;
2232{
2233 int error;
2234
2235 proc_fdlock(p);
2236 error = closef_locked((struct fileproc *)0, fg, p);
2237 proc_fdunlock(p);
2238
2239 return(error);
2240}
1c79356b
A
2241/*
2242 * Internal form of close.
2243 * Decrement reference count on file structure.
2244 * Note: p may be NULL when closing a file
2245 * that was being passed in a message.
2246 */
2247int
91447636
A
2248closef_locked(fp, fg, p)
2249 struct fileproc *fp;
2250 struct fileglob *fg;
2251 struct proc *p;
1c79356b
A
2252{
2253 struct vnode *vp;
2254 struct flock lf;
91447636 2255 struct vfs_context context;
1c79356b
A
2256 int error;
2257
91447636 2258 if (fg == NULL) {
1c79356b 2259 return (0);
91447636 2260 }
1c79356b
A
2261 /*
2262 * POSIX record locking dictates that any close releases ALL
2263 * locks owned by this process. This is handled by setting
2264 * a flag in the unlock to free ONLY locks obeying POSIX
2265 * semantics, and not to free BSD-style file locks.
2266 * If the descriptor was in a message, POSIX-style locks
2267 * aren't passed with the descriptor.
2268 */
b36670ce 2269 if (p && (p->p_ladvflag & P_LADVLOCK) && fg->fg_type == DTYPE_VNODE) {
91447636
A
2270 proc_fdunlock(p);
2271
1c79356b
A
2272 lf.l_whence = SEEK_SET;
2273 lf.l_start = 0;
2274 lf.l_len = 0;
2275 lf.l_type = F_UNLCK;
91447636
A
2276 vp = (struct vnode *)fg->fg_data;
2277
2278 if ( (error = vnode_getwithref(vp)) == 0 ) {
2279 context.vc_proc = p;
2280 context.vc_ucred = fg->fg_cred;
2281 (void) VNOP_ADVLOCK(vp, (caddr_t)p, F_UNLCK, &lf, F_POSIX, &context);
2282
2283 (void)vnode_put(vp);
2284 }
2285 proc_fdlock(p);
1c79356b 2286 }
91447636
A
2287 lck_mtx_lock(&fg->fg_lock);
2288 fg->fg_count--;
2289
2290 if (fg->fg_count > 0) {
2291 lck_mtx_unlock(&fg->fg_lock);
1c79356b 2292 return (0);
91447636
A
2293 }
2294 if (fg->fg_count != 0)
2295 panic("fg: being freed with bad fg_count (%d)", fg, fg->fg_count);
2296
2297 if (fp && (fp->f_flags & FP_WRITTEN))
2298 fg->fg_flag |= FWASWRITTEN;
2299
2300 fg->fg_lflags |= FG_TERM;
2301 lck_mtx_unlock(&fg->fg_lock);
2302
2303 proc_fdunlock(p);
2304 error = closef_finish(fp, fg, p);
2305 proc_fdlock(p);
2306
2307 return(error);
2308}
2309
2310
2311extern int selwait;
2312void
2313fileproc_drain(struct proc *p, struct fileproc * fp)
2314{
2315 fp->f_iocount-- ; /* (the one the close holds) */
2316
2317 while (fp->f_iocount) {
2318 if (((fp->f_flags & FP_INSELECT)== FP_INSELECT)) {
2319 wait_queue_wakeup_all((wait_queue_t)fp->f_waddr, &selwait, THREAD_INTERRUPTED);
2320 } else {
2321 if (fp->f_fglob->fg_ops->fo_drain) {
2322 (*fp->f_fglob->fg_ops->fo_drain)(fp, p);
2323 }
2324 }
2325 p->p_fpdrainwait = 1;
2326
2327 msleep(&p->p_fpdrainwait, &p->p_fdmlock, PRIBIO, "fpdrain",0);
2328
2329 //panic("successful wait after drain\n");
2330 }
2331}
2332
2333int
2334fp_free(struct proc * p, int fd, struct fileproc * fp)
2335{
2336 proc_fdlock(p);
2337 fdrelse(p, fd);
2338 proc_fdunlock(p);
2339
2340 fg_free(fp->f_fglob);
2341 FREE_ZONE(fp, sizeof *fp, M_FILEPROC);
1c79356b
A
2342}
2343
91447636 2344
1c79356b
A
2345/*
2346 * Apply an advisory lock on a file descriptor.
2347 *
2348 * Just attempt to get a record lock of the requested type on
2349 * the entire file (l_whence = SEEK_SET, l_start = 0, l_len = 0).
2350 */
1c79356b 2351int
91447636 2352flock(struct proc *p, register struct flock_args *uap, __unused register_t *retval)
1c79356b
A
2353{
2354 int fd = uap->fd;
2355 int how = uap->how;
91447636 2356 struct fileproc *fp;
1c79356b
A
2357 struct vnode *vp;
2358 struct flock lf;
91447636
A
2359 struct vfs_context context;
2360 int error=0;
1c79356b 2361
55e303ae 2362 AUDIT_ARG(fd, uap->fd);
91447636
A
2363 if ( (error = fp_getfvp(p, fd, &fp, &vp)) ) {
2364 return(error);
2365 }
2366 if ( (error = vnode_getwithref(vp)) ) {
2367 goto out1;
2368 }
55e303ae 2369 AUDIT_ARG(vnpath, vp, ARG_VNODE1);
91447636
A
2370
2371 context.vc_proc = p;
2372 context.vc_ucred = fp->f_cred;
2373
1c79356b
A
2374 lf.l_whence = SEEK_SET;
2375 lf.l_start = 0;
2376 lf.l_len = 0;
2377 if (how & LOCK_UN) {
2378 lf.l_type = F_UNLCK;
2379 fp->f_flag &= ~FHASLOCK;
91447636
A
2380 error = VNOP_ADVLOCK(vp, (caddr_t)fp->f_fglob, F_UNLCK, &lf, F_FLOCK, &context);
2381 goto out;
1c79356b
A
2382 }
2383 if (how & LOCK_EX)
2384 lf.l_type = F_WRLCK;
2385 else if (how & LOCK_SH)
2386 lf.l_type = F_RDLCK;
91447636
A
2387 else {
2388 error = EBADF;
2389 goto out;
2390 }
1c79356b 2391 fp->f_flag |= FHASLOCK;
91447636
A
2392 if (how & LOCK_NB) {
2393 error = VNOP_ADVLOCK(vp, (caddr_t)fp->f_fglob, F_SETLK, &lf, F_FLOCK, &context);
2394 goto out;
2395 }
2396 error = VNOP_ADVLOCK(vp, (caddr_t)fp->f_fglob, F_SETLK, &lf, F_FLOCK|F_WAIT, &context);
2397out:
2398 (void)vnode_put(vp);
2399out1:
2400 fp_drop(p, fd, fp, 0);
2401 return(error);
2402
1c79356b
A
2403}
2404
2405/*
2406 * File Descriptor pseudo-device driver (/dev/fd/).
2407 *
2408 * Opening minor device N dup()s the file (if any) connected to file
2409 * descriptor N belonging to the calling process. Note that this driver
2410 * consists of only the ``open()'' routine, because all subsequent
2411 * references to this file will be direct to the other driver.
2412 */
1c79356b 2413int
91447636 2414fdopen(dev_t dev, __unused int mode, __unused int type, struct proc *p)
1c79356b
A
2415{
2416
2417 /*
2418 * XXX Kludge: set curproc->p_dupfd to contain the value of the
2419 * the file descriptor being sought for duplication. The error
2420 * return ensures that the vnode for this device will be released
2421 * by vn_open. Open will detect this special error and take the
91447636 2422 * actions in dupfdopen below. Other callers of vn_open or vnop_open
1c79356b
A
2423 * will simply report the error.
2424 */
2425 p->p_dupfd = minor(dev);
2426 return (ENODEV);
2427}
2428
2429/*
2430 * Duplicate the specified descriptor to a free descriptor.
2431 */
2432int
2433dupfdopen(fdp, indx, dfd, mode, error)
2434 register struct filedesc *fdp;
2435 register int indx, dfd;
2436 int mode;
2437 int error;
2438{
91447636
A
2439 struct fileproc *wfp;
2440 struct fileproc *fp;
2441 struct proc * p = current_proc();
1c79356b
A
2442
2443 /*
2444 * If the to-be-dup'd fd number is greater than the allowed number
2445 * of file descriptors, or the fd to be dup'd has already been
2446 * closed, reject. Note, check for new == old is necessary as
2447 * falloc could allocate an already closed to-be-dup'd descriptor
2448 * as the new descriptor.
2449 */
91447636
A
2450 proc_fdlock(p);
2451
1c79356b 2452 fp = fdp->fd_ofiles[indx];
91447636 2453 if (dfd < 0 || dfd >= fdp->fd_nfiles ||
1c79356b 2454 (wfp = fdp->fd_ofiles[dfd]) == NULL || wfp == fp ||
91447636 2455 (fdp->fd_ofileflags[dfd] & UF_RESERVED)) {
1c79356b 2456
91447636
A
2457 proc_fdunlock(p);
2458 return (EBADF);
2459 }
1c79356b
A
2460 /*
2461 * There are two cases of interest here.
2462 *
2463 * For ENODEV simply dup (dfd) to file descriptor
2464 * (indx) and return.
2465 *
2466 * For ENXIO steal away the file structure from (dfd) and
2467 * store it in (indx). (dfd) is effectively closed by
2468 * this operation.
2469 *
2470 * Any other error code is just returned.
2471 */
2472 switch (error) {
2473 case ENODEV:
2474 /*
2475 * Check that the mode the file is being opened for is a
2476 * subset of the mode of the existing descriptor.
2477 */
91447636
A
2478 if (((mode & (FREAD|FWRITE)) | wfp->f_flag) != wfp->f_flag) {
2479 proc_fdunlock(p);
1c79356b 2480 return (EACCES);
91447636 2481 }
1c79356b 2482 if (indx > fdp->fd_lastfile)
91447636
A
2483 fdp->fd_lastfile = indx;
2484 (void)fg_ref(wfp);
2485
2486 if (fp->f_fglob)
2487 fg_free(fp->f_fglob);
2488 fp->f_fglob = wfp->f_fglob;
2489
1c79356b 2490 fdp->fd_ofileflags[indx] = fdp->fd_ofileflags[dfd];
91447636
A
2491
2492 proc_fdunlock(p);
1c79356b
A
2493 return (0);
2494
2495 case ENXIO:
2496 /*
2497 * Steal away the file pointer from dfd, and stuff it into indx.
2498 */
2499 if (indx > fdp->fd_lastfile)
91447636
A
2500 fdp->fd_lastfile = indx;
2501
2502 if (fp->f_fglob)
2503 fg_free(fp->f_fglob);
2504 fp->f_fglob = wfp->f_fglob;
2505
1c79356b
A
2506 fdp->fd_ofileflags[indx] = fdp->fd_ofileflags[dfd];
2507 _fdrelse(fdp, dfd);
91447636
A
2508
2509 proc_fdunlock(p);
2510
2511 FREE_ZONE(wfp, sizeof *fp, M_FILEPROC);
2512
1c79356b
A
2513 return (0);
2514
2515 default:
91447636 2516 proc_fdunlock(p);
1c79356b
A
2517 return (error);
2518 }
2519 /* NOTREACHED */
2520}
2521
91447636
A
2522void
2523fg_ref(struct fileproc * fp)
1c79356b 2524{
91447636
A
2525 struct fileglob *fg;
2526
2527 fg = fp->f_fglob;
2528
2529 lck_mtx_lock(&fg->fg_lock);
2530 fg->fg_count++;
2531 lck_mtx_unlock(&fg->fg_lock);
1c79356b
A
2532}
2533
91447636
A
2534void
2535fg_drop(struct fileproc * fp)
1c79356b 2536{
91447636
A
2537 struct fileglob *fg;
2538
2539 fg = fp->f_fglob;
2540 lck_mtx_lock(&fg->fg_lock);
2541 fg->fg_count--;
2542 lck_mtx_unlock(&fg->fg_lock);
1c79356b
A
2543}
2544
9bccf70c 2545
91447636
A
2546void
2547fg_insertuipc(struct fileglob * fg)
9bccf70c 2548{
91447636 2549int insertque = 0;
9bccf70c 2550
91447636
A
2551 lck_mtx_lock(&fg->fg_lock);
2552
2553 while (fg->fg_lflags & FG_RMMSGQ) {
2554 fg->fg_lflags |= FG_WRMMSGQ;
2555 msleep(&fg->fg_lflags, &fg->fg_lock, 0, "fg_insertuipc", 0);
2556 }
9bccf70c 2557
91447636
A
2558 fg->fg_count++;
2559 fg->fg_msgcount++;
2560 if (fg->fg_msgcount == 1) {
2561 fg->fg_lflags |= FG_INSMSGQ;
2562 insertque=1;
9bccf70c 2563 }
91447636
A
2564 lck_mtx_unlock(&fg->fg_lock);
2565
2566 if (insertque) {
2567 lck_mtx_lock(uipc_lock);
2568 LIST_INSERT_HEAD(&fmsghead, fg, f_msglist);
2569 lck_mtx_unlock(uipc_lock);
2570 lck_mtx_lock(&fg->fg_lock);
2571 fg->fg_lflags &= ~FG_INSMSGQ;
2572 if (fg->fg_lflags & FG_WINSMSGQ) {
2573 fg->fg_lflags &= ~FG_WINSMSGQ;
2574 wakeup(&fg->fg_lflags);
2575 }
2576 lck_mtx_unlock(&fg->fg_lock);
2577 }
2578
2579}
9bccf70c 2580
91447636
A
2581void
2582fg_removeuipc(struct fileglob * fg)
2583{
2584int removeque = 0;
2585
2586 lck_mtx_lock(&fg->fg_lock);
2587 while (fg->fg_lflags & FG_INSMSGQ) {
2588 fg->fg_lflags |= FG_WINSMSGQ;
2589 msleep(&fg->fg_lflags, &fg->fg_lock, 0, "fg_removeuipc", 0);
2590 }
2591 fg->fg_msgcount--;
2592 if (fg->fg_msgcount == 0) {
2593 fg->fg_lflags |= FG_RMMSGQ;
2594 removeque=1;
9bccf70c 2595 }
91447636
A
2596 lck_mtx_unlock(&fg->fg_lock);
2597
2598 if (removeque) {
2599 lck_mtx_lock(uipc_lock);
2600 LIST_REMOVE(fg, f_msglist);
2601 lck_mtx_unlock(uipc_lock);
2602 lck_mtx_lock(&fg->fg_lock);
2603 fg->fg_lflags &= ~FG_RMMSGQ;
2604 if (fg->fg_lflags & FG_WRMMSGQ) {
2605 fg->fg_lflags &= ~FG_WRMMSGQ;
2606 wakeup(&fg->fg_lflags);
2607 }
2608 lck_mtx_unlock(&fg->fg_lock);
2609 }
2610}
2611
2612
2613int
2614fo_read(struct fileproc *fp, struct uio *uio, kauth_cred_t cred, int flags, struct proc *p)
2615{
2616 return ((*fp->f_ops->fo_read)(fp, uio, cred, flags, p));
2617}
2618
2619int
2620fo_write(struct fileproc *fp, struct uio *uio, kauth_cred_t cred, int flags, struct proc *p)
2621{
2622 return((*fp->f_ops->fo_write)(fp, uio, cred, flags, p));
2623}
2624
2625int
2626fo_ioctl(struct fileproc *fp, u_long com, caddr_t data, struct proc *p)
2627{
2628int error;
2629
2630 proc_fdunlock(p);
2631 error = (*fp->f_ops->fo_ioctl)(fp, com, data, p);
2632 proc_fdlock(p);
2633 return(error);
2634}
2635
2636int
2637fo_select(struct fileproc *fp, int which, void *wql, struct proc *p)
2638{
2639 return((*fp->f_ops->fo_select)(fp, which, wql, p));
2640}
2641
2642int
2643fo_close(struct fileglob *fg, struct proc *p)
2644{
2645 return((*fg->fg_ops->fo_close)(fg, p));
9bccf70c
A
2646}
2647
1c79356b 2648int
91447636 2649fo_kqfilter(struct fileproc *fp, struct knote *kn, struct proc *p)
1c79356b 2650{
91447636 2651 return ((*fp->f_ops->fo_kqfilter)(fp, kn, p));
1c79356b
A
2652}
2653