]> git.saurik.com Git - apple/xnu.git/blame - bsd/kern/kern_descrip.c
xnu-792.6.76.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 *
37839358
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 *
37839358
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,
37839358
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
3a60a9f5
A
704 case F_GLOBAL_NOCACHE:
705 if (fp->f_type != DTYPE_VNODE) {
706 error = EBADF;
707 goto out;
708 }
709 vp = (struct vnode *)fp->f_data;
710 proc_fdunlock(p);
711
712 if ( (error = vnode_getwithref(vp)) == 0 ) {
713
714 *retval = vnode_isnocache(vp);
715
716 if (uap->arg)
717 vnode_setnocache(vp);
718 else
719 vnode_clearnocache(vp);
720
721 (void)vnode_put(vp);
722 }
723 goto outdrop;
724
91447636
A
725 case F_RDADVISE: {
726 struct radvisory ra_struct;
9bccf70c 727
91447636
A
728 if (fp->f_type != DTYPE_VNODE) {
729 error = EBADF;
730 goto out;
731 }
55e303ae 732 vp = (struct vnode *)fp->f_data;
91447636 733 proc_fdunlock(p);
55e303ae 734
91447636
A
735 if ( (error = copyin(argp, (caddr_t)&ra_struct, sizeof (ra_struct))) )
736 goto outdrop;
737 if ( (error = vnode_getwithref(vp)) == 0 ) {
738 error = VNOP_IOCTL(vp, F_RDADVISE, (caddr_t)&ra_struct, 0, &context);
739
740 (void)vnode_put(vp);
741 }
742 goto outdrop;
743 }
55e303ae 744
1c79356b 745 case F_READBOOTSTRAP:
91447636
A
746 case F_WRITEBOOTSTRAP: {
747 fbootstraptransfer_t fbt_struct;
748 user_fbootstraptransfer_t user_fbt_struct;
749 int sizeof_struct;
750 caddr_t boot_structp;
751
752 if (fp->f_type != DTYPE_VNODE) {
753 error = EBADF;
754 goto out;
755 }
ccc36f2f 756 vp = (struct vnode *)fp->f_data;
91447636 757 proc_fdunlock(p);
1c79356b 758
91447636
A
759 if (IS_64BIT_PROCESS(p)) {
760 sizeof_struct = sizeof(user_fbt_struct);
761 boot_structp = (caddr_t) &user_fbt_struct;
762 }
763 else {
764 sizeof_struct = sizeof(fbt_struct);
765 boot_structp = (caddr_t) &fbt_struct;
766 }
767 error = copyin(argp, boot_structp, sizeof_struct);
1c79356b 768 if (error)
91447636
A
769 goto outdrop;
770 if ( (error = vnode_getwithref(vp)) ) {
771 goto outdrop;
772 }
1c79356b 773 if (uap->cmd == F_WRITEBOOTSTRAP) {
91447636
A
774 /*
775 * Make sure that we are root. Updating the
776 * bootstrap on a disk could be a security hole
777 */
ccc36f2f 778 if (!is_suser()) {
91447636 779 (void)vnode_put(vp);
ccc36f2f 780 error = EACCES;
91447636 781 goto outdrop;
ccc36f2f 782 }
9bccf70c 783 }
91447636 784 if (strcmp(vnode_mount(vp)->mnt_vfsstat.f_fstypename, "hfs") != 0) {
9bccf70c 785 error = EINVAL;
91447636
A
786 } else {
787 /*
788 * call vnop_ioctl to handle the I/O
789 */
790 error = VNOP_IOCTL(vp, uap->cmd, boot_structp, 0, &context);
9bccf70c 791 }
91447636
A
792 (void)vnode_put(vp);
793 goto outdrop;
794 }
795 case F_LOG2PHYS: {
796 struct log2phys l2p_struct; /* structure for allocate command */
9bccf70c 797
91447636
A
798 if (fp->f_type != DTYPE_VNODE) {
799 error = EBADF;
800 goto out;
801 }
1c79356b 802 vp = (struct vnode *)fp->f_data;
91447636
A
803 proc_fdunlock(p);
804 if ( (error = vnode_getwithref(vp)) ) {
805 goto outdrop;
806 }
807 error = VNOP_OFFTOBLK(vp, fp->f_offset, &lbn);
808 if (error) {
809 (void)vnode_put(vp);
810 goto outdrop;
811 }
812 error = VNOP_BLKTOOFF(vp, lbn, &offset);
813 if (error) {
814 (void)vnode_put(vp);
815 goto outdrop;
816 }
817 devBlockSize = vfs_devblocksize(vnode_mount(vp));
818
819 error = VNOP_BLOCKMAP(vp, offset, devBlockSize, &bn, NULL, NULL, 0, &context);
820
821 (void)vnode_put(vp);
ccc36f2f 822
1c79356b
A
823 if (!error) {
824 l2p_struct.l2p_flags = 0; /* for now */
825 l2p_struct.l2p_contigbytes = 0; /* for now */
826 l2p_struct.l2p_devoffset = bn * devBlockSize;
827 l2p_struct.l2p_devoffset += fp->f_offset - offset;
91447636
A
828 error = copyout((caddr_t)&l2p_struct, argp, sizeof (l2p_struct));
829 }
830 goto outdrop;
1c79356b 831 }
55e303ae 832 case F_GETPATH: {
91447636
A
833 char *pathbufp;
834 int pathlen;
55e303ae 835
91447636
A
836 if (fp->f_type != DTYPE_VNODE) {
837 error = EBADF;
838 goto out;
839 }
55e303ae 840 vp = (struct vnode *)fp->f_data;
91447636 841 proc_fdunlock(p);
55e303ae 842
91447636
A
843 pathlen = MAXPATHLEN;
844 MALLOC(pathbufp, char *, pathlen, M_TEMP, M_WAITOK);
845 if (pathbufp == NULL) {
846 error = ENOMEM;
847 goto outdrop;
848 }
849 if ( (error = vnode_getwithref(vp)) == 0 ) {
850 error = vn_getpath(vp, pathbufp, &pathlen);
851 (void)vnode_put(vp);
4a249263 852
91447636
A
853 if (error == 0)
854 error = copyout((caddr_t)pathbufp, argp, pathlen);
855 }
856 FREE(pathbufp, M_TEMP);
857 goto outdrop;
55e303ae
A
858 }
859
91447636
A
860 case F_PATHPKG_CHECK: {
861 char *pathbufp;
862 size_t pathlen;
863
864 if (fp->f_type != DTYPE_VNODE) {
865 error = EBADF;
866 goto out;
867 }
55e303ae 868 vp = (struct vnode *)fp->f_data;
91447636 869 proc_fdunlock(p);
55e303ae 870
91447636
A
871 pathlen = MAXPATHLEN;
872 pathbufp = kalloc(MAXPATHLEN);
873
874 if ( (error = copyinstr(argp, pathbufp, MAXPATHLEN, &pathlen)) == 0 ) {
875 if ( (error = vnode_getwithref(vp)) == 0 ) {
876 error = vn_path_package_check(vp, pathbufp, pathlen, retval);
877
878 (void)vnode_put(vp);
879 }
880 }
881 kfree(pathbufp, MAXPATHLEN);
882 goto outdrop;
883 }
884
885 case F_CHKCLEAN: // used by regression tests to see if all dirty pages got cleaned by fsync()
886 case F_FULLFSYNC: // fsync + flush the journal + DKIOCSYNCHRONIZECACHE
887 case F_FREEZE_FS: // freeze all other fs operations for the fs of this fd
888 case F_THAW_FS: { // thaw all frozen fs operations for the fs of this fd
889 if (fp->f_type != DTYPE_VNODE) {
890 error = EBADF;
891 goto out;
892 }
893 vp = (struct vnode *)fp->f_data;
894 proc_fdunlock(p);
ccc36f2f 895
91447636
A
896 if ( (error = vnode_getwithref(vp)) == 0 ) {
897 error = VNOP_IOCTL(vp, uap->cmd, (caddr_t)NULL, 0, &context);
898
899 (void)vnode_put(vp);
900 }
ccc36f2f 901 break;
55e303ae
A
902 }
903
1c79356b 904 default:
91447636
A
905 if (uap->cmd < FCNTL_FS_SPECIFIC_BASE) {
906 error = EINVAL;
907 goto out;
908 }
909
910 // if it's a fs-specific fcntl() then just pass it through
911
912 if (fp->f_type != DTYPE_VNODE) {
913 error = EBADF;
914 goto out;
915 }
916 vp = (struct vnode *)fp->f_data;
917 proc_fdunlock(p);
918
919 if ( (error = vnode_getwithref(vp)) == 0 ) {
920 error = VNOP_IOCTL(vp, uap->cmd, CAST_DOWN(caddr_t, argp), 0, &context);
921
922 (void)vnode_put(vp);
923 }
924 break;
925
1c79356b 926 }
ccc36f2f 927
91447636
A
928outdrop:
929 AUDIT_ARG(vnpath_withref, vp, ARG_VNODE1);
930 fp_drop(p, fd, fp, 0);
931 return(error);
932out:
933 fp_drop(p, fd, fp, 1);
934 proc_fdunlock(p);
935 return(error);
1c79356b
A
936}
937
938/*
939 * Common code for dup, dup2, and fcntl(F_DUPFD).
940 */
941int
91447636 942finishdup(struct proc * p, struct filedesc *fdp, int old, int new, register_t *retval)
1c79356b 943{
91447636
A
944 struct fileproc *nfp;
945 struct fileproc *ofp;
1c79356b 946
91447636 947 if ((ofp = fdp->fd_ofiles[old]) == NULL ||
1c79356b
A
948 (fdp->fd_ofileflags[old] & UF_RESERVED)) {
949 _fdrelse(fdp, new);
950 return (EBADF);
951 }
91447636
A
952 fg_ref(ofp);
953 proc_fdunlock(p);
954
955 MALLOC_ZONE(nfp, struct fileproc *, sizeof(struct fileproc), M_FILEPROC, M_WAITOK);
956 bzero(nfp, sizeof(struct fileproc));
957
958 proc_fdlock(p);
959 nfp->f_flags = ofp->f_flags;
960 nfp->f_fglob = ofp->f_fglob;
961 nfp->f_iocount = 0;
962
963 fdp->fd_ofiles[new] = nfp;
1c79356b 964 fdp->fd_ofileflags[new] = fdp->fd_ofileflags[old] &~ UF_EXCLOSE;
1c79356b
A
965 if (new > fdp->fd_lastfile)
966 fdp->fd_lastfile = new;
967 *retval = new;
968 return (0);
969}
970
91447636 971
1c79356b 972int
91447636 973close(struct proc *p, struct close_args *uap, __unused register_t *retval)
1c79356b 974{
91447636 975 struct fileproc *fp;
1c79356b 976 int fd = uap->fd;
91447636 977 int error =0;
1c79356b 978
e5568f75 979 AUDIT_SYSCLOSE(p, fd);
91447636
A
980
981 proc_fdlock(p);
982
983 if ( (error = fp_lookup(p,fd,&fp, 1)) ) {
984 proc_fdunlock(p);
985 return(error);
986 }
987
988 error = close_internal(p, fd, fp, CLOSEINT_LOCKED | CLOSEINT_WAITONCLOSE);
989
990 proc_fdunlock(p);
991
992 return(error);
993}
994
995
996/*
997 * Close a file descriptor.
998 */
999int
1000close_internal(struct proc *p, int fd, struct fileproc *fp, int flags)
1001{
1002 struct filedesc *fdp = p->p_fd;
1003 int error =0;
1004 int locked = flags & CLOSEINT_LOCKED;
1005 int waitonclose = flags & CLOSEINT_WAITONCLOSE;
1006 int norelse = flags & CLOSEINT_NOFDRELSE;
1007 int nofdref = flags & CLOSEINT_NOFDNOREF;
1008 int slpstate = PRIBIO;
1009
1010 if (!locked)
1011 proc_fdlock(p);
55e303ae
A
1012
1013 /* Keep people from using the filedesc while we are closing it */
1014 fdp->fd_ofileflags[fd] |= UF_RESERVED;
55e303ae 1015
91447636
A
1016 fdp->fd_ofileflags[fd] |= UF_CLOSING;
1017
1018
1019 if ((waitonclose && ((fp->f_flags & FP_CLOSING) == FP_CLOSING))) {
1020 if (nofdref == 0)
1021 fp_drop(p, fd, fp, 1);
1022 fp->f_flags |= FP_WAITCLOSE;
1023 if (!locked)
1024 slpstate |= PDROP;
1025 msleep(&fp->f_flags, &p->p_fdmlock, slpstate, "close wait",0) ;
1026 return(EBADF);
1027 }
1028
1029 fp->f_flags |= FP_CLOSING;
1030 if (nofdref)
1031 fp->f_iocount++;
1032
1033 if ( (fp->f_flags & FP_AIOISSUED) || kauth_authorize_fileop_has_listeners() ) {
1034
1035 proc_fdunlock(p);
1036
1037 if ( (fp->f_type == DTYPE_VNODE) && kauth_authorize_fileop_has_listeners() ) {
1038 /*
1039 * call out to allow 3rd party notification of close.
1040 * Ignore result of kauth_authorize_fileop call.
1041 */
1042 if (vnode_getwithref((vnode_t)fp->f_data) == 0) {
1043 u_int fileop_flags = 0;
1044 if ((fp->f_flags & FP_WRITTEN) != 0)
1045 fileop_flags |= KAUTH_FILEOP_CLOSE_MODIFIED;
1046 kauth_authorize_fileop(fp->f_fglob->fg_cred, KAUTH_FILEOP_CLOSE,
1047 (uintptr_t)fp->f_data, (uintptr_t)fileop_flags);
1048 vnode_put((vnode_t)fp->f_data);
1049 }
1050 }
1051 if (fp->f_flags & FP_AIOISSUED)
1052 /*
1053 * cancel all async IO requests that can be cancelled.
1054 */
1055 _aio_close( p, fd );
1056
1057 proc_fdlock(p);
1058 }
1059
1060 if (fd < fdp->fd_knlistsize)
55e303ae
A
1061 knote_fdclose(p, fd);
1062
91447636
A
1063 if (fp->f_flags & FP_WAITEVENT)
1064 (void)waitevent_close(p, fp);
1065
1066 if ((fp->f_flags & FP_INCHRREAD) == 0)
1067 fileproc_drain(p, fp);
1068 if (norelse == 0)
1069 _fdrelse(fdp, fd);
1070 error = closef_locked(fp, fp->f_fglob, p);
1071 if ((fp->f_flags & FP_WAITCLOSE) == FP_WAITCLOSE)
1072 wakeup(&fp->f_flags);
1073 fp->f_flags &= ~(FP_WAITCLOSE | FP_CLOSING);
1074
1075 if (!locked)
1076 proc_fdunlock(p);
1077
1078 FREE_ZONE(fp, sizeof *fp, M_FILEPROC);
1079 return(error);
1c79356b
A
1080}
1081
1082/*
1083 * Return status information about a file descriptor.
91447636
A
1084 *
1085 * XXX switch on node type is bogus; need a stat in struct fileops instead.
1c79356b 1086 */
91447636
A
1087static int
1088fstat1(struct proc *p, int fd, user_addr_t ub, user_addr_t xsecurity, user_addr_t xsecurity_size)
1c79356b 1089{
91447636
A
1090 struct fileproc *fp;
1091 struct stat sb;
1092 struct user_stat user_sb;
1093 int error, my_size;
1094 int funnel_state;
1095 short type;
1096 caddr_t data;
1097 kauth_filesec_t fsec;
1098 ssize_t xsecurity_bufsize;
1099 int entrycount;
1100 struct vfs_context context;
1c79356b 1101
91447636
A
1102
1103 AUDIT_ARG(fd, fd);
1104
1105 if ((error = fp_lookup(p, fd, &fp, 0)) != 0)
1106 return(error);
1107 type = fp->f_type;
1108 data = fp->f_data;
1109 fsec = KAUTH_FILESEC_NONE;
1110
1111 switch (type) {
1c79356b
A
1112
1113 case DTYPE_VNODE:
91447636
A
1114 context.vc_proc = current_proc();
1115 context.vc_ucred = kauth_cred_get();
1116 if ((error = vnode_getwithref((vnode_t)data)) == 0) {
1117 /*
1118 * If the caller has the file open, and is not requesting extended security,
1119 * we are going to let them get the basic stat information.
1120 */
1121 if (xsecurity == USER_ADDR_NULL) {
1122 error = vn_stat_noauth((vnode_t)data, &sb, NULL, &context);
1123 } else {
1124 error = vn_stat((vnode_t)data, &sb, &fsec, &context);
1125 }
1126
1127 AUDIT_ARG(vnpath, (struct vnode *)data, ARG_VNODE1);
1128 (void)vnode_put((vnode_t)data);
55e303ae 1129 }
1c79356b
A
1130 break;
1131
1132 case DTYPE_SOCKET:
91447636
A
1133 error = soo_stat((struct socket *)data, &sb);
1134 break;
1135
1136 case DTYPE_PIPE:
1137 error = pipe_stat((void *)data, &sb);
1c79356b
A
1138 break;
1139
1140 case DTYPE_PSXSHM:
91447636 1141 error = pshm_stat((void *)data, &sb);
1c79356b 1142 break;
55e303ae
A
1143
1144 case DTYPE_KQUEUE:
91447636
A
1145 funnel_state = thread_funnel_set(kernel_flock, TRUE);
1146 error = kqueue_stat(fp, &sb, p);
1147 thread_funnel_set(kernel_flock, funnel_state);
1148 break;
55e303ae 1149
1c79356b 1150 default:
91447636
A
1151 error = EBADF;
1152 goto out;
1153 }
1154 /* Zap spare fields */
1155 sb.st_lspare = 0;
1156 sb.st_qspare[0] = 0LL;
1157 sb.st_qspare[1] = 0LL;
1158 if (error == 0) {
1159 caddr_t sbp;
1160 if (IS_64BIT_PROCESS(current_proc())) {
1161 munge_stat(&sb, &user_sb);
1162 my_size = sizeof(user_sb);
1163 sbp = (caddr_t)&user_sb;
1164 }
1165 else {
1166 my_size = sizeof(sb);
1167 sbp = (caddr_t)&sb;
1168 }
1169 error = copyout(sbp, ub, my_size);
1c79356b 1170 }
1c79356b 1171
91447636
A
1172 /* caller wants extended security information? */
1173 if (xsecurity != USER_ADDR_NULL) {
1c79356b 1174
91447636
A
1175 /* did we get any? */
1176 if (fsec == KAUTH_FILESEC_NONE) {
1177 if (susize(xsecurity_size, 0) != 0) {
1178 error = EFAULT;
1179 goto out;
1180 }
1181 } else {
1182 /* find the user buffer size */
1183 xsecurity_bufsize = fusize(xsecurity_size);
1c79356b 1184
91447636
A
1185 /* copy out the actual data size */
1186 if (susize(xsecurity_size, KAUTH_FILESEC_COPYSIZE(fsec)) != 0) {
1187 error = EFAULT;
1188 goto out;
1189 }
1c79356b 1190
91447636
A
1191 /* if the caller supplied enough room, copy out to it */
1192 if (xsecurity_bufsize >= KAUTH_FILESEC_COPYSIZE(fsec))
1193 error = copyout(fsec, xsecurity, KAUTH_FILESEC_COPYSIZE(fsec));
1194 }
1c79356b 1195 }
91447636
A
1196out:
1197 fp_drop(p, fd, fp, 0);
1198 if (fsec != NULL)
1199 kauth_filesec_free(fsec);
1c79356b
A
1200 return (error);
1201}
91447636
A
1202
1203int
1204fstat_extended(struct proc *p, struct fstat_extended_args *uap, __unused register_t *retval)
1205{
1206 return(fstat1(p, uap->fd, uap->ub, uap->xsecurity, uap->xsecurity_size));
1207}
1208
1209int
1210fstat(struct proc *p, register struct fstat_args *uap, __unused register_t *retval)
1211{
1212 return(fstat1(p, uap->fd, uap->ub, 0, 0));
1213}
1c79356b
A
1214
1215/*
1216 * Return pathconf information about a file descriptor.
1217 */
91447636 1218int
1c79356b
A
1219fpathconf(p, uap, retval)
1220 struct proc *p;
1221 register struct fpathconf_args *uap;
1222 register_t *retval;
1223{
1224 int fd = uap->fd;
91447636 1225 struct fileproc *fp;
1c79356b 1226 struct vnode *vp;
91447636
A
1227 struct vfs_context context;
1228 int error = 0;
1229 short type;
1230 caddr_t data;
1231
1c79356b 1232
55e303ae 1233 AUDIT_ARG(fd, uap->fd);
91447636
A
1234 if ( (error = fp_lookup(p, fd, &fp, 0)) )
1235 return(error);
1236 type = fp->f_type;
1237 data = fp->f_data;
1238
1239 switch (type) {
1c79356b
A
1240
1241 case DTYPE_SOCKET:
91447636
A
1242 if (uap->name != _PC_PIPE_BUF) {
1243 error = EINVAL;
1244 goto out;
1245 }
1c79356b 1246 *retval = PIPE_BUF;
91447636
A
1247 error = 0;
1248 goto out;
1249
1250 case DTYPE_PIPE:
1251 *retval = PIPE_BUF;
1252 error = 0;
1253 goto out;
1c79356b
A
1254
1255 case DTYPE_VNODE:
91447636
A
1256 vp = (struct vnode *)data;
1257
1258 if ( (error = vnode_getwithref(vp)) == 0) {
1259 AUDIT_ARG(vnpath, vp, ARG_VNODE1);
1260
1261 context.vc_proc = p;
1262 context.vc_ucred = kauth_cred_get();
1263
1264 error = vn_pathconf(vp, uap->name, retval, &context);
1265
1266 (void)vnode_put(vp);
1267 }
1268 goto out;
55e303ae 1269
91447636
A
1270 case DTYPE_PSXSHM:
1271 case DTYPE_KQUEUE:
1272 error = EINVAL;
1273 goto out;
1c79356b
A
1274
1275 default:
91447636 1276 panic("fpathconf (unrecognized - %d)", type);
1c79356b
A
1277 }
1278 /*NOTREACHED*/
91447636
A
1279out:
1280 fp_drop(p, fd, fp, 0);
1281 return(error);
1c79356b
A
1282}
1283
1284/*
1285 * Allocate a file descriptor for the process.
1286 */
1287int fdexpand;
1288
1289int
1290fdalloc(p, want, result)
1291 struct proc *p;
1292 int want;
1293 int *result;
1294{
1295 register struct filedesc *fdp = p->p_fd;
1296 register int i;
91447636
A
1297 int lim, last, numfiles, oldnfiles;
1298 struct fileproc **newofiles, **ofiles;
1c79356b
A
1299 char *newofileflags, *ofileflags;
1300
1301 /*
1302 * Search for a free descriptor starting at the higher
1303 * of want or fd_freefile. If that fails, consider
1304 * expanding the ofile array.
1305 */
1306 lim = min((int)p->p_rlimit[RLIMIT_NOFILE].rlim_cur, maxfiles);
1307 for (;;) {
1308 last = min(fdp->fd_nfiles, lim);
1309 if ((i = want) < fdp->fd_freefile)
1310 i = fdp->fd_freefile;
1311 ofiles = &fdp->fd_ofiles[i];
1312 ofileflags = &fdp->fd_ofileflags[i];
1313 for (; i < last; i++) {
1314 if (*ofiles == NULL && !(*ofileflags & UF_RESERVED)) {
1315 *ofileflags = UF_RESERVED;
1316 if (i > fdp->fd_lastfile)
1317 fdp->fd_lastfile = i;
1318 if (want <= fdp->fd_freefile)
1319 fdp->fd_freefile = i;
1320 *result = i;
1321 return (0);
1322 }
1323 ofiles++; ofileflags++;
1324 }
1325
1326 /*
1327 * No space in current array. Expand?
1328 */
1329 if (fdp->fd_nfiles >= lim)
1330 return (EMFILE);
1331 if (fdp->fd_nfiles < NDEXTENT)
91447636 1332 numfiles = NDEXTENT;
1c79356b 1333 else
91447636 1334 numfiles = 2 * fdp->fd_nfiles;
1c79356b 1335 /* Enforce lim */
91447636
A
1336 if (numfiles > lim)
1337 numfiles = lim;
1338 proc_fdunlock(p);
1339 MALLOC_ZONE(newofiles, struct fileproc **,
1340 numfiles * OFILESIZE, M_OFILETABL, M_WAITOK);
1341 proc_fdlock(p);
1342 if (newofiles == NULL) {
1343 return (ENOMEM);
1344 }
1345 if (fdp->fd_nfiles >= numfiles) {
1346 FREE_ZONE(newofiles, numfiles * OFILESIZE, M_OFILETABL);
1c79356b
A
1347 continue;
1348 }
91447636 1349 newofileflags = (char *) &newofiles[numfiles];
1c79356b
A
1350 /*
1351 * Copy the existing ofile and ofileflags arrays
1352 * and zero the new portion of each array.
1353 */
1354 oldnfiles = fdp->fd_nfiles;
1355 (void) memcpy(newofiles, fdp->fd_ofiles,
1356 oldnfiles * sizeof *fdp->fd_ofiles);
1357 (void) memset(&newofiles[oldnfiles], 0,
91447636 1358 (numfiles - oldnfiles) * sizeof *fdp->fd_ofiles);
1c79356b
A
1359
1360 (void) memcpy(newofileflags, fdp->fd_ofileflags,
1361 oldnfiles * sizeof *fdp->fd_ofileflags);
1362 (void) memset(&newofileflags[oldnfiles], 0,
91447636 1363 (numfiles - oldnfiles) *
1c79356b
A
1364 sizeof *fdp->fd_ofileflags);
1365 ofiles = fdp->fd_ofiles;
1366 fdp->fd_ofiles = newofiles;
1367 fdp->fd_ofileflags = newofileflags;
91447636 1368 fdp->fd_nfiles = numfiles;
1c79356b
A
1369 FREE_ZONE(ofiles, oldnfiles * OFILESIZE, M_OFILETABL);
1370 fdexpand++;
1371 }
1372}
1373
91447636
A
1374/*
1375 * Check to see whether n user file descriptors
1376 * are available to the process p.
1377 */
1378int
1379fdavail(p, n)
1380 struct proc *p;
1381 int n;
1382{
1383 struct filedesc *fdp = p->p_fd;
1384 struct fileproc **fpp;
1385 char *flags;
1386 int i, lim;
1387
1388 lim = min((int)p->p_rlimit[RLIMIT_NOFILE].rlim_cur, maxfiles);
1389 if ((i = lim - fdp->fd_nfiles) > 0 && (n -= i) <= 0)
1390 return (1);
1391 fpp = &fdp->fd_ofiles[fdp->fd_freefile];
1392 flags = &fdp->fd_ofileflags[fdp->fd_freefile];
1393 for (i = fdp->fd_nfiles - fdp->fd_freefile; --i >= 0; fpp++, flags++)
1394 if (*fpp == NULL && !(*flags & UF_RESERVED) && --n <= 0)
1395 return (1);
1396 return (0);
1397}
1398
1399void
1400fdrelse(p, fd)
1401 struct proc *p;
1402 int fd;
1403{
1404 _fdrelse(p->p_fd, fd);
1405}
1406
1407void
1408fddrop(p, fd)
1409 struct proc *p;
1410 int fd;
1411{
1412 struct filedesc *fdp = p->p_fd;
1413 struct fileproc *fp;
1414
1415 if (fd < fdp->fd_freefile)
1416 fdp->fd_freefile = fd;
1417#if DIAGNOSTIC
1418 if (fd > fdp->fd_lastfile)
1419 panic("fdrelse: fd_lastfile inconsistent");
1420#endif
1421 fp = fdp->fd_ofiles[fd];
1422 fdp->fd_ofiles[fd] = NULL;
1423 fdp->fd_ofileflags[fd] = 0;
1424
1425 while ((fd = fdp->fd_lastfile) > 0 &&
1426 fdp->fd_ofiles[fd] == NULL &&
1427 !(fdp->fd_ofileflags[fd] & UF_RESERVED))
1428 fdp->fd_lastfile--;
1429 FREE_ZONE(fp, sizeof *fp, M_FILEPROC);
1430}
1431
1432
1433int
1434fdgetf_noref(p, fd, resultfp)
1435 struct proc *p;
1436 int fd;
1437 struct fileproc **resultfp;
1438{
1439 struct filedesc *fdp = p->p_fd;
1440 struct fileproc *fp;
1441
1442 if (fd < 0 || fd >= fdp->fd_nfiles ||
1443 (fp = fdp->fd_ofiles[fd]) == NULL ||
1444 (fdp->fd_ofileflags[fd] & UF_RESERVED)) {
1445 return (EBADF);
1446 }
1447 if (resultfp)
1448 *resultfp = fp;
1449 return (0);
1450}
1451
1452
1453/* should be called only when proc_fdlock is held */
1454void
1455fp_setflags(proc_t p, struct fileproc * fp, int flags)
1456{
1457 proc_fdlock(p);
1458 fp->f_flags |= flags;
1459 proc_fdunlock(p);
1460}
1461
1462void
1463fp_clearflags(proc_t p, struct fileproc * fp, int flags)
1464{
1465
1466 proc_fdlock(p);
1467 if (fp)
1468 fp->f_flags &= ~flags;
1469 proc_fdunlock(p);
1470}
1471
1472int
1473fp_getfvp(p, fd, resultfp, resultvp)
1474 struct proc *p;
1475 int fd;
1476 struct fileproc **resultfp;
1477 struct vnode **resultvp;
1478{
1479 struct filedesc *fdp = p->p_fd;
1480 struct fileproc *fp;
1481
1482 proc_fdlock(p);
1483 if (fd < 0 || fd >= fdp->fd_nfiles ||
1484 (fp = fdp->fd_ofiles[fd]) == NULL ||
1485 (fdp->fd_ofileflags[fd] & UF_RESERVED)) {
1486 proc_fdunlock(p);
1487 return (EBADF);
1488 }
1489 if (fp->f_type != DTYPE_VNODE) {
1490 proc_fdunlock(p);
1491 return(ENOTSUP);
1492 }
1493 fp->f_iocount++;
1494
1495 if (resultfp)
1496 *resultfp = fp;
1497 if (resultvp)
1498 *resultvp = (struct vnode *)fp->f_data;
1499 proc_fdunlock(p);
1500
1501 return (0);
1502}
1503
1504
1505/*
1506 * Returns: EBADF The file descriptor is invalid
1507 * EOPNOTSUPP The file descriptor is not a socket
1508 * 0 Success
1509 *
1510 * Notes: EOPNOTSUPP should probably be ENOTSOCK; this function is only
1511 * ever called from accept1().
1512 */
1513int
1514fp_getfsock(p, fd, resultfp, results)
1515 struct proc *p;
1516 int fd;
1517 struct fileproc **resultfp;
1518 struct socket **results;
1519{
1520 struct filedesc *fdp = p->p_fd;
1521 struct fileproc *fp;
1522
1523 proc_fdlock(p);
1524 if (fd < 0 || fd >= fdp->fd_nfiles ||
1525 (fp = fdp->fd_ofiles[fd]) == NULL ||
1526 (fdp->fd_ofileflags[fd] & UF_RESERVED)) {
1527 proc_fdunlock(p);
1528 return (EBADF);
1529 }
1530 if (fp->f_type != DTYPE_SOCKET) {
1531 proc_fdunlock(p);
1532 return(EOPNOTSUPP);
1533 }
1534 fp->f_iocount++;
1535
1536 if (resultfp)
1537 *resultfp = fp;
1538 if (results)
1539 *results = (struct socket *)fp->f_data;
1540 proc_fdunlock(p);
1541
1542 return (0);
1543}
1544
1545
1546int
1547fp_getfkq(p, fd, resultfp, resultkq)
1548 struct proc *p;
1549 int fd;
1550 struct fileproc **resultfp;
1551 struct kqueue **resultkq;
1552{
1553 struct filedesc *fdp = p->p_fd;
1554 struct fileproc *fp;
1555
1556 proc_fdlock(p);
1557 if ( fd < 0 || fd >= fdp->fd_nfiles ||
1558 (fp = fdp->fd_ofiles[fd]) == NULL ||
1559 (fdp->fd_ofileflags[fd] & UF_RESERVED)) {
1560 proc_fdunlock(p);
1561 return (EBADF);
1562 }
1563 if (fp->f_type != DTYPE_KQUEUE) {
1564 proc_fdunlock(p);
1565 return(EBADF);
1566 }
1567 fp->f_iocount++;
1568
1569 if (resultfp)
1570 *resultfp = fp;
1571 if (resultkq)
1572 *resultkq = (struct kqueue *)fp->f_data;
1573 proc_fdunlock(p);
1574
1575 return (0);
1576}
1577
1578int
1579fp_getfpshm(p, fd, resultfp, resultpshm)
1580 struct proc *p;
1581 int fd;
1582 struct fileproc **resultfp;
1583 struct pshmnode **resultpshm;
1584{
1585 struct filedesc *fdp = p->p_fd;
1586 struct fileproc *fp;
1587
1588 proc_fdlock(p);
1589 if (fd < 0 || fd >= fdp->fd_nfiles ||
1590 (fp = fdp->fd_ofiles[fd]) == NULL ||
1591 (fdp->fd_ofileflags[fd] & UF_RESERVED)) {
1592 proc_fdunlock(p);
1593 return (EBADF);
1594 }
1595 if (fp->f_type != DTYPE_PSXSHM) {
1596
1597 proc_fdunlock(p);
1598 return(EBADF);
1599 }
1600 fp->f_iocount++;
1601
1602 if (resultfp)
1603 *resultfp = fp;
1604 if (resultpshm)
1605 *resultpshm = (struct pshmnode *)fp->f_data;
1606 proc_fdunlock(p);
1607
1608 return (0);
1609}
1610
1611
1612int
1613fp_getfpsem(p, fd, resultfp, resultpsem)
1614 struct proc *p;
1615 int fd;
1616 struct fileproc **resultfp;
1617 struct psemnode **resultpsem;
1618{
1619 struct filedesc *fdp = p->p_fd;
1620 struct fileproc *fp;
1621
1622 proc_fdlock(p);
1623 if (fd < 0 || fd >= fdp->fd_nfiles ||
1624 (fp = fdp->fd_ofiles[fd]) == NULL ||
1625 (fdp->fd_ofileflags[fd] & UF_RESERVED)) {
1626 proc_fdunlock(p);
1627 return (EBADF);
1628 }
1629 if (fp->f_type != DTYPE_PSXSEM) {
1630 proc_fdunlock(p);
1631 return(EBADF);
1632 }
1633 fp->f_iocount++;
1634
1635 if (resultfp)
1636 *resultfp = fp;
1637 if (resultpsem)
1638 *resultpsem = (struct psemnode *)fp->f_data;
1639 proc_fdunlock(p);
1640
1641 return (0);
1642}
1643int
1644fp_lookup(p, fd, resultfp, locked)
1645 struct proc *p;
1646 int fd;
1647 struct fileproc **resultfp;
1648 int locked;
1649{
1650 struct filedesc *fdp = p->p_fd;
1651 struct fileproc *fp;
1652
1653 if (!locked)
1654 proc_fdlock(p);
1655 if (fd < 0 || fd >= fdp->fd_nfiles ||
1656 (fp = fdp->fd_ofiles[fd]) == NULL ||
1657 (fdp->fd_ofileflags[fd] & UF_RESERVED)) {
1658 if (!locked)
1659 proc_fdunlock(p);
1660 return (EBADF);
1661 }
1662 fp->f_iocount++;
1663
1664 if (resultfp)
1665 *resultfp = fp;
1666 if (!locked)
1667 proc_fdunlock(p);
1668
1669 return (0);
1670}
1671
1672int
1673fp_drop_written(proc_t p, int fd, struct fileproc *fp)
1674{
1675 int error;
1676
1677 proc_fdlock(p);
1678
1679 fp->f_flags |= FP_WRITTEN;
1680
1681 error = fp_drop(p, fd, fp, 1);
1682
1683 proc_fdunlock(p);
1684
1685 return (error);
1686}
1687
1688
1689int
1690fp_drop_event(proc_t p, int fd, struct fileproc *fp)
1691{
1692 int error;
1693
1694 proc_fdlock(p);
1695
1696 fp->f_flags |= FP_WAITEVENT;
1697
1698 error = fp_drop(p, fd, fp, 1);
1699
1700 proc_fdunlock(p);
1701
1702 return (error);
1703}
1704
1c79356b 1705int
91447636 1706fp_drop(p, fd, fp, locked)
1c79356b 1707 struct proc *p;
91447636
A
1708 int fd;
1709 struct fileproc *fp;
1710 int locked;
1c79356b 1711{
91447636 1712 struct filedesc *fdp = p->p_fd;
1c79356b 1713
91447636
A
1714 if (!locked)
1715 proc_fdlock(p);
1716 if ((fp == FILEPROC_NULL) && (fd < 0 || fd >= fdp->fd_nfiles ||
1717 (fp = fdp->fd_ofiles[fd]) == NULL ||
1718 ((fdp->fd_ofileflags[fd] & UF_RESERVED) &&
1719 !(fdp->fd_ofileflags[fd] & UF_CLOSING)))) {
1720 if (!locked)
1721 proc_fdunlock(p);
1722 return (EBADF);
1723 }
1724 fp->f_iocount--;
1725
1726 if (p->p_fpdrainwait && fp->f_iocount == 0) {
1727 p->p_fpdrainwait = 0;
1728 wakeup(&p->p_fpdrainwait);
1729 }
1730 if (!locked)
1731 proc_fdunlock(p);
1732
1c79356b
A
1733 return (0);
1734}
1735
91447636
A
1736int
1737file_vnode(int fd, struct vnode **vpp)
1c79356b 1738{
91447636
A
1739 struct proc * p = current_proc();
1740 struct fileproc *fp;
1741 int error;
1742
1743 proc_fdlock(p);
1744 if ( (error = fp_lookup(p, fd, &fp, 1)) ) {
1745 proc_fdunlock(p);
1746 return(error);
1747 }
1748 if (fp->f_type != DTYPE_VNODE) {
1749 fp_drop(p, fd, fp,1);
1750 proc_fdunlock(p);
1751 return(EINVAL);
1752 }
1753 *vpp = (struct vnode *)fp->f_data;
1754 proc_fdunlock(p);
1755
1756 return(0);
1c79356b
A
1757}
1758
91447636 1759
1c79356b 1760int
91447636 1761file_socket(int fd, struct socket **sp)
1c79356b 1762{
91447636
A
1763 struct proc * p = current_proc();
1764 struct fileproc *fp;
1765 int error;
1766
1767 proc_fdlock(p);
1768 if ( (error = fp_lookup(p, fd, &fp, 1)) ) {
1769 proc_fdunlock(p);
1770 return(error);
1771 }
1772 if (fp->f_type != DTYPE_SOCKET) {
1773 fp_drop(p, fd, fp,1);
1774 proc_fdunlock(p);
1775 return(ENOTSOCK);
1776 }
1777 *sp = (struct socket *)fp->f_data;
1778 proc_fdunlock(p);
1c79356b 1779
91447636
A
1780 return(0);
1781}
1782
1783int
1784file_flags(int fd, int * flags)
1785{
1786
1787 struct proc * p = current_proc();
1788 struct fileproc *fp;
1789 int error;
1790
1791 proc_fdlock(p);
1792 if ( (error = fp_lookup(p, fd, &fp, 1)) ) {
1793 proc_fdunlock(p);
1794 return(error);
1795 }
1796 *flags = (int)fp->f_flag;
1797 fp_drop(p, fd, fp,1);
1798 proc_fdunlock(p);
1799
1800 return(0);
1801}
1802
1803
1804int
1805file_drop(int fd)
1806{
1807 struct fileproc *fp;
1808 struct proc *p = current_proc();
1809
1810 proc_fdlock(p);
1811 if (fd < 0 || fd >= p->p_fd->fd_nfiles ||
1812 (fp = p->p_fd->fd_ofiles[fd]) == NULL ||
1813 ((p->p_fd->fd_ofileflags[fd] & UF_RESERVED) &&
1814 !(p->p_fd->fd_ofileflags[fd] & UF_CLOSING))) {
1815 proc_fdunlock(p);
1c79356b 1816 return (EBADF);
91447636
A
1817 }
1818 fp->f_iocount --;
1819
1820 if (p->p_fpdrainwait && fp->f_iocount == 0) {
1821 p->p_fpdrainwait = 0;
1822 wakeup(&p->p_fpdrainwait);
1823 }
1824 proc_fdunlock(p);
1825 return(0);
1826
1c79356b 1827
1c79356b
A
1828}
1829
91447636
A
1830int
1831falloc(p, resultfp, resultfd )
1832 struct proc *p;
1833 struct fileproc **resultfp;
1834 int *resultfd;
1835{
1836 int error;
1837
1838 proc_fdlock(p);
1839 error = falloc_locked(p, resultfp, resultfd, 1);
1840 proc_fdunlock(p);
1841
1842 return(error);
1843}
1c79356b
A
1844/*
1845 * Create a new open file structure and allocate
1846 * a file decriptor for the process that refers to it.
1847 */
1848int
91447636
A
1849falloc_locked(p, resultfp, resultfd, locked)
1850 struct proc *p;
1851 struct fileproc **resultfp;
1c79356b 1852 int *resultfd;
91447636 1853 int locked;
1c79356b 1854{
91447636
A
1855 struct fileproc *fp, *fq;
1856 struct fileglob *fg;
1857 int error, nfd;
1858
1859 if (!locked)
1860 proc_fdlock(p);
1861 if ( (error = fdalloc(p, 0, &nfd)) ) {
1862 if (!locked)
1863 proc_fdunlock(p);
1c79356b 1864 return (error);
91447636 1865 }
1c79356b 1866 if (nfiles >= maxfiles) {
91447636
A
1867 if (!locked)
1868 proc_fdunlock(p);
1c79356b
A
1869 tablefull("file");
1870 return (ENFILE);
1871 }
1872 /*
1873 * Allocate a new file descriptor.
1874 * If the process has file descriptor zero open, add to the list
1875 * of open files at that point, otherwise put it at the front of
1876 * the list of open files.
1877 */
91447636
A
1878 proc_fdunlock(p);
1879
1880 MALLOC_ZONE(fp, struct fileproc *, sizeof(struct fileproc), M_FILEPROC, M_WAITOK);
1881 MALLOC_ZONE(fg, struct fileglob *, sizeof(struct fileglob), M_FILEGLOB, M_WAITOK);
1882 bzero(fp, sizeof(struct fileproc));
1883 bzero(fg, sizeof(struct fileglob));
1884 lck_mtx_init(&fg->fg_lock, file_lck_grp, file_lck_attr);
1885
1886 fp->f_iocount = 1;
1887 fg->fg_count = 1;
1888 fp->f_fglob = fg;
1889
1890 proc_fdlock(p);
1891
1892 fp->f_cred = kauth_cred_proc_ref(p);
1893
1894 lck_mtx_lock(file_flist_lock);
1895
1c79356b 1896 nfiles++;
91447636
A
1897
1898 if ( (fq = p->p_fd->fd_ofiles[0]) ) {
1899 LIST_INSERT_AFTER(fq->f_fglob, fg, f_list);
1900 } else {
1901 LIST_INSERT_HEAD(&filehead, fg, f_list);
1902 }
1903 lck_mtx_unlock(file_flist_lock);
1904
1905 p->p_fd->fd_ofiles[nfd] = fp;
1906
1907 if (!locked)
1908 proc_fdunlock(p);
1909
1c79356b
A
1910 if (resultfp)
1911 *resultfp = fp;
1912 if (resultfd)
91447636
A
1913 *resultfd = nfd;
1914
1c79356b
A
1915 return (0);
1916}
1917
1918/*
1919 * Free a file structure.
1920 */
1921void
91447636
A
1922fg_free(fg)
1923 struct fileglob *fg;
1c79356b 1924{
91447636
A
1925 kauth_cred_t cred;
1926
1927 lck_mtx_lock(file_flist_lock);
1928 LIST_REMOVE(fg, f_list);
1929 nfiles--;
1930 lck_mtx_unlock(file_flist_lock);
1c79356b 1931
91447636 1932 cred = fg->fg_cred;
1c79356b 1933 if (cred != NOCRED) {
91447636
A
1934 fg->fg_cred = NOCRED;
1935 kauth_cred_rele(cred);
1c79356b 1936 }
91447636 1937 lck_mtx_destroy(&fg->fg_lock, file_lck_grp);
fa4905b1 1938
91447636 1939 FREE_ZONE(fg, sizeof *fg, M_FILEGLOB);
1c79356b
A
1940}
1941
1942void
1943fdexec(p)
1944 struct proc *p;
1945{
91447636
A
1946 struct filedesc *fdp = p->p_fd;
1947 int i = fdp->fd_lastfile;
1948 struct fileproc **fpp = &fdp->fd_ofiles[i];
1949 char *flags = &fdp->fd_ofileflags[i];
1950 int funnel_state;
1951
1952 funnel_state = thread_funnel_set(kernel_flock, FALSE);
1953 proc_fdlock(p);
1c79356b
A
1954
1955 while (i >= 0) {
1956 if ((*flags & (UF_RESERVED|UF_EXCLOSE)) == UF_EXCLOSE) {
91447636 1957 struct fileproc *fp = *fpp;
1c79356b 1958
55e303ae
A
1959 if (i < fdp->fd_knlistsize)
1960 knote_fdclose(p, i);
1961
1c79356b
A
1962 *fpp = NULL; *flags = 0;
1963 if (i == fdp->fd_lastfile && i > 0)
1964 fdp->fd_lastfile--;
91447636
A
1965 closef_locked(fp, fp->f_fglob, p);
1966 FREE_ZONE(fp, sizeof *fp, M_FILEPROC);
1c79356b 1967 }
1c79356b
A
1968
1969 i--; fpp--; flags--;
1970 }
91447636
A
1971 proc_fdunlock(p);
1972 thread_funnel_set(kernel_flock, funnel_state);
1c79356b
A
1973}
1974
1975/*
1976 * Copy a filedesc structure.
1977 */
1978struct filedesc *
1979fdcopy(p)
1980 struct proc *p;
1981{
91447636
A
1982 struct filedesc *newfdp, *fdp = p->p_fd;
1983 int i;
1984 struct fileproc *ofp, *fp;
1985 vnode_t v_dir;
1c79356b
A
1986
1987 MALLOC_ZONE(newfdp, struct filedesc *,
1988 sizeof *newfdp, M_FILEDESC, M_WAITOK);
91447636
A
1989 if (newfdp == NULL)
1990 return(NULL);
1991
1992 proc_fdlock(p);
1993
1994 /*
1995 * the FD_CHROOT flag will be inherited via this copy
1996 */
1c79356b 1997 (void) memcpy(newfdp, fdp, sizeof *newfdp);
91447636
A
1998
1999 /*
2000 * for both fd_cdir and fd_rdir make sure we get
2001 * a valid reference... if we can't, than set
2002 * set the pointer(s) to NULL in the child... this
2003 * will keep us from using a non-referenced vp
2004 * and allows us to do the vnode_rele only on
2005 * a properly referenced vp
2006 */
2007 if ( (v_dir = newfdp->fd_cdir) ) {
2008 if (vnode_getwithref(v_dir) == 0) {
2009 if ( (vnode_ref(v_dir)) )
2010 newfdp->fd_cdir = NULL;
2011 vnode_put(v_dir);
2012 } else
2013 newfdp->fd_cdir = NULL;
2014 }
2015 if (newfdp->fd_cdir == NULL && fdp->fd_cdir) {
2016 /*
2017 * we couldn't get a new reference on
2018 * the current working directory being
2019 * inherited... we might as well drop
2020 * our reference from the parent also
2021 * since the vnode has gone DEAD making
2022 * it useless... by dropping it we'll
2023 * be that much closer to recyling it
2024 */
2025 vnode_rele(fdp->fd_cdir);
2026 fdp->fd_cdir = NULL;
2027 }
2028
2029 if ( (v_dir = newfdp->fd_rdir) ) {
2030 if (vnode_getwithref(v_dir) == 0) {
2031 if ( (vnode_ref(v_dir)) )
2032 newfdp->fd_rdir = NULL;
2033 vnode_put(v_dir);
2034 } else
2035 newfdp->fd_rdir = NULL;
2036 }
2037 if (newfdp->fd_rdir == NULL && fdp->fd_rdir) {
2038 /*
2039 * we couldn't get a new reference on
2040 * the root directory being
2041 * inherited... we might as well drop
2042 * our reference from the parent also
2043 * since the vnode has gone DEAD making
2044 * it useless... by dropping it we'll
2045 * be that much closer to recyling it
2046 */
2047 vnode_rele(fdp->fd_rdir);
2048 fdp->fd_rdir = NULL;
2049 }
1c79356b
A
2050 newfdp->fd_refcnt = 1;
2051
2052 /*
2053 * If the number of open files fits in the internal arrays
2054 * of the open file structure, use them, otherwise allocate
2055 * additional memory for the number of descriptors currently
2056 * in use.
2057 */
2058 if (newfdp->fd_lastfile < NDFILE)
2059 i = NDFILE;
2060 else {
2061 /*
2062 * Compute the smallest multiple of NDEXTENT needed
2063 * for the file descriptors currently in use,
2064 * allowing the table to shrink.
2065 */
2066 i = newfdp->fd_nfiles;
2067 while (i > 2 * NDEXTENT && i > newfdp->fd_lastfile * 2)
2068 i /= 2;
2069 }
91447636
A
2070 proc_fdunlock(p);
2071
2072 MALLOC_ZONE(newfdp->fd_ofiles, struct fileproc **,
1c79356b 2073 i * OFILESIZE, M_OFILETABL, M_WAITOK);
91447636
A
2074 if (newfdp->fd_ofiles == NULL) {
2075 if (newfdp->fd_cdir)
2076 vnode_rele(newfdp->fd_cdir);
2077 if (newfdp->fd_rdir)
2078 vnode_rele(newfdp->fd_rdir);
2079
2080 FREE_ZONE(newfdp, sizeof *newfdp, M_FILEDESC);
2081 return(NULL);
2082 }
2083 proc_fdlock(p);
2084
1c79356b
A
2085 newfdp->fd_ofileflags = (char *) &newfdp->fd_ofiles[i];
2086 newfdp->fd_nfiles = i;
91447636 2087
1c79356b 2088 if (fdp->fd_nfiles > 0) {
91447636
A
2089 struct fileproc **fpp;
2090 char *flags;
1c79356b
A
2091
2092 (void) memcpy(newfdp->fd_ofiles, fdp->fd_ofiles,
2093 i * sizeof *fdp->fd_ofiles);
2094 (void) memcpy(newfdp->fd_ofileflags, fdp->fd_ofileflags,
2095 i * sizeof *fdp->fd_ofileflags);
2096
55e303ae
A
2097 /*
2098 * kq descriptors cannot be copied.
2099 */
2100 if (newfdp->fd_knlistsize != -1) {
2101 fpp = &newfdp->fd_ofiles[newfdp->fd_lastfile];
2102 for (i = newfdp->fd_lastfile; i >= 0; i--, fpp--) {
2103 if (*fpp != NULL && (*fpp)->f_type == DTYPE_KQUEUE) {
2104 *fpp = NULL;
2105 if (i < newfdp->fd_freefile)
2106 newfdp->fd_freefile = i;
2107 }
2108 if (*fpp == NULL && i == newfdp->fd_lastfile && i > 0)
2109 newfdp->fd_lastfile--;
2110 }
2111 newfdp->fd_knlist = NULL;
2112 newfdp->fd_knlistsize = -1;
2113 newfdp->fd_knhash = NULL;
2114 newfdp->fd_knhashmask = 0;
2115 }
1c79356b
A
2116 fpp = newfdp->fd_ofiles;
2117 flags = newfdp->fd_ofileflags;
91447636 2118
1c79356b 2119 for (i = newfdp->fd_lastfile; i-- >= 0; fpp++, flags++)
91447636
A
2120 if ((ofp = *fpp) != NULL && !(*flags & UF_RESERVED)) {
2121 MALLOC_ZONE(fp, struct fileproc *, sizeof(struct fileproc), M_FILEPROC, M_WAITOK);
2122 bzero(fp, sizeof(struct fileproc));
2123 fp->f_flags = ofp->f_flags;
2124 //fp->f_iocount = ofp->f_iocount;
2125 fp->f_iocount = 0;
2126 fp->f_fglob = ofp->f_fglob;
2127 (void)fg_ref(fp);
2128 *fpp = fp;
1c79356b
A
2129 } else {
2130 *fpp = NULL;
2131 *flags = 0;
2132 }
fa4905b1 2133 } else
1c79356b
A
2134 (void) memset(newfdp->fd_ofiles, 0, i * OFILESIZE);
2135
91447636 2136 proc_fdunlock(p);
1c79356b
A
2137 return (newfdp);
2138}
2139
2140/*
2141 * Release a filedesc structure.
2142 */
2143void
2144fdfree(p)
2145 struct proc *p;
2146{
fa4905b1 2147 struct filedesc *fdp;
91447636 2148 struct fileproc *fp;
fa4905b1 2149 int i;
91447636
A
2150
2151 proc_fdlock(p);
1c79356b 2152
55e303ae 2153 /* Certain daemons might not have file descriptors */
91447636 2154 fdp = p->p_fd;
55e303ae 2155
91447636
A
2156 if ((fdp == NULL) || (--fdp->fd_refcnt > 0)) {
2157 proc_fdunlock(p);
1c79356b 2158 return;
91447636
A
2159 }
2160 if (fdp->fd_refcnt == 0xffff)
2161 panic("fdfree: bad fd_refcnt");
55e303ae
A
2162
2163 /* Last reference: the structure can't change out from under us */
91447636
A
2164
2165 if (fdp->fd_nfiles > 0 && fdp->fd_ofiles) {
2166 for (i = fdp->fd_lastfile; i >= 0; i--) {
55e303ae 2167 if ((fp = fdp->fd_ofiles[i]) != NULL) {
91447636
A
2168
2169 if (fdp->fd_ofileflags[i] & UF_RESERVED)
2170 panic("fdfree: found fp with UF_RESERVED\n");
2171
2172 /* closef drops the iocount ... */
2173 if ((fp->f_flags & FP_INCHRREAD) != 0)
2174 fp->f_iocount++;
2175 fdp->fd_ofiles[i] = NULL;
2176 fdp->fd_ofileflags[i] |= UF_RESERVED;
2177
55e303ae
A
2178 if (i < fdp->fd_knlistsize)
2179 knote_fdclose(p, i);
91447636
A
2180 if (fp->f_flags & FP_WAITEVENT)
2181 (void)waitevent_close(p, fp);
2182 (void) closef_locked(fp, fp->f_fglob, p);
2183 FREE_ZONE(fp, sizeof *fp, M_FILEPROC);
55e303ae 2184 }
91447636
A
2185 }
2186 FREE_ZONE(fdp->fd_ofiles, fdp->fd_nfiles * OFILESIZE, M_OFILETABL);
2187 fdp->fd_ofiles = NULL;
2188 fdp->fd_nfiles = 0;
2189 }
55e303ae 2190
91447636
A
2191 proc_fdunlock(p);
2192
2193 if (fdp->fd_cdir)
2194 vnode_rele(fdp->fd_cdir);
2195 if (fdp->fd_rdir)
2196 vnode_rele(fdp->fd_rdir);
55e303ae 2197
91447636
A
2198 proc_fdlock(p);
2199 p->p_fd = NULL;
2200 proc_fdunlock(p);
55e303ae
A
2201
2202 if (fdp->fd_knlist)
2203 FREE(fdp->fd_knlist, M_KQUEUE);
2204 if (fdp->fd_knhash)
2205 FREE(fdp->fd_knhash, M_KQUEUE);
2206
1c79356b
A
2207 FREE_ZONE(fdp, sizeof *fdp, M_FILEDESC);
2208}
2209
9bccf70c 2210static int
91447636
A
2211closef_finish(fp, fg, p)
2212 struct fileproc *fp;
2213 struct fileglob *fg;
2214 struct proc *p;
9bccf70c
A
2215{
2216 struct vnode *vp;
2217 struct flock lf;
2218 int error;
91447636 2219 struct vfs_context context;
9bccf70c 2220
91447636 2221 if ((fg->fg_flag & FHASLOCK) && fg->fg_type == DTYPE_VNODE) {
9bccf70c
A
2222 lf.l_whence = SEEK_SET;
2223 lf.l_start = 0;
2224 lf.l_len = 0;
2225 lf.l_type = F_UNLCK;
91447636
A
2226 vp = (struct vnode *)fg->fg_data;
2227 context.vc_proc = p;
2228 context.vc_ucred = fg->fg_cred;
2229
2230 (void) VNOP_ADVLOCK(vp, (caddr_t)fg, F_UNLCK, &lf, F_FLOCK, &context);
9bccf70c 2231 }
91447636
A
2232 if (fg->fg_ops)
2233 error = fo_close(fg, p);
9bccf70c
A
2234 else
2235 error = 0;
91447636
A
2236
2237 if (((fp != (struct fileproc *)0) && ((fp->f_flags & FP_INCHRREAD) != 0))) {
2238 proc_fdlock(p);
2239 if ( ((fp->f_flags & FP_INCHRREAD) != 0) ) {
2240 fileproc_drain(p, fp);
2241 }
2242 proc_fdunlock(p);
2243 }
2244 fg_free(fg);
2245
9bccf70c
A
2246 return (error);
2247}
2248
91447636
A
2249int
2250closef(fg, p)
2251 struct fileglob *fg;
2252 struct proc *p;
2253{
2254 int error;
2255
2256 proc_fdlock(p);
2257 error = closef_locked((struct fileproc *)0, fg, p);
2258 proc_fdunlock(p);
2259
2260 return(error);
2261}
1c79356b
A
2262/*
2263 * Internal form of close.
2264 * Decrement reference count on file structure.
2265 * Note: p may be NULL when closing a file
2266 * that was being passed in a message.
2267 */
2268int
91447636
A
2269closef_locked(fp, fg, p)
2270 struct fileproc *fp;
2271 struct fileglob *fg;
2272 struct proc *p;
1c79356b
A
2273{
2274 struct vnode *vp;
2275 struct flock lf;
91447636 2276 struct vfs_context context;
1c79356b
A
2277 int error;
2278
91447636 2279 if (fg == NULL) {
1c79356b 2280 return (0);
91447636 2281 }
1c79356b
A
2282 /*
2283 * POSIX record locking dictates that any close releases ALL
2284 * locks owned by this process. This is handled by setting
2285 * a flag in the unlock to free ONLY locks obeying POSIX
2286 * semantics, and not to free BSD-style file locks.
2287 * If the descriptor was in a message, POSIX-style locks
2288 * aren't passed with the descriptor.
2289 */
b36670ce 2290 if (p && (p->p_ladvflag & P_LADVLOCK) && fg->fg_type == DTYPE_VNODE) {
91447636
A
2291 proc_fdunlock(p);
2292
1c79356b
A
2293 lf.l_whence = SEEK_SET;
2294 lf.l_start = 0;
2295 lf.l_len = 0;
2296 lf.l_type = F_UNLCK;
91447636
A
2297 vp = (struct vnode *)fg->fg_data;
2298
2299 if ( (error = vnode_getwithref(vp)) == 0 ) {
2300 context.vc_proc = p;
2301 context.vc_ucred = fg->fg_cred;
2302 (void) VNOP_ADVLOCK(vp, (caddr_t)p, F_UNLCK, &lf, F_POSIX, &context);
2303
2304 (void)vnode_put(vp);
2305 }
2306 proc_fdlock(p);
1c79356b 2307 }
91447636
A
2308 lck_mtx_lock(&fg->fg_lock);
2309 fg->fg_count--;
2310
2311 if (fg->fg_count > 0) {
2312 lck_mtx_unlock(&fg->fg_lock);
1c79356b 2313 return (0);
91447636
A
2314 }
2315 if (fg->fg_count != 0)
2316 panic("fg: being freed with bad fg_count (%d)", fg, fg->fg_count);
2317
2318 if (fp && (fp->f_flags & FP_WRITTEN))
2319 fg->fg_flag |= FWASWRITTEN;
2320
2321 fg->fg_lflags |= FG_TERM;
2322 lck_mtx_unlock(&fg->fg_lock);
2323
2324 proc_fdunlock(p);
2325 error = closef_finish(fp, fg, p);
2326 proc_fdlock(p);
2327
2328 return(error);
2329}
2330
2331
2332extern int selwait;
2333void
2334fileproc_drain(struct proc *p, struct fileproc * fp)
2335{
2336 fp->f_iocount-- ; /* (the one the close holds) */
2337
2338 while (fp->f_iocount) {
2339 if (((fp->f_flags & FP_INSELECT)== FP_INSELECT)) {
2340 wait_queue_wakeup_all((wait_queue_t)fp->f_waddr, &selwait, THREAD_INTERRUPTED);
2341 } else {
2342 if (fp->f_fglob->fg_ops->fo_drain) {
2343 (*fp->f_fglob->fg_ops->fo_drain)(fp, p);
2344 }
2345 }
2346 p->p_fpdrainwait = 1;
2347
2348 msleep(&p->p_fpdrainwait, &p->p_fdmlock, PRIBIO, "fpdrain",0);
2349
2350 //panic("successful wait after drain\n");
2351 }
2352}
2353
2354int
2355fp_free(struct proc * p, int fd, struct fileproc * fp)
2356{
2357 proc_fdlock(p);
2358 fdrelse(p, fd);
2359 proc_fdunlock(p);
2360
2361 fg_free(fp->f_fglob);
2362 FREE_ZONE(fp, sizeof *fp, M_FILEPROC);
1c79356b
A
2363}
2364
91447636 2365
1c79356b
A
2366/*
2367 * Apply an advisory lock on a file descriptor.
2368 *
2369 * Just attempt to get a record lock of the requested type on
2370 * the entire file (l_whence = SEEK_SET, l_start = 0, l_len = 0).
2371 */
1c79356b 2372int
91447636 2373flock(struct proc *p, register struct flock_args *uap, __unused register_t *retval)
1c79356b
A
2374{
2375 int fd = uap->fd;
2376 int how = uap->how;
91447636 2377 struct fileproc *fp;
1c79356b
A
2378 struct vnode *vp;
2379 struct flock lf;
91447636
A
2380 struct vfs_context context;
2381 int error=0;
1c79356b 2382
55e303ae 2383 AUDIT_ARG(fd, uap->fd);
91447636
A
2384 if ( (error = fp_getfvp(p, fd, &fp, &vp)) ) {
2385 return(error);
2386 }
2387 if ( (error = vnode_getwithref(vp)) ) {
2388 goto out1;
2389 }
55e303ae 2390 AUDIT_ARG(vnpath, vp, ARG_VNODE1);
91447636
A
2391
2392 context.vc_proc = p;
2393 context.vc_ucred = fp->f_cred;
2394
1c79356b
A
2395 lf.l_whence = SEEK_SET;
2396 lf.l_start = 0;
2397 lf.l_len = 0;
2398 if (how & LOCK_UN) {
2399 lf.l_type = F_UNLCK;
2400 fp->f_flag &= ~FHASLOCK;
91447636
A
2401 error = VNOP_ADVLOCK(vp, (caddr_t)fp->f_fglob, F_UNLCK, &lf, F_FLOCK, &context);
2402 goto out;
1c79356b
A
2403 }
2404 if (how & LOCK_EX)
2405 lf.l_type = F_WRLCK;
2406 else if (how & LOCK_SH)
2407 lf.l_type = F_RDLCK;
91447636
A
2408 else {
2409 error = EBADF;
2410 goto out;
2411 }
1c79356b 2412 fp->f_flag |= FHASLOCK;
91447636
A
2413 if (how & LOCK_NB) {
2414 error = VNOP_ADVLOCK(vp, (caddr_t)fp->f_fglob, F_SETLK, &lf, F_FLOCK, &context);
2415 goto out;
2416 }
2417 error = VNOP_ADVLOCK(vp, (caddr_t)fp->f_fglob, F_SETLK, &lf, F_FLOCK|F_WAIT, &context);
2418out:
2419 (void)vnode_put(vp);
2420out1:
2421 fp_drop(p, fd, fp, 0);
2422 return(error);
2423
1c79356b
A
2424}
2425
2426/*
2427 * File Descriptor pseudo-device driver (/dev/fd/).
2428 *
2429 * Opening minor device N dup()s the file (if any) connected to file
2430 * descriptor N belonging to the calling process. Note that this driver
2431 * consists of only the ``open()'' routine, because all subsequent
2432 * references to this file will be direct to the other driver.
2433 */
1c79356b 2434int
91447636 2435fdopen(dev_t dev, __unused int mode, __unused int type, struct proc *p)
1c79356b
A
2436{
2437
2438 /*
2439 * XXX Kludge: set curproc->p_dupfd to contain the value of the
2440 * the file descriptor being sought for duplication. The error
2441 * return ensures that the vnode for this device will be released
2442 * by vn_open. Open will detect this special error and take the
91447636 2443 * actions in dupfdopen below. Other callers of vn_open or vnop_open
1c79356b
A
2444 * will simply report the error.
2445 */
2446 p->p_dupfd = minor(dev);
2447 return (ENODEV);
2448}
2449
2450/*
2451 * Duplicate the specified descriptor to a free descriptor.
2452 */
2453int
2454dupfdopen(fdp, indx, dfd, mode, error)
2455 register struct filedesc *fdp;
2456 register int indx, dfd;
2457 int mode;
2458 int error;
2459{
91447636
A
2460 struct fileproc *wfp;
2461 struct fileproc *fp;
2462 struct proc * p = current_proc();
1c79356b
A
2463
2464 /*
2465 * If the to-be-dup'd fd number is greater than the allowed number
2466 * of file descriptors, or the fd to be dup'd has already been
2467 * closed, reject. Note, check for new == old is necessary as
2468 * falloc could allocate an already closed to-be-dup'd descriptor
2469 * as the new descriptor.
2470 */
91447636
A
2471 proc_fdlock(p);
2472
1c79356b 2473 fp = fdp->fd_ofiles[indx];
91447636 2474 if (dfd < 0 || dfd >= fdp->fd_nfiles ||
1c79356b 2475 (wfp = fdp->fd_ofiles[dfd]) == NULL || wfp == fp ||
91447636 2476 (fdp->fd_ofileflags[dfd] & UF_RESERVED)) {
1c79356b 2477
91447636
A
2478 proc_fdunlock(p);
2479 return (EBADF);
2480 }
1c79356b
A
2481 /*
2482 * There are two cases of interest here.
2483 *
2484 * For ENODEV simply dup (dfd) to file descriptor
2485 * (indx) and return.
2486 *
2487 * For ENXIO steal away the file structure from (dfd) and
2488 * store it in (indx). (dfd) is effectively closed by
2489 * this operation.
2490 *
2491 * Any other error code is just returned.
2492 */
2493 switch (error) {
2494 case ENODEV:
2495 /*
2496 * Check that the mode the file is being opened for is a
2497 * subset of the mode of the existing descriptor.
2498 */
91447636
A
2499 if (((mode & (FREAD|FWRITE)) | wfp->f_flag) != wfp->f_flag) {
2500 proc_fdunlock(p);
1c79356b 2501 return (EACCES);
91447636 2502 }
1c79356b 2503 if (indx > fdp->fd_lastfile)
91447636
A
2504 fdp->fd_lastfile = indx;
2505 (void)fg_ref(wfp);
2506
2507 if (fp->f_fglob)
2508 fg_free(fp->f_fglob);
2509 fp->f_fglob = wfp->f_fglob;
2510
1c79356b 2511 fdp->fd_ofileflags[indx] = fdp->fd_ofileflags[dfd];
91447636
A
2512
2513 proc_fdunlock(p);
1c79356b
A
2514 return (0);
2515
2516 case ENXIO:
2517 /*
2518 * Steal away the file pointer from dfd, and stuff it into indx.
2519 */
2520 if (indx > fdp->fd_lastfile)
91447636
A
2521 fdp->fd_lastfile = indx;
2522
2523 if (fp->f_fglob)
2524 fg_free(fp->f_fglob);
2525 fp->f_fglob = wfp->f_fglob;
2526
1c79356b
A
2527 fdp->fd_ofileflags[indx] = fdp->fd_ofileflags[dfd];
2528 _fdrelse(fdp, dfd);
91447636
A
2529
2530 proc_fdunlock(p);
2531
2532 FREE_ZONE(wfp, sizeof *fp, M_FILEPROC);
2533
1c79356b
A
2534 return (0);
2535
2536 default:
91447636 2537 proc_fdunlock(p);
1c79356b
A
2538 return (error);
2539 }
2540 /* NOTREACHED */
2541}
2542
91447636
A
2543void
2544fg_ref(struct fileproc * fp)
1c79356b 2545{
91447636
A
2546 struct fileglob *fg;
2547
2548 fg = fp->f_fglob;
2549
2550 lck_mtx_lock(&fg->fg_lock);
2551 fg->fg_count++;
2552 lck_mtx_unlock(&fg->fg_lock);
1c79356b
A
2553}
2554
91447636
A
2555void
2556fg_drop(struct fileproc * fp)
1c79356b 2557{
91447636
A
2558 struct fileglob *fg;
2559
2560 fg = fp->f_fglob;
2561 lck_mtx_lock(&fg->fg_lock);
2562 fg->fg_count--;
2563 lck_mtx_unlock(&fg->fg_lock);
1c79356b
A
2564}
2565
9bccf70c 2566
91447636
A
2567void
2568fg_insertuipc(struct fileglob * fg)
9bccf70c 2569{
91447636 2570int insertque = 0;
9bccf70c 2571
91447636
A
2572 lck_mtx_lock(&fg->fg_lock);
2573
2574 while (fg->fg_lflags & FG_RMMSGQ) {
2575 fg->fg_lflags |= FG_WRMMSGQ;
2576 msleep(&fg->fg_lflags, &fg->fg_lock, 0, "fg_insertuipc", 0);
2577 }
9bccf70c 2578
91447636
A
2579 fg->fg_count++;
2580 fg->fg_msgcount++;
2581 if (fg->fg_msgcount == 1) {
2582 fg->fg_lflags |= FG_INSMSGQ;
2583 insertque=1;
9bccf70c 2584 }
91447636
A
2585 lck_mtx_unlock(&fg->fg_lock);
2586
2587 if (insertque) {
2588 lck_mtx_lock(uipc_lock);
2589 LIST_INSERT_HEAD(&fmsghead, fg, f_msglist);
2590 lck_mtx_unlock(uipc_lock);
2591 lck_mtx_lock(&fg->fg_lock);
2592 fg->fg_lflags &= ~FG_INSMSGQ;
2593 if (fg->fg_lflags & FG_WINSMSGQ) {
2594 fg->fg_lflags &= ~FG_WINSMSGQ;
2595 wakeup(&fg->fg_lflags);
2596 }
2597 lck_mtx_unlock(&fg->fg_lock);
2598 }
2599
2600}
9bccf70c 2601
91447636
A
2602void
2603fg_removeuipc(struct fileglob * fg)
2604{
2605int removeque = 0;
2606
2607 lck_mtx_lock(&fg->fg_lock);
2608 while (fg->fg_lflags & FG_INSMSGQ) {
2609 fg->fg_lflags |= FG_WINSMSGQ;
2610 msleep(&fg->fg_lflags, &fg->fg_lock, 0, "fg_removeuipc", 0);
2611 }
2612 fg->fg_msgcount--;
2613 if (fg->fg_msgcount == 0) {
2614 fg->fg_lflags |= FG_RMMSGQ;
2615 removeque=1;
9bccf70c 2616 }
91447636
A
2617 lck_mtx_unlock(&fg->fg_lock);
2618
2619 if (removeque) {
2620 lck_mtx_lock(uipc_lock);
2621 LIST_REMOVE(fg, f_msglist);
2622 lck_mtx_unlock(uipc_lock);
2623 lck_mtx_lock(&fg->fg_lock);
2624 fg->fg_lflags &= ~FG_RMMSGQ;
2625 if (fg->fg_lflags & FG_WRMMSGQ) {
2626 fg->fg_lflags &= ~FG_WRMMSGQ;
2627 wakeup(&fg->fg_lflags);
2628 }
2629 lck_mtx_unlock(&fg->fg_lock);
2630 }
2631}
2632
2633
2634int
2635fo_read(struct fileproc *fp, struct uio *uio, kauth_cred_t cred, int flags, struct proc *p)
2636{
2637 return ((*fp->f_ops->fo_read)(fp, uio, cred, flags, p));
2638}
2639
2640int
2641fo_write(struct fileproc *fp, struct uio *uio, kauth_cred_t cred, int flags, struct proc *p)
2642{
2643 return((*fp->f_ops->fo_write)(fp, uio, cred, flags, p));
2644}
2645
2646int
2647fo_ioctl(struct fileproc *fp, u_long com, caddr_t data, struct proc *p)
2648{
2649int error;
2650
2651 proc_fdunlock(p);
2652 error = (*fp->f_ops->fo_ioctl)(fp, com, data, p);
2653 proc_fdlock(p);
2654 return(error);
2655}
2656
2657int
2658fo_select(struct fileproc *fp, int which, void *wql, struct proc *p)
2659{
2660 return((*fp->f_ops->fo_select)(fp, which, wql, p));
2661}
2662
2663int
2664fo_close(struct fileglob *fg, struct proc *p)
2665{
2666 return((*fg->fg_ops->fo_close)(fg, p));
9bccf70c
A
2667}
2668
1c79356b 2669int
91447636 2670fo_kqfilter(struct fileproc *fp, struct knote *kn, struct proc *p)
1c79356b 2671{
91447636 2672 return ((*fp->f_ops->fo_kqfilter)(fp, kn, p));
1c79356b
A
2673}
2674