linux32_unistd.c revision 1.6 1 /* $NetBSD: linux32_unistd.c,v 1.6 2007/03/04 06:01:25 christos Exp $ */
2
3 /*-
4 * Copyright (c) 2006 Emmanuel Dreyfus, all rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. All advertising materials mentioning features or use of this software
15 * must display the following acknowledgement:
16 * This product includes software developed by Emmanuel Dreyfus
17 * 4. The name of the author may not be used to endorse or promote
18 * products derived from this software without specific prior written
19 * permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE THE AUTHOR AND CONTRIBUTORS ``AS IS''
22 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
23 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS
25 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
32 */
33
34 #include <sys/cdefs.h>
35
36 __KERNEL_RCSID(0, "$NetBSD: linux32_unistd.c,v 1.6 2007/03/04 06:01:25 christos Exp $");
37
38 #include <sys/types.h>
39 #include <sys/param.h>
40 #include <sys/fstypes.h>
41 #include <sys/signal.h>
42 #include <sys/dirent.h>
43 #include <sys/kernel.h>
44 #include <sys/fcntl.h>
45 #include <sys/select.h>
46 #include <sys/proc.h>
47 #include <sys/ucred.h>
48 #include <sys/swap.h>
49
50 #include <machine/types.h>
51
52 #include <sys/syscallargs.h>
53
54 #include <compat/netbsd32/netbsd32.h>
55 #include <compat/netbsd32/netbsd32_conv.h>
56 #include <compat/netbsd32/netbsd32_syscallargs.h>
57
58 #include <compat/linux/common/linux_types.h>
59 #include <compat/linux/common/linux_signal.h>
60 #include <compat/linux/common/linux_machdep.h>
61 #include <compat/linux/common/linux_misc.h>
62 #include <compat/linux/common/linux_oldolduname.h>
63 #include <compat/linux/linux_syscallargs.h>
64
65 #include <compat/linux32/common/linux32_types.h>
66 #include <compat/linux32/common/linux32_signal.h>
67 #include <compat/linux32/common/linux32_machdep.h>
68 #include <compat/linux32/common/linux32_sysctl.h>
69 #include <compat/linux32/common/linux32_socketcall.h>
70 #include <compat/linux32/linux32_syscallargs.h>
71
72 static int linux32_select1(struct lwp *, register_t *,
73 int, fd_set *, fd_set *, fd_set *, struct timeval *);
74
75 int
76 linux32_sys_brk(l, v, retval)
77 struct lwp *l;
78 void *v;
79 register_t *retval;
80 {
81 struct linux32_sys_brk_args /* {
82 syscallarg(netbsd32_charp) nsize;
83 } */ *uap = v;
84 struct linux_sys_brk_args ua;
85
86 NETBSD32TOP_UAP(nsize, char);
87 return linux_sys_brk(l, &ua, retval);
88 }
89
90 int
91 linux32_sys_access(l, v, retval)
92 struct lwp *l;
93 void *v;
94 register_t *retval;
95 {
96 struct linux32_sys_access_args /* {
97 syscallarg(const netbsd32_charp) path;
98 syscallarg(int) flags;
99 } */ *uap = v;
100 struct sys_access_args ua;
101 void *sg;
102
103 NETBSD32TOP_UAP(path, const char);
104 NETBSD32TO64_UAP(flags);
105
106 sg = stackgap_init(l->l_proc, 0);
107 CHECK_ALT_EXIST(l, &sg, SCARG(&ua, path));
108
109 return sys_access(l, &ua, retval);
110 }
111
112 int
113 linux32_sys_llseek(l, v, retval)
114 struct lwp *l;
115 void *v;
116 register_t *retval;
117 {
118 struct linux32_sys_llseek_args /* {
119 syscallcarg(int) fd;
120 syscallarg(u_int32_t) ohigh;
121 syscallarg(u_int32_t) olow;
122 syscallarg(netbsd32_void *) res;
123 syscallcarg(int) whence;
124 } */ *uap = v;
125 struct linux_sys_llseek_args ua;
126
127 NETBSD32TO64_UAP(fd);
128 NETBSD32TO64_UAP(ohigh);
129 NETBSD32TO64_UAP(olow);
130 NETBSD32TOP_UAP(res, char);
131 NETBSD32TO64_UAP(whence);
132
133 return linux_sys_llseek(l, &ua, retval);
134 }
135
136 int
137 linux32_sys_readlink(l, v, retval)
138 struct lwp *l;
139 void *v;
140 register_t *retval;
141 {
142 struct linux32_sys_readlink_args /* {
143 syscallarg(const netbsd32_charp) name;
144 syscallarg(netbsd32_charp) buf;
145 syscallarg(int) count;
146 } */ *uap = v;
147 struct linux_sys_readlink_args ua;
148
149 NETBSD32TOP_UAP(name, const char);
150 NETBSD32TOP_UAP(buf, char)
151 NETBSD32TO64_UAP(count);
152
153 return linux_sys_readlink(l, &ua, retval);
154 }
155
156
157 int
158 linux32_sys_select(l, v, retval)
159 struct lwp *l;
160 void *v;
161 register_t *retval;
162 {
163 struct linux32_sys_select_args /* {
164 syscallarg(int) nfds;
165 syscallarg(netbsd32_fd_setp_t) readfds;
166 syscallarg(netbsd32_fd_setp_t) writefds;
167 syscallarg(netbsd32_fd_setp_t) exceptfds;
168 syscallarg(netbsd32_timevalp_t) timeout;
169 } */ *uap = v;
170
171 return linux32_select1(l, retval, SCARG(uap, nfds),
172 NETBSD32PTR64(SCARG(uap, readfds)),
173 NETBSD32PTR64(SCARG(uap, writefds)),
174 NETBSD32PTR64(SCARG(uap, exceptfds)),
175 NETBSD32PTR64(SCARG(uap, timeout)));
176 }
177
178 int
179 linux32_sys_oldselect(l, v, retval)
180 struct lwp *l;
181 void *v;
182 register_t *retval;
183 {
184 struct linux32_sys_oldselect_args /* {
185 syscallarg(linux32_oldselectp_t) lsp;
186 } */ *uap = v;
187 struct linux32_oldselect lsp32;
188 int error;
189
190 if ((error = copyin(NETBSD32PTR64(SCARG(uap, lsp)),
191 &lsp32, sizeof(lsp32))) != 0)
192 return error;
193
194 return linux32_select1(l, retval, lsp32.nfds,
195 NETBSD32PTR64(lsp32.readfds), NETBSD32PTR64(lsp32.writefds),
196 NETBSD32PTR64(lsp32.exceptfds), NETBSD32PTR64(lsp32.timeout));
197 }
198
199 static int
200 linux32_select1(l, retval, nfds, readfds, writefds, exceptfds, timeout)
201 struct lwp *l;
202 register_t *retval;
203 int nfds;
204 fd_set *readfds, *writefds, *exceptfds;
205 struct timeval *timeout;
206 {
207 struct timeval tv0, tv1, utv, otv;
208 struct netbsd32_timeval utv32;
209 int error;
210
211 timerclear(&otv); /* XXX GCC4 */
212
213 /*
214 * Store current time for computation of the amount of
215 * time left.
216 */
217 if (timeout) {
218 if ((error = copyin(timeout, &utv32, sizeof(utv32))))
219 return error;
220
221 netbsd32_to_timeval(&utv32, &utv);
222 otv = utv;
223
224 if (itimerfix(&utv)) {
225 /*
226 * The timeval was invalid. Convert it to something
227 * valid that will act as it does under Linux.
228 */
229 utv.tv_sec += utv.tv_usec / 1000000;
230 utv.tv_usec %= 1000000;
231 if (utv.tv_usec < 0) {
232 utv.tv_sec -= 1;
233 utv.tv_usec += 1000000;
234 }
235 if (utv.tv_sec < 0)
236 timerclear(&utv);
237 }
238 microtime(&tv0);
239 } else {
240 timerclear(&utv);
241 }
242
243 error = selcommon(l, retval, nfds,
244 readfds, writefds, exceptfds, &utv, NULL);
245
246 if (error) {
247 /*
248 * See fs/select.c in the Linux kernel. Without this,
249 * Maelstrom doesn't work.
250 */
251 if (error == ERESTART)
252 error = EINTR;
253 return error;
254 }
255
256 if (timeout) {
257 if (*retval) {
258 /*
259 * Compute how much time was left of the timeout,
260 * by subtracting the current time and the time
261 * before we started the call, and subtracting
262 * that result from the user-supplied value.
263 */
264 microtime(&tv1);
265 timersub(&tv1, &tv0, &tv1);
266 timersub(&otv, &tv1, &utv);
267 if (utv.tv_sec < 0)
268 timerclear(&utv);
269 } else {
270 timerclear(&utv);
271 }
272
273 netbsd32_from_timeval(&utv, &utv32);
274
275 if ((error = copyout(&utv32, timeout, sizeof(utv32))))
276 return error;
277 }
278
279 return 0;
280 }
281
282 int
283 linux32_sys_pipe(l, v, retval)
284 struct lwp *l;
285 void *v;
286 register_t *retval;
287 {
288 struct linux32_sys_pipe_args /* {
289 syscallarg(netbsd32_intp) fd;
290 } */ *uap = v;
291 int error;
292 int pfds[2];
293
294 if ((error = sys_pipe(l, 0, retval)))
295 return error;
296
297 pfds[0] = (int)retval[0];
298 pfds[1] = (int)retval[1];
299
300 if ((error = copyout(pfds, NETBSD32PTR64(SCARG(uap, fd)),
301 2 * sizeof (int))) != 0)
302 return error;
303
304 retval[0] = 0;
305 retval[1] = 0;
306
307 return 0;
308 }
309
310
311 int
312 linux32_sys_unlink(l, v, retval)
313 struct lwp *l;
314 void *v;
315 register_t *retval;
316 {
317 struct linux32_sys_unlink_args /* {
318 syscallarg(const netbsd32_charp) path;
319 } */ *uap = v;
320 struct linux_sys_unlink_args ua;
321
322 NETBSD32TOP_UAP(path, const char);
323
324 return linux_sys_unlink(l, &ua, retval);
325 }
326
327 int
328 linux32_sys_chdir(l, v, retval)
329 struct lwp *l;
330 void *v;
331 register_t *retval;
332 {
333 struct linux32_sys_chdir_args /* {
334 syscallarg(const netbsd32_charp) path;
335 } */ *uap = v;
336 struct sys_chdir_args ua;
337 void *sg = stackgap_init(l->l_proc, 0);
338
339 NETBSD32TOP_UAP(path, const char);
340
341 CHECK_ALT_EXIST(l, &sg, SCARG(&ua, path));
342
343 return sys_chdir(l, &ua, retval);
344 }
345
346 int
347 linux32_sys_link(l, v, retval)
348 struct lwp *l;
349 void *v;
350 register_t *retval;
351 {
352 struct linux32_sys_link_args /* {
353 syscallarg(const netbsd32_charp) path;
354 syscallarg(const netbsd32_charp) link;
355 } */ *uap = v;
356 struct sys_link_args ua;
357 void *sg = stackgap_init(l->l_proc, 0);
358
359 NETBSD32TOP_UAP(path, const char);
360 NETBSD32TOP_UAP(link, const char);
361
362 CHECK_ALT_EXIST(l, &sg, SCARG(&ua, path));
363 CHECK_ALT_CREAT(l, &sg, SCARG(&ua, link));
364
365 return sys_link(l, &ua, retval);
366 }
367
368 int
369 linux32_sys_creat(l, v, retval)
370 struct lwp *l;
371 void *v;
372 register_t *retval;
373 {
374 struct linux32_sys_creat_args /* {
375 syscallarg(const netbsd32_charp) path;
376 syscallarg(int) mode;
377 } */ *uap = v;
378 struct sys_open_args ua;
379 void *sg = stackgap_init(l->l_proc, 0);
380
381 NETBSD32TOP_UAP(path, const char);
382 SCARG(&ua, flags) = O_CREAT | O_TRUNC | O_WRONLY;
383 NETBSD32TO64_UAP(mode);
384
385 CHECK_ALT_EXIST(l, &sg, SCARG(&ua, path));
386
387 return sys_open(l, &ua, retval);
388 }
389
390 int
391 linux32_sys_mknod(l, v, retval)
392 struct lwp *l;
393 void *v;
394 register_t *retval;
395 {
396 struct linux32_sys_mknod_args /* {
397 syscallarg(const netbsd32_charp) path;
398 syscallarg(int) mode;
399 syscallarg(int) dev;
400 } */ *uap = v;
401 struct linux_sys_mknod_args ua;
402
403 NETBSD32TOP_UAP(path, const char);
404 NETBSD32TO64_UAP(mode);
405 NETBSD32TO64_UAP(dev);
406
407 return linux_sys_mknod(l, &ua, retval);
408 }
409
410 int
411 linux32_sys_chmod(l, v, retval)
412 struct lwp *l;
413 void *v;
414 register_t *retval;
415 {
416 struct linux32_sys_chmod_args /* {
417 syscallarg(const netbsd32_charp) path;
418 syscallarg(int) mode;
419 } */ *uap = v;
420 struct sys_chmod_args ua;
421 void *sg = stackgap_init(l->l_proc, 0);
422
423 NETBSD32TOP_UAP(path, const char);
424 NETBSD32TO64_UAP(mode);
425
426 CHECK_ALT_EXIST(l, &sg, SCARG(&ua, path));
427
428 return sys_chmod(l, &ua, retval);
429 }
430
431 int
432 linux32_sys_lchown16(l, v, retval)
433 struct lwp *l;
434 void *v;
435 register_t *retval;
436 {
437 struct linux32_sys_lchown16_args /* {
438 syscallarg(const netbsd32_charp) path;
439 syscallarg(int) uid;
440 syscallarg(int) gid;
441 } */ *uap = v;
442 struct sys___posix_lchown_args ua;
443 void *sg = stackgap_init(l->l_proc, 0);
444
445 NETBSD32TOP_UAP(path, const char);
446 CHECK_ALT_SYMLINK(l, &sg, SCARG(&ua, path));
447
448 if ((linux32_uid_t)SCARG(uap, uid) == (linux32_uid_t)-1)
449 SCARG(&ua, uid) = (uid_t)-1;
450 else
451 SCARG(&ua, uid) = SCARG(uap, uid);
452
453 if ((linux32_gid_t)SCARG(uap, gid) == (linux32_gid_t)-1)
454 SCARG(&ua, gid) = (gid_t)-1;
455 else
456 SCARG(&ua, gid) = SCARG(uap, gid);
457
458 return sys___posix_lchown(l, &ua, retval);
459 }
460
461 int
462 linux32_sys_break(l, v, retval)
463 struct lwp *l;
464 void *v;
465 register_t *retval;
466 {
467 #if 0
468 struct linux32_sys_break_args /* {
469 syscallarg(const netbsd32_charp) nsize;
470 } */ *uap = v;
471 #endif
472
473 return ENOSYS;
474 }
475
476 int
477 linux32_sys_rename(l, v, retval)
478 struct lwp *l;
479 void *v;
480 register_t *retval;
481 {
482 struct linux32_sys_rename_args /* {
483 syscallarg(const netbsd32_charp) from;
484 syscallarg(const netbsd32_charp) to;
485 } */ *uap = v;
486 struct sys_rename_args ua;
487 void *sg = stackgap_init(l->l_proc, 0);
488
489 NETBSD32TOP_UAP(from, const char);
490 NETBSD32TOP_UAP(to, const char);
491
492 CHECK_ALT_EXIST(l, &sg, SCARG(&ua, from));
493 CHECK_ALT_CREAT(l, &sg, SCARG(&ua, to));
494
495 return sys___posix_rename(l, &ua, retval);
496 }
497
498 int
499 linux32_sys_mkdir(l, v, retval)
500 struct lwp *l;
501 void *v;
502 register_t *retval;
503 {
504 struct linux32_sys_mkdir_args /* {
505 syscallarg(const netbsd32_charp) path;
506 syscallarg(int) mode;
507 } */ *uap = v;
508 struct sys_mkdir_args ua;
509 void *sg = stackgap_init(l->l_proc, 0);
510
511 NETBSD32TOP_UAP(path, const char);
512 NETBSD32TO64_UAP(mode);
513
514 CHECK_ALT_CREAT(l, &sg, SCARG(&ua, path));
515
516 return sys_mkdir(l, &ua, retval);
517 }
518
519 int
520 linux32_sys_rmdir(l, v, retval)
521 struct lwp *l;
522 void *v;
523 register_t *retval;
524 {
525 struct linux32_sys_rmdir_args /* {
526 syscallarg(const netbsd32_charp) path;
527 } */ *uap = v;
528 struct sys_rmdir_args ua;
529 void *sg = stackgap_init(l->l_proc, 0);
530
531 NETBSD32TOP_UAP(path, const char);
532
533 CHECK_ALT_EXIST(l, &sg, SCARG(&ua, path));
534
535 return sys_rmdir(l, &ua, retval);
536 }
537
538 int
539 linux32_sys_getgroups16(l, v, retval)
540 struct lwp *l;
541 void *v;
542 register_t *retval;
543 {
544 struct linux32_sys_getgroups16_args /* {
545 syscallarg(int) gidsetsize;
546 syscallarg(linux32_gidp_t) gidset;
547 } */ *uap = v;
548 struct linux_sys_getgroups16_args ua;
549
550 NETBSD32TO64_UAP(gidsetsize);
551 NETBSD32TOP_UAP(gidset, linux_gid_t);
552
553 return linux_sys_getgroups16(l, &ua, retval);
554 }
555
556 int
557 linux32_sys_setgroups16(l, v, retval)
558 struct lwp *l;
559 void *v;
560 register_t *retval;
561 {
562 struct linux32_sys_setgroups16_args /* {
563 syscallarg(int) gidsetsize;
564 syscallarg(linux32_gidp_t) gidset;
565 } */ *uap = v;
566 struct linux_sys_setgroups16_args ua;
567
568 NETBSD32TO64_UAP(gidsetsize);
569 NETBSD32TOP_UAP(gidset, linux_gid_t);
570
571 return linux_sys_setgroups16(l, &ua, retval);
572 }
573
574 int
575 linux32_sys_symlink(l, v, retval)
576 struct lwp *l;
577 void *v;
578 register_t *retval;
579 {
580 struct linux32_sys_symlink_args /* {
581 syscallarg(const netbsd32_charp) path;
582 syscallarg(const netbsd32_charp) link;
583 } */ *uap = v;
584 struct sys_symlink_args ua;
585 void *sg = stackgap_init(l->l_proc, 0);
586
587 NETBSD32TOP_UAP(path, const char);
588 NETBSD32TOP_UAP(link, const char);
589
590 CHECK_ALT_EXIST(l, &sg, SCARG(&ua, path));
591 CHECK_ALT_CREAT(l, &sg, SCARG(&ua, link));
592
593 return sys_symlink(l, &ua, retval);
594 }
595
596
597 int
598 linux32_sys_swapon(l, v, retval)
599 struct lwp *l;
600 void *v;
601 register_t *retval;
602 {
603 struct linux32_sys_swapon_args /* {
604 syscallarg(const netbsd32_charp) name;
605 } */ *uap = v;
606 struct sys_swapctl_args ua;
607
608 SCARG(&ua, cmd) = SWAP_ON;
609 SCARG(&ua, arg) = (void *)__UNCONST(NETBSD32PTR64(SCARG(uap, name)));
610 SCARG(&ua, misc) = 0; /* priority */
611 return (sys_swapctl(l, &ua, retval));
612 }
613
614 int
615 linux32_sys_swapoff(l, v, retval)
616 struct lwp *l;
617 void *v;
618 register_t *retval;
619 {
620 struct linux32_sys_swapoff_args /* {
621 syscallarg(const netbsd32_charp) path;
622 } */ *uap = v;
623 struct sys_swapctl_args ua;
624
625 SCARG(&ua, cmd) = SWAP_OFF;
626 SCARG(&ua, arg) = (void *)__UNCONST(NETBSD32PTR64(SCARG(uap, path)));
627 SCARG(&ua, misc) = 0; /* priority */
628 return (sys_swapctl(l, &ua, retval));
629 }
630
631
632 int
633 linux32_sys_reboot(l, v, retval)
634 struct lwp *l;
635 void *v;
636 register_t *retval;
637 {
638 struct linux32_sys_reboot_args /* {
639 syscallarg(int) magic1;
640 syscallarg(int) magic2;
641 syscallarg(int) cmd;
642 syscallarg(netbsd32_voidp) arg;
643 } */ *uap = v;
644 struct linux_sys_reboot_args ua;
645
646 NETBSD32TO64_UAP(magic1);
647 NETBSD32TO64_UAP(magic2);
648 NETBSD32TO64_UAP(cmd);
649 NETBSD32TOP_UAP(arg, void);
650
651 return linux_sys_reboot(l, &ua, retval);
652 }
653
654 int
655 linux32_sys_truncate(l, v, retval)
656 struct lwp *l;
657 void *v;
658 register_t *retval;
659 {
660 struct linux32_sys_truncate_args /* {
661 syscallarg(const netbsd32_charp) path;
662 syscallarg(netbsd32_charp) buf;
663 syscallarg(int) count;
664 } */ *uap = v;
665 struct compat_43_sys_truncate_args ua;
666
667 NETBSD32TOP_UAP(path, const char);
668 NETBSD32TO64_UAP(length);
669
670 return compat_43_sys_truncate(l, &ua, retval);
671 }
672
673 int
674 linux32_sys_fchown16(l, v, retval)
675 struct lwp *l;
676 void *v;
677 register_t *retval;
678 {
679 struct linux32_sys_fchown16_args /* {
680 syscallarg(int) fd;
681 syscallarg(int) uid;
682 syscallarg(int) gid;
683 } */ *uap = v;
684 struct sys___posix_fchown_args ua;
685
686 SCARG(&ua, fd) = SCARG(uap, fd);
687
688 if ((linux32_uid_t)SCARG(uap, uid) == (linux32_uid_t)-1)
689 SCARG(&ua, uid) = (uid_t)-1;
690 else
691 SCARG(&ua, uid) = SCARG(uap, uid);
692
693 if ((linux32_gid_t)SCARG(uap, gid) == (linux32_gid_t)-1)
694 SCARG(&ua, gid) = (gid_t)-1;
695 else
696 SCARG(&ua, gid) = SCARG(uap, gid);
697
698 return sys___posix_fchown(l, &ua, retval);
699 }
700
701 int
702 linux32_sys_setresuid(l, v, retval)
703 struct lwp *l;
704 void *v;
705 register_t *retval;
706 {
707 struct linux32_sys_setresuid_args /* {
708 syscallarg(uid_t) ruid;
709 syscallarg(uid_t) euid;
710 syscallarg(uid_t) suid;
711 } */ *uap = v;
712 struct linux_sys_setresuid_args ua;
713
714 SCARG(&ua, ruid) = (SCARG(uap, ruid) == -1) ? -1 : SCARG(uap, ruid);
715 SCARG(&ua, euid) = (SCARG(uap, euid) == -1) ? -1 : SCARG(uap, euid);
716 SCARG(&ua, suid) = (SCARG(uap, suid) == -1) ? -1 : SCARG(uap, suid);
717
718 return linux_sys_setresuid(l, &ua, retval);
719 }
720
721 int
722 linux32_sys_setresgid(l, v, retval)
723 struct lwp *l;
724 void *v;
725 register_t *retval;
726 {
727 struct linux32_sys_setresgid_args /* {
728 syscallarg(gid_t) rgid;
729 syscallarg(gid_t) egid;
730 syscallarg(gid_t) sgid;
731 } */ *uap = v;
732 struct linux_sys_setresgid_args ua;
733
734 SCARG(&ua, rgid) = (SCARG(uap, rgid) == -1) ? -1 : SCARG(uap, rgid);
735 SCARG(&ua, egid) = (SCARG(uap, egid) == -1) ? -1 : SCARG(uap, egid);
736 SCARG(&ua, sgid) = (SCARG(uap, sgid) == -1) ? -1 : SCARG(uap, sgid);
737
738 return linux_sys_setresgid(l, &ua, retval);
739 }
740