2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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.
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
20 * @APPLE_LICENSE_HEADER_END@
22 /* Copyright (c) 1995, 1997 Apple Computer, Inc. All Rights Reserved */
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.
32 * Redistribution and use in source and binary forms, with or without
33 * modification, are permitted provided that the following conditions
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.
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
60 * @(#)kern_descrip.c 8.8 (Berkeley) 2/14/95
63 * CHW 8/5/98 Added F_SETSIZE command to truncate without
65 * CHW 7/6/98 Updated Preallocate command to take a structure
67 * CHW 6/25/98 Fixed a bug in the lock call in fcntl
71 #include <sys/param.h>
72 #include <sys/systm.h>
73 #include <sys/filedesc.h>
74 #include <sys/kernel.h>
75 #include <sys/vnode.h>
78 #include <sys/socket.h>
79 #include <sys/socketvar.h>
81 #include <sys/ioctl.h>
82 #include <sys/fcntl.h>
83 #include <sys/malloc.h>
84 #include <sys/syslog.h>
85 #include <sys/unistd.h>
86 #include <sys/resourcevar.h>
88 #include <sys/mount.h>
91 * Descriptor management.
93 struct filelist filehead
; /* head of list of open files */
94 int nfiles
; /* actual number of open files */
97 * System calls on descriptors.
101 getdtablesize(p
, uap
, retval
)
107 *retval
= min((int)p
->p_rlimit
[RLIMIT_NOFILE
].rlim_cur
, maxfiles
);
113 ogetdtablesize(p
, uap
, retval
)
119 *retval
= min((int)p
->p_rlimit
[RLIMIT_NOFILE
].rlim_cur
, NOFILE
);
124 void _fdrelse(fdp
, fd
)
125 register struct filedesc
*fdp
;
128 if (fd
< fdp
->fd_freefile
)
129 fdp
->fd_freefile
= fd
;
131 if (fd
> fdp
->fd_lastfile
)
132 panic("fdrelse: fd_lastfile inconsistent");
134 fdp
->fd_ofiles
[fd
] = NULL
;
135 fdp
->fd_ofileflags
[fd
] = 0;
136 while ((fd
= fdp
->fd_lastfile
) > 0 &&
137 fdp
->fd_ofiles
[fd
] == NULL
&&
138 !(fdp
->fd_ofileflags
[fd
] & UF_RESERVED
))
143 * Duplicate a file descriptor.
152 struct dup_args
*uap
;
155 register struct filedesc
*fdp
= p
->p_fd
;
156 register int old
= uap
->fd
;
159 if ((u_int
)old
>= fdp
->fd_nfiles
||
160 fdp
->fd_ofiles
[old
] == NULL
||
161 (fdp
->fd_ofileflags
[old
] & UF_RESERVED
))
163 if (error
= fdalloc(p
, 0, &new))
165 return (finishdup(fdp
, old
, new, retval
));
169 * Duplicate a file descriptor to a particular value.
179 struct dup2_args
*uap
;
182 register struct filedesc
*fdp
= p
->p_fd
;
183 register int old
= uap
->from
, new = uap
->to
;
186 if ((u_int
)old
>= fdp
->fd_nfiles
||
187 fdp
->fd_ofiles
[old
] == NULL
||
188 (fdp
->fd_ofileflags
[old
] & UF_RESERVED
) ||
189 (u_int
)new >= p
->p_rlimit
[RLIMIT_NOFILE
].rlim_cur
||
190 (u_int
)new >= maxfiles
)
196 if ((u_int
)new >= fdp
->fd_nfiles
) {
197 if (error
= fdalloc(p
, new, &i
))
208 if ((flags
= fdp
->fd_ofileflags
[new]) & UF_RESERVED
)
210 fdp
->fd_ofileflags
[new] = (flags
& ~UF_MAPPED
) | UF_RESERVED
;
212 * dup2() must succeed even if the close has an error.
214 if (*(fpp
= &fdp
->fd_ofiles
[new])) {
215 struct file
*fp
= *fpp
;
217 *fpp
= NULL
; (void) closef(fp
, p
);
220 return (finishdup(fdp
, old
, new, retval
));
224 * The file control system call.
233 fcntl(p
, uap
, retval
)
235 register struct fcntl_args
*uap
;
239 register struct filedesc
*fdp
= p
->p_fd
;
240 register struct file
*fp
;
242 struct vnode
*vp
, *devvp
;
243 int i
, tmp
, error
, error2
, flg
= F_POSIX
;
245 fstore_t alloc_struct
; /* structure for allocate command */
246 u_int32_t alloc_flags
= 0;
247 off_t offset
; /* used for F_SETSIZE */
249 struct radvisory ra_struct
;
250 fbootstraptransfer_t fbt_struct
; /* for F_READBOOTSTRAP and F_WRITEBOOTSTRAP */
251 struct log2phys l2p_struct
; /* structure for allocate command */
253 int devBlockSize
= 0;
255 if ((u_int
)fd
>= fdp
->fd_nfiles
||
256 (fp
= fdp
->fd_ofiles
[fd
]) == NULL
||
257 (fdp
->fd_ofileflags
[fd
] & UF_RESERVED
))
259 pop
= &fdp
->fd_ofileflags
[fd
];
263 newmin
= (long)uap
->arg
;
264 if ((u_int
)newmin
>= p
->p_rlimit
[RLIMIT_NOFILE
].rlim_cur
||
265 (u_int
)newmin
>= maxfiles
)
267 if (error
= fdalloc(p
, newmin
, &i
))
269 return (finishdup(fdp
, fd
, i
, retval
));
272 *retval
= (*pop
& UF_EXCLOSE
)? 1 : 0;
276 *pop
= (*pop
&~ UF_EXCLOSE
) |
277 ((long)(uap
->arg
) & 1)? UF_EXCLOSE
: 0;
281 *retval
= OFLAGS(fp
->f_flag
);
285 fp
->f_flag
&= ~FCNTLFLAGS
;
286 fp
->f_flag
|= FFLAGS((long)uap
->arg
) & FCNTLFLAGS
;
287 tmp
= fp
->f_flag
& FNONBLOCK
;
288 error
= (*fp
->f_ops
->fo_ioctl
)(fp
, FIONBIO
, (caddr_t
)&tmp
, p
);
291 tmp
= fp
->f_flag
& FASYNC
;
292 error
= (*fp
->f_ops
->fo_ioctl
)(fp
, FIOASYNC
, (caddr_t
)&tmp
, p
);
295 fp
->f_flag
&= ~FNONBLOCK
;
297 (void) (*fp
->f_ops
->fo_ioctl
)(fp
, FIONBIO
, (caddr_t
)&tmp
, p
);
301 if (fp
->f_type
== DTYPE_SOCKET
) {
302 *retval
= ((struct socket
*)fp
->f_data
)->so_pgid
;
305 error
= (*fp
->f_ops
->fo_ioctl
)
306 (fp
, (int)TIOCGPGRP
, (caddr_t
)retval
, p
);
311 if (fp
->f_type
== DTYPE_SOCKET
) {
312 ((struct socket
*)fp
->f_data
)->so_pgid
=
316 if ((long)uap
->arg
<= 0) {
317 uap
->arg
= (void *)(-(long)(uap
->arg
));
319 struct proc
*p1
= pfind((long)uap
->arg
);
322 uap
->arg
= (void *)(long)p1
->p_pgrp
->pg_id
;
324 return ((*fp
->f_ops
->fo_ioctl
)
325 (fp
, (int)TIOCSPGRP
, (caddr_t
)&uap
->arg
, p
));
329 /* Fall into F_SETLK */
332 if (fp
->f_type
!= DTYPE_VNODE
)
334 vp
= (struct vnode
*)fp
->f_data
;
335 /* Copy in the lock structure */
336 error
= copyin((caddr_t
)uap
->arg
, (caddr_t
)&fl
,
340 if (fl
.l_whence
== SEEK_CUR
)
341 fl
.l_start
+= fp
->f_offset
;
345 if ((fp
->f_flag
& FREAD
) == 0)
347 p
->p_flag
|= P_ADVLOCK
;
348 return (VOP_ADVLOCK(vp
, (caddr_t
)p
, F_SETLK
, &fl
, flg
));
351 if ((fp
->f_flag
& FWRITE
) == 0)
353 p
->p_flag
|= P_ADVLOCK
;
354 return (VOP_ADVLOCK(vp
, (caddr_t
)p
, F_SETLK
, &fl
, flg
));
357 return (VOP_ADVLOCK(vp
, (caddr_t
)p
, F_UNLCK
, &fl
,
365 if (fp
->f_type
!= DTYPE_VNODE
)
367 vp
= (struct vnode
*)fp
->f_data
;
368 /* Copy in the lock structure */
369 error
= copyin((caddr_t
)uap
->arg
, (caddr_t
)&fl
,
373 if (fl
.l_whence
== SEEK_CUR
)
374 fl
.l_start
+= fp
->f_offset
;
375 if (error
= VOP_ADVLOCK(vp
, (caddr_t
)p
, F_GETLK
, &fl
, F_POSIX
))
377 return (copyout((caddr_t
)&fl
, (caddr_t
)uap
->arg
,
382 /* Copy in the structure */
384 error
= copyin((caddr_t
)uap
->arg
, (caddr_t
)&alloc_struct
,
385 sizeof (alloc_struct
));
390 /* now set the space allocated to 0 and pass it out in
391 case we get a parameter checking error */
393 alloc_struct
.fst_bytesalloc
= 0;
395 error
= copyout((caddr_t
)&alloc_struct
, (caddr_t
)uap
->arg
,
396 sizeof (alloc_struct
));
401 /* First make sure that we have write permission */
403 if ((fp
->f_flag
& FWRITE
) == 0)
407 /* Do some simple parameter checking */
410 /* set up the flags */
412 alloc_flags
|= PREALLOCATE
;
414 if (alloc_struct
.fst_flags
& F_ALLOCATECONTIG
) {
415 alloc_flags
|= ALLOCATECONTIG
;
418 if (alloc_struct
.fst_flags
& F_ALLOCATEALL
) {
419 alloc_flags
|= ALLOCATEALL
;
422 /* Do any position mode specific stuff. The only */
423 /* position mode supported now is PEOFPOSMODE */
425 switch (alloc_struct
.fst_posmode
) {
429 if (alloc_struct
.fst_offset
!= 0)
432 alloc_flags
|= ALLOCATEFROMPEOF
;
437 if (alloc_struct
.fst_offset
<= 0)
440 alloc_flags
|= ALLOCATEFROMVOL
;
449 /* Now lock the vnode and call allocate to get the space */
451 vp
= (struct vnode
*)fp
->f_data
;
453 VOP_LOCK(vp
,LK_EXCLUSIVE
,p
);
454 error
= VOP_ALLOCATE(vp
,alloc_struct
.fst_length
,alloc_flags
,
455 &alloc_struct
.fst_bytesalloc
, alloc_struct
.fst_offset
,
459 if (error2
= (copyout((caddr_t
)&alloc_struct
, (caddr_t
)uap
->arg
,
460 sizeof (alloc_struct
)))) {
472 /* Copy in the structure */
474 error
= copyin((caddr_t
)uap
->arg
, (caddr_t
)&offset
,
481 /* First make sure that we are root. Growing a file */
482 /* without zero filling the data is a security hole */
483 /* root would have access anyway so we'll allow it */
489 /* Now lock the vnode and call allocate to get the space */
491 vp
= (struct vnode
*)fp
->f_data
;
493 VOP_LOCK(vp
,LK_EXCLUSIVE
,p
);
494 error
= VOP_TRUNCATE(vp
,offset
,IO_NOZEROFILL
,fp
->f_cred
,p
);
500 vp
= (struct vnode
*)fp
->f_data
;
502 simple_lock(&vp
->v_interlock
);
504 vp
->v_flag
&= ~VRAOFF
;
506 vp
->v_flag
|= VRAOFF
;
507 simple_unlock(&vp
->v_interlock
);
512 vp
= (struct vnode
*)fp
->f_data
;
514 simple_lock(&vp
->v_interlock
);
516 vp
->v_flag
|= VNOCACHE_DATA
;
518 vp
->v_flag
&= ~VNOCACHE_DATA
;
519 simple_unlock(&vp
->v_interlock
);
524 vp
= (struct vnode
*)fp
->f_data
;
526 if (error
= copyin((caddr_t
)uap
->arg
, (caddr_t
)&ra_struct
, sizeof (ra_struct
)))
528 return (VOP_IOCTL(vp
, 1, &ra_struct
, 0, fp
->f_cred
, p
));
530 case F_READBOOTSTRAP
:
531 case F_WRITEBOOTSTRAP
:
533 /* Copy in the structure */
535 error
= copyin((caddr_t
)uap
->arg
, (caddr_t
)&fbt_struct
,
536 sizeof (fbt_struct
));
542 if (uap
->cmd
== F_WRITEBOOTSTRAP
) {
543 /* First make sure that we are root. Updating the */
544 /* bootstrap on a disk could be a security hole */
551 /* Now lock the vnode and call VOP_IOCTL to handle the I/O: */
553 vp
= (struct vnode
*)fp
->f_data
;
554 if (vp
->v_tag
!= VT_HFS
) {
557 VOP_LOCK(vp
,LK_EXCLUSIVE
,p
);
558 error
= VOP_IOCTL(vp
, (uap
->cmd
== F_WRITEBOOTSTRAP
) ? 3 : 2, &fbt_struct
, 0, fp
->f_cred
, p
);
565 if (fp
->f_type
!= DTYPE_VNODE
)
567 vp
= (struct vnode
*)fp
->f_data
;
568 VOP_LOCK(vp
, LK_EXCLUSIVE
, p
);
569 if (VOP_OFFTOBLK(vp
, fp
->f_offset
, &lbn
))
570 panic("fcntl LOG2PHYS OFFTOBLK");
571 if (VOP_BLKTOOFF(vp
, lbn
, &offset
))
572 panic("fcntl LOG2PHYS BLKTOOFF1");
573 error
= VOP_BMAP(vp
, lbn
, &devvp
, &bn
, 0);
574 VOP_DEVBLOCKSIZE(devvp
, &devBlockSize
);
575 VOP_UNLOCK(vp
, 0, p
);
577 l2p_struct
.l2p_flags
= 0; /* for now */
578 l2p_struct
.l2p_contigbytes
= 0; /* for now */
579 l2p_struct
.l2p_devoffset
= bn
* devBlockSize
;
580 l2p_struct
.l2p_devoffset
+= fp
->f_offset
- offset
;
581 error
= copyout((caddr_t
)&l2p_struct
,
583 sizeof (l2p_struct
));
595 * Common code for dup, dup2, and fcntl(F_DUPFD).
598 finishdup(fdp
, old
, new, retval
)
599 register struct filedesc
*fdp
;
600 register int old
, new;
603 register struct file
*fp
;
605 if ((fp
= fdp
->fd_ofiles
[old
]) == NULL
||
606 (fdp
->fd_ofileflags
[old
] & UF_RESERVED
)) {
610 fdp
->fd_ofiles
[new] = fp
;
611 fdp
->fd_ofileflags
[new] = fdp
->fd_ofileflags
[old
] &~ UF_EXCLOSE
;
613 if (new > fdp
->fd_lastfile
)
614 fdp
->fd_lastfile
= new;
620 * Close a file descriptor.
627 close(p
, uap
, retval
)
629 struct close_args
*uap
;
633 register struct filedesc
*fdp
= p
->p_fd
;
634 register struct file
*fp
;
636 if ((u_int
)fd
>= fdp
->fd_nfiles
||
637 (fp
= fdp
->fd_ofiles
[fd
]) == NULL
||
638 (fdp
->fd_ofileflags
[fd
] & UF_RESERVED
))
641 return (closef(fp
, p
));
645 * Return status information about a file descriptor.
653 fstat(p
, uap
, retval
)
655 register struct fstat_args
*uap
;
659 register struct filedesc
*fdp
= p
->p_fd
;
660 register struct file
*fp
;
664 if ((u_int
)fd
>= fdp
->fd_nfiles
||
665 (fp
= fdp
->fd_ofiles
[fd
]) == NULL
||
666 (fdp
->fd_ofileflags
[fd
] & UF_RESERVED
))
668 switch (fp
->f_type
) {
671 error
= vn_stat((struct vnode
*)fp
->f_data
, &ub
, p
);
675 error
= soo_stat((struct socket
*)fp
->f_data
, &ub
);
679 error
= pshm_stat((void *)fp
->f_data
, &ub
);
686 error
= copyout((caddr_t
)&ub
, (caddr_t
)uap
->sb
,
693 * Return status information about a file descriptor.
700 ofstat(p
, uap
, retval
)
702 register struct ofstat_args
*uap
;
706 register struct filedesc
*fdp
= p
->p_fd
;
707 register struct file
*fp
;
712 if ((u_int
)fd
>= fdp
->fd_nfiles
||
713 (fp
= fdp
->fd_ofiles
[fd
]) == NULL
||
714 (fdp
->fd_ofileflags
[fd
] & UF_RESERVED
))
716 switch (fp
->f_type
) {
719 error
= vn_stat((struct vnode
*)fp
->f_data
, &ub
, p
);
723 error
= soo_stat((struct socket
*)fp
->f_data
, &ub
);
732 error
= copyout((caddr_t
)&oub
, (caddr_t
)uap
->sb
,
736 #endif /* COMPAT_43 */
739 * Return pathconf information about a file descriptor.
741 struct fpathconf_args
{
746 fpathconf(p
, uap
, retval
)
748 register struct fpathconf_args
*uap
;
752 struct filedesc
*fdp
= p
->p_fd
;
756 if ((u_int
)fd
>= fdp
->fd_nfiles
||
757 (fp
= fdp
->fd_ofiles
[fd
]) == NULL
||
758 (fdp
->fd_ofileflags
[fd
] & UF_RESERVED
))
760 switch (fp
->f_type
) {
763 if (uap
->name
!= _PC_PIPE_BUF
)
769 vp
= (struct vnode
*)fp
->f_data
;
770 return (VOP_PATHCONF(vp
, uap
->name
, retval
));
779 * Allocate a file descriptor for the process.
784 fdalloc(p
, want
, result
)
789 register struct filedesc
*fdp
= p
->p_fd
;
791 int lim
, last
, nfiles
, oldnfiles
;
792 struct file
**newofiles
, **ofiles
;
793 char *newofileflags
, *ofileflags
;
796 * Search for a free descriptor starting at the higher
797 * of want or fd_freefile. If that fails, consider
798 * expanding the ofile array.
800 lim
= min((int)p
->p_rlimit
[RLIMIT_NOFILE
].rlim_cur
, maxfiles
);
802 last
= min(fdp
->fd_nfiles
, lim
);
803 if ((i
= want
) < fdp
->fd_freefile
)
804 i
= fdp
->fd_freefile
;
805 ofiles
= &fdp
->fd_ofiles
[i
];
806 ofileflags
= &fdp
->fd_ofileflags
[i
];
807 for (; i
< last
; i
++) {
808 if (*ofiles
== NULL
&& !(*ofileflags
& UF_RESERVED
)) {
809 *ofileflags
= UF_RESERVED
;
810 if (i
> fdp
->fd_lastfile
)
811 fdp
->fd_lastfile
= i
;
812 if (want
<= fdp
->fd_freefile
)
813 fdp
->fd_freefile
= i
;
817 ofiles
++; ofileflags
++;
821 * No space in current array. Expand?
823 if (fdp
->fd_nfiles
>= lim
)
825 if (fdp
->fd_nfiles
< NDEXTENT
)
828 nfiles
= 2 * fdp
->fd_nfiles
;
832 MALLOC_ZONE(newofiles
, struct file
**,
833 nfiles
* OFILESIZE
, M_OFILETABL
, M_WAITOK
);
834 if (fdp
->fd_nfiles
>= nfiles
) {
835 FREE_ZONE(newofiles
, nfiles
* OFILESIZE
, M_OFILETABL
);
838 newofileflags
= (char *) &newofiles
[nfiles
];
840 * Copy the existing ofile and ofileflags arrays
841 * and zero the new portion of each array.
843 oldnfiles
= fdp
->fd_nfiles
;
844 (void) memcpy(newofiles
, fdp
->fd_ofiles
,
845 oldnfiles
* sizeof *fdp
->fd_ofiles
);
846 (void) memset(&newofiles
[oldnfiles
], 0,
847 (nfiles
- oldnfiles
) * sizeof *fdp
->fd_ofiles
);
849 (void) memcpy(newofileflags
, fdp
->fd_ofileflags
,
850 oldnfiles
* sizeof *fdp
->fd_ofileflags
);
851 (void) memset(&newofileflags
[oldnfiles
], 0,
852 (nfiles
- oldnfiles
) *
853 sizeof *fdp
->fd_ofileflags
);
854 ofiles
= fdp
->fd_ofiles
;
855 fdp
->fd_ofiles
= newofiles
;
856 fdp
->fd_ofileflags
= newofileflags
;
857 fdp
->fd_nfiles
= nfiles
;
858 FREE_ZONE(ofiles
, oldnfiles
* OFILESIZE
, M_OFILETABL
);
864 * Check to see whether n user file descriptors
865 * are available to the process p.
872 register struct filedesc
*fdp
= p
->p_fd
;
873 register struct file
**fpp
;
874 register char *flags
;
877 lim
= min((int)p
->p_rlimit
[RLIMIT_NOFILE
].rlim_cur
, maxfiles
);
878 if ((i
= lim
- fdp
->fd_nfiles
) > 0 && (n
-= i
) <= 0)
880 fpp
= &fdp
->fd_ofiles
[fdp
->fd_freefile
];
881 flags
= &fdp
->fd_ofileflags
[fdp
->fd_freefile
];
882 for (i
= fdp
->fd_nfiles
- fdp
->fd_freefile
; --i
>= 0; fpp
++, flags
++)
883 if (*fpp
== NULL
&& !(*flags
& UF_RESERVED
) && --n
<= 0)
893 _fdrelse(p
->p_fd
, fd
);
897 fdgetf(p
, fd
, resultfp
)
898 register struct proc
*p
;
900 struct file
**resultfp
;
902 register struct filedesc
*fdp
= p
->p_fd
;
905 if ((u_int
)fd
>= fdp
->fd_nfiles
||
906 (fp
= fdp
->fd_ofiles
[fd
]) == NULL
||
907 (fdp
->fd_ofileflags
[fd
] & UF_RESERVED
))
916 * Create a new open file structure and allocate
917 * a file decriptor for the process that refers to it.
920 falloc(p
, resultfp
, resultfd
)
921 register struct proc
*p
;
922 struct file
**resultfp
;
925 register struct file
*fp
, *fq
;
928 if (error
= fdalloc(p
, 0, &i
))
930 if (nfiles
>= maxfiles
) {
935 * Allocate a new file descriptor.
936 * If the process has file descriptor zero open, add to the list
937 * of open files at that point, otherwise put it at the front of
938 * the list of open files.
941 MALLOC_ZONE(fp
, struct file
*, sizeof(struct file
), M_FILE
, M_WAITOK
);
942 bzero(fp
, sizeof(struct file
));
943 if (fq
= p
->p_fd
->fd_ofiles
[0]) {
944 LIST_INSERT_AFTER(fq
, fp
, f_list
);
946 LIST_INSERT_HEAD(&filehead
, fp
, f_list
);
948 p
->p_fd
->fd_ofiles
[i
] = fp
;
950 fp
->f_cred
= p
->p_ucred
;
960 * Free a file structure.
964 register struct file
*fp
;
966 register struct file
*fq
;
969 LIST_REMOVE(fp
, f_list
);
971 if (cred
!= NOCRED
) {
979 FREE_ZONE(fp
, sizeof *fp
, M_FILE
);
986 register struct filedesc
*fdp
= p
->p_fd
;
987 register int i
= fdp
->fd_lastfile
;
988 register struct file
**fpp
= &fdp
->fd_ofiles
[i
];
989 register char *flags
= &fdp
->fd_ofileflags
[i
];
992 if ((*flags
& (UF_RESERVED
|UF_EXCLOSE
)) == UF_EXCLOSE
) {
993 register struct file
*fp
= *fpp
;
995 *fpp
= NULL
; *flags
= 0;
996 if (i
== fdp
->fd_lastfile
&& i
> 0)
1001 *flags
&= ~UF_MAPPED
;
1003 i
--; fpp
--; flags
--;
1008 * Copy a filedesc structure.
1014 register struct filedesc
*newfdp
, *fdp
= p
->p_fd
;
1017 MALLOC_ZONE(newfdp
, struct filedesc
*,
1018 sizeof *newfdp
, M_FILEDESC
, M_WAITOK
);
1019 (void) memcpy(newfdp
, fdp
, sizeof *newfdp
);
1020 VREF(newfdp
->fd_cdir
);
1021 if (newfdp
->fd_rdir
)
1022 VREF(newfdp
->fd_rdir
);
1023 newfdp
->fd_refcnt
= 1;
1026 * If the number of open files fits in the internal arrays
1027 * of the open file structure, use them, otherwise allocate
1028 * additional memory for the number of descriptors currently
1031 if (newfdp
->fd_lastfile
< NDFILE
)
1035 * Compute the smallest multiple of NDEXTENT needed
1036 * for the file descriptors currently in use,
1037 * allowing the table to shrink.
1039 i
= newfdp
->fd_nfiles
;
1040 while (i
> 2 * NDEXTENT
&& i
> newfdp
->fd_lastfile
* 2)
1043 MALLOC_ZONE(newfdp
->fd_ofiles
, struct file
**,
1044 i
* OFILESIZE
, M_OFILETABL
, M_WAITOK
);
1045 newfdp
->fd_ofileflags
= (char *) &newfdp
->fd_ofiles
[i
];
1046 newfdp
->fd_nfiles
= i
;
1047 if (fdp
->fd_nfiles
> 0) {
1048 register struct file
**fpp
;
1049 register char *flags
;
1051 (void) memcpy(newfdp
->fd_ofiles
, fdp
->fd_ofiles
,
1052 i
* sizeof *fdp
->fd_ofiles
);
1053 (void) memcpy(newfdp
->fd_ofileflags
, fdp
->fd_ofileflags
,
1054 i
* sizeof *fdp
->fd_ofileflags
);
1056 fpp
= newfdp
->fd_ofiles
;
1057 flags
= newfdp
->fd_ofileflags
;
1058 for (i
= newfdp
->fd_lastfile
; i
-- >= 0; fpp
++, flags
++)
1059 if (*fpp
!= NULL
&& !(*flags
& UF_RESERVED
)) {
1067 (void) memset(newfdp
->fd_ofiles
, 0, i
* OFILESIZE
);
1073 * Release a filedesc structure.
1079 register struct filedesc
*fdp
;
1080 register struct file
**fpp
;
1083 if ((fdp
= p
->p_fd
) == NULL
)
1085 if (--fdp
->fd_refcnt
> 0)
1088 if (fdp
->fd_nfiles
> 0) {
1089 fpp
= fdp
->fd_ofiles
;
1090 for (i
= fdp
->fd_lastfile
; i
-- >= 0; fpp
++)
1092 (void) closef(*fpp
, p
);
1093 FREE_ZONE(fdp
->fd_ofiles
,
1094 fdp
->fd_nfiles
* OFILESIZE
, M_OFILETABL
);
1096 vrele(fdp
->fd_cdir
);
1098 vrele(fdp
->fd_rdir
);
1099 FREE_ZONE(fdp
, sizeof *fdp
, M_FILEDESC
);
1103 * Internal form of close.
1104 * Decrement reference count on file structure.
1105 * Note: p may be NULL when closing a file
1106 * that was being passed in a message.
1110 register struct file
*fp
;
1111 register struct proc
*p
;
1120 * POSIX record locking dictates that any close releases ALL
1121 * locks owned by this process. This is handled by setting
1122 * a flag in the unlock to free ONLY locks obeying POSIX
1123 * semantics, and not to free BSD-style file locks.
1124 * If the descriptor was in a message, POSIX-style locks
1125 * aren't passed with the descriptor.
1127 if (p
&& (p
->p_flag
& P_ADVLOCK
) && fp
->f_type
== DTYPE_VNODE
) {
1128 lf
.l_whence
= SEEK_SET
;
1131 lf
.l_type
= F_UNLCK
;
1132 vp
= (struct vnode
*)fp
->f_data
;
1133 (void) VOP_ADVLOCK(vp
, (caddr_t
)p
, F_UNLCK
, &lf
, F_POSIX
);
1137 if ((fp
->f_flag
& FHASLOCK
) && fp
->f_type
== DTYPE_VNODE
) {
1138 lf
.l_whence
= SEEK_SET
;
1141 lf
.l_type
= F_UNLCK
;
1142 vp
= (struct vnode
*)fp
->f_data
;
1143 (void) VOP_ADVLOCK(vp
, (caddr_t
)fp
, F_UNLCK
, &lf
, F_FLOCK
);
1146 error
= (*fp
->f_ops
->fo_close
)(fp
, p
);
1154 * Apply an advisory lock on a file descriptor.
1156 * Just attempt to get a record lock of the requested type on
1157 * the entire file (l_whence = SEEK_SET, l_start = 0, l_len = 0).
1165 flock(p
, uap
, retval
)
1167 register struct flock_args
*uap
;
1172 register struct filedesc
*fdp
= p
->p_fd
;
1173 register struct file
*fp
;
1177 if ((u_int
)fd
>= fdp
->fd_nfiles
||
1178 (fp
= fdp
->fd_ofiles
[fd
]) == NULL
||
1179 (fdp
->fd_ofileflags
[fd
] & UF_RESERVED
))
1181 if (fp
->f_type
!= DTYPE_VNODE
)
1182 return (EOPNOTSUPP
);
1183 vp
= (struct vnode
*)fp
->f_data
;
1184 lf
.l_whence
= SEEK_SET
;
1187 if (how
& LOCK_UN
) {
1188 lf
.l_type
= F_UNLCK
;
1189 fp
->f_flag
&= ~FHASLOCK
;
1190 return (VOP_ADVLOCK(vp
, (caddr_t
)fp
, F_UNLCK
, &lf
, F_FLOCK
));
1193 lf
.l_type
= F_WRLCK
;
1194 else if (how
& LOCK_SH
)
1195 lf
.l_type
= F_RDLCK
;
1198 fp
->f_flag
|= FHASLOCK
;
1200 return (VOP_ADVLOCK(vp
, (caddr_t
)fp
, F_SETLK
, &lf
, F_FLOCK
));
1201 return (VOP_ADVLOCK(vp
, (caddr_t
)fp
, F_SETLK
, &lf
, F_FLOCK
|F_WAIT
));
1205 * File Descriptor pseudo-device driver (/dev/fd/).
1207 * Opening minor device N dup()s the file (if any) connected to file
1208 * descriptor N belonging to the calling process. Note that this driver
1209 * consists of only the ``open()'' routine, because all subsequent
1210 * references to this file will be direct to the other driver.
1214 fdopen(dev
, mode
, type
, p
)
1221 * XXX Kludge: set curproc->p_dupfd to contain the value of the
1222 * the file descriptor being sought for duplication. The error
1223 * return ensures that the vnode for this device will be released
1224 * by vn_open. Open will detect this special error and take the
1225 * actions in dupfdopen below. Other callers of vn_open or VOP_OPEN
1226 * will simply report the error.
1228 p
->p_dupfd
= minor(dev
);
1233 * Duplicate the specified descriptor to a free descriptor.
1236 dupfdopen(fdp
, indx
, dfd
, mode
, error
)
1237 register struct filedesc
*fdp
;
1238 register int indx
, dfd
;
1242 register struct file
*wfp
;
1246 * If the to-be-dup'd fd number is greater than the allowed number
1247 * of file descriptors, or the fd to be dup'd has already been
1248 * closed, reject. Note, check for new == old is necessary as
1249 * falloc could allocate an already closed to-be-dup'd descriptor
1250 * as the new descriptor.
1252 fp
= fdp
->fd_ofiles
[indx
];
1253 if ((u_int
)dfd
>= fdp
->fd_nfiles
||
1254 (wfp
= fdp
->fd_ofiles
[dfd
]) == NULL
|| wfp
== fp
||
1255 (fdp
->fd_ofileflags
[dfd
] & UF_RESERVED
))
1259 * There are two cases of interest here.
1261 * For ENODEV simply dup (dfd) to file descriptor
1262 * (indx) and return.
1264 * For ENXIO steal away the file structure from (dfd) and
1265 * store it in (indx). (dfd) is effectively closed by
1268 * Any other error code is just returned.
1273 * Check that the mode the file is being opened for is a
1274 * subset of the mode of the existing descriptor.
1276 if (((mode
& (FREAD
|FWRITE
)) | wfp
->f_flag
) != wfp
->f_flag
)
1279 if (indx
> fdp
->fd_lastfile
)
1280 fdp
->fd_lastfile
= indx
;;
1281 fdp
->fd_ofiles
[indx
] = wfp
;
1282 fdp
->fd_ofileflags
[indx
] = fdp
->fd_ofileflags
[dfd
];
1287 * Steal away the file pointer from dfd, and stuff it into indx.
1289 if (indx
> fdp
->fd_lastfile
)
1290 fdp
->fd_lastfile
= indx
;;
1291 fdp
->fd_ofiles
[indx
] = fdp
->fd_ofiles
[dfd
];
1292 fdp
->fd_ofileflags
[indx
] = fdp
->fd_ofileflags
[dfd
];
1302 /* Reference manipulation routines for the file structure */
1305 fref(struct file
*fp
)
1307 if (++fp
->f_count
<= 0)
1308 panic("fref: f_count");
1309 return ((int)fp
->f_count
);
1313 frele(struct file
*fp
)
1315 if (--fp
->f_count
< 0)
1316 panic("frele: count < 0");
1317 return ((int)fp
->f_count
);
1321 fcount(struct file
*fp
)
1323 return ((int)fp
->f_count
);