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