]> git.saurik.com Git - apple/xnu.git/blob - bsd/kern/kern_descrip.c
9cf181b0c12d7fc34ff5a863e661247ecada4f94
[apple/xnu.git] / bsd / kern / kern_descrip.c
1 /*
2 * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
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.
11 *
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
18 * under the License.
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
61 */
62
63 #include <sys/param.h>
64 #include <sys/systm.h>
65 #include <sys/filedesc.h>
66 #include <sys/kernel.h>
67 #include <sys/vnode.h>
68 #include <sys/proc.h>
69 #include <sys/file.h>
70 #include <sys/socket.h>
71 #include <sys/socketvar.h>
72 #include <sys/stat.h>
73 #include <sys/ioctl.h>
74 #include <sys/fcntl.h>
75 #include <sys/malloc.h>
76 #include <sys/syslog.h>
77 #include <sys/unistd.h>
78 #include <sys/resourcevar.h>
79 #include <sys/aio_kern.h>
80
81 #include <bsm/audit_kernel.h>
82
83 #include <sys/mount.h>
84
85 /*
86 * Descriptor management.
87 */
88 struct filelist filehead; /* head of list of open files */
89 int nfiles; /* actual number of open files */
90
91 static int frele_internal(struct file *);
92
93 /*
94 * System calls on descriptors.
95 */
96 /* ARGSUSED */
97 int
98 getdtablesize(p, uap, retval)
99 struct proc *p;
100 void *uap;
101 register_t *retval;
102 {
103 *retval = min((int)p->p_rlimit[RLIMIT_NOFILE].rlim_cur, maxfiles);
104 return (0);
105 }
106
107 /* ARGSUSED */
108 int
109 ogetdtablesize(p, uap, retval)
110 struct proc *p;
111 void *uap;
112 register_t *retval;
113 {
114 *retval = min((int)p->p_rlimit[RLIMIT_NOFILE].rlim_cur, NOFILE);
115 return (0);
116 }
117
118 static __inline__
119 void _fdrelse(fdp, fd)
120 register struct filedesc *fdp;
121 register int fd;
122 {
123 if (fd < fdp->fd_freefile)
124 fdp->fd_freefile = fd;
125 #if DIAGNOSTIC
126 if (fd > fdp->fd_lastfile)
127 panic("fdrelse: fd_lastfile inconsistent");
128 #endif
129 fdp->fd_ofiles[fd] = NULL;
130 fdp->fd_ofileflags[fd] = 0;
131 while ((fd = fdp->fd_lastfile) > 0 &&
132 fdp->fd_ofiles[fd] == NULL &&
133 !(fdp->fd_ofileflags[fd] & UF_RESERVED))
134 fdp->fd_lastfile--;
135 }
136
137 /*
138 * Duplicate a file descriptor.
139 */
140 struct dup_args {
141 u_int fd;
142 };
143 /* ARGSUSED */
144 int
145 dup(p, uap, retval)
146 struct proc *p;
147 struct dup_args *uap;
148 register_t *retval;
149 {
150 register struct filedesc *fdp = p->p_fd;
151 register int old = uap->fd;
152 int new, error;
153
154 if ((u_int)old >= fdp->fd_nfiles ||
155 fdp->fd_ofiles[old] == NULL ||
156 (fdp->fd_ofileflags[old] & UF_RESERVED))
157 return (EBADF);
158 if (error = fdalloc(p, 0, &new))
159 return (error);
160 return (finishdup(fdp, old, new, retval));
161 }
162
163 /*
164 * Duplicate a file descriptor to a particular value.
165 */
166 struct dup2_args {
167 u_int from;
168 u_int to;
169 };
170 /* ARGSUSED */
171 int
172 dup2(p, uap, retval)
173 struct proc *p;
174 struct dup2_args *uap;
175 register_t *retval;
176 {
177 register struct filedesc *fdp = p->p_fd;
178 register int old = uap->from, new = uap->to;
179 int i, error;
180
181 if ((u_int)old >= fdp->fd_nfiles ||
182 fdp->fd_ofiles[old] == NULL ||
183 (fdp->fd_ofileflags[old] & UF_RESERVED) ||
184 (u_int)new >= p->p_rlimit[RLIMIT_NOFILE].rlim_cur ||
185 (u_int)new >= maxfiles)
186 return (EBADF);
187 if (old == new) {
188 *retval = new;
189 return (0);
190 }
191 if ((u_int)new >= fdp->fd_nfiles) {
192 if (error = fdalloc(p, new, &i))
193 return (error);
194 if (new != i) {
195 _fdrelse(fdp, i);
196 goto closeit;
197 }
198 } else {
199 struct file **fpp;
200 char flags;
201 closeit:
202 if ((flags = fdp->fd_ofileflags[new]) & UF_RESERVED)
203 return (EBADF);
204 fdp->fd_ofileflags[new] = (flags & ~UF_MAPPED) | UF_RESERVED;
205 /*
206 * dup2() must succeed even if the close has an error.
207 */
208 if (*(fpp = &fdp->fd_ofiles[new])) {
209 struct file *fp = *fpp;
210
211 *fpp = NULL;
212 (void) closef(fp, p);
213 }
214 }
215 return (finishdup(fdp, old, new, retval));
216 }
217
218 /*
219 * The file control system call.
220 */
221 struct fcntl_args {
222 int fd;
223 int cmd;
224 int arg;
225 };
226 /* ARGSUSED */
227 int
228 fcntl(p, uap, retval)
229 struct proc *p;
230 register struct fcntl_args *uap;
231 register_t *retval;
232 {
233 int fd = uap->fd;
234 register struct filedesc *fdp = p->p_fd;
235 register struct file *fp;
236 register char *pop;
237 struct vnode *vp, *devvp;
238 int i, tmp, error, error2, flg = F_POSIX;
239 struct flock fl;
240 fstore_t alloc_struct; /* structure for allocate command */
241 u_int32_t alloc_flags = 0;
242 off_t offset; /* used for F_SETSIZE */
243 int newmin;
244 struct radvisory ra_struct;
245 fbootstraptransfer_t fbt_struct; /* for F_READBOOTSTRAP and F_WRITEBOOTSTRAP */
246 struct log2phys l2p_struct; /* structure for allocate command */
247 daddr_t lbn, bn;
248 int devBlockSize = 0;
249
250 AUDIT_ARG(fd, uap->fd);
251 AUDIT_ARG(cmd, uap->cmd);
252 if ((u_int)fd >= fdp->fd_nfiles ||
253 (fp = fdp->fd_ofiles[fd]) == NULL ||
254 (fdp->fd_ofileflags[fd] & UF_RESERVED))
255 return (EBADF);
256 pop = &fdp->fd_ofileflags[fd];
257
258 switch (uap->cmd) {
259
260 case F_DUPFD:
261 newmin = (long)uap->arg;
262 if ((u_int)newmin >= p->p_rlimit[RLIMIT_NOFILE].rlim_cur ||
263 (u_int)newmin >= maxfiles)
264 return (EINVAL);
265 if (error = fdalloc(p, newmin, &i))
266 return (error);
267 return (finishdup(fdp, fd, i, retval));
268
269 case F_GETFD:
270 *retval = (*pop & UF_EXCLOSE)? 1 : 0;
271 return (0);
272
273 case F_SETFD:
274 *pop = (*pop &~ UF_EXCLOSE) |
275 ((long)(uap->arg) & 1)? UF_EXCLOSE : 0;
276 return (0);
277
278 case F_GETFL:
279 *retval = OFLAGS(fp->f_flag);
280 return (0);
281
282 case F_SETFL:
283 fp->f_flag &= ~FCNTLFLAGS;
284 fp->f_flag |= FFLAGS((long)uap->arg) & FCNTLFLAGS;
285 tmp = fp->f_flag & FNONBLOCK;
286 error = fo_ioctl(fp, FIONBIO, (caddr_t)&tmp, p);
287 if (error)
288 return (error);
289 tmp = fp->f_flag & FASYNC;
290 error = fo_ioctl(fp, FIOASYNC, (caddr_t)&tmp, p);
291 if (!error)
292 return (0);
293 fp->f_flag &= ~FNONBLOCK;
294 tmp = 0;
295 (void)fo_ioctl(fp, FIONBIO, (caddr_t)&tmp, p);
296 return (error);
297
298 case F_GETOWN:
299 if (fp->f_type == DTYPE_SOCKET) {
300 *retval = ((struct socket *)fp->f_data)->so_pgid;
301 return (0);
302 }
303 error = fo_ioctl(fp, (int)TIOCGPGRP, (caddr_t)retval, p);
304 *retval = -*retval;
305 return (error);
306
307 case F_SETOWN:
308 if (fp->f_type == DTYPE_SOCKET) {
309 ((struct socket *)fp->f_data)->so_pgid =
310 (long)uap->arg;
311 return (0);
312 }
313 if ((long)uap->arg <= 0) {
314 uap->arg = (int)(-(long)(uap->arg));
315 } else {
316 struct proc *p1 = pfind((long)uap->arg);
317 if (p1 == 0)
318 return (ESRCH);
319 uap->arg = (int)p1->p_pgrp->pg_id;
320 }
321 return (fo_ioctl(fp, (int)TIOCSPGRP, (caddr_t)&uap->arg, p));
322
323 case F_SETLKW:
324 flg |= F_WAIT;
325 /* Fall into F_SETLK */
326
327 case F_SETLK:
328 if (fp->f_type != DTYPE_VNODE)
329 return (EBADF);
330 vp = (struct vnode *)fp->f_data;
331 AUDIT_ARG(vnpath, vp, ARG_VNODE1);
332 /* Copy in the lock structure */
333 error = copyin((caddr_t)uap->arg, (caddr_t)&fl,
334 sizeof (fl));
335 if (error)
336 return (error);
337 if (fl.l_whence == SEEK_CUR)
338 fl.l_start += fp->f_offset;
339 switch (fl.l_type) {
340
341 case F_RDLCK:
342 if ((fp->f_flag & FREAD) == 0)
343 return (EBADF);
344 p->p_flag |= P_ADVLOCK;
345 return (VOP_ADVLOCK(vp, (caddr_t)p, F_SETLK, &fl, flg));
346
347 case F_WRLCK:
348 if ((fp->f_flag & FWRITE) == 0)
349 return (EBADF);
350 p->p_flag |= P_ADVLOCK;
351 return (VOP_ADVLOCK(vp, (caddr_t)p, F_SETLK, &fl, flg));
352
353 case F_UNLCK:
354 return (VOP_ADVLOCK(vp, (caddr_t)p, F_UNLCK, &fl,
355 F_POSIX));
356
357 default:
358 return (EINVAL);
359 }
360
361 case F_GETLK:
362 if (fp->f_type != DTYPE_VNODE)
363 return (EBADF);
364 vp = (struct vnode *)fp->f_data;
365 AUDIT_ARG(vnpath, vp, ARG_VNODE1);
366 /* Copy in the lock structure */
367 error = copyin((caddr_t)uap->arg, (caddr_t)&fl,
368 sizeof (fl));
369 if (error)
370 return (error);
371 if (fl.l_whence == SEEK_CUR)
372 fl.l_start += fp->f_offset;
373 if (error = VOP_ADVLOCK(vp, (caddr_t)p, F_GETLK, &fl, F_POSIX))
374 return (error);
375 return (copyout((caddr_t)&fl, (caddr_t)uap->arg,
376 sizeof (fl)));
377
378 case F_PREALLOCATE:
379 if (fp->f_type != DTYPE_VNODE)
380 return (EBADF);
381
382 /* make sure that we have write permission */
383 if ((fp->f_flag & FWRITE) == 0)
384 return (EBADF);
385
386 error = copyin((caddr_t)uap->arg, (caddr_t)&alloc_struct,
387 sizeof (alloc_struct));
388 if (error)
389 return (error);
390
391 /* now set the space allocated to 0 */
392 alloc_struct.fst_bytesalloc = 0;
393
394 /*
395 * Do some simple parameter checking
396 */
397
398 /* set up the flags */
399
400 alloc_flags |= PREALLOCATE;
401
402 if (alloc_struct.fst_flags & F_ALLOCATECONTIG)
403 alloc_flags |= ALLOCATECONTIG;
404
405 if (alloc_struct.fst_flags & F_ALLOCATEALL)
406 alloc_flags |= ALLOCATEALL;
407
408 /*
409 * Do any position mode specific stuff. The only
410 * position mode supported now is PEOFPOSMODE
411 */
412
413 switch (alloc_struct.fst_posmode) {
414
415 case F_PEOFPOSMODE:
416 if (alloc_struct.fst_offset != 0)
417 return (EINVAL);
418
419 alloc_flags |= ALLOCATEFROMPEOF;
420 break;
421
422 case F_VOLPOSMODE:
423 if (alloc_struct.fst_offset <= 0)
424 return (EINVAL);
425
426 alloc_flags |= ALLOCATEFROMVOL;
427 break;
428
429 default:
430 return(EINVAL);
431 }
432
433 vp = (struct vnode *)fp->f_data;
434
435 /* lock the vnode and call allocate to get the space */
436 error = vn_lock(vp, LK_EXCLUSIVE|LK_RETRY, p);
437 if (error)
438 return (error);
439 error = VOP_ALLOCATE(vp,alloc_struct.fst_length,alloc_flags,
440 &alloc_struct.fst_bytesalloc, alloc_struct.fst_offset,
441 fp->f_cred, p);
442 VOP_UNLOCK(vp, 0, p);
443
444 if (error2 = copyout((caddr_t)&alloc_struct,
445 (caddr_t)uap->arg,
446 sizeof (alloc_struct))) {
447 if (error)
448 return(error);
449 else
450 return(error2);
451 }
452 return(error);
453
454 case F_SETSIZE:
455 if (fp->f_type != DTYPE_VNODE)
456 return (EBADF);
457
458 error = copyin((caddr_t)uap->arg, (caddr_t)&offset,
459 sizeof (off_t));
460 if (error)
461 return (error);
462
463 /*
464 * Make sure that we are root. Growing a file
465 * without zero filling the data is a security hole
466 * root would have access anyway so we'll allow it
467 */
468
469 if (!is_suser())
470 return (EACCES);
471
472 vp = (struct vnode *)fp->f_data;
473
474 /* lock the vnode and call allocate to get the space */
475 error = vn_lock(vp, LK_EXCLUSIVE|LK_RETRY, p);
476 if (error)
477 return (error);
478 error = VOP_TRUNCATE(vp,offset,IO_NOZEROFILL,fp->f_cred,p);
479 VOP_UNLOCK(vp,0,p);
480 return(error);
481
482 case F_RDAHEAD:
483 if (fp->f_type != DTYPE_VNODE)
484 return (EBADF);
485 vp = (struct vnode *)fp->f_data;
486
487 simple_lock(&vp->v_interlock);
488 if (uap->arg)
489 vp->v_flag &= ~VRAOFF;
490 else
491 vp->v_flag |= VRAOFF;
492 simple_unlock(&vp->v_interlock);
493 return (0);
494
495 case F_NOCACHE:
496 if (fp->f_type != DTYPE_VNODE)
497 return (EBADF);
498 vp = (struct vnode *)fp->f_data;
499
500 simple_lock(&vp->v_interlock);
501 if (uap->arg)
502 vp->v_flag |= VNOCACHE_DATA;
503 else
504 vp->v_flag &= ~VNOCACHE_DATA;
505 simple_unlock(&vp->v_interlock);
506 return (0);
507
508 case F_RDADVISE:
509 if (fp->f_type != DTYPE_VNODE)
510 return (EBADF);
511 vp = (struct vnode *)fp->f_data;
512
513 if (error = copyin((caddr_t)uap->arg,
514 (caddr_t)&ra_struct, sizeof (ra_struct)))
515 return(error);
516 return (VOP_IOCTL(vp, 1, (caddr_t)&ra_struct, 0, fp->f_cred, p));
517
518 case F_CHKCLEAN:
519 /*
520 * used by regression test to determine if
521 * all the dirty pages (via write) have been cleaned
522 * after a call to 'fsysnc'.
523 */
524 if (fp->f_type != DTYPE_VNODE)
525 return (EBADF);
526 vp = (struct vnode *)fp->f_data;
527
528 return (VOP_IOCTL(vp, 5, 0, 0, fp->f_cred, p));
529
530 case F_READBOOTSTRAP:
531 case F_WRITEBOOTSTRAP:
532 if (fp->f_type != DTYPE_VNODE)
533 return (EBADF);
534
535 error = copyin((caddr_t)uap->arg, (caddr_t)&fbt_struct,
536 sizeof (fbt_struct));
537 if (error)
538 return (error);
539
540 if (uap->cmd == F_WRITEBOOTSTRAP) {
541 /*
542 * Make sure that we are root. Updating the
543 * bootstrap on a disk could be a security hole
544 */
545 if (!is_suser())
546 return (EACCES);
547 }
548
549 vp = (struct vnode *)fp->f_data;
550 if (vp->v_tag != VT_HFS) /* XXX */
551 error = EINVAL;
552 else {
553 /* lock the vnode and call VOP_IOCTL to handle the I/O */
554 error = vn_lock(vp, LK_EXCLUSIVE|LK_RETRY, p);
555 if (error)
556 return (error);
557 error = VOP_IOCTL(vp, (uap->cmd == F_WRITEBOOTSTRAP) ? 3 : 2,
558 (caddr_t)&fbt_struct, 0, fp->f_cred, p);
559 VOP_UNLOCK(vp,0,p);
560 }
561 return(error);
562
563 case F_LOG2PHYS:
564 if (fp->f_type != DTYPE_VNODE)
565 return (EBADF);
566 vp = (struct vnode *)fp->f_data;
567 error = vn_lock(vp, LK_EXCLUSIVE|LK_RETRY, p);
568 if (error)
569 return (error);
570 error = VOP_OFFTOBLK(vp, fp->f_offset, &lbn);
571 if (error)
572 return (error);
573 error = VOP_BLKTOOFF(vp, lbn, &offset);
574 if (error)
575 return (error);
576 error = VOP_BMAP(vp, lbn, &devvp, &bn, 0);
577 VOP_DEVBLOCKSIZE(devvp, &devBlockSize);
578 VOP_UNLOCK(vp, 0, p);
579 if (!error) {
580 l2p_struct.l2p_flags = 0; /* for now */
581 l2p_struct.l2p_contigbytes = 0; /* for now */
582 l2p_struct.l2p_devoffset = bn * devBlockSize;
583 l2p_struct.l2p_devoffset += fp->f_offset - offset;
584 error = copyout((caddr_t)&l2p_struct,
585 (caddr_t)uap->arg,
586 sizeof (l2p_struct));
587 }
588 return (error);
589
590 case F_GETPATH: {
591 char *pathbuf;
592 int len;
593 extern int vn_getpath(struct vnode *vp, char *pathbuf, int *len);
594
595 if (fp->f_type != DTYPE_VNODE)
596 return (EBADF);
597 vp = (struct vnode *)fp->f_data;
598
599 len = MAXPATHLEN;
600 MALLOC(pathbuf, char *, len, M_TEMP, M_WAITOK);
601
602 error = vn_lock(vp, LK_EXCLUSIVE|LK_RETRY, p);
603 if (error) {
604 FREE(pathbuf, M_TEMP);
605 return (error);
606 }
607 error = vn_getpath(vp, pathbuf, &len);
608 if (error == 0)
609 error = copyout((caddr_t)pathbuf, (caddr_t)uap->arg, len);
610 VOP_UNLOCK(vp, 0, p);
611 FREE(pathbuf, M_TEMP);
612 return error;
613 }
614
615 case F_FULLFSYNC: {
616 if (fp->f_type != DTYPE_VNODE)
617 return (EBADF);
618 vp = (struct vnode *)fp->f_data;
619
620 error = vn_lock(vp, LK_EXCLUSIVE|LK_RETRY, p);
621 if (error) {
622 return (error);
623 }
624 error = VOP_IOCTL(vp, 6, (caddr_t)NULL, 0, fp->f_cred, p);
625 VOP_UNLOCK(vp, 0, p);
626 return error;
627 }
628
629 default:
630 return (EINVAL);
631 }
632 /* NOTREACHED */
633 }
634
635 /*
636 * Common code for dup, dup2, and fcntl(F_DUPFD).
637 */
638 int
639 finishdup(fdp, old, new, retval)
640 register struct filedesc *fdp;
641 register int old, new;
642 register_t *retval;
643 {
644 register struct file *fp;
645
646 if ((fp = fdp->fd_ofiles[old]) == NULL ||
647 (fdp->fd_ofileflags[old] & UF_RESERVED)) {
648 _fdrelse(fdp, new);
649 return (EBADF);
650 }
651 fdp->fd_ofiles[new] = fp;
652 fdp->fd_ofileflags[new] = fdp->fd_ofileflags[old] &~ UF_EXCLOSE;
653 (void)fref(fp);
654 if (new > fdp->fd_lastfile)
655 fdp->fd_lastfile = new;
656 *retval = new;
657 return (0);
658 }
659
660 /*
661 * Close a file descriptor.
662 */
663 struct close_args {
664 int fd;
665 };
666 /* ARGSUSED */
667 int
668 close(p, uap, retval)
669 struct proc *p;
670 struct close_args *uap;
671 register_t *retval;
672 {
673 int fd = uap->fd;
674 register struct filedesc *fdp = p->p_fd;
675 register struct file *fp;
676
677 AUDIT_SYSCLOSE(p, fd);
678 if ((u_int)fd >= fdp->fd_nfiles ||
679 (fp = fdp->fd_ofiles[fd]) == NULL ||
680 (fdp->fd_ofileflags[fd] & UF_RESERVED))
681 return (EBADF);
682
683 /* Keep people from using the filedesc while we are closing it */
684 fdp->fd_ofileflags[fd] |= UF_RESERVED;
685
686 /* cancel all async IO requests that can be cancelled. */
687 _aio_close( p, fd );
688
689 if (fd < fdp->fd_knlistsize)
690 knote_fdclose(p, fd);
691
692 _fdrelse(fdp, fd);
693 return (closef(fp, p));
694 }
695
696 /*
697 * Return status information about a file descriptor.
698 */
699 struct fstat_args {
700 int fd;
701 struct stat *sb;
702 };
703 /* ARGSUSED */
704 int
705 fstat(p, uap, retval)
706 struct proc *p;
707 register struct fstat_args *uap;
708 register_t *retval;
709 {
710 int fd = uap->fd;
711 register struct filedesc *fdp = p->p_fd;
712 register struct file *fp;
713 struct stat ub;
714 int error;
715
716 AUDIT_ARG(fd, uap->fd);
717 if ((u_int)fd >= fdp->fd_nfiles ||
718 (fp = fdp->fd_ofiles[fd]) == NULL ||
719 (fdp->fd_ofileflags[fd] & UF_RESERVED))
720 return (EBADF);
721 switch (fp->f_type) {
722
723 case DTYPE_VNODE:
724 error = vn_stat((struct vnode *)fp->f_data, &ub, p);
725 if (error == 0) {
726 AUDIT_ARG(vnpath, (struct vnode *)fp->f_data, ARG_VNODE1);
727 }
728 break;
729
730 case DTYPE_SOCKET:
731 error = soo_stat((struct socket *)fp->f_data, &ub);
732 break;
733
734 case DTYPE_PSXSHM:
735 error = pshm_stat((void *)fp->f_data, &ub);
736 break;
737
738 case DTYPE_KQUEUE:
739 error = kqueue_stat(fp, &ub, p);
740 break;
741
742 default:
743 panic("fstat");
744 /*NOTREACHED*/
745 }
746 if (error == 0)
747 error = copyout((caddr_t)&ub, (caddr_t)uap->sb,
748 sizeof (ub));
749 return (error);
750 }
751
752 #if COMPAT_43
753 /*
754 * Return status information about a file descriptor.
755 */
756 struct ofstat_args {
757 int fd;
758 struct ostat *sb;
759 };
760 /* ARGSUSED */
761 ofstat(p, uap, retval)
762 struct proc *p;
763 register struct ofstat_args *uap;
764 register_t *retval;
765 {
766 int fd = uap->fd;
767 register struct filedesc *fdp = p->p_fd;
768 register struct file *fp;
769 struct stat ub;
770 struct ostat oub;
771 int error;
772
773 if ((u_int)fd >= fdp->fd_nfiles ||
774 (fp = fdp->fd_ofiles[fd]) == NULL ||
775 (fdp->fd_ofileflags[fd] & UF_RESERVED))
776 return (EBADF);
777 switch (fp->f_type) {
778
779 case DTYPE_VNODE:
780 error = vn_stat((struct vnode *)fp->f_data, &ub, p);
781 break;
782
783 case DTYPE_SOCKET:
784 error = soo_stat((struct socket *)fp->f_data, &ub);
785 break;
786
787 default:
788 panic("ofstat");
789 /*NOTREACHED*/
790 }
791 cvtstat(&ub, &oub);
792 if (error == 0)
793 error = copyout((caddr_t)&oub, (caddr_t)uap->sb,
794 sizeof (oub));
795 return (error);
796 }
797 #endif /* COMPAT_43 */
798
799 /*
800 * Return pathconf information about a file descriptor.
801 */
802 struct fpathconf_args {
803 int fd;
804 int name;
805 };
806 /* ARGSUSED */
807 fpathconf(p, uap, retval)
808 struct proc *p;
809 register struct fpathconf_args *uap;
810 register_t *retval;
811 {
812 int fd = uap->fd;
813 struct filedesc *fdp = p->p_fd;
814 struct file *fp;
815 struct vnode *vp;
816
817 AUDIT_ARG(fd, uap->fd);
818 if ((u_int)fd >= fdp->fd_nfiles ||
819 (fp = fdp->fd_ofiles[fd]) == NULL ||
820 (fdp->fd_ofileflags[fd] & UF_RESERVED))
821 return (EBADF);
822 switch (fp->f_type) {
823
824 case DTYPE_SOCKET:
825 if (uap->name != _PC_PIPE_BUF)
826 return (EINVAL);
827 *retval = PIPE_BUF;
828 return (0);
829
830 case DTYPE_VNODE:
831 vp = (struct vnode *)fp->f_data;
832 AUDIT_ARG(vnpath, vp, ARG_VNODE1);
833
834 return (VOP_PATHCONF(vp, uap->name, retval));
835
836 default:
837 panic("fpathconf");
838 }
839 /*NOTREACHED*/
840 }
841
842 /*
843 * Allocate a file descriptor for the process.
844 */
845 int fdexpand;
846
847 int
848 fdalloc(p, want, result)
849 struct proc *p;
850 int want;
851 int *result;
852 {
853 register struct filedesc *fdp = p->p_fd;
854 register int i;
855 int lim, last, nfiles, oldnfiles;
856 struct file **newofiles, **ofiles;
857 char *newofileflags, *ofileflags;
858
859 /*
860 * Search for a free descriptor starting at the higher
861 * of want or fd_freefile. If that fails, consider
862 * expanding the ofile array.
863 */
864 lim = min((int)p->p_rlimit[RLIMIT_NOFILE].rlim_cur, maxfiles);
865 for (;;) {
866 last = min(fdp->fd_nfiles, lim);
867 if ((i = want) < fdp->fd_freefile)
868 i = fdp->fd_freefile;
869 ofiles = &fdp->fd_ofiles[i];
870 ofileflags = &fdp->fd_ofileflags[i];
871 for (; i < last; i++) {
872 if (*ofiles == NULL && !(*ofileflags & UF_RESERVED)) {
873 *ofileflags = UF_RESERVED;
874 if (i > fdp->fd_lastfile)
875 fdp->fd_lastfile = i;
876 if (want <= fdp->fd_freefile)
877 fdp->fd_freefile = i;
878 *result = i;
879 return (0);
880 }
881 ofiles++; ofileflags++;
882 }
883
884 /*
885 * No space in current array. Expand?
886 */
887 if (fdp->fd_nfiles >= lim)
888 return (EMFILE);
889 if (fdp->fd_nfiles < NDEXTENT)
890 nfiles = NDEXTENT;
891 else
892 nfiles = 2 * fdp->fd_nfiles;
893 /* Enforce lim */
894 if (nfiles > lim)
895 nfiles = lim;
896 MALLOC_ZONE(newofiles, struct file **,
897 nfiles * OFILESIZE, M_OFILETABL, M_WAITOK);
898 if (fdp->fd_nfiles >= nfiles) {
899 FREE_ZONE(newofiles, nfiles * OFILESIZE, M_OFILETABL);
900 continue;
901 }
902 newofileflags = (char *) &newofiles[nfiles];
903 /*
904 * Copy the existing ofile and ofileflags arrays
905 * and zero the new portion of each array.
906 */
907 oldnfiles = fdp->fd_nfiles;
908 (void) memcpy(newofiles, fdp->fd_ofiles,
909 oldnfiles * sizeof *fdp->fd_ofiles);
910 (void) memset(&newofiles[oldnfiles], 0,
911 (nfiles - oldnfiles) * sizeof *fdp->fd_ofiles);
912
913 (void) memcpy(newofileflags, fdp->fd_ofileflags,
914 oldnfiles * sizeof *fdp->fd_ofileflags);
915 (void) memset(&newofileflags[oldnfiles], 0,
916 (nfiles - oldnfiles) *
917 sizeof *fdp->fd_ofileflags);
918 ofiles = fdp->fd_ofiles;
919 fdp->fd_ofiles = newofiles;
920 fdp->fd_ofileflags = newofileflags;
921 fdp->fd_nfiles = nfiles;
922 FREE_ZONE(ofiles, oldnfiles * OFILESIZE, M_OFILETABL);
923 fdexpand++;
924 }
925 }
926
927 /*
928 * Check to see whether n user file descriptors
929 * are available to the process p.
930 */
931 int
932 fdavail(p, n)
933 struct proc *p;
934 register int n;
935 {
936 register struct filedesc *fdp = p->p_fd;
937 register struct file **fpp;
938 register char *flags;
939 register int i, lim;
940
941 lim = min((int)p->p_rlimit[RLIMIT_NOFILE].rlim_cur, maxfiles);
942 if ((i = lim - fdp->fd_nfiles) > 0 && (n -= i) <= 0)
943 return (1);
944 fpp = &fdp->fd_ofiles[fdp->fd_freefile];
945 flags = &fdp->fd_ofileflags[fdp->fd_freefile];
946 for (i = fdp->fd_nfiles - fdp->fd_freefile; --i >= 0; fpp++, flags++)
947 if (*fpp == NULL && !(*flags & UF_RESERVED) && --n <= 0)
948 return (1);
949 return (0);
950 }
951
952 void
953 fdrelse(p, fd)
954 struct proc *p;
955 int fd;
956 {
957 _fdrelse(p->p_fd, fd);
958 }
959
960 int
961 fdgetf(p, fd, resultfp)
962 register struct proc *p;
963 register int fd;
964 struct file **resultfp;
965 {
966 register struct filedesc *fdp = p->p_fd;
967 struct file *fp;
968
969 if ((u_int)fd >= fdp->fd_nfiles ||
970 (fp = fdp->fd_ofiles[fd]) == NULL ||
971 (fdp->fd_ofileflags[fd] & UF_RESERVED))
972 return (EBADF);
973
974 if (resultfp)
975 *resultfp = fp;
976 return (0);
977 }
978
979 /*
980 * Create a new open file structure and allocate
981 * a file decriptor for the process that refers to it.
982 */
983 int
984 falloc(p, resultfp, resultfd)
985 register struct proc *p;
986 struct file **resultfp;
987 int *resultfd;
988 {
989 register struct file *fp, *fq;
990 int error, i;
991
992 if (error = fdalloc(p, 0, &i))
993 return (error);
994 if (nfiles >= maxfiles) {
995 tablefull("file");
996 return (ENFILE);
997 }
998 /*
999 * Allocate a new file descriptor.
1000 * If the process has file descriptor zero open, add to the list
1001 * of open files at that point, otherwise put it at the front of
1002 * the list of open files.
1003 */
1004 nfiles++;
1005 MALLOC_ZONE(fp, struct file *, sizeof(struct file), M_FILE, M_WAITOK);
1006 bzero(fp, sizeof(struct file));
1007 p->p_fd->fd_ofiles[i] = fp;
1008 fp->f_count = 1;
1009 fp->f_cred = p->p_ucred;
1010 crhold(fp->f_cred);
1011 if (resultfp)
1012 *resultfp = fp;
1013 if (resultfd)
1014 *resultfd = i;
1015 if (fq = p->p_fd->fd_ofiles[0]) {
1016 LIST_INSERT_AFTER(fq, fp, f_list);
1017 } else {
1018 LIST_INSERT_HEAD(&filehead, fp, f_list);
1019 }
1020 return (0);
1021 }
1022
1023 /*
1024 * Free a file structure.
1025 */
1026 void
1027 ffree(fp)
1028 register struct file *fp;
1029 {
1030 register struct file *fq;
1031 struct ucred *cred;
1032
1033 LIST_REMOVE(fp, f_list);
1034 cred = fp->f_cred;
1035 if (cred != NOCRED) {
1036 fp->f_cred = NOCRED;
1037 crfree(cred);
1038 }
1039
1040 nfiles--;
1041 memset(fp, 0xff, sizeof *fp);
1042 fp->f_count = (short)0xffff;
1043
1044 FREE_ZONE(fp, sizeof *fp, M_FILE);
1045 }
1046
1047 void
1048 fdexec(p)
1049 struct proc *p;
1050 {
1051 register struct filedesc *fdp = p->p_fd;
1052 register int i = fdp->fd_lastfile;
1053 register struct file **fpp = &fdp->fd_ofiles[i];
1054 register char *flags = &fdp->fd_ofileflags[i];
1055
1056 while (i >= 0) {
1057 if ((*flags & (UF_RESERVED|UF_EXCLOSE)) == UF_EXCLOSE) {
1058 register struct file *fp = *fpp;
1059
1060 if (i < fdp->fd_knlistsize)
1061 knote_fdclose(p, i);
1062
1063 *fpp = NULL; *flags = 0;
1064 if (i == fdp->fd_lastfile && i > 0)
1065 fdp->fd_lastfile--;
1066 closef(fp, p);
1067 }
1068 else
1069 *flags &= ~UF_MAPPED;
1070
1071 i--; fpp--; flags--;
1072 }
1073 }
1074
1075 /*
1076 * Copy a filedesc structure.
1077 */
1078 struct filedesc *
1079 fdcopy(p)
1080 struct proc *p;
1081 {
1082 register struct filedesc *newfdp, *fdp = p->p_fd;
1083 register int i;
1084
1085 MALLOC_ZONE(newfdp, struct filedesc *,
1086 sizeof *newfdp, M_FILEDESC, M_WAITOK);
1087 (void) memcpy(newfdp, fdp, sizeof *newfdp);
1088 VREF(newfdp->fd_cdir);
1089 if (newfdp->fd_rdir)
1090 VREF(newfdp->fd_rdir);
1091 newfdp->fd_refcnt = 1;
1092
1093 /*
1094 * If the number of open files fits in the internal arrays
1095 * of the open file structure, use them, otherwise allocate
1096 * additional memory for the number of descriptors currently
1097 * in use.
1098 */
1099 if (newfdp->fd_lastfile < NDFILE)
1100 i = NDFILE;
1101 else {
1102 /*
1103 * Compute the smallest multiple of NDEXTENT needed
1104 * for the file descriptors currently in use,
1105 * allowing the table to shrink.
1106 */
1107 i = newfdp->fd_nfiles;
1108 while (i > 2 * NDEXTENT && i > newfdp->fd_lastfile * 2)
1109 i /= 2;
1110 }
1111 MALLOC_ZONE(newfdp->fd_ofiles, struct file **,
1112 i * OFILESIZE, M_OFILETABL, M_WAITOK);
1113 newfdp->fd_ofileflags = (char *) &newfdp->fd_ofiles[i];
1114 newfdp->fd_nfiles = i;
1115 if (fdp->fd_nfiles > 0) {
1116 register struct file **fpp;
1117 register char *flags;
1118
1119 (void) memcpy(newfdp->fd_ofiles, fdp->fd_ofiles,
1120 i * sizeof *fdp->fd_ofiles);
1121 (void) memcpy(newfdp->fd_ofileflags, fdp->fd_ofileflags,
1122 i * sizeof *fdp->fd_ofileflags);
1123
1124 /*
1125 * kq descriptors cannot be copied.
1126 */
1127 if (newfdp->fd_knlistsize != -1) {
1128 fpp = &newfdp->fd_ofiles[newfdp->fd_lastfile];
1129 for (i = newfdp->fd_lastfile; i >= 0; i--, fpp--) {
1130 if (*fpp != NULL && (*fpp)->f_type == DTYPE_KQUEUE) {
1131 *fpp = NULL;
1132 if (i < newfdp->fd_freefile)
1133 newfdp->fd_freefile = i;
1134 }
1135 if (*fpp == NULL && i == newfdp->fd_lastfile && i > 0)
1136 newfdp->fd_lastfile--;
1137 }
1138 newfdp->fd_knlist = NULL;
1139 newfdp->fd_knlistsize = -1;
1140 newfdp->fd_knhash = NULL;
1141 newfdp->fd_knhashmask = 0;
1142 }
1143
1144 fpp = newfdp->fd_ofiles;
1145 flags = newfdp->fd_ofileflags;
1146 for (i = newfdp->fd_lastfile; i-- >= 0; fpp++, flags++)
1147 if (*fpp != NULL && !(*flags & UF_RESERVED)) {
1148 (void)fref(*fpp);
1149 } else {
1150 *fpp = NULL;
1151 *flags = 0;
1152 }
1153 } else
1154 (void) memset(newfdp->fd_ofiles, 0, i * OFILESIZE);
1155
1156 return (newfdp);
1157 }
1158
1159 /*
1160 * Release a filedesc structure.
1161 */
1162 void
1163 fdfree(p)
1164 struct proc *p;
1165 {
1166 struct filedesc *fdp;
1167 struct file *fp;
1168 int i;
1169 struct vnode *tvp;
1170
1171 /* Certain daemons might not have file descriptors */
1172 if ((fdp = p->p_fd) == NULL)
1173 return;
1174
1175 if (--fdp->fd_refcnt > 0)
1176 return;
1177
1178 /* Last reference: the structure can't change out from under us */
1179 if (fdp->fd_nfiles > 0) {
1180 for (i = fdp->fd_lastfile; i >= 0; i--)
1181 #if 1 /* WORKAROUND */
1182 /*
1183 * Merlot: need to remove the bogus f_data check
1184 * from the following "if" statement. It's there
1185 * because of the network/kernel funnel race on a
1186 * close of a socket vs. fdfree on exit. See
1187 * Radar rdar://problem/3365650 for details, but
1188 * the sort version is the commment before the "if"
1189 * above is wrong under certain circumstances.
1190 *
1191 * We have to do this twice, in case knote_fdclose()
1192 * results in a block.
1193 *
1194 * This works because an fdfree() will set all fields
1195 * in the struct file to -1.
1196 */
1197 if ((fp = fdp->fd_ofiles[i]) != NULL &&
1198 fp->f_data != (caddr_t)-1) {
1199 if (i < fdp->fd_knlistsize)
1200 knote_fdclose(p, i);
1201 if (fp->f_data != (caddr_t)-1)
1202 (void) closef(fp, p);
1203 }
1204 #else /* !WORKAROUND */
1205 if ((fp = fdp->fd_ofiles[i]) != NULL) {
1206 if (i < fdp->fd_knlistsize)
1207 knote_fdclose(p, i);
1208 (void) closef(fp, p);
1209 }
1210 #endif /* !WORKAROUND */
1211 FREE_ZONE(fdp->fd_ofiles,
1212 fdp->fd_nfiles * OFILESIZE, M_OFILETABL);
1213 }
1214
1215 tvp = fdp->fd_cdir;
1216 fdp->fd_cdir = NULL;
1217 vrele(tvp);
1218
1219 if (fdp->fd_rdir) {
1220 tvp = fdp->fd_rdir;
1221 fdp->fd_rdir = NULL;
1222 vrele(tvp);
1223 }
1224
1225 if (fdp->fd_knlist)
1226 FREE(fdp->fd_knlist, M_KQUEUE);
1227 if (fdp->fd_knhash)
1228 FREE(fdp->fd_knhash, M_KQUEUE);
1229
1230 FREE_ZONE(fdp, sizeof *fdp, M_FILEDESC);
1231
1232 // XXXdbg
1233 {
1234 void clean_up_fmod_watch(struct proc *p);
1235 clean_up_fmod_watch(p);
1236 }
1237 }
1238
1239 static int
1240 closef_finish(fp, p)
1241 register struct file *fp;
1242 register struct proc *p;
1243 {
1244 struct vnode *vp;
1245 struct flock lf;
1246 int error;
1247
1248 if ((fp->f_flag & FHASLOCK) && fp->f_type == DTYPE_VNODE) {
1249 lf.l_whence = SEEK_SET;
1250 lf.l_start = 0;
1251 lf.l_len = 0;
1252 lf.l_type = F_UNLCK;
1253 vp = (struct vnode *)fp->f_data;
1254 (void) VOP_ADVLOCK(vp, (caddr_t)fp, F_UNLCK, &lf, F_FLOCK);
1255 }
1256 if (fp->f_ops)
1257 error = fo_close(fp, p);
1258 else
1259 error = 0;
1260 ffree(fp);
1261 return (error);
1262 }
1263
1264 /*
1265 * Internal form of close.
1266 * Decrement reference count on file structure.
1267 * Note: p may be NULL when closing a file
1268 * that was being passed in a message.
1269 */
1270 int
1271 closef(fp, p)
1272 register struct file *fp;
1273 register struct proc *p;
1274 {
1275 struct vnode *vp;
1276 struct flock lf;
1277 int error;
1278
1279 if (fp == NULL)
1280 return (0);
1281 /*
1282 * POSIX record locking dictates that any close releases ALL
1283 * locks owned by this process. This is handled by setting
1284 * a flag in the unlock to free ONLY locks obeying POSIX
1285 * semantics, and not to free BSD-style file locks.
1286 * If the descriptor was in a message, POSIX-style locks
1287 * aren't passed with the descriptor.
1288 */
1289 if (p && (p->p_flag & P_ADVLOCK) && fp->f_type == DTYPE_VNODE) {
1290 lf.l_whence = SEEK_SET;
1291 lf.l_start = 0;
1292 lf.l_len = 0;
1293 lf.l_type = F_UNLCK;
1294 vp = (struct vnode *)fp->f_data;
1295 (void) VOP_ADVLOCK(vp, (caddr_t)p, F_UNLCK, &lf, F_POSIX);
1296 }
1297 if (frele_internal(fp) > 0)
1298 return (0);
1299 return(closef_finish(fp, p));
1300 }
1301
1302 /*
1303 * Apply an advisory lock on a file descriptor.
1304 *
1305 * Just attempt to get a record lock of the requested type on
1306 * the entire file (l_whence = SEEK_SET, l_start = 0, l_len = 0).
1307 */
1308 struct flock_args {
1309 int fd;
1310 int how;
1311 };
1312 /* ARGSUSED */
1313 int
1314 flock(p, uap, retval)
1315 struct proc *p;
1316 register struct flock_args *uap;
1317 register_t *retval;
1318 {
1319 int fd = uap->fd;
1320 int how = uap->how;
1321 register struct filedesc *fdp = p->p_fd;
1322 register struct file *fp;
1323 struct vnode *vp;
1324 struct flock lf;
1325
1326 AUDIT_ARG(fd, uap->fd);
1327 if ((u_int)fd >= fdp->fd_nfiles ||
1328 (fp = fdp->fd_ofiles[fd]) == NULL ||
1329 (fdp->fd_ofileflags[fd] & UF_RESERVED))
1330 return (EBADF);
1331 if (fp->f_type != DTYPE_VNODE)
1332 return (EOPNOTSUPP);
1333 vp = (struct vnode *)fp->f_data;
1334 AUDIT_ARG(vnpath, vp, ARG_VNODE1);
1335 lf.l_whence = SEEK_SET;
1336 lf.l_start = 0;
1337 lf.l_len = 0;
1338 if (how & LOCK_UN) {
1339 lf.l_type = F_UNLCK;
1340 fp->f_flag &= ~FHASLOCK;
1341 return (VOP_ADVLOCK(vp, (caddr_t)fp, F_UNLCK, &lf, F_FLOCK));
1342 }
1343 if (how & LOCK_EX)
1344 lf.l_type = F_WRLCK;
1345 else if (how & LOCK_SH)
1346 lf.l_type = F_RDLCK;
1347 else
1348 return (EBADF);
1349 fp->f_flag |= FHASLOCK;
1350 if (how & LOCK_NB)
1351 return (VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, F_FLOCK));
1352 return (VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, F_FLOCK|F_WAIT));
1353 }
1354
1355 /*
1356 * File Descriptor pseudo-device driver (/dev/fd/).
1357 *
1358 * Opening minor device N dup()s the file (if any) connected to file
1359 * descriptor N belonging to the calling process. Note that this driver
1360 * consists of only the ``open()'' routine, because all subsequent
1361 * references to this file will be direct to the other driver.
1362 */
1363 /* ARGSUSED */
1364 int
1365 fdopen(dev, mode, type, p)
1366 dev_t dev;
1367 int mode, type;
1368 struct proc *p;
1369 {
1370
1371 /*
1372 * XXX Kludge: set curproc->p_dupfd to contain the value of the
1373 * the file descriptor being sought for duplication. The error
1374 * return ensures that the vnode for this device will be released
1375 * by vn_open. Open will detect this special error and take the
1376 * actions in dupfdopen below. Other callers of vn_open or VOP_OPEN
1377 * will simply report the error.
1378 */
1379 p->p_dupfd = minor(dev);
1380 return (ENODEV);
1381 }
1382
1383 /*
1384 * Duplicate the specified descriptor to a free descriptor.
1385 */
1386 int
1387 dupfdopen(fdp, indx, dfd, mode, error)
1388 register struct filedesc *fdp;
1389 register int indx, dfd;
1390 int mode;
1391 int error;
1392 {
1393 register struct file *wfp;
1394 struct file *fp;
1395
1396 /*
1397 * If the to-be-dup'd fd number is greater than the allowed number
1398 * of file descriptors, or the fd to be dup'd has already been
1399 * closed, reject. Note, check for new == old is necessary as
1400 * falloc could allocate an already closed to-be-dup'd descriptor
1401 * as the new descriptor.
1402 */
1403 fp = fdp->fd_ofiles[indx];
1404 if ((u_int)dfd >= fdp->fd_nfiles ||
1405 (wfp = fdp->fd_ofiles[dfd]) == NULL || wfp == fp ||
1406 (fdp->fd_ofileflags[dfd] & UF_RESERVED))
1407 return (EBADF);
1408
1409 /*
1410 * There are two cases of interest here.
1411 *
1412 * For ENODEV simply dup (dfd) to file descriptor
1413 * (indx) and return.
1414 *
1415 * For ENXIO steal away the file structure from (dfd) and
1416 * store it in (indx). (dfd) is effectively closed by
1417 * this operation.
1418 *
1419 * Any other error code is just returned.
1420 */
1421 switch (error) {
1422 case ENODEV:
1423 /*
1424 * Check that the mode the file is being opened for is a
1425 * subset of the mode of the existing descriptor.
1426 */
1427 if (((mode & (FREAD|FWRITE)) | wfp->f_flag) != wfp->f_flag)
1428 return (EACCES);
1429 (void)fref(wfp);
1430 if (indx > fdp->fd_lastfile)
1431 fdp->fd_lastfile = indx;;
1432 fdp->fd_ofiles[indx] = wfp;
1433 fdp->fd_ofileflags[indx] = fdp->fd_ofileflags[dfd];
1434 return (0);
1435
1436 case ENXIO:
1437 /*
1438 * Steal away the file pointer from dfd, and stuff it into indx.
1439 */
1440 if (indx > fdp->fd_lastfile)
1441 fdp->fd_lastfile = indx;;
1442 fdp->fd_ofiles[indx] = fdp->fd_ofiles[dfd];
1443 fdp->fd_ofileflags[indx] = fdp->fd_ofileflags[dfd];
1444 _fdrelse(fdp, dfd);
1445 return (0);
1446
1447 default:
1448 return (error);
1449 }
1450 /* NOTREACHED */
1451 }
1452
1453 /* Reference manipulation routines for the file structure */
1454
1455 int
1456 fref(struct file *fp)
1457 {
1458 if (fp->f_count == (short)0xffff)
1459 return (-1);
1460 if (++fp->f_count <= 0)
1461 panic("fref: f_count");
1462 return ((int)fp->f_count);
1463 }
1464
1465 static int
1466 frele_internal(struct file *fp)
1467 {
1468 if (fp->f_count == (short)0xffff)
1469 panic("frele: stale");
1470 if (--fp->f_count < 0)
1471 panic("frele: count < 0");
1472 return ((int)fp->f_count);
1473 }
1474
1475
1476 int
1477 frele(struct file *fp)
1478 {
1479 int count;
1480 funnel_t * fnl;
1481 extern int disable_funnel;
1482
1483 fnl = thread_funnel_get();
1484 /*
1485 * If the funnels are merged then atleast a funnel should be held
1486 * else frele should come in with kernel funnel only
1487 */
1488 if (!disable_funnel && (fnl != kernel_flock)) {
1489 panic("frele: kernel funnel not held");
1490
1491 } else if (fnl == THR_FUNNEL_NULL) {
1492 panic("frele: no funnel held");
1493 }
1494
1495 if ((count = frele_internal(fp)) == 0) {
1496 /* some one closed the fd while we were blocked */
1497 (void)closef_finish(fp, current_proc());
1498 }
1499 return(count);
1500 }
1501
1502 int
1503 fcount(struct file *fp)
1504 {
1505 if (fp->f_count == (short)0xffff)
1506 panic("fcount: stale");
1507 return ((int)fp->f_count);
1508 }
1509