* Copyright (c) 1982, 1986, 1989 Regents of the University of California.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* @(#)sys_generic.c 7.30 (Berkeley) 5/30/91
* PATCHES MAGIC LEVEL PATCH THAT GOT US HERE
* -------------------- ----- ----------------------
* CURRENT PATCH LEVEL: 1 00061
* -------------------- ----- ----------------------
* 11 Dec 92 Williams Jolitz Fixed tty handling
register struct read_args
*uap
;
register struct file
*fp
;
register struct filedesc
*fdp
= p
->p_fd
;
if (((unsigned)uap
->fdes
) >= fdp
->fd_nfiles
||
(fp
= fdp
->fd_ofiles
[uap
->fdes
]) == NULL
||
(fp
->f_flag
& FREAD
) == 0)
aiov
.iov_base
= (caddr_t
)uap
->cbuf
;
aiov
.iov_len
= uap
->count
;
auio
.uio_resid
= uap
->count
;
auio
.uio_segflg
= UIO_USERSPACE
;
* if tracing, save a copy of iovec
if (KTRPOINT(p
, KTR_GENIO
))
if (error
= (*fp
->f_ops
->fo_read
)(fp
, &auio
, fp
->f_cred
))
if (auio
.uio_resid
!= cnt
&& (error
== ERESTART
||
error
== EINTR
|| error
== EWOULDBLOCK
))
if (KTRPOINT(p
, KTR_GENIO
) && error
== 0)
ktrgenio(p
->p_tracep
, uap
->fdes
, UIO_READ
, &ktriov
, cnt
, error
);
* Scatter read system call.
register struct readv_args
*uap
;
register struct file
*fp
;
register struct filedesc
*fdp
= p
->p_fd
;
register struct iovec
*iov
;
struct iovec aiov
[UIO_SMALLIOV
];
struct iovec
*ktriov
= NULL
;
if (((unsigned)uap
->fdes
) >= fdp
->fd_nfiles
||
(fp
= fdp
->fd_ofiles
[uap
->fdes
]) == NULL
||
(fp
->f_flag
& FREAD
) == 0)
/* note: can't use iovlen until iovcnt is validated */
iovlen
= uap
->iovcnt
* sizeof (struct iovec
);
if (uap
->iovcnt
> UIO_SMALLIOV
) {
if (uap
->iovcnt
> UIO_MAXIOV
)
MALLOC(iov
, struct iovec
*, iovlen
, M_IOV
, M_WAITOK
);
auio
.uio_iovcnt
= uap
->iovcnt
;
auio
.uio_segflg
= UIO_USERSPACE
;
if (error
= copyin((caddr_t
)uap
->iovp
, (caddr_t
)iov
, iovlen
))
for (i
= 0; i
< uap
->iovcnt
; i
++) {
auio
.uio_resid
+= iov
->iov_len
;
if (auio
.uio_resid
< 0) {
* if tracing, save a copy of iovec
if (KTRPOINT(p
, KTR_GENIO
)) {
MALLOC(ktriov
, struct iovec
*, iovlen
, M_TEMP
, M_WAITOK
);
bcopy((caddr_t
)auio
.uio_iov
, (caddr_t
)ktriov
, iovlen
);
if (error
= (*fp
->f_ops
->fo_read
)(fp
, &auio
, fp
->f_cred
))
if (auio
.uio_resid
!= cnt
&& (error
== ERESTART
||
error
== EINTR
|| error
== EWOULDBLOCK
))
ktrgenio(p
->p_tracep
, uap
->fdes
, UIO_READ
, ktriov
,
if (uap
->iovcnt
> UIO_SMALLIOV
)
register struct write_args
*uap
;
register struct file
*fp
;
register struct filedesc
*fdp
= p
->p_fd
;
if (((unsigned)uap
->fdes
) >= fdp
->fd_nfiles
||
(fp
= fdp
->fd_ofiles
[uap
->fdes
]) == NULL
||
(fp
->f_flag
& FWRITE
) == 0)
aiov
.iov_base
= (caddr_t
)uap
->cbuf
;
aiov
.iov_len
= uap
->count
;
auio
.uio_resid
= uap
->count
;
auio
.uio_segflg
= UIO_USERSPACE
;
* if tracing, save a copy of iovec
if (KTRPOINT(p
, KTR_GENIO
))
if (error
= (*fp
->f_ops
->fo_write
)(fp
, &auio
, fp
->f_cred
)) {
if (auio
.uio_resid
!= cnt
&& (error
== ERESTART
||
error
== EINTR
|| error
== EWOULDBLOCK
))
if (KTRPOINT(p
, KTR_GENIO
) && error
== 0)
ktrgenio(p
->p_tracep
, uap
->fdes
, UIO_WRITE
,
* Gather write system call
register struct writev_args
*uap
;
register struct file
*fp
;
register struct filedesc
*fdp
= p
->p_fd
;
register struct iovec
*iov
;
struct iovec aiov
[UIO_SMALLIOV
];
struct iovec
*ktriov
= NULL
;
if (((unsigned)uap
->fdes
) >= fdp
->fd_nfiles
||
(fp
= fdp
->fd_ofiles
[uap
->fdes
]) == NULL
||
(fp
->f_flag
& FWRITE
) == 0)
/* note: can't use iovlen until iovcnt is validated */
iovlen
= uap
->iovcnt
* sizeof (struct iovec
);
if (uap
->iovcnt
> UIO_SMALLIOV
) {
if (uap
->iovcnt
> UIO_MAXIOV
)
MALLOC(iov
, struct iovec
*, iovlen
, M_IOV
, M_WAITOK
);
auio
.uio_iovcnt
= uap
->iovcnt
;
auio
.uio_segflg
= UIO_USERSPACE
;
if (error
= copyin((caddr_t
)uap
->iovp
, (caddr_t
)iov
, iovlen
))
for (i
= 0; i
< uap
->iovcnt
; i
++) {
auio
.uio_resid
+= iov
->iov_len
;
if (auio
.uio_resid
< 0) {
* if tracing, save a copy of iovec
if (KTRPOINT(p
, KTR_GENIO
)) {
MALLOC(ktriov
, struct iovec
*, iovlen
, M_TEMP
, M_WAITOK
);
bcopy((caddr_t
)auio
.uio_iov
, (caddr_t
)ktriov
, iovlen
);
if (error
= (*fp
->f_ops
->fo_write
)(fp
, &auio
, fp
->f_cred
)) {
if (auio
.uio_resid
!= cnt
&& (error
== ERESTART
||
error
== EINTR
|| error
== EWOULDBLOCK
))
ktrgenio(p
->p_tracep
, uap
->fdes
, UIO_WRITE
,
if (uap
->iovcnt
> UIO_SMALLIOV
)
register struct ioctl_args
*uap
;
register struct file
*fp
;
register struct filedesc
*fdp
= p
->p_fd
;
if ((unsigned)uap
->fdes
>= fdp
->fd_nfiles
||
(fp
= fdp
->fd_ofiles
[uap
->fdes
]) == NULL
)
if ((fp
->f_flag
& (FREAD
|FWRITE
)) == 0)
fdp
->fd_ofileflags
[uap
->fdes
] |= UF_EXCLOSE
;
fdp
->fd_ofileflags
[uap
->fdes
] &= ~UF_EXCLOSE
;
* Interpret high order word to find
* amount of data to be copied to/from the
if (size
> sizeof (stkbuf
)) {
memp
= (caddr_t
)malloc((u_long
)size
, M_IOCTLOPS
, M_WAITOK
);
error
= copyin(uap
->cmarg
, data
, (u_int
)size
);
*(caddr_t
*)data
= uap
->cmarg
;
} else if ((com
&IOC_OUT
) && size
)
* Zero the buffer so the user always
* gets back something deterministic.
*(caddr_t
*)data
= uap
->cmarg
;
fp
->f_flag
&= ~FNONBLOCK
;
error
= (*fp
->f_ops
->fo_ioctl
)(fp
, FIONBIO
, (caddr_t
)&tmp
, p
);
error
= (*fp
->f_ops
->fo_ioctl
)(fp
, FIOASYNC
, (caddr_t
)&tmp
, p
);
if (fp
->f_type
== DTYPE_SOCKET
) {
((struct socket
*)fp
->f_data
)->so_pgid
= tmp
;
struct proc
*p1
= pfind(tmp
);
error
= (*fp
->f_ops
->fo_ioctl
)
(fp
, (int)TIOCSPGRP
, (caddr_t
)&tmp
, p
);
if (fp
->f_type
== DTYPE_SOCKET
) {
*(int *)data
= ((struct socket
*)fp
->f_data
)->so_pgid
;
error
= (*fp
->f_ops
->fo_ioctl
)(fp
, (int)TIOCGPGRP
, data
, p
);
*(int *)data
= -*(int *)data
;
error
= (*fp
->f_ops
->fo_ioctl
)(fp
, com
, data
, p
);
* Copy any data to user, size was
* already set and checked above.
if (error
== 0 && (com
&IOC_OUT
) && size
)
error
= copyout(data
, uap
->cmarg
, (u_int
)size
);
register struct select_args
*uap
;
fd_set ibits
[3], obits
[3];
int s
, ncoll
, error
= 0, timo
;
bzero((caddr_t
)ibits
, sizeof(ibits
));
bzero((caddr_t
)obits
, sizeof(obits
));
if (uap
->nd
> p
->p_fd
->fd_nfiles
)
uap
->nd
= p
->p_fd
->fd_nfiles
; /* forgiving; slightly wrong */
ni
= howmany(uap
->nd
, NFDBITS
);
#define getbits(name, x) \
error = copyin((caddr_t)uap->name, (caddr_t)&ibits[x], \
(unsigned)(ni * sizeof(fd_mask))); \
error
= copyin((caddr_t
)uap
->tv
, (caddr_t
)&atv
,
s
= splhigh(); timevaladd(&atv
, &time
); splx(s
);
error
= selscan(p
, ibits
, obits
, uap
->nd
, retval
);
/* this should be timercmp(&time, &atv, >=) */
if (uap
->tv
&& (time
.tv_sec
> atv
.tv_sec
||
time
.tv_sec
== atv
.tv_sec
&& time
.tv_usec
>= atv
.tv_usec
)) {
if ((p
->p_flag
& SSEL
) == 0 || nselcoll
!= ncoll
) {
error
= tsleep((caddr_t
)&selwait
, PSOCK
| PCATCH
, "select", timo
);
/* select is not restarted after signals... */
if (error
== EWOULDBLOCK
)
#define putbits(name, x) \
int error2 = copyout((caddr_t)&obits[x], (caddr_t)uap->name, \
(unsigned)(ni * sizeof(fd_mask))); \
selscan(struct proc
*p
, fd_set
*ibits
, fd_set
*obits
, int nfd
, int *retval
)
register struct filedesc
*fdp
= p
->p_fd
;
register int which
, i
, j
;
for (which
= 0; which
< 3; which
++) {
for (i
= 0; i
< nfd
; i
+= NFDBITS
) {
bits
= ibits
[which
].fds_bits
[i
/NFDBITS
];
while ((j
= ffs(bits
)) && i
+ --j
< nfd
) {
fp
= fdp
->fd_ofiles
[i
+ j
];
if ((*fp
->f_ops
->fo_select
)(fp
, flag
, p
)) {
FD_SET(i
+ j
, &obits
[which
]);
seltrue(dev_t dev
, int which
, struct proc
*p
)
selwakeup(pid_t pid
, int coll
)
wakeup((caddr_t
)&selwait
);
if (pid
&& (p
= pfind(pid
))) {
if (p
->p_wchan
== (caddr_t
)&selwait
) {
} else if (p
->p_flag
& SSEL
)