* Copyright (c) 1982, 1986, 1989 Regents of the University of California.
* Redistribution and use in source and binary forms are permitted
* provided that the above copyright notice and this paragraph are
* duplicated in all such forms and that any documentation,
* advertising materials, and other materials related to such
* distribution and use acknowledge that the software was developed
* by the University of California, Berkeley. The name of the
* University may not be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
* @(#)sys_generic.c 7.12 (Berkeley) %G%
} *uap
= (struct a
*)u
.u_ap
;
register struct file
*fp
;
if (((unsigned)uap
->fdes
) >= NOFILE
||
(fp
= u
.u_ofile
[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(u
.u_procp
, KTR_GENIO
))
if (setjmp(&u
.u_qsave
)) {
if (auio
.uio_resid
== cnt
) {
if ((u
.u_sigintr
& sigmask(u
.u_procp
->p_cursig
)) != 0)
error
= (*fp
->f_ops
->fo_read
)(fp
, &auio
, fp
->f_cred
);
if (KTRPOINT(u
.u_procp
, KTR_GENIO
))
ktrgenio(u
.u_procp
->p_tracep
, uap
->fdes
, UIO_READ
, &ktriov
, cnt
);
} *uap
= (struct a
*)u
.u_ap
;
register struct file
*fp
;
register struct iovec
*iov
;
struct iovec aiov
[UIO_SMALLIOV
];
struct iovec
*ktriov
= NULL
;
if (((unsigned)uap
->fdes
) >= NOFILE
||
(fp
= u
.u_ofile
[uap
->fdes
]) == NULL
||
(fp
->f_flag
& FREAD
) == 0)
if (uap
->iovcnt
> UIO_SMALLIOV
) {
if (uap
->iovcnt
> UIO_MAXIOV
)
MALLOC(iov
, struct iovec
*,
sizeof(struct iovec
) * uap
->iovcnt
, M_IOV
, M_WAITOK
);
auio
.uio_iovcnt
= uap
->iovcnt
;
auio
.uio_segflg
= UIO_USERSPACE
;
if (error
= copyin((caddr_t
)uap
->iovp
, (caddr_t
)iov
,
uap
->iovcnt
* sizeof (struct iovec
)))
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(u
.u_procp
, KTR_GENIO
)) {
int iovlen
= auio
.uio_iovcnt
* sizeof (struct iovec
);
MALLOC(ktriov
, struct iovec
*, iovlen
, M_TEMP
, M_WAITOK
);
bcopy((caddr_t
)auio
.uio_iov
, (caddr_t
)ktriov
, iovlen
);
if (setjmp(&u
.u_qsave
)) {
if (auio
.uio_resid
== cnt
) {
if ((u
.u_sigintr
& sigmask(u
.u_procp
->p_cursig
)) != 0)
error
= (*fp
->f_ops
->fo_read
)(fp
, &auio
, fp
->f_cred
);
ktrgenio(u
.u_procp
->p_tracep
, uap
->fdes
, UIO_READ
, ktriov
, cnt
);
if (uap
->iovcnt
> UIO_SMALLIOV
)
} *uap
= (struct a
*)u
.u_ap
;
register struct file
*fp
;
if (((unsigned)uap
->fdes
) >= NOFILE
||
(fp
= u
.u_ofile
[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(u
.u_procp
, KTR_GENIO
))
if (setjmp(&u
.u_qsave
)) {
if (auio
.uio_resid
== cnt
) {
if ((u
.u_sigintr
& sigmask(u
.u_procp
->p_cursig
)) != 0)
error
= (*fp
->f_ops
->fo_write
)(fp
, &auio
, fp
->f_cred
);
if (KTRPOINT(u
.u_procp
, KTR_GENIO
))
ktrgenio(u
.u_procp
->p_tracep
, uap
->fdes
, UIO_WRITE
,
} *uap
= (struct a
*)u
.u_ap
;
register struct file
*fp
;
register struct iovec
*iov
;
struct iovec aiov
[UIO_SMALLIOV
];
struct iovec
*ktriov
= NULL
;
if (((unsigned)uap
->fdes
) >= NOFILE
||
(fp
= u
.u_ofile
[uap
->fdes
]) == NULL
||
(fp
->f_flag
& FWRITE
) == 0)
if (uap
->iovcnt
> UIO_SMALLIOV
) {
if (uap
->iovcnt
> UIO_MAXIOV
)
MALLOC(iov
, struct iovec
*,
sizeof(struct iovec
) * uap
->iovcnt
, M_IOV
, M_WAITOK
);
auio
.uio_iovcnt
= uap
->iovcnt
;
auio
.uio_segflg
= UIO_USERSPACE
;
if (error
= copyin((caddr_t
)uap
->iovp
, (caddr_t
)iov
,
uap
->iovcnt
* sizeof (struct iovec
)))
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(u
.u_procp
, KTR_GENIO
)) {
int iovlen
= auio
.uio_iovcnt
* sizeof (struct iovec
);
MALLOC(ktriov
, struct iovec
*, iovlen
, M_TEMP
, M_WAITOK
);
bcopy((caddr_t
)auio
.uio_iov
, (caddr_t
)ktriov
, iovlen
);
if (setjmp(&u
.u_qsave
)) {
if (auio
.uio_resid
== cnt
) {
if ((u
.u_sigintr
& sigmask(u
.u_procp
->p_cursig
)) != 0)
error
= (*fp
->f_ops
->fo_write
)(fp
, &auio
, fp
->f_cred
);
ktrgenio(u
.u_procp
->p_tracep
, uap
->fdes
, UIO_WRITE
,
if (uap
->iovcnt
> UIO_SMALLIOV
)
register struct file
*fp
;
} *uap
= (struct a
*)u
.u_ap
;
if ((unsigned)uap
->fdes
>= NOFILE
||
(fp
= u
.u_ofile
[uap
->fdes
]) == NULL
)
if ((fp
->f_flag
& (FREAD
|FWRITE
)) == 0) {
u
.u_pofile
[uap
->fdes
] |= UF_EXCLOSE
;
u
.u_pofile
[uap
->fdes
] &= ~UF_EXCLOSE
;
* Interpret high order word to find
* amount of data to be copied to/from the
if (size
> IOCPARM_MAX
) {
if (size
> sizeof (stkbuf
)) {
memp
= (caddr_t
)malloc((u_long
)IOCPARM_LEN(com
), M_IOCTLOPS
,
u
.u_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
;
u
.u_error
= fset(fp
, FNDELAY
, *(int *)data
);
u
.u_error
= fset(fp
, FASYNC
, *(int *)data
);
u
.u_error
= fsetown(fp
, *(int *)data
);
u
.u_error
= fgetown(fp
, (int *)data
);
u
.u_error
= (*fp
->f_ops
->fo_ioctl
)(fp
, com
, data
);
* Copy any data to user, size was
* already set and checked above.
if (u
.u_error
== 0 && (com
&IOC_OUT
) && size
)
u
.u_error
= copyout(data
, uap
->cmarg
, (u_int
)size
);
} *uap
= (struct uap
*)u
.u_ap
;
fd_set ibits
[3], obits
[3];
bzero((caddr_t
)ibits
, sizeof(ibits
));
bzero((caddr_t
)obits
, sizeof(obits
));
uap
->nd
= NOFILE
; /* forgiving, if slightly wrong */
ni
= howmany(uap
->nd
, NFDBITS
);
#define getbits(name, x) \
u.u_error = copyin((caddr_t)uap->name, (caddr_t)&ibits[x], \
(unsigned)(ni * sizeof(fd_mask))); \
u
.u_error
= copyin((caddr_t
)uap
->tv
, (caddr_t
)&atv
,
s
= splhigh(); timevaladd(&atv
, &time
); splx(s
);
u
.u_procp
->p_flag
|= SSEL
;
u
.u_r
.r_val1
= selscan(ibits
, obits
, uap
->nd
);
if (u
.u_error
|| u
.u_r
.r_val1
)
/* 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 ((u
.u_procp
->p_flag
& SSEL
) == 0 || nselcoll
!= ncoll
) {
u
.u_procp
->p_flag
&= ~SSEL
;
if (setjmp(&u
.u_qsave
)) {
untimeout(unselect
, (caddr_t
)u
.u_procp
);
timeout(unselect
, (caddr_t
)u
.u_procp
, hzto(&atv
));
sleep((caddr_t
)&selwait
, PZERO
+1);
untimeout(unselect
, (caddr_t
)u
.u_procp
);
u
.u_procp
->p_flag
&= ~SSEL
;
#define putbits(name, x) \
int error = copyout((caddr_t)&obits[x], (caddr_t)uap->name, \
(unsigned)(ni * sizeof(fd_mask))); \
register int s
= splhigh();
selscan(ibits
, obits
, nfd
)
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
) {
if ((*fp
->f_ops
->fo_select
)(fp
, flag
)) {
FD_SET(i
+ j
, &obits
[which
]);
wakeup((caddr_t
)&selwait
);
if (p
->p_wchan
== (caddr_t
)&selwait
) {
} else if (p
->p_flag
& SSEL
)