#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: kern_select_50.c,v 1.4 2023/07/28 18:19:00 christos Exp $");
#if defined(_KERNEL_OPT)
#include "opt_compat_netbsd.h"
#endif
#include <sys/param.h>
#include <sys/event.h>
#include <sys/poll.h>
#include <sys/select.h>
#include <sys/time.h>
#include <sys/syscall.h>
#include <sys/syscallvar.h>
#include <sys/syscallargs.h>
#include <compat/sys/event.h>
#include <compat/sys/time.h>
#include <compat/common/compat_mod.h>
static const struct syscall_package kern_select_50_syscalls[] = {
{ SYS_compat_50_kevent, 0, (sy_call_t *)compat_50_sys_kevent },
{ SYS_compat_50_select, 0, (sy_call_t *)compat_50_sys_select },
{ SYS_compat_50_pselect, 0, (sy_call_t *)compat_50_sys_pselect },
{ SYS_compat_50_pollts, 0, (sy_call_t *)compat_50_sys_pollts },
{ 0, 0, NULL }
};
static int
compat_50_kevent_fetch_timeout(const void *src, void *dest, size_t length)
{
struct timespec50 ts50;
int error;
KASSERT(length == sizeof(struct timespec));
error = copyin(src, &ts50, sizeof(ts50));
if (error)
return error;
timespec50_to_timespec(&ts50, (struct timespec *)dest);
return 0;
}
int
compat_50_sys_kevent(struct lwp *l, const struct compat_50_sys_kevent_args *uap,
register_t *retval)
{
static const struct kevent_ops compat_50_kevent_ops = {
.keo_private = NULL,
.keo_fetch_timeout = compat_50_kevent_fetch_timeout,
.keo_fetch_changes = compat_100___kevent50_fetch_changes,
.keo_put_events = compat_100___kevent50_put_events,
};
return kevent1(retval, SCARG(uap, fd),
(const struct kevent *)(const void *)SCARG(uap, changelist), SCARG(uap, nchanges),
(struct kevent *)(void *)SCARG(uap, eventlist), SCARG(uap, nevents),
(const struct timespec *)(const void *)SCARG(uap, timeout),
&compat_50_kevent_ops);
}
int
compat_50_sys_select(struct lwp *l,
const struct compat_50_sys_select_args *uap, register_t *retval)
{
struct timespec ats, *ts = NULL;
struct timeval50 atv50;
int error;
if (SCARG(uap, tv)) {
error = copyin(SCARG(uap, tv), (void *)&atv50, sizeof(atv50));
if (error)
return error;
if (atv50.tv_usec < 0 || atv50.tv_usec >= 1000000)
return EINVAL;
ats.tv_sec = atv50.tv_sec;
ats.tv_nsec = atv50.tv_usec * 1000;
ts = &ats;
}
return selcommon(retval, SCARG(uap, nd), SCARG(uap, in),
SCARG(uap, ou), SCARG(uap, ex), ts, NULL);
}
int
compat_50_sys_pselect(struct lwp *l,
const struct compat_50_sys_pselect_args *uap, register_t *retval)
{
struct timespec50 ats50;
struct timespec ats, *ts = NULL;
sigset_t amask, *mask = NULL;
int error;
if (SCARG(uap, ts)) {
error = copyin(SCARG(uap, ts), &ats50, sizeof(ats50));
if (error)
return error;
timespec50_to_timespec(&ats50, &ats);
ts = &ats;
}
if (SCARG(uap, mask) != NULL) {
error = copyin(SCARG(uap, mask), &amask, sizeof(amask));
if (error)
return error;
mask = &amask;
}
return selcommon(retval, SCARG(uap, nd), SCARG(uap, in),
SCARG(uap, ou), SCARG(uap, ex), ts, mask);
}
int
compat_50_sys_pollts(struct lwp *l, const struct compat_50_sys_pollts_args *uap,
register_t *retval)
{
struct timespec ats, *ts = NULL;
struct timespec50 ats50;
sigset_t amask, *mask = NULL;
int error;
if (SCARG(uap, ts)) {
error = copyin(SCARG(uap, ts), &ats50, sizeof(ats50));
if (error)
return error;
timespec50_to_timespec(&ats50, &ats);
ts = &ats;
}
if (SCARG(uap, mask)) {
error = copyin(SCARG(uap, mask), &amask, sizeof(amask));
if (error)
return error;
mask = &amask;
}
return pollcommon(retval, SCARG(uap, fds), SCARG(uap, nfds), ts, mask);
}
int
kern_select_50_init(void)
{
return syscall_establish(NULL, kern_select_50_syscalls);
}
int
kern_select_50_fini(void)
{
return syscall_disestablish(NULL, kern_select_50_syscalls);
}