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