* Copyright (c) 1982, 1986, 1989 Regents of the University of California.
* %sccs.include.redist.c%
* @(#)kern_descrip.c 7.20 (Berkeley) %G%
int nofile
= NOFILE
; /* per-process maximum open files */
* System calls on descriptors.
getdtablesize(p
, uap
, retval
)
* Duplicate a file descriptor.
register struct filedesc
*fdp
= p
->p_fd
;
if (uap
->i
&~ 077) { uap
->i
&= 077; return (dup2(p
, uap
, retval
)); }
if ((unsigned)uap
->i
>= fdp
->fd_maxfiles
||
(fp
= OFILE(fdp
, uap
->i
)) == NULL
)
if (error
= ufalloc(fdp
, 0, &fd
))
OFILEFLAGS(fdp
, fd
) = OFILEFLAGS(fdp
, uap
->i
) &~ UF_EXCLOSE
;
if (fd
> fdp
->fd_lastfile
)
* Duplicate a file descriptor to a particular value.
register struct filedesc
*fdp
= p
->p_fd
;
register struct file
*fp
;
if ((unsigned)uap
->i
>= fdp
->fd_maxfiles
||
(fp
= OFILE(fdp
, uap
->i
)) == NULL
||
(unsigned)uap
->j
>= nofile
)
if ((unsigned)uap
->j
>= fdp
->fd_maxfiles
) {
if (error
= ufalloc(fdp
, uap
->j
, &i
))
} else if (OFILE(fdp
, uap
->j
)) {
if (OFILEFLAGS(fdp
, uap
->j
) & UF_MAPPED
)
(void) munmapfd(p
, uap
->j
);
error
= closef(OFILE(fdp
, uap
->j
));
OFILEFLAGS(fdp
, uap
->j
) = OFILEFLAGS(fdp
, uap
->i
) &~ UF_EXCLOSE
;
if (uap
->j
> fdp
->fd_lastfile
)
fdp
->fd_lastfile
= uap
->j
;
* dup2() must succeed even though the close had an error.
* The file control system call.
register struct filedesc
*fdp
= p
->p_fd
;
register struct file
*fp
;
int i
, error
, flags
= F_POSIX
;
if ((unsigned)uap
->fdes
>= fdp
->fd_maxfiles
||
(fp
= OFILE(fdp
, uap
->fdes
)) == NULL
)
pop
= &OFILEFLAGS(fdp
, uap
->fdes
);
if ((unsigned)uap
->arg
>= nofile
)
if (error
= ufalloc(fdp
, uap
->arg
, &i
))
OFILEFLAGS(fdp
, i
) = *pop
&~ UF_EXCLOSE
;
if (i
> fdp
->fd_lastfile
)
*pop
= (*pop
&~ 1) | (uap
->arg
& 1);
*retval
= OFLAGS(fp
->f_flag
);
fp
->f_flag
&= ~FCNTLFLAGS
;
fp
->f_flag
|= FFLAGS(uap
->arg
) & FCNTLFLAGS
;
if (error
= fset(fp
, FNDELAY
, fp
->f_flag
& FNDELAY
))
if (error
= fset(fp
, FASYNC
, fp
->f_flag
& FASYNC
))
(void) fset(fp
, FNDELAY
, 0);
return (fgetown(fp
, retval
));
return (fsetown(fp
, uap
->arg
));
if (fp
->f_type
!= DTYPE_VNODE
)
vp
= (struct vnode
*)fp
->f_data
;
/* Copy in the lock structure */
error
= copyin((caddr_t
)uap
->arg
, (caddr_t
)&fl
, sizeof (fl
));
if (fl
.l_whence
== SEEK_CUR
)
fl
.l_start
+= fp
->f_offset
;
if ((fp
->f_flag
& FREAD
) == 0)
return (VOP_ADVLOCK(vp
, p
, F_SETLK
, &fl
, flags
));
if ((fp
->f_flag
& FWRITE
) == 0)
return (VOP_ADVLOCK(vp
, p
, F_SETLK
, &fl
, flags
));
return (VOP_ADVLOCK(vp
, p
, F_UNLCK
, &fl
, F_POSIX
));
if (fp
->f_type
!= DTYPE_VNODE
)
vp
= (struct vnode
*)fp
->f_data
;
/* Copy in the lock structure */
error
= copyin((caddr_t
)uap
->arg
, (caddr_t
)&fl
, sizeof (fl
));
if (fl
.l_whence
== SEEK_CUR
)
fl
.l_start
+= fp
->f_offset
;
if (error
= VOP_ADVLOCK(vp
, p
, F_GETLK
, &fl
, F_POSIX
))
return (copyout((caddr_t
)&fl
, (caddr_t
)uap
->arg
, sizeof (fl
)));
return (fioctl(fp
, (int)(bit
== FNDELAY
? FIONBIO
: FIOASYNC
),
*valuep
= ((struct socket
*)fp
->f_data
)->so_pgid
;
error
= fioctl(fp
, (int)TIOCGPGRP
, (caddr_t
)valuep
);
if (fp
->f_type
== DTYPE_SOCKET
) {
((struct socket
*)fp
->f_data
)->so_pgid
= value
;
struct proc
*p
= pfind(value
);
value
= p
->p_pgrp
->pg_id
;
return (fioctl(fp
, (int)TIOCSPGRP
, (caddr_t
)&value
));
return ((*fp
->f_ops
->fo_ioctl
)(fp
, cmd
, value
));
* Close a file descriptor.
register struct filedesc
*fdp
= p
->p_fd
;
register struct file
*fp
;
if ((unsigned)uap
->fdes
>= fdp
->fd_maxfiles
||
(fp
= OFILE(fdp
, uap
->fdes
)) == NULL
)
pf
= (u_char
*)&OFILEFLAGS(fdp
, uap
->fdes
);
(void) munmapfd(p
, uap
->fdes
);
OFILE(fdp
, uap
->fdes
) = NULL
;
while (fdp
->fd_lastfile
>= 0 && OFILE(fdp
, fdp
->fd_lastfile
) == NULL
)
* Return status information about a file descriptor.
register struct filedesc
*fdp
= p
->p_fd
;
register struct file
*fp
;
if ((unsigned)uap
->fdes
>= fdp
->fd_maxfiles
||
(fp
= OFILE(fdp
, uap
->fdes
)) == NULL
)
error
= vn_stat((struct vnode
*)fp
->f_data
, &ub
);
error
= soo_stat((struct socket
*)fp
->f_data
, &ub
);
error
= copyout((caddr_t
)&ub
, (caddr_t
)uap
->sb
, sizeof (ub
));
* Allocate a user file descriptor.
int fdexpand
, fdreexpand
;
ufalloc(fdp
, want
, result
)
register struct filedesc
*fdp
;
int last
, osize
, ofiles
, nfiles
;
last
= (fdp
->fd_maxfiles
< nofile
) ? fdp
->fd_maxfiles
: nofile
;
for (; want
< last
; want
++) {
if (OFILE(fdp
, want
) == NULL
) {
OFILEFLAGS(fdp
, want
) = 0;
if (want
> fdp
->fd_lastfile
)
if (fdp
->fd_maxfiles
>= nofile
)
if (fdp
->fd_maxfiles
== NDFILE
) {
fdp
->fd_moreofiles
= (struct file
**)
malloc(NDEXTENT
* OFILESIZE
, M_FILE
, M_WAITOK
);
(char *)&fdp
->fd_moreofiles
[NDEXTENT
];
bzero((char *)fdp
->fd_moreofiles
, NDEXTENT
* OFILESIZE
);
fdp
->fd_maxfiles
= NDFILE
+ NDEXTENT
;
ofiles
= fdp
->fd_maxfiles
- NDFILE
;
osize
= ofiles
* OFILESIZE
;
nfiles
= (2 * osize
) / OFILESIZE
;
newofile
= (struct file
**) malloc(2 * osize
, M_FILE
, M_WAITOK
);
newofileflags
= (char *)&newofile
[nfiles
];
bzero((char *)newofile
, 2 * osize
);
bcopy((char *)fdp
->fd_moreofiles
, (char *)newofile
,
sizeof(struct file
*) * ofiles
);
bcopy((char *)fdp
->fd_moreofileflags
, (char *)newofileflags
,
free(fdp
->fd_moreofiles
, M_FILE
);
fdp
->fd_moreofiles
= newofile
;
fdp
->fd_moreofileflags
= newofileflags
;
fdp
->fd_maxfiles
= NDFILE
+ nfiles
;
* Check to see if any user file descriptors are available.
register struct filedesc
*fdp
;
avail
= nofile
- fdp
->fd_maxfiles
;
for (i
= 0; i
< fdp
->fd_maxfiles
; i
++)
if (OFILE(fdp
, i
) == NULL
)
* Allocate a user file descriptor
* Initialize the descriptor
* to point at the file structure.
falloc(p
, resultfp
, resultfd
)
register struct file
*fp
;
if (error
= ufalloc(p
->p_fd
, 0, &i
))
for (fp
= lastf
; fp
< fileNFILE
; fp
++)
for (fp
= file
; fp
< lastf
; fp
++)
* Duplicate a filedesc structure.
register struct filedesc
*fdp
;
register struct filedesc
*newfdp
;
register struct file
*fp
;
MALLOC(newfdp
, struct filedesc
*, sizeof(*fdp
), M_FILE
, M_WAITOK
);
bcopy((char *)fdp
, (char *)newfdp
, sizeof(*fdp
));
newfdp
->fd_maxfiles
= NDFILE
;
if (fdp
->fd_lastfile
> NDFILE
&&
ufalloc(newfdp
, fdp
->fd_lastfile
, &j
)) {
log(LOG_ERR
, "fddup: lost file descriptor(s)");
last
= newfdp
->fd_maxfiles
;
for (i
= 0; i
<= last
; i
++) {
OFILEFLAGS(newfdp
, i
) = OFILEFLAGS(fdp
, i
);
* Release a filedesc structure.
register struct filedesc
*fdp
;
if (fdp
->fd_refcnt
> 1) {
for (i
= 0; i
<= fdp
->fd_lastfile
; i
++) {
if (fdp
->fd_maxfiles
> NDFILE
)
FREE(fdp
->fd_moreofiles
, M_FILE
);
* Internal form of close.
* Decrement reference count on file structure.
register struct file
*fp
;
struct proc
*p
= u
.u_procp
; /* XXX */
* POSIX record locking dictates that any close releases ALL
* locks owned by this process. This is handled by setting
* a flag in the unlock to free ONLY locks obeying POSIX
* semantics, and not to free BSD-style file locks.
if (fp
->f_type
== DTYPE_VNODE
) {
vp
= (struct vnode
*)fp
->f_data
;
(void) VOP_ADVLOCK(vp
, p
, F_UNLCK
, &lf
, F_POSIX
);
panic("closef: count < 1");
if (fp
->f_type
== DTYPE_VNODE
)
(void) VOP_ADVLOCK(vp
, fp
, F_UNLCK
, &lf
, F_FLOCK
);
error
= (*fp
->f_ops
->fo_close
)(fp
);
* Apply an advisory lock on a file descriptor.
* Just attempt to get a record lock of the requested type on
* the entire file (l_whence = SEEK_SET, l_start = 0, l_len = 0).
register struct filedesc
*fdp
= p
->p_fd
;
register struct file
*fp
;
if ((unsigned)uap
->fdes
>= fdp
->fd_maxfiles
||
(fp
= OFILE(fdp
, uap
->fdes
)) == NULL
)
if (fp
->f_type
!= DTYPE_VNODE
)
vp
= (struct vnode
*)fp
->f_data
;
if (uap
->how
& LOCK_UN
) {
return (VOP_ADVLOCK(vp
, fp
, F_UNLCK
, &lf
, F_FLOCK
));
else if (uap
->how
& LOCK_SH
)
return (VOP_ADVLOCK(vp
, fp
, F_SETLK
, &lf
, F_FLOCK
));
return (VOP_ADVLOCK(vp
, fp
, F_SETLK
, &lf
, F_FLOCK
|F_WAIT
));
* File Descriptor pseudo-device driver (/dev/fd/).
* Opening minor device N dup()s the file (if any) connected to file
* descriptor N belonging to the calling process. Note that this driver
* consists of only the ``open()'' routine, because all subsequent
* references to this file will be direct to the other driver.
struct proc
*p
= u
.u_procp
; /* XXX */
* XXX Kludge: set p->p_dupfd to contain the value of the
* the file descriptor being sought for duplication. The error
* return ensures that the vnode for this device will be released
* by vn_open. Open will detect this special error and take the
* actions in dupfdopen below. Other callers of vn_open or VOP_OPEN
* will simply report the error.
* Duplicate the specified descriptor to a free descriptor.
dupfdopen(fdp
, indx
, dfd
, mode
)
register struct filedesc
*fdp
;
register struct file
*wfp
;
* If the to-be-dup'd fd number is greater than the allowed number
* of file descriptors, or the fd to be dup'd has already been
* closed, reject. Note, check for new == old is necessary as
* falloc could allocate an already closed to-be-dup'd descriptor
if ((u_int
)dfd
>= fdp
->fd_maxfiles
|| (wfp
= OFILE(fdp
, dfd
)) == NULL
||
* Check that the mode the file is being opened for is a subset
* of the mode of the existing descriptor.
if (((mode
& (FREAD
|FWRITE
)) | wfp
->f_flag
) != wfp
->f_flag
)
OFILEFLAGS(fdp
, indx
) = OFILEFLAGS(fdp
, dfd
);
if (indx
> fdp
->fd_lastfile
)
#if defined(vax) || defined(tahoe)
* Brain dead routines to compensate for limitations in PCC
return (&fdp
->fd_ofile
[indx
]);
return (&fdp
->fd_moreofiles
[indx
- NDFILE
]);
ofileflagsfunc(fdp
, indx
)
return (&fdp
->fd_ofileflags
[indx
]);
return (&fdp
->fd_moreofileflags
[indx
- NDFILE
]);