1/*	$NetBSD: netbsd32_compat_50.c,v 1.20 2011/11/18 03:34:13 christos Exp $	*/
2
3/*-
4 * Copyright (c) 2008 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Christos Zoulas.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 *    notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in the
17 *    documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 *    must display the following acknowledgement:
20 *        This product includes software developed by the NetBSD
21 *        Foundation, Inc. and its contributors.
22 * 4. Neither the name of The NetBSD Foundation nor the names of its
23 *    contributors may be used to endorse or promote products derived
24 *    from this software without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 * POSSIBILITY OF SUCH DAMAGE.
37 */
38#include <sys/cdefs.h>
39__KERNEL_RCSID(0, "$NetBSD: netbsd32_compat_50.c,v 1.20 2011/11/18 03:34:13 christos Exp $");
40
41#if defined(_KERNEL_OPT)
42#include "opt_sysv.h"
43#endif
44
45#include <sys/param.h>
46#include <sys/systm.h>
47#include <sys/mount.h>
48#include <sys/socket.h>
49#include <sys/socketvar.h>
50#include <sys/stat.h>
51#include <sys/time.h>
52#include <sys/ktrace.h>
53#include <sys/eventvar.h>
54#include <sys/resourcevar.h>
55#include <sys/vnode.h>
56#include <sys/file.h>
57#include <sys/filedesc.h>
58#include <sys/poll.h>
59#include <sys/namei.h>
60#include <sys/statvfs.h>
61#include <sys/syscallargs.h>
62#include <sys/proc.h>
63#include <sys/dirent.h>
64#include <sys/kauth.h>
65#include <sys/vfs_syscalls.h>
66#include <sys/ipc.h>
67#include <sys/msg.h>
68#include <sys/sem.h>
69#include <sys/shm.h>
70
71#include <compat/netbsd32/netbsd32.h>
72#include <compat/netbsd32/netbsd32_syscallargs.h>
73#include <compat/netbsd32/netbsd32_conv.h>
74#include <compat/sys/mount.h>
75#include <compat/sys/time.h>
76
77
78/*
79 * Common routine to set access and modification times given a vnode.
80 */
81static int
82get_utimes32(const netbsd32_timeval50p_t *tptr, struct timeval *tv,
83    struct timeval **tvp)
84{
85	int error;
86	struct netbsd32_timeval50 tv32[2];
87
88	if (tptr == NULL) {
89		*tvp = NULL;
90		return 0;
91	}
92
93	error = copyin(tptr, tv32, sizeof(tv32));
94	if (error)
95		return error;
96	netbsd32_to_timeval50(&tv32[0], &tv[0]);
97	netbsd32_to_timeval50(&tv32[1], &tv[1]);
98
99	*tvp = tv;
100	return 0;
101}
102
103int
104compat_50_netbsd32_mknod(struct lwp *l,
105    const struct compat_50_netbsd32_mknod_args *uap, register_t *retval)
106{
107	/* {
108		syscallarg(netbsd32_charp) path;
109		syscallarg(mode_t) mode;
110		syscallarg(uint32_t) dev;
111	} */
112	return do_sys_mknod(l, SCARG_P32(uap, path), SCARG(uap, mode),
113	    SCARG(uap, dev), retval, UIO_USERSPACE);
114}
115
116int
117compat_50_netbsd32_select(struct lwp *l,
118    const struct compat_50_netbsd32_select_args *uap, register_t *retval)
119{
120	/* {
121		syscallarg(int) nd;
122		syscallarg(netbsd32_fd_setp_t) in;
123		syscallarg(netbsd32_fd_setp_t) ou;
124		syscallarg(netbsd32_fd_setp_t) ex;
125		syscallarg(netbsd32_timeval50p_t) tv;
126	} */
127	int error;
128	struct netbsd32_timeval50 tv32;
129	struct timespec ats, *ts = NULL;
130
131	if (SCARG_P32(uap, tv)) {
132		error = copyin(SCARG_P32(uap, tv), &tv32, sizeof(tv32));
133		if (error != 0)
134			return error;
135		ats.tv_sec = tv32.tv_sec;
136		ats.tv_nsec = tv32.tv_usec * 1000;
137		ts = &ats;
138	}
139
140	return selcommon(retval, SCARG(uap, nd), SCARG_P32(uap, in),
141	    SCARG_P32(uap, ou), SCARG_P32(uap, ex), ts, NULL);
142	return 0;
143}
144
145int
146compat_50_netbsd32_gettimeofday(struct lwp *l,
147    const struct compat_50_netbsd32_gettimeofday_args *uap, register_t *retval)
148{
149	/* {
150		syscallarg(netbsd32_timeval50p_t) tp;
151		syscallarg(netbsd32_timezonep_t) tzp;
152	} */
153	struct timeval atv;
154	struct netbsd32_timeval50 tv32;
155	int error = 0;
156	struct netbsd32_timezone tzfake;
157
158	if (SCARG_P32(uap, tp)) {
159		microtime(&atv);
160		netbsd32_from_timeval50(&atv, &tv32);
161		error = copyout(&tv32, SCARG_P32(uap, tp), sizeof(tv32));
162		if (error)
163			return error;
164	}
165	if (SCARG_P32(uap, tzp)) {
166		/*
167		 * NetBSD has no kernel notion of time zone, so we just
168		 * fake up a timezone struct and return it if demanded.
169		 */
170		tzfake.tz_minuteswest = 0;
171		tzfake.tz_dsttime = 0;
172		error = copyout(&tzfake, SCARG_P32(uap, tzp), sizeof(tzfake));
173	}
174	return error;
175}
176
177int
178compat_50_netbsd32_settimeofday(struct lwp *l,
179    const struct compat_50_netbsd32_settimeofday_args *uap, register_t *retval)
180{
181	/* {
182		syscallarg(const netbsd32_timeval50p_t) tv;
183		syscallarg(const netbsd32_timezonep_t) tzp;
184	} */
185	struct netbsd32_timeval50 atv32;
186	struct timeval atv;
187	struct timespec ats;
188	int error;
189	struct proc *p = l->l_proc;
190
191	/* Verify all parameters before changing time. */
192
193	/*
194	 * NetBSD has no kernel notion of time zone, and only an
195	 * obsolete program would try to set it, so we log a warning.
196	 */
197	if (SCARG_P32(uap, tzp))
198		printf("pid %d attempted to set the "
199		    "(obsolete) kernel time zone\n", p->p_pid);
200
201	if (SCARG_P32(uap, tv) == 0)
202		return 0;
203
204	if ((error = copyin(SCARG_P32(uap, tv), &atv32, sizeof(atv32))) != 0)
205		return error;
206
207	netbsd32_to_timeval50(&atv32, &atv);
208	TIMEVAL_TO_TIMESPEC(&atv, &ats);
209	return settime(p, &ats);
210}
211
212int
213compat_50_netbsd32_utimes(struct lwp *l,
214    const struct compat_50_netbsd32_utimes_args *uap, register_t *retval)
215{
216	/* {
217		syscallarg(const netbsd32_charp) path;
218		syscallarg(const netbsd32_timeval50p_t) tptr;
219	} */
220	int error;
221	struct timeval tv[2], *tvp;
222
223	error = get_utimes32(SCARG_P32(uap, tptr), tv, &tvp);
224	if (error != 0)
225		return error;
226
227	return do_sys_utimes(l, NULL, SCARG_P32(uap, path), FOLLOW,
228	    tvp, UIO_SYSSPACE);
229}
230
231int
232compat_50_netbsd32_adjtime(struct lwp *l,
233    const struct compat_50_netbsd32_adjtime_args *uap, register_t *retval)
234{
235	/* {
236		syscallarg(const netbsd32_timeval50p_t) delta;
237		syscallarg(netbsd32_timeval50p_t) olddelta;
238	} */
239	struct netbsd32_timeval50 atv;
240	int error;
241
242	extern int time_adjusted;     /* in kern_ntptime.c */
243	extern int64_t time_adjtime;  /* in kern_ntptime.c */
244
245	if ((error = kauth_authorize_system(l->l_cred,
246	    KAUTH_SYSTEM_TIME, KAUTH_REQ_SYSTEM_TIME_ADJTIME, NULL, NULL,
247	    NULL)) != 0)
248		return (error);
249
250	if (SCARG_P32(uap, olddelta)) {
251		atv.tv_sec = time_adjtime / 1000000;
252		atv.tv_usec = time_adjtime % 1000000;
253		if (atv.tv_usec < 0) {
254			atv.tv_usec += 1000000;
255			atv.tv_sec--;
256		}
257		(void) copyout(&atv,
258			       SCARG_P32(uap, olddelta),
259			       sizeof(atv));
260		if (error)
261			return (error);
262	}
263
264	if (SCARG_P32(uap, delta)) {
265		error = copyin(SCARG_P32(uap, delta), &atv,
266			       sizeof(struct timeval));
267		if (error)
268			return (error);
269
270		time_adjtime = (int64_t)atv.tv_sec * 1000000 + atv.tv_usec;
271
272		if (time_adjtime)
273			/* We need to save the system time during shutdown */
274			time_adjusted |= 1;
275	}
276
277	return 0;
278}
279
280int
281compat_50_netbsd32_futimes(struct lwp *l,
282    const struct compat_50_netbsd32_futimes_args *uap, register_t *retval)
283{
284	/* {
285		syscallarg(int) fd;
286		syscallarg(const netbsd32_timeval50p_t) tptr;
287	} */
288	int error;
289	file_t *fp;
290	struct timeval tv[2], *tvp;
291
292	error = get_utimes32(SCARG_P32(uap, tptr), tv, &tvp);
293	if (error != 0)
294		return error;
295
296	/* fd_getvnode() will use the descriptor for us */
297	if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0)
298		return error;
299
300	error = do_sys_utimes(l, fp->f_data, NULL, 0, tvp, UIO_SYSSPACE);
301
302	fd_putfile(SCARG(uap, fd));
303	return error;
304}
305
306int
307compat_50_netbsd32_clock_gettime(struct lwp *l,
308    const struct compat_50_netbsd32_clock_gettime_args *uap, register_t *retval)
309{
310	/* {
311		syscallarg(netbsd32_clockid_t) clock_id;
312		syscallarg(netbsd32_timespec50p_t) tp;
313	} */
314	int error;
315	struct timespec ats;
316	struct netbsd32_timespec50 ts32;
317
318	error = clock_gettime1(SCARG(uap, clock_id), &ats);
319	if (error != 0)
320		return error;
321
322	netbsd32_from_timespec50(&ats, &ts32);
323	return copyout(&ts32, SCARG_P32(uap, tp), sizeof(ts32));
324}
325
326int
327compat_50_netbsd32_clock_settime(struct lwp *l,
328    const struct compat_50_netbsd32_clock_settime_args *uap, register_t *retval)
329{
330	/* {
331		syscallarg(netbsd32_clockid_t) clock_id;
332		syscallarg(const netbsd32_timespec50p_t) tp;
333	} */
334	struct netbsd32_timespec50 ts32;
335	struct timespec ats;
336	int error;
337
338	if ((error = copyin(SCARG_P32(uap, tp), &ts32, sizeof(ts32))) != 0)
339		return (error);
340
341	netbsd32_to_timespec50(&ts32, &ats);
342	return clock_settime1(l->l_proc, SCARG(uap, clock_id), &ats, true);
343}
344
345int
346compat_50_netbsd32_clock_getres(struct lwp *l,
347    const struct compat_50_netbsd32_clock_getres_args *uap, register_t *retval)
348{
349	/* {
350		syscallarg(netbsd32_clockid_t) clock_id;
351		syscallarg(netbsd32_timespec50p_t) tp;
352	} */
353	struct netbsd32_timespec50 ts32;
354	struct timespec ts;
355	int error = 0;
356
357	error = clock_getres1(SCARG(uap, clock_id), &ts);
358	if (error != 0)
359		return error;
360
361	if (SCARG_P32(uap, tp)) {
362		netbsd32_from_timespec50(&ts, &ts32);
363		error = copyout(&ts32, SCARG_P32(uap, tp), sizeof(ts32));
364	}
365
366	return error;
367}
368
369int
370compat_50_netbsd32_timer_settime(struct lwp *l,
371    const struct compat_50_netbsd32_timer_settime_args *uap, register_t *retval)
372{
373	/* {
374		syscallarg(netbsd32_timer_t) timerid;
375		syscallarg(int) flags;
376		syscallarg(const netbsd32_itimerspec50p_t) value;
377		syscallarg(netbsd32_itimerspec50p_t) ovalue;
378	} */
379	int error;
380	struct itimerspec value, ovalue, *ovp = NULL;
381	struct netbsd32_itimerspec50 its32;
382
383	if ((error = copyin(SCARG_P32(uap, value), &its32, sizeof(its32))) != 0)
384		return (error);
385	netbsd32_to_timespec50(&its32.it_interval, &value.it_interval);
386	netbsd32_to_timespec50(&its32.it_value, &value.it_value);
387
388	if (SCARG_P32(uap, ovalue))
389		ovp = &ovalue;
390
391	if ((error = dotimer_settime(SCARG(uap, timerid), &value, ovp,
392	    SCARG(uap, flags), l->l_proc)) != 0)
393		return error;
394
395	if (ovp) {
396		netbsd32_from_timespec50(&ovp->it_interval, &its32.it_interval);
397		netbsd32_from_timespec50(&ovp->it_value, &its32.it_value);
398		return copyout(&its32, SCARG_P32(uap, ovalue), sizeof(its32));
399	}
400	return 0;
401}
402
403int
404compat_50_netbsd32_timer_gettime(struct lwp *l, const struct compat_50_netbsd32_timer_gettime_args *uap, register_t *retval)
405{
406	/* {
407		syscallarg(netbsd32_timer_t) timerid;
408		syscallarg(netbsd32_itimerspec50p_t) value;
409	} */
410	int error;
411	struct itimerspec its;
412	struct netbsd32_itimerspec50 its32;
413
414	if ((error = dotimer_gettime(SCARG(uap, timerid), l->l_proc,
415	    &its)) != 0)
416		return error;
417
418	netbsd32_from_timespec50(&its.it_interval, &its32.it_interval);
419	netbsd32_from_timespec50(&its.it_value, &its32.it_value);
420
421	return copyout(&its32, SCARG_P32(uap, value), sizeof(its32));
422}
423
424int
425compat_50_netbsd32_nanosleep(struct lwp *l,
426    const struct compat_50_netbsd32_nanosleep_args *uap, register_t *retval)
427{
428	/* {
429		syscallarg(const netbsd32_timespec50p_t) rqtp;
430		syscallarg(netbsd32_timespecp_t) rmtp;
431	} */
432	struct netbsd32_timespec50 ts32;
433	struct timespec rqt, rmt;
434	int error, error1;
435
436	error = copyin(SCARG_P32(uap, rqtp), &ts32, sizeof(ts32));
437	if (error)
438		return (error);
439	netbsd32_to_timespec50(&ts32, &rqt);
440
441	error = nanosleep1(l, &rqt, SCARG_P32(uap, rmtp) ? &rmt : NULL);
442	if (SCARG_P32(uap, rmtp) == NULL || (error != 0 && error != EINTR))
443		return error;
444
445	netbsd32_from_timespec50(&rmt, &ts32);
446	error1 = copyout(&ts32, SCARG_P32(uap,rmtp), sizeof(ts32));
447	return error1 ? error1 : error;
448}
449
450static int
451compat_50_netbsd32_sigtimedwait_put_info(const void *src, void *dst, size_t size)
452{
453	const siginfo_t *info = src;
454	siginfo32_t info32;
455
456	netbsd32_si_to_si32(&info32, info);
457
458	return copyout(&info32, dst, sizeof(info32));
459}
460
461static int
462compat_50_netbsd32_sigtimedwait_fetch_timeout(const void *src, void *dst, size_t size)
463{
464	struct timespec *ts = dst;
465	struct netbsd32_timespec50 ts32;
466	int error;
467
468	error = copyin(src, &ts32, sizeof(ts32));
469	if (error)
470		return error;
471
472	netbsd32_to_timespec50(&ts32, ts);
473	return 0;
474}
475
476static int
477compat_50_netbsd32_sigtimedwait_put_timeout(const void *src, void *dst, size_t size)
478{
479	const struct timespec *ts = src;
480	struct netbsd32_timespec50 ts32;
481
482	netbsd32_from_timespec50(ts, &ts32);
483
484	return copyout(&ts32, dst, sizeof(ts32));
485}
486
487int
488compat_50_netbsd32___sigtimedwait(struct lwp *l,
489    const struct compat_50_netbsd32___sigtimedwait_args *uap, register_t *retval)
490{
491	/* {
492		syscallarg(netbsd32_sigsetp_t) set;
493		syscallarg(netbsd32_siginfop_t) info;
494		syscallarg(netbsd32_timespec50p_t) timeout;
495	} */
496	struct sys_____sigtimedwait50_args ua;
497	int res;
498
499	NETBSD32TOP_UAP(set, const sigset_t);
500	NETBSD32TOP_UAP(info, siginfo_t);
501	NETBSD32TOP_UAP(timeout, struct timespec);
502
503	res = sigtimedwait1(l, &ua, retval,
504	    copyin,
505	    compat_50_netbsd32_sigtimedwait_put_info,
506	    compat_50_netbsd32_sigtimedwait_fetch_timeout,
507	    compat_50_netbsd32_sigtimedwait_put_timeout);
508	if (!res)
509		*retval = 0; /* XXX NetBSD<=5 was not POSIX compliant */
510	return res;
511}
512
513int
514compat_50_netbsd32_lutimes(struct lwp *l,
515    const struct compat_50_netbsd32_lutimes_args *uap, register_t *retval)
516{
517	/* {
518		syscallarg(const netbsd32_charp) path;
519		syscallarg(const netbsd32_timeval50p_t) tptr;
520	} */
521	int error;
522	struct timeval tv[2], *tvp;
523
524	error = get_utimes32(SCARG_P32(uap, tptr), tv, &tvp);
525	if (error != 0)
526		return error;
527
528	return do_sys_utimes(l, NULL, SCARG_P32(uap, path), NOFOLLOW,
529	    tvp, UIO_SYSSPACE);
530}
531
532int
533compat_50_netbsd32__lwp_park(struct lwp *l,
534    const struct compat_50_netbsd32__lwp_park_args *uap, register_t *retval)
535{
536	/* {
537		syscallarg(const netbsd32_timespec50p) ts;
538		syscallarg(lwpid_t) unpark;
539		syscallarg(netbsd32_voidp) hint;
540		syscallarg(netbsd32_voidp) unparkhint;
541	} */
542	struct timespec ts, *tsp;
543	struct netbsd32_timespec50 ts32;
544	int error;
545
546	if (SCARG_P32(uap, ts) == NULL)
547		tsp = NULL;
548	else {
549		error = copyin(SCARG_P32(uap, ts), &ts32, sizeof ts32);
550		if (error != 0)
551			return error;
552		netbsd32_to_timespec50(&ts32, &ts);
553		tsp = &ts;
554	}
555
556	if (SCARG(uap, unpark) != 0) {
557		error = lwp_unpark(SCARG(uap, unpark),
558		    SCARG_P32(uap, unparkhint));
559		if (error != 0)
560			return error;
561	}
562
563	return lwp_park(tsp, SCARG_P32(uap, hint));
564	return 0;
565}
566
567static int
568netbsd32_kevent_fetch_timeout(const void *src, void *dest, size_t length)
569{
570	struct netbsd32_timespec50 ts32;
571	int error;
572
573	KASSERT(length == sizeof(struct timespec50));
574
575	error = copyin(src, &ts32, sizeof(ts32));
576	if (error)
577		return error;
578	netbsd32_to_timespec50(&ts32, (struct timespec *)dest);
579	return 0;
580}
581
582static int
583netbsd32_kevent_fetch_changes(void *private, const struct kevent *changelist,
584    struct kevent *changes, size_t index, int n)
585{
586	const struct netbsd32_kevent *src =
587	    (const struct netbsd32_kevent *)changelist;
588	struct netbsd32_kevent *kev32, *changes32 = private;
589	int error, i;
590
591	error = copyin(src + index, changes32, n * sizeof(*changes32));
592	if (error)
593		return error;
594	for (i = 0, kev32 = changes32; i < n; i++, kev32++, changes++)
595		netbsd32_to_kevent(kev32, changes);
596	return 0;
597}
598
599static int
600netbsd32_kevent_put_events(void *private, struct kevent *events,
601    struct kevent *eventlist, size_t index, int n)
602{
603	struct netbsd32_kevent *kev32, *events32 = private;
604	int i;
605
606	for (i = 0, kev32 = events32; i < n; i++, kev32++, events++)
607		netbsd32_from_kevent(events, kev32);
608	kev32 = (struct netbsd32_kevent *)eventlist;
609	return  copyout(events32, kev32, n * sizeof(*events32));
610}
611
612int
613compat_50_netbsd32_kevent(struct lwp *l,
614    const struct compat_50_netbsd32_kevent_args *uap, register_t *retval)
615{
616	/* {
617		syscallarg(int) fd;
618		syscallarg(netbsd32_keventp_t) changelist;
619		syscallarg(netbsd32_size_t) nchanges;
620		syscallarg(netbsd32_keventp_t) eventlist;
621		syscallarg(netbsd32_size_t) nevents;
622		syscallarg(netbsd32_timespec50p_t) timeout;
623	} */
624	int error;
625	size_t maxalloc, nchanges, nevents;
626	struct kevent_ops netbsd32_kevent_ops = {
627		.keo_fetch_timeout = netbsd32_kevent_fetch_timeout,
628		.keo_fetch_changes = netbsd32_kevent_fetch_changes,
629		.keo_put_events = netbsd32_kevent_put_events,
630	};
631
632	nchanges = SCARG(uap, nchanges);
633	nevents = SCARG(uap, nevents);
634	maxalloc = KQ_NEVENTS;
635
636	netbsd32_kevent_ops.keo_private =
637	    kmem_alloc(maxalloc * sizeof(struct netbsd32_kevent), KM_SLEEP);
638
639	error = kevent1(retval, SCARG(uap, fd),
640	    NETBSD32PTR64(SCARG(uap, changelist)), nchanges,
641	    NETBSD32PTR64(SCARG(uap, eventlist)), nevents,
642	    NETBSD32PTR64(SCARG(uap, timeout)), &netbsd32_kevent_ops);
643
644	kmem_free(netbsd32_kevent_ops.keo_private,
645	    maxalloc * sizeof(struct netbsd32_kevent));
646	return error;
647}
648
649int
650compat_50_netbsd32_pselect(struct lwp *l,
651    const struct compat_50_netbsd32_pselect_args *uap, register_t *retval)
652{
653	/* {
654		syscallarg(int) nd;
655		syscallarg(netbsd32_fd_setp_t) in;
656		syscallarg(netbsd32_fd_setp_t) ou;
657		syscallarg(netbsd32_fd_setp_t) ex;
658		syscallarg(const netbsd32_timespec50p_t) ts;
659		syscallarg(const netbsd32_sigsetp_t) mask;
660	} */
661	int error;
662	struct netbsd32_timespec50 ts32;
663	struct timespec ats, *ts = NULL;
664	sigset_t amask, *mask = NULL;
665
666	if (SCARG_P32(uap, ts)) {
667		error = copyin(SCARG_P32(uap, ts), &ts32, sizeof(ts32));
668		if (error != 0)
669			return error;
670		netbsd32_to_timespec50(&ts32, &ats);
671		ts = &ats;
672	}
673	if (SCARG_P32(uap, mask)) {
674		error = copyin(SCARG_P32(uap, mask), &amask, sizeof(amask));
675		if (error != 0)
676			return error;
677		mask = &amask;
678	}
679
680	return selcommon(retval, SCARG(uap, nd), SCARG_P32(uap, in),
681	    SCARG_P32(uap, ou), SCARG_P32(uap, ex), ts, mask);
682	return 0;
683}
684
685int
686compat_50_netbsd32_pollts(struct lwp *l,
687    const struct compat_50_netbsd32_pollts_args *uap, register_t *retval)
688{
689	/* {
690		syscallarg(struct netbsd32_pollfdp_t) fds;
691		syscallarg(u_int) nfds;
692		syscallarg(const netbsd32_timespec50p_t) ts;
693		syscallarg(const netbsd32_sigsetp_t) mask;
694	} */
695	int error;
696	struct netbsd32_timespec50 ts32;
697	struct timespec ats, *ts = NULL;
698	sigset_t amask, *mask = NULL;
699
700	if (SCARG_P32(uap, ts)) {
701		error = copyin(SCARG_P32(uap, ts), &ts32, sizeof(ts32));
702		if (error != 0)
703			return error;
704		netbsd32_to_timespec50(&ts32, &ats);
705		ts = &ats;
706	}
707	if (NETBSD32PTR64( SCARG(uap, mask))) {
708		error = copyin(SCARG_P32(uap, mask), &amask, sizeof(amask));
709		if (error != 0)
710			return error;
711		mask = &amask;
712	}
713
714	return pollcommon(retval, SCARG_P32(uap, fds),
715	    SCARG(uap, nfds), ts, mask);
716}
717
718int
719compat_50_netbsd32___stat30(struct lwp *l,
720    const struct compat_50_netbsd32___stat30_args *uap, register_t *retval)
721{
722	/* {
723		syscallarg(const netbsd32_charp) path;
724		syscallarg(netbsd32_stat50p_t) ub;
725	} */
726	struct netbsd32_stat50 sb32;
727	struct stat sb;
728	int error;
729	const char *path;
730
731	path = SCARG_P32(uap, path);
732
733	error = do_sys_stat(path, FOLLOW, &sb);
734	if (error)
735		return error;
736	netbsd32_from___stat50(&sb, &sb32);
737	error = copyout(&sb32, SCARG_P32(uap, ub), sizeof(sb32));
738	return error;
739}
740
741int
742compat_50_netbsd32___fstat30(struct lwp *l,
743    const struct compat_50_netbsd32___fstat30_args *uap, register_t *retval)
744{
745	/* {
746		syscallarg(int) fd;
747		syscallarg(netbsd32_stat50p_t) sb;
748	} */
749	struct netbsd32_stat50 sb32;
750	struct stat ub;
751	int error;
752
753	error = do_sys_fstat(SCARG(uap, fd), &ub);
754	if (error == 0) {
755		netbsd32_from___stat50(&ub, &sb32);
756		error = copyout(&sb32, SCARG_P32(uap, sb), sizeof(sb32));
757	}
758	return error;
759}
760
761int
762compat_50_netbsd32___lstat30(struct lwp *l,
763    const struct compat_50_netbsd32___lstat30_args *uap, register_t *retval)
764{
765	/* {
766		syscallarg(const netbsd32_charp) path;
767		syscallarg(netbsd32_stat50p_t) ub;
768	} */
769	struct netbsd32_stat50 sb32;
770	struct stat sb;
771	int error;
772	const char *path;
773
774	path = SCARG_P32(uap, path);
775
776	error = do_sys_stat(path, NOFOLLOW, &sb);
777	if (error)
778		return error;
779	netbsd32_from___stat50(&sb, &sb32);
780	error = copyout(&sb32, SCARG_P32(uap, ub), sizeof(sb32));
781	return error;
782}
783
784int
785compat_50_netbsd32___fhstat40(struct lwp *l, const struct compat_50_netbsd32___fhstat40_args *uap, register_t *retval)
786{
787	/* {
788		syscallarg(const netbsd32_pointer_t) fhp;
789		syscallarg(netbsd32_size_t) fh_size;
790		syscallarg(netbsd32_stat50p_t) sb;
791	} */
792	struct stat sb;
793	struct netbsd32_stat50 sb32;
794	int error;
795
796	error = do_fhstat(l, SCARG_P32(uap, fhp), SCARG(uap, fh_size), &sb);
797	if (error != 0) {
798		netbsd32_from___stat50(&sb, &sb32);
799		error = copyout(&sb32, SCARG_P32(uap, sb), sizeof(sb));
800	}
801	return error;
802}
803
804int
805compat_50_netbsd32_wait4(struct lwp *l, const struct compat_50_netbsd32_wait4_args *uap, register_t *retval)
806{
807	/* {
808		syscallarg(int) pid;
809		syscallarg(netbsd32_intp) status;
810		syscallarg(int) options;
811		syscallarg(netbsd32_rusage50p_t) rusage;
812	} */
813	int error, status, pid = SCARG(uap, pid);
814	struct netbsd32_rusage50 ru32;
815	struct rusage ru;
816
817	error = do_sys_wait(&pid, &status, SCARG(uap, options),
818	    SCARG_P32(uap, rusage) != NULL ? &ru : NULL);
819
820	retval[0] = pid;
821	if (pid == 0)
822		return error;
823
824	if (SCARG_P32(uap, rusage)) {
825		netbsd32_from_rusage50(&ru, &ru32);
826		error = copyout(&ru32, SCARG_P32(uap, rusage), sizeof(ru32));
827	}
828
829	if (error == 0 && SCARG_P32(uap, status))
830		error = copyout(&status, SCARG_P32(uap, status), sizeof(status));
831
832	return error;
833}
834
835
836int
837compat_50_netbsd32_getrusage(struct lwp *l, const struct compat_50_netbsd32_getrusage_args *uap, register_t *retval)
838{
839	/* {
840		syscallarg(int) who;
841		syscallarg(netbsd32_rusage50p_t) rusage;
842	} */
843	struct proc *p = l->l_proc;
844	struct rusage *rup;
845	struct netbsd32_rusage50 ru;
846
847	switch (SCARG(uap, who)) {
848
849	case RUSAGE_SELF:
850		rup = &p->p_stats->p_ru;
851		mutex_enter(p->p_lock);
852		calcru(p, &rup->ru_utime, &rup->ru_stime, NULL, NULL);
853		mutex_exit(p->p_lock);
854		break;
855
856	case RUSAGE_CHILDREN:
857		rup = &p->p_stats->p_cru;
858		break;
859
860	default:
861		return (EINVAL);
862	}
863	netbsd32_from_rusage50(rup, &ru);
864	return copyout(&ru, SCARG_P32(uap, rusage), sizeof(ru));
865}
866
867int
868compat_50_netbsd32_setitimer(struct lwp *l,
869    const struct compat_50_netbsd32_setitimer_args *uap, register_t *retval)
870{
871	/* {
872		syscallarg(int) which;
873		syscallarg(const netbsd32_itimerval50p_t) itv;
874		syscallarg(netbsd32_itimerval50p_t) oitv;
875	} */
876	struct proc *p = l->l_proc;
877	struct netbsd32_itimerval50 s32it, *itv32;
878	int which = SCARG(uap, which);
879	struct compat_50_netbsd32_getitimer_args getargs;
880	struct itimerval aitv;
881	int error;
882
883	if ((u_int)which > ITIMER_PROF)
884		return (EINVAL);
885	itv32 = SCARG_P32(uap, itv);
886	if (itv32) {
887		if ((error = copyin(itv32, &s32it, sizeof(s32it))))
888			return (error);
889		netbsd32_to_itimerval50(&s32it, &aitv);
890	}
891	if (SCARG_P32(uap, oitv) != 0) {
892		SCARG(&getargs, which) = which;
893		SCARG(&getargs, itv) = SCARG(uap, oitv);
894		if ((error = compat_50_netbsd32_getitimer(l, &getargs, retval)) != 0)
895			return (error);
896	}
897	if (itv32 == 0)
898		return 0;
899
900	return dosetitimer(p, which, &aitv);
901}
902
903int
904compat_50_netbsd32_getitimer(struct lwp *l, const struct compat_50_netbsd32_getitimer_args *uap, register_t *retval)
905{
906	/* {
907		syscallarg(int) which;
908		syscallarg(netbsd32_itimerval50p_t) itv;
909	} */
910	struct proc *p = l->l_proc;
911	struct netbsd32_itimerval50 s32it;
912	struct itimerval aitv;
913	int error;
914
915	error = dogetitimer(p, SCARG(uap, which), &aitv);
916	if (error)
917		return error;
918
919	netbsd32_from_itimerval50(&aitv, &s32it);
920	return copyout(&s32it, SCARG_P32(uap, itv), sizeof(s32it));
921}
922
923#if defined(SYSVSEM)
924
925int
926compat_50_netbsd32___semctl14(struct lwp *l, const struct compat_50_netbsd32___semctl14_args *uap, register_t *retval)
927{
928	return do_netbsd32___semctl14(l, uap, retval, NULL);
929}
930
931int
932do_netbsd32___semctl14(struct lwp *l, const struct compat_50_netbsd32___semctl14_args *uap, register_t *retval, void *vkarg)
933{
934	/* {
935		syscallarg(int) semid;
936		syscallarg(int) semnum;
937		syscallarg(int) cmd;
938		syscallarg(netbsd32_semun50p_t) arg;
939	} */
940	struct semid_ds sembuf;
941	struct netbsd32_semid_ds50 sembuf32;
942	int cmd, error;
943	void *pass_arg;
944	union __semun karg;
945	union netbsd32_semun50 karg32;
946
947	cmd = SCARG(uap, cmd);
948
949	switch (cmd) {
950	case IPC_SET:
951	case IPC_STAT:
952		pass_arg = &sembuf;
953		break;
954
955	case GETALL:
956	case SETVAL:
957	case SETALL:
958		pass_arg = &karg;
959		break;
960	default:
961		pass_arg = NULL;
962		break;
963	}
964
965	if (pass_arg) {
966		if (vkarg != NULL)
967			karg32 = *(union netbsd32_semun50 *)vkarg;
968		else {
969			error = copyin(SCARG_P32(uap, arg), &karg32,
970					sizeof(karg32));
971			if (error)
972				return error;
973		}
974		if (pass_arg == &karg) {
975			switch (cmd) {
976			case GETALL:
977			case SETALL:
978				karg.array = NETBSD32PTR64(karg32.array);
979				break;
980			case SETVAL:
981				karg.val = karg32.val;
982				break;
983			}
984		}
985		if (cmd == IPC_SET) {
986			error = copyin(NETBSD32PTR64(karg32.buf), &sembuf32,
987			    sizeof(sembuf32));
988			if (error)
989				return (error);
990			netbsd32_to_semid_ds50(&sembuf32, &sembuf);
991		}
992	}
993
994	error = semctl1(l, SCARG(uap, semid), SCARG(uap, semnum), cmd,
995	    pass_arg, retval);
996
997	if (error == 0 && cmd == IPC_STAT) {
998		netbsd32_from_semid_ds50(&sembuf, &sembuf32);
999		error = copyout(&sembuf32, NETBSD32PTR64(karg32.buf),
1000		    sizeof(sembuf32));
1001	}
1002
1003	return (error);
1004}
1005#endif
1006
1007#if defined(SYSVMSG)
1008
1009int
1010compat_50_netbsd32___msgctl13(struct lwp *l, const struct compat_50_netbsd32___msgctl13_args *uap, register_t *retval)
1011{
1012	/* {
1013		syscallarg(int) msqid;
1014		syscallarg(int) cmd;
1015		syscallarg(netbsd32_msqid_ds50p_t) buf;
1016	} */
1017	struct msqid_ds ds;
1018	struct netbsd32_msqid_ds50 ds32;
1019	int error, cmd;
1020
1021	cmd = SCARG(uap, cmd);
1022	if (cmd == IPC_SET) {
1023		error = copyin(SCARG_P32(uap, buf), &ds32, sizeof(ds32));
1024		if (error)
1025			return error;
1026		netbsd32_to_msqid_ds50(&ds32, &ds);
1027	}
1028
1029	error = msgctl1(l, SCARG(uap, msqid), cmd,
1030	    (cmd == IPC_SET || cmd == IPC_STAT) ? &ds : NULL);
1031
1032	if (error == 0 && cmd == IPC_STAT) {
1033		netbsd32_from_msqid_ds50(&ds, &ds32);
1034		error = copyout(&ds32, SCARG_P32(uap, buf), sizeof(ds32));
1035	}
1036
1037	return error;
1038}
1039#endif
1040
1041#if defined(SYSVSHM)
1042
1043int
1044compat_50_netbsd32___shmctl13(struct lwp *l, const struct compat_50_netbsd32___shmctl13_args *uap, register_t *retval)
1045{
1046	/* {
1047		syscallarg(int) shmid;
1048		syscallarg(int) cmd;
1049		syscallarg(netbsd32_shmid_ds50p_t) buf;
1050	} */
1051	struct shmid_ds ds;
1052	struct netbsd32_shmid_ds50 ds32;
1053	int error, cmd;
1054
1055	cmd = SCARG(uap, cmd);
1056	if (cmd == IPC_SET) {
1057		error = copyin(SCARG_P32(uap, buf), &ds32, sizeof(ds32));
1058		if (error)
1059			return error;
1060		netbsd32_to_shmid_ds50(&ds32, &ds);
1061	}
1062
1063	error = shmctl1(l, SCARG(uap, shmid), cmd,
1064	    (cmd == IPC_SET || cmd == IPC_STAT) ? &ds : NULL);
1065
1066	if (error == 0 && cmd == IPC_STAT) {
1067		netbsd32_from_shmid_ds50(&ds, &ds32);
1068		error = copyout(&ds32, SCARG_P32(uap, buf), sizeof(ds32));
1069	}
1070
1071	return error;
1072}
1073#endif
1074
1075int
1076compat_50_netbsd32_quotactl(struct lwp *l, const struct compat_50_netbsd32_quotactl_args *uap, register_t *retval)
1077{
1078	/* {
1079		syscallarg(const netbsd32_charp) path;
1080		syscallarg(int) cmd;
1081		syscallarg(int) uid;
1082		syscallarg(netbsd32_voidp) arg;
1083	} */
1084	struct compat_50_sys_quotactl_args ua;
1085
1086	NETBSD32TOP_UAP(path, const char);
1087	NETBSD32TO64_UAP(cmd);
1088	NETBSD32TO64_UAP(uid);
1089	NETBSD32TOP_UAP(arg, void *);
1090	return (compat_50_sys_quotactl(l, &ua, retval));
1091}
1092