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