]> git.ipfire.org Git - thirdparty/qemu.git/blame - linux-user/syscall.c
linux-user: Fix broken m68k signal handling on 64 bit hosts
[thirdparty/qemu.git] / linux-user / syscall.c
CommitLineData
31e31b8a
FB
1/*
2 * Linux syscalls
5fafdf24 3 *
31e31b8a
FB
4 * Copyright (c) 2003 Fabrice Bellard
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
8167ee88 17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
31e31b8a 18 */
d5b3a9b6 19#define _ATFILE_SOURCE
31e31b8a
FB
20#include <stdlib.h>
21#include <stdio.h>
22#include <stdarg.h>
04369ff2 23#include <string.h>
31e31b8a
FB
24#include <elf.h>
25#include <endian.h>
26#include <errno.h>
27#include <unistd.h>
28#include <fcntl.h>
7854b056 29#include <time.h>
82e671d9 30#include <limits.h>
c56dc774 31#include <grp.h>
31e31b8a 32#include <sys/types.h>
d08d3bb8
TS
33#include <sys/ipc.h>
34#include <sys/msg.h>
31e31b8a
FB
35#include <sys/wait.h>
36#include <sys/time.h>
37#include <sys/stat.h>
38#include <sys/mount.h>
586b0bef
JS
39#include <sys/file.h>
40#include <sys/fsuid.h>
41#include <sys/personality.h>
39b9aae1 42#include <sys/prctl.h>
31e31b8a
FB
43#include <sys/resource.h>
44#include <sys/mman.h>
45#include <sys/swap.h>
e0eb210e 46#include <linux/capability.h>
31e31b8a
FB
47#include <signal.h>
48#include <sched.h>
60e99246
AJ
49#ifdef __ia64__
50int __clone2(int (*fn)(void *), void *child_stack_base,
51 size_t stack_size, int flags, void *arg, ...);
52#endif
31e31b8a 53#include <sys/socket.h>
607175e0 54#include <sys/un.h>
31e31b8a 55#include <sys/uio.h>
9de5e440 56#include <sys/poll.h>
32f36bce 57#include <sys/times.h>
8853f86e 58#include <sys/shm.h>
fa294816 59#include <sys/sem.h>
56c8f68f 60#include <sys/statfs.h>
ebc05488 61#include <utime.h>
a5448a7d 62#include <sys/sysinfo.h>
72f03900 63//#include <sys/user.h>
8853f86e 64#include <netinet/ip.h>
7854b056 65#include <netinet/tcp.h>
86fcd946 66#include <linux/wireless.h>
920394db 67#include <linux/icmp.h>
5a61cb60 68#include "qemu-common.h"
d80a1905
RV
69#ifdef CONFIG_TIMERFD
70#include <sys/timerfd.h>
71#endif
9788c9ca 72#ifdef TARGET_GPROF
6d946cda
AJ
73#include <sys/gmon.h>
74#endif
c2882b96
RV
75#ifdef CONFIG_EVENTFD
76#include <sys/eventfd.h>
77#endif
3b6edd16
PM
78#ifdef CONFIG_EPOLL
79#include <sys/epoll.h>
80#endif
a790ae38 81#ifdef CONFIG_ATTR
1de7afc9 82#include "qemu/xattr.h"
a790ae38 83#endif
a8fd1aba
PM
84#ifdef CONFIG_SENDFILE
85#include <sys/sendfile.h>
86#endif
31e31b8a
FB
87
88#define termios host_termios
89#define winsize host_winsize
90#define termio host_termio
04369ff2
FB
91#define sgttyb host_sgttyb /* same as target */
92#define tchars host_tchars /* same as target */
93#define ltchars host_ltchars /* same as target */
31e31b8a
FB
94
95#include <linux/termios.h>
96#include <linux/unistd.h>
31e31b8a
FB
97#include <linux/cdrom.h>
98#include <linux/hdreg.h>
99#include <linux/soundcard.h>
19b84f3c 100#include <linux/kd.h>
8fbd6b52 101#include <linux/mtio.h>
350d1779 102#include <linux/fs.h>
dace20dc 103#if defined(CONFIG_FIEMAP)
285da2b9 104#include <linux/fiemap.h>
dace20dc 105#endif
f7680a55
UH
106#include <linux/fb.h>
107#include <linux/vt.h>
56e904ec 108#include <linux/dm-ioctl.h>
c07ecc68 109#include <linux/reboot.h>
7ff7b666 110#include <linux/route.h>
f57d4192 111#include <linux/filter.h>
fff8c539 112#include <linux/blkpg.h>
d7e4036e 113#include "linux_loop.h"
18cb0088 114#include "uname.h"
31e31b8a 115
3ef693a0 116#include "qemu.h"
31e31b8a 117
d865bab5
PB
118#define CLONE_NPTL_FLAGS2 (CLONE_SETTLS | \
119 CLONE_PARENT_SETTID | CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID)
30813cea 120
72f03900 121//#define DEBUG
31e31b8a 122
1a9353d2 123//#include <linux/msdos_fs.h>
6556a833
AJ
124#define VFAT_IOCTL_READDIR_BOTH _IOR('r', 1, struct linux_dirent [2])
125#define VFAT_IOCTL_READDIR_SHORT _IOR('r', 2, struct linux_dirent [2])
1a9353d2 126
70a194b9 127
70a194b9
FB
128#undef _syscall0
129#undef _syscall1
130#undef _syscall2
131#undef _syscall3
132#undef _syscall4
133#undef _syscall5
83fcb515 134#undef _syscall6
70a194b9 135
83fcb515 136#define _syscall0(type,name) \
8fcd3692 137static type name (void) \
83fcb515
FB
138{ \
139 return syscall(__NR_##name); \
140}
70a194b9 141
83fcb515 142#define _syscall1(type,name,type1,arg1) \
8fcd3692 143static type name (type1 arg1) \
83fcb515
FB
144{ \
145 return syscall(__NR_##name, arg1); \
70a194b9
FB
146}
147
83fcb515 148#define _syscall2(type,name,type1,arg1,type2,arg2) \
8fcd3692 149static type name (type1 arg1,type2 arg2) \
83fcb515
FB
150{ \
151 return syscall(__NR_##name, arg1, arg2); \
70a194b9
FB
152}
153
83fcb515 154#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \
8fcd3692 155static type name (type1 arg1,type2 arg2,type3 arg3) \
83fcb515
FB
156{ \
157 return syscall(__NR_##name, arg1, arg2, arg3); \
70a194b9
FB
158}
159
83fcb515 160#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \
8fcd3692 161static type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4) \
83fcb515
FB
162{ \
163 return syscall(__NR_##name, arg1, arg2, arg3, arg4); \
70a194b9
FB
164}
165
83fcb515
FB
166#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
167 type5,arg5) \
8fcd3692 168static type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \
83fcb515
FB
169{ \
170 return syscall(__NR_##name, arg1, arg2, arg3, arg4, arg5); \
70a194b9
FB
171}
172
83fcb515
FB
173
174#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
175 type5,arg5,type6,arg6) \
8fcd3692
BS
176static type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5, \
177 type6 arg6) \
83fcb515
FB
178{ \
179 return syscall(__NR_##name, arg1, arg2, arg3, arg4, arg5, arg6); \
70a194b9 180}
83fcb515 181
70a194b9 182
31e31b8a 183#define __NR_sys_uname __NR_uname
72f03900 184#define __NR_sys_getcwd1 __NR_getcwd
72f03900 185#define __NR_sys_getdents __NR_getdents
dab2ed99 186#define __NR_sys_getdents64 __NR_getdents64
c6cda17a 187#define __NR_sys_getpriority __NR_getpriority
66fb9763 188#define __NR_sys_rt_sigqueueinfo __NR_rt_sigqueueinfo
7494b0f9 189#define __NR_sys_syslog __NR_syslog
71455574 190#define __NR_sys_tgkill __NR_tgkill
4cae1d16 191#define __NR_sys_tkill __NR_tkill
bd0c5661 192#define __NR_sys_futex __NR_futex
39b59763
AJ
193#define __NR_sys_inotify_init __NR_inotify_init
194#define __NR_sys_inotify_add_watch __NR_inotify_add_watch
195#define __NR_sys_inotify_rm_watch __NR_inotify_rm_watch
31e31b8a 196
42a39fbe
AG
197#if defined(__alpha__) || defined (__ia64__) || defined(__x86_64__) || \
198 defined(__s390x__)
9af9eaaa
FB
199#define __NR__llseek __NR_lseek
200#endif
201
a29e5ba2
JH
202/* Newer kernel ports have llseek() instead of _llseek() */
203#if defined(TARGET_NR_llseek) && !defined(TARGET_NR__llseek)
204#define TARGET_NR__llseek TARGET_NR_llseek
205#endif
206
72f03900 207#ifdef __NR_gettid
31e31b8a 208_syscall0(int, gettid)
72f03900 209#else
0da46a6e
TS
210/* This is a replacement for the host gettid() and must return a host
211 errno. */
72f03900
FB
212static int gettid(void) {
213 return -ENOSYS;
214}
215#endif
3307e236 216#ifdef __NR_getdents
3b3f24ad 217_syscall3(int, sys_getdents, uint, fd, struct linux_dirent *, dirp, uint, count);
3307e236
PM
218#endif
219#if !defined(__NR_getdents) || \
220 (defined(TARGET_NR_getdents64) && defined(__NR_getdents64))
3b3f24ad
AJ
221_syscall3(int, sys_getdents64, uint, fd, struct linux_dirent64 *, dirp, uint, count);
222#endif
d35b261c 223#if defined(TARGET_NR__llseek) && defined(__NR_llseek)
3b3f24ad
AJ
224_syscall5(int, _llseek, uint, fd, ulong, hi, ulong, lo,
225 loff_t *, res, uint, wh);
226#endif
227_syscall3(int,sys_rt_sigqueueinfo,int,pid,int,sig,siginfo_t *,uinfo)
228_syscall3(int,sys_syslog,int,type,char*,bufp,int,len)
229#if defined(TARGET_NR_tgkill) && defined(__NR_tgkill)
230_syscall3(int,sys_tgkill,int,tgid,int,pid,int,sig)
231#endif
232#if defined(TARGET_NR_tkill) && defined(__NR_tkill)
233_syscall2(int,sys_tkill,int,tid,int,sig)
234#endif
235#ifdef __NR_exit_group
236_syscall1(int,exit_group,int,error_code)
237#endif
238#if defined(TARGET_NR_set_tid_address) && defined(__NR_set_tid_address)
239_syscall1(int,set_tid_address,int *,tidptr)
240#endif
3b3f24ad
AJ
241#if defined(TARGET_NR_futex) && defined(__NR_futex)
242_syscall6(int,sys_futex,int *,uaddr,int,op,int,val,
243 const struct timespec *,timeout,int *,uaddr2,int,val3)
244#endif
737de1d1
MF
245#define __NR_sys_sched_getaffinity __NR_sched_getaffinity
246_syscall3(int, sys_sched_getaffinity, pid_t, pid, unsigned int, len,
247 unsigned long *, user_mask_ptr);
248#define __NR_sys_sched_setaffinity __NR_sched_setaffinity
249_syscall3(int, sys_sched_setaffinity, pid_t, pid, unsigned int, len,
250 unsigned long *, user_mask_ptr);
0f6b4d21
AG
251_syscall4(int, reboot, int, magic1, int, magic2, unsigned int, cmd,
252 void *, arg);
e0eb210e
PM
253_syscall2(int, capget, struct __user_cap_header_struct *, header,
254 struct __user_cap_data_struct *, data);
255_syscall2(int, capset, struct __user_cap_header_struct *, header,
256 struct __user_cap_data_struct *, data);
ab31cda3
PB
257#if defined(TARGET_NR_ioprio_get) && defined(__NR_ioprio_get)
258_syscall2(int, ioprio_get, int, which, int, who)
259#endif
260#if defined(TARGET_NR_ioprio_set) && defined(__NR_ioprio_set)
261_syscall3(int, ioprio_set, int, which, int, who, int, ioprio)
262#endif
3b3f24ad
AJ
263
264static bitmask_transtbl fcntl_flags_tbl[] = {
265 { TARGET_O_ACCMODE, TARGET_O_WRONLY, O_ACCMODE, O_WRONLY, },
266 { TARGET_O_ACCMODE, TARGET_O_RDWR, O_ACCMODE, O_RDWR, },
267 { TARGET_O_CREAT, TARGET_O_CREAT, O_CREAT, O_CREAT, },
268 { TARGET_O_EXCL, TARGET_O_EXCL, O_EXCL, O_EXCL, },
269 { TARGET_O_NOCTTY, TARGET_O_NOCTTY, O_NOCTTY, O_NOCTTY, },
270 { TARGET_O_TRUNC, TARGET_O_TRUNC, O_TRUNC, O_TRUNC, },
271 { TARGET_O_APPEND, TARGET_O_APPEND, O_APPEND, O_APPEND, },
272 { TARGET_O_NONBLOCK, TARGET_O_NONBLOCK, O_NONBLOCK, O_NONBLOCK, },
afc8763f 273 { TARGET_O_SYNC, TARGET_O_DSYNC, O_SYNC, O_DSYNC, },
3b3f24ad
AJ
274 { TARGET_O_SYNC, TARGET_O_SYNC, O_SYNC, O_SYNC, },
275 { TARGET_FASYNC, TARGET_FASYNC, FASYNC, FASYNC, },
276 { TARGET_O_DIRECTORY, TARGET_O_DIRECTORY, O_DIRECTORY, O_DIRECTORY, },
277 { TARGET_O_NOFOLLOW, TARGET_O_NOFOLLOW, O_NOFOLLOW, O_NOFOLLOW, },
3b3f24ad
AJ
278#if defined(O_DIRECT)
279 { TARGET_O_DIRECT, TARGET_O_DIRECT, O_DIRECT, O_DIRECT, },
afc8763f
RH
280#endif
281#if defined(O_NOATIME)
282 { TARGET_O_NOATIME, TARGET_O_NOATIME, O_NOATIME, O_NOATIME },
283#endif
284#if defined(O_CLOEXEC)
285 { TARGET_O_CLOEXEC, TARGET_O_CLOEXEC, O_CLOEXEC, O_CLOEXEC },
286#endif
287#if defined(O_PATH)
288 { TARGET_O_PATH, TARGET_O_PATH, O_PATH, O_PATH },
289#endif
290 /* Don't terminate the list prematurely on 64-bit host+guest. */
291#if TARGET_O_LARGEFILE != 0 || O_LARGEFILE != 0
292 { TARGET_O_LARGEFILE, TARGET_O_LARGEFILE, O_LARGEFILE, O_LARGEFILE, },
3b3f24ad
AJ
293#endif
294 { 0, 0, 0, 0 }
295};
296
3b3f24ad
AJ
297static int sys_getcwd1(char *buf, size_t size)
298{
299 if (getcwd(buf, size) == NULL) {
300 /* getcwd() sets errno */
301 return (-1);
302 }
aaf4ad39 303 return strlen(buf)+1;
3b3f24ad
AJ
304}
305
f4c69010 306static int sys_openat(int dirfd, const char *pathname, int flags, mode_t mode)
3b3f24ad
AJ
307{
308 /*
309 * open(2) has extra parameter 'mode' when called with
310 * flag O_CREAT.
311 */
312 if ((flags & O_CREAT) != 0) {
3b3f24ad
AJ
313 return (openat(dirfd, pathname, flags, mode));
314 }
315 return (openat(dirfd, pathname, flags));
316}
ebc996f3 317
1acae9f2 318#ifdef TARGET_NR_utimensat
ebc996f3
RV
319#ifdef CONFIG_UTIMENSAT
320static int sys_utimensat(int dirfd, const char *pathname,
321 const struct timespec times[2], int flags)
322{
323 if (pathname == NULL)
324 return futimens(dirfd, times);
325 else
326 return utimensat(dirfd, pathname, times, flags);
327}
1acae9f2
PM
328#elif defined(__NR_utimensat)
329#define __NR_sys_utimensat __NR_utimensat
9007f0ef
TS
330_syscall4(int,sys_utimensat,int,dirfd,const char *,pathname,
331 const struct timespec *,tsp,int,flags)
1acae9f2
PM
332#else
333static int sys_utimensat(int dirfd, const char *pathname,
334 const struct timespec times[2], int flags)
335{
336 errno = ENOSYS;
337 return -1;
338}
9007f0ef 339#endif
1acae9f2 340#endif /* TARGET_NR_utimensat */
3b3f24ad
AJ
341
342#ifdef CONFIG_INOTIFY
8690e420 343#include <sys/inotify.h>
3b3f24ad 344
39b59763 345#if defined(TARGET_NR_inotify_init) && defined(__NR_inotify_init)
3b3f24ad
AJ
346static int sys_inotify_init(void)
347{
348 return (inotify_init());
349}
39b59763
AJ
350#endif
351#if defined(TARGET_NR_inotify_add_watch) && defined(__NR_inotify_add_watch)
3b3f24ad
AJ
352static int sys_inotify_add_watch(int fd,const char *pathname, int32_t mask)
353{
354 return (inotify_add_watch(fd, pathname, mask));
355}
39b59763
AJ
356#endif
357#if defined(TARGET_NR_inotify_rm_watch) && defined(__NR_inotify_rm_watch)
3b3f24ad
AJ
358static int sys_inotify_rm_watch(int fd, int32_t wd)
359{
8690e420 360 return (inotify_rm_watch(fd, wd));
3b3f24ad 361}
bd0c5661 362#endif
c05c7a73
RV
363#ifdef CONFIG_INOTIFY1
364#if defined(TARGET_NR_inotify_init1) && defined(__NR_inotify_init1)
365static int sys_inotify_init1(int flags)
366{
367 return (inotify_init1(flags));
368}
369#endif
370#endif
3b3f24ad
AJ
371#else
372/* Userspace can usually survive runtime without inotify */
373#undef TARGET_NR_inotify_init
c05c7a73 374#undef TARGET_NR_inotify_init1
3b3f24ad
AJ
375#undef TARGET_NR_inotify_add_watch
376#undef TARGET_NR_inotify_rm_watch
377#endif /* CONFIG_INOTIFY */
378
d8035d4c
MF
379#if defined(TARGET_NR_ppoll)
380#ifndef __NR_ppoll
381# define __NR_ppoll -1
382#endif
383#define __NR_sys_ppoll __NR_ppoll
384_syscall5(int, sys_ppoll, struct pollfd *, fds, nfds_t, nfds,
34d60862 385 struct timespec *, timeout, const sigset_t *, sigmask,
d8035d4c
MF
386 size_t, sigsetsize)
387#endif
66fb9763 388
055e0906
MF
389#if defined(TARGET_NR_pselect6)
390#ifndef __NR_pselect6
391# define __NR_pselect6 -1
392#endif
393#define __NR_sys_pselect6 __NR_pselect6
394_syscall6(int, sys_pselect6, int, nfds, fd_set *, readfds, fd_set *, writefds,
395 fd_set *, exceptfds, struct timespec *, timeout, void *, sig);
396#endif
397
163a05a8
PM
398#if defined(TARGET_NR_prlimit64)
399#ifndef __NR_prlimit64
400# define __NR_prlimit64 -1
401#endif
402#define __NR_sys_prlimit64 __NR_prlimit64
403/* The glibc rlimit structure may not be that used by the underlying syscall */
404struct host_rlimit64 {
405 uint64_t rlim_cur;
406 uint64_t rlim_max;
407};
408_syscall4(int, sys_prlimit64, pid_t, pid, int, resource,
409 const struct host_rlimit64 *, new_limit,
410 struct host_rlimit64 *, old_limit)
411#endif
412
f4f1e10a
ECL
413
414#if defined(TARGET_NR_timer_create)
415/* Maxiumum of 32 active POSIX timers allowed at any one time. */
416static timer_t g_posix_timers[32] = { 0, } ;
417
418static inline int next_free_host_timer(void)
419{
420 int k ;
421 /* FIXME: Does finding the next free slot require a lock? */
422 for (k = 0; k < ARRAY_SIZE(g_posix_timers); k++) {
423 if (g_posix_timers[k] == 0) {
424 g_posix_timers[k] = (timer_t) 1;
425 return k;
426 }
427 }
428 return -1;
429}
430#endif
431
48e515d4 432/* ARM EABI and MIPS expect 64bit types aligned even on pairs or registers */
4a1def4e 433#ifdef TARGET_ARM
48e515d4
RV
434static inline int regpairs_aligned(void *cpu_env) {
435 return ((((CPUARMState *)cpu_env)->eabi) == 1) ;
436}
437#elif defined(TARGET_MIPS)
438static inline int regpairs_aligned(void *cpu_env) { return 1; }
4a1def4e
AG
439#elif defined(TARGET_PPC) && !defined(TARGET_PPC64)
440/* SysV AVI for PPC32 expects 64bit parameters to be passed on odd/even pairs
441 * of registers which translates to the same as ARM/MIPS, because we start with
442 * r3 as arg1 */
443static inline int regpairs_aligned(void *cpu_env) { return 1; }
48e515d4
RV
444#else
445static inline int regpairs_aligned(void *cpu_env) { return 0; }
446#endif
447
b92c47c1
TS
448#define ERRNO_TABLE_SIZE 1200
449
450/* target_to_host_errno_table[] is initialized from
451 * host_to_target_errno_table[] in syscall_init(). */
452static uint16_t target_to_host_errno_table[ERRNO_TABLE_SIZE] = {
453};
454
637947f1 455/*
fe8f096b 456 * This list is the union of errno values overridden in asm-<arch>/errno.h
637947f1
TS
457 * minus the errnos that are not actually generic to all archs.
458 */
b92c47c1 459static uint16_t host_to_target_errno_table[ERRNO_TABLE_SIZE] = {
637947f1
TS
460 [EIDRM] = TARGET_EIDRM,
461 [ECHRNG] = TARGET_ECHRNG,
462 [EL2NSYNC] = TARGET_EL2NSYNC,
463 [EL3HLT] = TARGET_EL3HLT,
464 [EL3RST] = TARGET_EL3RST,
465 [ELNRNG] = TARGET_ELNRNG,
466 [EUNATCH] = TARGET_EUNATCH,
467 [ENOCSI] = TARGET_ENOCSI,
468 [EL2HLT] = TARGET_EL2HLT,
469 [EDEADLK] = TARGET_EDEADLK,
470 [ENOLCK] = TARGET_ENOLCK,
471 [EBADE] = TARGET_EBADE,
472 [EBADR] = TARGET_EBADR,
473 [EXFULL] = TARGET_EXFULL,
474 [ENOANO] = TARGET_ENOANO,
475 [EBADRQC] = TARGET_EBADRQC,
476 [EBADSLT] = TARGET_EBADSLT,
477 [EBFONT] = TARGET_EBFONT,
478 [ENOSTR] = TARGET_ENOSTR,
479 [ENODATA] = TARGET_ENODATA,
480 [ETIME] = TARGET_ETIME,
481 [ENOSR] = TARGET_ENOSR,
482 [ENONET] = TARGET_ENONET,
483 [ENOPKG] = TARGET_ENOPKG,
484 [EREMOTE] = TARGET_EREMOTE,
485 [ENOLINK] = TARGET_ENOLINK,
486 [EADV] = TARGET_EADV,
487 [ESRMNT] = TARGET_ESRMNT,
488 [ECOMM] = TARGET_ECOMM,
489 [EPROTO] = TARGET_EPROTO,
490 [EDOTDOT] = TARGET_EDOTDOT,
491 [EMULTIHOP] = TARGET_EMULTIHOP,
492 [EBADMSG] = TARGET_EBADMSG,
493 [ENAMETOOLONG] = TARGET_ENAMETOOLONG,
494 [EOVERFLOW] = TARGET_EOVERFLOW,
495 [ENOTUNIQ] = TARGET_ENOTUNIQ,
496 [EBADFD] = TARGET_EBADFD,
497 [EREMCHG] = TARGET_EREMCHG,
498 [ELIBACC] = TARGET_ELIBACC,
499 [ELIBBAD] = TARGET_ELIBBAD,
500 [ELIBSCN] = TARGET_ELIBSCN,
501 [ELIBMAX] = TARGET_ELIBMAX,
502 [ELIBEXEC] = TARGET_ELIBEXEC,
503 [EILSEQ] = TARGET_EILSEQ,
504 [ENOSYS] = TARGET_ENOSYS,
505 [ELOOP] = TARGET_ELOOP,
506 [ERESTART] = TARGET_ERESTART,
507 [ESTRPIPE] = TARGET_ESTRPIPE,
508 [ENOTEMPTY] = TARGET_ENOTEMPTY,
509 [EUSERS] = TARGET_EUSERS,
510 [ENOTSOCK] = TARGET_ENOTSOCK,
511 [EDESTADDRREQ] = TARGET_EDESTADDRREQ,
512 [EMSGSIZE] = TARGET_EMSGSIZE,
513 [EPROTOTYPE] = TARGET_EPROTOTYPE,
514 [ENOPROTOOPT] = TARGET_ENOPROTOOPT,
515 [EPROTONOSUPPORT] = TARGET_EPROTONOSUPPORT,
516 [ESOCKTNOSUPPORT] = TARGET_ESOCKTNOSUPPORT,
517 [EOPNOTSUPP] = TARGET_EOPNOTSUPP,
518 [EPFNOSUPPORT] = TARGET_EPFNOSUPPORT,
519 [EAFNOSUPPORT] = TARGET_EAFNOSUPPORT,
520 [EADDRINUSE] = TARGET_EADDRINUSE,
521 [EADDRNOTAVAIL] = TARGET_EADDRNOTAVAIL,
522 [ENETDOWN] = TARGET_ENETDOWN,
523 [ENETUNREACH] = TARGET_ENETUNREACH,
524 [ENETRESET] = TARGET_ENETRESET,
525 [ECONNABORTED] = TARGET_ECONNABORTED,
526 [ECONNRESET] = TARGET_ECONNRESET,
527 [ENOBUFS] = TARGET_ENOBUFS,
528 [EISCONN] = TARGET_EISCONN,
529 [ENOTCONN] = TARGET_ENOTCONN,
530 [EUCLEAN] = TARGET_EUCLEAN,
531 [ENOTNAM] = TARGET_ENOTNAM,
532 [ENAVAIL] = TARGET_ENAVAIL,
533 [EISNAM] = TARGET_EISNAM,
534 [EREMOTEIO] = TARGET_EREMOTEIO,
535 [ESHUTDOWN] = TARGET_ESHUTDOWN,
536 [ETOOMANYREFS] = TARGET_ETOOMANYREFS,
537 [ETIMEDOUT] = TARGET_ETIMEDOUT,
538 [ECONNREFUSED] = TARGET_ECONNREFUSED,
539 [EHOSTDOWN] = TARGET_EHOSTDOWN,
540 [EHOSTUNREACH] = TARGET_EHOSTUNREACH,
541 [EALREADY] = TARGET_EALREADY,
542 [EINPROGRESS] = TARGET_EINPROGRESS,
543 [ESTALE] = TARGET_ESTALE,
544 [ECANCELED] = TARGET_ECANCELED,
545 [ENOMEDIUM] = TARGET_ENOMEDIUM,
546 [EMEDIUMTYPE] = TARGET_EMEDIUMTYPE,
b7fe5db7 547#ifdef ENOKEY
637947f1 548 [ENOKEY] = TARGET_ENOKEY,
b7fe5db7
TS
549#endif
550#ifdef EKEYEXPIRED
637947f1 551 [EKEYEXPIRED] = TARGET_EKEYEXPIRED,
b7fe5db7
TS
552#endif
553#ifdef EKEYREVOKED
637947f1 554 [EKEYREVOKED] = TARGET_EKEYREVOKED,
b7fe5db7
TS
555#endif
556#ifdef EKEYREJECTED
637947f1 557 [EKEYREJECTED] = TARGET_EKEYREJECTED,
b7fe5db7
TS
558#endif
559#ifdef EOWNERDEAD
637947f1 560 [EOWNERDEAD] = TARGET_EOWNERDEAD,
b7fe5db7
TS
561#endif
562#ifdef ENOTRECOVERABLE
637947f1 563 [ENOTRECOVERABLE] = TARGET_ENOTRECOVERABLE,
b7fe5db7 564#endif
b92c47c1 565};
637947f1
TS
566
567static inline int host_to_target_errno(int err)
568{
569 if(host_to_target_errno_table[err])
570 return host_to_target_errno_table[err];
571 return err;
572}
573
b92c47c1
TS
574static inline int target_to_host_errno(int err)
575{
576 if (target_to_host_errno_table[err])
577 return target_to_host_errno_table[err];
578 return err;
579}
580
992f48a0 581static inline abi_long get_errno(abi_long ret)
31e31b8a
FB
582{
583 if (ret == -1)
637947f1 584 return -host_to_target_errno(errno);
31e31b8a
FB
585 else
586 return ret;
587}
588
992f48a0 589static inline int is_error(abi_long ret)
31e31b8a 590{
992f48a0 591 return (abi_ulong)ret >= (abi_ulong)(-4096);
31e31b8a
FB
592}
593
b92c47c1
TS
594char *target_strerror(int err)
595{
962b289e
AG
596 if ((err >= ERRNO_TABLE_SIZE) || (err < 0)) {
597 return NULL;
598 }
b92c47c1
TS
599 return strerror(target_to_host_errno(err));
600}
601
8289d112
PB
602static inline int host_to_target_sock_type(int host_type)
603{
604 int target_type;
605
606 switch (host_type & 0xf /* SOCK_TYPE_MASK */) {
607 case SOCK_DGRAM:
608 target_type = TARGET_SOCK_DGRAM;
609 break;
610 case SOCK_STREAM:
611 target_type = TARGET_SOCK_STREAM;
612 break;
613 default:
614 target_type = host_type & 0xf /* SOCK_TYPE_MASK */;
615 break;
616 }
617
618#if defined(SOCK_CLOEXEC)
619 if (host_type & SOCK_CLOEXEC) {
620 target_type |= TARGET_SOCK_CLOEXEC;
621 }
622#endif
623
624#if defined(SOCK_NONBLOCK)
625 if (host_type & SOCK_NONBLOCK) {
626 target_type |= TARGET_SOCK_NONBLOCK;
627 }
628#endif
629
630 return target_type;
631}
632
992f48a0
BS
633static abi_ulong target_brk;
634static abi_ulong target_original_brk;
4d1de87c 635static abi_ulong brk_page;
31e31b8a 636
992f48a0 637void target_set_brk(abi_ulong new_brk)
31e31b8a 638{
4c1de73d 639 target_original_brk = target_brk = HOST_PAGE_ALIGN(new_brk);
4d1de87c 640 brk_page = HOST_PAGE_ALIGN(target_brk);
31e31b8a
FB
641}
642
4d1de87c
CV
643//#define DEBUGF_BRK(message, args...) do { fprintf(stderr, (message), ## args); } while (0)
644#define DEBUGF_BRK(message, args...)
645
0da46a6e 646/* do_brk() must return target values and target errnos. */
992f48a0 647abi_long do_brk(abi_ulong new_brk)
31e31b8a 648{
992f48a0 649 abi_long mapped_addr;
31e31b8a
FB
650 int new_alloc_size;
651
3a0c6c4a 652 DEBUGF_BRK("do_brk(" TARGET_ABI_FMT_lx ") -> ", new_brk);
4d1de87c
CV
653
654 if (!new_brk) {
3a0c6c4a 655 DEBUGF_BRK(TARGET_ABI_FMT_lx " (!new_brk)\n", target_brk);
53a5960a 656 return target_brk;
4d1de87c
CV
657 }
658 if (new_brk < target_original_brk) {
3a0c6c4a
PB
659 DEBUGF_BRK(TARGET_ABI_FMT_lx " (new_brk < target_original_brk)\n",
660 target_brk);
7ab240ad 661 return target_brk;
4d1de87c 662 }
3b46e624 663
4d1de87c
CV
664 /* If the new brk is less than the highest page reserved to the
665 * target heap allocation, set it and we're almost done... */
666 if (new_brk <= brk_page) {
667 /* Heap contents are initialized to zero, as for anonymous
668 * mapped pages. */
669 if (new_brk > target_brk) {
670 memset(g2h(target_brk), 0, new_brk - target_brk);
671 }
31e31b8a 672 target_brk = new_brk;
3a0c6c4a 673 DEBUGF_BRK(TARGET_ABI_FMT_lx " (new_brk <= brk_page)\n", target_brk);
53a5960a 674 return target_brk;
31e31b8a
FB
675 }
676
00faf08c
PM
677 /* We need to allocate more memory after the brk... Note that
678 * we don't use MAP_FIXED because that will map over the top of
679 * any existing mapping (like the one with the host libc or qemu
680 * itself); instead we treat "mapped but at wrong address" as
681 * a failure and unmap again.
682 */
4d1de87c 683 new_alloc_size = HOST_PAGE_ALIGN(new_brk - brk_page);
5fafdf24 684 mapped_addr = get_errno(target_mmap(brk_page, new_alloc_size,
54936004 685 PROT_READ|PROT_WRITE,
00faf08c
PM
686 MAP_ANON|MAP_PRIVATE, 0, 0));
687
688 if (mapped_addr == brk_page) {
70afc343
CV
689 /* Heap contents are initialized to zero, as for anonymous
690 * mapped pages. Technically the new pages are already
691 * initialized to zero since they *are* anonymous mapped
692 * pages, however we have to take care with the contents that
693 * come from the remaining part of the previous page: it may
694 * contains garbage data due to a previous heap usage (grown
695 * then shrunken). */
696 memset(g2h(target_brk), 0, brk_page - target_brk);
697
00faf08c 698 target_brk = new_brk;
4d1de87c 699 brk_page = HOST_PAGE_ALIGN(target_brk);
3a0c6c4a
PB
700 DEBUGF_BRK(TARGET_ABI_FMT_lx " (mapped_addr == brk_page)\n",
701 target_brk);
00faf08c
PM
702 return target_brk;
703 } else if (mapped_addr != -1) {
704 /* Mapped but at wrong address, meaning there wasn't actually
705 * enough space for this brk.
706 */
707 target_munmap(mapped_addr, new_alloc_size);
708 mapped_addr = -1;
3a0c6c4a 709 DEBUGF_BRK(TARGET_ABI_FMT_lx " (mapped_addr != -1)\n", target_brk);
4d1de87c
CV
710 }
711 else {
3a0c6c4a 712 DEBUGF_BRK(TARGET_ABI_FMT_lx " (otherwise)\n", target_brk);
00faf08c 713 }
7ab240ad 714
7dd46c02
RH
715#if defined(TARGET_ALPHA)
716 /* We (partially) emulate OSF/1 on Alpha, which requires we
717 return a proper errno, not an unchanged brk value. */
00faf08c 718 return -TARGET_ENOMEM;
7dd46c02 719#endif
00faf08c 720 /* For everything else, return the previous break. */
7ab240ad 721 return target_brk;
31e31b8a
FB
722}
723
26edcf41
TS
724static inline abi_long copy_from_user_fdset(fd_set *fds,
725 abi_ulong target_fds_addr,
726 int n)
31e31b8a 727{
26edcf41
TS
728 int i, nw, j, k;
729 abi_ulong b, *target_fds;
730
731 nw = (n + TARGET_ABI_BITS - 1) / TARGET_ABI_BITS;
732 if (!(target_fds = lock_user(VERIFY_READ,
733 target_fds_addr,
734 sizeof(abi_ulong) * nw,
735 1)))
736 return -TARGET_EFAULT;
737
738 FD_ZERO(fds);
739 k = 0;
740 for (i = 0; i < nw; i++) {
741 /* grab the abi_ulong */
742 __get_user(b, &target_fds[i]);
743 for (j = 0; j < TARGET_ABI_BITS; j++) {
744 /* check the bit inside the abi_ulong */
745 if ((b >> j) & 1)
746 FD_SET(k, fds);
747 k++;
31e31b8a 748 }
31e31b8a 749 }
26edcf41
TS
750
751 unlock_user(target_fds, target_fds_addr, 0);
752
753 return 0;
31e31b8a
FB
754}
755
055e0906
MF
756static inline abi_ulong copy_from_user_fdset_ptr(fd_set *fds, fd_set **fds_ptr,
757 abi_ulong target_fds_addr,
758 int n)
759{
760 if (target_fds_addr) {
761 if (copy_from_user_fdset(fds, target_fds_addr, n))
762 return -TARGET_EFAULT;
763 *fds_ptr = fds;
764 } else {
765 *fds_ptr = NULL;
766 }
767 return 0;
768}
769
26edcf41
TS
770static inline abi_long copy_to_user_fdset(abi_ulong target_fds_addr,
771 const fd_set *fds,
772 int n)
31e31b8a 773{
31e31b8a 774 int i, nw, j, k;
992f48a0 775 abi_long v;
26edcf41 776 abi_ulong *target_fds;
31e31b8a 777
26edcf41
TS
778 nw = (n + TARGET_ABI_BITS - 1) / TARGET_ABI_BITS;
779 if (!(target_fds = lock_user(VERIFY_WRITE,
780 target_fds_addr,
781 sizeof(abi_ulong) * nw,
782 0)))
783 return -TARGET_EFAULT;
784
785 k = 0;
786 for (i = 0; i < nw; i++) {
787 v = 0;
788 for (j = 0; j < TARGET_ABI_BITS; j++) {
9ab709be 789 v |= ((abi_ulong)(FD_ISSET(k, fds) != 0) << j);
26edcf41 790 k++;
31e31b8a 791 }
26edcf41 792 __put_user(v, &target_fds[i]);
31e31b8a 793 }
26edcf41
TS
794
795 unlock_user(target_fds, target_fds_addr, sizeof(abi_ulong) * nw);
796
797 return 0;
31e31b8a
FB
798}
799
c596ed17
FB
800#if defined(__alpha__)
801#define HOST_HZ 1024
802#else
803#define HOST_HZ 100
804#endif
805
992f48a0 806static inline abi_long host_to_target_clock_t(long ticks)
c596ed17
FB
807{
808#if HOST_HZ == TARGET_HZ
809 return ticks;
810#else
811 return ((int64_t)ticks * TARGET_HZ) / HOST_HZ;
812#endif
813}
814
579a97f7
FB
815static inline abi_long host_to_target_rusage(abi_ulong target_addr,
816 const struct rusage *rusage)
b409186b 817{
53a5960a
PB
818 struct target_rusage *target_rusage;
819
579a97f7
FB
820 if (!lock_user_struct(VERIFY_WRITE, target_rusage, target_addr, 0))
821 return -TARGET_EFAULT;
cbb21eed
MB
822 target_rusage->ru_utime.tv_sec = tswapal(rusage->ru_utime.tv_sec);
823 target_rusage->ru_utime.tv_usec = tswapal(rusage->ru_utime.tv_usec);
824 target_rusage->ru_stime.tv_sec = tswapal(rusage->ru_stime.tv_sec);
825 target_rusage->ru_stime.tv_usec = tswapal(rusage->ru_stime.tv_usec);
826 target_rusage->ru_maxrss = tswapal(rusage->ru_maxrss);
827 target_rusage->ru_ixrss = tswapal(rusage->ru_ixrss);
828 target_rusage->ru_idrss = tswapal(rusage->ru_idrss);
829 target_rusage->ru_isrss = tswapal(rusage->ru_isrss);
830 target_rusage->ru_minflt = tswapal(rusage->ru_minflt);
831 target_rusage->ru_majflt = tswapal(rusage->ru_majflt);
832 target_rusage->ru_nswap = tswapal(rusage->ru_nswap);
833 target_rusage->ru_inblock = tswapal(rusage->ru_inblock);
834 target_rusage->ru_oublock = tswapal(rusage->ru_oublock);
835 target_rusage->ru_msgsnd = tswapal(rusage->ru_msgsnd);
836 target_rusage->ru_msgrcv = tswapal(rusage->ru_msgrcv);
837 target_rusage->ru_nsignals = tswapal(rusage->ru_nsignals);
838 target_rusage->ru_nvcsw = tswapal(rusage->ru_nvcsw);
839 target_rusage->ru_nivcsw = tswapal(rusage->ru_nivcsw);
53a5960a 840 unlock_user_struct(target_rusage, target_addr, 1);
579a97f7
FB
841
842 return 0;
b409186b
FB
843}
844
cbb21eed 845static inline rlim_t target_to_host_rlim(abi_ulong target_rlim)
81bbe906 846{
cbb21eed 847 abi_ulong target_rlim_swap;
95b33b2f
WT
848 rlim_t result;
849
cbb21eed
MB
850 target_rlim_swap = tswapal(target_rlim);
851 if (target_rlim_swap == TARGET_RLIM_INFINITY)
852 return RLIM_INFINITY;
853
854 result = target_rlim_swap;
855 if (target_rlim_swap != (rlim_t)result)
856 return RLIM_INFINITY;
95b33b2f
WT
857
858 return result;
81bbe906
TY
859}
860
cbb21eed 861static inline abi_ulong host_to_target_rlim(rlim_t rlim)
81bbe906 862{
cbb21eed
MB
863 abi_ulong target_rlim_swap;
864 abi_ulong result;
95b33b2f 865
cbb21eed 866 if (rlim == RLIM_INFINITY || rlim != (abi_long)rlim)
95b33b2f 867 target_rlim_swap = TARGET_RLIM_INFINITY;
81bbe906 868 else
95b33b2f 869 target_rlim_swap = rlim;
cbb21eed 870 result = tswapal(target_rlim_swap);
95b33b2f
WT
871
872 return result;
81bbe906
TY
873}
874
e22b7015
WT
875static inline int target_to_host_resource(int code)
876{
877 switch (code) {
878 case TARGET_RLIMIT_AS:
879 return RLIMIT_AS;
880 case TARGET_RLIMIT_CORE:
881 return RLIMIT_CORE;
882 case TARGET_RLIMIT_CPU:
883 return RLIMIT_CPU;
884 case TARGET_RLIMIT_DATA:
885 return RLIMIT_DATA;
886 case TARGET_RLIMIT_FSIZE:
887 return RLIMIT_FSIZE;
888 case TARGET_RLIMIT_LOCKS:
889 return RLIMIT_LOCKS;
890 case TARGET_RLIMIT_MEMLOCK:
891 return RLIMIT_MEMLOCK;
892 case TARGET_RLIMIT_MSGQUEUE:
893 return RLIMIT_MSGQUEUE;
894 case TARGET_RLIMIT_NICE:
895 return RLIMIT_NICE;
896 case TARGET_RLIMIT_NOFILE:
897 return RLIMIT_NOFILE;
898 case TARGET_RLIMIT_NPROC:
899 return RLIMIT_NPROC;
900 case TARGET_RLIMIT_RSS:
901 return RLIMIT_RSS;
902 case TARGET_RLIMIT_RTPRIO:
903 return RLIMIT_RTPRIO;
904 case TARGET_RLIMIT_SIGPENDING:
905 return RLIMIT_SIGPENDING;
906 case TARGET_RLIMIT_STACK:
907 return RLIMIT_STACK;
908 default:
909 return code;
910 }
911}
912
788f5ec4
TS
913static inline abi_long copy_from_user_timeval(struct timeval *tv,
914 abi_ulong target_tv_addr)
31e31b8a 915{
53a5960a
PB
916 struct target_timeval *target_tv;
917
788f5ec4 918 if (!lock_user_struct(VERIFY_READ, target_tv, target_tv_addr, 1))
579a97f7 919 return -TARGET_EFAULT;
788f5ec4
TS
920
921 __get_user(tv->tv_sec, &target_tv->tv_sec);
922 __get_user(tv->tv_usec, &target_tv->tv_usec);
923
924 unlock_user_struct(target_tv, target_tv_addr, 0);
579a97f7
FB
925
926 return 0;
31e31b8a
FB
927}
928
788f5ec4
TS
929static inline abi_long copy_to_user_timeval(abi_ulong target_tv_addr,
930 const struct timeval *tv)
31e31b8a 931{
53a5960a
PB
932 struct target_timeval *target_tv;
933
788f5ec4 934 if (!lock_user_struct(VERIFY_WRITE, target_tv, target_tv_addr, 0))
579a97f7 935 return -TARGET_EFAULT;
788f5ec4
TS
936
937 __put_user(tv->tv_sec, &target_tv->tv_sec);
938 __put_user(tv->tv_usec, &target_tv->tv_usec);
939
940 unlock_user_struct(target_tv, target_tv_addr, 1);
579a97f7
FB
941
942 return 0;
31e31b8a
FB
943}
944
ef4467e9
PB
945static inline abi_long copy_from_user_timezone(struct timezone *tz,
946 abi_ulong target_tz_addr)
947{
948 struct target_timezone *target_tz;
949
950 if (!lock_user_struct(VERIFY_READ, target_tz, target_tz_addr, 1)) {
951 return -TARGET_EFAULT;
952 }
953
954 __get_user(tz->tz_minuteswest, &target_tz->tz_minuteswest);
955 __get_user(tz->tz_dsttime, &target_tz->tz_dsttime);
956
957 unlock_user_struct(target_tz, target_tz_addr, 0);
958
959 return 0;
960}
961
8ec9cf89
NF
962#if defined(TARGET_NR_mq_open) && defined(__NR_mq_open)
963#include <mqueue.h>
964
24e1003a
AJ
965static inline abi_long copy_from_user_mq_attr(struct mq_attr *attr,
966 abi_ulong target_mq_attr_addr)
967{
968 struct target_mq_attr *target_mq_attr;
969
970 if (!lock_user_struct(VERIFY_READ, target_mq_attr,
971 target_mq_attr_addr, 1))
972 return -TARGET_EFAULT;
973
974 __get_user(attr->mq_flags, &target_mq_attr->mq_flags);
975 __get_user(attr->mq_maxmsg, &target_mq_attr->mq_maxmsg);
976 __get_user(attr->mq_msgsize, &target_mq_attr->mq_msgsize);
977 __get_user(attr->mq_curmsgs, &target_mq_attr->mq_curmsgs);
978
979 unlock_user_struct(target_mq_attr, target_mq_attr_addr, 0);
980
981 return 0;
982}
983
984static inline abi_long copy_to_user_mq_attr(abi_ulong target_mq_attr_addr,
985 const struct mq_attr *attr)
986{
987 struct target_mq_attr *target_mq_attr;
988
989 if (!lock_user_struct(VERIFY_WRITE, target_mq_attr,
990 target_mq_attr_addr, 0))
991 return -TARGET_EFAULT;
992
993 __put_user(attr->mq_flags, &target_mq_attr->mq_flags);
994 __put_user(attr->mq_maxmsg, &target_mq_attr->mq_maxmsg);
995 __put_user(attr->mq_msgsize, &target_mq_attr->mq_msgsize);
996 __put_user(attr->mq_curmsgs, &target_mq_attr->mq_curmsgs);
997
998 unlock_user_struct(target_mq_attr, target_mq_attr_addr, 1);
999
1000 return 0;
1001}
8ec9cf89 1002#endif
31e31b8a 1003
055e0906 1004#if defined(TARGET_NR_select) || defined(TARGET_NR__newselect)
0da46a6e 1005/* do_select() must return target values and target errnos. */
992f48a0 1006static abi_long do_select(int n,
26edcf41
TS
1007 abi_ulong rfd_addr, abi_ulong wfd_addr,
1008 abi_ulong efd_addr, abi_ulong target_tv_addr)
31e31b8a
FB
1009{
1010 fd_set rfds, wfds, efds;
1011 fd_set *rfds_ptr, *wfds_ptr, *efds_ptr;
1012 struct timeval tv, *tv_ptr;
992f48a0 1013 abi_long ret;
31e31b8a 1014
055e0906
MF
1015 ret = copy_from_user_fdset_ptr(&rfds, &rfds_ptr, rfd_addr, n);
1016 if (ret) {
1017 return ret;
53a5960a 1018 }
055e0906
MF
1019 ret = copy_from_user_fdset_ptr(&wfds, &wfds_ptr, wfd_addr, n);
1020 if (ret) {
1021 return ret;
53a5960a 1022 }
055e0906
MF
1023 ret = copy_from_user_fdset_ptr(&efds, &efds_ptr, efd_addr, n);
1024 if (ret) {
1025 return ret;
53a5960a 1026 }
3b46e624 1027
26edcf41 1028 if (target_tv_addr) {
788f5ec4
TS
1029 if (copy_from_user_timeval(&tv, target_tv_addr))
1030 return -TARGET_EFAULT;
31e31b8a
FB
1031 tv_ptr = &tv;
1032 } else {
1033 tv_ptr = NULL;
1034 }
26edcf41 1035
31e31b8a 1036 ret = get_errno(select(n, rfds_ptr, wfds_ptr, efds_ptr, tv_ptr));
53a5960a 1037
26edcf41
TS
1038 if (!is_error(ret)) {
1039 if (rfd_addr && copy_to_user_fdset(rfd_addr, &rfds, n))
1040 return -TARGET_EFAULT;
1041 if (wfd_addr && copy_to_user_fdset(wfd_addr, &wfds, n))
1042 return -TARGET_EFAULT;
1043 if (efd_addr && copy_to_user_fdset(efd_addr, &efds, n))
1044 return -TARGET_EFAULT;
31e31b8a 1045
788f5ec4
TS
1046 if (target_tv_addr && copy_to_user_timeval(target_tv_addr, &tv))
1047 return -TARGET_EFAULT;
31e31b8a 1048 }
579a97f7 1049
31e31b8a
FB
1050 return ret;
1051}
055e0906 1052#endif
31e31b8a 1053
099d6b0f
RV
1054static abi_long do_pipe2(int host_pipe[], int flags)
1055{
1056#ifdef CONFIG_PIPE2
1057 return pipe2(host_pipe, flags);
1058#else
1059 return -ENOSYS;
1060#endif
1061}
1062
fb41a66e
RH
1063static abi_long do_pipe(void *cpu_env, abi_ulong pipedes,
1064 int flags, int is_pipe2)
099d6b0f
RV
1065{
1066 int host_pipe[2];
1067 abi_long ret;
1068 ret = flags ? do_pipe2(host_pipe, flags) : pipe(host_pipe);
1069
1070 if (is_error(ret))
1071 return get_errno(ret);
fb41a66e
RH
1072
1073 /* Several targets have special calling conventions for the original
1074 pipe syscall, but didn't replicate this into the pipe2 syscall. */
1075 if (!is_pipe2) {
1076#if defined(TARGET_ALPHA)
1077 ((CPUAlphaState *)cpu_env)->ir[IR_A4] = host_pipe[1];
1078 return host_pipe[0];
1079#elif defined(TARGET_MIPS)
1080 ((CPUMIPSState*)cpu_env)->active_tc.gpr[3] = host_pipe[1];
1081 return host_pipe[0];
1082#elif defined(TARGET_SH4)
597c0212 1083 ((CPUSH4State*)cpu_env)->gregs[1] = host_pipe[1];
fb41a66e 1084 return host_pipe[0];
82f05b69
PM
1085#elif defined(TARGET_SPARC)
1086 ((CPUSPARCState*)cpu_env)->regwptr[1] = host_pipe[1];
1087 return host_pipe[0];
597c0212 1088#endif
fb41a66e
RH
1089 }
1090
099d6b0f
RV
1091 if (put_user_s32(host_pipe[0], pipedes)
1092 || put_user_s32(host_pipe[1], pipedes + sizeof(host_pipe[0])))
1093 return -TARGET_EFAULT;
099d6b0f
RV
1094 return get_errno(ret);
1095}
1096
b975b83b
LL
1097static inline abi_long target_to_host_ip_mreq(struct ip_mreqn *mreqn,
1098 abi_ulong target_addr,
1099 socklen_t len)
1100{
1101 struct target_ip_mreqn *target_smreqn;
1102
1103 target_smreqn = lock_user(VERIFY_READ, target_addr, len, 1);
1104 if (!target_smreqn)
1105 return -TARGET_EFAULT;
1106 mreqn->imr_multiaddr.s_addr = target_smreqn->imr_multiaddr.s_addr;
1107 mreqn->imr_address.s_addr = target_smreqn->imr_address.s_addr;
1108 if (len == sizeof(struct target_ip_mreqn))
cbb21eed 1109 mreqn->imr_ifindex = tswapal(target_smreqn->imr_ifindex);
b975b83b
LL
1110 unlock_user(target_smreqn, target_addr, 0);
1111
1112 return 0;
1113}
1114
579a97f7
FB
1115static inline abi_long target_to_host_sockaddr(struct sockaddr *addr,
1116 abi_ulong target_addr,
1117 socklen_t len)
7854b056 1118{
607175e0
AJ
1119 const socklen_t unix_maxlen = sizeof (struct sockaddr_un);
1120 sa_family_t sa_family;
53a5960a
PB
1121 struct target_sockaddr *target_saddr;
1122
579a97f7
FB
1123 target_saddr = lock_user(VERIFY_READ, target_addr, len, 1);
1124 if (!target_saddr)
1125 return -TARGET_EFAULT;
607175e0
AJ
1126
1127 sa_family = tswap16(target_saddr->sa_family);
1128
1129 /* Oops. The caller might send a incomplete sun_path; sun_path
1130 * must be terminated by \0 (see the manual page), but
1131 * unfortunately it is quite common to specify sockaddr_un
1132 * length as "strlen(x->sun_path)" while it should be
1133 * "strlen(...) + 1". We'll fix that here if needed.
1134 * Linux kernel has a similar feature.
1135 */
1136
1137 if (sa_family == AF_UNIX) {
1138 if (len < unix_maxlen && len > 0) {
1139 char *cp = (char*)target_saddr;
1140
1141 if ( cp[len-1] && !cp[len] )
1142 len++;
1143 }
1144 if (len > unix_maxlen)
1145 len = unix_maxlen;
1146 }
1147
53a5960a 1148 memcpy(addr, target_saddr, len);
607175e0 1149 addr->sa_family = sa_family;
33a29b51
JT
1150 if (sa_family == AF_PACKET) {
1151 struct target_sockaddr_ll *lladdr;
1152
1153 lladdr = (struct target_sockaddr_ll *)addr;
1154 lladdr->sll_ifindex = tswap32(lladdr->sll_ifindex);
1155 lladdr->sll_hatype = tswap16(lladdr->sll_hatype);
1156 }
53a5960a 1157 unlock_user(target_saddr, target_addr, 0);
579a97f7
FB
1158
1159 return 0;
7854b056
FB
1160}
1161
579a97f7
FB
1162static inline abi_long host_to_target_sockaddr(abi_ulong target_addr,
1163 struct sockaddr *addr,
1164 socklen_t len)
7854b056 1165{
53a5960a
PB
1166 struct target_sockaddr *target_saddr;
1167
579a97f7
FB
1168 target_saddr = lock_user(VERIFY_WRITE, target_addr, len, 0);
1169 if (!target_saddr)
1170 return -TARGET_EFAULT;
53a5960a
PB
1171 memcpy(target_saddr, addr, len);
1172 target_saddr->sa_family = tswap16(addr->sa_family);
1173 unlock_user(target_saddr, target_addr, len);
579a97f7
FB
1174
1175 return 0;
7854b056
FB
1176}
1177
5a4a898d
FB
1178static inline abi_long target_to_host_cmsg(struct msghdr *msgh,
1179 struct target_msghdr *target_msgh)
7854b056
FB
1180{
1181 struct cmsghdr *cmsg = CMSG_FIRSTHDR(msgh);
5a4a898d
FB
1182 abi_long msg_controllen;
1183 abi_ulong target_cmsg_addr;
1184 struct target_cmsghdr *target_cmsg;
7854b056 1185 socklen_t space = 0;
5a4a898d 1186
cbb21eed 1187 msg_controllen = tswapal(target_msgh->msg_controllen);
5a4a898d
FB
1188 if (msg_controllen < sizeof (struct target_cmsghdr))
1189 goto the_end;
cbb21eed 1190 target_cmsg_addr = tswapal(target_msgh->msg_control);
5a4a898d
FB
1191 target_cmsg = lock_user(VERIFY_READ, target_cmsg_addr, msg_controllen, 1);
1192 if (!target_cmsg)
1193 return -TARGET_EFAULT;
7854b056
FB
1194
1195 while (cmsg && target_cmsg) {
1196 void *data = CMSG_DATA(cmsg);
1197 void *target_data = TARGET_CMSG_DATA(target_cmsg);
1198
cbb21eed 1199 int len = tswapal(target_cmsg->cmsg_len)
7854b056
FB
1200 - TARGET_CMSG_ALIGN(sizeof (struct target_cmsghdr));
1201
1202 space += CMSG_SPACE(len);
1203 if (space > msgh->msg_controllen) {
1204 space -= CMSG_SPACE(len);
31febb71 1205 gemu_log("Host cmsg overflow\n");
7854b056
FB
1206 break;
1207 }
1208
dbf4f796
PJ
1209 if (tswap32(target_cmsg->cmsg_level) == TARGET_SOL_SOCKET) {
1210 cmsg->cmsg_level = SOL_SOCKET;
1211 } else {
1212 cmsg->cmsg_level = tswap32(target_cmsg->cmsg_level);
1213 }
7854b056
FB
1214 cmsg->cmsg_type = tswap32(target_cmsg->cmsg_type);
1215 cmsg->cmsg_len = CMSG_LEN(len);
1216
dbf4f796 1217 if (cmsg->cmsg_level != SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS) {
7854b056
FB
1218 gemu_log("Unsupported ancillary data: %d/%d\n", cmsg->cmsg_level, cmsg->cmsg_type);
1219 memcpy(data, target_data, len);
1220 } else {
1221 int *fd = (int *)data;
1222 int *target_fd = (int *)target_data;
1223 int i, numfds = len / sizeof(int);
1224
1225 for (i = 0; i < numfds; i++)
1226 fd[i] = tswap32(target_fd[i]);
1227 }
1228
1229 cmsg = CMSG_NXTHDR(msgh, cmsg);
1230 target_cmsg = TARGET_CMSG_NXTHDR(target_msgh, target_cmsg);
1231 }
5a4a898d
FB
1232 unlock_user(target_cmsg, target_cmsg_addr, 0);
1233 the_end:
7854b056 1234 msgh->msg_controllen = space;
5a4a898d 1235 return 0;
7854b056
FB
1236}
1237
5a4a898d
FB
1238static inline abi_long host_to_target_cmsg(struct target_msghdr *target_msgh,
1239 struct msghdr *msgh)
7854b056
FB
1240{
1241 struct cmsghdr *cmsg = CMSG_FIRSTHDR(msgh);
5a4a898d
FB
1242 abi_long msg_controllen;
1243 abi_ulong target_cmsg_addr;
1244 struct target_cmsghdr *target_cmsg;
7854b056
FB
1245 socklen_t space = 0;
1246
cbb21eed 1247 msg_controllen = tswapal(target_msgh->msg_controllen);
5a4a898d
FB
1248 if (msg_controllen < sizeof (struct target_cmsghdr))
1249 goto the_end;
cbb21eed 1250 target_cmsg_addr = tswapal(target_msgh->msg_control);
5a4a898d
FB
1251 target_cmsg = lock_user(VERIFY_WRITE, target_cmsg_addr, msg_controllen, 0);
1252 if (!target_cmsg)
1253 return -TARGET_EFAULT;
1254
7854b056
FB
1255 while (cmsg && target_cmsg) {
1256 void *data = CMSG_DATA(cmsg);
1257 void *target_data = TARGET_CMSG_DATA(target_cmsg);
1258
1259 int len = cmsg->cmsg_len - CMSG_ALIGN(sizeof (struct cmsghdr));
1260
1261 space += TARGET_CMSG_SPACE(len);
5a4a898d 1262 if (space > msg_controllen) {
7854b056 1263 space -= TARGET_CMSG_SPACE(len);
31febb71 1264 gemu_log("Target cmsg overflow\n");
7854b056
FB
1265 break;
1266 }
1267
dbf4f796
PJ
1268 if (cmsg->cmsg_level == SOL_SOCKET) {
1269 target_cmsg->cmsg_level = tswap32(TARGET_SOL_SOCKET);
1270 } else {
1271 target_cmsg->cmsg_level = tswap32(cmsg->cmsg_level);
1272 }
7854b056 1273 target_cmsg->cmsg_type = tswap32(cmsg->cmsg_type);
cbb21eed 1274 target_cmsg->cmsg_len = tswapal(TARGET_CMSG_LEN(len));
7854b056 1275
52b65494
HD
1276 switch (cmsg->cmsg_level) {
1277 case SOL_SOCKET:
1278 switch (cmsg->cmsg_type) {
1279 case SCM_RIGHTS:
1280 {
1281 int *fd = (int *)data;
1282 int *target_fd = (int *)target_data;
1283 int i, numfds = len / sizeof(int);
1284
1285 for (i = 0; i < numfds; i++)
1286 target_fd[i] = tswap32(fd[i]);
1287 break;
1288 }
1289 case SO_TIMESTAMP:
1290 {
1291 struct timeval *tv = (struct timeval *)data;
1292 struct target_timeval *target_tv =
1293 (struct target_timeval *)target_data;
1294
1295 if (len != sizeof(struct timeval))
1296 goto unimplemented;
1297
1298 /* copy struct timeval to target */
1299 target_tv->tv_sec = tswapal(tv->tv_sec);
1300 target_tv->tv_usec = tswapal(tv->tv_usec);
1301 break;
1302 }
4bc29756
HD
1303 case SCM_CREDENTIALS:
1304 {
1305 struct ucred *cred = (struct ucred *)data;
1306 struct target_ucred *target_cred =
1307 (struct target_ucred *)target_data;
1308
1309 __put_user(cred->pid, &target_cred->pid);
1310 __put_user(cred->uid, &target_cred->uid);
1311 __put_user(cred->gid, &target_cred->gid);
1312 break;
1313 }
52b65494
HD
1314 default:
1315 goto unimplemented;
1316 }
1317 break;
7854b056 1318
52b65494
HD
1319 default:
1320 unimplemented:
aebf5bc7
JH
1321 gemu_log("Unsupported ancillary data: %d/%d\n",
1322 cmsg->cmsg_level, cmsg->cmsg_type);
1323 memcpy(target_data, data, len);
7854b056
FB
1324 }
1325
1326 cmsg = CMSG_NXTHDR(msgh, cmsg);
1327 target_cmsg = TARGET_CMSG_NXTHDR(target_msgh, target_cmsg);
1328 }
5a4a898d
FB
1329 unlock_user(target_cmsg, target_cmsg_addr, space);
1330 the_end:
cbb21eed 1331 target_msgh->msg_controllen = tswapal(space);
5a4a898d 1332 return 0;
7854b056
FB
1333}
1334
0da46a6e 1335/* do_setsockopt() Must return target values and target errnos. */
992f48a0 1336static abi_long do_setsockopt(int sockfd, int level, int optname,
2f619698 1337 abi_ulong optval_addr, socklen_t optlen)
7854b056 1338{
992f48a0 1339 abi_long ret;
32407103 1340 int val;
b975b83b 1341 struct ip_mreqn *ip_mreq;
6e3cb58f 1342 struct ip_mreq_source *ip_mreq_source;
3b46e624 1343
8853f86e
FB
1344 switch(level) {
1345 case SOL_TCP:
7854b056 1346 /* TCP options all take an 'int' value. */
7854b056 1347 if (optlen < sizeof(uint32_t))
0da46a6e 1348 return -TARGET_EINVAL;
3b46e624 1349
2f619698
FB
1350 if (get_user_u32(val, optval_addr))
1351 return -TARGET_EFAULT;
8853f86e
FB
1352 ret = get_errno(setsockopt(sockfd, level, optname, &val, sizeof(val)));
1353 break;
1354 case SOL_IP:
1355 switch(optname) {
2efbe911
FB
1356 case IP_TOS:
1357 case IP_TTL:
8853f86e 1358 case IP_HDRINCL:
2efbe911
FB
1359 case IP_ROUTER_ALERT:
1360 case IP_RECVOPTS:
1361 case IP_RETOPTS:
1362 case IP_PKTINFO:
1363 case IP_MTU_DISCOVER:
1364 case IP_RECVERR:
1365 case IP_RECVTOS:
1366#ifdef IP_FREEBIND
1367 case IP_FREEBIND:
1368#endif
1369 case IP_MULTICAST_TTL:
1370 case IP_MULTICAST_LOOP:
8853f86e
FB
1371 val = 0;
1372 if (optlen >= sizeof(uint32_t)) {
2f619698
FB
1373 if (get_user_u32(val, optval_addr))
1374 return -TARGET_EFAULT;
8853f86e 1375 } else if (optlen >= 1) {
2f619698
FB
1376 if (get_user_u8(val, optval_addr))
1377 return -TARGET_EFAULT;
8853f86e
FB
1378 }
1379 ret = get_errno(setsockopt(sockfd, level, optname, &val, sizeof(val)));
1380 break;
b975b83b
LL
1381 case IP_ADD_MEMBERSHIP:
1382 case IP_DROP_MEMBERSHIP:
1383 if (optlen < sizeof (struct target_ip_mreq) ||
1384 optlen > sizeof (struct target_ip_mreqn))
1385 return -TARGET_EINVAL;
1386
1387 ip_mreq = (struct ip_mreqn *) alloca(optlen);
1388 target_to_host_ip_mreq(ip_mreq, optval_addr, optlen);
1389 ret = get_errno(setsockopt(sockfd, level, optname, ip_mreq, optlen));
1390 break;
1391
6e3cb58f
LL
1392 case IP_BLOCK_SOURCE:
1393 case IP_UNBLOCK_SOURCE:
1394 case IP_ADD_SOURCE_MEMBERSHIP:
1395 case IP_DROP_SOURCE_MEMBERSHIP:
1396 if (optlen != sizeof (struct target_ip_mreq_source))
1397 return -TARGET_EINVAL;
1398
1399 ip_mreq_source = lock_user(VERIFY_READ, optval_addr, optlen, 1);
1400 ret = get_errno(setsockopt(sockfd, level, optname, ip_mreq_source, optlen));
1401 unlock_user (ip_mreq_source, optval_addr, 0);
1402 break;
1403
920394db
JH
1404 default:
1405 goto unimplemented;
1406 }
1407 break;
0d78b3b5
LV
1408 case SOL_IPV6:
1409 switch (optname) {
1410 case IPV6_MTU_DISCOVER:
1411 case IPV6_MTU:
1412 case IPV6_V6ONLY:
1413 case IPV6_RECVPKTINFO:
1414 val = 0;
1415 if (optlen < sizeof(uint32_t)) {
1416 return -TARGET_EINVAL;
1417 }
1418 if (get_user_u32(val, optval_addr)) {
1419 return -TARGET_EFAULT;
1420 }
1421 ret = get_errno(setsockopt(sockfd, level, optname,
1422 &val, sizeof(val)));
1423 break;
1424 default:
1425 goto unimplemented;
1426 }
1427 break;
920394db
JH
1428 case SOL_RAW:
1429 switch (optname) {
1430 case ICMP_FILTER:
1431 /* struct icmp_filter takes an u32 value */
1432 if (optlen < sizeof(uint32_t)) {
1433 return -TARGET_EINVAL;
1434 }
1435
1436 if (get_user_u32(val, optval_addr)) {
1437 return -TARGET_EFAULT;
1438 }
1439 ret = get_errno(setsockopt(sockfd, level, optname,
1440 &val, sizeof(val)));
1441 break;
1442
8853f86e
FB
1443 default:
1444 goto unimplemented;
1445 }
1446 break;
3532fa74 1447 case TARGET_SOL_SOCKET:
8853f86e 1448 switch (optname) {
1b09aeb9
LV
1449 case TARGET_SO_RCVTIMEO:
1450 {
1451 struct timeval tv;
1452
1453 optname = SO_RCVTIMEO;
1454
1455set_timeout:
1456 if (optlen != sizeof(struct target_timeval)) {
1457 return -TARGET_EINVAL;
1458 }
1459
1460 if (copy_from_user_timeval(&tv, optval_addr)) {
1461 return -TARGET_EFAULT;
1462 }
1463
1464 ret = get_errno(setsockopt(sockfd, SOL_SOCKET, optname,
1465 &tv, sizeof(tv)));
1466 return ret;
1467 }
1468 case TARGET_SO_SNDTIMEO:
1469 optname = SO_SNDTIMEO;
1470 goto set_timeout;
f57d4192
LV
1471 case TARGET_SO_ATTACH_FILTER:
1472 {
1473 struct target_sock_fprog *tfprog;
1474 struct target_sock_filter *tfilter;
1475 struct sock_fprog fprog;
1476 struct sock_filter *filter;
1477 int i;
1478
1479 if (optlen != sizeof(*tfprog)) {
1480 return -TARGET_EINVAL;
1481 }
1482 if (!lock_user_struct(VERIFY_READ, tfprog, optval_addr, 0)) {
1483 return -TARGET_EFAULT;
1484 }
1485 if (!lock_user_struct(VERIFY_READ, tfilter,
1486 tswapal(tfprog->filter), 0)) {
1487 unlock_user_struct(tfprog, optval_addr, 1);
1488 return -TARGET_EFAULT;
1489 }
1490
1491 fprog.len = tswap16(tfprog->len);
1492 filter = malloc(fprog.len * sizeof(*filter));
1493 if (filter == NULL) {
1494 unlock_user_struct(tfilter, tfprog->filter, 1);
1495 unlock_user_struct(tfprog, optval_addr, 1);
1496 return -TARGET_ENOMEM;
1497 }
1498 for (i = 0; i < fprog.len; i++) {
1499 filter[i].code = tswap16(tfilter[i].code);
1500 filter[i].jt = tfilter[i].jt;
1501 filter[i].jf = tfilter[i].jf;
1502 filter[i].k = tswap32(tfilter[i].k);
1503 }
1504 fprog.filter = filter;
1505
1506 ret = get_errno(setsockopt(sockfd, SOL_SOCKET,
1507 SO_ATTACH_FILTER, &fprog, sizeof(fprog)));
1508 free(filter);
1509
1510 unlock_user_struct(tfilter, tfprog->filter, 1);
1511 unlock_user_struct(tfprog, optval_addr, 1);
1512 return ret;
1513 }
451aaf68
JT
1514 case TARGET_SO_BINDTODEVICE:
1515 {
1516 char *dev_ifname, *addr_ifname;
1517
1518 if (optlen > IFNAMSIZ - 1) {
1519 optlen = IFNAMSIZ - 1;
1520 }
1521 dev_ifname = lock_user(VERIFY_READ, optval_addr, optlen, 1);
1522 if (!dev_ifname) {
1523 return -TARGET_EFAULT;
1524 }
1525 optname = SO_BINDTODEVICE;
1526 addr_ifname = alloca(IFNAMSIZ);
1527 memcpy(addr_ifname, dev_ifname, optlen);
1528 addr_ifname[optlen] = 0;
1529 ret = get_errno(setsockopt(sockfd, level, optname, addr_ifname, optlen));
1530 unlock_user (dev_ifname, optval_addr, 0);
1531 return ret;
1532 }
8853f86e 1533 /* Options with 'int' argument. */
3532fa74
FB
1534 case TARGET_SO_DEBUG:
1535 optname = SO_DEBUG;
1536 break;
1537 case TARGET_SO_REUSEADDR:
1538 optname = SO_REUSEADDR;
1539 break;
1540 case TARGET_SO_TYPE:
1541 optname = SO_TYPE;
1542 break;
1543 case TARGET_SO_ERROR:
1544 optname = SO_ERROR;
1545 break;
1546 case TARGET_SO_DONTROUTE:
1547 optname = SO_DONTROUTE;
1548 break;
1549 case TARGET_SO_BROADCAST:
1550 optname = SO_BROADCAST;
1551 break;
1552 case TARGET_SO_SNDBUF:
1553 optname = SO_SNDBUF;
1554 break;
d79b6cc4
PB
1555 case TARGET_SO_SNDBUFFORCE:
1556 optname = SO_SNDBUFFORCE;
1557 break;
3532fa74
FB
1558 case TARGET_SO_RCVBUF:
1559 optname = SO_RCVBUF;
1560 break;
d79b6cc4
PB
1561 case TARGET_SO_RCVBUFFORCE:
1562 optname = SO_RCVBUFFORCE;
1563 break;
3532fa74
FB
1564 case TARGET_SO_KEEPALIVE:
1565 optname = SO_KEEPALIVE;
1566 break;
1567 case TARGET_SO_OOBINLINE:
1568 optname = SO_OOBINLINE;
1569 break;
1570 case TARGET_SO_NO_CHECK:
1571 optname = SO_NO_CHECK;
1572 break;
1573 case TARGET_SO_PRIORITY:
1574 optname = SO_PRIORITY;
1575 break;
5e83e8e3 1576#ifdef SO_BSDCOMPAT
3532fa74
FB
1577 case TARGET_SO_BSDCOMPAT:
1578 optname = SO_BSDCOMPAT;
1579 break;
5e83e8e3 1580#endif
3532fa74
FB
1581 case TARGET_SO_PASSCRED:
1582 optname = SO_PASSCRED;
1583 break;
82d0fe6b
PB
1584 case TARGET_SO_PASSSEC:
1585 optname = SO_PASSSEC;
1586 break;
3532fa74
FB
1587 case TARGET_SO_TIMESTAMP:
1588 optname = SO_TIMESTAMP;
1589 break;
1590 case TARGET_SO_RCVLOWAT:
1591 optname = SO_RCVLOWAT;
1592 break;
8853f86e
FB
1593 break;
1594 default:
1595 goto unimplemented;
1596 }
3532fa74 1597 if (optlen < sizeof(uint32_t))
2f619698 1598 return -TARGET_EINVAL;
3532fa74 1599
2f619698
FB
1600 if (get_user_u32(val, optval_addr))
1601 return -TARGET_EFAULT;
3532fa74 1602 ret = get_errno(setsockopt(sockfd, SOL_SOCKET, optname, &val, sizeof(val)));
8853f86e 1603 break;
7854b056 1604 default:
8853f86e 1605 unimplemented:
b2bedb21 1606 gemu_log("Unsupported setsockopt level=%d optname=%d\n", level, optname);
6fa13c17 1607 ret = -TARGET_ENOPROTOOPT;
7854b056 1608 }
8853f86e 1609 return ret;
7854b056
FB
1610}
1611
0da46a6e 1612/* do_getsockopt() Must return target values and target errnos. */
992f48a0 1613static abi_long do_getsockopt(int sockfd, int level, int optname,
2f619698 1614 abi_ulong optval_addr, abi_ulong optlen)
7854b056 1615{
992f48a0 1616 abi_long ret;
b55266b5
BS
1617 int len, val;
1618 socklen_t lv;
8853f86e
FB
1619
1620 switch(level) {
3532fa74 1621 case TARGET_SOL_SOCKET:
f3b974cd
JL
1622 level = SOL_SOCKET;
1623 switch (optname) {
1624 /* These don't just return a single integer */
1625 case TARGET_SO_LINGER:
1626 case TARGET_SO_RCVTIMEO:
1627 case TARGET_SO_SNDTIMEO:
f3b974cd
JL
1628 case TARGET_SO_PEERNAME:
1629 goto unimplemented;
583359a6
AP
1630 case TARGET_SO_PEERCRED: {
1631 struct ucred cr;
1632 socklen_t crlen;
1633 struct target_ucred *tcr;
1634
1635 if (get_user_u32(len, optlen)) {
1636 return -TARGET_EFAULT;
1637 }
1638 if (len < 0) {
1639 return -TARGET_EINVAL;
1640 }
1641
1642 crlen = sizeof(cr);
1643 ret = get_errno(getsockopt(sockfd, level, SO_PEERCRED,
1644 &cr, &crlen));
1645 if (ret < 0) {
1646 return ret;
1647 }
1648 if (len > crlen) {
1649 len = crlen;
1650 }
1651 if (!lock_user_struct(VERIFY_WRITE, tcr, optval_addr, 0)) {
1652 return -TARGET_EFAULT;
1653 }
1654 __put_user(cr.pid, &tcr->pid);
1655 __put_user(cr.uid, &tcr->uid);
1656 __put_user(cr.gid, &tcr->gid);
1657 unlock_user_struct(tcr, optval_addr, 1);
1658 if (put_user_u32(len, optlen)) {
1659 return -TARGET_EFAULT;
1660 }
1661 break;
1662 }
f3b974cd
JL
1663 /* Options with 'int' argument. */
1664 case TARGET_SO_DEBUG:
1665 optname = SO_DEBUG;
1666 goto int_case;
1667 case TARGET_SO_REUSEADDR:
1668 optname = SO_REUSEADDR;
1669 goto int_case;
1670 case TARGET_SO_TYPE:
1671 optname = SO_TYPE;
1672 goto int_case;
1673 case TARGET_SO_ERROR:
1674 optname = SO_ERROR;
1675 goto int_case;
1676 case TARGET_SO_DONTROUTE:
1677 optname = SO_DONTROUTE;
1678 goto int_case;
1679 case TARGET_SO_BROADCAST:
1680 optname = SO_BROADCAST;
1681 goto int_case;
1682 case TARGET_SO_SNDBUF:
1683 optname = SO_SNDBUF;
1684 goto int_case;
1685 case TARGET_SO_RCVBUF:
1686 optname = SO_RCVBUF;
1687 goto int_case;
1688 case TARGET_SO_KEEPALIVE:
1689 optname = SO_KEEPALIVE;
1690 goto int_case;
1691 case TARGET_SO_OOBINLINE:
1692 optname = SO_OOBINLINE;
1693 goto int_case;
1694 case TARGET_SO_NO_CHECK:
1695 optname = SO_NO_CHECK;
1696 goto int_case;
1697 case TARGET_SO_PRIORITY:
1698 optname = SO_PRIORITY;
1699 goto int_case;
1700#ifdef SO_BSDCOMPAT
1701 case TARGET_SO_BSDCOMPAT:
1702 optname = SO_BSDCOMPAT;
1703 goto int_case;
1704#endif
1705 case TARGET_SO_PASSCRED:
1706 optname = SO_PASSCRED;
1707 goto int_case;
1708 case TARGET_SO_TIMESTAMP:
1709 optname = SO_TIMESTAMP;
1710 goto int_case;
1711 case TARGET_SO_RCVLOWAT:
1712 optname = SO_RCVLOWAT;
1713 goto int_case;
aec1ca41
PB
1714 case TARGET_SO_ACCEPTCONN:
1715 optname = SO_ACCEPTCONN;
1716 goto int_case;
8853f86e 1717 default:
2efbe911
FB
1718 goto int_case;
1719 }
1720 break;
1721 case SOL_TCP:
1722 /* TCP options all take an 'int' value. */
1723 int_case:
2f619698
FB
1724 if (get_user_u32(len, optlen))
1725 return -TARGET_EFAULT;
2efbe911 1726 if (len < 0)
0da46a6e 1727 return -TARGET_EINVAL;
73160d95 1728 lv = sizeof(lv);
2efbe911
FB
1729 ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
1730 if (ret < 0)
1731 return ret;
8289d112
PB
1732 if (optname == SO_TYPE) {
1733 val = host_to_target_sock_type(val);
1734 }
2efbe911
FB
1735 if (len > lv)
1736 len = lv;
2f619698
FB
1737 if (len == 4) {
1738 if (put_user_u32(val, optval_addr))
1739 return -TARGET_EFAULT;
1740 } else {
1741 if (put_user_u8(val, optval_addr))
1742 return -TARGET_EFAULT;
f3b974cd 1743 }
2f619698
FB
1744 if (put_user_u32(len, optlen))
1745 return -TARGET_EFAULT;
2efbe911
FB
1746 break;
1747 case SOL_IP:
1748 switch(optname) {
1749 case IP_TOS:
1750 case IP_TTL:
1751 case IP_HDRINCL:
1752 case IP_ROUTER_ALERT:
1753 case IP_RECVOPTS:
1754 case IP_RETOPTS:
1755 case IP_PKTINFO:
1756 case IP_MTU_DISCOVER:
1757 case IP_RECVERR:
1758 case IP_RECVTOS:
1759#ifdef IP_FREEBIND
1760 case IP_FREEBIND:
1761#endif
1762 case IP_MULTICAST_TTL:
1763 case IP_MULTICAST_LOOP:
2f619698
FB
1764 if (get_user_u32(len, optlen))
1765 return -TARGET_EFAULT;
8853f86e 1766 if (len < 0)
0da46a6e 1767 return -TARGET_EINVAL;
73160d95 1768 lv = sizeof(lv);
8853f86e
FB
1769 ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
1770 if (ret < 0)
1771 return ret;
2efbe911 1772 if (len < sizeof(int) && len > 0 && val >= 0 && val < 255) {
2efbe911 1773 len = 1;
2f619698
FB
1774 if (put_user_u32(len, optlen)
1775 || put_user_u8(val, optval_addr))
1776 return -TARGET_EFAULT;
2efbe911 1777 } else {
2efbe911
FB
1778 if (len > sizeof(int))
1779 len = sizeof(int);
2f619698
FB
1780 if (put_user_u32(len, optlen)
1781 || put_user_u32(val, optval_addr))
1782 return -TARGET_EFAULT;
2efbe911 1783 }
8853f86e 1784 break;
2efbe911 1785 default:
c02f499e
TS
1786 ret = -TARGET_ENOPROTOOPT;
1787 break;
8853f86e
FB
1788 }
1789 break;
1790 default:
1791 unimplemented:
1792 gemu_log("getsockopt level=%d optname=%d not yet supported\n",
1793 level, optname);
c02f499e 1794 ret = -TARGET_EOPNOTSUPP;
8853f86e
FB
1795 break;
1796 }
1797 return ret;
7854b056
FB
1798}
1799
f287b2c2
RH
1800static struct iovec *lock_iovec(int type, abi_ulong target_addr,
1801 int count, int copy)
53a5960a
PB
1802{
1803 struct target_iovec *target_vec;
f287b2c2
RH
1804 struct iovec *vec;
1805 abi_ulong total_len, max_len;
d732dcb4 1806 int i;
501bb4b0 1807 int err = 0;
29560a6c 1808 bool bad_address = false;
53a5960a 1809
f287b2c2
RH
1810 if (count == 0) {
1811 errno = 0;
1812 return NULL;
1813 }
dfae8e00 1814 if (count < 0 || count > IOV_MAX) {
f287b2c2
RH
1815 errno = EINVAL;
1816 return NULL;
1817 }
1818
1819 vec = calloc(count, sizeof(struct iovec));
1820 if (vec == NULL) {
1821 errno = ENOMEM;
1822 return NULL;
1823 }
1824
1825 target_vec = lock_user(VERIFY_READ, target_addr,
1826 count * sizeof(struct target_iovec), 1);
1827 if (target_vec == NULL) {
501bb4b0 1828 err = EFAULT;
f287b2c2
RH
1829 goto fail2;
1830 }
1831
1832 /* ??? If host page size > target page size, this will result in a
1833 value larger than what we can actually support. */
1834 max_len = 0x7fffffff & TARGET_PAGE_MASK;
1835 total_len = 0;
1836
1837 for (i = 0; i < count; i++) {
1838 abi_ulong base = tswapal(target_vec[i].iov_base);
1839 abi_long len = tswapal(target_vec[i].iov_len);
1840
1841 if (len < 0) {
501bb4b0 1842 err = EINVAL;
f287b2c2
RH
1843 goto fail;
1844 } else if (len == 0) {
1845 /* Zero length pointer is ignored. */
1846 vec[i].iov_base = 0;
41df8411 1847 } else {
f287b2c2 1848 vec[i].iov_base = lock_user(type, base, len, copy);
29560a6c
TM
1849 /* If the first buffer pointer is bad, this is a fault. But
1850 * subsequent bad buffers will result in a partial write; this
1851 * is realized by filling the vector with null pointers and
1852 * zero lengths. */
f287b2c2 1853 if (!vec[i].iov_base) {
29560a6c
TM
1854 if (i == 0) {
1855 err = EFAULT;
1856 goto fail;
1857 } else {
1858 bad_address = true;
1859 }
1860 }
1861 if (bad_address) {
1862 len = 0;
f287b2c2
RH
1863 }
1864 if (len > max_len - total_len) {
1865 len = max_len - total_len;
1866 }
41df8411 1867 }
f287b2c2
RH
1868 vec[i].iov_len = len;
1869 total_len += len;
579a97f7 1870 }
f287b2c2
RH
1871
1872 unlock_user(target_vec, target_addr, 0);
1873 return vec;
1874
1875 fail:
f287b2c2 1876 unlock_user(target_vec, target_addr, 0);
501bb4b0
PM
1877 fail2:
1878 free(vec);
1879 errno = err;
f287b2c2 1880 return NULL;
53a5960a
PB
1881}
1882
f287b2c2
RH
1883static void unlock_iovec(struct iovec *vec, abi_ulong target_addr,
1884 int count, int copy)
53a5960a
PB
1885{
1886 struct target_iovec *target_vec;
53a5960a
PB
1887 int i;
1888
f287b2c2
RH
1889 target_vec = lock_user(VERIFY_READ, target_addr,
1890 count * sizeof(struct target_iovec), 1);
1891 if (target_vec) {
1892 for (i = 0; i < count; i++) {
1893 abi_ulong base = tswapal(target_vec[i].iov_base);
1894 abi_long len = tswapal(target_vec[i].iov_base);
1895 if (len < 0) {
1896 break;
1897 }
d732dcb4
AZ
1898 unlock_user(vec[i].iov_base, base, copy ? vec[i].iov_len : 0);
1899 }
f287b2c2 1900 unlock_user(target_vec, target_addr, 0);
53a5960a 1901 }
579a97f7 1902
f287b2c2 1903 free(vec);
53a5960a
PB
1904}
1905
53d09b76 1906static inline int target_to_host_sock_type(int *type)
3532fa74 1907{
f651e6ae
PJ
1908 int host_type = 0;
1909 int target_type = *type;
1910
1911 switch (target_type & TARGET_SOCK_TYPE_MASK) {
3532fa74 1912 case TARGET_SOCK_DGRAM:
f651e6ae 1913 host_type = SOCK_DGRAM;
3532fa74
FB
1914 break;
1915 case TARGET_SOCK_STREAM:
f651e6ae 1916 host_type = SOCK_STREAM;
3532fa74 1917 break;
f651e6ae
PJ
1918 default:
1919 host_type = target_type & TARGET_SOCK_TYPE_MASK;
3532fa74
FB
1920 break;
1921 }
f651e6ae 1922 if (target_type & TARGET_SOCK_CLOEXEC) {
53d09b76 1923#if defined(SOCK_CLOEXEC)
f651e6ae 1924 host_type |= SOCK_CLOEXEC;
53d09b76
EI
1925#else
1926 return -TARGET_EINVAL;
1927#endif
f651e6ae
PJ
1928 }
1929 if (target_type & TARGET_SOCK_NONBLOCK) {
53d09b76 1930#if defined(SOCK_NONBLOCK)
f651e6ae 1931 host_type |= SOCK_NONBLOCK;
53d09b76
EI
1932#elif !defined(O_NONBLOCK)
1933 return -TARGET_EINVAL;
1934#endif
f651e6ae
PJ
1935 }
1936 *type = host_type;
53d09b76
EI
1937 return 0;
1938}
1939
1940/* Try to emulate socket type flags after socket creation. */
1941static int sock_flags_fixup(int fd, int target_type)
1942{
1943#if !defined(SOCK_NONBLOCK) && defined(O_NONBLOCK)
1944 if (target_type & TARGET_SOCK_NONBLOCK) {
1945 int flags = fcntl(fd, F_GETFL);
1946 if (fcntl(fd, F_SETFL, O_NONBLOCK | flags) == -1) {
1947 close(fd);
1948 return -TARGET_EINVAL;
1949 }
1950 }
1951#endif
1952 return fd;
f651e6ae
PJ
1953}
1954
1955/* do_socket() Must return target values and target errnos. */
1956static abi_long do_socket(int domain, int type, int protocol)
1957{
53d09b76
EI
1958 int target_type = type;
1959 int ret;
1960
1961 ret = target_to_host_sock_type(&type);
1962 if (ret) {
1963 return ret;
1964 }
f651e6ae 1965
12bc92ab 1966 if (domain == PF_NETLINK)
480eda2e 1967 return -TARGET_EAFNOSUPPORT;
53d09b76
EI
1968 ret = get_errno(socket(domain, type, protocol));
1969 if (ret >= 0) {
1970 ret = sock_flags_fixup(ret, target_type);
1971 }
1972 return ret;
3532fa74
FB
1973}
1974
0da46a6e 1975/* do_bind() Must return target values and target errnos. */
992f48a0
BS
1976static abi_long do_bind(int sockfd, abi_ulong target_addr,
1977 socklen_t addrlen)
3532fa74 1978{
8f7aeaf6 1979 void *addr;
917507b0 1980 abi_long ret;
8f7aeaf6 1981
38724253 1982 if ((int)addrlen < 0) {
8f7aeaf6 1983 return -TARGET_EINVAL;
38724253 1984 }
8f7aeaf6 1985
607175e0 1986 addr = alloca(addrlen+1);
3b46e624 1987
917507b0
AP
1988 ret = target_to_host_sockaddr(addr, target_addr, addrlen);
1989 if (ret)
1990 return ret;
1991
3532fa74
FB
1992 return get_errno(bind(sockfd, addr, addrlen));
1993}
1994
0da46a6e 1995/* do_connect() Must return target values and target errnos. */
992f48a0
BS
1996static abi_long do_connect(int sockfd, abi_ulong target_addr,
1997 socklen_t addrlen)
3532fa74 1998{
8f7aeaf6 1999 void *addr;
917507b0 2000 abi_long ret;
8f7aeaf6 2001
38724253 2002 if ((int)addrlen < 0) {
8f7aeaf6 2003 return -TARGET_EINVAL;
38724253 2004 }
8f7aeaf6 2005
2dd08dfd 2006 addr = alloca(addrlen+1);
3b46e624 2007
917507b0
AP
2008 ret = target_to_host_sockaddr(addr, target_addr, addrlen);
2009 if (ret)
2010 return ret;
2011
3532fa74
FB
2012 return get_errno(connect(sockfd, addr, addrlen));
2013}
2014
f19e00d7
AG
2015/* do_sendrecvmsg_locked() Must return target values and target errnos. */
2016static abi_long do_sendrecvmsg_locked(int fd, struct target_msghdr *msgp,
2017 int flags, int send)
3532fa74 2018{
6de645c7 2019 abi_long ret, len;
3532fa74
FB
2020 struct msghdr msg;
2021 int count;
2022 struct iovec *vec;
992f48a0 2023 abi_ulong target_vec;
3532fa74 2024
3532fa74
FB
2025 if (msgp->msg_name) {
2026 msg.msg_namelen = tswap32(msgp->msg_namelen);
2dd08dfd 2027 msg.msg_name = alloca(msg.msg_namelen+1);
cbb21eed 2028 ret = target_to_host_sockaddr(msg.msg_name, tswapal(msgp->msg_name),
3532fa74 2029 msg.msg_namelen);
917507b0 2030 if (ret) {
f287b2c2 2031 goto out2;
917507b0 2032 }
3532fa74
FB
2033 } else {
2034 msg.msg_name = NULL;
2035 msg.msg_namelen = 0;
2036 }
cbb21eed 2037 msg.msg_controllen = 2 * tswapal(msgp->msg_controllen);
3532fa74
FB
2038 msg.msg_control = alloca(msg.msg_controllen);
2039 msg.msg_flags = tswap32(msgp->msg_flags);
3b46e624 2040
cbb21eed 2041 count = tswapal(msgp->msg_iovlen);
cbb21eed 2042 target_vec = tswapal(msgp->msg_iov);
f287b2c2
RH
2043 vec = lock_iovec(send ? VERIFY_READ : VERIFY_WRITE,
2044 target_vec, count, send);
2045 if (vec == NULL) {
2046 ret = -host_to_target_errno(errno);
2047 goto out2;
2048 }
3532fa74
FB
2049 msg.msg_iovlen = count;
2050 msg.msg_iov = vec;
3b46e624 2051
3532fa74 2052 if (send) {
5a4a898d
FB
2053 ret = target_to_host_cmsg(&msg, msgp);
2054 if (ret == 0)
2055 ret = get_errno(sendmsg(fd, &msg, flags));
3532fa74
FB
2056 } else {
2057 ret = get_errno(recvmsg(fd, &msg, flags));
6de645c7
AZ
2058 if (!is_error(ret)) {
2059 len = ret;
5a4a898d 2060 ret = host_to_target_cmsg(msgp, &msg);
ca619067
JH
2061 if (!is_error(ret)) {
2062 msgp->msg_namelen = tswap32(msg.msg_namelen);
2063 if (msg.msg_name != NULL) {
2064 ret = host_to_target_sockaddr(tswapal(msgp->msg_name),
2065 msg.msg_name, msg.msg_namelen);
2066 if (ret) {
2067 goto out;
2068 }
2069 }
2070
6de645c7 2071 ret = len;
ca619067 2072 }
6de645c7 2073 }
3532fa74 2074 }
ca619067
JH
2075
2076out:
3532fa74 2077 unlock_iovec(vec, target_vec, count, !send);
f287b2c2 2078out2:
f19e00d7
AG
2079 return ret;
2080}
2081
2082static abi_long do_sendrecvmsg(int fd, abi_ulong target_msg,
2083 int flags, int send)
2084{
2085 abi_long ret;
2086 struct target_msghdr *msgp;
2087
2088 if (!lock_user_struct(send ? VERIFY_READ : VERIFY_WRITE,
2089 msgp,
2090 target_msg,
2091 send ? 1 : 0)) {
2092 return -TARGET_EFAULT;
2093 }
2094 ret = do_sendrecvmsg_locked(fd, msgp, flags, send);
579a97f7 2095 unlock_user_struct(msgp, target_msg, send ? 0 : 1);
3532fa74
FB
2096 return ret;
2097}
2098
f19e00d7
AG
2099#ifdef TARGET_NR_sendmmsg
2100/* We don't rely on the C library to have sendmmsg/recvmmsg support,
2101 * so it might not have this *mmsg-specific flag either.
2102 */
2103#ifndef MSG_WAITFORONE
2104#define MSG_WAITFORONE 0x10000
2105#endif
2106
2107static abi_long do_sendrecvmmsg(int fd, abi_ulong target_msgvec,
2108 unsigned int vlen, unsigned int flags,
2109 int send)
2110{
2111 struct target_mmsghdr *mmsgp;
2112 abi_long ret = 0;
2113 int i;
2114
2115 if (vlen > UIO_MAXIOV) {
2116 vlen = UIO_MAXIOV;
2117 }
2118
2119 mmsgp = lock_user(VERIFY_WRITE, target_msgvec, sizeof(*mmsgp) * vlen, 1);
2120 if (!mmsgp) {
2121 return -TARGET_EFAULT;
2122 }
2123
2124 for (i = 0; i < vlen; i++) {
2125 ret = do_sendrecvmsg_locked(fd, &mmsgp[i].msg_hdr, flags, send);
2126 if (is_error(ret)) {
2127 break;
2128 }
2129 mmsgp[i].msg_len = tswap32(ret);
2130 /* MSG_WAITFORONE turns on MSG_DONTWAIT after one packet */
2131 if (flags & MSG_WAITFORONE) {
2132 flags |= MSG_DONTWAIT;
2133 }
2134 }
2135
2136 unlock_user(mmsgp, target_msgvec, sizeof(*mmsgp) * i);
2137
2138 /* Return number of datagrams sent if we sent any at all;
2139 * otherwise return the error.
2140 */
2141 if (i) {
2142 return i;
2143 }
2144 return ret;
2145}
2146#endif
2147
a94b4987
PM
2148/* If we don't have a system accept4() then just call accept.
2149 * The callsites to do_accept4() will ensure that they don't
2150 * pass a non-zero flags argument in this config.
2151 */
2152#ifndef CONFIG_ACCEPT4
2153static inline int accept4(int sockfd, struct sockaddr *addr,
2154 socklen_t *addrlen, int flags)
2155{
2156 assert(flags == 0);
2157 return accept(sockfd, addr, addrlen);
2158}
2159#endif
2160
2161/* do_accept4() Must return target values and target errnos. */
2162static abi_long do_accept4(int fd, abi_ulong target_addr,
2163 abi_ulong target_addrlen_addr, int flags)
1be9e1dc 2164{
2f619698
FB
2165 socklen_t addrlen;
2166 void *addr;
992f48a0 2167 abi_long ret;
d25295d4
PJ
2168 int host_flags;
2169
2170 host_flags = target_to_host_bitmask(flags, fcntl_flags_tbl);
1be9e1dc 2171
a94b4987 2172 if (target_addr == 0) {
d25295d4 2173 return get_errno(accept4(fd, NULL, NULL, host_flags));
a94b4987 2174 }
917507b0
AP
2175
2176 /* linux returns EINVAL if addrlen pointer is invalid */
2f619698 2177 if (get_user_u32(addrlen, target_addrlen_addr))
917507b0 2178 return -TARGET_EINVAL;
2f619698 2179
38724253 2180 if ((int)addrlen < 0) {
8f7aeaf6 2181 return -TARGET_EINVAL;
38724253 2182 }
8f7aeaf6 2183
917507b0
AP
2184 if (!access_ok(VERIFY_WRITE, target_addr, addrlen))
2185 return -TARGET_EINVAL;
2186
2f619698
FB
2187 addr = alloca(addrlen);
2188
d25295d4 2189 ret = get_errno(accept4(fd, addr, &addrlen, host_flags));
1be9e1dc
PB
2190 if (!is_error(ret)) {
2191 host_to_target_sockaddr(target_addr, addr, addrlen);
2f619698
FB
2192 if (put_user_u32(addrlen, target_addrlen_addr))
2193 ret = -TARGET_EFAULT;
1be9e1dc
PB
2194 }
2195 return ret;
2196}
2197
0da46a6e 2198/* do_getpeername() Must return target values and target errnos. */
992f48a0 2199static abi_long do_getpeername(int fd, abi_ulong target_addr,
2f619698 2200 abi_ulong target_addrlen_addr)
1be9e1dc 2201{
2f619698
FB
2202 socklen_t addrlen;
2203 void *addr;
992f48a0 2204 abi_long ret;
1be9e1dc 2205
2f619698
FB
2206 if (get_user_u32(addrlen, target_addrlen_addr))
2207 return -TARGET_EFAULT;
2208
38724253 2209 if ((int)addrlen < 0) {
8f7aeaf6 2210 return -TARGET_EINVAL;
38724253 2211 }
8f7aeaf6 2212
917507b0
AP
2213 if (!access_ok(VERIFY_WRITE, target_addr, addrlen))
2214 return -TARGET_EFAULT;
2215
2f619698
FB
2216 addr = alloca(addrlen);
2217
1be9e1dc
PB
2218 ret = get_errno(getpeername(fd, addr, &addrlen));
2219 if (!is_error(ret)) {
2220 host_to_target_sockaddr(target_addr, addr, addrlen);
2f619698
FB
2221 if (put_user_u32(addrlen, target_addrlen_addr))
2222 ret = -TARGET_EFAULT;
1be9e1dc
PB
2223 }
2224 return ret;
2225}
2226
0da46a6e 2227/* do_getsockname() Must return target values and target errnos. */
992f48a0 2228static abi_long do_getsockname(int fd, abi_ulong target_addr,
2f619698 2229 abi_ulong target_addrlen_addr)
1be9e1dc 2230{
2f619698
FB
2231 socklen_t addrlen;
2232 void *addr;
992f48a0 2233 abi_long ret;
1be9e1dc 2234
2f619698
FB
2235 if (get_user_u32(addrlen, target_addrlen_addr))
2236 return -TARGET_EFAULT;
2237
38724253 2238 if ((int)addrlen < 0) {
8f7aeaf6 2239 return -TARGET_EINVAL;
38724253 2240 }
8f7aeaf6 2241
917507b0
AP
2242 if (!access_ok(VERIFY_WRITE, target_addr, addrlen))
2243 return -TARGET_EFAULT;
2244
2f619698
FB
2245 addr = alloca(addrlen);
2246
1be9e1dc
PB
2247 ret = get_errno(getsockname(fd, addr, &addrlen));
2248 if (!is_error(ret)) {
2249 host_to_target_sockaddr(target_addr, addr, addrlen);
2f619698
FB
2250 if (put_user_u32(addrlen, target_addrlen_addr))
2251 ret = -TARGET_EFAULT;
1be9e1dc
PB
2252 }
2253 return ret;
2254}
2255
0da46a6e 2256/* do_socketpair() Must return target values and target errnos. */
992f48a0 2257static abi_long do_socketpair(int domain, int type, int protocol,
2f619698 2258 abi_ulong target_tab_addr)
1be9e1dc
PB
2259{
2260 int tab[2];
992f48a0 2261 abi_long ret;
1be9e1dc 2262
f651e6ae
PJ
2263 target_to_host_sock_type(&type);
2264
1be9e1dc
PB
2265 ret = get_errno(socketpair(domain, type, protocol, tab));
2266 if (!is_error(ret)) {
2f619698
FB
2267 if (put_user_s32(tab[0], target_tab_addr)
2268 || put_user_s32(tab[1], target_tab_addr + sizeof(tab[0])))
2269 ret = -TARGET_EFAULT;
1be9e1dc
PB
2270 }
2271 return ret;
2272}
2273
0da46a6e 2274/* do_sendto() Must return target values and target errnos. */
992f48a0
BS
2275static abi_long do_sendto(int fd, abi_ulong msg, size_t len, int flags,
2276 abi_ulong target_addr, socklen_t addrlen)
1be9e1dc
PB
2277{
2278 void *addr;
2279 void *host_msg;
992f48a0 2280 abi_long ret;
1be9e1dc 2281
38724253 2282 if ((int)addrlen < 0) {
8f7aeaf6 2283 return -TARGET_EINVAL;
38724253 2284 }
8f7aeaf6 2285
579a97f7
FB
2286 host_msg = lock_user(VERIFY_READ, msg, len, 1);
2287 if (!host_msg)
2288 return -TARGET_EFAULT;
1be9e1dc 2289 if (target_addr) {
2dd08dfd 2290 addr = alloca(addrlen+1);
917507b0
AP
2291 ret = target_to_host_sockaddr(addr, target_addr, addrlen);
2292 if (ret) {
2293 unlock_user(host_msg, msg, 0);
2294 return ret;
2295 }
1be9e1dc
PB
2296 ret = get_errno(sendto(fd, host_msg, len, flags, addr, addrlen));
2297 } else {
2298 ret = get_errno(send(fd, host_msg, len, flags));
2299 }
2300 unlock_user(host_msg, msg, 0);
2301 return ret;
2302}
2303
0da46a6e 2304/* do_recvfrom() Must return target values and target errnos. */
992f48a0
BS
2305static abi_long do_recvfrom(int fd, abi_ulong msg, size_t len, int flags,
2306 abi_ulong target_addr,
2307 abi_ulong target_addrlen)
1be9e1dc
PB
2308{
2309 socklen_t addrlen;
2310 void *addr;
2311 void *host_msg;
992f48a0 2312 abi_long ret;
1be9e1dc 2313
579a97f7
FB
2314 host_msg = lock_user(VERIFY_WRITE, msg, len, 0);
2315 if (!host_msg)
2316 return -TARGET_EFAULT;
1be9e1dc 2317 if (target_addr) {
2f619698
FB
2318 if (get_user_u32(addrlen, target_addrlen)) {
2319 ret = -TARGET_EFAULT;
2320 goto fail;
2321 }
38724253 2322 if ((int)addrlen < 0) {
8f7aeaf6
AJ
2323 ret = -TARGET_EINVAL;
2324 goto fail;
2325 }
1be9e1dc
PB
2326 addr = alloca(addrlen);
2327 ret = get_errno(recvfrom(fd, host_msg, len, flags, addr, &addrlen));
2328 } else {
2329 addr = NULL; /* To keep compiler quiet. */
00aa0040 2330 ret = get_errno(qemu_recv(fd, host_msg, len, flags));
1be9e1dc
PB
2331 }
2332 if (!is_error(ret)) {
2333 if (target_addr) {
2334 host_to_target_sockaddr(target_addr, addr, addrlen);
2f619698
FB
2335 if (put_user_u32(addrlen, target_addrlen)) {
2336 ret = -TARGET_EFAULT;
2337 goto fail;
2338 }
1be9e1dc
PB
2339 }
2340 unlock_user(host_msg, msg, len);
2341 } else {
2f619698 2342fail:
1be9e1dc
PB
2343 unlock_user(host_msg, msg, 0);
2344 }
2345 return ret;
2346}
2347
32407103 2348#ifdef TARGET_NR_socketcall
0da46a6e 2349/* do_socketcall() Must return target values and target errnos. */
992f48a0 2350static abi_long do_socketcall(int num, abi_ulong vptr)
31e31b8a 2351{
62dc90c6
MT
2352 static const unsigned ac[] = { /* number of arguments per call */
2353 [SOCKOP_socket] = 3, /* domain, type, protocol */
2354 [SOCKOP_bind] = 3, /* sockfd, addr, addrlen */
2355 [SOCKOP_connect] = 3, /* sockfd, addr, addrlen */
2356 [SOCKOP_listen] = 2, /* sockfd, backlog */
2357 [SOCKOP_accept] = 3, /* sockfd, addr, addrlen */
2358 [SOCKOP_accept4] = 4, /* sockfd, addr, addrlen, flags */
2359 [SOCKOP_getsockname] = 3, /* sockfd, addr, addrlen */
2360 [SOCKOP_getpeername] = 3, /* sockfd, addr, addrlen */
2361 [SOCKOP_socketpair] = 4, /* domain, type, protocol, tab */
2362 [SOCKOP_send] = 4, /* sockfd, msg, len, flags */
2363 [SOCKOP_recv] = 4, /* sockfd, msg, len, flags */
2364 [SOCKOP_sendto] = 6, /* sockfd, msg, len, flags, addr, addrlen */
2365 [SOCKOP_recvfrom] = 6, /* sockfd, msg, len, flags, addr, addrlen */
2366 [SOCKOP_shutdown] = 2, /* sockfd, how */
2367 [SOCKOP_sendmsg] = 3, /* sockfd, msg, flags */
2368 [SOCKOP_recvmsg] = 3, /* sockfd, msg, flags */
2369 [SOCKOP_setsockopt] = 5, /* sockfd, level, optname, optval, optlen */
2370 [SOCKOP_getsockopt] = 5, /* sockfd, level, optname, optval, optlen */
2371 };
2372 abi_long a[6]; /* max 6 args */
2373
2374 /* first, collect the arguments in a[] according to ac[] */
2375 if (num >= 0 && num < ARRAY_SIZE(ac)) {
2376 unsigned i;
2377 assert(ARRAY_SIZE(a) >= ac[num]); /* ensure we have space for args */
2378 for (i = 0; i < ac[num]; ++i) {
2379 if (get_user_ual(a[i], vptr + i * sizeof(abi_long)) != 0) {
b9d36eb2
AH
2380 return -TARGET_EFAULT;
2381 }
31e31b8a 2382 }
62dc90c6 2383 }
7854b056 2384
62dc90c6
MT
2385 /* now when we have the args, actually handle the call */
2386 switch (num) {
2387 case SOCKOP_socket: /* domain, type, protocol */
2388 return do_socket(a[0], a[1], a[2]);
2389 case SOCKOP_bind: /* sockfd, addr, addrlen */
2390 return do_bind(a[0], a[1], a[2]);
2391 case SOCKOP_connect: /* sockfd, addr, addrlen */
2392 return do_connect(a[0], a[1], a[2]);
2393 case SOCKOP_listen: /* sockfd, backlog */
2394 return get_errno(listen(a[0], a[1]));
2395 case SOCKOP_accept: /* sockfd, addr, addrlen */
2396 return do_accept4(a[0], a[1], a[2], 0);
2397 case SOCKOP_accept4: /* sockfd, addr, addrlen, flags */
2398 return do_accept4(a[0], a[1], a[2], a[3]);
2399 case SOCKOP_getsockname: /* sockfd, addr, addrlen */
2400 return do_getsockname(a[0], a[1], a[2]);
2401 case SOCKOP_getpeername: /* sockfd, addr, addrlen */
2402 return do_getpeername(a[0], a[1], a[2]);
2403 case SOCKOP_socketpair: /* domain, type, protocol, tab */
2404 return do_socketpair(a[0], a[1], a[2], a[3]);
2405 case SOCKOP_send: /* sockfd, msg, len, flags */
2406 return do_sendto(a[0], a[1], a[2], a[3], 0, 0);
2407 case SOCKOP_recv: /* sockfd, msg, len, flags */
2408 return do_recvfrom(a[0], a[1], a[2], a[3], 0, 0);
2409 case SOCKOP_sendto: /* sockfd, msg, len, flags, addr, addrlen */
2410 return do_sendto(a[0], a[1], a[2], a[3], a[4], a[5]);
2411 case SOCKOP_recvfrom: /* sockfd, msg, len, flags, addr, addrlen */
2412 return do_recvfrom(a[0], a[1], a[2], a[3], a[4], a[5]);
2413 case SOCKOP_shutdown: /* sockfd, how */
2414 return get_errno(shutdown(a[0], a[1]));
2415 case SOCKOP_sendmsg: /* sockfd, msg, flags */
2416 return do_sendrecvmsg(a[0], a[1], a[2], 1);
2417 case SOCKOP_recvmsg: /* sockfd, msg, flags */
2418 return do_sendrecvmsg(a[0], a[1], a[2], 0);
2419 case SOCKOP_setsockopt: /* sockfd, level, optname, optval, optlen */
2420 return do_setsockopt(a[0], a[1], a[2], a[3], a[4]);
2421 case SOCKOP_getsockopt: /* sockfd, level, optname, optval, optlen */
2422 return do_getsockopt(a[0], a[1], a[2], a[3], a[4]);
31e31b8a
FB
2423 default:
2424 gemu_log("Unsupported socketcall: %d\n", num);
62dc90c6 2425 return -TARGET_ENOSYS;
31e31b8a 2426 }
31e31b8a 2427}
32407103 2428#endif
31e31b8a 2429
8853f86e
FB
2430#define N_SHM_REGIONS 32
2431
2432static struct shm_region {
5a4a898d
FB
2433 abi_ulong start;
2434 abi_ulong size;
8853f86e
FB
2435} shm_regions[N_SHM_REGIONS];
2436
3eb6b044
TS
2437struct target_semid_ds
2438{
2439 struct target_ipc_perm sem_perm;
992f48a0 2440 abi_ulong sem_otime;
03527344 2441#if !defined(TARGET_PPC64)
992f48a0 2442 abi_ulong __unused1;
03527344 2443#endif
992f48a0 2444 abi_ulong sem_ctime;
03527344 2445#if !defined(TARGET_PPC64)
992f48a0 2446 abi_ulong __unused2;
03527344 2447#endif
992f48a0
BS
2448 abi_ulong sem_nsems;
2449 abi_ulong __unused3;
2450 abi_ulong __unused4;
3eb6b044
TS
2451};
2452
579a97f7
FB
2453static inline abi_long target_to_host_ipc_perm(struct ipc_perm *host_ip,
2454 abi_ulong target_addr)
3eb6b044
TS
2455{
2456 struct target_ipc_perm *target_ip;
2457 struct target_semid_ds *target_sd;
2458
579a97f7
FB
2459 if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
2460 return -TARGET_EFAULT;
e8bbe36c 2461 target_ip = &(target_sd->sem_perm);
55a2b163
PJ
2462 host_ip->__key = tswap32(target_ip->__key);
2463 host_ip->uid = tswap32(target_ip->uid);
2464 host_ip->gid = tswap32(target_ip->gid);
2465 host_ip->cuid = tswap32(target_ip->cuid);
2466 host_ip->cgid = tswap32(target_ip->cgid);
2467#if defined(TARGET_ALPHA) || defined(TARGET_MIPS) || defined(TARGET_PPC)
2468 host_ip->mode = tswap32(target_ip->mode);
2469#else
cbb21eed 2470 host_ip->mode = tswap16(target_ip->mode);
55a2b163
PJ
2471#endif
2472#if defined(TARGET_PPC)
2473 host_ip->__seq = tswap32(target_ip->__seq);
2474#else
2475 host_ip->__seq = tswap16(target_ip->__seq);
2476#endif
3eb6b044 2477 unlock_user_struct(target_sd, target_addr, 0);
579a97f7 2478 return 0;
3eb6b044
TS
2479}
2480
579a97f7
FB
2481static inline abi_long host_to_target_ipc_perm(abi_ulong target_addr,
2482 struct ipc_perm *host_ip)
3eb6b044
TS
2483{
2484 struct target_ipc_perm *target_ip;
2485 struct target_semid_ds *target_sd;
2486
579a97f7
FB
2487 if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
2488 return -TARGET_EFAULT;
3eb6b044 2489 target_ip = &(target_sd->sem_perm);
55a2b163
PJ
2490 target_ip->__key = tswap32(host_ip->__key);
2491 target_ip->uid = tswap32(host_ip->uid);
2492 target_ip->gid = tswap32(host_ip->gid);
2493 target_ip->cuid = tswap32(host_ip->cuid);
2494 target_ip->cgid = tswap32(host_ip->cgid);
2495#if defined(TARGET_ALPHA) || defined(TARGET_MIPS) || defined(TARGET_PPC)
2496 target_ip->mode = tswap32(host_ip->mode);
2497#else
cbb21eed 2498 target_ip->mode = tswap16(host_ip->mode);
55a2b163
PJ
2499#endif
2500#if defined(TARGET_PPC)
2501 target_ip->__seq = tswap32(host_ip->__seq);
2502#else
2503 target_ip->__seq = tswap16(host_ip->__seq);
2504#endif
3eb6b044 2505 unlock_user_struct(target_sd, target_addr, 1);
579a97f7 2506 return 0;
3eb6b044
TS
2507}
2508
579a97f7
FB
2509static inline abi_long target_to_host_semid_ds(struct semid_ds *host_sd,
2510 abi_ulong target_addr)
3eb6b044
TS
2511{
2512 struct target_semid_ds *target_sd;
2513
579a97f7
FB
2514 if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
2515 return -TARGET_EFAULT;
e5289087
AJ
2516 if (target_to_host_ipc_perm(&(host_sd->sem_perm),target_addr))
2517 return -TARGET_EFAULT;
cbb21eed
MB
2518 host_sd->sem_nsems = tswapal(target_sd->sem_nsems);
2519 host_sd->sem_otime = tswapal(target_sd->sem_otime);
2520 host_sd->sem_ctime = tswapal(target_sd->sem_ctime);
3eb6b044 2521 unlock_user_struct(target_sd, target_addr, 0);
579a97f7 2522 return 0;
3eb6b044
TS
2523}
2524
579a97f7
FB
2525static inline abi_long host_to_target_semid_ds(abi_ulong target_addr,
2526 struct semid_ds *host_sd)
3eb6b044
TS
2527{
2528 struct target_semid_ds *target_sd;
2529
579a97f7
FB
2530 if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
2531 return -TARGET_EFAULT;
e5289087 2532 if (host_to_target_ipc_perm(target_addr,&(host_sd->sem_perm)))
3a93113a 2533 return -TARGET_EFAULT;
cbb21eed
MB
2534 target_sd->sem_nsems = tswapal(host_sd->sem_nsems);
2535 target_sd->sem_otime = tswapal(host_sd->sem_otime);
2536 target_sd->sem_ctime = tswapal(host_sd->sem_ctime);
3eb6b044 2537 unlock_user_struct(target_sd, target_addr, 1);
579a97f7 2538 return 0;
3eb6b044
TS
2539}
2540
e5289087
AJ
2541struct target_seminfo {
2542 int semmap;
2543 int semmni;
2544 int semmns;
2545 int semmnu;
2546 int semmsl;
2547 int semopm;
2548 int semume;
2549 int semusz;
2550 int semvmx;
2551 int semaem;
2552};
2553
2554static inline abi_long host_to_target_seminfo(abi_ulong target_addr,
2555 struct seminfo *host_seminfo)
2556{
2557 struct target_seminfo *target_seminfo;
2558 if (!lock_user_struct(VERIFY_WRITE, target_seminfo, target_addr, 0))
2559 return -TARGET_EFAULT;
2560 __put_user(host_seminfo->semmap, &target_seminfo->semmap);
2561 __put_user(host_seminfo->semmni, &target_seminfo->semmni);
2562 __put_user(host_seminfo->semmns, &target_seminfo->semmns);
2563 __put_user(host_seminfo->semmnu, &target_seminfo->semmnu);
2564 __put_user(host_seminfo->semmsl, &target_seminfo->semmsl);
2565 __put_user(host_seminfo->semopm, &target_seminfo->semopm);
2566 __put_user(host_seminfo->semume, &target_seminfo->semume);
2567 __put_user(host_seminfo->semusz, &target_seminfo->semusz);
2568 __put_user(host_seminfo->semvmx, &target_seminfo->semvmx);
2569 __put_user(host_seminfo->semaem, &target_seminfo->semaem);
2570 unlock_user_struct(target_seminfo, target_addr, 1);
2571 return 0;
2572}
2573
fa294816
TS
2574union semun {
2575 int val;
3eb6b044 2576 struct semid_ds *buf;
fa294816 2577 unsigned short *array;
e5289087 2578 struct seminfo *__buf;
fa294816
TS
2579};
2580
3eb6b044
TS
2581union target_semun {
2582 int val;
e5289087
AJ
2583 abi_ulong buf;
2584 abi_ulong array;
2585 abi_ulong __buf;
3eb6b044
TS
2586};
2587
e5289087
AJ
2588static inline abi_long target_to_host_semarray(int semid, unsigned short **host_array,
2589 abi_ulong target_addr)
3eb6b044 2590{
e5289087
AJ
2591 int nsems;
2592 unsigned short *array;
2593 union semun semun;
2594 struct semid_ds semid_ds;
2595 int i, ret;
3eb6b044 2596
e5289087
AJ
2597 semun.buf = &semid_ds;
2598
2599 ret = semctl(semid, 0, IPC_STAT, semun);
2600 if (ret == -1)
2601 return get_errno(ret);
2602
2603 nsems = semid_ds.sem_nsems;
2604
2605 *host_array = malloc(nsems*sizeof(unsigned short));
69d4c703
PM
2606 if (!*host_array) {
2607 return -TARGET_ENOMEM;
2608 }
e5289087
AJ
2609 array = lock_user(VERIFY_READ, target_addr,
2610 nsems*sizeof(unsigned short), 1);
69d4c703
PM
2611 if (!array) {
2612 free(*host_array);
e5289087 2613 return -TARGET_EFAULT;
69d4c703 2614 }
e5289087
AJ
2615
2616 for(i=0; i<nsems; i++) {
2617 __get_user((*host_array)[i], &array[i]);
3eb6b044 2618 }
e5289087
AJ
2619 unlock_user(array, target_addr, 0);
2620
579a97f7 2621 return 0;
3eb6b044
TS
2622}
2623
e5289087
AJ
2624static inline abi_long host_to_target_semarray(int semid, abi_ulong target_addr,
2625 unsigned short **host_array)
3eb6b044 2626{
e5289087
AJ
2627 int nsems;
2628 unsigned short *array;
2629 union semun semun;
2630 struct semid_ds semid_ds;
2631 int i, ret;
3eb6b044 2632
e5289087
AJ
2633 semun.buf = &semid_ds;
2634
2635 ret = semctl(semid, 0, IPC_STAT, semun);
2636 if (ret == -1)
2637 return get_errno(ret);
2638
2639 nsems = semid_ds.sem_nsems;
2640
2641 array = lock_user(VERIFY_WRITE, target_addr,
2642 nsems*sizeof(unsigned short), 0);
2643 if (!array)
2644 return -TARGET_EFAULT;
2645
2646 for(i=0; i<nsems; i++) {
2647 __put_user((*host_array)[i], &array[i]);
3eb6b044 2648 }
e5289087
AJ
2649 free(*host_array);
2650 unlock_user(array, target_addr, 1);
2651
579a97f7 2652 return 0;
3eb6b044
TS
2653}
2654
e5289087
AJ
2655static inline abi_long do_semctl(int semid, int semnum, int cmd,
2656 union target_semun target_su)
3eb6b044
TS
2657{
2658 union semun arg;
2659 struct semid_ds dsarg;
7b8118e8 2660 unsigned short *array = NULL;
e5289087
AJ
2661 struct seminfo seminfo;
2662 abi_long ret = -TARGET_EINVAL;
2663 abi_long err;
2664 cmd &= 0xff;
3eb6b044
TS
2665
2666 switch( cmd ) {
2667 case GETVAL:
3eb6b044 2668 case SETVAL:
5464baec
TM
2669 /* In 64 bit cross-endian situations, we will erroneously pick up
2670 * the wrong half of the union for the "val" element. To rectify
2671 * this, the entire 8-byte structure is byteswapped, followed by
2672 * a swap of the 4 byte val field. In other cases, the data is
2673 * already in proper host byte order. */
2674 if (sizeof(target_su.val) != (sizeof(target_su.buf))) {
2675 target_su.buf = tswapal(target_su.buf);
2676 arg.val = tswap32(target_su.val);
2677 } else {
2678 arg.val = target_su.val;
2679 }
e5289087 2680 ret = get_errno(semctl(semid, semnum, cmd, arg));
3eb6b044
TS
2681 break;
2682 case GETALL:
3eb6b044 2683 case SETALL:
e5289087
AJ
2684 err = target_to_host_semarray(semid, &array, target_su.array);
2685 if (err)
2686 return err;
2687 arg.array = array;
2688 ret = get_errno(semctl(semid, semnum, cmd, arg));
2689 err = host_to_target_semarray(semid, target_su.array, &array);
2690 if (err)
2691 return err;
3eb6b044
TS
2692 break;
2693 case IPC_STAT:
3eb6b044 2694 case IPC_SET:
e5289087
AJ
2695 case SEM_STAT:
2696 err = target_to_host_semid_ds(&dsarg, target_su.buf);
2697 if (err)
2698 return err;
2699 arg.buf = &dsarg;
2700 ret = get_errno(semctl(semid, semnum, cmd, arg));
2701 err = host_to_target_semid_ds(target_su.buf, &dsarg);
2702 if (err)
2703 return err;
2704 break;
2705 case IPC_INFO:
2706 case SEM_INFO:
2707 arg.__buf = &seminfo;
2708 ret = get_errno(semctl(semid, semnum, cmd, arg));
2709 err = host_to_target_seminfo(target_su.__buf, &seminfo);
2710 if (err)
2711 return err;
2712 break;
2713 case IPC_RMID:
2714 case GETPID:
2715 case GETNCNT:
2716 case GETZCNT:
2717 ret = get_errno(semctl(semid, semnum, cmd, NULL));
3eb6b044 2718 break;
3eb6b044
TS
2719 }
2720
2721 return ret;
2722}
2723
e5289087
AJ
2724struct target_sembuf {
2725 unsigned short sem_num;
2726 short sem_op;
2727 short sem_flg;
2728};
2729
2730static inline abi_long target_to_host_sembuf(struct sembuf *host_sembuf,
2731 abi_ulong target_addr,
2732 unsigned nsops)
2733{
2734 struct target_sembuf *target_sembuf;
2735 int i;
2736
2737 target_sembuf = lock_user(VERIFY_READ, target_addr,
2738 nsops*sizeof(struct target_sembuf), 1);
2739 if (!target_sembuf)
2740 return -TARGET_EFAULT;
2741
2742 for(i=0; i<nsops; i++) {
2743 __get_user(host_sembuf[i].sem_num, &target_sembuf[i].sem_num);
2744 __get_user(host_sembuf[i].sem_op, &target_sembuf[i].sem_op);
2745 __get_user(host_sembuf[i].sem_flg, &target_sembuf[i].sem_flg);
2746 }
2747
2748 unlock_user(target_sembuf, target_addr, 0);
2749
2750 return 0;
2751}
2752
2753static inline abi_long do_semop(int semid, abi_long ptr, unsigned nsops)
2754{
2755 struct sembuf sops[nsops];
2756
2757 if (target_to_host_sembuf(sops, ptr, nsops))
2758 return -TARGET_EFAULT;
2759
c7128c9f 2760 return get_errno(semop(semid, sops, nsops));
e5289087
AJ
2761}
2762
1bc012f6
TS
2763struct target_msqid_ds
2764{
1c54ff97
AJ
2765 struct target_ipc_perm msg_perm;
2766 abi_ulong msg_stime;
2767#if TARGET_ABI_BITS == 32
2768 abi_ulong __unused1;
2769#endif
2770 abi_ulong msg_rtime;
2771#if TARGET_ABI_BITS == 32
2772 abi_ulong __unused2;
2773#endif
2774 abi_ulong msg_ctime;
2775#if TARGET_ABI_BITS == 32
2776 abi_ulong __unused3;
2777#endif
2778 abi_ulong __msg_cbytes;
2779 abi_ulong msg_qnum;
2780 abi_ulong msg_qbytes;
2781 abi_ulong msg_lspid;
2782 abi_ulong msg_lrpid;
2783 abi_ulong __unused4;
2784 abi_ulong __unused5;
1bc012f6
TS
2785};
2786
579a97f7
FB
2787static inline abi_long target_to_host_msqid_ds(struct msqid_ds *host_md,
2788 abi_ulong target_addr)
1bc012f6
TS
2789{
2790 struct target_msqid_ds *target_md;
2791
579a97f7
FB
2792 if (!lock_user_struct(VERIFY_READ, target_md, target_addr, 1))
2793 return -TARGET_EFAULT;
1c54ff97
AJ
2794 if (target_to_host_ipc_perm(&(host_md->msg_perm),target_addr))
2795 return -TARGET_EFAULT;
cbb21eed
MB
2796 host_md->msg_stime = tswapal(target_md->msg_stime);
2797 host_md->msg_rtime = tswapal(target_md->msg_rtime);
2798 host_md->msg_ctime = tswapal(target_md->msg_ctime);
2799 host_md->__msg_cbytes = tswapal(target_md->__msg_cbytes);
2800 host_md->msg_qnum = tswapal(target_md->msg_qnum);
2801 host_md->msg_qbytes = tswapal(target_md->msg_qbytes);
2802 host_md->msg_lspid = tswapal(target_md->msg_lspid);
2803 host_md->msg_lrpid = tswapal(target_md->msg_lrpid);
1bc012f6 2804 unlock_user_struct(target_md, target_addr, 0);
579a97f7 2805 return 0;
1bc012f6
TS
2806}
2807
579a97f7
FB
2808static inline abi_long host_to_target_msqid_ds(abi_ulong target_addr,
2809 struct msqid_ds *host_md)
1bc012f6
TS
2810{
2811 struct target_msqid_ds *target_md;
2812
579a97f7
FB
2813 if (!lock_user_struct(VERIFY_WRITE, target_md, target_addr, 0))
2814 return -TARGET_EFAULT;
1c54ff97
AJ
2815 if (host_to_target_ipc_perm(target_addr,&(host_md->msg_perm)))
2816 return -TARGET_EFAULT;
cbb21eed
MB
2817 target_md->msg_stime = tswapal(host_md->msg_stime);
2818 target_md->msg_rtime = tswapal(host_md->msg_rtime);
2819 target_md->msg_ctime = tswapal(host_md->msg_ctime);
2820 target_md->__msg_cbytes = tswapal(host_md->__msg_cbytes);
2821 target_md->msg_qnum = tswapal(host_md->msg_qnum);
2822 target_md->msg_qbytes = tswapal(host_md->msg_qbytes);
2823 target_md->msg_lspid = tswapal(host_md->msg_lspid);
2824 target_md->msg_lrpid = tswapal(host_md->msg_lrpid);
1bc012f6 2825 unlock_user_struct(target_md, target_addr, 1);
579a97f7 2826 return 0;
1bc012f6
TS
2827}
2828
1c54ff97
AJ
2829struct target_msginfo {
2830 int msgpool;
2831 int msgmap;
2832 int msgmax;
2833 int msgmnb;
2834 int msgmni;
2835 int msgssz;
2836 int msgtql;
2837 unsigned short int msgseg;
2838};
2839
2840static inline abi_long host_to_target_msginfo(abi_ulong target_addr,
2841 struct msginfo *host_msginfo)
2842{
2843 struct target_msginfo *target_msginfo;
2844 if (!lock_user_struct(VERIFY_WRITE, target_msginfo, target_addr, 0))
2845 return -TARGET_EFAULT;
2846 __put_user(host_msginfo->msgpool, &target_msginfo->msgpool);
2847 __put_user(host_msginfo->msgmap, &target_msginfo->msgmap);
2848 __put_user(host_msginfo->msgmax, &target_msginfo->msgmax);
2849 __put_user(host_msginfo->msgmnb, &target_msginfo->msgmnb);
2850 __put_user(host_msginfo->msgmni, &target_msginfo->msgmni);
2851 __put_user(host_msginfo->msgssz, &target_msginfo->msgssz);
2852 __put_user(host_msginfo->msgtql, &target_msginfo->msgtql);
2853 __put_user(host_msginfo->msgseg, &target_msginfo->msgseg);
2854 unlock_user_struct(target_msginfo, target_addr, 1);
00b229ac 2855 return 0;
1c54ff97
AJ
2856}
2857
2858static inline abi_long do_msgctl(int msgid, int cmd, abi_long ptr)
1bc012f6
TS
2859{
2860 struct msqid_ds dsarg;
1c54ff97
AJ
2861 struct msginfo msginfo;
2862 abi_long ret = -TARGET_EINVAL;
2863
2864 cmd &= 0xff;
2865
2866 switch (cmd) {
1bc012f6
TS
2867 case IPC_STAT:
2868 case IPC_SET:
1c54ff97
AJ
2869 case MSG_STAT:
2870 if (target_to_host_msqid_ds(&dsarg,ptr))
2871 return -TARGET_EFAULT;
2872 ret = get_errno(msgctl(msgid, cmd, &dsarg));
2873 if (host_to_target_msqid_ds(ptr,&dsarg))
2874 return -TARGET_EFAULT;
2875 break;
2876 case IPC_RMID:
2877 ret = get_errno(msgctl(msgid, cmd, NULL));
2878 break;
2879 case IPC_INFO:
2880 case MSG_INFO:
2881 ret = get_errno(msgctl(msgid, cmd, (struct msqid_ds *)&msginfo));
2882 if (host_to_target_msginfo(ptr, &msginfo))
2883 return -TARGET_EFAULT;
2884 break;
1bc012f6 2885 }
1c54ff97 2886
1bc012f6
TS
2887 return ret;
2888}
2889
2890struct target_msgbuf {
1c54ff97
AJ
2891 abi_long mtype;
2892 char mtext[1];
1bc012f6
TS
2893};
2894
992f48a0 2895static inline abi_long do_msgsnd(int msqid, abi_long msgp,
edcc5f9d 2896 ssize_t msgsz, int msgflg)
1bc012f6
TS
2897{
2898 struct target_msgbuf *target_mb;
2899 struct msgbuf *host_mb;
992f48a0 2900 abi_long ret = 0;
1bc012f6 2901
edcc5f9d
TM
2902 if (msgsz < 0) {
2903 return -TARGET_EINVAL;
2904 }
2905
579a97f7
FB
2906 if (!lock_user_struct(VERIFY_READ, target_mb, msgp, 0))
2907 return -TARGET_EFAULT;
1bc012f6 2908 host_mb = malloc(msgsz+sizeof(long));
29e03fcb
HZ
2909 if (!host_mb) {
2910 unlock_user_struct(target_mb, msgp, 0);
2911 return -TARGET_ENOMEM;
2912 }
cbb21eed 2913 host_mb->mtype = (abi_long) tswapal(target_mb->mtype);
1c54ff97 2914 memcpy(host_mb->mtext, target_mb->mtext, msgsz);
1bc012f6
TS
2915 ret = get_errno(msgsnd(msqid, host_mb, msgsz, msgflg));
2916 free(host_mb);
2917 unlock_user_struct(target_mb, msgp, 0);
2918
2919 return ret;
2920}
2921
992f48a0 2922static inline abi_long do_msgrcv(int msqid, abi_long msgp,
1c54ff97 2923 unsigned int msgsz, abi_long msgtyp,
992f48a0 2924 int msgflg)
1bc012f6
TS
2925{
2926 struct target_msgbuf *target_mb;
579a97f7 2927 char *target_mtext;
1bc012f6 2928 struct msgbuf *host_mb;
992f48a0 2929 abi_long ret = 0;
1bc012f6 2930
579a97f7
FB
2931 if (!lock_user_struct(VERIFY_WRITE, target_mb, msgp, 0))
2932 return -TARGET_EFAULT;
1c54ff97 2933
0d07fe47 2934 host_mb = g_malloc(msgsz+sizeof(long));
79dd77de 2935 ret = get_errno(msgrcv(msqid, host_mb, msgsz, msgtyp, msgflg));
1c54ff97 2936
579a97f7
FB
2937 if (ret > 0) {
2938 abi_ulong target_mtext_addr = msgp + sizeof(abi_ulong);
2939 target_mtext = lock_user(VERIFY_WRITE, target_mtext_addr, ret, 0);
2940 if (!target_mtext) {
2941 ret = -TARGET_EFAULT;
2942 goto end;
2943 }
1c54ff97 2944 memcpy(target_mb->mtext, host_mb->mtext, ret);
579a97f7
FB
2945 unlock_user(target_mtext, target_mtext_addr, ret);
2946 }
1c54ff97 2947
cbb21eed 2948 target_mb->mtype = tswapal(host_mb->mtype);
1bc012f6 2949
579a97f7
FB
2950end:
2951 if (target_mb)
2952 unlock_user_struct(target_mb, msgp, 1);
0d07fe47 2953 g_free(host_mb);
1bc012f6
TS
2954 return ret;
2955}
2956
88a8c984
RV
2957static inline abi_long target_to_host_shmid_ds(struct shmid_ds *host_sd,
2958 abi_ulong target_addr)
2959{
2960 struct target_shmid_ds *target_sd;
2961
2962 if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
2963 return -TARGET_EFAULT;
2964 if (target_to_host_ipc_perm(&(host_sd->shm_perm), target_addr))
2965 return -TARGET_EFAULT;
2966 __get_user(host_sd->shm_segsz, &target_sd->shm_segsz);
2967 __get_user(host_sd->shm_atime, &target_sd->shm_atime);
2968 __get_user(host_sd->shm_dtime, &target_sd->shm_dtime);
2969 __get_user(host_sd->shm_ctime, &target_sd->shm_ctime);
2970 __get_user(host_sd->shm_cpid, &target_sd->shm_cpid);
2971 __get_user(host_sd->shm_lpid, &target_sd->shm_lpid);
2972 __get_user(host_sd->shm_nattch, &target_sd->shm_nattch);
2973 unlock_user_struct(target_sd, target_addr, 0);
2974 return 0;
2975}
2976
2977static inline abi_long host_to_target_shmid_ds(abi_ulong target_addr,
2978 struct shmid_ds *host_sd)
2979{
2980 struct target_shmid_ds *target_sd;
2981
2982 if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
2983 return -TARGET_EFAULT;
2984 if (host_to_target_ipc_perm(target_addr, &(host_sd->shm_perm)))
2985 return -TARGET_EFAULT;
2986 __put_user(host_sd->shm_segsz, &target_sd->shm_segsz);
2987 __put_user(host_sd->shm_atime, &target_sd->shm_atime);
2988 __put_user(host_sd->shm_dtime, &target_sd->shm_dtime);
2989 __put_user(host_sd->shm_ctime, &target_sd->shm_ctime);
2990 __put_user(host_sd->shm_cpid, &target_sd->shm_cpid);
2991 __put_user(host_sd->shm_lpid, &target_sd->shm_lpid);
2992 __put_user(host_sd->shm_nattch, &target_sd->shm_nattch);
2993 unlock_user_struct(target_sd, target_addr, 1);
2994 return 0;
2995}
2996
2997struct target_shminfo {
2998 abi_ulong shmmax;
2999 abi_ulong shmmin;
3000 abi_ulong shmmni;
3001 abi_ulong shmseg;
3002 abi_ulong shmall;
3003};
3004
3005static inline abi_long host_to_target_shminfo(abi_ulong target_addr,
3006 struct shminfo *host_shminfo)
3007{
3008 struct target_shminfo *target_shminfo;
3009 if (!lock_user_struct(VERIFY_WRITE, target_shminfo, target_addr, 0))
3010 return -TARGET_EFAULT;
3011 __put_user(host_shminfo->shmmax, &target_shminfo->shmmax);
3012 __put_user(host_shminfo->shmmin, &target_shminfo->shmmin);
3013 __put_user(host_shminfo->shmmni, &target_shminfo->shmmni);
3014 __put_user(host_shminfo->shmseg, &target_shminfo->shmseg);
3015 __put_user(host_shminfo->shmall, &target_shminfo->shmall);
3016 unlock_user_struct(target_shminfo, target_addr, 1);
3017 return 0;
3018}
3019
3020struct target_shm_info {
3021 int used_ids;
3022 abi_ulong shm_tot;
3023 abi_ulong shm_rss;
3024 abi_ulong shm_swp;
3025 abi_ulong swap_attempts;
3026 abi_ulong swap_successes;
3027};
3028
3029static inline abi_long host_to_target_shm_info(abi_ulong target_addr,
3030 struct shm_info *host_shm_info)
3031{
3032 struct target_shm_info *target_shm_info;
3033 if (!lock_user_struct(VERIFY_WRITE, target_shm_info, target_addr, 0))
3034 return -TARGET_EFAULT;
3035 __put_user(host_shm_info->used_ids, &target_shm_info->used_ids);
3036 __put_user(host_shm_info->shm_tot, &target_shm_info->shm_tot);
3037 __put_user(host_shm_info->shm_rss, &target_shm_info->shm_rss);
3038 __put_user(host_shm_info->shm_swp, &target_shm_info->shm_swp);
3039 __put_user(host_shm_info->swap_attempts, &target_shm_info->swap_attempts);
3040 __put_user(host_shm_info->swap_successes, &target_shm_info->swap_successes);
3041 unlock_user_struct(target_shm_info, target_addr, 1);
3042 return 0;
3043}
3044
3045static inline abi_long do_shmctl(int shmid, int cmd, abi_long buf)
3046{
3047 struct shmid_ds dsarg;
3048 struct shminfo shminfo;
3049 struct shm_info shm_info;
3050 abi_long ret = -TARGET_EINVAL;
3051
3052 cmd &= 0xff;
3053
3054 switch(cmd) {
3055 case IPC_STAT:
3056 case IPC_SET:
3057 case SHM_STAT:
3058 if (target_to_host_shmid_ds(&dsarg, buf))
3059 return -TARGET_EFAULT;
3060 ret = get_errno(shmctl(shmid, cmd, &dsarg));
3061 if (host_to_target_shmid_ds(buf, &dsarg))
3062 return -TARGET_EFAULT;
3063 break;
3064 case IPC_INFO:
3065 ret = get_errno(shmctl(shmid, cmd, (struct shmid_ds *)&shminfo));
3066 if (host_to_target_shminfo(buf, &shminfo))
3067 return -TARGET_EFAULT;
3068 break;
3069 case SHM_INFO:
3070 ret = get_errno(shmctl(shmid, cmd, (struct shmid_ds *)&shm_info));
3071 if (host_to_target_shm_info(buf, &shm_info))
3072 return -TARGET_EFAULT;
3073 break;
3074 case IPC_RMID:
3075 case SHM_LOCK:
3076 case SHM_UNLOCK:
3077 ret = get_errno(shmctl(shmid, cmd, NULL));
3078 break;
3079 }
3080
3081 return ret;
3082}
3083
3084static inline abi_ulong do_shmat(int shmid, abi_ulong shmaddr, int shmflg)
3085{
3086 abi_long raddr;
3087 void *host_raddr;
3088 struct shmid_ds shm_info;
3089 int i,ret;
3090
3091 /* find out the length of the shared memory segment */
3092 ret = get_errno(shmctl(shmid, IPC_STAT, &shm_info));
3093 if (is_error(ret)) {
3094 /* can't get length, bail out */
3095 return ret;
3096 }
3097
3098 mmap_lock();
3099
3100 if (shmaddr)
3101 host_raddr = shmat(shmid, (void *)g2h(shmaddr), shmflg);
3102 else {
3103 abi_ulong mmap_start;
3104
3105 mmap_start = mmap_find_vma(0, shm_info.shm_segsz);
3106
3107 if (mmap_start == -1) {
3108 errno = ENOMEM;
3109 host_raddr = (void *)-1;
3110 } else
3111 host_raddr = shmat(shmid, g2h(mmap_start), shmflg | SHM_REMAP);
3112 }
3113
3114 if (host_raddr == (void *)-1) {
3115 mmap_unlock();
3116 return get_errno((long)host_raddr);
3117 }
3118 raddr=h2g((unsigned long)host_raddr);
3119
3120 page_set_flags(raddr, raddr + shm_info.shm_segsz,
3121 PAGE_VALID | PAGE_READ |
3122 ((shmflg & SHM_RDONLY)? 0 : PAGE_WRITE));
3123
3124 for (i = 0; i < N_SHM_REGIONS; i++) {
3125 if (shm_regions[i].start == 0) {
3126 shm_regions[i].start = raddr;
3127 shm_regions[i].size = shm_info.shm_segsz;
3128 break;
3129 }
3130 }
3131
3132 mmap_unlock();
3133 return raddr;
3134
3135}
3136
3137static inline abi_long do_shmdt(abi_ulong shmaddr)
3138{
3139 int i;
3140
3141 for (i = 0; i < N_SHM_REGIONS; ++i) {
3142 if (shm_regions[i].start == shmaddr) {
3143 shm_regions[i].start = 0;
e00ac249 3144 page_set_flags(shmaddr, shmaddr + shm_regions[i].size, 0);
88a8c984
RV
3145 break;
3146 }
3147 }
3148
3149 return get_errno(shmdt(g2h(shmaddr)));
3150}
3151
1c54ff97 3152#ifdef TARGET_NR_ipc
53a5960a 3153/* ??? This only works with linear mappings. */
0da46a6e 3154/* do_ipc() must return target values and target errnos. */
37ed0956
TM
3155static abi_long do_ipc(unsigned int call, abi_long first,
3156 abi_long second, abi_long third,
992f48a0 3157 abi_long ptr, abi_long fifth)
8853f86e
FB
3158{
3159 int version;
992f48a0 3160 abi_long ret = 0;
8853f86e
FB
3161
3162 version = call >> 16;
3163 call &= 0xffff;
3164
3165 switch (call) {
fa294816 3166 case IPCOP_semop:
e5289087 3167 ret = do_semop(first, ptr, second);
fa294816
TS
3168 break;
3169
3170 case IPCOP_semget:
3171 ret = get_errno(semget(first, second, third));
3172 break;
3173
5d2fa8eb
TM
3174 case IPCOP_semctl: {
3175 /* The semun argument to semctl is passed by value, so dereference the
3176 * ptr argument. */
3177 abi_ulong atptr;
37ed0956 3178 get_user_ual(atptr, ptr);
5d2fa8eb 3179 ret = do_semctl(first, second, third,
37ed0956 3180 (union target_semun) atptr);
fa294816 3181 break;
5d2fa8eb 3182 }
d96372ef 3183
1c54ff97
AJ
3184 case IPCOP_msgget:
3185 ret = get_errno(msgget(first, second));
3186 break;
d96372ef 3187
1c54ff97
AJ
3188 case IPCOP_msgsnd:
3189 ret = do_msgsnd(first, ptr, second, third);
3190 break;
d96372ef 3191
1c54ff97
AJ
3192 case IPCOP_msgctl:
3193 ret = do_msgctl(first, second, ptr);
3194 break;
d96372ef 3195
1c54ff97
AJ
3196 case IPCOP_msgrcv:
3197 switch (version) {
3198 case 0:
3199 {
3200 struct target_ipc_kludge {
3201 abi_long msgp;
3202 abi_long msgtyp;
3203 } *tmp;
3204
3205 if (!lock_user_struct(VERIFY_READ, tmp, ptr, 1)) {
3206 ret = -TARGET_EFAULT;
3207 break;
3208 }
d96372ef 3209
79dd77de 3210 ret = do_msgrcv(first, tswapal(tmp->msgp), second, tswapal(tmp->msgtyp), third);
d96372ef 3211
1c54ff97
AJ
3212 unlock_user_struct(tmp, ptr, 0);
3213 break;
3214 }
3215 default:
3216 ret = do_msgrcv(first, ptr, second, fifth, third);
3217 }
3218 break;
d96372ef 3219
8853f86e 3220 case IPCOP_shmat:
88a8c984
RV
3221 switch (version) {
3222 default:
5a4a898d
FB
3223 {
3224 abi_ulong raddr;
88a8c984
RV
3225 raddr = do_shmat(first, ptr, second);
3226 if (is_error(raddr))
3227 return get_errno(raddr);
2f619698 3228 if (put_user_ual(raddr, third))
5a4a898d 3229 return -TARGET_EFAULT;
88a8c984
RV
3230 break;
3231 }
3232 case 1:
3233 ret = -TARGET_EINVAL;
3234 break;
5a4a898d 3235 }
8853f86e
FB
3236 break;
3237 case IPCOP_shmdt:
88a8c984 3238 ret = do_shmdt(ptr);
8853f86e
FB
3239 break;
3240
3241 case IPCOP_shmget:
3242 /* IPC_* flag values are the same on all linux platforms */
3243 ret = get_errno(shmget(first, second, third));
3244 break;
3245
3246 /* IPC_* and SHM_* command values are the same on all linux platforms */
3247 case IPCOP_shmctl:
a2926784 3248 ret = do_shmctl(first, second, ptr);
8853f86e
FB
3249 break;
3250 default:
32407103 3251 gemu_log("Unsupported ipc call: %d (version %d)\n", call, version);
0da46a6e 3252 ret = -TARGET_ENOSYS;
8853f86e
FB
3253 break;
3254 }
3255 return ret;
3256}
32407103 3257#endif
8853f86e 3258
31e31b8a 3259/* kernel structure types definitions */
31e31b8a 3260
001faf32 3261#define STRUCT(name, ...) STRUCT_ ## name,
31e31b8a
FB
3262#define STRUCT_SPECIAL(name) STRUCT_ ## name,
3263enum {
3264#include "syscall_types.h"
3265};
3266#undef STRUCT
3267#undef STRUCT_SPECIAL
3268
001faf32 3269#define STRUCT(name, ...) static const argtype struct_ ## name ## _def[] = { __VA_ARGS__, TYPE_NULL };
31e31b8a
FB
3270#define STRUCT_SPECIAL(name)
3271#include "syscall_types.h"
3272#undef STRUCT
3273#undef STRUCT_SPECIAL
3274
d2ef05bb
PM
3275typedef struct IOCTLEntry IOCTLEntry;
3276
3277typedef abi_long do_ioctl_fn(const IOCTLEntry *ie, uint8_t *buf_temp,
3278 int fd, abi_long cmd, abi_long arg);
3279
3280struct IOCTLEntry {
9c6bf9c7 3281 int target_cmd;
2ab83ea7 3282 unsigned int host_cmd;
31e31b8a
FB
3283 const char *name;
3284 int access;
d2ef05bb 3285 do_ioctl_fn *do_ioctl;
1a9353d2 3286 const argtype arg_type[5];
d2ef05bb 3287};
31e31b8a
FB
3288
3289#define IOC_R 0x0001
3290#define IOC_W 0x0002
3291#define IOC_RW (IOC_R | IOC_W)
3292
3293#define MAX_STRUCT_SIZE 4096
3294
dace20dc 3295#ifdef CONFIG_FIEMAP
285da2b9
PM
3296/* So fiemap access checks don't overflow on 32 bit systems.
3297 * This is very slightly smaller than the limit imposed by
3298 * the underlying kernel.
3299 */
3300#define FIEMAP_MAX_EXTENTS ((UINT_MAX - sizeof(struct fiemap)) \
3301 / sizeof(struct fiemap_extent))
3302
3303static abi_long do_ioctl_fs_ioc_fiemap(const IOCTLEntry *ie, uint8_t *buf_temp,
3304 int fd, abi_long cmd, abi_long arg)
3305{
3306 /* The parameter for this ioctl is a struct fiemap followed
3307 * by an array of struct fiemap_extent whose size is set
3308 * in fiemap->fm_extent_count. The array is filled in by the
3309 * ioctl.
3310 */
3311 int target_size_in, target_size_out;
3312 struct fiemap *fm;
3313 const argtype *arg_type = ie->arg_type;
3314 const argtype extent_arg_type[] = { MK_STRUCT(STRUCT_fiemap_extent) };
3315 void *argptr, *p;
3316 abi_long ret;
3317 int i, extent_size = thunk_type_size(extent_arg_type, 0);
3318 uint32_t outbufsz;
3319 int free_fm = 0;
3320
3321 assert(arg_type[0] == TYPE_PTR);
3322 assert(ie->access == IOC_RW);
3323 arg_type++;
3324 target_size_in = thunk_type_size(arg_type, 0);
3325 argptr = lock_user(VERIFY_READ, arg, target_size_in, 1);
3326 if (!argptr) {
3327 return -TARGET_EFAULT;
3328 }
3329 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
3330 unlock_user(argptr, arg, 0);
3331 fm = (struct fiemap *)buf_temp;
3332 if (fm->fm_extent_count > FIEMAP_MAX_EXTENTS) {
3333 return -TARGET_EINVAL;
3334 }
3335
3336 outbufsz = sizeof (*fm) +
3337 (sizeof(struct fiemap_extent) * fm->fm_extent_count);
3338
3339 if (outbufsz > MAX_STRUCT_SIZE) {
3340 /* We can't fit all the extents into the fixed size buffer.
3341 * Allocate one that is large enough and use it instead.
3342 */
3343 fm = malloc(outbufsz);
3344 if (!fm) {
3345 return -TARGET_ENOMEM;
3346 }
3347 memcpy(fm, buf_temp, sizeof(struct fiemap));
3348 free_fm = 1;
3349 }
3350 ret = get_errno(ioctl(fd, ie->host_cmd, fm));
3351 if (!is_error(ret)) {
3352 target_size_out = target_size_in;
3353 /* An extent_count of 0 means we were only counting the extents
3354 * so there are no structs to copy
3355 */
3356 if (fm->fm_extent_count != 0) {
3357 target_size_out += fm->fm_mapped_extents * extent_size;
3358 }
3359 argptr = lock_user(VERIFY_WRITE, arg, target_size_out, 0);
3360 if (!argptr) {
3361 ret = -TARGET_EFAULT;
3362 } else {
3363 /* Convert the struct fiemap */
3364 thunk_convert(argptr, fm, arg_type, THUNK_TARGET);
3365 if (fm->fm_extent_count != 0) {
3366 p = argptr + target_size_in;
3367 /* ...and then all the struct fiemap_extents */
3368 for (i = 0; i < fm->fm_mapped_extents; i++) {
3369 thunk_convert(p, &fm->fm_extents[i], extent_arg_type,
3370 THUNK_TARGET);
3371 p += extent_size;
3372 }
3373 }
3374 unlock_user(argptr, arg, target_size_out);
3375 }
3376 }
3377 if (free_fm) {
3378 free(fm);
3379 }
3380 return ret;
3381}
dace20dc 3382#endif
285da2b9 3383
059c2f2c
LV
3384static abi_long do_ioctl_ifconf(const IOCTLEntry *ie, uint8_t *buf_temp,
3385 int fd, abi_long cmd, abi_long arg)
3386{
3387 const argtype *arg_type = ie->arg_type;
3388 int target_size;
3389 void *argptr;
3390 int ret;
3391 struct ifconf *host_ifconf;
3392 uint32_t outbufsz;
3393 const argtype ifreq_arg_type[] = { MK_STRUCT(STRUCT_sockaddr_ifreq) };
3394 int target_ifreq_size;
3395 int nb_ifreq;
3396 int free_buf = 0;
3397 int i;
3398 int target_ifc_len;
3399 abi_long target_ifc_buf;
3400 int host_ifc_len;
3401 char *host_ifc_buf;
3402
3403 assert(arg_type[0] == TYPE_PTR);
3404 assert(ie->access == IOC_RW);
3405
3406 arg_type++;
3407 target_size = thunk_type_size(arg_type, 0);
3408
3409 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
3410 if (!argptr)
3411 return -TARGET_EFAULT;
3412 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
3413 unlock_user(argptr, arg, 0);
3414
3415 host_ifconf = (struct ifconf *)(unsigned long)buf_temp;
3416 target_ifc_len = host_ifconf->ifc_len;
3417 target_ifc_buf = (abi_long)(unsigned long)host_ifconf->ifc_buf;
3418
3419 target_ifreq_size = thunk_type_size(ifreq_arg_type, 0);
3420 nb_ifreq = target_ifc_len / target_ifreq_size;
3421 host_ifc_len = nb_ifreq * sizeof(struct ifreq);
3422
3423 outbufsz = sizeof(*host_ifconf) + host_ifc_len;
3424 if (outbufsz > MAX_STRUCT_SIZE) {
3425 /* We can't fit all the extents into the fixed size buffer.
3426 * Allocate one that is large enough and use it instead.
3427 */
3428 host_ifconf = malloc(outbufsz);
3429 if (!host_ifconf) {
3430 return -TARGET_ENOMEM;
3431 }
3432 memcpy(host_ifconf, buf_temp, sizeof(*host_ifconf));
3433 free_buf = 1;
3434 }
3435 host_ifc_buf = (char*)host_ifconf + sizeof(*host_ifconf);
3436
3437 host_ifconf->ifc_len = host_ifc_len;
3438 host_ifconf->ifc_buf = host_ifc_buf;
3439
3440 ret = get_errno(ioctl(fd, ie->host_cmd, host_ifconf));
3441 if (!is_error(ret)) {
3442 /* convert host ifc_len to target ifc_len */
3443
3444 nb_ifreq = host_ifconf->ifc_len / sizeof(struct ifreq);
3445 target_ifc_len = nb_ifreq * target_ifreq_size;
3446 host_ifconf->ifc_len = target_ifc_len;
3447
3448 /* restore target ifc_buf */
3449
3450 host_ifconf->ifc_buf = (char *)(unsigned long)target_ifc_buf;
3451
3452 /* copy struct ifconf to target user */
3453
3454 argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
3455 if (!argptr)
3456 return -TARGET_EFAULT;
3457 thunk_convert(argptr, host_ifconf, arg_type, THUNK_TARGET);
3458 unlock_user(argptr, arg, target_size);
3459
3460 /* copy ifreq[] to target user */
3461
3462 argptr = lock_user(VERIFY_WRITE, target_ifc_buf, target_ifc_len, 0);
3463 for (i = 0; i < nb_ifreq ; i++) {
3464 thunk_convert(argptr + i * target_ifreq_size,
3465 host_ifc_buf + i * sizeof(struct ifreq),
3466 ifreq_arg_type, THUNK_TARGET);
3467 }
3468 unlock_user(argptr, target_ifc_buf, target_ifc_len);
3469 }
3470
3471 if (free_buf) {
3472 free(host_ifconf);
3473 }
3474
3475 return ret;
3476}
3477
56e904ec
AG
3478static abi_long do_ioctl_dm(const IOCTLEntry *ie, uint8_t *buf_temp, int fd,
3479 abi_long cmd, abi_long arg)
3480{
3481 void *argptr;
3482 struct dm_ioctl *host_dm;
3483 abi_long guest_data;
3484 uint32_t guest_data_size;
3485 int target_size;
3486 const argtype *arg_type = ie->arg_type;
3487 abi_long ret;
3488 void *big_buf = NULL;
3489 char *host_data;
3490
3491 arg_type++;
3492 target_size = thunk_type_size(arg_type, 0);
3493 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
3494 if (!argptr) {
3495 ret = -TARGET_EFAULT;
3496 goto out;
3497 }
3498 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
3499 unlock_user(argptr, arg, 0);
3500
3501 /* buf_temp is too small, so fetch things into a bigger buffer */
3502 big_buf = g_malloc0(((struct dm_ioctl*)buf_temp)->data_size * 2);
3503 memcpy(big_buf, buf_temp, target_size);
3504 buf_temp = big_buf;
3505 host_dm = big_buf;
3506
3507 guest_data = arg + host_dm->data_start;
3508 if ((guest_data - arg) < 0) {
3509 ret = -EINVAL;
3510 goto out;
3511 }
3512 guest_data_size = host_dm->data_size - host_dm->data_start;
3513 host_data = (char*)host_dm + host_dm->data_start;
3514
3515 argptr = lock_user(VERIFY_READ, guest_data, guest_data_size, 1);
3516 switch (ie->host_cmd) {
3517 case DM_REMOVE_ALL:
3518 case DM_LIST_DEVICES:
3519 case DM_DEV_CREATE:
3520 case DM_DEV_REMOVE:
3521 case DM_DEV_SUSPEND:
3522 case DM_DEV_STATUS:
3523 case DM_DEV_WAIT:
3524 case DM_TABLE_STATUS:
3525 case DM_TABLE_CLEAR:
3526 case DM_TABLE_DEPS:
3527 case DM_LIST_VERSIONS:
3528 /* no input data */
3529 break;
3530 case DM_DEV_RENAME:
3531 case DM_DEV_SET_GEOMETRY:
3532 /* data contains only strings */
3533 memcpy(host_data, argptr, guest_data_size);
3534 break;
3535 case DM_TARGET_MSG:
3536 memcpy(host_data, argptr, guest_data_size);
3537 *(uint64_t*)host_data = tswap64(*(uint64_t*)argptr);
3538 break;
3539 case DM_TABLE_LOAD:
3540 {
3541 void *gspec = argptr;
3542 void *cur_data = host_data;
3543 const argtype arg_type[] = { MK_STRUCT(STRUCT_dm_target_spec) };
3544 int spec_size = thunk_type_size(arg_type, 0);
3545 int i;
3546
3547 for (i = 0; i < host_dm->target_count; i++) {
3548 struct dm_target_spec *spec = cur_data;
3549 uint32_t next;
3550 int slen;
3551
3552 thunk_convert(spec, gspec, arg_type, THUNK_HOST);
3553 slen = strlen((char*)gspec + spec_size) + 1;
3554 next = spec->next;
3555 spec->next = sizeof(*spec) + slen;
3556 strcpy((char*)&spec[1], gspec + spec_size);
3557 gspec += next;
3558 cur_data += spec->next;
3559 }
3560 break;
3561 }
3562 default:
3563 ret = -TARGET_EINVAL;
3564 goto out;
3565 }
3566 unlock_user(argptr, guest_data, 0);
3567
3568 ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
3569 if (!is_error(ret)) {
3570 guest_data = arg + host_dm->data_start;
3571 guest_data_size = host_dm->data_size - host_dm->data_start;
3572 argptr = lock_user(VERIFY_WRITE, guest_data, guest_data_size, 0);
3573 switch (ie->host_cmd) {
3574 case DM_REMOVE_ALL:
3575 case DM_DEV_CREATE:
3576 case DM_DEV_REMOVE:
3577 case DM_DEV_RENAME:
3578 case DM_DEV_SUSPEND:
3579 case DM_DEV_STATUS:
3580 case DM_TABLE_LOAD:
3581 case DM_TABLE_CLEAR:
3582 case DM_TARGET_MSG:
3583 case DM_DEV_SET_GEOMETRY:
3584 /* no return data */
3585 break;
3586 case DM_LIST_DEVICES:
3587 {
3588 struct dm_name_list *nl = (void*)host_dm + host_dm->data_start;
3589 uint32_t remaining_data = guest_data_size;
3590 void *cur_data = argptr;
3591 const argtype arg_type[] = { MK_STRUCT(STRUCT_dm_name_list) };
3592 int nl_size = 12; /* can't use thunk_size due to alignment */
3593
3594 while (1) {
3595 uint32_t next = nl->next;
3596 if (next) {
3597 nl->next = nl_size + (strlen(nl->name) + 1);
3598 }
3599 if (remaining_data < nl->next) {
3600 host_dm->flags |= DM_BUFFER_FULL_FLAG;
3601 break;
3602 }
3603 thunk_convert(cur_data, nl, arg_type, THUNK_TARGET);
3604 strcpy(cur_data + nl_size, nl->name);
3605 cur_data += nl->next;
3606 remaining_data -= nl->next;
3607 if (!next) {
3608 break;
3609 }
3610 nl = (void*)nl + next;
3611 }
3612 break;
3613 }
3614 case DM_DEV_WAIT:
3615 case DM_TABLE_STATUS:
3616 {
3617 struct dm_target_spec *spec = (void*)host_dm + host_dm->data_start;
3618 void *cur_data = argptr;
3619 const argtype arg_type[] = { MK_STRUCT(STRUCT_dm_target_spec) };
3620 int spec_size = thunk_type_size(arg_type, 0);
3621 int i;
3622
3623 for (i = 0; i < host_dm->target_count; i++) {
3624 uint32_t next = spec->next;
3625 int slen = strlen((char*)&spec[1]) + 1;
3626 spec->next = (cur_data - argptr) + spec_size + slen;
3627 if (guest_data_size < spec->next) {
3628 host_dm->flags |= DM_BUFFER_FULL_FLAG;
3629 break;
3630 }
3631 thunk_convert(cur_data, spec, arg_type, THUNK_TARGET);
3632 strcpy(cur_data + spec_size, (char*)&spec[1]);
3633 cur_data = argptr + spec->next;
3634 spec = (void*)host_dm + host_dm->data_start + next;
3635 }
3636 break;
3637 }
3638 case DM_TABLE_DEPS:
3639 {
3640 void *hdata = (void*)host_dm + host_dm->data_start;
3641 int count = *(uint32_t*)hdata;
3642 uint64_t *hdev = hdata + 8;
3643 uint64_t *gdev = argptr + 8;
3644 int i;
3645
3646 *(uint32_t*)argptr = tswap32(count);
3647 for (i = 0; i < count; i++) {
3648 *gdev = tswap64(*hdev);
3649 gdev++;
3650 hdev++;
3651 }
3652 break;
3653 }
3654 case DM_LIST_VERSIONS:
3655 {
3656 struct dm_target_versions *vers = (void*)host_dm + host_dm->data_start;
3657 uint32_t remaining_data = guest_data_size;
3658 void *cur_data = argptr;
3659 const argtype arg_type[] = { MK_STRUCT(STRUCT_dm_target_versions) };
3660 int vers_size = thunk_type_size(arg_type, 0);
3661
3662 while (1) {
3663 uint32_t next = vers->next;
3664 if (next) {
3665 vers->next = vers_size + (strlen(vers->name) + 1);
3666 }
3667 if (remaining_data < vers->next) {
3668 host_dm->flags |= DM_BUFFER_FULL_FLAG;
3669 break;
3670 }
3671 thunk_convert(cur_data, vers, arg_type, THUNK_TARGET);
3672 strcpy(cur_data + vers_size, vers->name);
3673 cur_data += vers->next;
3674 remaining_data -= vers->next;
3675 if (!next) {
3676 break;
3677 }
3678 vers = (void*)vers + next;
3679 }
3680 break;
3681 }
3682 default:
3683 ret = -TARGET_EINVAL;
3684 goto out;
3685 }
3686 unlock_user(argptr, guest_data, guest_data_size);
3687
3688 argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
3689 if (!argptr) {
3690 ret = -TARGET_EFAULT;
3691 goto out;
3692 }
3693 thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
3694 unlock_user(argptr, arg, target_size);
3695 }
3696out:
ad11ad77 3697 g_free(big_buf);
56e904ec
AG
3698 return ret;
3699}
3700
a59b5e35
AG
3701static abi_long do_ioctl_blkpg(const IOCTLEntry *ie, uint8_t *buf_temp, int fd,
3702 abi_long cmd, abi_long arg)
3703{
3704 void *argptr;
3705 int target_size;
3706 const argtype *arg_type = ie->arg_type;
3707 const argtype part_arg_type[] = { MK_STRUCT(STRUCT_blkpg_partition) };
3708 abi_long ret;
3709
3710 struct blkpg_ioctl_arg *host_blkpg = (void*)buf_temp;
3711 struct blkpg_partition host_part;
3712
3713 /* Read and convert blkpg */
3714 arg_type++;
3715 target_size = thunk_type_size(arg_type, 0);
3716 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
3717 if (!argptr) {
3718 ret = -TARGET_EFAULT;
3719 goto out;
3720 }
3721 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
3722 unlock_user(argptr, arg, 0);
3723
3724 switch (host_blkpg->op) {
3725 case BLKPG_ADD_PARTITION:
3726 case BLKPG_DEL_PARTITION:
3727 /* payload is struct blkpg_partition */
3728 break;
3729 default:
3730 /* Unknown opcode */
3731 ret = -TARGET_EINVAL;
3732 goto out;
3733 }
3734
3735 /* Read and convert blkpg->data */
3736 arg = (abi_long)(uintptr_t)host_blkpg->data;
3737 target_size = thunk_type_size(part_arg_type, 0);
3738 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
3739 if (!argptr) {
3740 ret = -TARGET_EFAULT;
3741 goto out;
3742 }
3743 thunk_convert(&host_part, argptr, part_arg_type, THUNK_HOST);
3744 unlock_user(argptr, arg, 0);
3745
3746 /* Swizzle the data pointer to our local copy and call! */
3747 host_blkpg->data = &host_part;
3748 ret = get_errno(ioctl(fd, ie->host_cmd, host_blkpg));
3749
3750out:
3751 return ret;
3752}
3753
7ff7b666
LV
3754static abi_long do_ioctl_rt(const IOCTLEntry *ie, uint8_t *buf_temp,
3755 int fd, abi_long cmd, abi_long arg)
3756{
3757 const argtype *arg_type = ie->arg_type;
3758 const StructEntry *se;
3759 const argtype *field_types;
3760 const int *dst_offsets, *src_offsets;
3761 int target_size;
3762 void *argptr;
3763 abi_ulong *target_rt_dev_ptr;
3764 unsigned long *host_rt_dev_ptr;
3765 abi_long ret;
3766 int i;
3767
3768 assert(ie->access == IOC_W);
3769 assert(*arg_type == TYPE_PTR);
3770 arg_type++;
3771 assert(*arg_type == TYPE_STRUCT);
3772 target_size = thunk_type_size(arg_type, 0);
3773 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
3774 if (!argptr) {
3775 return -TARGET_EFAULT;
3776 }
3777 arg_type++;
3778 assert(*arg_type == (int)STRUCT_rtentry);
3779 se = struct_entries + *arg_type++;
3780 assert(se->convert[0] == NULL);
3781 /* convert struct here to be able to catch rt_dev string */
3782 field_types = se->field_types;
3783 dst_offsets = se->field_offsets[THUNK_HOST];
3784 src_offsets = se->field_offsets[THUNK_TARGET];
3785 for (i = 0; i < se->nb_fields; i++) {
3786 if (dst_offsets[i] == offsetof(struct rtentry, rt_dev)) {
3787 assert(*field_types == TYPE_PTRVOID);
3788 target_rt_dev_ptr = (abi_ulong *)(argptr + src_offsets[i]);
3789 host_rt_dev_ptr = (unsigned long *)(buf_temp + dst_offsets[i]);
3790 if (*target_rt_dev_ptr != 0) {
3791 *host_rt_dev_ptr = (unsigned long)lock_user_string(
3792 tswapal(*target_rt_dev_ptr));
3793 if (!*host_rt_dev_ptr) {
3794 unlock_user(argptr, arg, 0);
3795 return -TARGET_EFAULT;
3796 }
3797 } else {
3798 *host_rt_dev_ptr = 0;
3799 }
3800 field_types++;
3801 continue;
3802 }
3803 field_types = thunk_convert(buf_temp + dst_offsets[i],
3804 argptr + src_offsets[i],
3805 field_types, THUNK_HOST);
3806 }
3807 unlock_user(argptr, arg, 0);
3808
3809 ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
3810 if (*host_rt_dev_ptr != 0) {
3811 unlock_user((void *)*host_rt_dev_ptr,
3812 *target_rt_dev_ptr, 0);
3813 }
3814 return ret;
3815}
3816
ca56f5b5
PB
3817static abi_long do_ioctl_kdsigaccept(const IOCTLEntry *ie, uint8_t *buf_temp,
3818 int fd, abi_long cmd, abi_long arg)
3819{
3820 int sig = target_to_host_signal(arg);
3821 return get_errno(ioctl(fd, ie->host_cmd, sig));
3822}
3823
9f106a75 3824static IOCTLEntry ioctl_entries[] = {
001faf32 3825#define IOCTL(cmd, access, ...) \
d2ef05bb
PM
3826 { TARGET_ ## cmd, cmd, #cmd, access, 0, { __VA_ARGS__ } },
3827#define IOCTL_SPECIAL(cmd, access, dofn, ...) \
3828 { TARGET_ ## cmd, cmd, #cmd, access, dofn, { __VA_ARGS__ } },
31e31b8a
FB
3829#include "ioctls.h"
3830 { 0, 0, },
3831};
3832
53a5960a 3833/* ??? Implement proper locking for ioctls. */
0da46a6e 3834/* do_ioctl() Must return target values and target errnos. */
992f48a0 3835static abi_long do_ioctl(int fd, abi_long cmd, abi_long arg)
31e31b8a
FB
3836{
3837 const IOCTLEntry *ie;
3838 const argtype *arg_type;
992f48a0 3839 abi_long ret;
31e31b8a 3840 uint8_t buf_temp[MAX_STRUCT_SIZE];
53a5960a
PB
3841 int target_size;
3842 void *argptr;
31e31b8a
FB
3843
3844 ie = ioctl_entries;
3845 for(;;) {
3846 if (ie->target_cmd == 0) {
32407103 3847 gemu_log("Unsupported ioctl: cmd=0x%04lx\n", (long)cmd);
0da46a6e 3848 return -TARGET_ENOSYS;
31e31b8a
FB
3849 }
3850 if (ie->target_cmd == cmd)
3851 break;
3852 ie++;
3853 }
3854 arg_type = ie->arg_type;
9de5e440 3855#if defined(DEBUG)
32407103 3856 gemu_log("ioctl: cmd=0x%04lx (%s)\n", (long)cmd, ie->name);
72f03900 3857#endif
d2ef05bb
PM
3858 if (ie->do_ioctl) {
3859 return ie->do_ioctl(ie, buf_temp, fd, cmd, arg);
3860 }
3861
31e31b8a
FB
3862 switch(arg_type[0]) {
3863 case TYPE_NULL:
3864 /* no argument */
3865 ret = get_errno(ioctl(fd, ie->host_cmd));
3866 break;
3867 case TYPE_PTRVOID:
3868 case TYPE_INT:
3869 /* int argment */
3870 ret = get_errno(ioctl(fd, ie->host_cmd, arg));
3871 break;
3872 case TYPE_PTR:
3873 arg_type++;
53a5960a 3874 target_size = thunk_type_size(arg_type, 0);
31e31b8a
FB
3875 switch(ie->access) {
3876 case IOC_R:
3877 ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
3878 if (!is_error(ret)) {
579a97f7
FB
3879 argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
3880 if (!argptr)
3881 return -TARGET_EFAULT;
53a5960a
PB
3882 thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
3883 unlock_user(argptr, arg, target_size);
31e31b8a
FB
3884 }
3885 break;
3886 case IOC_W:
579a97f7
FB
3887 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
3888 if (!argptr)
3889 return -TARGET_EFAULT;
53a5960a
PB
3890 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
3891 unlock_user(argptr, arg, 0);
31e31b8a
FB
3892 ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
3893 break;
3894 default:
3895 case IOC_RW:
579a97f7
FB
3896 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
3897 if (!argptr)
3898 return -TARGET_EFAULT;
53a5960a
PB
3899 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
3900 unlock_user(argptr, arg, 0);
31e31b8a
FB
3901 ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
3902 if (!is_error(ret)) {
579a97f7
FB
3903 argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
3904 if (!argptr)
3905 return -TARGET_EFAULT;
53a5960a
PB
3906 thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
3907 unlock_user(argptr, arg, target_size);
31e31b8a
FB
3908 }
3909 break;
3910 }
3911 break;
3912 default:
32407103
JM
3913 gemu_log("Unsupported ioctl type: cmd=0x%04lx type=%d\n",
3914 (long)cmd, arg_type[0]);
0da46a6e 3915 ret = -TARGET_ENOSYS;
31e31b8a
FB
3916 break;
3917 }
3918 return ret;
3919}
3920
b39bc503 3921static const bitmask_transtbl iflag_tbl[] = {
31e31b8a
FB
3922 { TARGET_IGNBRK, TARGET_IGNBRK, IGNBRK, IGNBRK },
3923 { TARGET_BRKINT, TARGET_BRKINT, BRKINT, BRKINT },
3924 { TARGET_IGNPAR, TARGET_IGNPAR, IGNPAR, IGNPAR },
3925 { TARGET_PARMRK, TARGET_PARMRK, PARMRK, PARMRK },
3926 { TARGET_INPCK, TARGET_INPCK, INPCK, INPCK },
3927 { TARGET_ISTRIP, TARGET_ISTRIP, ISTRIP, ISTRIP },
3928 { TARGET_INLCR, TARGET_INLCR, INLCR, INLCR },
3929 { TARGET_IGNCR, TARGET_IGNCR, IGNCR, IGNCR },
3930 { TARGET_ICRNL, TARGET_ICRNL, ICRNL, ICRNL },
3931 { TARGET_IUCLC, TARGET_IUCLC, IUCLC, IUCLC },
3932 { TARGET_IXON, TARGET_IXON, IXON, IXON },
3933 { TARGET_IXANY, TARGET_IXANY, IXANY, IXANY },
3934 { TARGET_IXOFF, TARGET_IXOFF, IXOFF, IXOFF },
3935 { TARGET_IMAXBEL, TARGET_IMAXBEL, IMAXBEL, IMAXBEL },
3936 { 0, 0, 0, 0 }
3937};
3938
b39bc503 3939static const bitmask_transtbl oflag_tbl[] = {
31e31b8a
FB
3940 { TARGET_OPOST, TARGET_OPOST, OPOST, OPOST },
3941 { TARGET_OLCUC, TARGET_OLCUC, OLCUC, OLCUC },
3942 { TARGET_ONLCR, TARGET_ONLCR, ONLCR, ONLCR },
3943 { TARGET_OCRNL, TARGET_OCRNL, OCRNL, OCRNL },
3944 { TARGET_ONOCR, TARGET_ONOCR, ONOCR, ONOCR },
3945 { TARGET_ONLRET, TARGET_ONLRET, ONLRET, ONLRET },
3946 { TARGET_OFILL, TARGET_OFILL, OFILL, OFILL },
3947 { TARGET_OFDEL, TARGET_OFDEL, OFDEL, OFDEL },
3948 { TARGET_NLDLY, TARGET_NL0, NLDLY, NL0 },
3949 { TARGET_NLDLY, TARGET_NL1, NLDLY, NL1 },
3950 { TARGET_CRDLY, TARGET_CR0, CRDLY, CR0 },
3951 { TARGET_CRDLY, TARGET_CR1, CRDLY, CR1 },
3952 { TARGET_CRDLY, TARGET_CR2, CRDLY, CR2 },
3953 { TARGET_CRDLY, TARGET_CR3, CRDLY, CR3 },
3954 { TARGET_TABDLY, TARGET_TAB0, TABDLY, TAB0 },
3955 { TARGET_TABDLY, TARGET_TAB1, TABDLY, TAB1 },
3956 { TARGET_TABDLY, TARGET_TAB2, TABDLY, TAB2 },
3957 { TARGET_TABDLY, TARGET_TAB3, TABDLY, TAB3 },
3958 { TARGET_BSDLY, TARGET_BS0, BSDLY, BS0 },
3959 { TARGET_BSDLY, TARGET_BS1, BSDLY, BS1 },
3960 { TARGET_VTDLY, TARGET_VT0, VTDLY, VT0 },
3961 { TARGET_VTDLY, TARGET_VT1, VTDLY, VT1 },
3962 { TARGET_FFDLY, TARGET_FF0, FFDLY, FF0 },
3963 { TARGET_FFDLY, TARGET_FF1, FFDLY, FF1 },
3964 { 0, 0, 0, 0 }
3965};
3966
b39bc503 3967static const bitmask_transtbl cflag_tbl[] = {
31e31b8a
FB
3968 { TARGET_CBAUD, TARGET_B0, CBAUD, B0 },
3969 { TARGET_CBAUD, TARGET_B50, CBAUD, B50 },
3970 { TARGET_CBAUD, TARGET_B75, CBAUD, B75 },
3971 { TARGET_CBAUD, TARGET_B110, CBAUD, B110 },
3972 { TARGET_CBAUD, TARGET_B134, CBAUD, B134 },
3973 { TARGET_CBAUD, TARGET_B150, CBAUD, B150 },
3974 { TARGET_CBAUD, TARGET_B200, CBAUD, B200 },
3975 { TARGET_CBAUD, TARGET_B300, CBAUD, B300 },
3976 { TARGET_CBAUD, TARGET_B600, CBAUD, B600 },
3977 { TARGET_CBAUD, TARGET_B1200, CBAUD, B1200 },
3978 { TARGET_CBAUD, TARGET_B1800, CBAUD, B1800 },
3979 { TARGET_CBAUD, TARGET_B2400, CBAUD, B2400 },
3980 { TARGET_CBAUD, TARGET_B4800, CBAUD, B4800 },
3981 { TARGET_CBAUD, TARGET_B9600, CBAUD, B9600 },
3982 { TARGET_CBAUD, TARGET_B19200, CBAUD, B19200 },
3983 { TARGET_CBAUD, TARGET_B38400, CBAUD, B38400 },
3984 { TARGET_CBAUD, TARGET_B57600, CBAUD, B57600 },
3985 { TARGET_CBAUD, TARGET_B115200, CBAUD, B115200 },
3986 { TARGET_CBAUD, TARGET_B230400, CBAUD, B230400 },
3987 { TARGET_CBAUD, TARGET_B460800, CBAUD, B460800 },
3988 { TARGET_CSIZE, TARGET_CS5, CSIZE, CS5 },
3989 { TARGET_CSIZE, TARGET_CS6, CSIZE, CS6 },
3990 { TARGET_CSIZE, TARGET_CS7, CSIZE, CS7 },
3991 { TARGET_CSIZE, TARGET_CS8, CSIZE, CS8 },
3992 { TARGET_CSTOPB, TARGET_CSTOPB, CSTOPB, CSTOPB },
3993 { TARGET_CREAD, TARGET_CREAD, CREAD, CREAD },
3994 { TARGET_PARENB, TARGET_PARENB, PARENB, PARENB },
3995 { TARGET_PARODD, TARGET_PARODD, PARODD, PARODD },
3996 { TARGET_HUPCL, TARGET_HUPCL, HUPCL, HUPCL },
3997 { TARGET_CLOCAL, TARGET_CLOCAL, CLOCAL, CLOCAL },
3998 { TARGET_CRTSCTS, TARGET_CRTSCTS, CRTSCTS, CRTSCTS },
3999 { 0, 0, 0, 0 }
4000};
4001
b39bc503 4002static const bitmask_transtbl lflag_tbl[] = {
31e31b8a
FB
4003 { TARGET_ISIG, TARGET_ISIG, ISIG, ISIG },
4004 { TARGET_ICANON, TARGET_ICANON, ICANON, ICANON },
4005 { TARGET_XCASE, TARGET_XCASE, XCASE, XCASE },
4006 { TARGET_ECHO, TARGET_ECHO, ECHO, ECHO },
4007 { TARGET_ECHOE, TARGET_ECHOE, ECHOE, ECHOE },
4008 { TARGET_ECHOK, TARGET_ECHOK, ECHOK, ECHOK },
4009 { TARGET_ECHONL, TARGET_ECHONL, ECHONL, ECHONL },
4010 { TARGET_NOFLSH, TARGET_NOFLSH, NOFLSH, NOFLSH },
4011 { TARGET_TOSTOP, TARGET_TOSTOP, TOSTOP, TOSTOP },
4012 { TARGET_ECHOCTL, TARGET_ECHOCTL, ECHOCTL, ECHOCTL },
4013 { TARGET_ECHOPRT, TARGET_ECHOPRT, ECHOPRT, ECHOPRT },
4014 { TARGET_ECHOKE, TARGET_ECHOKE, ECHOKE, ECHOKE },
4015 { TARGET_FLUSHO, TARGET_FLUSHO, FLUSHO, FLUSHO },
4016 { TARGET_PENDIN, TARGET_PENDIN, PENDIN, PENDIN },
4017 { TARGET_IEXTEN, TARGET_IEXTEN, IEXTEN, IEXTEN },
4018 { 0, 0, 0, 0 }
4019};
4020
4021static void target_to_host_termios (void *dst, const void *src)
4022{
4023 struct host_termios *host = dst;
4024 const struct target_termios *target = src;
3b46e624 4025
5fafdf24 4026 host->c_iflag =
31e31b8a 4027 target_to_host_bitmask(tswap32(target->c_iflag), iflag_tbl);
5fafdf24 4028 host->c_oflag =
31e31b8a 4029 target_to_host_bitmask(tswap32(target->c_oflag), oflag_tbl);
5fafdf24 4030 host->c_cflag =
31e31b8a 4031 target_to_host_bitmask(tswap32(target->c_cflag), cflag_tbl);
5fafdf24 4032 host->c_lflag =
31e31b8a
FB
4033 target_to_host_bitmask(tswap32(target->c_lflag), lflag_tbl);
4034 host->c_line = target->c_line;
3b46e624 4035
44607123 4036 memset(host->c_cc, 0, sizeof(host->c_cc));
5fafdf24
TS
4037 host->c_cc[VINTR] = target->c_cc[TARGET_VINTR];
4038 host->c_cc[VQUIT] = target->c_cc[TARGET_VQUIT];
3b46e624 4039 host->c_cc[VERASE] = target->c_cc[TARGET_VERASE];
5fafdf24 4040 host->c_cc[VKILL] = target->c_cc[TARGET_VKILL];
3b46e624 4041 host->c_cc[VEOF] = target->c_cc[TARGET_VEOF];
5fafdf24 4042 host->c_cc[VTIME] = target->c_cc[TARGET_VTIME];
3b46e624 4043 host->c_cc[VMIN] = target->c_cc[TARGET_VMIN];
5fafdf24 4044 host->c_cc[VSWTC] = target->c_cc[TARGET_VSWTC];
3b46e624 4045 host->c_cc[VSTART] = target->c_cc[TARGET_VSTART];
5fafdf24
TS
4046 host->c_cc[VSTOP] = target->c_cc[TARGET_VSTOP];
4047 host->c_cc[VSUSP] = target->c_cc[TARGET_VSUSP];
3b46e624
TS
4048 host->c_cc[VEOL] = target->c_cc[TARGET_VEOL];
4049 host->c_cc[VREPRINT] = target->c_cc[TARGET_VREPRINT];
4050 host->c_cc[VDISCARD] = target->c_cc[TARGET_VDISCARD];
4051 host->c_cc[VWERASE] = target->c_cc[TARGET_VWERASE];
4052 host->c_cc[VLNEXT] = target->c_cc[TARGET_VLNEXT];
5fafdf24 4053 host->c_cc[VEOL2] = target->c_cc[TARGET_VEOL2];
31e31b8a 4054}
3b46e624 4055
31e31b8a
FB
4056static void host_to_target_termios (void *dst, const void *src)
4057{
4058 struct target_termios *target = dst;
4059 const struct host_termios *host = src;
4060
5fafdf24 4061 target->c_iflag =
31e31b8a 4062 tswap32(host_to_target_bitmask(host->c_iflag, iflag_tbl));
5fafdf24 4063 target->c_oflag =
31e31b8a 4064 tswap32(host_to_target_bitmask(host->c_oflag, oflag_tbl));
5fafdf24 4065 target->c_cflag =
31e31b8a 4066 tswap32(host_to_target_bitmask(host->c_cflag, cflag_tbl));
5fafdf24 4067 target->c_lflag =
31e31b8a
FB
4068 tswap32(host_to_target_bitmask(host->c_lflag, lflag_tbl));
4069 target->c_line = host->c_line;
3b46e624 4070
44607123 4071 memset(target->c_cc, 0, sizeof(target->c_cc));
31e31b8a
FB
4072 target->c_cc[TARGET_VINTR] = host->c_cc[VINTR];
4073 target->c_cc[TARGET_VQUIT] = host->c_cc[VQUIT];
4074 target->c_cc[TARGET_VERASE] = host->c_cc[VERASE];
4075 target->c_cc[TARGET_VKILL] = host->c_cc[VKILL];
4076 target->c_cc[TARGET_VEOF] = host->c_cc[VEOF];
4077 target->c_cc[TARGET_VTIME] = host->c_cc[VTIME];
4078 target->c_cc[TARGET_VMIN] = host->c_cc[VMIN];
4079 target->c_cc[TARGET_VSWTC] = host->c_cc[VSWTC];
4080 target->c_cc[TARGET_VSTART] = host->c_cc[VSTART];
4081 target->c_cc[TARGET_VSTOP] = host->c_cc[VSTOP];
4082 target->c_cc[TARGET_VSUSP] = host->c_cc[VSUSP];
4083 target->c_cc[TARGET_VEOL] = host->c_cc[VEOL];
4084 target->c_cc[TARGET_VREPRINT] = host->c_cc[VREPRINT];
4085 target->c_cc[TARGET_VDISCARD] = host->c_cc[VDISCARD];
4086 target->c_cc[TARGET_VWERASE] = host->c_cc[VWERASE];
4087 target->c_cc[TARGET_VLNEXT] = host->c_cc[VLNEXT];
4088 target->c_cc[TARGET_VEOL2] = host->c_cc[VEOL2];
4089}
4090
8e853dc7 4091static const StructEntry struct_termios_def = {
31e31b8a
FB
4092 .convert = { host_to_target_termios, target_to_host_termios },
4093 .size = { sizeof(struct target_termios), sizeof(struct host_termios) },
4094 .align = { __alignof__(struct target_termios), __alignof__(struct host_termios) },
4095};
4096
5286db75
FB
4097static bitmask_transtbl mmap_flags_tbl[] = {
4098 { TARGET_MAP_SHARED, TARGET_MAP_SHARED, MAP_SHARED, MAP_SHARED },
4099 { TARGET_MAP_PRIVATE, TARGET_MAP_PRIVATE, MAP_PRIVATE, MAP_PRIVATE },
4100 { TARGET_MAP_FIXED, TARGET_MAP_FIXED, MAP_FIXED, MAP_FIXED },
4101 { TARGET_MAP_ANONYMOUS, TARGET_MAP_ANONYMOUS, MAP_ANONYMOUS, MAP_ANONYMOUS },
4102 { TARGET_MAP_GROWSDOWN, TARGET_MAP_GROWSDOWN, MAP_GROWSDOWN, MAP_GROWSDOWN },
4103 { TARGET_MAP_DENYWRITE, TARGET_MAP_DENYWRITE, MAP_DENYWRITE, MAP_DENYWRITE },
4104 { TARGET_MAP_EXECUTABLE, TARGET_MAP_EXECUTABLE, MAP_EXECUTABLE, MAP_EXECUTABLE },
4105 { TARGET_MAP_LOCKED, TARGET_MAP_LOCKED, MAP_LOCKED, MAP_LOCKED },
e8efd8e7
CL
4106 { TARGET_MAP_NORESERVE, TARGET_MAP_NORESERVE, MAP_NORESERVE,
4107 MAP_NORESERVE },
5286db75
FB
4108 { 0, 0, 0, 0 }
4109};
4110
2ab83ea7 4111#if defined(TARGET_I386)
6dbad63e
FB
4112
4113/* NOTE: there is really one LDT for all the threads */
b1d8e52e 4114static uint8_t *ldt_table;
6dbad63e 4115
03acab66 4116static abi_long read_ldt(abi_ulong ptr, unsigned long bytecount)
6dbad63e
FB
4117{
4118 int size;
53a5960a 4119 void *p;
6dbad63e
FB
4120
4121 if (!ldt_table)
4122 return 0;
4123 size = TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE;
4124 if (size > bytecount)
4125 size = bytecount;
579a97f7
FB
4126 p = lock_user(VERIFY_WRITE, ptr, size, 0);
4127 if (!p)
03acab66 4128 return -TARGET_EFAULT;
579a97f7 4129 /* ??? Should this by byteswapped? */
53a5960a
PB
4130 memcpy(p, ldt_table, size);
4131 unlock_user(p, ptr, size);
6dbad63e
FB
4132 return size;
4133}
4134
4135/* XXX: add locking support */
03acab66
FB
4136static abi_long write_ldt(CPUX86State *env,
4137 abi_ulong ptr, unsigned long bytecount, int oldmode)
6dbad63e
FB
4138{
4139 struct target_modify_ldt_ldt_s ldt_info;
53a5960a 4140 struct target_modify_ldt_ldt_s *target_ldt_info;
6dbad63e 4141 int seg_32bit, contents, read_exec_only, limit_in_pages;
8d18e893 4142 int seg_not_present, useable, lm;
6dbad63e
FB
4143 uint32_t *lp, entry_1, entry_2;
4144
4145 if (bytecount != sizeof(ldt_info))
03acab66 4146 return -TARGET_EINVAL;
579a97f7 4147 if (!lock_user_struct(VERIFY_READ, target_ldt_info, ptr, 1))
03acab66 4148 return -TARGET_EFAULT;
53a5960a 4149 ldt_info.entry_number = tswap32(target_ldt_info->entry_number);
cbb21eed 4150 ldt_info.base_addr = tswapal(target_ldt_info->base_addr);
53a5960a
PB
4151 ldt_info.limit = tswap32(target_ldt_info->limit);
4152 ldt_info.flags = tswap32(target_ldt_info->flags);
4153 unlock_user_struct(target_ldt_info, ptr, 0);
3b46e624 4154
6dbad63e 4155 if (ldt_info.entry_number >= TARGET_LDT_ENTRIES)
03acab66 4156 return -TARGET_EINVAL;
6dbad63e
FB
4157 seg_32bit = ldt_info.flags & 1;
4158 contents = (ldt_info.flags >> 1) & 3;
4159 read_exec_only = (ldt_info.flags >> 3) & 1;
4160 limit_in_pages = (ldt_info.flags >> 4) & 1;
4161 seg_not_present = (ldt_info.flags >> 5) & 1;
4162 useable = (ldt_info.flags >> 6) & 1;
8d18e893
FB
4163#ifdef TARGET_ABI32
4164 lm = 0;
4165#else
4166 lm = (ldt_info.flags >> 7) & 1;
4167#endif
6dbad63e
FB
4168 if (contents == 3) {
4169 if (oldmode)
03acab66 4170 return -TARGET_EINVAL;
6dbad63e 4171 if (seg_not_present == 0)
03acab66 4172 return -TARGET_EINVAL;
6dbad63e
FB
4173 }
4174 /* allocate the LDT */
4175 if (!ldt_table) {
e441570f
AZ
4176 env->ldt.base = target_mmap(0,
4177 TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE,
4178 PROT_READ|PROT_WRITE,
4179 MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
4180 if (env->ldt.base == -1)
03acab66 4181 return -TARGET_ENOMEM;
e441570f
AZ
4182 memset(g2h(env->ldt.base), 0,
4183 TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE);
6dbad63e 4184 env->ldt.limit = 0xffff;
e441570f 4185 ldt_table = g2h(env->ldt.base);
6dbad63e
FB
4186 }
4187
4188 /* NOTE: same code as Linux kernel */
4189 /* Allow LDTs to be cleared by the user. */
4190 if (ldt_info.base_addr == 0 && ldt_info.limit == 0) {
4191 if (oldmode ||
4192 (contents == 0 &&
4193 read_exec_only == 1 &&
4194 seg_32bit == 0 &&
4195 limit_in_pages == 0 &&
4196 seg_not_present == 1 &&
4197 useable == 0 )) {
4198 entry_1 = 0;
4199 entry_2 = 0;
4200 goto install;
4201 }
4202 }
3b46e624 4203
6dbad63e
FB
4204 entry_1 = ((ldt_info.base_addr & 0x0000ffff) << 16) |
4205 (ldt_info.limit & 0x0ffff);
4206 entry_2 = (ldt_info.base_addr & 0xff000000) |
4207 ((ldt_info.base_addr & 0x00ff0000) >> 16) |
4208 (ldt_info.limit & 0xf0000) |
4209 ((read_exec_only ^ 1) << 9) |
4210 (contents << 10) |
4211 ((seg_not_present ^ 1) << 15) |
4212 (seg_32bit << 22) |
4213 (limit_in_pages << 23) |
8d18e893 4214 (lm << 21) |
6dbad63e
FB
4215 0x7000;
4216 if (!oldmode)
4217 entry_2 |= (useable << 20);
14ae3ba7 4218
6dbad63e
FB
4219 /* Install the new entry ... */
4220install:
4221 lp = (uint32_t *)(ldt_table + (ldt_info.entry_number << 3));
4222 lp[0] = tswap32(entry_1);
4223 lp[1] = tswap32(entry_2);
4224 return 0;
4225}
4226
4227/* specific and weird i386 syscalls */
8fcd3692
BS
4228static abi_long do_modify_ldt(CPUX86State *env, int func, abi_ulong ptr,
4229 unsigned long bytecount)
6dbad63e 4230{
03acab66 4231 abi_long ret;
3b46e624 4232
6dbad63e
FB
4233 switch (func) {
4234 case 0:
4235 ret = read_ldt(ptr, bytecount);
4236 break;
4237 case 1:
4238 ret = write_ldt(env, ptr, bytecount, 1);
4239 break;
4240 case 0x11:
4241 ret = write_ldt(env, ptr, bytecount, 0);
4242 break;
03acab66
FB
4243 default:
4244 ret = -TARGET_ENOSYS;
4245 break;
6dbad63e
FB
4246 }
4247 return ret;
4248}
1b6b029e 4249
4583f589 4250#if defined(TARGET_I386) && defined(TARGET_ABI32)
bc22eb44 4251abi_long do_set_thread_area(CPUX86State *env, abi_ulong ptr)
8d18e893
FB
4252{
4253 uint64_t *gdt_table = g2h(env->gdt.base);
4254 struct target_modify_ldt_ldt_s ldt_info;
4255 struct target_modify_ldt_ldt_s *target_ldt_info;
4256 int seg_32bit, contents, read_exec_only, limit_in_pages;
4257 int seg_not_present, useable, lm;
4258 uint32_t *lp, entry_1, entry_2;
4259 int i;
4260
4261 lock_user_struct(VERIFY_WRITE, target_ldt_info, ptr, 1);
4262 if (!target_ldt_info)
4263 return -TARGET_EFAULT;
4264 ldt_info.entry_number = tswap32(target_ldt_info->entry_number);
cbb21eed 4265 ldt_info.base_addr = tswapal(target_ldt_info->base_addr);
8d18e893
FB
4266 ldt_info.limit = tswap32(target_ldt_info->limit);
4267 ldt_info.flags = tswap32(target_ldt_info->flags);
4268 if (ldt_info.entry_number == -1) {
4269 for (i=TARGET_GDT_ENTRY_TLS_MIN; i<=TARGET_GDT_ENTRY_TLS_MAX; i++) {
4270 if (gdt_table[i] == 0) {
4271 ldt_info.entry_number = i;
4272 target_ldt_info->entry_number = tswap32(i);
4273 break;
4274 }
4275 }
4276 }
4277 unlock_user_struct(target_ldt_info, ptr, 1);
4278
4279 if (ldt_info.entry_number < TARGET_GDT_ENTRY_TLS_MIN ||
4280 ldt_info.entry_number > TARGET_GDT_ENTRY_TLS_MAX)
4281 return -TARGET_EINVAL;
4282 seg_32bit = ldt_info.flags & 1;
4283 contents = (ldt_info.flags >> 1) & 3;
4284 read_exec_only = (ldt_info.flags >> 3) & 1;
4285 limit_in_pages = (ldt_info.flags >> 4) & 1;
4286 seg_not_present = (ldt_info.flags >> 5) & 1;
4287 useable = (ldt_info.flags >> 6) & 1;
4288#ifdef TARGET_ABI32
4289 lm = 0;
4290#else
4291 lm = (ldt_info.flags >> 7) & 1;
4292#endif
4293
4294 if (contents == 3) {
4295 if (seg_not_present == 0)
4296 return -TARGET_EINVAL;
4297 }
4298
4299 /* NOTE: same code as Linux kernel */
4300 /* Allow LDTs to be cleared by the user. */
4301 if (ldt_info.base_addr == 0 && ldt_info.limit == 0) {
4302 if ((contents == 0 &&
4303 read_exec_only == 1 &&
4304 seg_32bit == 0 &&
4305 limit_in_pages == 0 &&
4306 seg_not_present == 1 &&
4307 useable == 0 )) {
4308 entry_1 = 0;
4309 entry_2 = 0;
4310 goto install;
4311 }
4312 }
4313
4314 entry_1 = ((ldt_info.base_addr & 0x0000ffff) << 16) |
4315 (ldt_info.limit & 0x0ffff);
4316 entry_2 = (ldt_info.base_addr & 0xff000000) |
4317 ((ldt_info.base_addr & 0x00ff0000) >> 16) |
4318 (ldt_info.limit & 0xf0000) |
4319 ((read_exec_only ^ 1) << 9) |
4320 (contents << 10) |
4321 ((seg_not_present ^ 1) << 15) |
4322 (seg_32bit << 22) |
4323 (limit_in_pages << 23) |
4324 (useable << 20) |
4325 (lm << 21) |
4326 0x7000;
4327
4328 /* Install the new entry ... */
4329install:
4330 lp = (uint32_t *)(gdt_table + ldt_info.entry_number);
4331 lp[0] = tswap32(entry_1);
4332 lp[1] = tswap32(entry_2);
4333 return 0;
4334}
4335
8fcd3692 4336static abi_long do_get_thread_area(CPUX86State *env, abi_ulong ptr)
8d18e893
FB
4337{
4338 struct target_modify_ldt_ldt_s *target_ldt_info;
4339 uint64_t *gdt_table = g2h(env->gdt.base);
4340 uint32_t base_addr, limit, flags;
4341 int seg_32bit, contents, read_exec_only, limit_in_pages, idx;
4342 int seg_not_present, useable, lm;
4343 uint32_t *lp, entry_1, entry_2;
4344
4345 lock_user_struct(VERIFY_WRITE, target_ldt_info, ptr, 1);
4346 if (!target_ldt_info)
4347 return -TARGET_EFAULT;
4348 idx = tswap32(target_ldt_info->entry_number);
4349 if (idx < TARGET_GDT_ENTRY_TLS_MIN ||
4350 idx > TARGET_GDT_ENTRY_TLS_MAX) {
4351 unlock_user_struct(target_ldt_info, ptr, 1);
4352 return -TARGET_EINVAL;
4353 }
4354 lp = (uint32_t *)(gdt_table + idx);
4355 entry_1 = tswap32(lp[0]);
4356 entry_2 = tswap32(lp[1]);
4357
4358 read_exec_only = ((entry_2 >> 9) & 1) ^ 1;
4359 contents = (entry_2 >> 10) & 3;
4360 seg_not_present = ((entry_2 >> 15) & 1) ^ 1;
4361 seg_32bit = (entry_2 >> 22) & 1;
4362 limit_in_pages = (entry_2 >> 23) & 1;
4363 useable = (entry_2 >> 20) & 1;
4364#ifdef TARGET_ABI32
4365 lm = 0;
4366#else
4367 lm = (entry_2 >> 21) & 1;
4368#endif
4369 flags = (seg_32bit << 0) | (contents << 1) |
4370 (read_exec_only << 3) | (limit_in_pages << 4) |
4371 (seg_not_present << 5) | (useable << 6) | (lm << 7);
4372 limit = (entry_1 & 0xffff) | (entry_2 & 0xf0000);
4373 base_addr = (entry_1 >> 16) |
4374 (entry_2 & 0xff000000) |
4375 ((entry_2 & 0xff) << 16);
cbb21eed 4376 target_ldt_info->base_addr = tswapal(base_addr);
8d18e893
FB
4377 target_ldt_info->limit = tswap32(limit);
4378 target_ldt_info->flags = tswap32(flags);
4379 unlock_user_struct(target_ldt_info, ptr, 1);
4380 return 0;
4381}
4583f589 4382#endif /* TARGET_I386 && TARGET_ABI32 */
8d18e893 4383
d2fd1af7 4384#ifndef TARGET_ABI32
2667e71c 4385abi_long do_arch_prctl(CPUX86State *env, int code, abi_ulong addr)
d2fd1af7 4386{
1add8698 4387 abi_long ret = 0;
d2fd1af7
FB
4388 abi_ulong val;
4389 int idx;
1add8698 4390
d2fd1af7
FB
4391 switch(code) {
4392 case TARGET_ARCH_SET_GS:
4393 case TARGET_ARCH_SET_FS:
4394 if (code == TARGET_ARCH_SET_GS)
4395 idx = R_GS;
4396 else
4397 idx = R_FS;
4398 cpu_x86_load_seg(env, idx, 0);
4399 env->segs[idx].base = addr;
4400 break;
4401 case TARGET_ARCH_GET_GS:
4402 case TARGET_ARCH_GET_FS:
4403 if (code == TARGET_ARCH_GET_GS)
4404 idx = R_GS;
4405 else
4406 idx = R_FS;
4407 val = env->segs[idx].base;
4408 if (put_user(val, addr, abi_ulong))
1add8698 4409 ret = -TARGET_EFAULT;
d2fd1af7
FB
4410 break;
4411 default:
4412 ret = -TARGET_EINVAL;
4413 break;
4414 }
1add8698 4415 return ret;
d2fd1af7
FB
4416}
4417#endif
4418
2ab83ea7
FB
4419#endif /* defined(TARGET_I386) */
4420
05098a93 4421#define NEW_STACK_SIZE 0x40000
d865bab5 4422
d865bab5
PB
4423
4424static pthread_mutex_t clone_lock = PTHREAD_MUTEX_INITIALIZER;
4425typedef struct {
9349b4f9 4426 CPUArchState *env;
d865bab5
PB
4427 pthread_mutex_t mutex;
4428 pthread_cond_t cond;
4429 pthread_t thread;
4430 uint32_t tid;
4431 abi_ulong child_tidptr;
4432 abi_ulong parent_tidptr;
4433 sigset_t sigmask;
4434} new_thread_info;
4435
4436static void *clone_func(void *arg)
4437{
4438 new_thread_info *info = arg;
9349b4f9 4439 CPUArchState *env;
0d34282f 4440 CPUState *cpu;
edf8e2af 4441 TaskState *ts;
d865bab5
PB
4442
4443 env = info->env;
0d34282f 4444 cpu = ENV_GET_CPU(env);
a2247f8e 4445 thread_cpu = cpu;
0429a971 4446 ts = (TaskState *)cpu->opaque;
d865bab5 4447 info->tid = gettid();
0d34282f 4448 cpu->host_tid = info->tid;
edf8e2af 4449 task_settid(ts);
d865bab5
PB
4450 if (info->child_tidptr)
4451 put_user_u32(info->tid, info->child_tidptr);
4452 if (info->parent_tidptr)
4453 put_user_u32(info->tid, info->parent_tidptr);
4454 /* Enable signals. */
4455 sigprocmask(SIG_SETMASK, &info->sigmask, NULL);
4456 /* Signal to the parent that we're ready. */
4457 pthread_mutex_lock(&info->mutex);
4458 pthread_cond_broadcast(&info->cond);
4459 pthread_mutex_unlock(&info->mutex);
4460 /* Wait until the parent has finshed initializing the tls state. */
4461 pthread_mutex_lock(&clone_lock);
4462 pthread_mutex_unlock(&clone_lock);
4463 cpu_loop(env);
4464 /* never exits */
4465 return NULL;
4466}
1b6b029e 4467
0da46a6e
TS
4468/* do_fork() Must return host values and target errnos (unlike most
4469 do_*() functions). */
9349b4f9 4470static int do_fork(CPUArchState *env, unsigned int flags, abi_ulong newsp,
d865bab5
PB
4471 abi_ulong parent_tidptr, target_ulong newtls,
4472 abi_ulong child_tidptr)
1b6b029e 4473{
0429a971 4474 CPUState *cpu = ENV_GET_CPU(env);
1b6b029e 4475 int ret;
5cd4393b 4476 TaskState *ts;
0429a971 4477 CPUState *new_cpu;
9349b4f9 4478 CPUArchState *new_env;
d865bab5
PB
4479 unsigned int nptl_flags;
4480 sigset_t sigmask;
3b46e624 4481
436d124b
AZ
4482 /* Emulate vfork() with fork() */
4483 if (flags & CLONE_VFORK)
4484 flags &= ~(CLONE_VFORK | CLONE_VM);
4485
1b6b029e 4486 if (flags & CLONE_VM) {
0429a971 4487 TaskState *parent_ts = (TaskState *)cpu->opaque;
d865bab5
PB
4488 new_thread_info info;
4489 pthread_attr_t attr;
24cb36a6 4490
7267c094 4491 ts = g_malloc0(sizeof(TaskState));
624f7979 4492 init_task_state(ts);
1b6b029e 4493 /* we create a new CPU instance. */
c5be9f08 4494 new_env = cpu_copy(env);
6e68e076
PB
4495 /* Init regs that differ from the parent. */
4496 cpu_clone_regs(new_env, newsp);
0429a971
AF
4497 new_cpu = ENV_GET_CPU(new_env);
4498 new_cpu->opaque = ts;
edf8e2af
MW
4499 ts->bprm = parent_ts->bprm;
4500 ts->info = parent_ts->info;
d865bab5
PB
4501 nptl_flags = flags;
4502 flags &= ~CLONE_NPTL_FLAGS2;
4503
c2764719
PB
4504 if (nptl_flags & CLONE_CHILD_CLEARTID) {
4505 ts->child_tidptr = child_tidptr;
4506 }
4507
d865bab5
PB
4508 if (nptl_flags & CLONE_SETTLS)
4509 cpu_set_tls (new_env, newtls);
4510
4511 /* Grab a mutex so that thread setup appears atomic. */
4512 pthread_mutex_lock(&clone_lock);
4513
4514 memset(&info, 0, sizeof(info));
4515 pthread_mutex_init(&info.mutex, NULL);
4516 pthread_mutex_lock(&info.mutex);
4517 pthread_cond_init(&info.cond, NULL);
4518 info.env = new_env;
4519 if (nptl_flags & CLONE_CHILD_SETTID)
4520 info.child_tidptr = child_tidptr;
4521 if (nptl_flags & CLONE_PARENT_SETTID)
4522 info.parent_tidptr = parent_tidptr;
4523
4524 ret = pthread_attr_init(&attr);
48e15fc2
NF
4525 ret = pthread_attr_setstacksize(&attr, NEW_STACK_SIZE);
4526 ret = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
d865bab5
PB
4527 /* It is not safe to deliver signals until the child has finished
4528 initializing, so temporarily block all signals. */
4529 sigfillset(&sigmask);
4530 sigprocmask(SIG_BLOCK, &sigmask, &info.sigmask);
4531
4532 ret = pthread_create(&info.thread, &attr, clone_func, &info);
c2764719 4533 /* TODO: Free new CPU state if thread creation failed. */
d865bab5
PB
4534
4535 sigprocmask(SIG_SETMASK, &info.sigmask, NULL);
4536 pthread_attr_destroy(&attr);
4537 if (ret == 0) {
4538 /* Wait for the child to initialize. */
4539 pthread_cond_wait(&info.cond, &info.mutex);
4540 ret = info.tid;
4541 if (flags & CLONE_PARENT_SETTID)
4542 put_user_u32(ret, parent_tidptr);
4543 } else {
4544 ret = -1;
4545 }
4546 pthread_mutex_unlock(&info.mutex);
4547 pthread_cond_destroy(&info.cond);
4548 pthread_mutex_destroy(&info.mutex);
4549 pthread_mutex_unlock(&clone_lock);
1b6b029e
FB
4550 } else {
4551 /* if no CLONE_VM, we consider it is a fork */
d865bab5 4552 if ((flags & ~(CSIGNAL | CLONE_NPTL_FLAGS2)) != 0)
1b6b029e 4553 return -EINVAL;
d865bab5 4554 fork_start();
1b6b029e 4555 ret = fork();
d865bab5 4556 if (ret == 0) {
2b1319c8 4557 /* Child Process. */
d865bab5
PB
4558 cpu_clone_regs(env, newsp);
4559 fork_end(1);
2b1319c8
AJ
4560 /* There is a race condition here. The parent process could
4561 theoretically read the TID in the child process before the child
4562 tid is set. This would require using either ptrace
4563 (not implemented) or having *_tidptr to point at a shared memory
4564 mapping. We can't repeat the spinlock hack used above because
4565 the child process gets its own copy of the lock. */
d865bab5
PB
4566 if (flags & CLONE_CHILD_SETTID)
4567 put_user_u32(gettid(), child_tidptr);
4568 if (flags & CLONE_PARENT_SETTID)
4569 put_user_u32(gettid(), parent_tidptr);
0429a971 4570 ts = (TaskState *)cpu->opaque;
d865bab5
PB
4571 if (flags & CLONE_SETTLS)
4572 cpu_set_tls (env, newtls);
c2764719
PB
4573 if (flags & CLONE_CHILD_CLEARTID)
4574 ts->child_tidptr = child_tidptr;
d865bab5
PB
4575 } else {
4576 fork_end(0);
4577 }
1b6b029e
FB
4578 }
4579 return ret;
4580}
4581
5f106811
APR
4582/* warning : doesn't handle linux specific flags... */
4583static int target_to_host_fcntl_cmd(int cmd)
4584{
4585 switch(cmd) {
4586 case TARGET_F_DUPFD:
4587 case TARGET_F_GETFD:
4588 case TARGET_F_SETFD:
4589 case TARGET_F_GETFL:
4590 case TARGET_F_SETFL:
4591 return cmd;
4592 case TARGET_F_GETLK:
4593 return F_GETLK;
4594 case TARGET_F_SETLK:
4595 return F_SETLK;
4596 case TARGET_F_SETLKW:
4597 return F_SETLKW;
4598 case TARGET_F_GETOWN:
4599 return F_GETOWN;
4600 case TARGET_F_SETOWN:
4601 return F_SETOWN;
4602 case TARGET_F_GETSIG:
4603 return F_GETSIG;
4604 case TARGET_F_SETSIG:
4605 return F_SETSIG;
4606#if TARGET_ABI_BITS == 32
4607 case TARGET_F_GETLK64:
4608 return F_GETLK64;
4609 case TARGET_F_SETLK64:
4610 return F_SETLK64;
4611 case TARGET_F_SETLKW64:
4612 return F_SETLKW64;
4613#endif
7e22e546
UH
4614 case TARGET_F_SETLEASE:
4615 return F_SETLEASE;
4616 case TARGET_F_GETLEASE:
4617 return F_GETLEASE;
fbd5de9b 4618#ifdef F_DUPFD_CLOEXEC
7e22e546
UH
4619 case TARGET_F_DUPFD_CLOEXEC:
4620 return F_DUPFD_CLOEXEC;
fbd5de9b 4621#endif
7e22e546
UH
4622 case TARGET_F_NOTIFY:
4623 return F_NOTIFY;
8d5d3004
AS
4624#ifdef F_GETOWN_EX
4625 case TARGET_F_GETOWN_EX:
4626 return F_GETOWN_EX;
4627#endif
4628#ifdef F_SETOWN_EX
4629 case TARGET_F_SETOWN_EX:
4630 return F_SETOWN_EX;
4631#endif
5f106811
APR
4632 default:
4633 return -TARGET_EINVAL;
4634 }
4635 return -TARGET_EINVAL;
4636}
4637
2ba7f730
LV
4638#define TRANSTBL_CONVERT(a) { -1, TARGET_##a, -1, a }
4639static const bitmask_transtbl flock_tbl[] = {
4640 TRANSTBL_CONVERT(F_RDLCK),
4641 TRANSTBL_CONVERT(F_WRLCK),
4642 TRANSTBL_CONVERT(F_UNLCK),
4643 TRANSTBL_CONVERT(F_EXLCK),
4644 TRANSTBL_CONVERT(F_SHLCK),
4645 { 0, 0, 0, 0 }
4646};
4647
992f48a0 4648static abi_long do_fcntl(int fd, int cmd, abi_ulong arg)
7775e9ec
FB
4649{
4650 struct flock fl;
53a5960a 4651 struct target_flock *target_fl;
43f238d7
TS
4652 struct flock64 fl64;
4653 struct target_flock64 *target_fl64;
8d5d3004
AS
4654#ifdef F_GETOWN_EX
4655 struct f_owner_ex fox;
4656 struct target_f_owner_ex *target_fox;
4657#endif
992f48a0 4658 abi_long ret;
5f106811
APR
4659 int host_cmd = target_to_host_fcntl_cmd(cmd);
4660
4661 if (host_cmd == -TARGET_EINVAL)
4662 return host_cmd;
53a5960a 4663
7775e9ec
FB
4664 switch(cmd) {
4665 case TARGET_F_GETLK:
579a97f7
FB
4666 if (!lock_user_struct(VERIFY_READ, target_fl, arg, 1))
4667 return -TARGET_EFAULT;
2ba7f730
LV
4668 fl.l_type =
4669 target_to_host_bitmask(tswap16(target_fl->l_type), flock_tbl);
5813427b 4670 fl.l_whence = tswap16(target_fl->l_whence);
cbb21eed
MB
4671 fl.l_start = tswapal(target_fl->l_start);
4672 fl.l_len = tswapal(target_fl->l_len);
7e22e546 4673 fl.l_pid = tswap32(target_fl->l_pid);
5813427b 4674 unlock_user_struct(target_fl, arg, 0);
5f106811 4675 ret = get_errno(fcntl(fd, host_cmd, &fl));
7775e9ec 4676 if (ret == 0) {
579a97f7
FB
4677 if (!lock_user_struct(VERIFY_WRITE, target_fl, arg, 0))
4678 return -TARGET_EFAULT;
2ba7f730
LV
4679 target_fl->l_type =
4680 host_to_target_bitmask(tswap16(fl.l_type), flock_tbl);
7775e9ec 4681 target_fl->l_whence = tswap16(fl.l_whence);
cbb21eed
MB
4682 target_fl->l_start = tswapal(fl.l_start);
4683 target_fl->l_len = tswapal(fl.l_len);
7e22e546 4684 target_fl->l_pid = tswap32(fl.l_pid);
53a5960a 4685 unlock_user_struct(target_fl, arg, 1);
7775e9ec
FB
4686 }
4687 break;
3b46e624 4688
7775e9ec
FB
4689 case TARGET_F_SETLK:
4690 case TARGET_F_SETLKW:
579a97f7
FB
4691 if (!lock_user_struct(VERIFY_READ, target_fl, arg, 1))
4692 return -TARGET_EFAULT;
2ba7f730
LV
4693 fl.l_type =
4694 target_to_host_bitmask(tswap16(target_fl->l_type), flock_tbl);
7775e9ec 4695 fl.l_whence = tswap16(target_fl->l_whence);
cbb21eed
MB
4696 fl.l_start = tswapal(target_fl->l_start);
4697 fl.l_len = tswapal(target_fl->l_len);
7e22e546 4698 fl.l_pid = tswap32(target_fl->l_pid);
53a5960a 4699 unlock_user_struct(target_fl, arg, 0);
5f106811 4700 ret = get_errno(fcntl(fd, host_cmd, &fl));
7775e9ec 4701 break;
3b46e624 4702
7775e9ec 4703 case TARGET_F_GETLK64:
579a97f7
FB
4704 if (!lock_user_struct(VERIFY_READ, target_fl64, arg, 1))
4705 return -TARGET_EFAULT;
2ba7f730
LV
4706 fl64.l_type =
4707 target_to_host_bitmask(tswap16(target_fl64->l_type), flock_tbl) >> 1;
5813427b 4708 fl64.l_whence = tswap16(target_fl64->l_whence);
cbb21eed
MB
4709 fl64.l_start = tswap64(target_fl64->l_start);
4710 fl64.l_len = tswap64(target_fl64->l_len);
7e22e546 4711 fl64.l_pid = tswap32(target_fl64->l_pid);
5813427b 4712 unlock_user_struct(target_fl64, arg, 0);
5f106811 4713 ret = get_errno(fcntl(fd, host_cmd, &fl64));
43f238d7 4714 if (ret == 0) {
579a97f7
FB
4715 if (!lock_user_struct(VERIFY_WRITE, target_fl64, arg, 0))
4716 return -TARGET_EFAULT;
2ba7f730
LV
4717 target_fl64->l_type =
4718 host_to_target_bitmask(tswap16(fl64.l_type), flock_tbl) >> 1;
43f238d7 4719 target_fl64->l_whence = tswap16(fl64.l_whence);
cbb21eed
MB
4720 target_fl64->l_start = tswap64(fl64.l_start);
4721 target_fl64->l_len = tswap64(fl64.l_len);
7e22e546 4722 target_fl64->l_pid = tswap32(fl64.l_pid);
43f238d7
TS
4723 unlock_user_struct(target_fl64, arg, 1);
4724 }
9ee1fa2c 4725 break;
7775e9ec
FB
4726 case TARGET_F_SETLK64:
4727 case TARGET_F_SETLKW64:
579a97f7
FB
4728 if (!lock_user_struct(VERIFY_READ, target_fl64, arg, 1))
4729 return -TARGET_EFAULT;
2ba7f730
LV
4730 fl64.l_type =
4731 target_to_host_bitmask(tswap16(target_fl64->l_type), flock_tbl) >> 1;
43f238d7 4732 fl64.l_whence = tswap16(target_fl64->l_whence);
cbb21eed
MB
4733 fl64.l_start = tswap64(target_fl64->l_start);
4734 fl64.l_len = tswap64(target_fl64->l_len);
7e22e546 4735 fl64.l_pid = tswap32(target_fl64->l_pid);
43f238d7 4736 unlock_user_struct(target_fl64, arg, 0);
5f106811 4737 ret = get_errno(fcntl(fd, host_cmd, &fl64));
7775e9ec
FB
4738 break;
4739
5f106811
APR
4740 case TARGET_F_GETFL:
4741 ret = get_errno(fcntl(fd, host_cmd, arg));
9ee1fa2c
FB
4742 if (ret >= 0) {
4743 ret = host_to_target_bitmask(ret, fcntl_flags_tbl);
4744 }
ffa65c3b
FB
4745 break;
4746
5f106811
APR
4747 case TARGET_F_SETFL:
4748 ret = get_errno(fcntl(fd, host_cmd, target_to_host_bitmask(arg, fcntl_flags_tbl)));
4749 break;
4750
8d5d3004
AS
4751#ifdef F_GETOWN_EX
4752 case TARGET_F_GETOWN_EX:
4753 ret = get_errno(fcntl(fd, host_cmd, &fox));
4754 if (ret >= 0) {
4755 if (!lock_user_struct(VERIFY_WRITE, target_fox, arg, 0))
4756 return -TARGET_EFAULT;
4757 target_fox->type = tswap32(fox.type);
4758 target_fox->pid = tswap32(fox.pid);
4759 unlock_user_struct(target_fox, arg, 1);
4760 }
4761 break;
4762#endif
4763
4764#ifdef F_SETOWN_EX
4765 case TARGET_F_SETOWN_EX:
4766 if (!lock_user_struct(VERIFY_READ, target_fox, arg, 1))
4767 return -TARGET_EFAULT;
4768 fox.type = tswap32(target_fox->type);
4769 fox.pid = tswap32(target_fox->pid);
4770 unlock_user_struct(target_fox, arg, 0);
4771 ret = get_errno(fcntl(fd, host_cmd, &fox));
4772 break;
4773#endif
4774
5f106811
APR
4775 case TARGET_F_SETOWN:
4776 case TARGET_F_GETOWN:
4777 case TARGET_F_SETSIG:
4778 case TARGET_F_GETSIG:
7e22e546
UH
4779 case TARGET_F_SETLEASE:
4780 case TARGET_F_GETLEASE:
5f106811 4781 ret = get_errno(fcntl(fd, host_cmd, arg));
ffa65c3b
FB
4782 break;
4783
7775e9ec 4784 default:
9ee1fa2c 4785 ret = get_errno(fcntl(fd, cmd, arg));
7775e9ec
FB
4786 break;
4787 }
4788 return ret;
4789}
4790
67867308 4791#ifdef USE_UID16
7775e9ec 4792
67867308
FB
4793static inline int high2lowuid(int uid)
4794{
4795 if (uid > 65535)
4796 return 65534;
4797 else
4798 return uid;
4799}
4800
4801static inline int high2lowgid(int gid)
4802{
4803 if (gid > 65535)
4804 return 65534;
4805 else
4806 return gid;
4807}
4808
4809static inline int low2highuid(int uid)
4810{
4811 if ((int16_t)uid == -1)
4812 return -1;
4813 else
4814 return uid;
4815}
4816
4817static inline int low2highgid(int gid)
4818{
4819 if ((int16_t)gid == -1)
4820 return -1;
4821 else
4822 return gid;
4823}
0c866a7e
RV
4824static inline int tswapid(int id)
4825{
4826 return tswap16(id);
4827}
76ca310a
PM
4828
4829#define put_user_id(x, gaddr) put_user_u16(x, gaddr)
4830
0c866a7e
RV
4831#else /* !USE_UID16 */
4832static inline int high2lowuid(int uid)
4833{
4834 return uid;
4835}
4836static inline int high2lowgid(int gid)
4837{
4838 return gid;
4839}
4840static inline int low2highuid(int uid)
4841{
4842 return uid;
4843}
4844static inline int low2highgid(int gid)
4845{
4846 return gid;
4847}
4848static inline int tswapid(int id)
4849{
4850 return tswap32(id);
4851}
76ca310a
PM
4852
4853#define put_user_id(x, gaddr) put_user_u32(x, gaddr)
4854
67867308 4855#endif /* USE_UID16 */
1b6b029e 4856
31e31b8a
FB
4857void syscall_init(void)
4858{
2ab83ea7
FB
4859 IOCTLEntry *ie;
4860 const argtype *arg_type;
4861 int size;
b92c47c1 4862 int i;
2ab83ea7 4863
001faf32 4864#define STRUCT(name, ...) thunk_register_struct(STRUCT_ ## name, #name, struct_ ## name ## _def);
5fafdf24 4865#define STRUCT_SPECIAL(name) thunk_register_struct_direct(STRUCT_ ## name, #name, &struct_ ## name ## _def);
31e31b8a
FB
4866#include "syscall_types.h"
4867#undef STRUCT
4868#undef STRUCT_SPECIAL
2ab83ea7 4869
dd6e957a
PM
4870 /* Build target_to_host_errno_table[] table from
4871 * host_to_target_errno_table[]. */
4872 for (i = 0; i < ERRNO_TABLE_SIZE; i++) {
4873 target_to_host_errno_table[host_to_target_errno_table[i]] = i;
4874 }
4875
2ab83ea7
FB
4876 /* we patch the ioctl size if necessary. We rely on the fact that
4877 no ioctl has all the bits at '1' in the size field */
4878 ie = ioctl_entries;
4879 while (ie->target_cmd != 0) {
4880 if (((ie->target_cmd >> TARGET_IOC_SIZESHIFT) & TARGET_IOC_SIZEMASK) ==
4881 TARGET_IOC_SIZEMASK) {
4882 arg_type = ie->arg_type;
4883 if (arg_type[0] != TYPE_PTR) {
5fafdf24 4884 fprintf(stderr, "cannot patch size for ioctl 0x%x\n",
2ab83ea7
FB
4885 ie->target_cmd);
4886 exit(1);
4887 }
4888 arg_type++;
4889 size = thunk_type_size(arg_type, 0);
5fafdf24 4890 ie->target_cmd = (ie->target_cmd &
2ab83ea7
FB
4891 ~(TARGET_IOC_SIZEMASK << TARGET_IOC_SIZESHIFT)) |
4892 (size << TARGET_IOC_SIZESHIFT);
4893 }
b92c47c1 4894
2ab83ea7 4895 /* automatic consistency check if same arch */
872ea0c0
AZ
4896#if (defined(__i386__) && defined(TARGET_I386) && defined(TARGET_ABI32)) || \
4897 (defined(__x86_64__) && defined(TARGET_X86_64))
4898 if (unlikely(ie->target_cmd != ie->host_cmd)) {
4899 fprintf(stderr, "ERROR: ioctl(%s): target=0x%x host=0x%x\n",
4900 ie->name, ie->target_cmd, ie->host_cmd);
2ab83ea7
FB
4901 }
4902#endif
4903 ie++;
4904 }
31e31b8a 4905}
c573ff67 4906
992f48a0 4907#if TARGET_ABI_BITS == 32
ce4defa0
PB
4908static inline uint64_t target_offset64(uint32_t word0, uint32_t word1)
4909{
af325d36 4910#ifdef TARGET_WORDS_BIGENDIAN
ce4defa0
PB
4911 return ((uint64_t)word0 << 32) | word1;
4912#else
4913 return ((uint64_t)word1 << 32) | word0;
4914#endif
4915}
992f48a0 4916#else /* TARGET_ABI_BITS == 32 */
32407103
JM
4917static inline uint64_t target_offset64(uint64_t word0, uint64_t word1)
4918{
4919 return word0;
4920}
992f48a0 4921#endif /* TARGET_ABI_BITS != 32 */
ce4defa0
PB
4922
4923#ifdef TARGET_NR_truncate64
992f48a0
BS
4924static inline abi_long target_truncate64(void *cpu_env, const char *arg1,
4925 abi_long arg2,
4926 abi_long arg3,
4927 abi_long arg4)
ce4defa0 4928{
48e515d4 4929 if (regpairs_aligned(cpu_env)) {
ce4defa0
PB
4930 arg2 = arg3;
4931 arg3 = arg4;
48e515d4 4932 }
ce4defa0
PB
4933 return get_errno(truncate64(arg1, target_offset64(arg2, arg3)));
4934}
4935#endif
4936
4937#ifdef TARGET_NR_ftruncate64
992f48a0
BS
4938static inline abi_long target_ftruncate64(void *cpu_env, abi_long arg1,
4939 abi_long arg2,
4940 abi_long arg3,
4941 abi_long arg4)
ce4defa0 4942{
48e515d4 4943 if (regpairs_aligned(cpu_env)) {
ce4defa0
PB
4944 arg2 = arg3;
4945 arg3 = arg4;
48e515d4 4946 }
ce4defa0
PB
4947 return get_errno(ftruncate64(arg1, target_offset64(arg2, arg3)));
4948}
4949#endif
4950
579a97f7
FB
4951static inline abi_long target_to_host_timespec(struct timespec *host_ts,
4952 abi_ulong target_addr)
53a5960a
PB
4953{
4954 struct target_timespec *target_ts;
4955
579a97f7
FB
4956 if (!lock_user_struct(VERIFY_READ, target_ts, target_addr, 1))
4957 return -TARGET_EFAULT;
cbb21eed
MB
4958 host_ts->tv_sec = tswapal(target_ts->tv_sec);
4959 host_ts->tv_nsec = tswapal(target_ts->tv_nsec);
53a5960a 4960 unlock_user_struct(target_ts, target_addr, 0);
b255bfa8 4961 return 0;
53a5960a
PB
4962}
4963
579a97f7
FB
4964static inline abi_long host_to_target_timespec(abi_ulong target_addr,
4965 struct timespec *host_ts)
53a5960a
PB
4966{
4967 struct target_timespec *target_ts;
4968
579a97f7
FB
4969 if (!lock_user_struct(VERIFY_WRITE, target_ts, target_addr, 0))
4970 return -TARGET_EFAULT;
cbb21eed
MB
4971 target_ts->tv_sec = tswapal(host_ts->tv_sec);
4972 target_ts->tv_nsec = tswapal(host_ts->tv_nsec);
53a5960a 4973 unlock_user_struct(target_ts, target_addr, 1);
b255bfa8 4974 return 0;
53a5960a
PB
4975}
4976
f4f1e10a
ECL
4977static inline abi_long target_to_host_itimerspec(struct itimerspec *host_itspec,
4978 abi_ulong target_addr)
4979{
4980 struct target_itimerspec *target_itspec;
4981
4982 if (!lock_user_struct(VERIFY_READ, target_itspec, target_addr, 1)) {
4983 return -TARGET_EFAULT;
4984 }
4985
4986 host_itspec->it_interval.tv_sec =
4987 tswapal(target_itspec->it_interval.tv_sec);
4988 host_itspec->it_interval.tv_nsec =
4989 tswapal(target_itspec->it_interval.tv_nsec);
4990 host_itspec->it_value.tv_sec = tswapal(target_itspec->it_value.tv_sec);
4991 host_itspec->it_value.tv_nsec = tswapal(target_itspec->it_value.tv_nsec);
4992
4993 unlock_user_struct(target_itspec, target_addr, 1);
4994 return 0;
4995}
4996
4997static inline abi_long host_to_target_itimerspec(abi_ulong target_addr,
4998 struct itimerspec *host_its)
4999{
5000 struct target_itimerspec *target_itspec;
5001
5002 if (!lock_user_struct(VERIFY_WRITE, target_itspec, target_addr, 0)) {
5003 return -TARGET_EFAULT;
5004 }
5005
5006 target_itspec->it_interval.tv_sec = tswapal(host_its->it_interval.tv_sec);
5007 target_itspec->it_interval.tv_nsec = tswapal(host_its->it_interval.tv_nsec);
5008
5009 target_itspec->it_value.tv_sec = tswapal(host_its->it_value.tv_sec);
5010 target_itspec->it_value.tv_nsec = tswapal(host_its->it_value.tv_nsec);
5011
5012 unlock_user_struct(target_itspec, target_addr, 0);
5013 return 0;
5014}
5015
c065976f
PM
5016static inline abi_long target_to_host_sigevent(struct sigevent *host_sevp,
5017 abi_ulong target_addr)
5018{
5019 struct target_sigevent *target_sevp;
5020
5021 if (!lock_user_struct(VERIFY_READ, target_sevp, target_addr, 1)) {
5022 return -TARGET_EFAULT;
5023 }
5024
5025 /* This union is awkward on 64 bit systems because it has a 32 bit
5026 * integer and a pointer in it; we follow the conversion approach
5027 * used for handling sigval types in signal.c so the guest should get
5028 * the correct value back even if we did a 64 bit byteswap and it's
5029 * using the 32 bit integer.
5030 */
5031 host_sevp->sigev_value.sival_ptr =
5032 (void *)(uintptr_t)tswapal(target_sevp->sigev_value.sival_ptr);
5033 host_sevp->sigev_signo =
5034 target_to_host_signal(tswap32(target_sevp->sigev_signo));
5035 host_sevp->sigev_notify = tswap32(target_sevp->sigev_notify);
5036 host_sevp->_sigev_un._tid = tswap32(target_sevp->_sigev_un._tid);
5037
5038 unlock_user_struct(target_sevp, target_addr, 1);
5039 return 0;
5040}
5041
6f6a4032
TM
5042#if defined(TARGET_NR_mlockall)
5043static inline int target_to_host_mlockall_arg(int arg)
5044{
5045 int result = 0;
5046
5047 if (arg & TARGET_MLOCKALL_MCL_CURRENT) {
5048 result |= MCL_CURRENT;
5049 }
5050 if (arg & TARGET_MLOCKALL_MCL_FUTURE) {
5051 result |= MCL_FUTURE;
5052 }
5053 return result;
5054}
5055#endif
5056
9d33b76b 5057#if defined(TARGET_NR_stat64) || defined(TARGET_NR_newfstatat)
6a24a778
AZ
5058static inline abi_long host_to_target_stat64(void *cpu_env,
5059 abi_ulong target_addr,
5060 struct stat *host_st)
5061{
09701199 5062#if defined(TARGET_ARM) && defined(TARGET_ABI32)
6a24a778
AZ
5063 if (((CPUARMState *)cpu_env)->eabi) {
5064 struct target_eabi_stat64 *target_st;
5065
5066 if (!lock_user_struct(VERIFY_WRITE, target_st, target_addr, 0))
5067 return -TARGET_EFAULT;
5068 memset(target_st, 0, sizeof(struct target_eabi_stat64));
5069 __put_user(host_st->st_dev, &target_st->st_dev);
5070 __put_user(host_st->st_ino, &target_st->st_ino);
5071#ifdef TARGET_STAT64_HAS_BROKEN_ST_INO
5072 __put_user(host_st->st_ino, &target_st->__st_ino);
5073#endif
5074 __put_user(host_st->st_mode, &target_st->st_mode);
5075 __put_user(host_st->st_nlink, &target_st->st_nlink);
5076 __put_user(host_st->st_uid, &target_st->st_uid);
5077 __put_user(host_st->st_gid, &target_st->st_gid);
5078 __put_user(host_st->st_rdev, &target_st->st_rdev);
5079 __put_user(host_st->st_size, &target_st->st_size);
5080 __put_user(host_st->st_blksize, &target_st->st_blksize);
5081 __put_user(host_st->st_blocks, &target_st->st_blocks);
5082 __put_user(host_st->st_atime, &target_st->target_st_atime);
5083 __put_user(host_st->st_mtime, &target_st->target_st_mtime);
5084 __put_user(host_st->st_ctime, &target_st->target_st_ctime);
5085 unlock_user_struct(target_st, target_addr, 1);
5086 } else
5087#endif
5088 {
20d155bc 5089#if defined(TARGET_HAS_STRUCT_STAT64)
6a24a778 5090 struct target_stat64 *target_st;
20d155bc
SW
5091#else
5092 struct target_stat *target_st;
9d33b76b 5093#endif
6a24a778
AZ
5094
5095 if (!lock_user_struct(VERIFY_WRITE, target_st, target_addr, 0))
5096 return -TARGET_EFAULT;
9d33b76b 5097 memset(target_st, 0, sizeof(*target_st));
6a24a778
AZ
5098 __put_user(host_st->st_dev, &target_st->st_dev);
5099 __put_user(host_st->st_ino, &target_st->st_ino);
5100#ifdef TARGET_STAT64_HAS_BROKEN_ST_INO
5101 __put_user(host_st->st_ino, &target_st->__st_ino);
5102#endif
5103 __put_user(host_st->st_mode, &target_st->st_mode);
5104 __put_user(host_st->st_nlink, &target_st->st_nlink);
5105 __put_user(host_st->st_uid, &target_st->st_uid);
5106 __put_user(host_st->st_gid, &target_st->st_gid);
5107 __put_user(host_st->st_rdev, &target_st->st_rdev);
5108 /* XXX: better use of kernel struct */
5109 __put_user(host_st->st_size, &target_st->st_size);
5110 __put_user(host_st->st_blksize, &target_st->st_blksize);
5111 __put_user(host_st->st_blocks, &target_st->st_blocks);
5112 __put_user(host_st->st_atime, &target_st->target_st_atime);
5113 __put_user(host_st->st_mtime, &target_st->target_st_mtime);
5114 __put_user(host_st->st_ctime, &target_st->target_st_ctime);
5115 unlock_user_struct(target_st, target_addr, 1);
5116 }
5117
5118 return 0;
5119}
5120#endif
5121
bd0c5661
PB
5122/* ??? Using host futex calls even when target atomic operations
5123 are not really atomic probably breaks things. However implementing
5124 futexes locally would make futexes shared between multiple processes
5125 tricky. However they're probably useless because guest atomic
5126 operations won't work either. */
8fcd3692
BS
5127static int do_futex(target_ulong uaddr, int op, int val, target_ulong timeout,
5128 target_ulong uaddr2, int val3)
bd0c5661
PB
5129{
5130 struct timespec ts, *pts;
a16aae0c 5131 int base_op;
bd0c5661
PB
5132
5133 /* ??? We assume FUTEX_* constants are the same on both host
5134 and target. */
a29ccd63 5135#ifdef FUTEX_CMD_MASK
a16aae0c 5136 base_op = op & FUTEX_CMD_MASK;
a29ccd63 5137#else
a16aae0c 5138 base_op = op;
a29ccd63 5139#endif
a16aae0c 5140 switch (base_op) {
bd0c5661 5141 case FUTEX_WAIT:
cce246e0 5142 case FUTEX_WAIT_BITSET:
bd0c5661
PB
5143 if (timeout) {
5144 pts = &ts;
5145 target_to_host_timespec(pts, timeout);
5146 } else {
5147 pts = NULL;
5148 }
a29ccd63 5149 return get_errno(sys_futex(g2h(uaddr), op, tswap32(val),
cce246e0 5150 pts, NULL, val3));
bd0c5661 5151 case FUTEX_WAKE:
a29ccd63 5152 return get_errno(sys_futex(g2h(uaddr), op, val, NULL, NULL, 0));
bd0c5661 5153 case FUTEX_FD:
a29ccd63 5154 return get_errno(sys_futex(g2h(uaddr), op, val, NULL, NULL, 0));
bd0c5661 5155 case FUTEX_REQUEUE:
bd0c5661 5156 case FUTEX_CMP_REQUEUE:
a16aae0c
NF
5157 case FUTEX_WAKE_OP:
5158 /* For FUTEX_REQUEUE, FUTEX_CMP_REQUEUE, and FUTEX_WAKE_OP, the
5159 TIMEOUT parameter is interpreted as a uint32_t by the kernel.
5160 But the prototype takes a `struct timespec *'; insert casts
5161 to satisfy the compiler. We do not need to tswap TIMEOUT
5162 since it's not compared to guest memory. */
5163 pts = (struct timespec *)(uintptr_t) timeout;
5164 return get_errno(sys_futex(g2h(uaddr), op, val, pts,
5165 g2h(uaddr2),
5166 (base_op == FUTEX_CMP_REQUEUE
5167 ? tswap32(val3)
5168 : val3)));
bd0c5661
PB
5169 default:
5170 return -TARGET_ENOSYS;
5171 }
5172}
bd0c5661 5173
1d9d8b55
PB
5174/* Map host to target signal numbers for the wait family of syscalls.
5175 Assume all other status bits are the same. */
a05c6409 5176int host_to_target_waitstatus(int status)
1d9d8b55
PB
5177{
5178 if (WIFSIGNALED(status)) {
5179 return host_to_target_signal(WTERMSIG(status)) | (status & ~0x7f);
5180 }
5181 if (WIFSTOPPED(status)) {
5182 return (host_to_target_signal(WSTOPSIG(status)) << 8)
5183 | (status & 0xff);
5184 }
5185 return status;
5186}
5187
76b94245
WVS
5188static int open_self_cmdline(void *cpu_env, int fd)
5189{
5190 int fd_orig = -1;
5191 bool word_skipped = false;
5192
5193 fd_orig = open("/proc/self/cmdline", O_RDONLY);
5194 if (fd_orig < 0) {
5195 return fd_orig;
5196 }
5197
5198 while (true) {
5199 ssize_t nb_read;
5200 char buf[128];
5201 char *cp_buf = buf;
5202
5203 nb_read = read(fd_orig, buf, sizeof(buf));
5204 if (nb_read < 0) {
5205 fd_orig = close(fd_orig);
5206 return -1;
5207 } else if (nb_read == 0) {
5208 break;
5209 }
5210
5211 if (!word_skipped) {
5212 /* Skip the first string, which is the path to qemu-*-static
5213 instead of the actual command. */
5214 cp_buf = memchr(buf, 0, sizeof(buf));
5215 if (cp_buf) {
5216 /* Null byte found, skip one string */
5217 cp_buf++;
5218 nb_read -= cp_buf - buf;
5219 word_skipped = true;
5220 }
5221 }
5222
5223 if (word_skipped) {
5224 if (write(fd, cp_buf, nb_read) != nb_read) {
680dfde9 5225 close(fd_orig);
76b94245
WVS
5226 return -1;
5227 }
5228 }
5229 }
5230
5231 return close(fd_orig);
5232}
5233
36c08d49
AG
5234static int open_self_maps(void *cpu_env, int fd)
5235{
0429a971
AF
5236 CPUState *cpu = ENV_GET_CPU((CPUArchState *)cpu_env);
5237 TaskState *ts = cpu->opaque;
1a49ef2a
AG
5238 FILE *fp;
5239 char *line = NULL;
5240 size_t len = 0;
5241 ssize_t read;
5242
5243 fp = fopen("/proc/self/maps", "r");
5244 if (fp == NULL) {
5245 return -EACCES;
5246 }
36c08d49 5247
1a49ef2a
AG
5248 while ((read = getline(&line, &len, fp)) != -1) {
5249 int fields, dev_maj, dev_min, inode;
5250 uint64_t min, max, offset;
5251 char flag_r, flag_w, flag_x, flag_p;
5252 char path[512] = "";
5253 fields = sscanf(line, "%"PRIx64"-%"PRIx64" %c%c%c%c %"PRIx64" %x:%x %d"
5254 " %512s", &min, &max, &flag_r, &flag_w, &flag_x,
5255 &flag_p, &offset, &dev_maj, &dev_min, &inode, path);
5256
5257 if ((fields < 10) || (fields > 11)) {
5258 continue;
5259 }
d67f4aaa
MI
5260 if (h2g_valid(min)) {
5261 int flags = page_get_flags(h2g(min));
5262 max = h2g_valid(max - 1) ? max : (uintptr_t)g2h(GUEST_ADDR_MAX);
5263 if (page_check_range(h2g(min), max - min, flags) == -1) {
5264 continue;
5265 }
5266 if (h2g(min) == ts->info->stack_limit) {
5267 pstrcpy(path, sizeof(path), " [stack]");
5268 }
1a49ef2a 5269 dprintf(fd, TARGET_ABI_FMT_lx "-" TARGET_ABI_FMT_lx
e24fed4e 5270 " %c%c%c%c %08" PRIx64 " %02x:%02x %d %s%s\n",
d67f4aaa 5271 h2g(min), h2g(max - 1) + 1, flag_r, flag_w,
1a49ef2a 5272 flag_x, flag_p, offset, dev_maj, dev_min, inode,
e24fed4e 5273 path[0] ? " " : "", path);
1a49ef2a
AG
5274 }
5275 }
5276
5277 free(line);
5278 fclose(fp);
5279
36c08d49
AG
5280 return 0;
5281}
5282
480b8e7d
AG
5283static int open_self_stat(void *cpu_env, int fd)
5284{
0429a971
AF
5285 CPUState *cpu = ENV_GET_CPU((CPUArchState *)cpu_env);
5286 TaskState *ts = cpu->opaque;
480b8e7d
AG
5287 abi_ulong start_stack = ts->info->start_stack;
5288 int i;
5289
5290 for (i = 0; i < 44; i++) {
5291 char buf[128];
5292 int len;
5293 uint64_t val = 0;
5294
e0e65bee
FE
5295 if (i == 0) {
5296 /* pid */
5297 val = getpid();
5298 snprintf(buf, sizeof(buf), "%"PRId64 " ", val);
5299 } else if (i == 1) {
5300 /* app name */
5301 snprintf(buf, sizeof(buf), "(%s) ", ts->bprm->argv[0]);
5302 } else if (i == 27) {
5303 /* stack bottom */
5304 val = start_stack;
5305 snprintf(buf, sizeof(buf), "%"PRId64 " ", val);
5306 } else {
5307 /* for the rest, there is MasterCard */
5308 snprintf(buf, sizeof(buf), "0%c", i == 43 ? '\n' : ' ');
480b8e7d 5309 }
e0e65bee 5310
480b8e7d
AG
5311 len = strlen(buf);
5312 if (write(fd, buf, len) != len) {
5313 return -1;
5314 }
5315 }
5316
5317 return 0;
5318}
5319
257450ee
AG
5320static int open_self_auxv(void *cpu_env, int fd)
5321{
0429a971
AF
5322 CPUState *cpu = ENV_GET_CPU((CPUArchState *)cpu_env);
5323 TaskState *ts = cpu->opaque;
257450ee
AG
5324 abi_ulong auxv = ts->info->saved_auxv;
5325 abi_ulong len = ts->info->auxv_len;
5326 char *ptr;
5327
5328 /*
5329 * Auxiliary vector is stored in target process stack.
5330 * read in whole auxv vector and copy it to file
5331 */
5332 ptr = lock_user(VERIFY_READ, auxv, len, 0);
5333 if (ptr != NULL) {
5334 while (len > 0) {
5335 ssize_t r;
5336 r = write(fd, ptr, len);
5337 if (r <= 0) {
5338 break;
5339 }
5340 len -= r;
5341 ptr += r;
5342 }
5343 lseek(fd, 0, SEEK_SET);
5344 unlock_user(ptr, auxv, len);
5345 }
5346
5347 return 0;
5348}
5349
463d8e73
AS
5350static int is_proc_myself(const char *filename, const char *entry)
5351{
5352 if (!strncmp(filename, "/proc/", strlen("/proc/"))) {
5353 filename += strlen("/proc/");
5354 if (!strncmp(filename, "self/", strlen("self/"))) {
5355 filename += strlen("self/");
5356 } else if (*filename >= '1' && *filename <= '9') {
5357 char myself[80];
5358 snprintf(myself, sizeof(myself), "%d/", getpid());
5359 if (!strncmp(filename, myself, strlen(myself))) {
5360 filename += strlen(myself);
5361 } else {
5362 return 0;
5363 }
5364 } else {
5365 return 0;
5366 }
5367 if (!strcmp(filename, entry)) {
5368 return 1;
5369 }
5370 }
5371 return 0;
5372}
5373
de6b9933
LV
5374#if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN)
5375static int is_proc(const char *filename, const char *entry)
5376{
5377 return strcmp(filename, entry) == 0;
5378}
5379
5380static int open_net_route(void *cpu_env, int fd)
5381{
5382 FILE *fp;
5383 char *line = NULL;
5384 size_t len = 0;
5385 ssize_t read;
5386
5387 fp = fopen("/proc/net/route", "r");
5388 if (fp == NULL) {
5389 return -EACCES;
5390 }
5391
5392 /* read header */
5393
5394 read = getline(&line, &len, fp);
5395 dprintf(fd, "%s", line);
5396
5397 /* read routes */
5398
5399 while ((read = getline(&line, &len, fp)) != -1) {
5400 char iface[16];
5401 uint32_t dest, gw, mask;
5402 unsigned int flags, refcnt, use, metric, mtu, window, irtt;
5403 sscanf(line, "%s\t%08x\t%08x\t%04x\t%d\t%d\t%d\t%08x\t%d\t%u\t%u\n",
5404 iface, &dest, &gw, &flags, &refcnt, &use, &metric,
5405 &mask, &mtu, &window, &irtt);
5406 dprintf(fd, "%s\t%08x\t%08x\t%04x\t%d\t%d\t%d\t%08x\t%d\t%u\t%u\n",
5407 iface, tswap32(dest), tswap32(gw), flags, refcnt, use,
5408 metric, tswap32(mask), mtu, window, irtt);
5409 }
5410
5411 free(line);
5412 fclose(fp);
5413
5414 return 0;
5415}
5416#endif
5417
0b2effd7 5418static int do_openat(void *cpu_env, int dirfd, const char *pathname, int flags, mode_t mode)
3be14d05
AG
5419{
5420 struct fake_open {
5421 const char *filename;
5422 int (*fill)(void *cpu_env, int fd);
de6b9933 5423 int (*cmp)(const char *s1, const char *s2);
3be14d05
AG
5424 };
5425 const struct fake_open *fake_open;
5426 static const struct fake_open fakes[] = {
de6b9933
LV
5427 { "maps", open_self_maps, is_proc_myself },
5428 { "stat", open_self_stat, is_proc_myself },
5429 { "auxv", open_self_auxv, is_proc_myself },
76b94245 5430 { "cmdline", open_self_cmdline, is_proc_myself },
de6b9933
LV
5431#if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN)
5432 { "/proc/net/route", open_net_route, is_proc },
5433#endif
5434 { NULL, NULL, NULL }
3be14d05
AG
5435 };
5436
aa07f5ec
MO
5437 if (is_proc_myself(pathname, "exe")) {
5438 int execfd = qemu_getauxval(AT_EXECFD);
0b2effd7 5439 return execfd ? execfd : get_errno(sys_openat(dirfd, exec_path, flags, mode));
aa07f5ec
MO
5440 }
5441
3be14d05 5442 for (fake_open = fakes; fake_open->filename; fake_open++) {
de6b9933 5443 if (fake_open->cmp(pathname, fake_open->filename)) {
3be14d05
AG
5444 break;
5445 }
5446 }
5447
5448 if (fake_open->filename) {
5449 const char *tmpdir;
5450 char filename[PATH_MAX];
5451 int fd, r;
5452
5453 /* create temporary file to map stat to */
5454 tmpdir = getenv("TMPDIR");
5455 if (!tmpdir)
5456 tmpdir = "/tmp";
5457 snprintf(filename, sizeof(filename), "%s/qemu-open.XXXXXX", tmpdir);
5458 fd = mkstemp(filename);
5459 if (fd < 0) {
5460 return fd;
5461 }
5462 unlink(filename);
5463
5464 if ((r = fake_open->fill(cpu_env, fd))) {
5465 close(fd);
5466 return r;
5467 }
5468 lseek(fd, 0, SEEK_SET);
5469
5470 return fd;
5471 }
5472
0b2effd7 5473 return get_errno(sys_openat(dirfd, path(pathname), flags, mode));
3be14d05
AG
5474}
5475
aecc8861
AG
5476#define TIMER_MAGIC 0x0caf0000
5477#define TIMER_MAGIC_MASK 0xffff0000
5478
5479/* Convert QEMU provided timer ID back to internal 16bit index format */
5480static target_timer_t get_timer_id(abi_long arg)
5481{
5482 target_timer_t timerid = arg;
5483
5484 if ((timerid & TIMER_MAGIC_MASK) != TIMER_MAGIC) {
5485 return -TARGET_EINVAL;
5486 }
5487
5488 timerid &= 0xffff;
5489
5490 if (timerid >= ARRAY_SIZE(g_posix_timers)) {
5491 return -TARGET_EINVAL;
5492 }
5493
5494 return timerid;
5495}
5496
0da46a6e
TS
5497/* do_syscall() should always have a single exit point at the end so
5498 that actions, such as logging of syscall results, can be performed.
5499 All errnos that do_syscall() returns must be -TARGET_<errcode>. */
992f48a0
BS
5500abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
5501 abi_long arg2, abi_long arg3, abi_long arg4,
5945cfcb
PM
5502 abi_long arg5, abi_long arg6, abi_long arg7,
5503 abi_long arg8)
31e31b8a 5504{
182735ef 5505 CPUState *cpu = ENV_GET_CPU(cpu_env);
992f48a0 5506 abi_long ret;
31e31b8a 5507 struct stat st;
56c8f68f 5508 struct statfs stfs;
53a5960a 5509 void *p;
3b46e624 5510
72f03900 5511#ifdef DEBUG
c573ff67 5512 gemu_log("syscall %d", num);
72f03900 5513#endif
b92c47c1
TS
5514 if(do_strace)
5515 print_syscall(num, arg1, arg2, arg3, arg4, arg5, arg6);
5516
31e31b8a
FB
5517 switch(num) {
5518 case TARGET_NR_exit:
9b056fcc
AF
5519 /* In old applications this may be used to implement _exit(2).
5520 However in threaded applictions it is used for thread termination,
5521 and _exit_group is used for application termination.
5522 Do thread termination if we have more then one thread. */
5523 /* FIXME: This probably breaks if a signal arrives. We should probably
5524 be disabling signals. */
bdc44640 5525 if (CPU_NEXT(first_cpu)) {
9b056fcc 5526 TaskState *ts;
9b056fcc
AF
5527
5528 cpu_list_lock();
9b056fcc 5529 /* Remove the CPU from the list. */
bdc44640 5530 QTAILQ_REMOVE(&cpus, cpu, node);
9b056fcc 5531 cpu_list_unlock();
0429a971 5532 ts = cpu->opaque;
9b056fcc
AF
5533 if (ts->child_tidptr) {
5534 put_user_u32(0, ts->child_tidptr);
5535 sys_futex(g2h(ts->child_tidptr), FUTEX_WAKE, INT_MAX,
5536 NULL, NULL, 0);
5537 }
a2247f8e 5538 thread_cpu = NULL;
0429a971 5539 object_unref(OBJECT(cpu));
9b056fcc
AF
5540 g_free(ts);
5541 pthread_exit(NULL);
5542 }
9788c9ca 5543#ifdef TARGET_GPROF
7d13299d
FB
5544 _mcleanup();
5545#endif
e9009676 5546 gdb_exit(cpu_env, arg1);
c2764719 5547 _exit(arg1);
31e31b8a
FB
5548 ret = 0; /* avoid warning */
5549 break;
5550 case TARGET_NR_read:
38d840e6
AJ
5551 if (arg3 == 0)
5552 ret = 0;
5553 else {
5554 if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
5555 goto efault;
5556 ret = get_errno(read(arg1, p, arg3));
5557 unlock_user(p, arg2, ret);
5558 }
31e31b8a
FB
5559 break;
5560 case TARGET_NR_write:
579a97f7
FB
5561 if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
5562 goto efault;
53a5960a
PB
5563 ret = get_errno(write(arg1, p, arg3));
5564 unlock_user(p, arg2, 0);
31e31b8a
FB
5565 break;
5566 case TARGET_NR_open:
2f619698
FB
5567 if (!(p = lock_user_string(arg1)))
5568 goto efault;
0b2effd7
RV
5569 ret = get_errno(do_openat(cpu_env, AT_FDCWD, p,
5570 target_to_host_bitmask(arg2, fcntl_flags_tbl),
5571 arg3));
53a5960a 5572 unlock_user(p, arg1, 0);
31e31b8a 5573 break;
82424832 5574 case TARGET_NR_openat:
579a97f7
FB
5575 if (!(p = lock_user_string(arg2)))
5576 goto efault;
0b2effd7
RV
5577 ret = get_errno(do_openat(cpu_env, arg1, p,
5578 target_to_host_bitmask(arg3, fcntl_flags_tbl),
5579 arg4));
579a97f7 5580 unlock_user(p, arg2, 0);
82424832 5581 break;
31e31b8a
FB
5582 case TARGET_NR_close:
5583 ret = get_errno(close(arg1));
5584 break;
5585 case TARGET_NR_brk:
53a5960a 5586 ret = do_brk(arg1);
31e31b8a
FB
5587 break;
5588 case TARGET_NR_fork:
d865bab5 5589 ret = get_errno(do_fork(cpu_env, SIGCHLD, 0, 0, 0, 0));
31e31b8a 5590 break;
e5febef5 5591#ifdef TARGET_NR_waitpid
31e31b8a
FB
5592 case TARGET_NR_waitpid:
5593 {
53a5960a
PB
5594 int status;
5595 ret = get_errno(waitpid(arg1, &status, arg3));
5379557b 5596 if (!is_error(ret) && arg2 && ret
1d9d8b55 5597 && put_user_s32(host_to_target_waitstatus(status), arg2))
2f619698 5598 goto efault;
31e31b8a
FB
5599 }
5600 break;
e5febef5 5601#endif
f0cbb613
PB
5602#ifdef TARGET_NR_waitid
5603 case TARGET_NR_waitid:
5604 {
5605 siginfo_t info;
5606 info.si_pid = 0;
5607 ret = get_errno(waitid(arg1, arg2, &info, arg4));
5608 if (!is_error(ret) && arg3 && info.si_pid != 0) {
c227f099 5609 if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_siginfo_t), 0)))
f0cbb613
PB
5610 goto efault;
5611 host_to_target_siginfo(p, &info);
c227f099 5612 unlock_user(p, arg3, sizeof(target_siginfo_t));
f0cbb613
PB
5613 }
5614 }
5615 break;
5616#endif
7a3148a9 5617#ifdef TARGET_NR_creat /* not on alpha */
31e31b8a 5618 case TARGET_NR_creat:
579a97f7
FB
5619 if (!(p = lock_user_string(arg1)))
5620 goto efault;
53a5960a
PB
5621 ret = get_errno(creat(p, arg2));
5622 unlock_user(p, arg1, 0);
31e31b8a 5623 break;
7a3148a9 5624#endif
31e31b8a 5625 case TARGET_NR_link:
53a5960a
PB
5626 {
5627 void * p2;
5628 p = lock_user_string(arg1);
5629 p2 = lock_user_string(arg2);
579a97f7
FB
5630 if (!p || !p2)
5631 ret = -TARGET_EFAULT;
5632 else
5633 ret = get_errno(link(p, p2));
53a5960a
PB
5634 unlock_user(p2, arg2, 0);
5635 unlock_user(p, arg1, 0);
5636 }
31e31b8a 5637 break;
c0d472b1 5638#if defined(TARGET_NR_linkat)
64f0ce4c 5639 case TARGET_NR_linkat:
64f0ce4c
TS
5640 {
5641 void * p2 = NULL;
579a97f7
FB
5642 if (!arg2 || !arg4)
5643 goto efault;
64f0ce4c
TS
5644 p = lock_user_string(arg2);
5645 p2 = lock_user_string(arg4);
579a97f7 5646 if (!p || !p2)
0da46a6e 5647 ret = -TARGET_EFAULT;
64f0ce4c 5648 else
c0d472b1 5649 ret = get_errno(linkat(arg1, p, arg3, p2, arg5));
579a97f7
FB
5650 unlock_user(p, arg2, 0);
5651 unlock_user(p2, arg4, 0);
64f0ce4c
TS
5652 }
5653 break;
5654#endif
31e31b8a 5655 case TARGET_NR_unlink:
579a97f7
FB
5656 if (!(p = lock_user_string(arg1)))
5657 goto efault;
53a5960a
PB
5658 ret = get_errno(unlink(p));
5659 unlock_user(p, arg1, 0);
31e31b8a 5660 break;
c0d472b1 5661#if defined(TARGET_NR_unlinkat)
8170f56b 5662 case TARGET_NR_unlinkat:
579a97f7
FB
5663 if (!(p = lock_user_string(arg2)))
5664 goto efault;
c0d472b1 5665 ret = get_errno(unlinkat(arg1, p, arg3));
579a97f7 5666 unlock_user(p, arg2, 0);
ed494d87 5667 break;
b7d35e65 5668#endif
31e31b8a 5669 case TARGET_NR_execve:
7854b056
FB
5670 {
5671 char **argp, **envp;
f7341ff4 5672 int argc, envc;
992f48a0
BS
5673 abi_ulong gp;
5674 abi_ulong guest_argp;
5675 abi_ulong guest_envp;
5676 abi_ulong addr;
7854b056 5677 char **q;
a6f79cc9 5678 int total_size = 0;
7854b056 5679
f7341ff4 5680 argc = 0;
53a5960a 5681 guest_argp = arg2;
da94d263 5682 for (gp = guest_argp; gp; gp += sizeof(abi_ulong)) {
03aa1976 5683 if (get_user_ual(addr, gp))
2f619698 5684 goto efault;
03aa1976 5685 if (!addr)
2f619698 5686 break;
7854b056 5687 argc++;
2f619698 5688 }
f7341ff4 5689 envc = 0;
53a5960a 5690 guest_envp = arg3;
da94d263 5691 for (gp = guest_envp; gp; gp += sizeof(abi_ulong)) {
03aa1976 5692 if (get_user_ual(addr, gp))
2f619698 5693 goto efault;
03aa1976 5694 if (!addr)
2f619698 5695 break;
7854b056 5696 envc++;
2f619698 5697 }
7854b056 5698
f7341ff4
FB
5699 argp = alloca((argc + 1) * sizeof(void *));
5700 envp = alloca((envc + 1) * sizeof(void *));
7854b056 5701
da94d263 5702 for (gp = guest_argp, q = argp; gp;
992f48a0 5703 gp += sizeof(abi_ulong), q++) {
2f619698
FB
5704 if (get_user_ual(addr, gp))
5705 goto execve_efault;
53a5960a
PB
5706 if (!addr)
5707 break;
2f619698
FB
5708 if (!(*q = lock_user_string(addr)))
5709 goto execve_efault;
a6f79cc9 5710 total_size += strlen(*q) + 1;
53a5960a 5711 }
f7341ff4
FB
5712 *q = NULL;
5713
da94d263 5714 for (gp = guest_envp, q = envp; gp;
992f48a0 5715 gp += sizeof(abi_ulong), q++) {
2f619698
FB
5716 if (get_user_ual(addr, gp))
5717 goto execve_efault;
53a5960a
PB
5718 if (!addr)
5719 break;
2f619698
FB
5720 if (!(*q = lock_user_string(addr)))
5721 goto execve_efault;
a6f79cc9 5722 total_size += strlen(*q) + 1;
53a5960a 5723 }
f7341ff4 5724 *q = NULL;
7854b056 5725
a6f79cc9
UH
5726 /* This case will not be caught by the host's execve() if its
5727 page size is bigger than the target's. */
5728 if (total_size > MAX_ARG_PAGES * TARGET_PAGE_SIZE) {
5729 ret = -TARGET_E2BIG;
5730 goto execve_end;
5731 }
2f619698
FB
5732 if (!(p = lock_user_string(arg1)))
5733 goto execve_efault;
53a5960a
PB
5734 ret = get_errno(execve(p, argp, envp));
5735 unlock_user(p, arg1, 0);
5736
2f619698
FB
5737 goto execve_end;
5738
5739 execve_efault:
5740 ret = -TARGET_EFAULT;
5741
5742 execve_end:
53a5960a 5743 for (gp = guest_argp, q = argp; *q;
992f48a0 5744 gp += sizeof(abi_ulong), q++) {
2f619698
FB
5745 if (get_user_ual(addr, gp)
5746 || !addr)
5747 break;
53a5960a
PB
5748 unlock_user(*q, addr, 0);
5749 }
5750 for (gp = guest_envp, q = envp; *q;
992f48a0 5751 gp += sizeof(abi_ulong), q++) {
2f619698
FB
5752 if (get_user_ual(addr, gp)
5753 || !addr)
5754 break;
53a5960a
PB
5755 unlock_user(*q, addr, 0);
5756 }
7854b056 5757 }
31e31b8a
FB
5758 break;
5759 case TARGET_NR_chdir:
579a97f7
FB
5760 if (!(p = lock_user_string(arg1)))
5761 goto efault;
53a5960a
PB
5762 ret = get_errno(chdir(p));
5763 unlock_user(p, arg1, 0);
31e31b8a 5764 break;
a315a145 5765#ifdef TARGET_NR_time
31e31b8a
FB
5766 case TARGET_NR_time:
5767 {
53a5960a
PB
5768 time_t host_time;
5769 ret = get_errno(time(&host_time));
2f619698
FB
5770 if (!is_error(ret)
5771 && arg1
5772 && put_user_sal(host_time, arg1))
5773 goto efault;
31e31b8a
FB
5774 }
5775 break;
a315a145 5776#endif
31e31b8a 5777 case TARGET_NR_mknod:
579a97f7
FB
5778 if (!(p = lock_user_string(arg1)))
5779 goto efault;
53a5960a
PB
5780 ret = get_errno(mknod(p, arg2, arg3));
5781 unlock_user(p, arg1, 0);
31e31b8a 5782 break;
c0d472b1 5783#if defined(TARGET_NR_mknodat)
75ac37a0 5784 case TARGET_NR_mknodat:
579a97f7
FB
5785 if (!(p = lock_user_string(arg2)))
5786 goto efault;
c0d472b1 5787 ret = get_errno(mknodat(arg1, p, arg3, arg4));
579a97f7 5788 unlock_user(p, arg2, 0);
75ac37a0
TS
5789 break;
5790#endif
31e31b8a 5791 case TARGET_NR_chmod:
579a97f7
FB
5792 if (!(p = lock_user_string(arg1)))
5793 goto efault;
53a5960a
PB
5794 ret = get_errno(chmod(p, arg2));
5795 unlock_user(p, arg1, 0);
31e31b8a 5796 break;
ebc05488 5797#ifdef TARGET_NR_break
31e31b8a
FB
5798 case TARGET_NR_break:
5799 goto unimplemented;
ebc05488
FB
5800#endif
5801#ifdef TARGET_NR_oldstat
31e31b8a
FB
5802 case TARGET_NR_oldstat:
5803 goto unimplemented;
ebc05488 5804#endif
31e31b8a
FB
5805 case TARGET_NR_lseek:
5806 ret = get_errno(lseek(arg1, arg2, arg3));
5807 break;
9231733a
RH
5808#if defined(TARGET_NR_getxpid) && defined(TARGET_ALPHA)
5809 /* Alpha specific */
7a3148a9 5810 case TARGET_NR_getxpid:
9231733a
RH
5811 ((CPUAlphaState *)cpu_env)->ir[IR_A4] = getppid();
5812 ret = get_errno(getpid());
5813 break;
7a3148a9 5814#endif
9231733a
RH
5815#ifdef TARGET_NR_getpid
5816 case TARGET_NR_getpid:
31e31b8a
FB
5817 ret = get_errno(getpid());
5818 break;
9231733a 5819#endif
31e31b8a 5820 case TARGET_NR_mount:
356d771b
PB
5821 {
5822 /* need to look at the data field */
5823 void *p2, *p3;
5824
5825 if (arg1) {
5826 p = lock_user_string(arg1);
5827 if (!p) {
5828 goto efault;
5829 }
5830 } else {
5831 p = NULL;
5832 }
5833
5834 p2 = lock_user_string(arg2);
5835 if (!p2) {
5836 if (arg1) {
5837 unlock_user(p, arg1, 0);
5838 }
5839 goto efault;
5840 }
5841
5842 if (arg3) {
5843 p3 = lock_user_string(arg3);
5844 if (!p3) {
5845 if (arg1) {
579a97f7 5846 unlock_user(p, arg1, 0);
356d771b
PB
5847 }
5848 unlock_user(p2, arg2, 0);
5849 goto efault;
5850 }
5851 } else {
5852 p3 = NULL;
5853 }
5854
5855 /* FIXME - arg5 should be locked, but it isn't clear how to
5856 * do that since it's not guaranteed to be a NULL-terminated
5857 * string.
5858 */
5859 if (!arg5) {
5860 ret = mount(p, p2, p3, (unsigned long)arg4, NULL);
5861 } else {
5862 ret = mount(p, p2, p3, (unsigned long)arg4, g2h(arg5));
5863 }
5864 ret = get_errno(ret);
5865
5866 if (arg1) {
5867 unlock_user(p, arg1, 0);
5868 }
5869 unlock_user(p2, arg2, 0);
5870 if (arg3) {
5871 unlock_user(p3, arg3, 0);
5872 }
5873 }
5874 break;
e5febef5 5875#ifdef TARGET_NR_umount
31e31b8a 5876 case TARGET_NR_umount:
579a97f7
FB
5877 if (!(p = lock_user_string(arg1)))
5878 goto efault;
53a5960a
PB
5879 ret = get_errno(umount(p));
5880 unlock_user(p, arg1, 0);
31e31b8a 5881 break;
e5febef5 5882#endif
7a3148a9 5883#ifdef TARGET_NR_stime /* not on alpha */
31e31b8a
FB
5884 case TARGET_NR_stime:
5885 {
53a5960a 5886 time_t host_time;
2f619698
FB
5887 if (get_user_sal(host_time, arg1))
5888 goto efault;
53a5960a 5889 ret = get_errno(stime(&host_time));
31e31b8a
FB
5890 }
5891 break;
7a3148a9 5892#endif
31e31b8a
FB
5893 case TARGET_NR_ptrace:
5894 goto unimplemented;
7a3148a9 5895#ifdef TARGET_NR_alarm /* not on alpha */
31e31b8a
FB
5896 case TARGET_NR_alarm:
5897 ret = alarm(arg1);
5898 break;
7a3148a9 5899#endif
ebc05488 5900#ifdef TARGET_NR_oldfstat
31e31b8a
FB
5901 case TARGET_NR_oldfstat:
5902 goto unimplemented;
ebc05488 5903#endif
7a3148a9 5904#ifdef TARGET_NR_pause /* not on alpha */
31e31b8a
FB
5905 case TARGET_NR_pause:
5906 ret = get_errno(pause());
5907 break;
7a3148a9 5908#endif
e5febef5 5909#ifdef TARGET_NR_utime
31e31b8a 5910 case TARGET_NR_utime:
ebc05488 5911 {
53a5960a
PB
5912 struct utimbuf tbuf, *host_tbuf;
5913 struct target_utimbuf *target_tbuf;
5914 if (arg2) {
579a97f7
FB
5915 if (!lock_user_struct(VERIFY_READ, target_tbuf, arg2, 1))
5916 goto efault;
cbb21eed
MB
5917 tbuf.actime = tswapal(target_tbuf->actime);
5918 tbuf.modtime = tswapal(target_tbuf->modtime);
53a5960a
PB
5919 unlock_user_struct(target_tbuf, arg2, 0);
5920 host_tbuf = &tbuf;
f72e8ff4 5921 } else {
53a5960a 5922 host_tbuf = NULL;
f72e8ff4 5923 }
579a97f7
FB
5924 if (!(p = lock_user_string(arg1)))
5925 goto efault;
53a5960a
PB
5926 ret = get_errno(utime(p, host_tbuf));
5927 unlock_user(p, arg1, 0);
ebc05488
FB
5928 }
5929 break;
e5febef5 5930#endif
978a66ff
FB
5931 case TARGET_NR_utimes:
5932 {
978a66ff 5933 struct timeval *tvp, tv[2];
53a5960a 5934 if (arg2) {
788f5ec4
TS
5935 if (copy_from_user_timeval(&tv[0], arg2)
5936 || copy_from_user_timeval(&tv[1],
5937 arg2 + sizeof(struct target_timeval)))
5938 goto efault;
978a66ff
FB
5939 tvp = tv;
5940 } else {
5941 tvp = NULL;
5942 }
579a97f7
FB
5943 if (!(p = lock_user_string(arg1)))
5944 goto efault;
53a5960a
PB
5945 ret = get_errno(utimes(p, tvp));
5946 unlock_user(p, arg1, 0);
978a66ff
FB
5947 }
5948 break;
c0d472b1 5949#if defined(TARGET_NR_futimesat)
ac8a6556
AZ
5950 case TARGET_NR_futimesat:
5951 {
5952 struct timeval *tvp, tv[2];
5953 if (arg3) {
5954 if (copy_from_user_timeval(&tv[0], arg3)
5955 || copy_from_user_timeval(&tv[1],
5956 arg3 + sizeof(struct target_timeval)))
5957 goto efault;
5958 tvp = tv;
5959 } else {
5960 tvp = NULL;
5961 }
5962 if (!(p = lock_user_string(arg2)))
5963 goto efault;
c0d472b1 5964 ret = get_errno(futimesat(arg1, path(p), tvp));
ac8a6556
AZ
5965 unlock_user(p, arg2, 0);
5966 }
5967 break;
5968#endif
ebc05488 5969#ifdef TARGET_NR_stty
31e31b8a
FB
5970 case TARGET_NR_stty:
5971 goto unimplemented;
ebc05488
FB
5972#endif
5973#ifdef TARGET_NR_gtty
31e31b8a
FB
5974 case TARGET_NR_gtty:
5975 goto unimplemented;
ebc05488 5976#endif
31e31b8a 5977 case TARGET_NR_access:
579a97f7
FB
5978 if (!(p = lock_user_string(arg1)))
5979 goto efault;
719f908e 5980 ret = get_errno(access(path(p), arg2));
53a5960a 5981 unlock_user(p, arg1, 0);
31e31b8a 5982 break;
92a34c10
TS
5983#if defined(TARGET_NR_faccessat) && defined(__NR_faccessat)
5984 case TARGET_NR_faccessat:
579a97f7
FB
5985 if (!(p = lock_user_string(arg2)))
5986 goto efault;
c0d472b1 5987 ret = get_errno(faccessat(arg1, p, arg3, 0));
579a97f7 5988 unlock_user(p, arg2, 0);
92a34c10
TS
5989 break;
5990#endif
7a3148a9 5991#ifdef TARGET_NR_nice /* not on alpha */
31e31b8a
FB
5992 case TARGET_NR_nice:
5993 ret = get_errno(nice(arg1));
5994 break;
7a3148a9 5995#endif
ebc05488 5996#ifdef TARGET_NR_ftime
31e31b8a
FB
5997 case TARGET_NR_ftime:
5998 goto unimplemented;
ebc05488 5999#endif
31e31b8a 6000 case TARGET_NR_sync:
04369ff2
FB
6001 sync();
6002 ret = 0;
31e31b8a
FB
6003 break;
6004 case TARGET_NR_kill:
4cb05961 6005 ret = get_errno(kill(arg1, target_to_host_signal(arg2)));
31e31b8a
FB
6006 break;
6007 case TARGET_NR_rename:
53a5960a
PB
6008 {
6009 void *p2;
6010 p = lock_user_string(arg1);
6011 p2 = lock_user_string(arg2);
579a97f7
FB
6012 if (!p || !p2)
6013 ret = -TARGET_EFAULT;
6014 else
6015 ret = get_errno(rename(p, p2));
53a5960a
PB
6016 unlock_user(p2, arg2, 0);
6017 unlock_user(p, arg1, 0);
6018 }
31e31b8a 6019 break;
c0d472b1 6020#if defined(TARGET_NR_renameat)
722183f6 6021 case TARGET_NR_renameat:
722183f6 6022 {
579a97f7 6023 void *p2;
722183f6
TS
6024 p = lock_user_string(arg2);
6025 p2 = lock_user_string(arg4);
579a97f7 6026 if (!p || !p2)
0da46a6e 6027 ret = -TARGET_EFAULT;
722183f6 6028 else
c0d472b1 6029 ret = get_errno(renameat(arg1, p, arg3, p2));
579a97f7
FB
6030 unlock_user(p2, arg4, 0);
6031 unlock_user(p, arg2, 0);
722183f6
TS
6032 }
6033 break;
6034#endif
31e31b8a 6035 case TARGET_NR_mkdir:
579a97f7
FB
6036 if (!(p = lock_user_string(arg1)))
6037 goto efault;
53a5960a
PB
6038 ret = get_errno(mkdir(p, arg2));
6039 unlock_user(p, arg1, 0);
31e31b8a 6040 break;
c0d472b1 6041#if defined(TARGET_NR_mkdirat)
4472ad0d 6042 case TARGET_NR_mkdirat:
579a97f7
FB
6043 if (!(p = lock_user_string(arg2)))
6044 goto efault;
c0d472b1 6045 ret = get_errno(mkdirat(arg1, p, arg3));
579a97f7 6046 unlock_user(p, arg2, 0);
4472ad0d
TS
6047 break;
6048#endif
31e31b8a 6049 case TARGET_NR_rmdir:
579a97f7
FB
6050 if (!(p = lock_user_string(arg1)))
6051 goto efault;
53a5960a
PB
6052 ret = get_errno(rmdir(p));
6053 unlock_user(p, arg1, 0);
31e31b8a
FB
6054 break;
6055 case TARGET_NR_dup:
6056 ret = get_errno(dup(arg1));
6057 break;
6058 case TARGET_NR_pipe:
fb41a66e 6059 ret = do_pipe(cpu_env, arg1, 0, 0);
099d6b0f
RV
6060 break;
6061#ifdef TARGET_NR_pipe2
6062 case TARGET_NR_pipe2:
e7ea6cbe
RH
6063 ret = do_pipe(cpu_env, arg1,
6064 target_to_host_bitmask(arg2, fcntl_flags_tbl), 1);
31e31b8a 6065 break;
099d6b0f 6066#endif
31e31b8a 6067 case TARGET_NR_times:
32f36bce 6068 {
53a5960a 6069 struct target_tms *tmsp;
32f36bce
FB
6070 struct tms tms;
6071 ret = get_errno(times(&tms));
53a5960a 6072 if (arg1) {
579a97f7
FB
6073 tmsp = lock_user(VERIFY_WRITE, arg1, sizeof(struct target_tms), 0);
6074 if (!tmsp)
6075 goto efault;
cbb21eed
MB
6076 tmsp->tms_utime = tswapal(host_to_target_clock_t(tms.tms_utime));
6077 tmsp->tms_stime = tswapal(host_to_target_clock_t(tms.tms_stime));
6078 tmsp->tms_cutime = tswapal(host_to_target_clock_t(tms.tms_cutime));
6079 tmsp->tms_cstime = tswapal(host_to_target_clock_t(tms.tms_cstime));
32f36bce 6080 }
c596ed17
FB
6081 if (!is_error(ret))
6082 ret = host_to_target_clock_t(ret);
32f36bce
FB
6083 }
6084 break;
ebc05488 6085#ifdef TARGET_NR_prof
31e31b8a
FB
6086 case TARGET_NR_prof:
6087 goto unimplemented;
ebc05488 6088#endif
e5febef5 6089#ifdef TARGET_NR_signal
31e31b8a
FB
6090 case TARGET_NR_signal:
6091 goto unimplemented;
e5febef5 6092#endif
31e31b8a 6093 case TARGET_NR_acct:
38d840e6
AJ
6094 if (arg1 == 0) {
6095 ret = get_errno(acct(NULL));
6096 } else {
6097 if (!(p = lock_user_string(arg1)))
6098 goto efault;
6099 ret = get_errno(acct(path(p)));
6100 unlock_user(p, arg1, 0);
6101 }
24836689 6102 break;
8070e7be 6103#ifdef TARGET_NR_umount2
31e31b8a 6104 case TARGET_NR_umount2:
579a97f7
FB
6105 if (!(p = lock_user_string(arg1)))
6106 goto efault;
53a5960a
PB
6107 ret = get_errno(umount2(p, arg2));
6108 unlock_user(p, arg1, 0);
31e31b8a 6109 break;
7a3148a9 6110#endif
ebc05488 6111#ifdef TARGET_NR_lock
31e31b8a
FB
6112 case TARGET_NR_lock:
6113 goto unimplemented;
ebc05488 6114#endif
31e31b8a
FB
6115 case TARGET_NR_ioctl:
6116 ret = do_ioctl(arg1, arg2, arg3);
6117 break;
6118 case TARGET_NR_fcntl:
9ee1fa2c 6119 ret = do_fcntl(arg1, arg2, arg3);
31e31b8a 6120 break;
ebc05488 6121#ifdef TARGET_NR_mpx
31e31b8a
FB
6122 case TARGET_NR_mpx:
6123 goto unimplemented;
ebc05488 6124#endif
31e31b8a
FB
6125 case TARGET_NR_setpgid:
6126 ret = get_errno(setpgid(arg1, arg2));
6127 break;
ebc05488 6128#ifdef TARGET_NR_ulimit
31e31b8a
FB
6129 case TARGET_NR_ulimit:
6130 goto unimplemented;
ebc05488
FB
6131#endif
6132#ifdef TARGET_NR_oldolduname
31e31b8a
FB
6133 case TARGET_NR_oldolduname:
6134 goto unimplemented;
ebc05488 6135#endif
31e31b8a
FB
6136 case TARGET_NR_umask:
6137 ret = get_errno(umask(arg1));
6138 break;
6139 case TARGET_NR_chroot:
579a97f7
FB
6140 if (!(p = lock_user_string(arg1)))
6141 goto efault;
53a5960a
PB
6142 ret = get_errno(chroot(p));
6143 unlock_user(p, arg1, 0);
31e31b8a
FB
6144 break;
6145 case TARGET_NR_ustat:
6146 goto unimplemented;
6147 case TARGET_NR_dup2:
6148 ret = get_errno(dup2(arg1, arg2));
6149 break;
d0927938
UH
6150#if defined(CONFIG_DUP3) && defined(TARGET_NR_dup3)
6151 case TARGET_NR_dup3:
6152 ret = get_errno(dup3(arg1, arg2, arg3));
6153 break;
6154#endif
7a3148a9 6155#ifdef TARGET_NR_getppid /* not on alpha */
31e31b8a
FB
6156 case TARGET_NR_getppid:
6157 ret = get_errno(getppid());
6158 break;
7a3148a9 6159#endif
31e31b8a
FB
6160 case TARGET_NR_getpgrp:
6161 ret = get_errno(getpgrp());
6162 break;
6163 case TARGET_NR_setsid:
6164 ret = get_errno(setsid());
6165 break;
e5febef5 6166#ifdef TARGET_NR_sigaction
31e31b8a 6167 case TARGET_NR_sigaction:
31e31b8a 6168 {
6049f4f8
RH
6169#if defined(TARGET_ALPHA)
6170 struct target_sigaction act, oact, *pact = 0;
53a5960a 6171 struct target_old_sigaction *old_act;
53a5960a 6172 if (arg2) {
579a97f7
FB
6173 if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1))
6174 goto efault;
66fb9763
FB
6175 act._sa_handler = old_act->_sa_handler;
6176 target_siginitset(&act.sa_mask, old_act->sa_mask);
6177 act.sa_flags = old_act->sa_flags;
6049f4f8 6178 act.sa_restorer = 0;
53a5960a 6179 unlock_user_struct(old_act, arg2, 0);
66fb9763 6180 pact = &act;
66fb9763
FB
6181 }
6182 ret = get_errno(do_sigaction(arg1, pact, &oact));
53a5960a 6183 if (!is_error(ret) && arg3) {
579a97f7
FB
6184 if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0))
6185 goto efault;
53a5960a
PB
6186 old_act->_sa_handler = oact._sa_handler;
6187 old_act->sa_mask = oact.sa_mask.sig[0];
6188 old_act->sa_flags = oact.sa_flags;
53a5960a 6189 unlock_user_struct(old_act, arg3, 1);
66fb9763 6190 }
6049f4f8 6191#elif defined(TARGET_MIPS)
106ec879
FB
6192 struct target_sigaction act, oact, *pact, *old_act;
6193
6194 if (arg2) {
579a97f7
FB
6195 if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1))
6196 goto efault;
106ec879
FB
6197 act._sa_handler = old_act->_sa_handler;
6198 target_siginitset(&act.sa_mask, old_act->sa_mask.sig[0]);
6199 act.sa_flags = old_act->sa_flags;
6200 unlock_user_struct(old_act, arg2, 0);
6201 pact = &act;
6202 } else {
6203 pact = NULL;
6204 }
6205
6206 ret = get_errno(do_sigaction(arg1, pact, &oact));
6207
6208 if (!is_error(ret) && arg3) {
579a97f7
FB
6209 if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0))
6210 goto efault;
106ec879
FB
6211 old_act->_sa_handler = oact._sa_handler;
6212 old_act->sa_flags = oact.sa_flags;
6213 old_act->sa_mask.sig[0] = oact.sa_mask.sig[0];
6214 old_act->sa_mask.sig[1] = 0;
6215 old_act->sa_mask.sig[2] = 0;
6216 old_act->sa_mask.sig[3] = 0;
6217 unlock_user_struct(old_act, arg3, 1);
6218 }
6049f4f8
RH
6219#else
6220 struct target_old_sigaction *old_act;
6221 struct target_sigaction act, oact, *pact;
6222 if (arg2) {
6223 if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1))
6224 goto efault;
6225 act._sa_handler = old_act->_sa_handler;
6226 target_siginitset(&act.sa_mask, old_act->sa_mask);
6227 act.sa_flags = old_act->sa_flags;
6228 act.sa_restorer = old_act->sa_restorer;
6229 unlock_user_struct(old_act, arg2, 0);
6230 pact = &act;
6231 } else {
6232 pact = NULL;
6233 }
6234 ret = get_errno(do_sigaction(arg1, pact, &oact));
6235 if (!is_error(ret) && arg3) {
6236 if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0))
6237 goto efault;
6238 old_act->_sa_handler = oact._sa_handler;
6239 old_act->sa_mask = oact.sa_mask.sig[0];
6240 old_act->sa_flags = oact.sa_flags;
6241 old_act->sa_restorer = oact.sa_restorer;
6242 unlock_user_struct(old_act, arg3, 1);
6243 }
388bb21a 6244#endif
31e31b8a
FB
6245 }
6246 break;
e5febef5 6247#endif
66fb9763 6248 case TARGET_NR_rt_sigaction:
53a5960a 6249 {
6049f4f8
RH
6250#if defined(TARGET_ALPHA)
6251 struct target_sigaction act, oact, *pact = 0;
6252 struct target_rt_sigaction *rt_act;
6253 /* ??? arg4 == sizeof(sigset_t). */
6254 if (arg2) {
6255 if (!lock_user_struct(VERIFY_READ, rt_act, arg2, 1))
6256 goto efault;
6257 act._sa_handler = rt_act->_sa_handler;
6258 act.sa_mask = rt_act->sa_mask;
6259 act.sa_flags = rt_act->sa_flags;
6260 act.sa_restorer = arg5;
6261 unlock_user_struct(rt_act, arg2, 0);
6262 pact = &act;
6263 }
6264 ret = get_errno(do_sigaction(arg1, pact, &oact));
6265 if (!is_error(ret) && arg3) {
6266 if (!lock_user_struct(VERIFY_WRITE, rt_act, arg3, 0))
6267 goto efault;
6268 rt_act->_sa_handler = oact._sa_handler;
6269 rt_act->sa_mask = oact.sa_mask;
6270 rt_act->sa_flags = oact.sa_flags;
6271 unlock_user_struct(rt_act, arg3, 1);
6272 }
6273#else
53a5960a
PB
6274 struct target_sigaction *act;
6275 struct target_sigaction *oact;
6276
579a97f7
FB
6277 if (arg2) {
6278 if (!lock_user_struct(VERIFY_READ, act, arg2, 1))
6279 goto efault;
6280 } else
53a5960a 6281 act = NULL;
579a97f7
FB
6282 if (arg3) {
6283 if (!lock_user_struct(VERIFY_WRITE, oact, arg3, 0)) {
6284 ret = -TARGET_EFAULT;
6285 goto rt_sigaction_fail;
6286 }
6287 } else
53a5960a
PB
6288 oact = NULL;
6289 ret = get_errno(do_sigaction(arg1, act, oact));
579a97f7
FB
6290 rt_sigaction_fail:
6291 if (act)
53a5960a 6292 unlock_user_struct(act, arg2, 0);
579a97f7 6293 if (oact)
53a5960a 6294 unlock_user_struct(oact, arg3, 1);
6049f4f8 6295#endif
53a5960a 6296 }
66fb9763 6297 break;
7a3148a9 6298#ifdef TARGET_NR_sgetmask /* not on alpha */
31e31b8a 6299 case TARGET_NR_sgetmask:
66fb9763
FB
6300 {
6301 sigset_t cur_set;
992f48a0 6302 abi_ulong target_set;
1c275925 6303 do_sigprocmask(0, NULL, &cur_set);
66fb9763
FB
6304 host_to_target_old_sigset(&target_set, &cur_set);
6305 ret = target_set;
6306 }
6307 break;
7a3148a9
JM
6308#endif
6309#ifdef TARGET_NR_ssetmask /* not on alpha */
31e31b8a 6310 case TARGET_NR_ssetmask:
66fb9763
FB
6311 {
6312 sigset_t set, oset, cur_set;
992f48a0 6313 abi_ulong target_set = arg1;
1c275925 6314 do_sigprocmask(0, NULL, &cur_set);
66fb9763
FB
6315 target_to_host_old_sigset(&set, &target_set);
6316 sigorset(&set, &set, &cur_set);
1c275925 6317 do_sigprocmask(SIG_SETMASK, &set, &oset);
66fb9763
FB
6318 host_to_target_old_sigset(&target_set, &oset);
6319 ret = target_set;
6320 }
6321 break;
7a3148a9 6322#endif
e5febef5 6323#ifdef TARGET_NR_sigprocmask
66fb9763
FB
6324 case TARGET_NR_sigprocmask:
6325 {
a5b3b13b
RH
6326#if defined(TARGET_ALPHA)
6327 sigset_t set, oldset;
6328 abi_ulong mask;
6329 int how;
6330
6331 switch (arg1) {
6332 case TARGET_SIG_BLOCK:
6333 how = SIG_BLOCK;
6334 break;
6335 case TARGET_SIG_UNBLOCK:
6336 how = SIG_UNBLOCK;
6337 break;
6338 case TARGET_SIG_SETMASK:
6339 how = SIG_SETMASK;
6340 break;
6341 default:
6342 ret = -TARGET_EINVAL;
6343 goto fail;
6344 }
6345 mask = arg2;
6346 target_to_host_old_sigset(&set, &mask);
6347
1c275925 6348 ret = get_errno(do_sigprocmask(how, &set, &oldset));
a5b3b13b
RH
6349 if (!is_error(ret)) {
6350 host_to_target_old_sigset(&mask, &oldset);
6351 ret = mask;
0229f5a3 6352 ((CPUAlphaState *)cpu_env)->ir[IR_V0] = 0; /* force no error */
a5b3b13b
RH
6353 }
6354#else
66fb9763 6355 sigset_t set, oldset, *set_ptr;
a5b3b13b 6356 int how;
3b46e624 6357
53a5960a 6358 if (arg2) {
a5b3b13b 6359 switch (arg1) {
66fb9763
FB
6360 case TARGET_SIG_BLOCK:
6361 how = SIG_BLOCK;
6362 break;
6363 case TARGET_SIG_UNBLOCK:
6364 how = SIG_UNBLOCK;
6365 break;
6366 case TARGET_SIG_SETMASK:
6367 how = SIG_SETMASK;
6368 break;
6369 default:
0da46a6e 6370 ret = -TARGET_EINVAL;
66fb9763
FB
6371 goto fail;
6372 }
c227f099 6373 if (!(p = lock_user(VERIFY_READ, arg2, sizeof(target_sigset_t), 1)))
579a97f7 6374 goto efault;
53a5960a
PB
6375 target_to_host_old_sigset(&set, p);
6376 unlock_user(p, arg2, 0);
66fb9763
FB
6377 set_ptr = &set;
6378 } else {
6379 how = 0;
6380 set_ptr = NULL;
6381 }
1c275925 6382 ret = get_errno(do_sigprocmask(how, set_ptr, &oldset));
53a5960a 6383 if (!is_error(ret) && arg3) {
c227f099 6384 if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0)))
579a97f7 6385 goto efault;
53a5960a 6386 host_to_target_old_sigset(p, &oldset);
c227f099 6387 unlock_user(p, arg3, sizeof(target_sigset_t));
66fb9763 6388 }
a5b3b13b 6389#endif
66fb9763
FB
6390 }
6391 break;
e5febef5 6392#endif
66fb9763
FB
6393 case TARGET_NR_rt_sigprocmask:
6394 {
6395 int how = arg1;
6396 sigset_t set, oldset, *set_ptr;
3b46e624 6397
53a5960a 6398 if (arg2) {
66fb9763
FB
6399 switch(how) {
6400 case TARGET_SIG_BLOCK:
6401 how = SIG_BLOCK;
6402 break;
6403 case TARGET_SIG_UNBLOCK:
6404 how = SIG_UNBLOCK;
6405 break;
6406 case TARGET_SIG_SETMASK:
6407 how = SIG_SETMASK;
6408 break;
6409 default:
0da46a6e 6410 ret = -TARGET_EINVAL;
66fb9763
FB
6411 goto fail;
6412 }
c227f099 6413 if (!(p = lock_user(VERIFY_READ, arg2, sizeof(target_sigset_t), 1)))
579a97f7 6414 goto efault;
53a5960a
PB
6415 target_to_host_sigset(&set, p);
6416 unlock_user(p, arg2, 0);
66fb9763
FB
6417 set_ptr = &set;
6418 } else {
6419 how = 0;
6420 set_ptr = NULL;
6421 }
1c275925 6422 ret = get_errno(do_sigprocmask(how, set_ptr, &oldset));
53a5960a 6423 if (!is_error(ret) && arg3) {
c227f099 6424 if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0)))
579a97f7 6425 goto efault;
53a5960a 6426 host_to_target_sigset(p, &oldset);
c227f099 6427 unlock_user(p, arg3, sizeof(target_sigset_t));
66fb9763
FB
6428 }
6429 }
6430 break;
e5febef5 6431#ifdef TARGET_NR_sigpending
66fb9763
FB
6432 case TARGET_NR_sigpending:
6433 {
6434 sigset_t set;
6435 ret = get_errno(sigpending(&set));
6436 if (!is_error(ret)) {
c227f099 6437 if (!(p = lock_user(VERIFY_WRITE, arg1, sizeof(target_sigset_t), 0)))
579a97f7 6438 goto efault;
53a5960a 6439 host_to_target_old_sigset(p, &set);
c227f099 6440 unlock_user(p, arg1, sizeof(target_sigset_t));
66fb9763
FB
6441 }
6442 }
6443 break;
e5febef5 6444#endif
66fb9763
FB
6445 case TARGET_NR_rt_sigpending:
6446 {
6447 sigset_t set;
6448 ret = get_errno(sigpending(&set));
6449 if (!is_error(ret)) {
c227f099 6450 if (!(p = lock_user(VERIFY_WRITE, arg1, sizeof(target_sigset_t), 0)))
579a97f7 6451 goto efault;
53a5960a 6452 host_to_target_sigset(p, &set);
c227f099 6453 unlock_user(p, arg1, sizeof(target_sigset_t));
66fb9763
FB
6454 }
6455 }
6456 break;
e5febef5 6457#ifdef TARGET_NR_sigsuspend
66fb9763
FB
6458 case TARGET_NR_sigsuspend:
6459 {
6460 sigset_t set;
f43ce12b
RH
6461#if defined(TARGET_ALPHA)
6462 abi_ulong mask = arg1;
6463 target_to_host_old_sigset(&set, &mask);
6464#else
c227f099 6465 if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
579a97f7 6466 goto efault;
53a5960a
PB
6467 target_to_host_old_sigset(&set, p);
6468 unlock_user(p, arg1, 0);
f43ce12b 6469#endif
66fb9763
FB
6470 ret = get_errno(sigsuspend(&set));
6471 }
6472 break;
e5febef5 6473#endif
66fb9763
FB
6474 case TARGET_NR_rt_sigsuspend:
6475 {
6476 sigset_t set;
c227f099 6477 if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
579a97f7 6478 goto efault;
53a5960a
PB
6479 target_to_host_sigset(&set, p);
6480 unlock_user(p, arg1, 0);
66fb9763
FB
6481 ret = get_errno(sigsuspend(&set));
6482 }
6483 break;
6484 case TARGET_NR_rt_sigtimedwait:
6485 {
66fb9763
FB
6486 sigset_t set;
6487 struct timespec uts, *puts;
6488 siginfo_t uinfo;
3b46e624 6489
c227f099 6490 if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
579a97f7 6491 goto efault;
53a5960a
PB
6492 target_to_host_sigset(&set, p);
6493 unlock_user(p, arg1, 0);
6494 if (arg3) {
66fb9763 6495 puts = &uts;
53a5960a 6496 target_to_host_timespec(puts, arg3);
66fb9763
FB
6497 } else {
6498 puts = NULL;
6499 }
6500 ret = get_errno(sigtimedwait(&set, &uinfo, puts));
974a196d
PJ
6501 if (!is_error(ret)) {
6502 if (arg2) {
6503 p = lock_user(VERIFY_WRITE, arg2, sizeof(target_siginfo_t),
6504 0);
6505 if (!p) {
6506 goto efault;
6507 }
6508 host_to_target_siginfo(p, &uinfo);
6509 unlock_user(p, arg2, sizeof(target_siginfo_t));
6510 }
6511 ret = host_to_target_signal(ret);
66fb9763
FB
6512 }
6513 }
6514 break;
6515 case TARGET_NR_rt_sigqueueinfo:
6516 {
6517 siginfo_t uinfo;
c227f099 6518 if (!(p = lock_user(VERIFY_READ, arg3, sizeof(target_sigset_t), 1)))
579a97f7 6519 goto efault;
53a5960a
PB
6520 target_to_host_siginfo(&uinfo, p);
6521 unlock_user(p, arg1, 0);
66fb9763
FB
6522 ret = get_errno(sys_rt_sigqueueinfo(arg1, arg2, &uinfo));
6523 }
6524 break;
e5febef5 6525#ifdef TARGET_NR_sigreturn
66fb9763
FB
6526 case TARGET_NR_sigreturn:
6527 /* NOTE: ret is eax, so not transcoding must be done */
6528 ret = do_sigreturn(cpu_env);
6529 break;
e5febef5 6530#endif
66fb9763
FB
6531 case TARGET_NR_rt_sigreturn:
6532 /* NOTE: ret is eax, so not transcoding must be done */
6533 ret = do_rt_sigreturn(cpu_env);
6534 break;
31e31b8a 6535 case TARGET_NR_sethostname:
579a97f7
FB
6536 if (!(p = lock_user_string(arg1)))
6537 goto efault;
53a5960a
PB
6538 ret = get_errno(sethostname(p, arg2));
6539 unlock_user(p, arg1, 0);
31e31b8a
FB
6540 break;
6541 case TARGET_NR_setrlimit:
9de5e440 6542 {
e22b7015 6543 int resource = target_to_host_resource(arg1);
53a5960a 6544 struct target_rlimit *target_rlim;
9de5e440 6545 struct rlimit rlim;
579a97f7
FB
6546 if (!lock_user_struct(VERIFY_READ, target_rlim, arg2, 1))
6547 goto efault;
81bbe906
TY
6548 rlim.rlim_cur = target_to_host_rlim(target_rlim->rlim_cur);
6549 rlim.rlim_max = target_to_host_rlim(target_rlim->rlim_max);
53a5960a 6550 unlock_user_struct(target_rlim, arg2, 0);
9de5e440
FB
6551 ret = get_errno(setrlimit(resource, &rlim));
6552 }
6553 break;
31e31b8a 6554 case TARGET_NR_getrlimit:
9de5e440 6555 {
e22b7015 6556 int resource = target_to_host_resource(arg1);
53a5960a 6557 struct target_rlimit *target_rlim;
9de5e440 6558 struct rlimit rlim;
3b46e624 6559
9de5e440
FB
6560 ret = get_errno(getrlimit(resource, &rlim));
6561 if (!is_error(ret)) {
579a97f7
FB
6562 if (!lock_user_struct(VERIFY_WRITE, target_rlim, arg2, 0))
6563 goto efault;
81bbe906
TY
6564 target_rlim->rlim_cur = host_to_target_rlim(rlim.rlim_cur);
6565 target_rlim->rlim_max = host_to_target_rlim(rlim.rlim_max);
53a5960a 6566 unlock_user_struct(target_rlim, arg2, 1);
9de5e440
FB
6567 }
6568 }
6569 break;
31e31b8a 6570 case TARGET_NR_getrusage:
b409186b
FB
6571 {
6572 struct rusage rusage;
b409186b
FB
6573 ret = get_errno(getrusage(arg1, &rusage));
6574 if (!is_error(ret)) {
a39fb273 6575 ret = host_to_target_rusage(arg2, &rusage);
b409186b
FB
6576 }
6577 }
6578 break;
31e31b8a
FB
6579 case TARGET_NR_gettimeofday:
6580 {
31e31b8a
FB
6581 struct timeval tv;
6582 ret = get_errno(gettimeofday(&tv, NULL));
6583 if (!is_error(ret)) {
788f5ec4
TS
6584 if (copy_to_user_timeval(arg1, &tv))
6585 goto efault;
31e31b8a
FB
6586 }
6587 }
6588 break;
6589 case TARGET_NR_settimeofday:
6590 {
b67d8031 6591 struct timeval tv, *ptv = NULL;
ef4467e9
PB
6592 struct timezone tz, *ptz = NULL;
6593
b67d8031
PB
6594 if (arg1) {
6595 if (copy_from_user_timeval(&tv, arg1)) {
6596 goto efault;
6597 }
6598 ptv = &tv;
6599 }
ef4467e9
PB
6600
6601 if (arg2) {
6602 if (copy_from_user_timezone(&tz, arg2)) {
6603 goto efault;
6604 }
6605 ptz = &tz;
6606 }
6607
b67d8031 6608 ret = get_errno(settimeofday(ptv, ptz));
31e31b8a
FB
6609 }
6610 break;
9468a5d4 6611#if defined(TARGET_NR_select)
31e31b8a 6612 case TARGET_NR_select:
9468a5d4
LV
6613#if defined(TARGET_S390X) || defined(TARGET_ALPHA)
6614 ret = do_select(arg1, arg2, arg3, arg4, arg5);
6615#else
f2674e31 6616 {
53a5960a 6617 struct target_sel_arg_struct *sel;
992f48a0 6618 abi_ulong inp, outp, exp, tvp;
53a5960a
PB
6619 long nsel;
6620
579a97f7
FB
6621 if (!lock_user_struct(VERIFY_READ, sel, arg1, 1))
6622 goto efault;
cbb21eed
MB
6623 nsel = tswapal(sel->n);
6624 inp = tswapal(sel->inp);
6625 outp = tswapal(sel->outp);
6626 exp = tswapal(sel->exp);
6627 tvp = tswapal(sel->tvp);
53a5960a
PB
6628 unlock_user_struct(sel, arg1, 0);
6629 ret = do_select(nsel, inp, outp, exp, tvp);
f2674e31 6630 }
9468a5d4 6631#endif
f2674e31 6632 break;
9e42382f
RV
6633#endif
6634#ifdef TARGET_NR_pselect6
6635 case TARGET_NR_pselect6:
055e0906
MF
6636 {
6637 abi_long rfd_addr, wfd_addr, efd_addr, n, ts_addr;
6638 fd_set rfds, wfds, efds;
6639 fd_set *rfds_ptr, *wfds_ptr, *efds_ptr;
6640 struct timespec ts, *ts_ptr;
6641
6642 /*
6643 * The 6th arg is actually two args smashed together,
6644 * so we cannot use the C library.
6645 */
6646 sigset_t set;
6647 struct {
6648 sigset_t *set;
6649 size_t size;
6650 } sig, *sig_ptr;
6651
6652 abi_ulong arg_sigset, arg_sigsize, *arg7;
6653 target_sigset_t *target_sigset;
6654
6655 n = arg1;
6656 rfd_addr = arg2;
6657 wfd_addr = arg3;
6658 efd_addr = arg4;
6659 ts_addr = arg5;
6660
6661 ret = copy_from_user_fdset_ptr(&rfds, &rfds_ptr, rfd_addr, n);
6662 if (ret) {
6663 goto fail;
6664 }
6665 ret = copy_from_user_fdset_ptr(&wfds, &wfds_ptr, wfd_addr, n);
6666 if (ret) {
6667 goto fail;
6668 }
6669 ret = copy_from_user_fdset_ptr(&efds, &efds_ptr, efd_addr, n);
6670 if (ret) {
6671 goto fail;
6672 }
6673
6674 /*
6675 * This takes a timespec, and not a timeval, so we cannot
6676 * use the do_select() helper ...
6677 */
6678 if (ts_addr) {
6679 if (target_to_host_timespec(&ts, ts_addr)) {
6680 goto efault;
6681 }
6682 ts_ptr = &ts;
6683 } else {
6684 ts_ptr = NULL;
6685 }
6686
6687 /* Extract the two packed args for the sigset */
6688 if (arg6) {
6689 sig_ptr = &sig;
6690 sig.size = _NSIG / 8;
6691
6692 arg7 = lock_user(VERIFY_READ, arg6, sizeof(*arg7) * 2, 1);
6693 if (!arg7) {
6694 goto efault;
6695 }
cbb21eed
MB
6696 arg_sigset = tswapal(arg7[0]);
6697 arg_sigsize = tswapal(arg7[1]);
055e0906
MF
6698 unlock_user(arg7, arg6, 0);
6699
6700 if (arg_sigset) {
6701 sig.set = &set;
8f04eeb3
PM
6702 if (arg_sigsize != sizeof(*target_sigset)) {
6703 /* Like the kernel, we enforce correct size sigsets */
6704 ret = -TARGET_EINVAL;
6705 goto fail;
6706 }
055e0906
MF
6707 target_sigset = lock_user(VERIFY_READ, arg_sigset,
6708 sizeof(*target_sigset), 1);
6709 if (!target_sigset) {
6710 goto efault;
6711 }
6712 target_to_host_sigset(&set, target_sigset);
6713 unlock_user(target_sigset, arg_sigset, 0);
6714 } else {
6715 sig.set = NULL;
6716 }
6717 } else {
6718 sig_ptr = NULL;
6719 }
6720
6721 ret = get_errno(sys_pselect6(n, rfds_ptr, wfds_ptr, efds_ptr,
6722 ts_ptr, sig_ptr));
6723
6724 if (!is_error(ret)) {
6725 if (rfd_addr && copy_to_user_fdset(rfd_addr, &rfds, n))
6726 goto efault;
6727 if (wfd_addr && copy_to_user_fdset(wfd_addr, &wfds, n))
6728 goto efault;
6729 if (efd_addr && copy_to_user_fdset(efd_addr, &efds, n))
6730 goto efault;
6731
6732 if (ts_addr && host_to_target_timespec(ts_addr, &ts))
6733 goto efault;
6734 }
6735 }
6736 break;
048f6b4d 6737#endif
31e31b8a 6738 case TARGET_NR_symlink:
53a5960a
PB
6739 {
6740 void *p2;
6741 p = lock_user_string(arg1);
6742 p2 = lock_user_string(arg2);
579a97f7
FB
6743 if (!p || !p2)
6744 ret = -TARGET_EFAULT;
6745 else
6746 ret = get_errno(symlink(p, p2));
53a5960a
PB
6747 unlock_user(p2, arg2, 0);
6748 unlock_user(p, arg1, 0);
6749 }
31e31b8a 6750 break;
c0d472b1 6751#if defined(TARGET_NR_symlinkat)
f0b6243d 6752 case TARGET_NR_symlinkat:
f0b6243d 6753 {
579a97f7 6754 void *p2;
f0b6243d
TS
6755 p = lock_user_string(arg1);
6756 p2 = lock_user_string(arg3);
579a97f7 6757 if (!p || !p2)
0da46a6e 6758 ret = -TARGET_EFAULT;
f0b6243d 6759 else
c0d472b1 6760 ret = get_errno(symlinkat(p, arg2, p2));
579a97f7
FB
6761 unlock_user(p2, arg3, 0);
6762 unlock_user(p, arg1, 0);
f0b6243d
TS
6763 }
6764 break;
6765#endif
ebc05488 6766#ifdef TARGET_NR_oldlstat
31e31b8a
FB
6767 case TARGET_NR_oldlstat:
6768 goto unimplemented;
ebc05488 6769#endif
31e31b8a 6770 case TARGET_NR_readlink:
53a5960a 6771 {
463d8e73 6772 void *p2;
53a5960a 6773 p = lock_user_string(arg1);
579a97f7 6774 p2 = lock_user(VERIFY_WRITE, arg2, arg3, 0);
463d8e73 6775 if (!p || !p2) {
579a97f7 6776 ret = -TARGET_EFAULT;
f17f4989
MF
6777 } else if (!arg3) {
6778 /* Short circuit this for the magic exe check. */
6779 ret = -TARGET_EINVAL;
463d8e73
AS
6780 } else if (is_proc_myself((const char *)p, "exe")) {
6781 char real[PATH_MAX], *temp;
6782 temp = realpath(exec_path, real);
f17f4989
MF
6783 /* Return value is # of bytes that we wrote to the buffer. */
6784 if (temp == NULL) {
6785 ret = get_errno(-1);
6786 } else {
6787 /* Don't worry about sign mismatch as earlier mapping
6788 * logic would have thrown a bad address error. */
6789 ret = MIN(strlen(real), arg3);
6790 /* We cannot NUL terminate the string. */
6791 memcpy(p2, real, ret);
6792 }
463d8e73
AS
6793 } else {
6794 ret = get_errno(readlink(path(p), p2, arg3));
d088d664 6795 }
53a5960a
PB
6796 unlock_user(p2, arg2, ret);
6797 unlock_user(p, arg1, 0);
6798 }
31e31b8a 6799 break;
c0d472b1 6800#if defined(TARGET_NR_readlinkat)
5e0ccb18 6801 case TARGET_NR_readlinkat:
5e0ccb18 6802 {
579a97f7 6803 void *p2;
5e0ccb18 6804 p = lock_user_string(arg2);
579a97f7 6805 p2 = lock_user(VERIFY_WRITE, arg3, arg4, 0);
463d8e73
AS
6806 if (!p || !p2) {
6807 ret = -TARGET_EFAULT;
6808 } else if (is_proc_myself((const char *)p, "exe")) {
6809 char real[PATH_MAX], *temp;
6810 temp = realpath(exec_path, real);
6811 ret = temp == NULL ? get_errno(-1) : strlen(real) ;
6812 snprintf((char *)p2, arg4, "%s", real);
6813 } else {
c0d472b1 6814 ret = get_errno(readlinkat(arg1, path(p), p2, arg4));
463d8e73 6815 }
579a97f7
FB
6816 unlock_user(p2, arg3, ret);
6817 unlock_user(p, arg2, 0);
5e0ccb18
TS
6818 }
6819 break;
6820#endif
e5febef5 6821#ifdef TARGET_NR_uselib
31e31b8a
FB
6822 case TARGET_NR_uselib:
6823 goto unimplemented;
e5febef5
TS
6824#endif
6825#ifdef TARGET_NR_swapon
31e31b8a 6826 case TARGET_NR_swapon:
579a97f7
FB
6827 if (!(p = lock_user_string(arg1)))
6828 goto efault;
53a5960a
PB
6829 ret = get_errno(swapon(p, arg2));
6830 unlock_user(p, arg1, 0);
31e31b8a 6831 break;
e5febef5 6832#endif
31e31b8a 6833 case TARGET_NR_reboot:
c07ecc68
LV
6834 if (arg3 == LINUX_REBOOT_CMD_RESTART2) {
6835 /* arg4 must be ignored in all other cases */
6836 p = lock_user_string(arg4);
6837 if (!p) {
6838 goto efault;
6839 }
6840 ret = get_errno(reboot(arg1, arg2, arg3, p));
6841 unlock_user(p, arg4, 0);
6842 } else {
6843 ret = get_errno(reboot(arg1, arg2, arg3, NULL));
6844 }
0f6b4d21 6845 break;
e5febef5 6846#ifdef TARGET_NR_readdir
31e31b8a
FB
6847 case TARGET_NR_readdir:
6848 goto unimplemented;
e5febef5
TS
6849#endif
6850#ifdef TARGET_NR_mmap
31e31b8a 6851 case TARGET_NR_mmap:
09701199
AG
6852#if (defined(TARGET_I386) && defined(TARGET_ABI32)) || \
6853 (defined(TARGET_ARM) && defined(TARGET_ABI32)) || \
a4c075f1
UH
6854 defined(TARGET_M68K) || defined(TARGET_CRIS) || defined(TARGET_MICROBLAZE) \
6855 || defined(TARGET_S390X)
31e31b8a 6856 {
992f48a0
BS
6857 abi_ulong *v;
6858 abi_ulong v1, v2, v3, v4, v5, v6;
579a97f7
FB
6859 if (!(v = lock_user(VERIFY_READ, arg1, 6 * sizeof(abi_ulong), 1)))
6860 goto efault;
cbb21eed
MB
6861 v1 = tswapal(v[0]);
6862 v2 = tswapal(v[1]);
6863 v3 = tswapal(v[2]);
6864 v4 = tswapal(v[3]);
6865 v5 = tswapal(v[4]);
6866 v6 = tswapal(v[5]);
53a5960a 6867 unlock_user(v, arg1, 0);
5fafdf24 6868 ret = get_errno(target_mmap(v1, v2, v3,
5286db75
FB
6869 target_to_host_bitmask(v4, mmap_flags_tbl),
6870 v5, v6));
31e31b8a 6871 }
31e31b8a 6872#else
5fafdf24
TS
6873 ret = get_errno(target_mmap(arg1, arg2, arg3,
6874 target_to_host_bitmask(arg4, mmap_flags_tbl),
6fb883e8
FB
6875 arg5,
6876 arg6));
31e31b8a 6877#endif
6fb883e8 6878 break;
e5febef5 6879#endif
a315a145 6880#ifdef TARGET_NR_mmap2
6fb883e8 6881 case TARGET_NR_mmap2:
bb7ec043 6882#ifndef MMAP_SHIFT
c573ff67 6883#define MMAP_SHIFT 12
c573ff67 6884#endif
5fafdf24
TS
6885 ret = get_errno(target_mmap(arg1, arg2, arg3,
6886 target_to_host_bitmask(arg4, mmap_flags_tbl),
5286db75 6887 arg5,
c573ff67 6888 arg6 << MMAP_SHIFT));
31e31b8a 6889 break;
a315a145 6890#endif
31e31b8a 6891 case TARGET_NR_munmap:
54936004 6892 ret = get_errno(target_munmap(arg1, arg2));
31e31b8a 6893 break;
9de5e440 6894 case TARGET_NR_mprotect:
97374d38 6895 {
0429a971 6896 TaskState *ts = cpu->opaque;
97374d38
PB
6897 /* Special hack to detect libc making the stack executable. */
6898 if ((arg3 & PROT_GROWSDOWN)
6899 && arg1 >= ts->info->stack_limit
6900 && arg1 <= ts->info->start_stack) {
6901 arg3 &= ~PROT_GROWSDOWN;
6902 arg2 = arg2 + arg1 - ts->info->stack_limit;
6903 arg1 = ts->info->stack_limit;
6904 }
6905 }
54936004 6906 ret = get_errno(target_mprotect(arg1, arg2, arg3));
9de5e440 6907 break;
e5febef5 6908#ifdef TARGET_NR_mremap
9de5e440 6909 case TARGET_NR_mremap:
54936004 6910 ret = get_errno(target_mremap(arg1, arg2, arg3, arg4, arg5));
9de5e440 6911 break;
e5febef5 6912#endif
53a5960a 6913 /* ??? msync/mlock/munlock are broken for softmmu. */
e5febef5 6914#ifdef TARGET_NR_msync
9de5e440 6915 case TARGET_NR_msync:
53a5960a 6916 ret = get_errno(msync(g2h(arg1), arg2, arg3));
9de5e440 6917 break;
e5febef5
TS
6918#endif
6919#ifdef TARGET_NR_mlock
9de5e440 6920 case TARGET_NR_mlock:
53a5960a 6921 ret = get_errno(mlock(g2h(arg1), arg2));
9de5e440 6922 break;
e5febef5
TS
6923#endif
6924#ifdef TARGET_NR_munlock
9de5e440 6925 case TARGET_NR_munlock:
53a5960a 6926 ret = get_errno(munlock(g2h(arg1), arg2));
9de5e440 6927 break;
e5febef5
TS
6928#endif
6929#ifdef TARGET_NR_mlockall
9de5e440 6930 case TARGET_NR_mlockall:
6f6a4032 6931 ret = get_errno(mlockall(target_to_host_mlockall_arg(arg1)));
9de5e440 6932 break;
e5febef5
TS
6933#endif
6934#ifdef TARGET_NR_munlockall
9de5e440
FB
6935 case TARGET_NR_munlockall:
6936 ret = get_errno(munlockall());
6937 break;
e5febef5 6938#endif
31e31b8a 6939 case TARGET_NR_truncate:
579a97f7
FB
6940 if (!(p = lock_user_string(arg1)))
6941 goto efault;
53a5960a
PB
6942 ret = get_errno(truncate(p, arg2));
6943 unlock_user(p, arg1, 0);
31e31b8a
FB
6944 break;
6945 case TARGET_NR_ftruncate:
6946 ret = get_errno(ftruncate(arg1, arg2));
6947 break;
6948 case TARGET_NR_fchmod:
6949 ret = get_errno(fchmod(arg1, arg2));
6950 break;
c0d472b1 6951#if defined(TARGET_NR_fchmodat)
814d7977 6952 case TARGET_NR_fchmodat:
579a97f7
FB
6953 if (!(p = lock_user_string(arg2)))
6954 goto efault;
c0d472b1 6955 ret = get_errno(fchmodat(arg1, p, arg3, 0));
579a97f7 6956 unlock_user(p, arg2, 0);
814d7977
TS
6957 break;
6958#endif
31e31b8a 6959 case TARGET_NR_getpriority:
95c09828
RH
6960 /* Note that negative values are valid for getpriority, so we must
6961 differentiate based on errno settings. */
6962 errno = 0;
6963 ret = getpriority(arg1, arg2);
6964 if (ret == -1 && errno != 0) {
6965 ret = -host_to_target_errno(errno);
6966 break;
6967 }
6968#ifdef TARGET_ALPHA
6969 /* Return value is the unbiased priority. Signal no error. */
6970 ((CPUAlphaState *)cpu_env)->ir[IR_V0] = 0;
6971#else
6972 /* Return value is a biased priority to avoid negative numbers. */
6973 ret = 20 - ret;
6974#endif
31e31b8a
FB
6975 break;
6976 case TARGET_NR_setpriority:
6977 ret = get_errno(setpriority(arg1, arg2, arg3));
6978 break;
ebc05488 6979#ifdef TARGET_NR_profil
31e31b8a
FB
6980 case TARGET_NR_profil:
6981 goto unimplemented;
ebc05488 6982#endif
31e31b8a 6983 case TARGET_NR_statfs:
579a97f7
FB
6984 if (!(p = lock_user_string(arg1)))
6985 goto efault;
53a5960a
PB
6986 ret = get_errno(statfs(path(p), &stfs));
6987 unlock_user(p, arg1, 0);
31e31b8a
FB
6988 convert_statfs:
6989 if (!is_error(ret)) {
53a5960a 6990 struct target_statfs *target_stfs;
3b46e624 6991
579a97f7
FB
6992 if (!lock_user_struct(VERIFY_WRITE, target_stfs, arg2, 0))
6993 goto efault;
6994 __put_user(stfs.f_type, &target_stfs->f_type);
6995 __put_user(stfs.f_bsize, &target_stfs->f_bsize);
6996 __put_user(stfs.f_blocks, &target_stfs->f_blocks);
6997 __put_user(stfs.f_bfree, &target_stfs->f_bfree);
6998 __put_user(stfs.f_bavail, &target_stfs->f_bavail);
6999 __put_user(stfs.f_files, &target_stfs->f_files);
7000 __put_user(stfs.f_ffree, &target_stfs->f_ffree);
7001 __put_user(stfs.f_fsid.__val[0], &target_stfs->f_fsid.val[0]);
7002 __put_user(stfs.f_fsid.__val[1], &target_stfs->f_fsid.val[1]);
7003 __put_user(stfs.f_namelen, &target_stfs->f_namelen);
229d3376
AG
7004 __put_user(stfs.f_frsize, &target_stfs->f_frsize);
7005 memset(target_stfs->f_spare, 0, sizeof(target_stfs->f_spare));
53a5960a 7006 unlock_user_struct(target_stfs, arg2, 1);
31e31b8a
FB
7007 }
7008 break;
7009 case TARGET_NR_fstatfs:
56c8f68f 7010 ret = get_errno(fstatfs(arg1, &stfs));
31e31b8a 7011 goto convert_statfs;
56c8f68f
FB
7012#ifdef TARGET_NR_statfs64
7013 case TARGET_NR_statfs64:
579a97f7
FB
7014 if (!(p = lock_user_string(arg1)))
7015 goto efault;
53a5960a
PB
7016 ret = get_errno(statfs(path(p), &stfs));
7017 unlock_user(p, arg1, 0);
56c8f68f
FB
7018 convert_statfs64:
7019 if (!is_error(ret)) {
53a5960a 7020 struct target_statfs64 *target_stfs;
3b46e624 7021
579a97f7
FB
7022 if (!lock_user_struct(VERIFY_WRITE, target_stfs, arg3, 0))
7023 goto efault;
7024 __put_user(stfs.f_type, &target_stfs->f_type);
7025 __put_user(stfs.f_bsize, &target_stfs->f_bsize);
7026 __put_user(stfs.f_blocks, &target_stfs->f_blocks);
7027 __put_user(stfs.f_bfree, &target_stfs->f_bfree);
7028 __put_user(stfs.f_bavail, &target_stfs->f_bavail);
7029 __put_user(stfs.f_files, &target_stfs->f_files);
7030 __put_user(stfs.f_ffree, &target_stfs->f_ffree);
7031 __put_user(stfs.f_fsid.__val[0], &target_stfs->f_fsid.val[0]);
7032 __put_user(stfs.f_fsid.__val[1], &target_stfs->f_fsid.val[1]);
7033 __put_user(stfs.f_namelen, &target_stfs->f_namelen);
229d3376
AG
7034 __put_user(stfs.f_frsize, &target_stfs->f_frsize);
7035 memset(target_stfs->f_spare, 0, sizeof(target_stfs->f_spare));
579a97f7 7036 unlock_user_struct(target_stfs, arg3, 1);
56c8f68f
FB
7037 }
7038 break;
7039 case TARGET_NR_fstatfs64:
7040 ret = get_errno(fstatfs(arg1, &stfs));
7041 goto convert_statfs64;
7042#endif
ebc05488 7043#ifdef TARGET_NR_ioperm
31e31b8a
FB
7044 case TARGET_NR_ioperm:
7045 goto unimplemented;
ebc05488 7046#endif
e5febef5 7047#ifdef TARGET_NR_socketcall
31e31b8a 7048 case TARGET_NR_socketcall:
53a5960a 7049 ret = do_socketcall(arg1, arg2);
31e31b8a 7050 break;
e5febef5 7051#endif
3532fa74
FB
7052#ifdef TARGET_NR_accept
7053 case TARGET_NR_accept:
a94b4987
PM
7054 ret = do_accept4(arg1, arg2, arg3, 0);
7055 break;
7056#endif
7057#ifdef TARGET_NR_accept4
7058 case TARGET_NR_accept4:
7059#ifdef CONFIG_ACCEPT4
7060 ret = do_accept4(arg1, arg2, arg3, arg4);
7061#else
7062 goto unimplemented;
7063#endif
3532fa74
FB
7064 break;
7065#endif
7066#ifdef TARGET_NR_bind
7067 case TARGET_NR_bind:
7068 ret = do_bind(arg1, arg2, arg3);
7069 break;
7070#endif
7071#ifdef TARGET_NR_connect
7072 case TARGET_NR_connect:
7073 ret = do_connect(arg1, arg2, arg3);
7074 break;
7075#endif
7076#ifdef TARGET_NR_getpeername
7077 case TARGET_NR_getpeername:
1be9e1dc 7078 ret = do_getpeername(arg1, arg2, arg3);
3532fa74
FB
7079 break;
7080#endif
7081#ifdef TARGET_NR_getsockname
7082 case TARGET_NR_getsockname:
1be9e1dc 7083 ret = do_getsockname(arg1, arg2, arg3);
3532fa74
FB
7084 break;
7085#endif
7086#ifdef TARGET_NR_getsockopt
7087 case TARGET_NR_getsockopt:
7088 ret = do_getsockopt(arg1, arg2, arg3, arg4, arg5);
7089 break;
7090#endif
7091#ifdef TARGET_NR_listen
7092 case TARGET_NR_listen:
1be9e1dc 7093 ret = get_errno(listen(arg1, arg2));
3532fa74
FB
7094 break;
7095#endif
7096#ifdef TARGET_NR_recv
7097 case TARGET_NR_recv:
214201bd 7098 ret = do_recvfrom(arg1, arg2, arg3, arg4, 0, 0);
3532fa74
FB
7099 break;
7100#endif
7101#ifdef TARGET_NR_recvfrom
7102 case TARGET_NR_recvfrom:
214201bd 7103 ret = do_recvfrom(arg1, arg2, arg3, arg4, arg5, arg6);
3532fa74
FB
7104 break;
7105#endif
7106#ifdef TARGET_NR_recvmsg
7107 case TARGET_NR_recvmsg:
7108 ret = do_sendrecvmsg(arg1, arg2, arg3, 0);
7109 break;
7110#endif
7111#ifdef TARGET_NR_send
7112 case TARGET_NR_send:
1be9e1dc 7113 ret = do_sendto(arg1, arg2, arg3, arg4, 0, 0);
3532fa74
FB
7114 break;
7115#endif
7116#ifdef TARGET_NR_sendmsg
7117 case TARGET_NR_sendmsg:
7118 ret = do_sendrecvmsg(arg1, arg2, arg3, 1);
7119 break;
7120#endif
f19e00d7
AG
7121#ifdef TARGET_NR_sendmmsg
7122 case TARGET_NR_sendmmsg:
7123 ret = do_sendrecvmmsg(arg1, arg2, arg3, arg4, 1);
7124 break;
7125 case TARGET_NR_recvmmsg:
7126 ret = do_sendrecvmmsg(arg1, arg2, arg3, arg4, 0);
7127 break;
7128#endif
3532fa74
FB
7129#ifdef TARGET_NR_sendto
7130 case TARGET_NR_sendto:
1be9e1dc 7131 ret = do_sendto(arg1, arg2, arg3, arg4, arg5, arg6);
3532fa74
FB
7132 break;
7133#endif
7134#ifdef TARGET_NR_shutdown
7135 case TARGET_NR_shutdown:
1be9e1dc 7136 ret = get_errno(shutdown(arg1, arg2));
3532fa74
FB
7137 break;
7138#endif
7139#ifdef TARGET_NR_socket
7140 case TARGET_NR_socket:
7141 ret = do_socket(arg1, arg2, arg3);
7142 break;
7143#endif
7144#ifdef TARGET_NR_socketpair
7145 case TARGET_NR_socketpair:
1be9e1dc 7146 ret = do_socketpair(arg1, arg2, arg3, arg4);
3532fa74
FB
7147 break;
7148#endif
7149#ifdef TARGET_NR_setsockopt
7150 case TARGET_NR_setsockopt:
7151 ret = do_setsockopt(arg1, arg2, arg3, arg4, (socklen_t) arg5);
7152 break;
7153#endif
7494b0f9 7154
31e31b8a 7155 case TARGET_NR_syslog:
579a97f7
FB
7156 if (!(p = lock_user_string(arg2)))
7157 goto efault;
e5574487
TS
7158 ret = get_errno(sys_syslog((int)arg1, p, (int)arg3));
7159 unlock_user(p, arg2, 0);
7494b0f9
TS
7160 break;
7161
31e31b8a 7162 case TARGET_NR_setitimer:
66fb9763 7163 {
66fb9763
FB
7164 struct itimerval value, ovalue, *pvalue;
7165
53a5960a 7166 if (arg2) {
66fb9763 7167 pvalue = &value;
788f5ec4
TS
7168 if (copy_from_user_timeval(&pvalue->it_interval, arg2)
7169 || copy_from_user_timeval(&pvalue->it_value,
7170 arg2 + sizeof(struct target_timeval)))
7171 goto efault;
66fb9763
FB
7172 } else {
7173 pvalue = NULL;
7174 }
7175 ret = get_errno(setitimer(arg1, pvalue, &ovalue));
53a5960a 7176 if (!is_error(ret) && arg3) {
788f5ec4
TS
7177 if (copy_to_user_timeval(arg3,
7178 &ovalue.it_interval)
7179 || copy_to_user_timeval(arg3 + sizeof(struct target_timeval),
7180 &ovalue.it_value))
7181 goto efault;
66fb9763
FB
7182 }
7183 }
7184 break;
31e31b8a 7185 case TARGET_NR_getitimer:
66fb9763 7186 {
66fb9763 7187 struct itimerval value;
3b46e624 7188
66fb9763 7189 ret = get_errno(getitimer(arg1, &value));
53a5960a 7190 if (!is_error(ret) && arg2) {
788f5ec4
TS
7191 if (copy_to_user_timeval(arg2,
7192 &value.it_interval)
7193 || copy_to_user_timeval(arg2 + sizeof(struct target_timeval),
7194 &value.it_value))
7195 goto efault;
66fb9763
FB
7196 }
7197 }
7198 break;
31e31b8a 7199 case TARGET_NR_stat:
579a97f7
FB
7200 if (!(p = lock_user_string(arg1)))
7201 goto efault;
53a5960a
PB
7202 ret = get_errno(stat(path(p), &st));
7203 unlock_user(p, arg1, 0);
31e31b8a
FB
7204 goto do_stat;
7205 case TARGET_NR_lstat:
579a97f7
FB
7206 if (!(p = lock_user_string(arg1)))
7207 goto efault;
53a5960a
PB
7208 ret = get_errno(lstat(path(p), &st));
7209 unlock_user(p, arg1, 0);
31e31b8a
FB
7210 goto do_stat;
7211 case TARGET_NR_fstat:
7212 {
7213 ret = get_errno(fstat(arg1, &st));
7214 do_stat:
7215 if (!is_error(ret)) {
53a5960a 7216 struct target_stat *target_st;
e3584658 7217
579a97f7
FB
7218 if (!lock_user_struct(VERIFY_WRITE, target_st, arg2, 0))
7219 goto efault;
12727917 7220 memset(target_st, 0, sizeof(*target_st));
d2fd1af7
FB
7221 __put_user(st.st_dev, &target_st->st_dev);
7222 __put_user(st.st_ino, &target_st->st_ino);
7223 __put_user(st.st_mode, &target_st->st_mode);
7224 __put_user(st.st_uid, &target_st->st_uid);
7225 __put_user(st.st_gid, &target_st->st_gid);
7226 __put_user(st.st_nlink, &target_st->st_nlink);
7227 __put_user(st.st_rdev, &target_st->st_rdev);
7228 __put_user(st.st_size, &target_st->st_size);
7229 __put_user(st.st_blksize, &target_st->st_blksize);
7230 __put_user(st.st_blocks, &target_st->st_blocks);
7231 __put_user(st.st_atime, &target_st->target_st_atime);
7232 __put_user(st.st_mtime, &target_st->target_st_mtime);
7233 __put_user(st.st_ctime, &target_st->target_st_ctime);
53a5960a 7234 unlock_user_struct(target_st, arg2, 1);
31e31b8a
FB
7235 }
7236 }
7237 break;
ebc05488 7238#ifdef TARGET_NR_olduname
31e31b8a
FB
7239 case TARGET_NR_olduname:
7240 goto unimplemented;
ebc05488
FB
7241#endif
7242#ifdef TARGET_NR_iopl
31e31b8a
FB
7243 case TARGET_NR_iopl:
7244 goto unimplemented;
ebc05488 7245#endif
31e31b8a
FB
7246 case TARGET_NR_vhangup:
7247 ret = get_errno(vhangup());
7248 break;
ebc05488 7249#ifdef TARGET_NR_idle
31e31b8a
FB
7250 case TARGET_NR_idle:
7251 goto unimplemented;
42ad6ae9
FB
7252#endif
7253#ifdef TARGET_NR_syscall
7254 case TARGET_NR_syscall:
5945cfcb
PM
7255 ret = do_syscall(cpu_env, arg1 & 0xffff, arg2, arg3, arg4, arg5,
7256 arg6, arg7, arg8, 0);
7257 break;
ebc05488 7258#endif
31e31b8a
FB
7259 case TARGET_NR_wait4:
7260 {
7261 int status;
992f48a0 7262 abi_long status_ptr = arg2;
31e31b8a 7263 struct rusage rusage, *rusage_ptr;
992f48a0 7264 abi_ulong target_rusage = arg4;
a39fb273 7265 abi_long rusage_err;
31e31b8a
FB
7266 if (target_rusage)
7267 rusage_ptr = &rusage;
7268 else
7269 rusage_ptr = NULL;
7270 ret = get_errno(wait4(arg1, &status, arg3, rusage_ptr));
7271 if (!is_error(ret)) {
5379557b 7272 if (status_ptr && ret) {
1d9d8b55 7273 status = host_to_target_waitstatus(status);
2f619698
FB
7274 if (put_user_s32(status, status_ptr))
7275 goto efault;
31e31b8a 7276 }
a39fb273
PJ
7277 if (target_rusage) {
7278 rusage_err = host_to_target_rusage(target_rusage, &rusage);
7279 if (rusage_err) {
7280 ret = rusage_err;
7281 }
7282 }
31e31b8a
FB
7283 }
7284 }
7285 break;
e5febef5 7286#ifdef TARGET_NR_swapoff
31e31b8a 7287 case TARGET_NR_swapoff:
579a97f7
FB
7288 if (!(p = lock_user_string(arg1)))
7289 goto efault;
53a5960a
PB
7290 ret = get_errno(swapoff(p));
7291 unlock_user(p, arg1, 0);
31e31b8a 7292 break;
e5febef5 7293#endif
31e31b8a 7294 case TARGET_NR_sysinfo:
a5448a7d 7295 {
53a5960a 7296 struct target_sysinfo *target_value;
a5448a7d
FB
7297 struct sysinfo value;
7298 ret = get_errno(sysinfo(&value));
53a5960a 7299 if (!is_error(ret) && arg1)
a5448a7d 7300 {
579a97f7
FB
7301 if (!lock_user_struct(VERIFY_WRITE, target_value, arg1, 0))
7302 goto efault;
a5448a7d
FB
7303 __put_user(value.uptime, &target_value->uptime);
7304 __put_user(value.loads[0], &target_value->loads[0]);
7305 __put_user(value.loads[1], &target_value->loads[1]);
7306 __put_user(value.loads[2], &target_value->loads[2]);
7307 __put_user(value.totalram, &target_value->totalram);
7308 __put_user(value.freeram, &target_value->freeram);
7309 __put_user(value.sharedram, &target_value->sharedram);
7310 __put_user(value.bufferram, &target_value->bufferram);
7311 __put_user(value.totalswap, &target_value->totalswap);
7312 __put_user(value.freeswap, &target_value->freeswap);
7313 __put_user(value.procs, &target_value->procs);
7314 __put_user(value.totalhigh, &target_value->totalhigh);
7315 __put_user(value.freehigh, &target_value->freehigh);
7316 __put_user(value.mem_unit, &target_value->mem_unit);
53a5960a 7317 unlock_user_struct(target_value, arg1, 1);
a5448a7d
FB
7318 }
7319 }
7320 break;
e5febef5 7321#ifdef TARGET_NR_ipc
31e31b8a 7322 case TARGET_NR_ipc:
8853f86e
FB
7323 ret = do_ipc(arg1, arg2, arg3, arg4, arg5, arg6);
7324 break;
e5febef5 7325#endif
e5289087
AJ
7326#ifdef TARGET_NR_semget
7327 case TARGET_NR_semget:
7328 ret = get_errno(semget(arg1, arg2, arg3));
7329 break;
7330#endif
7331#ifdef TARGET_NR_semop
7332 case TARGET_NR_semop:
c7128c9f 7333 ret = do_semop(arg1, arg2, arg3);
e5289087
AJ
7334 break;
7335#endif
7336#ifdef TARGET_NR_semctl
7337 case TARGET_NR_semctl:
7338 ret = do_semctl(arg1, arg2, arg3, (union target_semun)(abi_ulong)arg4);
7339 break;
7340#endif
eeb438c1
AJ
7341#ifdef TARGET_NR_msgctl
7342 case TARGET_NR_msgctl:
7343 ret = do_msgctl(arg1, arg2, arg3);
7344 break;
7345#endif
7346#ifdef TARGET_NR_msgget
7347 case TARGET_NR_msgget:
7348 ret = get_errno(msgget(arg1, arg2));
7349 break;
7350#endif
7351#ifdef TARGET_NR_msgrcv
7352 case TARGET_NR_msgrcv:
7353 ret = do_msgrcv(arg1, arg2, arg3, arg4, arg5);
7354 break;
7355#endif
7356#ifdef TARGET_NR_msgsnd
7357 case TARGET_NR_msgsnd:
7358 ret = do_msgsnd(arg1, arg2, arg3, arg4);
7359 break;
88a8c984
RV
7360#endif
7361#ifdef TARGET_NR_shmget
7362 case TARGET_NR_shmget:
7363 ret = get_errno(shmget(arg1, arg2, arg3));
7364 break;
7365#endif
7366#ifdef TARGET_NR_shmctl
7367 case TARGET_NR_shmctl:
7368 ret = do_shmctl(arg1, arg2, arg3);
7369 break;
7370#endif
7371#ifdef TARGET_NR_shmat
7372 case TARGET_NR_shmat:
7373 ret = do_shmat(arg1, arg2, arg3);
7374 break;
7375#endif
7376#ifdef TARGET_NR_shmdt
7377 case TARGET_NR_shmdt:
7378 ret = do_shmdt(arg1);
7379 break;
eeb438c1 7380#endif
31e31b8a
FB
7381 case TARGET_NR_fsync:
7382 ret = get_errno(fsync(arg1));
7383 break;
31e31b8a 7384 case TARGET_NR_clone:
4ce6243d
PM
7385 /* Linux manages to have three different orderings for its
7386 * arguments to clone(); the BACKWARDS and BACKWARDS2 defines
7387 * match the kernel's CONFIG_CLONE_* settings.
7388 * Microblaze is further special in that it uses a sixth
7389 * implicit argument to clone for the TLS pointer.
7390 */
7391#if defined(TARGET_MICROBLAZE)
a5b3bdcb 7392 ret = get_errno(do_fork(cpu_env, arg1, arg2, arg4, arg6, arg5));
4ce6243d
PM
7393#elif defined(TARGET_CLONE_BACKWARDS)
7394 ret = get_errno(do_fork(cpu_env, arg1, arg2, arg3, arg4, arg5));
7395#elif defined(TARGET_CLONE_BACKWARDS2)
a4c075f1 7396 ret = get_errno(do_fork(cpu_env, arg2, arg1, arg3, arg5, arg4));
0b6d3ae0 7397#else
4ce6243d 7398 ret = get_errno(do_fork(cpu_env, arg1, arg2, arg3, arg5, arg4));
0b6d3ae0 7399#endif
1b6b029e 7400 break;
ec86b0fb
FB
7401#ifdef __NR_exit_group
7402 /* new thread calls */
7403 case TARGET_NR_exit_group:
9788c9ca 7404#ifdef TARGET_GPROF
6d946cda
AJ
7405 _mcleanup();
7406#endif
e9009676 7407 gdb_exit(cpu_env, arg1);
ec86b0fb
FB
7408 ret = get_errno(exit_group(arg1));
7409 break;
7410#endif
31e31b8a 7411 case TARGET_NR_setdomainname:
579a97f7
FB
7412 if (!(p = lock_user_string(arg1)))
7413 goto efault;
53a5960a
PB
7414 ret = get_errno(setdomainname(p, arg2));
7415 unlock_user(p, arg1, 0);
31e31b8a
FB
7416 break;
7417 case TARGET_NR_uname:
7418 /* no need to transcode because we use the linux syscall */
29e619b1
FB
7419 {
7420 struct new_utsname * buf;
3b46e624 7421
579a97f7
FB
7422 if (!lock_user_struct(VERIFY_WRITE, buf, arg1, 0))
7423 goto efault;
29e619b1
FB
7424 ret = get_errno(sys_uname(buf));
7425 if (!is_error(ret)) {
7426 /* Overrite the native machine name with whatever is being
7427 emulated. */
da79030f 7428 strcpy (buf->machine, cpu_to_uname_machine(cpu_env));
c5937220
PB
7429 /* Allow the user to override the reported release. */
7430 if (qemu_uname_release && *qemu_uname_release)
7431 strcpy (buf->release, qemu_uname_release);
29e619b1 7432 }
53a5960a 7433 unlock_user_struct(buf, arg1, 1);
29e619b1 7434 }
31e31b8a 7435 break;
6dbad63e 7436#ifdef TARGET_I386
31e31b8a 7437 case TARGET_NR_modify_ldt:
03acab66 7438 ret = do_modify_ldt(cpu_env, arg1, arg2, arg3);
5cd4393b 7439 break;
84409ddb 7440#if !defined(TARGET_X86_64)
5cd4393b
FB
7441 case TARGET_NR_vm86old:
7442 goto unimplemented;
7443 case TARGET_NR_vm86:
53a5960a 7444 ret = do_vm86(cpu_env, arg1, arg2);
6dbad63e 7445 break;
84409ddb 7446#endif
6dbad63e 7447#endif
31e31b8a
FB
7448 case TARGET_NR_adjtimex:
7449 goto unimplemented;
e5febef5 7450#ifdef TARGET_NR_create_module
31e31b8a 7451 case TARGET_NR_create_module:
e5febef5 7452#endif
31e31b8a
FB
7453 case TARGET_NR_init_module:
7454 case TARGET_NR_delete_module:
e5febef5 7455#ifdef TARGET_NR_get_kernel_syms
31e31b8a 7456 case TARGET_NR_get_kernel_syms:
e5febef5 7457#endif
31e31b8a
FB
7458 goto unimplemented;
7459 case TARGET_NR_quotactl:
7460 goto unimplemented;
7461 case TARGET_NR_getpgid:
7462 ret = get_errno(getpgid(arg1));
7463 break;
7464 case TARGET_NR_fchdir:
7465 ret = get_errno(fchdir(arg1));
7466 break;
84409ddb 7467#ifdef TARGET_NR_bdflush /* not on x86_64 */
31e31b8a
FB
7468 case TARGET_NR_bdflush:
7469 goto unimplemented;
84409ddb 7470#endif
e5febef5 7471#ifdef TARGET_NR_sysfs
31e31b8a
FB
7472 case TARGET_NR_sysfs:
7473 goto unimplemented;
e5febef5 7474#endif
31e31b8a 7475 case TARGET_NR_personality:
1b6b029e 7476 ret = get_errno(personality(arg1));
31e31b8a 7477 break;
e5febef5 7478#ifdef TARGET_NR_afs_syscall
31e31b8a
FB
7479 case TARGET_NR_afs_syscall:
7480 goto unimplemented;
e5febef5 7481#endif
7a3148a9 7482#ifdef TARGET_NR__llseek /* Not on alpha */
31e31b8a
FB
7483 case TARGET_NR__llseek:
7484 {
0c1592d9 7485 int64_t res;
d35b261c 7486#if !defined(__NR_llseek)
0c1592d9
PM
7487 res = lseek(arg1, ((uint64_t)arg2 << 32) | arg3, arg5);
7488 if (res == -1) {
7489 ret = get_errno(res);
7490 } else {
7491 ret = 0;
7492 }
4f2ac237 7493#else
31e31b8a 7494 ret = get_errno(_llseek(arg1, arg2, arg3, &res, arg5));
4f2ac237 7495#endif
0c1592d9
PM
7496 if ((ret == 0) && put_user_s64(res, arg4)) {
7497 goto efault;
7498 }
31e31b8a
FB
7499 }
7500 break;
7a3148a9 7501#endif
31e31b8a 7502 case TARGET_NR_getdents:
3307e236 7503#ifdef __NR_getdents
d83c8733 7504#if TARGET_ABI_BITS == 32 && HOST_LONG_BITS == 64
4add45b4 7505 {
53a5960a 7506 struct target_dirent *target_dirp;
6556a833 7507 struct linux_dirent *dirp;
992f48a0 7508 abi_long count = arg3;
4add45b4
FB
7509
7510 dirp = malloc(count);
0da46a6e 7511 if (!dirp) {
579a97f7 7512 ret = -TARGET_ENOMEM;
0da46a6e
TS
7513 goto fail;
7514 }
3b46e624 7515
4add45b4
FB
7516 ret = get_errno(sys_getdents(arg1, dirp, count));
7517 if (!is_error(ret)) {
6556a833 7518 struct linux_dirent *de;
4add45b4
FB
7519 struct target_dirent *tde;
7520 int len = ret;
7521 int reclen, treclen;
7522 int count1, tnamelen;
7523
7524 count1 = 0;
7525 de = dirp;
579a97f7
FB
7526 if (!(target_dirp = lock_user(VERIFY_WRITE, arg2, count, 0)))
7527 goto efault;
4add45b4
FB
7528 tde = target_dirp;
7529 while (len > 0) {
7530 reclen = de->d_reclen;
333858b7
DL
7531 tnamelen = reclen - offsetof(struct linux_dirent, d_name);
7532 assert(tnamelen >= 0);
7533 treclen = tnamelen + offsetof(struct target_dirent, d_name);
7534 assert(count1 + treclen <= count);
4add45b4 7535 tde->d_reclen = tswap16(treclen);
cbb21eed
MB
7536 tde->d_ino = tswapal(de->d_ino);
7537 tde->d_off = tswapal(de->d_off);
333858b7 7538 memcpy(tde->d_name, de->d_name, tnamelen);
6556a833 7539 de = (struct linux_dirent *)((char *)de + reclen);
4add45b4 7540 len -= reclen;
1c5bf3bf 7541 tde = (struct target_dirent *)((char *)tde + treclen);
4add45b4
FB
7542 count1 += treclen;
7543 }
7544 ret = count1;
579a97f7 7545 unlock_user(target_dirp, arg2, ret);
4add45b4
FB
7546 }
7547 free(dirp);
7548 }
7549#else
31e31b8a 7550 {
6556a833 7551 struct linux_dirent *dirp;
992f48a0 7552 abi_long count = arg3;
dab2ed99 7553
579a97f7
FB
7554 if (!(dirp = lock_user(VERIFY_WRITE, arg2, count, 0)))
7555 goto efault;
72f03900 7556 ret = get_errno(sys_getdents(arg1, dirp, count));
31e31b8a 7557 if (!is_error(ret)) {
6556a833 7558 struct linux_dirent *de;
31e31b8a
FB
7559 int len = ret;
7560 int reclen;
7561 de = dirp;
7562 while (len > 0) {
8083a3e5 7563 reclen = de->d_reclen;
31e31b8a
FB
7564 if (reclen > len)
7565 break;
8083a3e5 7566 de->d_reclen = tswap16(reclen);
31e31b8a
FB
7567 tswapls(&de->d_ino);
7568 tswapls(&de->d_off);
6556a833 7569 de = (struct linux_dirent *)((char *)de + reclen);
31e31b8a
FB
7570 len -= reclen;
7571 }
7572 }
53a5960a 7573 unlock_user(dirp, arg2, ret);
3307e236
PM
7574 }
7575#endif
7576#else
7577 /* Implement getdents in terms of getdents64 */
7578 {
7579 struct linux_dirent64 *dirp;
7580 abi_long count = arg3;
7581
7582 dirp = lock_user(VERIFY_WRITE, arg2, count, 0);
7583 if (!dirp) {
7584 goto efault;
7585 }
7586 ret = get_errno(sys_getdents64(arg1, dirp, count));
7587 if (!is_error(ret)) {
7588 /* Convert the dirent64 structs to target dirent. We do this
7589 * in-place, since we can guarantee that a target_dirent is no
7590 * larger than a dirent64; however this means we have to be
7591 * careful to read everything before writing in the new format.
7592 */
7593 struct linux_dirent64 *de;
7594 struct target_dirent *tde;
7595 int len = ret;
7596 int tlen = 0;
7597
7598 de = dirp;
7599 tde = (struct target_dirent *)dirp;
7600 while (len > 0) {
7601 int namelen, treclen;
7602 int reclen = de->d_reclen;
7603 uint64_t ino = de->d_ino;
7604 int64_t off = de->d_off;
7605 uint8_t type = de->d_type;
7606
7607 namelen = strlen(de->d_name);
7608 treclen = offsetof(struct target_dirent, d_name)
7609 + namelen + 2;
7610 treclen = QEMU_ALIGN_UP(treclen, sizeof(abi_long));
7611
7612 memmove(tde->d_name, de->d_name, namelen + 1);
7613 tde->d_ino = tswapal(ino);
7614 tde->d_off = tswapal(off);
7615 tde->d_reclen = tswap16(treclen);
7616 /* The target_dirent type is in what was formerly a padding
7617 * byte at the end of the structure:
7618 */
7619 *(((char *)tde) + treclen - 1) = type;
7620
7621 de = (struct linux_dirent64 *)((char *)de + reclen);
7622 tde = (struct target_dirent *)((char *)tde + treclen);
7623 len -= reclen;
7624 tlen += treclen;
7625 }
7626 ret = tlen;
7627 }
7628 unlock_user(dirp, arg2, ret);
31e31b8a 7629 }
4add45b4 7630#endif
31e31b8a 7631 break;
3ae43202 7632#if defined(TARGET_NR_getdents64) && defined(__NR_getdents64)
dab2ed99
FB
7633 case TARGET_NR_getdents64:
7634 {
6556a833 7635 struct linux_dirent64 *dirp;
992f48a0 7636 abi_long count = arg3;
579a97f7
FB
7637 if (!(dirp = lock_user(VERIFY_WRITE, arg2, count, 0)))
7638 goto efault;
dab2ed99
FB
7639 ret = get_errno(sys_getdents64(arg1, dirp, count));
7640 if (!is_error(ret)) {
6556a833 7641 struct linux_dirent64 *de;
dab2ed99
FB
7642 int len = ret;
7643 int reclen;
7644 de = dirp;
7645 while (len > 0) {
8083a3e5 7646 reclen = de->d_reclen;
dab2ed99
FB
7647 if (reclen > len)
7648 break;
8083a3e5 7649 de->d_reclen = tswap16(reclen);
8582a53a
FB
7650 tswap64s((uint64_t *)&de->d_ino);
7651 tswap64s((uint64_t *)&de->d_off);
6556a833 7652 de = (struct linux_dirent64 *)((char *)de + reclen);
dab2ed99
FB
7653 len -= reclen;
7654 }
7655 }
53a5960a 7656 unlock_user(dirp, arg2, ret);
dab2ed99
FB
7657 }
7658 break;
a541f297 7659#endif /* TARGET_NR_getdents64 */
9468a5d4 7660#if defined(TARGET_NR__newselect)
31e31b8a 7661 case TARGET_NR__newselect:
53a5960a 7662 ret = do_select(arg1, arg2, arg3, arg4, arg5);
31e31b8a 7663 break;
e5febef5 7664#endif
d8035d4c
MF
7665#if defined(TARGET_NR_poll) || defined(TARGET_NR_ppoll)
7666# ifdef TARGET_NR_poll
9de5e440 7667 case TARGET_NR_poll:
d8035d4c
MF
7668# endif
7669# ifdef TARGET_NR_ppoll
7670 case TARGET_NR_ppoll:
7671# endif
9de5e440 7672 {
53a5960a 7673 struct target_pollfd *target_pfd;
9de5e440
FB
7674 unsigned int nfds = arg2;
7675 int timeout = arg3;
7676 struct pollfd *pfd;
7854b056 7677 unsigned int i;
9de5e440 7678
579a97f7
FB
7679 target_pfd = lock_user(VERIFY_WRITE, arg1, sizeof(struct target_pollfd) * nfds, 1);
7680 if (!target_pfd)
7681 goto efault;
d8035d4c 7682
9de5e440
FB
7683 pfd = alloca(sizeof(struct pollfd) * nfds);
7684 for(i = 0; i < nfds; i++) {
5cd4393b
FB
7685 pfd[i].fd = tswap32(target_pfd[i].fd);
7686 pfd[i].events = tswap16(target_pfd[i].events);
9de5e440 7687 }
d8035d4c
MF
7688
7689# ifdef TARGET_NR_ppoll
7690 if (num == TARGET_NR_ppoll) {
7691 struct timespec _timeout_ts, *timeout_ts = &_timeout_ts;
7692 target_sigset_t *target_set;
7693 sigset_t _set, *set = &_set;
7694
7695 if (arg3) {
7696 if (target_to_host_timespec(timeout_ts, arg3)) {
7697 unlock_user(target_pfd, arg1, 0);
7698 goto efault;
7699 }
7700 } else {
7701 timeout_ts = NULL;
7702 }
7703
7704 if (arg4) {
7705 target_set = lock_user(VERIFY_READ, arg4, sizeof(target_sigset_t), 1);
7706 if (!target_set) {
7707 unlock_user(target_pfd, arg1, 0);
7708 goto efault;
7709 }
7710 target_to_host_sigset(set, target_set);
7711 } else {
7712 set = NULL;
7713 }
7714
7715 ret = get_errno(sys_ppoll(pfd, nfds, timeout_ts, set, _NSIG/8));
7716
7717 if (!is_error(ret) && arg3) {
7718 host_to_target_timespec(arg3, timeout_ts);
7719 }
7720 if (arg4) {
7721 unlock_user(target_set, arg4, 0);
7722 }
7723 } else
7724# endif
7725 ret = get_errno(poll(pfd, nfds, timeout));
7726
9de5e440
FB
7727 if (!is_error(ret)) {
7728 for(i = 0; i < nfds; i++) {
5cd4393b 7729 target_pfd[i].revents = tswap16(pfd[i].revents);
9de5e440
FB
7730 }
7731 }
30cb4cde 7732 unlock_user(target_pfd, arg1, sizeof(struct target_pollfd) * nfds);
9de5e440
FB
7733 }
7734 break;
e5febef5 7735#endif
31e31b8a 7736 case TARGET_NR_flock:
9de5e440
FB
7737 /* NOTE: the flock constant seems to be the same for every
7738 Linux platform */
7739 ret = get_errno(flock(arg1, arg2));
31e31b8a
FB
7740 break;
7741 case TARGET_NR_readv:
7742 {
f287b2c2
RH
7743 struct iovec *vec = lock_iovec(VERIFY_WRITE, arg2, arg3, 0);
7744 if (vec != NULL) {
7745 ret = get_errno(readv(arg1, vec, arg3));
7746 unlock_iovec(vec, arg2, arg3, 1);
7747 } else {
7748 ret = -host_to_target_errno(errno);
7749 }
31e31b8a
FB
7750 }
7751 break;
7752 case TARGET_NR_writev:
7753 {
f287b2c2
RH
7754 struct iovec *vec = lock_iovec(VERIFY_READ, arg2, arg3, 1);
7755 if (vec != NULL) {
7756 ret = get_errno(writev(arg1, vec, arg3));
7757 unlock_iovec(vec, arg2, arg3, 0);
7758 } else {
7759 ret = -host_to_target_errno(errno);
7760 }
31e31b8a
FB
7761 }
7762 break;
7763 case TARGET_NR_getsid:
7764 ret = get_errno(getsid(arg1));
7765 break;
7a3148a9 7766#if defined(TARGET_NR_fdatasync) /* Not on alpha (osf_datasync ?) */
31e31b8a 7767 case TARGET_NR_fdatasync:
5cd4393b
FB
7768 ret = get_errno(fdatasync(arg1));
7769 break;
7a3148a9 7770#endif
31e31b8a 7771 case TARGET_NR__sysctl:
0da46a6e 7772 /* We don't implement this, but ENOTDIR is always a safe
29e619b1 7773 return value. */
0da46a6e
TS
7774 ret = -TARGET_ENOTDIR;
7775 break;
737de1d1
MF
7776 case TARGET_NR_sched_getaffinity:
7777 {
7778 unsigned int mask_size;
7779 unsigned long *mask;
7780
7781 /*
7782 * sched_getaffinity needs multiples of ulong, so need to take
7783 * care of mismatches between target ulong and host ulong sizes.
7784 */
7785 if (arg2 & (sizeof(abi_ulong) - 1)) {
7786 ret = -TARGET_EINVAL;
7787 break;
7788 }
7789 mask_size = (arg2 + (sizeof(*mask) - 1)) & ~(sizeof(*mask) - 1);
7790
7791 mask = alloca(mask_size);
7792 ret = get_errno(sys_sched_getaffinity(arg1, mask_size, mask));
7793
7794 if (!is_error(ret)) {
be3bd286
PM
7795 if (ret > arg2) {
7796 /* More data returned than the caller's buffer will fit.
7797 * This only happens if sizeof(abi_long) < sizeof(long)
7798 * and the caller passed us a buffer holding an odd number
7799 * of abi_longs. If the host kernel is actually using the
7800 * extra 4 bytes then fail EINVAL; otherwise we can just
7801 * ignore them and only copy the interesting part.
7802 */
7803 int numcpus = sysconf(_SC_NPROCESSORS_CONF);
7804 if (numcpus > arg2 * 8) {
7805 ret = -TARGET_EINVAL;
7806 break;
7807 }
7808 ret = arg2;
7809 }
7810
cd18f05e 7811 if (copy_to_user(arg3, mask, ret)) {
737de1d1
MF
7812 goto efault;
7813 }
737de1d1
MF
7814 }
7815 }
7816 break;
7817 case TARGET_NR_sched_setaffinity:
7818 {
7819 unsigned int mask_size;
7820 unsigned long *mask;
7821
7822 /*
7823 * sched_setaffinity needs multiples of ulong, so need to take
7824 * care of mismatches between target ulong and host ulong sizes.
7825 */
7826 if (arg2 & (sizeof(abi_ulong) - 1)) {
7827 ret = -TARGET_EINVAL;
7828 break;
7829 }
7830 mask_size = (arg2 + (sizeof(*mask) - 1)) & ~(sizeof(*mask) - 1);
7831
7832 mask = alloca(mask_size);
7833 if (!lock_user_struct(VERIFY_READ, p, arg3, 1)) {
7834 goto efault;
7835 }
7836 memcpy(mask, p, arg2);
7837 unlock_user_struct(p, arg2, 0);
7838
7839 ret = get_errno(sys_sched_setaffinity(arg1, mask_size, mask));
7840 }
7841 break;
31e31b8a 7842 case TARGET_NR_sched_setparam:
5cd4393b 7843 {
53a5960a 7844 struct sched_param *target_schp;
5cd4393b 7845 struct sched_param schp;
53a5960a 7846
a1d5c5b2
TM
7847 if (arg2 == 0) {
7848 return -TARGET_EINVAL;
7849 }
579a97f7
FB
7850 if (!lock_user_struct(VERIFY_READ, target_schp, arg2, 1))
7851 goto efault;
5cd4393b 7852 schp.sched_priority = tswap32(target_schp->sched_priority);
53a5960a 7853 unlock_user_struct(target_schp, arg2, 0);
5cd4393b
FB
7854 ret = get_errno(sched_setparam(arg1, &schp));
7855 }
7856 break;
31e31b8a 7857 case TARGET_NR_sched_getparam:
5cd4393b 7858 {
53a5960a 7859 struct sched_param *target_schp;
5cd4393b 7860 struct sched_param schp;
a1d5c5b2
TM
7861
7862 if (arg2 == 0) {
7863 return -TARGET_EINVAL;
7864 }
5cd4393b
FB
7865 ret = get_errno(sched_getparam(arg1, &schp));
7866 if (!is_error(ret)) {
579a97f7
FB
7867 if (!lock_user_struct(VERIFY_WRITE, target_schp, arg2, 0))
7868 goto efault;
5cd4393b 7869 target_schp->sched_priority = tswap32(schp.sched_priority);
53a5960a 7870 unlock_user_struct(target_schp, arg2, 1);
5cd4393b
FB
7871 }
7872 }
7873 break;
31e31b8a 7874 case TARGET_NR_sched_setscheduler:
5cd4393b 7875 {
53a5960a 7876 struct sched_param *target_schp;
5cd4393b 7877 struct sched_param schp;
a1d5c5b2
TM
7878 if (arg3 == 0) {
7879 return -TARGET_EINVAL;
7880 }
579a97f7
FB
7881 if (!lock_user_struct(VERIFY_READ, target_schp, arg3, 1))
7882 goto efault;
5cd4393b 7883 schp.sched_priority = tswap32(target_schp->sched_priority);
53a5960a 7884 unlock_user_struct(target_schp, arg3, 0);
5cd4393b
FB
7885 ret = get_errno(sched_setscheduler(arg1, arg2, &schp));
7886 }
7887 break;
31e31b8a 7888 case TARGET_NR_sched_getscheduler:
5cd4393b
FB
7889 ret = get_errno(sched_getscheduler(arg1));
7890 break;
31e31b8a
FB
7891 case TARGET_NR_sched_yield:
7892 ret = get_errno(sched_yield());
7893 break;
7894 case TARGET_NR_sched_get_priority_max:
5cd4393b
FB
7895 ret = get_errno(sched_get_priority_max(arg1));
7896 break;
31e31b8a 7897 case TARGET_NR_sched_get_priority_min:
5cd4393b
FB
7898 ret = get_errno(sched_get_priority_min(arg1));
7899 break;
31e31b8a 7900 case TARGET_NR_sched_rr_get_interval:
5cd4393b 7901 {
5cd4393b
FB
7902 struct timespec ts;
7903 ret = get_errno(sched_rr_get_interval(arg1, &ts));
7904 if (!is_error(ret)) {
d4290c40 7905 ret = host_to_target_timespec(arg2, &ts);
5cd4393b
FB
7906 }
7907 }
7908 break;
31e31b8a 7909 case TARGET_NR_nanosleep:
1b6b029e 7910 {
1b6b029e 7911 struct timespec req, rem;
53a5960a 7912 target_to_host_timespec(&req, arg1);
1b6b029e 7913 ret = get_errno(nanosleep(&req, &rem));
53a5960a
PB
7914 if (is_error(ret) && arg2) {
7915 host_to_target_timespec(arg2, &rem);
1b6b029e
FB
7916 }
7917 }
7918 break;
e5febef5 7919#ifdef TARGET_NR_query_module
31e31b8a 7920 case TARGET_NR_query_module:
5cd4393b 7921 goto unimplemented;
e5febef5
TS
7922#endif
7923#ifdef TARGET_NR_nfsservctl
31e31b8a 7924 case TARGET_NR_nfsservctl:
5cd4393b 7925 goto unimplemented;
e5febef5 7926#endif
31e31b8a 7927 case TARGET_NR_prctl:
1e6722f8
PM
7928 switch (arg1) {
7929 case PR_GET_PDEATHSIG:
7930 {
7931 int deathsig;
7932 ret = get_errno(prctl(arg1, &deathsig, arg3, arg4, arg5));
7933 if (!is_error(ret) && arg2
7934 && put_user_ual(deathsig, arg2)) {
7935 goto efault;
e5574487 7936 }
1e6722f8
PM
7937 break;
7938 }
db9526b1
PM
7939#ifdef PR_GET_NAME
7940 case PR_GET_NAME:
7941 {
7942 void *name = lock_user(VERIFY_WRITE, arg2, 16, 1);
7943 if (!name) {
7944 goto efault;
7945 }
7946 ret = get_errno(prctl(arg1, (unsigned long)name,
7947 arg3, arg4, arg5));
7948 unlock_user(name, arg2, 16);
7949 break;
7950 }
7951 case PR_SET_NAME:
7952 {
7953 void *name = lock_user(VERIFY_READ, arg2, 16, 1);
7954 if (!name) {
7955 goto efault;
7956 }
7957 ret = get_errno(prctl(arg1, (unsigned long)name,
7958 arg3, arg4, arg5));
7959 unlock_user(name, arg2, 0);
7960 break;
7961 }
7962#endif
1e6722f8
PM
7963 default:
7964 /* Most prctl options have no pointer arguments */
7965 ret = get_errno(prctl(arg1, arg2, arg3, arg4, arg5));
7966 break;
7967 }
39b9aae1 7968 break;
d2fd1af7
FB
7969#ifdef TARGET_NR_arch_prctl
7970 case TARGET_NR_arch_prctl:
7971#if defined(TARGET_I386) && !defined(TARGET_ABI32)
7972 ret = do_arch_prctl(cpu_env, arg1, arg2);
7973 break;
7974#else
7975 goto unimplemented;
7976#endif
7977#endif
f2c7ba15
AJ
7978#ifdef TARGET_NR_pread64
7979 case TARGET_NR_pread64:
ae017a5b
AG
7980 if (regpairs_aligned(cpu_env)) {
7981 arg4 = arg5;
7982 arg5 = arg6;
7983 }
f2c7ba15
AJ
7984 if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
7985 goto efault;
7986 ret = get_errno(pread64(arg1, p, arg3, target_offset64(arg4, arg5)));
7987 unlock_user(p, arg2, ret);
7988 break;
7989 case TARGET_NR_pwrite64:
ae017a5b
AG
7990 if (regpairs_aligned(cpu_env)) {
7991 arg4 = arg5;
7992 arg5 = arg6;
7993 }
f2c7ba15
AJ
7994 if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
7995 goto efault;
7996 ret = get_errno(pwrite64(arg1, p, arg3, target_offset64(arg4, arg5)));
7997 unlock_user(p, arg2, 0);
7998 break;
67867308 7999#endif
31e31b8a 8000 case TARGET_NR_getcwd:
579a97f7
FB
8001 if (!(p = lock_user(VERIFY_WRITE, arg1, arg2, 0)))
8002 goto efault;
53a5960a
PB
8003 ret = get_errno(sys_getcwd1(p, arg2));
8004 unlock_user(p, arg1, ret);
31e31b8a
FB
8005 break;
8006 case TARGET_NR_capget:
8007 case TARGET_NR_capset:
e0eb210e
PM
8008 {
8009 struct target_user_cap_header *target_header;
8010 struct target_user_cap_data *target_data = NULL;
8011 struct __user_cap_header_struct header;
8012 struct __user_cap_data_struct data[2];
8013 struct __user_cap_data_struct *dataptr = NULL;
8014 int i, target_datalen;
8015 int data_items = 1;
8016
8017 if (!lock_user_struct(VERIFY_WRITE, target_header, arg1, 1)) {
8018 goto efault;
8019 }
8020 header.version = tswap32(target_header->version);
8021 header.pid = tswap32(target_header->pid);
8022
ec864874 8023 if (header.version != _LINUX_CAPABILITY_VERSION) {
e0eb210e
PM
8024 /* Version 2 and up takes pointer to two user_data structs */
8025 data_items = 2;
8026 }
8027
8028 target_datalen = sizeof(*target_data) * data_items;
8029
8030 if (arg2) {
8031 if (num == TARGET_NR_capget) {
8032 target_data = lock_user(VERIFY_WRITE, arg2, target_datalen, 0);
8033 } else {
8034 target_data = lock_user(VERIFY_READ, arg2, target_datalen, 1);
8035 }
8036 if (!target_data) {
8037 unlock_user_struct(target_header, arg1, 0);
8038 goto efault;
8039 }
8040
8041 if (num == TARGET_NR_capset) {
8042 for (i = 0; i < data_items; i++) {
8043 data[i].effective = tswap32(target_data[i].effective);
8044 data[i].permitted = tswap32(target_data[i].permitted);
8045 data[i].inheritable = tswap32(target_data[i].inheritable);
8046 }
8047 }
8048
8049 dataptr = data;
8050 }
8051
8052 if (num == TARGET_NR_capget) {
8053 ret = get_errno(capget(&header, dataptr));
8054 } else {
8055 ret = get_errno(capset(&header, dataptr));
8056 }
8057
8058 /* The kernel always updates version for both capget and capset */
8059 target_header->version = tswap32(header.version);
8060 unlock_user_struct(target_header, arg1, 1);
8061
8062 if (arg2) {
8063 if (num == TARGET_NR_capget) {
8064 for (i = 0; i < data_items; i++) {
8065 target_data[i].effective = tswap32(data[i].effective);
8066 target_data[i].permitted = tswap32(data[i].permitted);
8067 target_data[i].inheritable = tswap32(data[i].inheritable);
8068 }
8069 unlock_user(target_data, arg2, target_datalen);
8070 } else {
8071 unlock_user(target_data, arg2, 0);
8072 }
8073 }
8074 break;
8075 }
31e31b8a 8076 case TARGET_NR_sigaltstack:
198a74de 8077#if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_MIPS) || \
c761c154 8078 defined(TARGET_SPARC) || defined(TARGET_PPC) || defined(TARGET_ALPHA) || \
d962783e 8079 defined(TARGET_M68K) || defined(TARGET_S390X) || defined(TARGET_OPENRISC)
9349b4f9 8080 ret = do_sigaltstack(arg1, arg2, get_sp_from_cpustate((CPUArchState *)cpu_env));
a04e134a
TS
8081 break;
8082#else
5cd4393b 8083 goto unimplemented;
a04e134a 8084#endif
a8fd1aba
PM
8085
8086#ifdef CONFIG_SENDFILE
8087 case TARGET_NR_sendfile:
8088 {
8089 off_t *offp = NULL;
8090 off_t off;
8091 if (arg3) {
8092 ret = get_user_sal(off, arg3);
8093 if (is_error(ret)) {
8094 break;
8095 }
8096 offp = &off;
8097 }
8098 ret = get_errno(sendfile(arg1, arg2, offp, arg4));
8099 if (!is_error(ret) && arg3) {
8100 abi_long ret2 = put_user_sal(off, arg3);
8101 if (is_error(ret2)) {
8102 ret = ret2;
8103 }
8104 }
8105 break;
8106 }
8107#ifdef TARGET_NR_sendfile64
8108 case TARGET_NR_sendfile64:
8109 {
8110 off_t *offp = NULL;
8111 off_t off;
8112 if (arg3) {
8113 ret = get_user_s64(off, arg3);
8114 if (is_error(ret)) {
8115 break;
8116 }
8117 offp = &off;
8118 }
8119 ret = get_errno(sendfile(arg1, arg2, offp, arg4));
8120 if (!is_error(ret) && arg3) {
8121 abi_long ret2 = put_user_s64(off, arg3);
8122 if (is_error(ret2)) {
8123 ret = ret2;
8124 }
8125 }
8126 break;
8127 }
8128#endif
8129#else
31e31b8a 8130 case TARGET_NR_sendfile:
7edd2cf1 8131#ifdef TARGET_NR_sendfile64
a8fd1aba
PM
8132 case TARGET_NR_sendfile64:
8133#endif
5cd4393b 8134 goto unimplemented;
a8fd1aba
PM
8135#endif
8136
ebc05488 8137#ifdef TARGET_NR_getpmsg
31e31b8a 8138 case TARGET_NR_getpmsg:
5cd4393b 8139 goto unimplemented;
ebc05488
FB
8140#endif
8141#ifdef TARGET_NR_putpmsg
31e31b8a 8142 case TARGET_NR_putpmsg:
5cd4393b 8143 goto unimplemented;
ebc05488 8144#endif
048f6b4d 8145#ifdef TARGET_NR_vfork
31e31b8a 8146 case TARGET_NR_vfork:
d865bab5
PB
8147 ret = get_errno(do_fork(cpu_env, CLONE_VFORK | CLONE_VM | SIGCHLD,
8148 0, 0, 0, 0));
31e31b8a 8149 break;
048f6b4d 8150#endif
ebc05488 8151#ifdef TARGET_NR_ugetrlimit
31e31b8a 8152 case TARGET_NR_ugetrlimit:
728584be
FB
8153 {
8154 struct rlimit rlim;
e22b7015
WT
8155 int resource = target_to_host_resource(arg1);
8156 ret = get_errno(getrlimit(resource, &rlim));
728584be 8157 if (!is_error(ret)) {
53a5960a 8158 struct target_rlimit *target_rlim;
579a97f7
FB
8159 if (!lock_user_struct(VERIFY_WRITE, target_rlim, arg2, 0))
8160 goto efault;
81bbe906
TY
8161 target_rlim->rlim_cur = host_to_target_rlim(rlim.rlim_cur);
8162 target_rlim->rlim_max = host_to_target_rlim(rlim.rlim_max);
53a5960a 8163 unlock_user_struct(target_rlim, arg2, 1);
728584be
FB
8164 }
8165 break;
8166 }
ebc05488 8167#endif
a315a145 8168#ifdef TARGET_NR_truncate64
31e31b8a 8169 case TARGET_NR_truncate64:
579a97f7
FB
8170 if (!(p = lock_user_string(arg1)))
8171 goto efault;
53a5960a
PB
8172 ret = target_truncate64(cpu_env, p, arg2, arg3, arg4);
8173 unlock_user(p, arg1, 0);
667f38b1 8174 break;
a315a145
FB
8175#endif
8176#ifdef TARGET_NR_ftruncate64
31e31b8a 8177 case TARGET_NR_ftruncate64:
ce4defa0 8178 ret = target_ftruncate64(cpu_env, arg1, arg2, arg3, arg4);
667f38b1 8179 break;
a315a145
FB
8180#endif
8181#ifdef TARGET_NR_stat64
31e31b8a 8182 case TARGET_NR_stat64:
579a97f7
FB
8183 if (!(p = lock_user_string(arg1)))
8184 goto efault;
53a5960a
PB
8185 ret = get_errno(stat(path(p), &st));
8186 unlock_user(p, arg1, 0);
6a24a778
AZ
8187 if (!is_error(ret))
8188 ret = host_to_target_stat64(cpu_env, arg2, &st);
8189 break;
a315a145
FB
8190#endif
8191#ifdef TARGET_NR_lstat64
31e31b8a 8192 case TARGET_NR_lstat64:
579a97f7
FB
8193 if (!(p = lock_user_string(arg1)))
8194 goto efault;
53a5960a
PB
8195 ret = get_errno(lstat(path(p), &st));
8196 unlock_user(p, arg1, 0);
6a24a778
AZ
8197 if (!is_error(ret))
8198 ret = host_to_target_stat64(cpu_env, arg2, &st);
8199 break;
a315a145
FB
8200#endif
8201#ifdef TARGET_NR_fstat64
31e31b8a 8202 case TARGET_NR_fstat64:
6a24a778
AZ
8203 ret = get_errno(fstat(arg1, &st));
8204 if (!is_error(ret))
8205 ret = host_to_target_stat64(cpu_env, arg2, &st);
8206 break;
ce4defa0 8207#endif
c0d472b1 8208#if (defined(TARGET_NR_fstatat64) || defined(TARGET_NR_newfstatat))
9d33b76b 8209#ifdef TARGET_NR_fstatat64
6a24a778 8210 case TARGET_NR_fstatat64:
9d33b76b
AJ
8211#endif
8212#ifdef TARGET_NR_newfstatat
8213 case TARGET_NR_newfstatat:
8214#endif
6a24a778
AZ
8215 if (!(p = lock_user_string(arg2)))
8216 goto efault;
c0d472b1 8217 ret = get_errno(fstatat(arg1, path(p), &st, arg4));
6a24a778
AZ
8218 if (!is_error(ret))
8219 ret = host_to_target_stat64(cpu_env, arg3, &st);
60cd49d5 8220 break;
a315a145 8221#endif
67867308 8222 case TARGET_NR_lchown:
579a97f7
FB
8223 if (!(p = lock_user_string(arg1)))
8224 goto efault;
53a5960a
PB
8225 ret = get_errno(lchown(p, low2highuid(arg2), low2highgid(arg3)));
8226 unlock_user(p, arg1, 0);
67867308 8227 break;
0c866a7e 8228#ifdef TARGET_NR_getuid
67867308
FB
8229 case TARGET_NR_getuid:
8230 ret = get_errno(high2lowuid(getuid()));
8231 break;
0c866a7e
RV
8232#endif
8233#ifdef TARGET_NR_getgid
67867308
FB
8234 case TARGET_NR_getgid:
8235 ret = get_errno(high2lowgid(getgid()));
8236 break;
0c866a7e
RV
8237#endif
8238#ifdef TARGET_NR_geteuid
67867308
FB
8239 case TARGET_NR_geteuid:
8240 ret = get_errno(high2lowuid(geteuid()));
8241 break;
0c866a7e
RV
8242#endif
8243#ifdef TARGET_NR_getegid
67867308
FB
8244 case TARGET_NR_getegid:
8245 ret = get_errno(high2lowgid(getegid()));
8246 break;
0c866a7e 8247#endif
67867308
FB
8248 case TARGET_NR_setreuid:
8249 ret = get_errno(setreuid(low2highuid(arg1), low2highuid(arg2)));
8250 break;
8251 case TARGET_NR_setregid:
8252 ret = get_errno(setregid(low2highgid(arg1), low2highgid(arg2)));
8253 break;
8254 case TARGET_NR_getgroups:
8255 {
8256 int gidsetsize = arg1;
0c866a7e 8257 target_id *target_grouplist;
67867308
FB
8258 gid_t *grouplist;
8259 int i;
8260
8261 grouplist = alloca(gidsetsize * sizeof(gid_t));
8262 ret = get_errno(getgroups(gidsetsize, grouplist));
cb3bc233
AZ
8263 if (gidsetsize == 0)
8264 break;
67867308 8265 if (!is_error(ret)) {
03903ffc 8266 target_grouplist = lock_user(VERIFY_WRITE, arg2, gidsetsize * sizeof(target_id), 0);
579a97f7
FB
8267 if (!target_grouplist)
8268 goto efault;
a2155fcc 8269 for(i = 0;i < ret; i++)
0c866a7e 8270 target_grouplist[i] = tswapid(high2lowgid(grouplist[i]));
03903ffc 8271 unlock_user(target_grouplist, arg2, gidsetsize * sizeof(target_id));
67867308
FB
8272 }
8273 }
8274 break;
8275 case TARGET_NR_setgroups:
8276 {
8277 int gidsetsize = arg1;
0c866a7e 8278 target_id *target_grouplist;
f2b79ce9 8279 gid_t *grouplist = NULL;
67867308 8280 int i;
f2b79ce9
DA
8281 if (gidsetsize) {
8282 grouplist = alloca(gidsetsize * sizeof(gid_t));
03903ffc 8283 target_grouplist = lock_user(VERIFY_READ, arg2, gidsetsize * sizeof(target_id), 1);
f2b79ce9
DA
8284 if (!target_grouplist) {
8285 ret = -TARGET_EFAULT;
8286 goto fail;
8287 }
8288 for (i = 0; i < gidsetsize; i++) {
8289 grouplist[i] = low2highgid(tswapid(target_grouplist[i]));
8290 }
8291 unlock_user(target_grouplist, arg2, 0);
579a97f7 8292 }
67867308
FB
8293 ret = get_errno(setgroups(gidsetsize, grouplist));
8294 }
8295 break;
8296 case TARGET_NR_fchown:
8297 ret = get_errno(fchown(arg1, low2highuid(arg2), low2highgid(arg3)));
8298 break;
c0d472b1 8299#if defined(TARGET_NR_fchownat)
ccfa72b7 8300 case TARGET_NR_fchownat:
579a97f7
FB
8301 if (!(p = lock_user_string(arg2)))
8302 goto efault;
c0d472b1
PM
8303 ret = get_errno(fchownat(arg1, p, low2highuid(arg3),
8304 low2highgid(arg4), arg5));
579a97f7 8305 unlock_user(p, arg2, 0);
ccfa72b7
TS
8306 break;
8307#endif
67867308
FB
8308#ifdef TARGET_NR_setresuid
8309 case TARGET_NR_setresuid:
5fafdf24
TS
8310 ret = get_errno(setresuid(low2highuid(arg1),
8311 low2highuid(arg2),
67867308
FB
8312 low2highuid(arg3)));
8313 break;
8314#endif
8315#ifdef TARGET_NR_getresuid
8316 case TARGET_NR_getresuid:
8317 {
53a5960a 8318 uid_t ruid, euid, suid;
67867308
FB
8319 ret = get_errno(getresuid(&ruid, &euid, &suid));
8320 if (!is_error(ret)) {
76ca310a
PM
8321 if (put_user_id(high2lowuid(ruid), arg1)
8322 || put_user_id(high2lowuid(euid), arg2)
8323 || put_user_id(high2lowuid(suid), arg3))
2f619698 8324 goto efault;
67867308
FB
8325 }
8326 }
8327 break;
8328#endif
8329#ifdef TARGET_NR_getresgid
8330 case TARGET_NR_setresgid:
5fafdf24
TS
8331 ret = get_errno(setresgid(low2highgid(arg1),
8332 low2highgid(arg2),
67867308
FB
8333 low2highgid(arg3)));
8334 break;
8335#endif
8336#ifdef TARGET_NR_getresgid
8337 case TARGET_NR_getresgid:
8338 {
53a5960a 8339 gid_t rgid, egid, sgid;
67867308
FB
8340 ret = get_errno(getresgid(&rgid, &egid, &sgid));
8341 if (!is_error(ret)) {
76ca310a
PM
8342 if (put_user_id(high2lowgid(rgid), arg1)
8343 || put_user_id(high2lowgid(egid), arg2)
8344 || put_user_id(high2lowgid(sgid), arg3))
2f619698 8345 goto efault;
67867308
FB
8346 }
8347 }
8348 break;
8349#endif
8350 case TARGET_NR_chown:
579a97f7
FB
8351 if (!(p = lock_user_string(arg1)))
8352 goto efault;
53a5960a
PB
8353 ret = get_errno(chown(p, low2highuid(arg2), low2highgid(arg3)));
8354 unlock_user(p, arg1, 0);
67867308
FB
8355 break;
8356 case TARGET_NR_setuid:
8357 ret = get_errno(setuid(low2highuid(arg1)));
8358 break;
8359 case TARGET_NR_setgid:
8360 ret = get_errno(setgid(low2highgid(arg1)));
8361 break;
8362 case TARGET_NR_setfsuid:
8363 ret = get_errno(setfsuid(arg1));
8364 break;
8365 case TARGET_NR_setfsgid:
8366 ret = get_errno(setfsgid(arg1));
8367 break;
67867308 8368
a315a145 8369#ifdef TARGET_NR_lchown32
31e31b8a 8370 case TARGET_NR_lchown32:
579a97f7
FB
8371 if (!(p = lock_user_string(arg1)))
8372 goto efault;
53a5960a
PB
8373 ret = get_errno(lchown(p, arg2, arg3));
8374 unlock_user(p, arg1, 0);
b03c60f3 8375 break;
a315a145
FB
8376#endif
8377#ifdef TARGET_NR_getuid32
31e31b8a 8378 case TARGET_NR_getuid32:
b03c60f3
FB
8379 ret = get_errno(getuid());
8380 break;
a315a145 8381#endif
64b4d28c
AJ
8382
8383#if defined(TARGET_NR_getxuid) && defined(TARGET_ALPHA)
8384 /* Alpha specific */
8385 case TARGET_NR_getxuid:
ba0e276d
RH
8386 {
8387 uid_t euid;
8388 euid=geteuid();
8389 ((CPUAlphaState *)cpu_env)->ir[IR_A4]=euid;
8390 }
64b4d28c
AJ
8391 ret = get_errno(getuid());
8392 break;
8393#endif
8394#if defined(TARGET_NR_getxgid) && defined(TARGET_ALPHA)
8395 /* Alpha specific */
8396 case TARGET_NR_getxgid:
ba0e276d
RH
8397 {
8398 uid_t egid;
8399 egid=getegid();
8400 ((CPUAlphaState *)cpu_env)->ir[IR_A4]=egid;
8401 }
64b4d28c
AJ
8402 ret = get_errno(getgid());
8403 break;
8404#endif
ba0e276d
RH
8405#if defined(TARGET_NR_osf_getsysinfo) && defined(TARGET_ALPHA)
8406 /* Alpha specific */
8407 case TARGET_NR_osf_getsysinfo:
8408 ret = -TARGET_EOPNOTSUPP;
8409 switch (arg1) {
8410 case TARGET_GSI_IEEE_FP_CONTROL:
8411 {
8412 uint64_t swcr, fpcr = cpu_alpha_load_fpcr (cpu_env);
8413
8414 /* Copied from linux ieee_fpcr_to_swcr. */
8415 swcr = (fpcr >> 35) & SWCR_STATUS_MASK;
8416 swcr |= (fpcr >> 36) & SWCR_MAP_DMZ;
8417 swcr |= (~fpcr >> 48) & (SWCR_TRAP_ENABLE_INV
8418 | SWCR_TRAP_ENABLE_DZE
8419 | SWCR_TRAP_ENABLE_OVF);
8420 swcr |= (~fpcr >> 57) & (SWCR_TRAP_ENABLE_UNF
8421 | SWCR_TRAP_ENABLE_INE);
8422 swcr |= (fpcr >> 47) & SWCR_MAP_UMZ;
8423 swcr |= (~fpcr >> 41) & SWCR_TRAP_ENABLE_DNO;
8424
8425 if (put_user_u64 (swcr, arg2))
8426 goto efault;
8427 ret = 0;
8428 }
8429 break;
8430
8431 /* case GSI_IEEE_STATE_AT_SIGNAL:
8432 -- Not implemented in linux kernel.
8433 case GSI_UACPROC:
8434 -- Retrieves current unaligned access state; not much used.
8435 case GSI_PROC_TYPE:
8436 -- Retrieves implver information; surely not used.
8437 case GSI_GET_HWRPB:
8438 -- Grabs a copy of the HWRPB; surely not used.
8439 */
8440 }
8441 break;
8442#endif
8443#if defined(TARGET_NR_osf_setsysinfo) && defined(TARGET_ALPHA)
8444 /* Alpha specific */
8445 case TARGET_NR_osf_setsysinfo:
8446 ret = -TARGET_EOPNOTSUPP;
8447 switch (arg1) {
8448 case TARGET_SSI_IEEE_FP_CONTROL:
ba0e276d
RH
8449 {
8450 uint64_t swcr, fpcr, orig_fpcr;
8451
6e06d515 8452 if (get_user_u64 (swcr, arg2)) {
ba0e276d 8453 goto efault;
6e06d515
RH
8454 }
8455 orig_fpcr = cpu_alpha_load_fpcr(cpu_env);
ba0e276d
RH
8456 fpcr = orig_fpcr & FPCR_DYN_MASK;
8457
8458 /* Copied from linux ieee_swcr_to_fpcr. */
8459 fpcr |= (swcr & SWCR_STATUS_MASK) << 35;
8460 fpcr |= (swcr & SWCR_MAP_DMZ) << 36;
8461 fpcr |= (~swcr & (SWCR_TRAP_ENABLE_INV
8462 | SWCR_TRAP_ENABLE_DZE
8463 | SWCR_TRAP_ENABLE_OVF)) << 48;
8464 fpcr |= (~swcr & (SWCR_TRAP_ENABLE_UNF
8465 | SWCR_TRAP_ENABLE_INE)) << 57;
8466 fpcr |= (swcr & SWCR_MAP_UMZ ? FPCR_UNDZ | FPCR_UNFD : 0);
8467 fpcr |= (~swcr & SWCR_TRAP_ENABLE_DNO) << 41;
8468
6e06d515 8469 cpu_alpha_store_fpcr(cpu_env, fpcr);
ba0e276d 8470 ret = 0;
6e06d515
RH
8471 }
8472 break;
8473
8474 case TARGET_SSI_IEEE_RAISE_EXCEPTION:
8475 {
8476 uint64_t exc, fpcr, orig_fpcr;
8477 int si_code;
8478
8479 if (get_user_u64(exc, arg2)) {
8480 goto efault;
8481 }
ba0e276d 8482
6e06d515 8483 orig_fpcr = cpu_alpha_load_fpcr(cpu_env);
ba0e276d 8484
6e06d515
RH
8485 /* We only add to the exception status here. */
8486 fpcr = orig_fpcr | ((exc & SWCR_STATUS_MASK) << 35);
8487
8488 cpu_alpha_store_fpcr(cpu_env, fpcr);
8489 ret = 0;
8490
8491 /* Old exceptions are not signaled. */
8492 fpcr &= ~(orig_fpcr & FPCR_STATUS_MASK);
8493
8494 /* If any exceptions set by this call,
8495 and are unmasked, send a signal. */
8496 si_code = 0;
8497 if ((fpcr & (FPCR_INE | FPCR_INED)) == FPCR_INE) {
8498 si_code = TARGET_FPE_FLTRES;
8499 }
8500 if ((fpcr & (FPCR_UNF | FPCR_UNFD)) == FPCR_UNF) {
8501 si_code = TARGET_FPE_FLTUND;
8502 }
8503 if ((fpcr & (FPCR_OVF | FPCR_OVFD)) == FPCR_OVF) {
8504 si_code = TARGET_FPE_FLTOVF;
8505 }
8506 if ((fpcr & (FPCR_DZE | FPCR_DZED)) == FPCR_DZE) {
8507 si_code = TARGET_FPE_FLTDIV;
8508 }
8509 if ((fpcr & (FPCR_INV | FPCR_INVD)) == FPCR_INV) {
8510 si_code = TARGET_FPE_FLTINV;
8511 }
8512 if (si_code != 0) {
8513 target_siginfo_t info;
8514 info.si_signo = SIGFPE;
8515 info.si_errno = 0;
8516 info.si_code = si_code;
8517 info._sifields._sigfault._addr
8518 = ((CPUArchState *)cpu_env)->pc;
8519 queue_signal((CPUArchState *)cpu_env, info.si_signo, &info);
ba0e276d
RH
8520 }
8521 }
8522 break;
8523
8524 /* case SSI_NVPAIRS:
8525 -- Used with SSIN_UACPROC to enable unaligned accesses.
8526 case SSI_IEEE_STATE_AT_SIGNAL:
8527 case SSI_IEEE_IGNORE_STATE_AT_SIGNAL:
8528 -- Not implemented in linux kernel
8529 */
8530 }
8531 break;
8532#endif
8533#ifdef TARGET_NR_osf_sigprocmask
8534 /* Alpha specific. */
8535 case TARGET_NR_osf_sigprocmask:
8536 {
8537 abi_ulong mask;
bc088ba1 8538 int how;
ba0e276d
RH
8539 sigset_t set, oldset;
8540
8541 switch(arg1) {
8542 case TARGET_SIG_BLOCK:
8543 how = SIG_BLOCK;
8544 break;
8545 case TARGET_SIG_UNBLOCK:
8546 how = SIG_UNBLOCK;
8547 break;
8548 case TARGET_SIG_SETMASK:
8549 how = SIG_SETMASK;
8550 break;
8551 default:
8552 ret = -TARGET_EINVAL;
8553 goto fail;
8554 }
8555 mask = arg2;
8556 target_to_host_old_sigset(&set, &mask);
1c275925 8557 do_sigprocmask(how, &set, &oldset);
ba0e276d
RH
8558 host_to_target_old_sigset(&mask, &oldset);
8559 ret = mask;
8560 }
8561 break;
8562#endif
64b4d28c 8563
a315a145 8564#ifdef TARGET_NR_getgid32
31e31b8a 8565 case TARGET_NR_getgid32:
b03c60f3
FB
8566 ret = get_errno(getgid());
8567 break;
a315a145
FB
8568#endif
8569#ifdef TARGET_NR_geteuid32
31e31b8a 8570 case TARGET_NR_geteuid32:
b03c60f3
FB
8571 ret = get_errno(geteuid());
8572 break;
a315a145
FB
8573#endif
8574#ifdef TARGET_NR_getegid32
31e31b8a 8575 case TARGET_NR_getegid32:
b03c60f3
FB
8576 ret = get_errno(getegid());
8577 break;
a315a145
FB
8578#endif
8579#ifdef TARGET_NR_setreuid32
31e31b8a 8580 case TARGET_NR_setreuid32:
b03c60f3
FB
8581 ret = get_errno(setreuid(arg1, arg2));
8582 break;
a315a145
FB
8583#endif
8584#ifdef TARGET_NR_setregid32
31e31b8a 8585 case TARGET_NR_setregid32:
b03c60f3
FB
8586 ret = get_errno(setregid(arg1, arg2));
8587 break;
a315a145
FB
8588#endif
8589#ifdef TARGET_NR_getgroups32
31e31b8a 8590 case TARGET_NR_getgroups32:
99c475ab
FB
8591 {
8592 int gidsetsize = arg1;
53a5960a 8593 uint32_t *target_grouplist;
99c475ab
FB
8594 gid_t *grouplist;
8595 int i;
8596
8597 grouplist = alloca(gidsetsize * sizeof(gid_t));
8598 ret = get_errno(getgroups(gidsetsize, grouplist));
cb3bc233
AZ
8599 if (gidsetsize == 0)
8600 break;
99c475ab 8601 if (!is_error(ret)) {
579a97f7
FB
8602 target_grouplist = lock_user(VERIFY_WRITE, arg2, gidsetsize * 4, 0);
8603 if (!target_grouplist) {
8604 ret = -TARGET_EFAULT;
8605 goto fail;
8606 }
a2155fcc 8607 for(i = 0;i < ret; i++)
53a5960a
PB
8608 target_grouplist[i] = tswap32(grouplist[i]);
8609 unlock_user(target_grouplist, arg2, gidsetsize * 4);
99c475ab
FB
8610 }
8611 }
8612 break;
a315a145
FB
8613#endif
8614#ifdef TARGET_NR_setgroups32
31e31b8a 8615 case TARGET_NR_setgroups32:
99c475ab
FB
8616 {
8617 int gidsetsize = arg1;
53a5960a 8618 uint32_t *target_grouplist;
99c475ab
FB
8619 gid_t *grouplist;
8620 int i;
3b46e624 8621
99c475ab 8622 grouplist = alloca(gidsetsize * sizeof(gid_t));
579a97f7
FB
8623 target_grouplist = lock_user(VERIFY_READ, arg2, gidsetsize * 4, 1);
8624 if (!target_grouplist) {
8625 ret = -TARGET_EFAULT;
8626 goto fail;
8627 }
99c475ab 8628 for(i = 0;i < gidsetsize; i++)
53a5960a
PB
8629 grouplist[i] = tswap32(target_grouplist[i]);
8630 unlock_user(target_grouplist, arg2, 0);
99c475ab
FB
8631 ret = get_errno(setgroups(gidsetsize, grouplist));
8632 }
8633 break;
a315a145
FB
8634#endif
8635#ifdef TARGET_NR_fchown32
31e31b8a 8636 case TARGET_NR_fchown32:
b03c60f3
FB
8637 ret = get_errno(fchown(arg1, arg2, arg3));
8638 break;
a315a145
FB
8639#endif
8640#ifdef TARGET_NR_setresuid32
31e31b8a 8641 case TARGET_NR_setresuid32:
b03c60f3
FB
8642 ret = get_errno(setresuid(arg1, arg2, arg3));
8643 break;
a315a145
FB
8644#endif
8645#ifdef TARGET_NR_getresuid32
31e31b8a 8646 case TARGET_NR_getresuid32:
b03c60f3 8647 {
53a5960a 8648 uid_t ruid, euid, suid;
b03c60f3
FB
8649 ret = get_errno(getresuid(&ruid, &euid, &suid));
8650 if (!is_error(ret)) {
2f619698
FB
8651 if (put_user_u32(ruid, arg1)
8652 || put_user_u32(euid, arg2)
8653 || put_user_u32(suid, arg3))
8654 goto efault;
b03c60f3
FB
8655 }
8656 }
8657 break;
a315a145
FB
8658#endif
8659#ifdef TARGET_NR_setresgid32
31e31b8a 8660 case TARGET_NR_setresgid32:
b03c60f3
FB
8661 ret = get_errno(setresgid(arg1, arg2, arg3));
8662 break;
a315a145
FB
8663#endif
8664#ifdef TARGET_NR_getresgid32
31e31b8a 8665 case TARGET_NR_getresgid32:
b03c60f3 8666 {
53a5960a 8667 gid_t rgid, egid, sgid;
b03c60f3
FB
8668 ret = get_errno(getresgid(&rgid, &egid, &sgid));
8669 if (!is_error(ret)) {
2f619698
FB
8670 if (put_user_u32(rgid, arg1)
8671 || put_user_u32(egid, arg2)
8672 || put_user_u32(sgid, arg3))
8673 goto efault;
b03c60f3
FB
8674 }
8675 }
8676 break;
a315a145
FB
8677#endif
8678#ifdef TARGET_NR_chown32
31e31b8a 8679 case TARGET_NR_chown32:
579a97f7
FB
8680 if (!(p = lock_user_string(arg1)))
8681 goto efault;
53a5960a
PB
8682 ret = get_errno(chown(p, arg2, arg3));
8683 unlock_user(p, arg1, 0);
b03c60f3 8684 break;
a315a145
FB
8685#endif
8686#ifdef TARGET_NR_setuid32
31e31b8a 8687 case TARGET_NR_setuid32:
b03c60f3
FB
8688 ret = get_errno(setuid(arg1));
8689 break;
a315a145
FB
8690#endif
8691#ifdef TARGET_NR_setgid32
31e31b8a 8692 case TARGET_NR_setgid32:
b03c60f3
FB
8693 ret = get_errno(setgid(arg1));
8694 break;
a315a145
FB
8695#endif
8696#ifdef TARGET_NR_setfsuid32
31e31b8a 8697 case TARGET_NR_setfsuid32:
b03c60f3
FB
8698 ret = get_errno(setfsuid(arg1));
8699 break;
a315a145
FB
8700#endif
8701#ifdef TARGET_NR_setfsgid32
31e31b8a 8702 case TARGET_NR_setfsgid32:
b03c60f3
FB
8703 ret = get_errno(setfsgid(arg1));
8704 break;
a315a145 8705#endif
67867308 8706
31e31b8a 8707 case TARGET_NR_pivot_root:
b03c60f3 8708 goto unimplemented;
ffa65c3b 8709#ifdef TARGET_NR_mincore
31e31b8a 8710 case TARGET_NR_mincore:
04bb9ace
AJ
8711 {
8712 void *a;
8713 ret = -TARGET_EFAULT;
8714 if (!(a = lock_user(VERIFY_READ, arg1,arg2, 0)))
8715 goto efault;
8716 if (!(p = lock_user_string(arg3)))
8717 goto mincore_fail;
8718 ret = get_errno(mincore(a, arg2, p));
8719 unlock_user(p, arg3, ret);
8720 mincore_fail:
8721 unlock_user(a, arg1, 0);
8722 }
8723 break;
ffa65c3b 8724#endif
408321b6
AJ
8725#ifdef TARGET_NR_arm_fadvise64_64
8726 case TARGET_NR_arm_fadvise64_64:
8727 {
8728 /*
8729 * arm_fadvise64_64 looks like fadvise64_64 but
8730 * with different argument order
8731 */
8732 abi_long temp;
8733 temp = arg3;
8734 arg3 = arg4;
8735 arg4 = temp;
8736 }
8737#endif
e72d2cc7 8738#if defined(TARGET_NR_fadvise64_64) || defined(TARGET_NR_arm_fadvise64_64) || defined(TARGET_NR_fadvise64)
408321b6
AJ
8739#ifdef TARGET_NR_fadvise64_64
8740 case TARGET_NR_fadvise64_64:
8741#endif
e72d2cc7
UH
8742#ifdef TARGET_NR_fadvise64
8743 case TARGET_NR_fadvise64:
8744#endif
8745#ifdef TARGET_S390X
8746 switch (arg4) {
8747 case 4: arg4 = POSIX_FADV_NOREUSE + 1; break; /* make sure it's an invalid value */
8748 case 5: arg4 = POSIX_FADV_NOREUSE + 2; break; /* ditto */
8749 case 6: arg4 = POSIX_FADV_DONTNEED; break;
8750 case 7: arg4 = POSIX_FADV_NOREUSE; break;
8751 default: break;
8752 }
8753#endif
8754 ret = -posix_fadvise(arg1, arg2, arg3, arg4);
408321b6
AJ
8755 break;
8756#endif
ffa65c3b 8757#ifdef TARGET_NR_madvise
31e31b8a 8758 case TARGET_NR_madvise:
24836689 8759 /* A straight passthrough may not be safe because qemu sometimes
d2d6b857 8760 turns private file-backed mappings into anonymous mappings.
24836689
PB
8761 This will break MADV_DONTNEED.
8762 This is a hint, so ignoring and returning success is ok. */
8763 ret = get_errno(0);
8764 break;
ffa65c3b 8765#endif
992f48a0 8766#if TARGET_ABI_BITS == 32
31e31b8a 8767 case TARGET_NR_fcntl64:
77e4672d 8768 {
b1e341eb 8769 int cmd;
77e4672d 8770 struct flock64 fl;
53a5960a 8771 struct target_flock64 *target_fl;
ce4defa0 8772#ifdef TARGET_ARM
53a5960a 8773 struct target_eabi_flock64 *target_efl;
ce4defa0 8774#endif
77e4672d 8775
5f106811 8776 cmd = target_to_host_fcntl_cmd(arg2);
31b63193
PM
8777 if (cmd == -TARGET_EINVAL) {
8778 ret = cmd;
8779 break;
8780 }
b1e341eb 8781
60cd49d5 8782 switch(arg2) {
b1e341eb 8783 case TARGET_F_GETLK64:
5813427b
TS
8784#ifdef TARGET_ARM
8785 if (((CPUARMState *)cpu_env)->eabi) {
9ee1fa2c
FB
8786 if (!lock_user_struct(VERIFY_READ, target_efl, arg3, 1))
8787 goto efault;
5813427b
TS
8788 fl.l_type = tswap16(target_efl->l_type);
8789 fl.l_whence = tswap16(target_efl->l_whence);
8790 fl.l_start = tswap64(target_efl->l_start);
8791 fl.l_len = tswap64(target_efl->l_len);
7e22e546 8792 fl.l_pid = tswap32(target_efl->l_pid);
5813427b
TS
8793 unlock_user_struct(target_efl, arg3, 0);
8794 } else
8795#endif
8796 {
9ee1fa2c
FB
8797 if (!lock_user_struct(VERIFY_READ, target_fl, arg3, 1))
8798 goto efault;
5813427b
TS
8799 fl.l_type = tswap16(target_fl->l_type);
8800 fl.l_whence = tswap16(target_fl->l_whence);
8801 fl.l_start = tswap64(target_fl->l_start);
8802 fl.l_len = tswap64(target_fl->l_len);
7e22e546 8803 fl.l_pid = tswap32(target_fl->l_pid);
5813427b
TS
8804 unlock_user_struct(target_fl, arg3, 0);
8805 }
b1e341eb 8806 ret = get_errno(fcntl(arg1, cmd, &fl));
77e4672d 8807 if (ret == 0) {
ce4defa0
PB
8808#ifdef TARGET_ARM
8809 if (((CPUARMState *)cpu_env)->eabi) {
9ee1fa2c
FB
8810 if (!lock_user_struct(VERIFY_WRITE, target_efl, arg3, 0))
8811 goto efault;
ce4defa0
PB
8812 target_efl->l_type = tswap16(fl.l_type);
8813 target_efl->l_whence = tswap16(fl.l_whence);
8814 target_efl->l_start = tswap64(fl.l_start);
8815 target_efl->l_len = tswap64(fl.l_len);
7e22e546 8816 target_efl->l_pid = tswap32(fl.l_pid);
53a5960a 8817 unlock_user_struct(target_efl, arg3, 1);
ce4defa0
PB
8818 } else
8819#endif
8820 {
9ee1fa2c
FB
8821 if (!lock_user_struct(VERIFY_WRITE, target_fl, arg3, 0))
8822 goto efault;
ce4defa0
PB
8823 target_fl->l_type = tswap16(fl.l_type);
8824 target_fl->l_whence = tswap16(fl.l_whence);
8825 target_fl->l_start = tswap64(fl.l_start);
8826 target_fl->l_len = tswap64(fl.l_len);
7e22e546 8827 target_fl->l_pid = tswap32(fl.l_pid);
53a5960a 8828 unlock_user_struct(target_fl, arg3, 1);
ce4defa0 8829 }
77e4672d
FB
8830 }
8831 break;
8832
b1e341eb
TS
8833 case TARGET_F_SETLK64:
8834 case TARGET_F_SETLKW64:
ce4defa0
PB
8835#ifdef TARGET_ARM
8836 if (((CPUARMState *)cpu_env)->eabi) {
9ee1fa2c
FB
8837 if (!lock_user_struct(VERIFY_READ, target_efl, arg3, 1))
8838 goto efault;
ce4defa0
PB
8839 fl.l_type = tswap16(target_efl->l_type);
8840 fl.l_whence = tswap16(target_efl->l_whence);
8841 fl.l_start = tswap64(target_efl->l_start);
8842 fl.l_len = tswap64(target_efl->l_len);
7e22e546 8843 fl.l_pid = tswap32(target_efl->l_pid);
53a5960a 8844 unlock_user_struct(target_efl, arg3, 0);
ce4defa0
PB
8845 } else
8846#endif
8847 {
9ee1fa2c
FB
8848 if (!lock_user_struct(VERIFY_READ, target_fl, arg3, 1))
8849 goto efault;
ce4defa0
PB
8850 fl.l_type = tswap16(target_fl->l_type);
8851 fl.l_whence = tswap16(target_fl->l_whence);
8852 fl.l_start = tswap64(target_fl->l_start);
8853 fl.l_len = tswap64(target_fl->l_len);
7e22e546 8854 fl.l_pid = tswap32(target_fl->l_pid);
53a5960a 8855 unlock_user_struct(target_fl, arg3, 0);
ce4defa0 8856 }
b1e341eb 8857 ret = get_errno(fcntl(arg1, cmd, &fl));
77e4672d 8858 break;
60cd49d5 8859 default:
5f106811 8860 ret = do_fcntl(arg1, arg2, arg3);
60cd49d5
FB
8861 break;
8862 }
77e4672d
FB
8863 break;
8864 }
60cd49d5 8865#endif
7d600c80
TS
8866#ifdef TARGET_NR_cacheflush
8867 case TARGET_NR_cacheflush:
8868 /* self-modifying code is handled automatically, so nothing needed */
8869 ret = 0;
8870 break;
8871#endif
ebc05488 8872#ifdef TARGET_NR_security
31e31b8a
FB
8873 case TARGET_NR_security:
8874 goto unimplemented;
c573ff67
FB
8875#endif
8876#ifdef TARGET_NR_getpagesize
8877 case TARGET_NR_getpagesize:
8878 ret = TARGET_PAGE_SIZE;
8879 break;
ebc05488 8880#endif
31e31b8a
FB
8881 case TARGET_NR_gettid:
8882 ret = get_errno(gettid());
8883 break;
e5febef5 8884#ifdef TARGET_NR_readahead
31e31b8a 8885 case TARGET_NR_readahead:
2054ac9b 8886#if TARGET_ABI_BITS == 32
48e515d4 8887 if (regpairs_aligned(cpu_env)) {
2054ac9b
AJ
8888 arg2 = arg3;
8889 arg3 = arg4;
8890 arg4 = arg5;
8891 }
2054ac9b
AJ
8892 ret = get_errno(readahead(arg1, ((off64_t)arg3 << 32) | arg2, arg4));
8893#else
8894 ret = get_errno(readahead(arg1, arg2, arg3));
8895#endif
8896 break;
e5febef5 8897#endif
a790ae38 8898#ifdef CONFIG_ATTR
ebc05488 8899#ifdef TARGET_NR_setxattr
31e31b8a
FB
8900 case TARGET_NR_listxattr:
8901 case TARGET_NR_llistxattr:
fb5590f7
PM
8902 {
8903 void *p, *b = 0;
8904 if (arg2) {
8905 b = lock_user(VERIFY_WRITE, arg2, arg3, 0);
8906 if (!b) {
8907 ret = -TARGET_EFAULT;
8908 break;
8909 }
8910 }
8911 p = lock_user_string(arg1);
8912 if (p) {
8913 if (num == TARGET_NR_listxattr) {
8914 ret = get_errno(listxattr(p, b, arg3));
8915 } else {
8916 ret = get_errno(llistxattr(p, b, arg3));
8917 }
8918 } else {
8919 ret = -TARGET_EFAULT;
8920 }
8921 unlock_user(p, arg1, 0);
8922 unlock_user(b, arg2, arg3);
8923 break;
8924 }
31e31b8a 8925 case TARGET_NR_flistxattr:
fb5590f7
PM
8926 {
8927 void *b = 0;
8928 if (arg2) {
8929 b = lock_user(VERIFY_WRITE, arg2, arg3, 0);
8930 if (!b) {
8931 ret = -TARGET_EFAULT;
8932 break;
8933 }
8934 }
8935 ret = get_errno(flistxattr(arg1, b, arg3));
8936 unlock_user(b, arg2, arg3);
6f932f91 8937 break;
fb5590f7 8938 }
a790ae38 8939 case TARGET_NR_setxattr:
30297b55 8940 case TARGET_NR_lsetxattr:
a790ae38 8941 {
e3c33ec6
PM
8942 void *p, *n, *v = 0;
8943 if (arg3) {
8944 v = lock_user(VERIFY_READ, arg3, arg4, 1);
8945 if (!v) {
8946 ret = -TARGET_EFAULT;
8947 break;
8948 }
8949 }
a790ae38
ACH
8950 p = lock_user_string(arg1);
8951 n = lock_user_string(arg2);
e3c33ec6 8952 if (p && n) {
30297b55
PM
8953 if (num == TARGET_NR_setxattr) {
8954 ret = get_errno(setxattr(p, n, v, arg4, arg5));
8955 } else {
8956 ret = get_errno(lsetxattr(p, n, v, arg4, arg5));
8957 }
a790ae38
ACH
8958 } else {
8959 ret = -TARGET_EFAULT;
8960 }
8961 unlock_user(p, arg1, 0);
8962 unlock_user(n, arg2, 0);
8963 unlock_user(v, arg3, 0);
8964 }
8965 break;
30297b55
PM
8966 case TARGET_NR_fsetxattr:
8967 {
8968 void *n, *v = 0;
8969 if (arg3) {
8970 v = lock_user(VERIFY_READ, arg3, arg4, 1);
8971 if (!v) {
8972 ret = -TARGET_EFAULT;
8973 break;
8974 }
8975 }
8976 n = lock_user_string(arg2);
8977 if (n) {
8978 ret = get_errno(fsetxattr(arg1, n, v, arg4, arg5));
8979 } else {
8980 ret = -TARGET_EFAULT;
8981 }
8982 unlock_user(n, arg2, 0);
8983 unlock_user(v, arg3, 0);
8984 }
8985 break;
a790ae38 8986 case TARGET_NR_getxattr:
30297b55 8987 case TARGET_NR_lgetxattr:
a790ae38 8988 {
e3c33ec6
PM
8989 void *p, *n, *v = 0;
8990 if (arg3) {
8991 v = lock_user(VERIFY_WRITE, arg3, arg4, 0);
8992 if (!v) {
8993 ret = -TARGET_EFAULT;
8994 break;
8995 }
8996 }
a790ae38
ACH
8997 p = lock_user_string(arg1);
8998 n = lock_user_string(arg2);
e3c33ec6 8999 if (p && n) {
30297b55
PM
9000 if (num == TARGET_NR_getxattr) {
9001 ret = get_errno(getxattr(p, n, v, arg4));
9002 } else {
9003 ret = get_errno(lgetxattr(p, n, v, arg4));
9004 }
a790ae38
ACH
9005 } else {
9006 ret = -TARGET_EFAULT;
9007 }
9008 unlock_user(p, arg1, 0);
9009 unlock_user(n, arg2, 0);
9010 unlock_user(v, arg3, arg4);
9011 }
9012 break;
30297b55
PM
9013 case TARGET_NR_fgetxattr:
9014 {
9015 void *n, *v = 0;
9016 if (arg3) {
9017 v = lock_user(VERIFY_WRITE, arg3, arg4, 0);
9018 if (!v) {
9019 ret = -TARGET_EFAULT;
9020 break;
9021 }
9022 }
9023 n = lock_user_string(arg2);
9024 if (n) {
9025 ret = get_errno(fgetxattr(arg1, n, v, arg4));
9026 } else {
9027 ret = -TARGET_EFAULT;
9028 }
9029 unlock_user(n, arg2, 0);
9030 unlock_user(v, arg3, arg4);
9031 }
9032 break;
a790ae38 9033 case TARGET_NR_removexattr:
30297b55 9034 case TARGET_NR_lremovexattr:
a790ae38
ACH
9035 {
9036 void *p, *n;
9037 p = lock_user_string(arg1);
9038 n = lock_user_string(arg2);
9039 if (p && n) {
30297b55
PM
9040 if (num == TARGET_NR_removexattr) {
9041 ret = get_errno(removexattr(p, n));
9042 } else {
9043 ret = get_errno(lremovexattr(p, n));
9044 }
a790ae38
ACH
9045 } else {
9046 ret = -TARGET_EFAULT;
9047 }
9048 unlock_user(p, arg1, 0);
9049 unlock_user(n, arg2, 0);
9050 }
9051 break;
30297b55
PM
9052 case TARGET_NR_fremovexattr:
9053 {
9054 void *n;
9055 n = lock_user_string(arg2);
9056 if (n) {
9057 ret = get_errno(fremovexattr(arg1, n));
9058 } else {
9059 ret = -TARGET_EFAULT;
9060 }
9061 unlock_user(n, arg2, 0);
9062 }
9063 break;
ebc05488 9064#endif
a790ae38 9065#endif /* CONFIG_ATTR */
ebc05488 9066#ifdef TARGET_NR_set_thread_area
5cd4393b 9067 case TARGET_NR_set_thread_area:
8d18e893 9068#if defined(TARGET_MIPS)
d279279e 9069 ((CPUMIPSState *) cpu_env)->active_tc.CP0_UserLocal = arg1;
6f5b89a0
TS
9070 ret = 0;
9071 break;
ef96779b
EI
9072#elif defined(TARGET_CRIS)
9073 if (arg1 & 0xff)
9074 ret = -TARGET_EINVAL;
9075 else {
9076 ((CPUCRISState *) cpu_env)->pregs[PR_PID] = arg1;
9077 ret = 0;
9078 }
9079 break;
8d18e893
FB
9080#elif defined(TARGET_I386) && defined(TARGET_ABI32)
9081 ret = do_set_thread_area(cpu_env, arg1);
9082 break;
1ccd9374
PM
9083#elif defined(TARGET_M68K)
9084 {
0429a971 9085 TaskState *ts = cpu->opaque;
1ccd9374 9086 ts->tp_value = arg1;
95c1eb19 9087 ret = 0;
1ccd9374
PM
9088 break;
9089 }
6f5b89a0
TS
9090#else
9091 goto unimplemented_nowarn;
9092#endif
9093#endif
9094#ifdef TARGET_NR_get_thread_area
5cd4393b 9095 case TARGET_NR_get_thread_area:
8d18e893
FB
9096#if defined(TARGET_I386) && defined(TARGET_ABI32)
9097 ret = do_get_thread_area(cpu_env, arg1);
d312bbe1 9098 break;
1ccd9374
PM
9099#elif defined(TARGET_M68K)
9100 {
0429a971 9101 TaskState *ts = cpu->opaque;
1ccd9374
PM
9102 ret = ts->tp_value;
9103 break;
9104 }
8d18e893 9105#else
5cd4393b 9106 goto unimplemented_nowarn;
48dc41eb 9107#endif
8d18e893 9108#endif
48dc41eb
FB
9109#ifdef TARGET_NR_getdomainname
9110 case TARGET_NR_getdomainname:
9111 goto unimplemented_nowarn;
ebc05488 9112#endif
6f5b89a0 9113
b5906f95
TS
9114#ifdef TARGET_NR_clock_gettime
9115 case TARGET_NR_clock_gettime:
9116 {
9117 struct timespec ts;
9118 ret = get_errno(clock_gettime(arg1, &ts));
9119 if (!is_error(ret)) {
9120 host_to_target_timespec(arg2, &ts);
9121 }
9122 break;
9123 }
9124#endif
9125#ifdef TARGET_NR_clock_getres
9126 case TARGET_NR_clock_getres:
9127 {
9128 struct timespec ts;
9129 ret = get_errno(clock_getres(arg1, &ts));
9130 if (!is_error(ret)) {
9131 host_to_target_timespec(arg2, &ts);
9132 }
9133 break;
9134 }
9135#endif
63d7651b
PB
9136#ifdef TARGET_NR_clock_nanosleep
9137 case TARGET_NR_clock_nanosleep:
9138 {
9139 struct timespec ts;
9140 target_to_host_timespec(&ts, arg3);
9141 ret = get_errno(clock_nanosleep(arg1, arg2, &ts, arg4 ? &ts : NULL));
9142 if (arg4)
9143 host_to_target_timespec(arg4, &ts);
8fbe8fdf
TM
9144
9145#if defined(TARGET_PPC)
9146 /* clock_nanosleep is odd in that it returns positive errno values.
9147 * On PPC, CR0 bit 3 should be set in such a situation. */
9148 if (ret) {
9149 ((CPUPPCState *)cpu_env)->crf[0] |= 1;
9150 }
9151#endif
63d7651b
PB
9152 break;
9153 }
9154#endif
b5906f95 9155
6f5b89a0
TS
9156#if defined(TARGET_NR_set_tid_address) && defined(__NR_set_tid_address)
9157 case TARGET_NR_set_tid_address:
579a97f7
FB
9158 ret = get_errno(set_tid_address((int *)g2h(arg1)));
9159 break;
6f5b89a0
TS
9160#endif
9161
3ae43202 9162#if defined(TARGET_NR_tkill) && defined(__NR_tkill)
4cae1d16 9163 case TARGET_NR_tkill:
4cb05961 9164 ret = get_errno(sys_tkill((int)arg1, target_to_host_signal(arg2)));
4cae1d16
TS
9165 break;
9166#endif
9167
3ae43202 9168#if defined(TARGET_NR_tgkill) && defined(__NR_tgkill)
71455574 9169 case TARGET_NR_tgkill:
4cb05961
PB
9170 ret = get_errno(sys_tgkill((int)arg1, (int)arg2,
9171 target_to_host_signal(arg3)));
71455574
TS
9172 break;
9173#endif
9174
4f2b1fe8
TS
9175#ifdef TARGET_NR_set_robust_list
9176 case TARGET_NR_set_robust_list:
e9a970a8
PM
9177 case TARGET_NR_get_robust_list:
9178 /* The ABI for supporting robust futexes has userspace pass
9179 * the kernel a pointer to a linked list which is updated by
9180 * userspace after the syscall; the list is walked by the kernel
9181 * when the thread exits. Since the linked list in QEMU guest
9182 * memory isn't a valid linked list for the host and we have
9183 * no way to reliably intercept the thread-death event, we can't
9184 * support these. Silently return ENOSYS so that guest userspace
9185 * falls back to a non-robust futex implementation (which should
9186 * be OK except in the corner case of the guest crashing while
9187 * holding a mutex that is shared with another process via
9188 * shared memory).
9189 */
9190 goto unimplemented_nowarn;
4f2b1fe8
TS
9191#endif
9192
1acae9f2 9193#if defined(TARGET_NR_utimensat)
9007f0ef
TS
9194 case TARGET_NR_utimensat:
9195 {
ebc996f3
RV
9196 struct timespec *tsp, ts[2];
9197 if (!arg3) {
9198 tsp = NULL;
9199 } else {
9200 target_to_host_timespec(ts, arg3);
9201 target_to_host_timespec(ts+1, arg3+sizeof(struct target_timespec));
9202 tsp = ts;
9203 }
9007f0ef 9204 if (!arg2)
ebc996f3 9205 ret = get_errno(sys_utimensat(arg1, NULL, tsp, arg4));
9007f0ef 9206 else {
579a97f7 9207 if (!(p = lock_user_string(arg2))) {
0da46a6e 9208 ret = -TARGET_EFAULT;
579a97f7
FB
9209 goto fail;
9210 }
ebc996f3 9211 ret = get_errno(sys_utimensat(arg1, path(p), tsp, arg4));
579a97f7 9212 unlock_user(p, arg2, 0);
9007f0ef
TS
9213 }
9214 }
9215 break;
9216#endif
bd0c5661
PB
9217 case TARGET_NR_futex:
9218 ret = do_futex(arg1, arg2, arg3, arg4, arg5, arg6);
9219 break;
dbfe4c36 9220#if defined(TARGET_NR_inotify_init) && defined(__NR_inotify_init)
39b59763
AJ
9221 case TARGET_NR_inotify_init:
9222 ret = get_errno(sys_inotify_init());
9223 break;
9224#endif
a1606b0b 9225#ifdef CONFIG_INOTIFY1
c05c7a73
RV
9226#if defined(TARGET_NR_inotify_init1) && defined(__NR_inotify_init1)
9227 case TARGET_NR_inotify_init1:
9228 ret = get_errno(sys_inotify_init1(arg1));
9229 break;
9230#endif
a1606b0b 9231#endif
dbfe4c36 9232#if defined(TARGET_NR_inotify_add_watch) && defined(__NR_inotify_add_watch)
39b59763
AJ
9233 case TARGET_NR_inotify_add_watch:
9234 p = lock_user_string(arg2);
9235 ret = get_errno(sys_inotify_add_watch(arg1, path(p), arg3));
9236 unlock_user(p, arg2, 0);
9237 break;
9238#endif
dbfe4c36 9239#if defined(TARGET_NR_inotify_rm_watch) && defined(__NR_inotify_rm_watch)
39b59763
AJ
9240 case TARGET_NR_inotify_rm_watch:
9241 ret = get_errno(sys_inotify_rm_watch(arg1, arg2));
9242 break;
9243#endif
9007f0ef 9244
8ec9cf89 9245#if defined(TARGET_NR_mq_open) && defined(__NR_mq_open)
24e1003a
AJ
9246 case TARGET_NR_mq_open:
9247 {
b6ce1f6b 9248 struct mq_attr posix_mq_attr, *attrp;
24e1003a
AJ
9249
9250 p = lock_user_string(arg1 - 1);
b6ce1f6b 9251 if (arg4 != 0) {
24e1003a 9252 copy_from_user_mq_attr (&posix_mq_attr, arg4);
b6ce1f6b
TM
9253 attrp = &posix_mq_attr;
9254 } else {
9255 attrp = 0;
9256 }
9257 ret = get_errno(mq_open(p, arg2, arg3, attrp));
24e1003a
AJ
9258 unlock_user (p, arg1, 0);
9259 }
9260 break;
9261
9262 case TARGET_NR_mq_unlink:
9263 p = lock_user_string(arg1 - 1);
9264 ret = get_errno(mq_unlink(p));
9265 unlock_user (p, arg1, 0);
9266 break;
9267
9268 case TARGET_NR_mq_timedsend:
9269 {
9270 struct timespec ts;
9271
9272 p = lock_user (VERIFY_READ, arg2, arg3, 1);
9273 if (arg5 != 0) {
9274 target_to_host_timespec(&ts, arg5);
9275 ret = get_errno(mq_timedsend(arg1, p, arg3, arg4, &ts));
9276 host_to_target_timespec(arg5, &ts);
9277 }
9278 else
9279 ret = get_errno(mq_send(arg1, p, arg3, arg4));
9280 unlock_user (p, arg2, arg3);
9281 }
9282 break;
9283
9284 case TARGET_NR_mq_timedreceive:
9285 {
9286 struct timespec ts;
9287 unsigned int prio;
9288
9289 p = lock_user (VERIFY_READ, arg2, arg3, 1);
9290 if (arg5 != 0) {
9291 target_to_host_timespec(&ts, arg5);
9292 ret = get_errno(mq_timedreceive(arg1, p, arg3, &prio, &ts));
9293 host_to_target_timespec(arg5, &ts);
9294 }
9295 else
9296 ret = get_errno(mq_receive(arg1, p, arg3, &prio));
9297 unlock_user (p, arg2, arg3);
9298 if (arg4 != 0)
9299 put_user_u32(prio, arg4);
9300 }
9301 break;
9302
9303 /* Not implemented for now... */
9304/* case TARGET_NR_mq_notify: */
9305/* break; */
9306
9307 case TARGET_NR_mq_getsetattr:
9308 {
9309 struct mq_attr posix_mq_attr_in, posix_mq_attr_out;
9310 ret = 0;
9311 if (arg3 != 0) {
9312 ret = mq_getattr(arg1, &posix_mq_attr_out);
9313 copy_to_user_mq_attr(arg3, &posix_mq_attr_out);
9314 }
9315 if (arg2 != 0) {
9316 copy_from_user_mq_attr(&posix_mq_attr_in, arg2);
9317 ret |= mq_setattr(arg1, &posix_mq_attr_in, &posix_mq_attr_out);
9318 }
9319
9320 }
9321 break;
9322#endif
9323
3ce34dfb
VS
9324#ifdef CONFIG_SPLICE
9325#ifdef TARGET_NR_tee
9326 case TARGET_NR_tee:
9327 {
9328 ret = get_errno(tee(arg1,arg2,arg3,arg4));
9329 }
9330 break;
9331#endif
9332#ifdef TARGET_NR_splice
9333 case TARGET_NR_splice:
9334 {
9335 loff_t loff_in, loff_out;
9336 loff_t *ploff_in = NULL, *ploff_out = NULL;
9337 if(arg2) {
9338 get_user_u64(loff_in, arg2);
9339 ploff_in = &loff_in;
9340 }
9341 if(arg4) {
9342 get_user_u64(loff_out, arg2);
9343 ploff_out = &loff_out;
9344 }
9345 ret = get_errno(splice(arg1, ploff_in, arg3, ploff_out, arg5, arg6));
9346 }
9347 break;
9348#endif
9349#ifdef TARGET_NR_vmsplice
9350 case TARGET_NR_vmsplice:
9351 {
f287b2c2
RH
9352 struct iovec *vec = lock_iovec(VERIFY_READ, arg2, arg3, 1);
9353 if (vec != NULL) {
9354 ret = get_errno(vmsplice(arg1, vec, arg3, arg4));
9355 unlock_iovec(vec, arg2, arg3, 0);
9356 } else {
9357 ret = -host_to_target_errno(errno);
9358 }
3ce34dfb
VS
9359 }
9360 break;
9361#endif
9362#endif /* CONFIG_SPLICE */
c2882b96
RV
9363#ifdef CONFIG_EVENTFD
9364#if defined(TARGET_NR_eventfd)
9365 case TARGET_NR_eventfd:
9366 ret = get_errno(eventfd(arg1, 0));
9367 break;
9368#endif
9369#if defined(TARGET_NR_eventfd2)
9370 case TARGET_NR_eventfd2:
5947c697
PJ
9371 {
9372 int host_flags = arg2 & (~(TARGET_O_NONBLOCK | TARGET_O_CLOEXEC));
9373 if (arg2 & TARGET_O_NONBLOCK) {
9374 host_flags |= O_NONBLOCK;
9375 }
9376 if (arg2 & TARGET_O_CLOEXEC) {
9377 host_flags |= O_CLOEXEC;
9378 }
9379 ret = get_errno(eventfd(arg1, host_flags));
c2882b96 9380 break;
5947c697 9381 }
c2882b96
RV
9382#endif
9383#endif /* CONFIG_EVENTFD */
d0927938
UH
9384#if defined(CONFIG_FALLOCATE) && defined(TARGET_NR_fallocate)
9385 case TARGET_NR_fallocate:
20249ae1
AG
9386#if TARGET_ABI_BITS == 32
9387 ret = get_errno(fallocate(arg1, arg2, target_offset64(arg3, arg4),
9388 target_offset64(arg5, arg6)));
9389#else
d0927938 9390 ret = get_errno(fallocate(arg1, arg2, arg3, arg4));
20249ae1 9391#endif
d0927938 9392 break;
c727f47d
PM
9393#endif
9394#if defined(CONFIG_SYNC_FILE_RANGE)
9395#if defined(TARGET_NR_sync_file_range)
9396 case TARGET_NR_sync_file_range:
9397#if TARGET_ABI_BITS == 32
bfcedc57
RV
9398#if defined(TARGET_MIPS)
9399 ret = get_errno(sync_file_range(arg1, target_offset64(arg3, arg4),
9400 target_offset64(arg5, arg6), arg7));
9401#else
c727f47d
PM
9402 ret = get_errno(sync_file_range(arg1, target_offset64(arg2, arg3),
9403 target_offset64(arg4, arg5), arg6));
bfcedc57 9404#endif /* !TARGET_MIPS */
c727f47d
PM
9405#else
9406 ret = get_errno(sync_file_range(arg1, arg2, arg3, arg4));
9407#endif
9408 break;
9409#endif
9410#if defined(TARGET_NR_sync_file_range2)
9411 case TARGET_NR_sync_file_range2:
9412 /* This is like sync_file_range but the arguments are reordered */
9413#if TARGET_ABI_BITS == 32
9414 ret = get_errno(sync_file_range(arg1, target_offset64(arg3, arg4),
9415 target_offset64(arg5, arg6), arg2));
9416#else
9417 ret = get_errno(sync_file_range(arg1, arg3, arg4, arg2));
9418#endif
9419 break;
9420#endif
3b6edd16
PM
9421#endif
9422#if defined(CONFIG_EPOLL)
9423#if defined(TARGET_NR_epoll_create)
9424 case TARGET_NR_epoll_create:
9425 ret = get_errno(epoll_create(arg1));
9426 break;
9427#endif
9428#if defined(TARGET_NR_epoll_create1) && defined(CONFIG_EPOLL_CREATE1)
9429 case TARGET_NR_epoll_create1:
9430 ret = get_errno(epoll_create1(arg1));
9431 break;
9432#endif
9433#if defined(TARGET_NR_epoll_ctl)
9434 case TARGET_NR_epoll_ctl:
9435 {
9436 struct epoll_event ep;
9437 struct epoll_event *epp = 0;
9438 if (arg4) {
9439 struct target_epoll_event *target_ep;
9440 if (!lock_user_struct(VERIFY_READ, target_ep, arg4, 1)) {
9441 goto efault;
9442 }
9443 ep.events = tswap32(target_ep->events);
9444 /* The epoll_data_t union is just opaque data to the kernel,
9445 * so we transfer all 64 bits across and need not worry what
9446 * actual data type it is.
9447 */
9448 ep.data.u64 = tswap64(target_ep->data.u64);
9449 unlock_user_struct(target_ep, arg4, 0);
9450 epp = &ep;
9451 }
9452 ret = get_errno(epoll_ctl(arg1, arg2, arg3, epp));
9453 break;
9454 }
9455#endif
9456
9457#if defined(TARGET_NR_epoll_pwait) && defined(CONFIG_EPOLL_PWAIT)
9458#define IMPLEMENT_EPOLL_PWAIT
9459#endif
9460#if defined(TARGET_NR_epoll_wait) || defined(IMPLEMENT_EPOLL_PWAIT)
9461#if defined(TARGET_NR_epoll_wait)
9462 case TARGET_NR_epoll_wait:
9463#endif
9464#if defined(IMPLEMENT_EPOLL_PWAIT)
9465 case TARGET_NR_epoll_pwait:
9466#endif
9467 {
9468 struct target_epoll_event *target_ep;
9469 struct epoll_event *ep;
9470 int epfd = arg1;
9471 int maxevents = arg3;
9472 int timeout = arg4;
9473
9474 target_ep = lock_user(VERIFY_WRITE, arg2,
9475 maxevents * sizeof(struct target_epoll_event), 1);
9476 if (!target_ep) {
9477 goto efault;
9478 }
9479
9480 ep = alloca(maxevents * sizeof(struct epoll_event));
9481
9482 switch (num) {
9483#if defined(IMPLEMENT_EPOLL_PWAIT)
9484 case TARGET_NR_epoll_pwait:
9485 {
9486 target_sigset_t *target_set;
9487 sigset_t _set, *set = &_set;
9488
9489 if (arg5) {
9490 target_set = lock_user(VERIFY_READ, arg5,
9491 sizeof(target_sigset_t), 1);
9492 if (!target_set) {
9493 unlock_user(target_ep, arg2, 0);
9494 goto efault;
9495 }
9496 target_to_host_sigset(set, target_set);
9497 unlock_user(target_set, arg5, 0);
9498 } else {
9499 set = NULL;
9500 }
9501
9502 ret = get_errno(epoll_pwait(epfd, ep, maxevents, timeout, set));
9503 break;
9504 }
9505#endif
9506#if defined(TARGET_NR_epoll_wait)
9507 case TARGET_NR_epoll_wait:
9508 ret = get_errno(epoll_wait(epfd, ep, maxevents, timeout));
9509 break;
9510#endif
9511 default:
9512 ret = -TARGET_ENOSYS;
9513 }
9514 if (!is_error(ret)) {
9515 int i;
9516 for (i = 0; i < ret; i++) {
9517 target_ep[i].events = tswap32(ep[i].events);
9518 target_ep[i].data.u64 = tswap64(ep[i].data.u64);
9519 }
9520 }
9521 unlock_user(target_ep, arg2, ret * sizeof(struct target_epoll_event));
9522 break;
9523 }
9524#endif
163a05a8
PM
9525#endif
9526#ifdef TARGET_NR_prlimit64
9527 case TARGET_NR_prlimit64:
9528 {
9529 /* args: pid, resource number, ptr to new rlimit, ptr to old rlimit */
9530 struct target_rlimit64 *target_rnew, *target_rold;
9531 struct host_rlimit64 rnew, rold, *rnewp = 0;
95018018 9532 int resource = target_to_host_resource(arg2);
163a05a8
PM
9533 if (arg3) {
9534 if (!lock_user_struct(VERIFY_READ, target_rnew, arg3, 1)) {
9535 goto efault;
9536 }
9537 rnew.rlim_cur = tswap64(target_rnew->rlim_cur);
9538 rnew.rlim_max = tswap64(target_rnew->rlim_max);
9539 unlock_user_struct(target_rnew, arg3, 0);
9540 rnewp = &rnew;
9541 }
9542
95018018 9543 ret = get_errno(sys_prlimit64(arg1, resource, rnewp, arg4 ? &rold : 0));
163a05a8
PM
9544 if (!is_error(ret) && arg4) {
9545 if (!lock_user_struct(VERIFY_WRITE, target_rold, arg4, 1)) {
9546 goto efault;
9547 }
9548 target_rold->rlim_cur = tswap64(rold.rlim_cur);
9549 target_rold->rlim_max = tswap64(rold.rlim_max);
9550 unlock_user_struct(target_rold, arg4, 1);
9551 }
9552 break;
9553 }
3d21d29c
RH
9554#endif
9555#ifdef TARGET_NR_gethostname
9556 case TARGET_NR_gethostname:
9557 {
9558 char *name = lock_user(VERIFY_WRITE, arg1, arg2, 0);
9559 if (name) {
9560 ret = get_errno(gethostname(name, arg2));
9561 unlock_user(name, arg1, arg2);
9562 } else {
9563 ret = -TARGET_EFAULT;
9564 }
9565 break;
9566 }
89aaf1a6
RV
9567#endif
9568#ifdef TARGET_NR_atomic_cmpxchg_32
9569 case TARGET_NR_atomic_cmpxchg_32:
9570 {
9571 /* should use start_exclusive from main.c */
9572 abi_ulong mem_value;
9573 if (get_user_u32(mem_value, arg6)) {
9574 target_siginfo_t info;
9575 info.si_signo = SIGSEGV;
9576 info.si_errno = 0;
9577 info.si_code = TARGET_SEGV_MAPERR;
9578 info._sifields._sigfault._addr = arg6;
9579 queue_signal((CPUArchState *)cpu_env, info.si_signo, &info);
9580 ret = 0xdeadbeef;
9581
9582 }
9583 if (mem_value == arg2)
9584 put_user_u32(arg1, arg6);
9585 ret = mem_value;
9586 break;
9587 }
9588#endif
9589#ifdef TARGET_NR_atomic_barrier
9590 case TARGET_NR_atomic_barrier:
9591 {
9592 /* Like the kernel implementation and the qemu arm barrier, no-op this? */
3b899ea7 9593 ret = 0;
89aaf1a6
RV
9594 break;
9595 }
d0927938 9596#endif
f4f1e10a
ECL
9597
9598#ifdef TARGET_NR_timer_create
9599 case TARGET_NR_timer_create:
9600 {
9601 /* args: clockid_t clockid, struct sigevent *sevp, timer_t *timerid */
9602
9603 struct sigevent host_sevp = { {0}, }, *phost_sevp = NULL;
f4f1e10a
ECL
9604
9605 int clkid = arg1;
9606 int timer_index = next_free_host_timer();
9607
9608 if (timer_index < 0) {
9609 ret = -TARGET_EAGAIN;
9610 } else {
9611 timer_t *phtimer = g_posix_timers + timer_index;
9612
9613 if (arg2) {
f4f1e10a 9614 phost_sevp = &host_sevp;
c065976f
PM
9615 ret = target_to_host_sigevent(phost_sevp, arg2);
9616 if (ret != 0) {
9617 break;
9618 }
f4f1e10a
ECL
9619 }
9620
9621 ret = get_errno(timer_create(clkid, phost_sevp, phtimer));
9622 if (ret) {
9623 phtimer = NULL;
9624 } else {
aecc8861 9625 if (put_user(TIMER_MAGIC | timer_index, arg3, target_timer_t)) {
f4f1e10a
ECL
9626 goto efault;
9627 }
f4f1e10a
ECL
9628 }
9629 }
9630 break;
9631 }
9632#endif
9633
9634#ifdef TARGET_NR_timer_settime
9635 case TARGET_NR_timer_settime:
9636 {
9637 /* args: timer_t timerid, int flags, const struct itimerspec *new_value,
9638 * struct itimerspec * old_value */
aecc8861 9639 target_timer_t timerid = get_timer_id(arg1);
e52a99f7 9640
aecc8861
AG
9641 if (timerid < 0) {
9642 ret = timerid;
9643 } else if (arg3 == 0) {
f4f1e10a
ECL
9644 ret = -TARGET_EINVAL;
9645 } else {
e52a99f7 9646 timer_t htimer = g_posix_timers[timerid];
f4f1e10a
ECL
9647 struct itimerspec hspec_new = {{0},}, hspec_old = {{0},};
9648
9649 target_to_host_itimerspec(&hspec_new, arg3);
9650 ret = get_errno(
9651 timer_settime(htimer, arg2, &hspec_new, &hspec_old));
9652 host_to_target_itimerspec(arg2, &hspec_old);
9653 }
9654 break;
9655 }
9656#endif
9657
9658#ifdef TARGET_NR_timer_gettime
9659 case TARGET_NR_timer_gettime:
9660 {
9661 /* args: timer_t timerid, struct itimerspec *curr_value */
aecc8861 9662 target_timer_t timerid = get_timer_id(arg1);
e52a99f7 9663
aecc8861
AG
9664 if (timerid < 0) {
9665 ret = timerid;
9666 } else if (!arg2) {
9667 ret = -TARGET_EFAULT;
f4f1e10a 9668 } else {
e52a99f7 9669 timer_t htimer = g_posix_timers[timerid];
f4f1e10a
ECL
9670 struct itimerspec hspec;
9671 ret = get_errno(timer_gettime(htimer, &hspec));
9672
9673 if (host_to_target_itimerspec(arg2, &hspec)) {
9674 ret = -TARGET_EFAULT;
9675 }
9676 }
9677 break;
9678 }
9679#endif
9680
9681#ifdef TARGET_NR_timer_getoverrun
9682 case TARGET_NR_timer_getoverrun:
9683 {
9684 /* args: timer_t timerid */
aecc8861 9685 target_timer_t timerid = get_timer_id(arg1);
e52a99f7 9686
aecc8861
AG
9687 if (timerid < 0) {
9688 ret = timerid;
f4f1e10a 9689 } else {
e52a99f7 9690 timer_t htimer = g_posix_timers[timerid];
f4f1e10a
ECL
9691 ret = get_errno(timer_getoverrun(htimer));
9692 }
9693 break;
9694 }
9695#endif
9696
9697#ifdef TARGET_NR_timer_delete
9698 case TARGET_NR_timer_delete:
9699 {
9700 /* args: timer_t timerid */
aecc8861 9701 target_timer_t timerid = get_timer_id(arg1);
e52a99f7 9702
aecc8861
AG
9703 if (timerid < 0) {
9704 ret = timerid;
f4f1e10a 9705 } else {
e52a99f7 9706 timer_t htimer = g_posix_timers[timerid];
f4f1e10a 9707 ret = get_errno(timer_delete(htimer));
e52a99f7 9708 g_posix_timers[timerid] = 0;
f4f1e10a
ECL
9709 }
9710 break;
9711 }
9712#endif
9713
51834341
RV
9714#if defined(TARGET_NR_timerfd_create) && defined(CONFIG_TIMERFD)
9715 case TARGET_NR_timerfd_create:
9716 ret = get_errno(timerfd_create(arg1,
9717 target_to_host_bitmask(arg2, fcntl_flags_tbl)));
9718 break;
9719#endif
9720
9721#if defined(TARGET_NR_timerfd_gettime) && defined(CONFIG_TIMERFD)
9722 case TARGET_NR_timerfd_gettime:
9723 {
9724 struct itimerspec its_curr;
9725
9726 ret = get_errno(timerfd_gettime(arg1, &its_curr));
9727
9728 if (arg2 && host_to_target_itimerspec(arg2, &its_curr)) {
9729 goto efault;
9730 }
9731 }
9732 break;
9733#endif
9734
9735#if defined(TARGET_NR_timerfd_settime) && defined(CONFIG_TIMERFD)
9736 case TARGET_NR_timerfd_settime:
9737 {
9738 struct itimerspec its_new, its_old, *p_new;
9739
9740 if (arg3) {
9741 if (target_to_host_itimerspec(&its_new, arg3)) {
9742 goto efault;
9743 }
9744 p_new = &its_new;
9745 } else {
9746 p_new = NULL;
9747 }
9748
9749 ret = get_errno(timerfd_settime(arg1, arg2, p_new, &its_old));
9750
9751 if (arg4 && host_to_target_itimerspec(arg4, &its_old)) {
9752 goto efault;
9753 }
9754 }
9755 break;
9756#endif
9757
ab31cda3
PB
9758#if defined(TARGET_NR_ioprio_get) && defined(__NR_ioprio_get)
9759 case TARGET_NR_ioprio_get:
9760 ret = get_errno(ioprio_get(arg1, arg2));
9761 break;
9762#endif
9763
9764#if defined(TARGET_NR_ioprio_set) && defined(__NR_ioprio_set)
9765 case TARGET_NR_ioprio_set:
9766 ret = get_errno(ioprio_set(arg1, arg2, arg3));
9767 break;
9768#endif
9769
9af5c906
RV
9770#if defined(TARGET_NR_setns) && defined(CONFIG_SETNS)
9771 case TARGET_NR_setns:
9772 ret = get_errno(setns(arg1, arg2));
9773 break;
9774#endif
9775#if defined(TARGET_NR_unshare) && defined(CONFIG_SETNS)
9776 case TARGET_NR_unshare:
9777 ret = get_errno(unshare(arg1));
9778 break;
9779#endif
9780
31e31b8a
FB
9781 default:
9782 unimplemented:
5cd4393b 9783 gemu_log("qemu: Unsupported syscall: %d\n", num);
4f2b1fe8 9784#if defined(TARGET_NR_setxattr) || defined(TARGET_NR_get_thread_area) || defined(TARGET_NR_getdomainname) || defined(TARGET_NR_set_robust_list)
5cd4393b 9785 unimplemented_nowarn:
80a9d035 9786#endif
0da46a6e 9787 ret = -TARGET_ENOSYS;
31e31b8a
FB
9788 break;
9789 }
579a97f7 9790fail:
c573ff67 9791#ifdef DEBUG
0bf9e31a 9792 gemu_log(" = " TARGET_ABI_FMT_ld "\n", ret);
c573ff67 9793#endif
b92c47c1
TS
9794 if(do_strace)
9795 print_syscall_ret(num, ret);
31e31b8a 9796 return ret;
579a97f7
FB
9797efault:
9798 ret = -TARGET_EFAULT;
9799 goto fail;
31e31b8a 9800}