]> git.ipfire.org Git - thirdparty/qemu.git/blame - linux-user/syscall.c
linux-user: correct timerfd_create syscall numbers
[thirdparty/qemu.git] / linux-user / syscall.c
CommitLineData
31e31b8a
FB
1/*
2 * Linux syscalls
5fafdf24 3 *
31e31b8a
FB
4 * Copyright (c) 2003 Fabrice Bellard
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
8167ee88 17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
31e31b8a 18 */
d5b3a9b6 19#define _ATFILE_SOURCE
d39594e9 20#include "qemu/osdep.h"
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 */
5089c7ce
LV
321 target_fd_trans = g_renew(TargetFdTrans *,
322 target_fd_trans, target_fd_max);
e36800c9
LV
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 {
b6e17875
PM
2601 abi_ulong start;
2602 abi_ulong size;
2603 bool in_use;
8853f86e
FB
2604} shm_regions[N_SHM_REGIONS];
2605
3eb6b044
TS
2606struct target_semid_ds
2607{
2608 struct target_ipc_perm sem_perm;
992f48a0 2609 abi_ulong sem_otime;
03527344 2610#if !defined(TARGET_PPC64)
992f48a0 2611 abi_ulong __unused1;
03527344 2612#endif
992f48a0 2613 abi_ulong sem_ctime;
03527344 2614#if !defined(TARGET_PPC64)
992f48a0 2615 abi_ulong __unused2;
03527344 2616#endif
992f48a0
BS
2617 abi_ulong sem_nsems;
2618 abi_ulong __unused3;
2619 abi_ulong __unused4;
3eb6b044
TS
2620};
2621
579a97f7
FB
2622static inline abi_long target_to_host_ipc_perm(struct ipc_perm *host_ip,
2623 abi_ulong target_addr)
3eb6b044
TS
2624{
2625 struct target_ipc_perm *target_ip;
2626 struct target_semid_ds *target_sd;
2627
579a97f7
FB
2628 if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
2629 return -TARGET_EFAULT;
e8bbe36c 2630 target_ip = &(target_sd->sem_perm);
55a2b163
PJ
2631 host_ip->__key = tswap32(target_ip->__key);
2632 host_ip->uid = tswap32(target_ip->uid);
2633 host_ip->gid = tswap32(target_ip->gid);
2634 host_ip->cuid = tswap32(target_ip->cuid);
2635 host_ip->cgid = tswap32(target_ip->cgid);
2636#if defined(TARGET_ALPHA) || defined(TARGET_MIPS) || defined(TARGET_PPC)
2637 host_ip->mode = tswap32(target_ip->mode);
2638#else
cbb21eed 2639 host_ip->mode = tswap16(target_ip->mode);
55a2b163
PJ
2640#endif
2641#if defined(TARGET_PPC)
2642 host_ip->__seq = tswap32(target_ip->__seq);
2643#else
2644 host_ip->__seq = tswap16(target_ip->__seq);
2645#endif
3eb6b044 2646 unlock_user_struct(target_sd, target_addr, 0);
579a97f7 2647 return 0;
3eb6b044
TS
2648}
2649
579a97f7
FB
2650static inline abi_long host_to_target_ipc_perm(abi_ulong target_addr,
2651 struct ipc_perm *host_ip)
3eb6b044
TS
2652{
2653 struct target_ipc_perm *target_ip;
2654 struct target_semid_ds *target_sd;
2655
579a97f7
FB
2656 if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
2657 return -TARGET_EFAULT;
3eb6b044 2658 target_ip = &(target_sd->sem_perm);
55a2b163
PJ
2659 target_ip->__key = tswap32(host_ip->__key);
2660 target_ip->uid = tswap32(host_ip->uid);
2661 target_ip->gid = tswap32(host_ip->gid);
2662 target_ip->cuid = tswap32(host_ip->cuid);
2663 target_ip->cgid = tswap32(host_ip->cgid);
2664#if defined(TARGET_ALPHA) || defined(TARGET_MIPS) || defined(TARGET_PPC)
2665 target_ip->mode = tswap32(host_ip->mode);
2666#else
cbb21eed 2667 target_ip->mode = tswap16(host_ip->mode);
55a2b163
PJ
2668#endif
2669#if defined(TARGET_PPC)
2670 target_ip->__seq = tswap32(host_ip->__seq);
2671#else
2672 target_ip->__seq = tswap16(host_ip->__seq);
2673#endif
3eb6b044 2674 unlock_user_struct(target_sd, target_addr, 1);
579a97f7 2675 return 0;
3eb6b044
TS
2676}
2677
579a97f7
FB
2678static inline abi_long target_to_host_semid_ds(struct semid_ds *host_sd,
2679 abi_ulong target_addr)
3eb6b044
TS
2680{
2681 struct target_semid_ds *target_sd;
2682
579a97f7
FB
2683 if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
2684 return -TARGET_EFAULT;
e5289087
AJ
2685 if (target_to_host_ipc_perm(&(host_sd->sem_perm),target_addr))
2686 return -TARGET_EFAULT;
cbb21eed
MB
2687 host_sd->sem_nsems = tswapal(target_sd->sem_nsems);
2688 host_sd->sem_otime = tswapal(target_sd->sem_otime);
2689 host_sd->sem_ctime = tswapal(target_sd->sem_ctime);
3eb6b044 2690 unlock_user_struct(target_sd, target_addr, 0);
579a97f7 2691 return 0;
3eb6b044
TS
2692}
2693
579a97f7
FB
2694static inline abi_long host_to_target_semid_ds(abi_ulong target_addr,
2695 struct semid_ds *host_sd)
3eb6b044
TS
2696{
2697 struct target_semid_ds *target_sd;
2698
579a97f7
FB
2699 if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
2700 return -TARGET_EFAULT;
e5289087 2701 if (host_to_target_ipc_perm(target_addr,&(host_sd->sem_perm)))
3a93113a 2702 return -TARGET_EFAULT;
cbb21eed
MB
2703 target_sd->sem_nsems = tswapal(host_sd->sem_nsems);
2704 target_sd->sem_otime = tswapal(host_sd->sem_otime);
2705 target_sd->sem_ctime = tswapal(host_sd->sem_ctime);
3eb6b044 2706 unlock_user_struct(target_sd, target_addr, 1);
579a97f7 2707 return 0;
3eb6b044
TS
2708}
2709
e5289087
AJ
2710struct target_seminfo {
2711 int semmap;
2712 int semmni;
2713 int semmns;
2714 int semmnu;
2715 int semmsl;
2716 int semopm;
2717 int semume;
2718 int semusz;
2719 int semvmx;
2720 int semaem;
2721};
2722
2723static inline abi_long host_to_target_seminfo(abi_ulong target_addr,
2724 struct seminfo *host_seminfo)
2725{
2726 struct target_seminfo *target_seminfo;
2727 if (!lock_user_struct(VERIFY_WRITE, target_seminfo, target_addr, 0))
2728 return -TARGET_EFAULT;
2729 __put_user(host_seminfo->semmap, &target_seminfo->semmap);
2730 __put_user(host_seminfo->semmni, &target_seminfo->semmni);
2731 __put_user(host_seminfo->semmns, &target_seminfo->semmns);
2732 __put_user(host_seminfo->semmnu, &target_seminfo->semmnu);
2733 __put_user(host_seminfo->semmsl, &target_seminfo->semmsl);
2734 __put_user(host_seminfo->semopm, &target_seminfo->semopm);
2735 __put_user(host_seminfo->semume, &target_seminfo->semume);
2736 __put_user(host_seminfo->semusz, &target_seminfo->semusz);
2737 __put_user(host_seminfo->semvmx, &target_seminfo->semvmx);
2738 __put_user(host_seminfo->semaem, &target_seminfo->semaem);
2739 unlock_user_struct(target_seminfo, target_addr, 1);
2740 return 0;
2741}
2742
fa294816
TS
2743union semun {
2744 int val;
3eb6b044 2745 struct semid_ds *buf;
fa294816 2746 unsigned short *array;
e5289087 2747 struct seminfo *__buf;
fa294816
TS
2748};
2749
3eb6b044
TS
2750union target_semun {
2751 int val;
e5289087
AJ
2752 abi_ulong buf;
2753 abi_ulong array;
2754 abi_ulong __buf;
3eb6b044
TS
2755};
2756
e5289087
AJ
2757static inline abi_long target_to_host_semarray(int semid, unsigned short **host_array,
2758 abi_ulong target_addr)
3eb6b044 2759{
e5289087
AJ
2760 int nsems;
2761 unsigned short *array;
2762 union semun semun;
2763 struct semid_ds semid_ds;
2764 int i, ret;
3eb6b044 2765
e5289087
AJ
2766 semun.buf = &semid_ds;
2767
2768 ret = semctl(semid, 0, IPC_STAT, semun);
2769 if (ret == -1)
2770 return get_errno(ret);
2771
2772 nsems = semid_ds.sem_nsems;
2773
0e173b24 2774 *host_array = g_try_new(unsigned short, nsems);
69d4c703
PM
2775 if (!*host_array) {
2776 return -TARGET_ENOMEM;
2777 }
e5289087
AJ
2778 array = lock_user(VERIFY_READ, target_addr,
2779 nsems*sizeof(unsigned short), 1);
69d4c703 2780 if (!array) {
0e173b24 2781 g_free(*host_array);
e5289087 2782 return -TARGET_EFAULT;
69d4c703 2783 }
e5289087
AJ
2784
2785 for(i=0; i<nsems; i++) {
2786 __get_user((*host_array)[i], &array[i]);
3eb6b044 2787 }
e5289087
AJ
2788 unlock_user(array, target_addr, 0);
2789
579a97f7 2790 return 0;
3eb6b044
TS
2791}
2792
e5289087
AJ
2793static inline abi_long host_to_target_semarray(int semid, abi_ulong target_addr,
2794 unsigned short **host_array)
3eb6b044 2795{
e5289087
AJ
2796 int nsems;
2797 unsigned short *array;
2798 union semun semun;
2799 struct semid_ds semid_ds;
2800 int i, ret;
3eb6b044 2801
e5289087
AJ
2802 semun.buf = &semid_ds;
2803
2804 ret = semctl(semid, 0, IPC_STAT, semun);
2805 if (ret == -1)
2806 return get_errno(ret);
2807
2808 nsems = semid_ds.sem_nsems;
2809
2810 array = lock_user(VERIFY_WRITE, target_addr,
2811 nsems*sizeof(unsigned short), 0);
2812 if (!array)
2813 return -TARGET_EFAULT;
2814
2815 for(i=0; i<nsems; i++) {
2816 __put_user((*host_array)[i], &array[i]);
3eb6b044 2817 }
0e173b24 2818 g_free(*host_array);
e5289087
AJ
2819 unlock_user(array, target_addr, 1);
2820
579a97f7 2821 return 0;
3eb6b044
TS
2822}
2823
e5289087 2824static inline abi_long do_semctl(int semid, int semnum, int cmd,
d1c002b6 2825 abi_ulong target_arg)
3eb6b044 2826{
d1c002b6 2827 union target_semun target_su = { .buf = target_arg };
3eb6b044
TS
2828 union semun arg;
2829 struct semid_ds dsarg;
7b8118e8 2830 unsigned short *array = NULL;
e5289087
AJ
2831 struct seminfo seminfo;
2832 abi_long ret = -TARGET_EINVAL;
2833 abi_long err;
2834 cmd &= 0xff;
3eb6b044
TS
2835
2836 switch( cmd ) {
2837 case GETVAL:
3eb6b044 2838 case SETVAL:
5464baec
TM
2839 /* In 64 bit cross-endian situations, we will erroneously pick up
2840 * the wrong half of the union for the "val" element. To rectify
2841 * this, the entire 8-byte structure is byteswapped, followed by
2842 * a swap of the 4 byte val field. In other cases, the data is
2843 * already in proper host byte order. */
2844 if (sizeof(target_su.val) != (sizeof(target_su.buf))) {
2845 target_su.buf = tswapal(target_su.buf);
2846 arg.val = tswap32(target_su.val);
2847 } else {
2848 arg.val = target_su.val;
2849 }
e5289087 2850 ret = get_errno(semctl(semid, semnum, cmd, arg));
3eb6b044
TS
2851 break;
2852 case GETALL:
3eb6b044 2853 case SETALL:
e5289087
AJ
2854 err = target_to_host_semarray(semid, &array, target_su.array);
2855 if (err)
2856 return err;
2857 arg.array = array;
2858 ret = get_errno(semctl(semid, semnum, cmd, arg));
2859 err = host_to_target_semarray(semid, target_su.array, &array);
2860 if (err)
2861 return err;
3eb6b044
TS
2862 break;
2863 case IPC_STAT:
3eb6b044 2864 case IPC_SET:
e5289087
AJ
2865 case SEM_STAT:
2866 err = target_to_host_semid_ds(&dsarg, target_su.buf);
2867 if (err)
2868 return err;
2869 arg.buf = &dsarg;
2870 ret = get_errno(semctl(semid, semnum, cmd, arg));
2871 err = host_to_target_semid_ds(target_su.buf, &dsarg);
2872 if (err)
2873 return err;
2874 break;
2875 case IPC_INFO:
2876 case SEM_INFO:
2877 arg.__buf = &seminfo;
2878 ret = get_errno(semctl(semid, semnum, cmd, arg));
2879 err = host_to_target_seminfo(target_su.__buf, &seminfo);
2880 if (err)
2881 return err;
2882 break;
2883 case IPC_RMID:
2884 case GETPID:
2885 case GETNCNT:
2886 case GETZCNT:
2887 ret = get_errno(semctl(semid, semnum, cmd, NULL));
3eb6b044 2888 break;
3eb6b044
TS
2889 }
2890
2891 return ret;
2892}
2893
e5289087
AJ
2894struct target_sembuf {
2895 unsigned short sem_num;
2896 short sem_op;
2897 short sem_flg;
2898};
2899
2900static inline abi_long target_to_host_sembuf(struct sembuf *host_sembuf,
2901 abi_ulong target_addr,
2902 unsigned nsops)
2903{
2904 struct target_sembuf *target_sembuf;
2905 int i;
2906
2907 target_sembuf = lock_user(VERIFY_READ, target_addr,
2908 nsops*sizeof(struct target_sembuf), 1);
2909 if (!target_sembuf)
2910 return -TARGET_EFAULT;
2911
2912 for(i=0; i<nsops; i++) {
2913 __get_user(host_sembuf[i].sem_num, &target_sembuf[i].sem_num);
2914 __get_user(host_sembuf[i].sem_op, &target_sembuf[i].sem_op);
2915 __get_user(host_sembuf[i].sem_flg, &target_sembuf[i].sem_flg);
2916 }
2917
2918 unlock_user(target_sembuf, target_addr, 0);
2919
2920 return 0;
2921}
2922
2923static inline abi_long do_semop(int semid, abi_long ptr, unsigned nsops)
2924{
2925 struct sembuf sops[nsops];
2926
2927 if (target_to_host_sembuf(sops, ptr, nsops))
2928 return -TARGET_EFAULT;
2929
c7128c9f 2930 return get_errno(semop(semid, sops, nsops));
e5289087
AJ
2931}
2932
1bc012f6
TS
2933struct target_msqid_ds
2934{
1c54ff97
AJ
2935 struct target_ipc_perm msg_perm;
2936 abi_ulong msg_stime;
2937#if TARGET_ABI_BITS == 32
2938 abi_ulong __unused1;
2939#endif
2940 abi_ulong msg_rtime;
2941#if TARGET_ABI_BITS == 32
2942 abi_ulong __unused2;
2943#endif
2944 abi_ulong msg_ctime;
2945#if TARGET_ABI_BITS == 32
2946 abi_ulong __unused3;
2947#endif
2948 abi_ulong __msg_cbytes;
2949 abi_ulong msg_qnum;
2950 abi_ulong msg_qbytes;
2951 abi_ulong msg_lspid;
2952 abi_ulong msg_lrpid;
2953 abi_ulong __unused4;
2954 abi_ulong __unused5;
1bc012f6
TS
2955};
2956
579a97f7
FB
2957static inline abi_long target_to_host_msqid_ds(struct msqid_ds *host_md,
2958 abi_ulong target_addr)
1bc012f6
TS
2959{
2960 struct target_msqid_ds *target_md;
2961
579a97f7
FB
2962 if (!lock_user_struct(VERIFY_READ, target_md, target_addr, 1))
2963 return -TARGET_EFAULT;
1c54ff97
AJ
2964 if (target_to_host_ipc_perm(&(host_md->msg_perm),target_addr))
2965 return -TARGET_EFAULT;
cbb21eed
MB
2966 host_md->msg_stime = tswapal(target_md->msg_stime);
2967 host_md->msg_rtime = tswapal(target_md->msg_rtime);
2968 host_md->msg_ctime = tswapal(target_md->msg_ctime);
2969 host_md->__msg_cbytes = tswapal(target_md->__msg_cbytes);
2970 host_md->msg_qnum = tswapal(target_md->msg_qnum);
2971 host_md->msg_qbytes = tswapal(target_md->msg_qbytes);
2972 host_md->msg_lspid = tswapal(target_md->msg_lspid);
2973 host_md->msg_lrpid = tswapal(target_md->msg_lrpid);
1bc012f6 2974 unlock_user_struct(target_md, target_addr, 0);
579a97f7 2975 return 0;
1bc012f6
TS
2976}
2977
579a97f7
FB
2978static inline abi_long host_to_target_msqid_ds(abi_ulong target_addr,
2979 struct msqid_ds *host_md)
1bc012f6
TS
2980{
2981 struct target_msqid_ds *target_md;
2982
579a97f7
FB
2983 if (!lock_user_struct(VERIFY_WRITE, target_md, target_addr, 0))
2984 return -TARGET_EFAULT;
1c54ff97
AJ
2985 if (host_to_target_ipc_perm(target_addr,&(host_md->msg_perm)))
2986 return -TARGET_EFAULT;
cbb21eed
MB
2987 target_md->msg_stime = tswapal(host_md->msg_stime);
2988 target_md->msg_rtime = tswapal(host_md->msg_rtime);
2989 target_md->msg_ctime = tswapal(host_md->msg_ctime);
2990 target_md->__msg_cbytes = tswapal(host_md->__msg_cbytes);
2991 target_md->msg_qnum = tswapal(host_md->msg_qnum);
2992 target_md->msg_qbytes = tswapal(host_md->msg_qbytes);
2993 target_md->msg_lspid = tswapal(host_md->msg_lspid);
2994 target_md->msg_lrpid = tswapal(host_md->msg_lrpid);
1bc012f6 2995 unlock_user_struct(target_md, target_addr, 1);
579a97f7 2996 return 0;
1bc012f6
TS
2997}
2998
1c54ff97
AJ
2999struct target_msginfo {
3000 int msgpool;
3001 int msgmap;
3002 int msgmax;
3003 int msgmnb;
3004 int msgmni;
3005 int msgssz;
3006 int msgtql;
3007 unsigned short int msgseg;
3008};
3009
3010static inline abi_long host_to_target_msginfo(abi_ulong target_addr,
3011 struct msginfo *host_msginfo)
3012{
3013 struct target_msginfo *target_msginfo;
3014 if (!lock_user_struct(VERIFY_WRITE, target_msginfo, target_addr, 0))
3015 return -TARGET_EFAULT;
3016 __put_user(host_msginfo->msgpool, &target_msginfo->msgpool);
3017 __put_user(host_msginfo->msgmap, &target_msginfo->msgmap);
3018 __put_user(host_msginfo->msgmax, &target_msginfo->msgmax);
3019 __put_user(host_msginfo->msgmnb, &target_msginfo->msgmnb);
3020 __put_user(host_msginfo->msgmni, &target_msginfo->msgmni);
3021 __put_user(host_msginfo->msgssz, &target_msginfo->msgssz);
3022 __put_user(host_msginfo->msgtql, &target_msginfo->msgtql);
3023 __put_user(host_msginfo->msgseg, &target_msginfo->msgseg);
3024 unlock_user_struct(target_msginfo, target_addr, 1);
00b229ac 3025 return 0;
1c54ff97
AJ
3026}
3027
3028static inline abi_long do_msgctl(int msgid, int cmd, abi_long ptr)
1bc012f6
TS
3029{
3030 struct msqid_ds dsarg;
1c54ff97
AJ
3031 struct msginfo msginfo;
3032 abi_long ret = -TARGET_EINVAL;
3033
3034 cmd &= 0xff;
3035
3036 switch (cmd) {
1bc012f6
TS
3037 case IPC_STAT:
3038 case IPC_SET:
1c54ff97
AJ
3039 case MSG_STAT:
3040 if (target_to_host_msqid_ds(&dsarg,ptr))
3041 return -TARGET_EFAULT;
3042 ret = get_errno(msgctl(msgid, cmd, &dsarg));
3043 if (host_to_target_msqid_ds(ptr,&dsarg))
3044 return -TARGET_EFAULT;
3045 break;
3046 case IPC_RMID:
3047 ret = get_errno(msgctl(msgid, cmd, NULL));
3048 break;
3049 case IPC_INFO:
3050 case MSG_INFO:
3051 ret = get_errno(msgctl(msgid, cmd, (struct msqid_ds *)&msginfo));
3052 if (host_to_target_msginfo(ptr, &msginfo))
3053 return -TARGET_EFAULT;
3054 break;
1bc012f6 3055 }
1c54ff97 3056
1bc012f6
TS
3057 return ret;
3058}
3059
3060struct target_msgbuf {
1c54ff97
AJ
3061 abi_long mtype;
3062 char mtext[1];
1bc012f6
TS
3063};
3064
992f48a0 3065static inline abi_long do_msgsnd(int msqid, abi_long msgp,
edcc5f9d 3066 ssize_t msgsz, int msgflg)
1bc012f6
TS
3067{
3068 struct target_msgbuf *target_mb;
3069 struct msgbuf *host_mb;
992f48a0 3070 abi_long ret = 0;
1bc012f6 3071
edcc5f9d
TM
3072 if (msgsz < 0) {
3073 return -TARGET_EINVAL;
3074 }
3075
579a97f7
FB
3076 if (!lock_user_struct(VERIFY_READ, target_mb, msgp, 0))
3077 return -TARGET_EFAULT;
0e173b24 3078 host_mb = g_try_malloc(msgsz + sizeof(long));
29e03fcb
HZ
3079 if (!host_mb) {
3080 unlock_user_struct(target_mb, msgp, 0);
3081 return -TARGET_ENOMEM;
3082 }
cbb21eed 3083 host_mb->mtype = (abi_long) tswapal(target_mb->mtype);
1c54ff97 3084 memcpy(host_mb->mtext, target_mb->mtext, msgsz);
1bc012f6 3085 ret = get_errno(msgsnd(msqid, host_mb, msgsz, msgflg));
0e173b24 3086 g_free(host_mb);
1bc012f6
TS
3087 unlock_user_struct(target_mb, msgp, 0);
3088
3089 return ret;
3090}
3091
992f48a0 3092static inline abi_long do_msgrcv(int msqid, abi_long msgp,
1c54ff97 3093 unsigned int msgsz, abi_long msgtyp,
992f48a0 3094 int msgflg)
1bc012f6
TS
3095{
3096 struct target_msgbuf *target_mb;
579a97f7 3097 char *target_mtext;
1bc012f6 3098 struct msgbuf *host_mb;
992f48a0 3099 abi_long ret = 0;
1bc012f6 3100
579a97f7
FB
3101 if (!lock_user_struct(VERIFY_WRITE, target_mb, msgp, 0))
3102 return -TARGET_EFAULT;
1c54ff97 3103
0d07fe47 3104 host_mb = g_malloc(msgsz+sizeof(long));
79dd77de 3105 ret = get_errno(msgrcv(msqid, host_mb, msgsz, msgtyp, msgflg));
1c54ff97 3106
579a97f7
FB
3107 if (ret > 0) {
3108 abi_ulong target_mtext_addr = msgp + sizeof(abi_ulong);
3109 target_mtext = lock_user(VERIFY_WRITE, target_mtext_addr, ret, 0);
3110 if (!target_mtext) {
3111 ret = -TARGET_EFAULT;
3112 goto end;
3113 }
1c54ff97 3114 memcpy(target_mb->mtext, host_mb->mtext, ret);
579a97f7
FB
3115 unlock_user(target_mtext, target_mtext_addr, ret);
3116 }
1c54ff97 3117
cbb21eed 3118 target_mb->mtype = tswapal(host_mb->mtype);
1bc012f6 3119
579a97f7
FB
3120end:
3121 if (target_mb)
3122 unlock_user_struct(target_mb, msgp, 1);
0d07fe47 3123 g_free(host_mb);
1bc012f6
TS
3124 return ret;
3125}
3126
88a8c984
RV
3127static inline abi_long target_to_host_shmid_ds(struct shmid_ds *host_sd,
3128 abi_ulong target_addr)
3129{
3130 struct target_shmid_ds *target_sd;
3131
3132 if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
3133 return -TARGET_EFAULT;
3134 if (target_to_host_ipc_perm(&(host_sd->shm_perm), target_addr))
3135 return -TARGET_EFAULT;
3136 __get_user(host_sd->shm_segsz, &target_sd->shm_segsz);
3137 __get_user(host_sd->shm_atime, &target_sd->shm_atime);
3138 __get_user(host_sd->shm_dtime, &target_sd->shm_dtime);
3139 __get_user(host_sd->shm_ctime, &target_sd->shm_ctime);
3140 __get_user(host_sd->shm_cpid, &target_sd->shm_cpid);
3141 __get_user(host_sd->shm_lpid, &target_sd->shm_lpid);
3142 __get_user(host_sd->shm_nattch, &target_sd->shm_nattch);
3143 unlock_user_struct(target_sd, target_addr, 0);
3144 return 0;
3145}
3146
3147static inline abi_long host_to_target_shmid_ds(abi_ulong target_addr,
3148 struct shmid_ds *host_sd)
3149{
3150 struct target_shmid_ds *target_sd;
3151
3152 if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
3153 return -TARGET_EFAULT;
3154 if (host_to_target_ipc_perm(target_addr, &(host_sd->shm_perm)))
3155 return -TARGET_EFAULT;
3156 __put_user(host_sd->shm_segsz, &target_sd->shm_segsz);
3157 __put_user(host_sd->shm_atime, &target_sd->shm_atime);
3158 __put_user(host_sd->shm_dtime, &target_sd->shm_dtime);
3159 __put_user(host_sd->shm_ctime, &target_sd->shm_ctime);
3160 __put_user(host_sd->shm_cpid, &target_sd->shm_cpid);
3161 __put_user(host_sd->shm_lpid, &target_sd->shm_lpid);
3162 __put_user(host_sd->shm_nattch, &target_sd->shm_nattch);
3163 unlock_user_struct(target_sd, target_addr, 1);
3164 return 0;
3165}
3166
3167struct target_shminfo {
3168 abi_ulong shmmax;
3169 abi_ulong shmmin;
3170 abi_ulong shmmni;
3171 abi_ulong shmseg;
3172 abi_ulong shmall;
3173};
3174
3175static inline abi_long host_to_target_shminfo(abi_ulong target_addr,
3176 struct shminfo *host_shminfo)
3177{
3178 struct target_shminfo *target_shminfo;
3179 if (!lock_user_struct(VERIFY_WRITE, target_shminfo, target_addr, 0))
3180 return -TARGET_EFAULT;
3181 __put_user(host_shminfo->shmmax, &target_shminfo->shmmax);
3182 __put_user(host_shminfo->shmmin, &target_shminfo->shmmin);
3183 __put_user(host_shminfo->shmmni, &target_shminfo->shmmni);
3184 __put_user(host_shminfo->shmseg, &target_shminfo->shmseg);
3185 __put_user(host_shminfo->shmall, &target_shminfo->shmall);
3186 unlock_user_struct(target_shminfo, target_addr, 1);
3187 return 0;
3188}
3189
3190struct target_shm_info {
3191 int used_ids;
3192 abi_ulong shm_tot;
3193 abi_ulong shm_rss;
3194 abi_ulong shm_swp;
3195 abi_ulong swap_attempts;
3196 abi_ulong swap_successes;
3197};
3198
3199static inline abi_long host_to_target_shm_info(abi_ulong target_addr,
3200 struct shm_info *host_shm_info)
3201{
3202 struct target_shm_info *target_shm_info;
3203 if (!lock_user_struct(VERIFY_WRITE, target_shm_info, target_addr, 0))
3204 return -TARGET_EFAULT;
3205 __put_user(host_shm_info->used_ids, &target_shm_info->used_ids);
3206 __put_user(host_shm_info->shm_tot, &target_shm_info->shm_tot);
3207 __put_user(host_shm_info->shm_rss, &target_shm_info->shm_rss);
3208 __put_user(host_shm_info->shm_swp, &target_shm_info->shm_swp);
3209 __put_user(host_shm_info->swap_attempts, &target_shm_info->swap_attempts);
3210 __put_user(host_shm_info->swap_successes, &target_shm_info->swap_successes);
3211 unlock_user_struct(target_shm_info, target_addr, 1);
3212 return 0;
3213}
3214
3215static inline abi_long do_shmctl(int shmid, int cmd, abi_long buf)
3216{
3217 struct shmid_ds dsarg;
3218 struct shminfo shminfo;
3219 struct shm_info shm_info;
3220 abi_long ret = -TARGET_EINVAL;
3221
3222 cmd &= 0xff;
3223
3224 switch(cmd) {
3225 case IPC_STAT:
3226 case IPC_SET:
3227 case SHM_STAT:
3228 if (target_to_host_shmid_ds(&dsarg, buf))
3229 return -TARGET_EFAULT;
3230 ret = get_errno(shmctl(shmid, cmd, &dsarg));
3231 if (host_to_target_shmid_ds(buf, &dsarg))
3232 return -TARGET_EFAULT;
3233 break;
3234 case IPC_INFO:
3235 ret = get_errno(shmctl(shmid, cmd, (struct shmid_ds *)&shminfo));
3236 if (host_to_target_shminfo(buf, &shminfo))
3237 return -TARGET_EFAULT;
3238 break;
3239 case SHM_INFO:
3240 ret = get_errno(shmctl(shmid, cmd, (struct shmid_ds *)&shm_info));
3241 if (host_to_target_shm_info(buf, &shm_info))
3242 return -TARGET_EFAULT;
3243 break;
3244 case IPC_RMID:
3245 case SHM_LOCK:
3246 case SHM_UNLOCK:
3247 ret = get_errno(shmctl(shmid, cmd, NULL));
3248 break;
3249 }
3250
3251 return ret;
3252}
3253
3254static inline abi_ulong do_shmat(int shmid, abi_ulong shmaddr, int shmflg)
3255{
3256 abi_long raddr;
3257 void *host_raddr;
3258 struct shmid_ds shm_info;
3259 int i,ret;
3260
3261 /* find out the length of the shared memory segment */
3262 ret = get_errno(shmctl(shmid, IPC_STAT, &shm_info));
3263 if (is_error(ret)) {
3264 /* can't get length, bail out */
3265 return ret;
3266 }
3267
3268 mmap_lock();
3269
3270 if (shmaddr)
3271 host_raddr = shmat(shmid, (void *)g2h(shmaddr), shmflg);
3272 else {
3273 abi_ulong mmap_start;
3274
3275 mmap_start = mmap_find_vma(0, shm_info.shm_segsz);
3276
3277 if (mmap_start == -1) {
3278 errno = ENOMEM;
3279 host_raddr = (void *)-1;
3280 } else
3281 host_raddr = shmat(shmid, g2h(mmap_start), shmflg | SHM_REMAP);
3282 }
3283
3284 if (host_raddr == (void *)-1) {
3285 mmap_unlock();
3286 return get_errno((long)host_raddr);
3287 }
3288 raddr=h2g((unsigned long)host_raddr);
3289
3290 page_set_flags(raddr, raddr + shm_info.shm_segsz,
3291 PAGE_VALID | PAGE_READ |
3292 ((shmflg & SHM_RDONLY)? 0 : PAGE_WRITE));
3293
3294 for (i = 0; i < N_SHM_REGIONS; i++) {
b6e17875
PM
3295 if (!shm_regions[i].in_use) {
3296 shm_regions[i].in_use = true;
88a8c984
RV
3297 shm_regions[i].start = raddr;
3298 shm_regions[i].size = shm_info.shm_segsz;
3299 break;
3300 }
3301 }
3302
3303 mmap_unlock();
3304 return raddr;
3305
3306}
3307
3308static inline abi_long do_shmdt(abi_ulong shmaddr)
3309{
3310 int i;
3311
3312 for (i = 0; i < N_SHM_REGIONS; ++i) {
b6e17875
PM
3313 if (shm_regions[i].in_use && shm_regions[i].start == shmaddr) {
3314 shm_regions[i].in_use = false;
e00ac249 3315 page_set_flags(shmaddr, shmaddr + shm_regions[i].size, 0);
88a8c984
RV
3316 break;
3317 }
3318 }
3319
3320 return get_errno(shmdt(g2h(shmaddr)));
3321}
3322
1c54ff97 3323#ifdef TARGET_NR_ipc
53a5960a 3324/* ??? This only works with linear mappings. */
0da46a6e 3325/* do_ipc() must return target values and target errnos. */
37ed0956
TM
3326static abi_long do_ipc(unsigned int call, abi_long first,
3327 abi_long second, abi_long third,
992f48a0 3328 abi_long ptr, abi_long fifth)
8853f86e
FB
3329{
3330 int version;
992f48a0 3331 abi_long ret = 0;
8853f86e
FB
3332
3333 version = call >> 16;
3334 call &= 0xffff;
3335
3336 switch (call) {
fa294816 3337 case IPCOP_semop:
e5289087 3338 ret = do_semop(first, ptr, second);
fa294816
TS
3339 break;
3340
3341 case IPCOP_semget:
3342 ret = get_errno(semget(first, second, third));
3343 break;
3344
5d2fa8eb
TM
3345 case IPCOP_semctl: {
3346 /* The semun argument to semctl is passed by value, so dereference the
3347 * ptr argument. */
3348 abi_ulong atptr;
37ed0956 3349 get_user_ual(atptr, ptr);
d1c002b6 3350 ret = do_semctl(first, second, third, atptr);
fa294816 3351 break;
5d2fa8eb 3352 }
d96372ef 3353
1c54ff97
AJ
3354 case IPCOP_msgget:
3355 ret = get_errno(msgget(first, second));
3356 break;
d96372ef 3357
1c54ff97
AJ
3358 case IPCOP_msgsnd:
3359 ret = do_msgsnd(first, ptr, second, third);
3360 break;
d96372ef 3361
1c54ff97
AJ
3362 case IPCOP_msgctl:
3363 ret = do_msgctl(first, second, ptr);
3364 break;
d96372ef 3365
1c54ff97
AJ
3366 case IPCOP_msgrcv:
3367 switch (version) {
3368 case 0:
3369 {
3370 struct target_ipc_kludge {
3371 abi_long msgp;
3372 abi_long msgtyp;
3373 } *tmp;
3374
3375 if (!lock_user_struct(VERIFY_READ, tmp, ptr, 1)) {
3376 ret = -TARGET_EFAULT;
3377 break;
3378 }
d96372ef 3379
79dd77de 3380 ret = do_msgrcv(first, tswapal(tmp->msgp), second, tswapal(tmp->msgtyp), third);
d96372ef 3381
1c54ff97
AJ
3382 unlock_user_struct(tmp, ptr, 0);
3383 break;
3384 }
3385 default:
3386 ret = do_msgrcv(first, ptr, second, fifth, third);
3387 }
3388 break;
d96372ef 3389
8853f86e 3390 case IPCOP_shmat:
88a8c984
RV
3391 switch (version) {
3392 default:
5a4a898d
FB
3393 {
3394 abi_ulong raddr;
88a8c984
RV
3395 raddr = do_shmat(first, ptr, second);
3396 if (is_error(raddr))
3397 return get_errno(raddr);
2f619698 3398 if (put_user_ual(raddr, third))
5a4a898d 3399 return -TARGET_EFAULT;
88a8c984
RV
3400 break;
3401 }
3402 case 1:
3403 ret = -TARGET_EINVAL;
3404 break;
5a4a898d 3405 }
8853f86e
FB
3406 break;
3407 case IPCOP_shmdt:
88a8c984 3408 ret = do_shmdt(ptr);
8853f86e
FB
3409 break;
3410
3411 case IPCOP_shmget:
3412 /* IPC_* flag values are the same on all linux platforms */
3413 ret = get_errno(shmget(first, second, third));
3414 break;
3415
3416 /* IPC_* and SHM_* command values are the same on all linux platforms */
3417 case IPCOP_shmctl:
a2926784 3418 ret = do_shmctl(first, second, ptr);
8853f86e
FB
3419 break;
3420 default:
32407103 3421 gemu_log("Unsupported ipc call: %d (version %d)\n", call, version);
0da46a6e 3422 ret = -TARGET_ENOSYS;
8853f86e
FB
3423 break;
3424 }
3425 return ret;
3426}
32407103 3427#endif
8853f86e 3428
31e31b8a 3429/* kernel structure types definitions */
31e31b8a 3430
001faf32 3431#define STRUCT(name, ...) STRUCT_ ## name,
31e31b8a
FB
3432#define STRUCT_SPECIAL(name) STRUCT_ ## name,
3433enum {
3434#include "syscall_types.h"
8be656b8 3435STRUCT_MAX
31e31b8a
FB
3436};
3437#undef STRUCT
3438#undef STRUCT_SPECIAL
3439
001faf32 3440#define STRUCT(name, ...) static const argtype struct_ ## name ## _def[] = { __VA_ARGS__, TYPE_NULL };
31e31b8a
FB
3441#define STRUCT_SPECIAL(name)
3442#include "syscall_types.h"
3443#undef STRUCT
3444#undef STRUCT_SPECIAL
3445
d2ef05bb
PM
3446typedef struct IOCTLEntry IOCTLEntry;
3447
3448typedef abi_long do_ioctl_fn(const IOCTLEntry *ie, uint8_t *buf_temp,
45c874eb 3449 int fd, int cmd, abi_long arg);
d2ef05bb
PM
3450
3451struct IOCTLEntry {
9c6bf9c7 3452 int target_cmd;
2ab83ea7 3453 unsigned int host_cmd;
31e31b8a
FB
3454 const char *name;
3455 int access;
d2ef05bb 3456 do_ioctl_fn *do_ioctl;
1a9353d2 3457 const argtype arg_type[5];
d2ef05bb 3458};
31e31b8a
FB
3459
3460#define IOC_R 0x0001
3461#define IOC_W 0x0002
3462#define IOC_RW (IOC_R | IOC_W)
3463
3464#define MAX_STRUCT_SIZE 4096
3465
dace20dc 3466#ifdef CONFIG_FIEMAP
285da2b9
PM
3467/* So fiemap access checks don't overflow on 32 bit systems.
3468 * This is very slightly smaller than the limit imposed by
3469 * the underlying kernel.
3470 */
3471#define FIEMAP_MAX_EXTENTS ((UINT_MAX - sizeof(struct fiemap)) \
3472 / sizeof(struct fiemap_extent))
3473
3474static abi_long do_ioctl_fs_ioc_fiemap(const IOCTLEntry *ie, uint8_t *buf_temp,
45c874eb 3475 int fd, int cmd, abi_long arg)
285da2b9
PM
3476{
3477 /* The parameter for this ioctl is a struct fiemap followed
3478 * by an array of struct fiemap_extent whose size is set
3479 * in fiemap->fm_extent_count. The array is filled in by the
3480 * ioctl.
3481 */
3482 int target_size_in, target_size_out;
3483 struct fiemap *fm;
3484 const argtype *arg_type = ie->arg_type;
3485 const argtype extent_arg_type[] = { MK_STRUCT(STRUCT_fiemap_extent) };
3486 void *argptr, *p;
3487 abi_long ret;
3488 int i, extent_size = thunk_type_size(extent_arg_type, 0);
3489 uint32_t outbufsz;
3490 int free_fm = 0;
3491
3492 assert(arg_type[0] == TYPE_PTR);
3493 assert(ie->access == IOC_RW);
3494 arg_type++;
3495 target_size_in = thunk_type_size(arg_type, 0);
3496 argptr = lock_user(VERIFY_READ, arg, target_size_in, 1);
3497 if (!argptr) {
3498 return -TARGET_EFAULT;
3499 }
3500 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
3501 unlock_user(argptr, arg, 0);
3502 fm = (struct fiemap *)buf_temp;
3503 if (fm->fm_extent_count > FIEMAP_MAX_EXTENTS) {
3504 return -TARGET_EINVAL;
3505 }
3506
3507 outbufsz = sizeof (*fm) +
3508 (sizeof(struct fiemap_extent) * fm->fm_extent_count);
3509
3510 if (outbufsz > MAX_STRUCT_SIZE) {
3511 /* We can't fit all the extents into the fixed size buffer.
3512 * Allocate one that is large enough and use it instead.
3513 */
0e173b24 3514 fm = g_try_malloc(outbufsz);
285da2b9
PM
3515 if (!fm) {
3516 return -TARGET_ENOMEM;
3517 }
3518 memcpy(fm, buf_temp, sizeof(struct fiemap));
3519 free_fm = 1;
3520 }
3521 ret = get_errno(ioctl(fd, ie->host_cmd, fm));
3522 if (!is_error(ret)) {
3523 target_size_out = target_size_in;
3524 /* An extent_count of 0 means we were only counting the extents
3525 * so there are no structs to copy
3526 */
3527 if (fm->fm_extent_count != 0) {
3528 target_size_out += fm->fm_mapped_extents * extent_size;
3529 }
3530 argptr = lock_user(VERIFY_WRITE, arg, target_size_out, 0);
3531 if (!argptr) {
3532 ret = -TARGET_EFAULT;
3533 } else {
3534 /* Convert the struct fiemap */
3535 thunk_convert(argptr, fm, arg_type, THUNK_TARGET);
3536 if (fm->fm_extent_count != 0) {
3537 p = argptr + target_size_in;
3538 /* ...and then all the struct fiemap_extents */
3539 for (i = 0; i < fm->fm_mapped_extents; i++) {
3540 thunk_convert(p, &fm->fm_extents[i], extent_arg_type,
3541 THUNK_TARGET);
3542 p += extent_size;
3543 }
3544 }
3545 unlock_user(argptr, arg, target_size_out);
3546 }
3547 }
3548 if (free_fm) {
0e173b24 3549 g_free(fm);
285da2b9
PM
3550 }
3551 return ret;
3552}
dace20dc 3553#endif
285da2b9 3554
059c2f2c 3555static abi_long do_ioctl_ifconf(const IOCTLEntry *ie, uint8_t *buf_temp,
45c874eb 3556 int fd, int cmd, abi_long arg)
059c2f2c
LV
3557{
3558 const argtype *arg_type = ie->arg_type;
3559 int target_size;
3560 void *argptr;
3561 int ret;
3562 struct ifconf *host_ifconf;
3563 uint32_t outbufsz;
3564 const argtype ifreq_arg_type[] = { MK_STRUCT(STRUCT_sockaddr_ifreq) };
3565 int target_ifreq_size;
3566 int nb_ifreq;
3567 int free_buf = 0;
3568 int i;
3569 int target_ifc_len;
3570 abi_long target_ifc_buf;
3571 int host_ifc_len;
3572 char *host_ifc_buf;
3573
3574 assert(arg_type[0] == TYPE_PTR);
3575 assert(ie->access == IOC_RW);
3576
3577 arg_type++;
3578 target_size = thunk_type_size(arg_type, 0);
3579
3580 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
3581 if (!argptr)
3582 return -TARGET_EFAULT;
3583 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
3584 unlock_user(argptr, arg, 0);
3585
3586 host_ifconf = (struct ifconf *)(unsigned long)buf_temp;
3587 target_ifc_len = host_ifconf->ifc_len;
3588 target_ifc_buf = (abi_long)(unsigned long)host_ifconf->ifc_buf;
3589
3590 target_ifreq_size = thunk_type_size(ifreq_arg_type, 0);
3591 nb_ifreq = target_ifc_len / target_ifreq_size;
3592 host_ifc_len = nb_ifreq * sizeof(struct ifreq);
3593
3594 outbufsz = sizeof(*host_ifconf) + host_ifc_len;
3595 if (outbufsz > MAX_STRUCT_SIZE) {
3596 /* We can't fit all the extents into the fixed size buffer.
3597 * Allocate one that is large enough and use it instead.
3598 */
3599 host_ifconf = malloc(outbufsz);
3600 if (!host_ifconf) {
3601 return -TARGET_ENOMEM;
3602 }
3603 memcpy(host_ifconf, buf_temp, sizeof(*host_ifconf));
3604 free_buf = 1;
3605 }
3606 host_ifc_buf = (char*)host_ifconf + sizeof(*host_ifconf);
3607
3608 host_ifconf->ifc_len = host_ifc_len;
3609 host_ifconf->ifc_buf = host_ifc_buf;
3610
3611 ret = get_errno(ioctl(fd, ie->host_cmd, host_ifconf));
3612 if (!is_error(ret)) {
3613 /* convert host ifc_len to target ifc_len */
3614
3615 nb_ifreq = host_ifconf->ifc_len / sizeof(struct ifreq);
3616 target_ifc_len = nb_ifreq * target_ifreq_size;
3617 host_ifconf->ifc_len = target_ifc_len;
3618
3619 /* restore target ifc_buf */
3620
3621 host_ifconf->ifc_buf = (char *)(unsigned long)target_ifc_buf;
3622
3623 /* copy struct ifconf to target user */
3624
3625 argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
3626 if (!argptr)
3627 return -TARGET_EFAULT;
3628 thunk_convert(argptr, host_ifconf, arg_type, THUNK_TARGET);
3629 unlock_user(argptr, arg, target_size);
3630
3631 /* copy ifreq[] to target user */
3632
3633 argptr = lock_user(VERIFY_WRITE, target_ifc_buf, target_ifc_len, 0);
3634 for (i = 0; i < nb_ifreq ; i++) {
3635 thunk_convert(argptr + i * target_ifreq_size,
3636 host_ifc_buf + i * sizeof(struct ifreq),
3637 ifreq_arg_type, THUNK_TARGET);
3638 }
3639 unlock_user(argptr, target_ifc_buf, target_ifc_len);
3640 }
3641
3642 if (free_buf) {
3643 free(host_ifconf);
3644 }
3645
3646 return ret;
3647}
3648
56e904ec 3649static abi_long do_ioctl_dm(const IOCTLEntry *ie, uint8_t *buf_temp, int fd,
45c874eb 3650 int cmd, abi_long arg)
56e904ec
AG
3651{
3652 void *argptr;
3653 struct dm_ioctl *host_dm;
3654 abi_long guest_data;
3655 uint32_t guest_data_size;
3656 int target_size;
3657 const argtype *arg_type = ie->arg_type;
3658 abi_long ret;
3659 void *big_buf = NULL;
3660 char *host_data;
3661
3662 arg_type++;
3663 target_size = thunk_type_size(arg_type, 0);
3664 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
3665 if (!argptr) {
3666 ret = -TARGET_EFAULT;
3667 goto out;
3668 }
3669 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
3670 unlock_user(argptr, arg, 0);
3671
3672 /* buf_temp is too small, so fetch things into a bigger buffer */
3673 big_buf = g_malloc0(((struct dm_ioctl*)buf_temp)->data_size * 2);
3674 memcpy(big_buf, buf_temp, target_size);
3675 buf_temp = big_buf;
3676 host_dm = big_buf;
3677
3678 guest_data = arg + host_dm->data_start;
3679 if ((guest_data - arg) < 0) {
3680 ret = -EINVAL;
3681 goto out;
3682 }
3683 guest_data_size = host_dm->data_size - host_dm->data_start;
3684 host_data = (char*)host_dm + host_dm->data_start;
3685
3686 argptr = lock_user(VERIFY_READ, guest_data, guest_data_size, 1);
3687 switch (ie->host_cmd) {
3688 case DM_REMOVE_ALL:
3689 case DM_LIST_DEVICES:
3690 case DM_DEV_CREATE:
3691 case DM_DEV_REMOVE:
3692 case DM_DEV_SUSPEND:
3693 case DM_DEV_STATUS:
3694 case DM_DEV_WAIT:
3695 case DM_TABLE_STATUS:
3696 case DM_TABLE_CLEAR:
3697 case DM_TABLE_DEPS:
3698 case DM_LIST_VERSIONS:
3699 /* no input data */
3700 break;
3701 case DM_DEV_RENAME:
3702 case DM_DEV_SET_GEOMETRY:
3703 /* data contains only strings */
3704 memcpy(host_data, argptr, guest_data_size);
3705 break;
3706 case DM_TARGET_MSG:
3707 memcpy(host_data, argptr, guest_data_size);
3708 *(uint64_t*)host_data = tswap64(*(uint64_t*)argptr);
3709 break;
3710 case DM_TABLE_LOAD:
3711 {
3712 void *gspec = argptr;
3713 void *cur_data = host_data;
3714 const argtype arg_type[] = { MK_STRUCT(STRUCT_dm_target_spec) };
3715 int spec_size = thunk_type_size(arg_type, 0);
3716 int i;
3717
3718 for (i = 0; i < host_dm->target_count; i++) {
3719 struct dm_target_spec *spec = cur_data;
3720 uint32_t next;
3721 int slen;
3722
3723 thunk_convert(spec, gspec, arg_type, THUNK_HOST);
3724 slen = strlen((char*)gspec + spec_size) + 1;
3725 next = spec->next;
3726 spec->next = sizeof(*spec) + slen;
3727 strcpy((char*)&spec[1], gspec + spec_size);
3728 gspec += next;
3729 cur_data += spec->next;
3730 }
3731 break;
3732 }
3733 default:
3734 ret = -TARGET_EINVAL;
dec0473d 3735 unlock_user(argptr, guest_data, 0);
56e904ec
AG
3736 goto out;
3737 }
3738 unlock_user(argptr, guest_data, 0);
3739
3740 ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
3741 if (!is_error(ret)) {
3742 guest_data = arg + host_dm->data_start;
3743 guest_data_size = host_dm->data_size - host_dm->data_start;
3744 argptr = lock_user(VERIFY_WRITE, guest_data, guest_data_size, 0);
3745 switch (ie->host_cmd) {
3746 case DM_REMOVE_ALL:
3747 case DM_DEV_CREATE:
3748 case DM_DEV_REMOVE:
3749 case DM_DEV_RENAME:
3750 case DM_DEV_SUSPEND:
3751 case DM_DEV_STATUS:
3752 case DM_TABLE_LOAD:
3753 case DM_TABLE_CLEAR:
3754 case DM_TARGET_MSG:
3755 case DM_DEV_SET_GEOMETRY:
3756 /* no return data */
3757 break;
3758 case DM_LIST_DEVICES:
3759 {
3760 struct dm_name_list *nl = (void*)host_dm + host_dm->data_start;
3761 uint32_t remaining_data = guest_data_size;
3762 void *cur_data = argptr;
3763 const argtype arg_type[] = { MK_STRUCT(STRUCT_dm_name_list) };
3764 int nl_size = 12; /* can't use thunk_size due to alignment */
3765
3766 while (1) {
3767 uint32_t next = nl->next;
3768 if (next) {
3769 nl->next = nl_size + (strlen(nl->name) + 1);
3770 }
3771 if (remaining_data < nl->next) {
3772 host_dm->flags |= DM_BUFFER_FULL_FLAG;
3773 break;
3774 }
3775 thunk_convert(cur_data, nl, arg_type, THUNK_TARGET);
3776 strcpy(cur_data + nl_size, nl->name);
3777 cur_data += nl->next;
3778 remaining_data -= nl->next;
3779 if (!next) {
3780 break;
3781 }
3782 nl = (void*)nl + next;
3783 }
3784 break;
3785 }
3786 case DM_DEV_WAIT:
3787 case DM_TABLE_STATUS:
3788 {
3789 struct dm_target_spec *spec = (void*)host_dm + host_dm->data_start;
3790 void *cur_data = argptr;
3791 const argtype arg_type[] = { MK_STRUCT(STRUCT_dm_target_spec) };
3792 int spec_size = thunk_type_size(arg_type, 0);
3793 int i;
3794
3795 for (i = 0; i < host_dm->target_count; i++) {
3796 uint32_t next = spec->next;
3797 int slen = strlen((char*)&spec[1]) + 1;
3798 spec->next = (cur_data - argptr) + spec_size + slen;
3799 if (guest_data_size < spec->next) {
3800 host_dm->flags |= DM_BUFFER_FULL_FLAG;
3801 break;
3802 }
3803 thunk_convert(cur_data, spec, arg_type, THUNK_TARGET);
3804 strcpy(cur_data + spec_size, (char*)&spec[1]);
3805 cur_data = argptr + spec->next;
3806 spec = (void*)host_dm + host_dm->data_start + next;
3807 }
3808 break;
3809 }
3810 case DM_TABLE_DEPS:
3811 {
3812 void *hdata = (void*)host_dm + host_dm->data_start;
3813 int count = *(uint32_t*)hdata;
3814 uint64_t *hdev = hdata + 8;
3815 uint64_t *gdev = argptr + 8;
3816 int i;
3817
3818 *(uint32_t*)argptr = tswap32(count);
3819 for (i = 0; i < count; i++) {
3820 *gdev = tswap64(*hdev);
3821 gdev++;
3822 hdev++;
3823 }
3824 break;
3825 }
3826 case DM_LIST_VERSIONS:
3827 {
3828 struct dm_target_versions *vers = (void*)host_dm + host_dm->data_start;
3829 uint32_t remaining_data = guest_data_size;
3830 void *cur_data = argptr;
3831 const argtype arg_type[] = { MK_STRUCT(STRUCT_dm_target_versions) };
3832 int vers_size = thunk_type_size(arg_type, 0);
3833
3834 while (1) {
3835 uint32_t next = vers->next;
3836 if (next) {
3837 vers->next = vers_size + (strlen(vers->name) + 1);
3838 }
3839 if (remaining_data < vers->next) {
3840 host_dm->flags |= DM_BUFFER_FULL_FLAG;
3841 break;
3842 }
3843 thunk_convert(cur_data, vers, arg_type, THUNK_TARGET);
3844 strcpy(cur_data + vers_size, vers->name);
3845 cur_data += vers->next;
3846 remaining_data -= vers->next;
3847 if (!next) {
3848 break;
3849 }
3850 vers = (void*)vers + next;
3851 }
3852 break;
3853 }
3854 default:
dec0473d 3855 unlock_user(argptr, guest_data, 0);
56e904ec
AG
3856 ret = -TARGET_EINVAL;
3857 goto out;
3858 }
3859 unlock_user(argptr, guest_data, guest_data_size);
3860
3861 argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
3862 if (!argptr) {
3863 ret = -TARGET_EFAULT;
3864 goto out;
3865 }
3866 thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
3867 unlock_user(argptr, arg, target_size);
3868 }
3869out:
ad11ad77 3870 g_free(big_buf);
56e904ec
AG
3871 return ret;
3872}
3873
a59b5e35 3874static abi_long do_ioctl_blkpg(const IOCTLEntry *ie, uint8_t *buf_temp, int fd,
45c874eb 3875 int cmd, abi_long arg)
a59b5e35
AG
3876{
3877 void *argptr;
3878 int target_size;
3879 const argtype *arg_type = ie->arg_type;
3880 const argtype part_arg_type[] = { MK_STRUCT(STRUCT_blkpg_partition) };
3881 abi_long ret;
3882
3883 struct blkpg_ioctl_arg *host_blkpg = (void*)buf_temp;
3884 struct blkpg_partition host_part;
3885
3886 /* Read and convert blkpg */
3887 arg_type++;
3888 target_size = thunk_type_size(arg_type, 0);
3889 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
3890 if (!argptr) {
3891 ret = -TARGET_EFAULT;
3892 goto out;
3893 }
3894 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
3895 unlock_user(argptr, arg, 0);
3896
3897 switch (host_blkpg->op) {
3898 case BLKPG_ADD_PARTITION:
3899 case BLKPG_DEL_PARTITION:
3900 /* payload is struct blkpg_partition */
3901 break;
3902 default:
3903 /* Unknown opcode */
3904 ret = -TARGET_EINVAL;
3905 goto out;
3906 }
3907
3908 /* Read and convert blkpg->data */
3909 arg = (abi_long)(uintptr_t)host_blkpg->data;
3910 target_size = thunk_type_size(part_arg_type, 0);
3911 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
3912 if (!argptr) {
3913 ret = -TARGET_EFAULT;
3914 goto out;
3915 }
3916 thunk_convert(&host_part, argptr, part_arg_type, THUNK_HOST);
3917 unlock_user(argptr, arg, 0);
3918
3919 /* Swizzle the data pointer to our local copy and call! */
3920 host_blkpg->data = &host_part;
3921 ret = get_errno(ioctl(fd, ie->host_cmd, host_blkpg));
3922
3923out:
3924 return ret;
3925}
3926
7ff7b666 3927static abi_long do_ioctl_rt(const IOCTLEntry *ie, uint8_t *buf_temp,
45c874eb 3928 int fd, int cmd, abi_long arg)
7ff7b666
LV
3929{
3930 const argtype *arg_type = ie->arg_type;
3931 const StructEntry *se;
3932 const argtype *field_types;
3933 const int *dst_offsets, *src_offsets;
3934 int target_size;
3935 void *argptr;
3936 abi_ulong *target_rt_dev_ptr;
3937 unsigned long *host_rt_dev_ptr;
3938 abi_long ret;
3939 int i;
3940
3941 assert(ie->access == IOC_W);
3942 assert(*arg_type == TYPE_PTR);
3943 arg_type++;
3944 assert(*arg_type == TYPE_STRUCT);
3945 target_size = thunk_type_size(arg_type, 0);
3946 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
3947 if (!argptr) {
3948 return -TARGET_EFAULT;
3949 }
3950 arg_type++;
3951 assert(*arg_type == (int)STRUCT_rtentry);
3952 se = struct_entries + *arg_type++;
3953 assert(se->convert[0] == NULL);
3954 /* convert struct here to be able to catch rt_dev string */
3955 field_types = se->field_types;
3956 dst_offsets = se->field_offsets[THUNK_HOST];
3957 src_offsets = se->field_offsets[THUNK_TARGET];
3958 for (i = 0; i < se->nb_fields; i++) {
3959 if (dst_offsets[i] == offsetof(struct rtentry, rt_dev)) {
3960 assert(*field_types == TYPE_PTRVOID);
3961 target_rt_dev_ptr = (abi_ulong *)(argptr + src_offsets[i]);
3962 host_rt_dev_ptr = (unsigned long *)(buf_temp + dst_offsets[i]);
3963 if (*target_rt_dev_ptr != 0) {
3964 *host_rt_dev_ptr = (unsigned long)lock_user_string(
3965 tswapal(*target_rt_dev_ptr));
3966 if (!*host_rt_dev_ptr) {
3967 unlock_user(argptr, arg, 0);
3968 return -TARGET_EFAULT;
3969 }
3970 } else {
3971 *host_rt_dev_ptr = 0;
3972 }
3973 field_types++;
3974 continue;
3975 }
3976 field_types = thunk_convert(buf_temp + dst_offsets[i],
3977 argptr + src_offsets[i],
3978 field_types, THUNK_HOST);
3979 }
3980 unlock_user(argptr, arg, 0);
3981
3982 ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
3983 if (*host_rt_dev_ptr != 0) {
3984 unlock_user((void *)*host_rt_dev_ptr,
3985 *target_rt_dev_ptr, 0);
3986 }
3987 return ret;
3988}
3989
ca56f5b5 3990static abi_long do_ioctl_kdsigaccept(const IOCTLEntry *ie, uint8_t *buf_temp,
45c874eb 3991 int fd, int cmd, abi_long arg)
ca56f5b5
PB
3992{
3993 int sig = target_to_host_signal(arg);
3994 return get_errno(ioctl(fd, ie->host_cmd, sig));
3995}
3996
9f106a75 3997static IOCTLEntry ioctl_entries[] = {
001faf32 3998#define IOCTL(cmd, access, ...) \
d2ef05bb
PM
3999 { TARGET_ ## cmd, cmd, #cmd, access, 0, { __VA_ARGS__ } },
4000#define IOCTL_SPECIAL(cmd, access, dofn, ...) \
4001 { TARGET_ ## cmd, cmd, #cmd, access, dofn, { __VA_ARGS__ } },
31e31b8a
FB
4002#include "ioctls.h"
4003 { 0, 0, },
4004};
4005
53a5960a 4006/* ??? Implement proper locking for ioctls. */
0da46a6e 4007/* do_ioctl() Must return target values and target errnos. */
45c874eb 4008static abi_long do_ioctl(int fd, int cmd, abi_long arg)
31e31b8a
FB
4009{
4010 const IOCTLEntry *ie;
4011 const argtype *arg_type;
992f48a0 4012 abi_long ret;
31e31b8a 4013 uint8_t buf_temp[MAX_STRUCT_SIZE];
53a5960a
PB
4014 int target_size;
4015 void *argptr;
31e31b8a
FB
4016
4017 ie = ioctl_entries;
4018 for(;;) {
4019 if (ie->target_cmd == 0) {
32407103 4020 gemu_log("Unsupported ioctl: cmd=0x%04lx\n", (long)cmd);
0da46a6e 4021 return -TARGET_ENOSYS;
31e31b8a
FB
4022 }
4023 if (ie->target_cmd == cmd)
4024 break;
4025 ie++;
4026 }
4027 arg_type = ie->arg_type;
9de5e440 4028#if defined(DEBUG)
32407103 4029 gemu_log("ioctl: cmd=0x%04lx (%s)\n", (long)cmd, ie->name);
72f03900 4030#endif
d2ef05bb
PM
4031 if (ie->do_ioctl) {
4032 return ie->do_ioctl(ie, buf_temp, fd, cmd, arg);
4033 }
4034
31e31b8a
FB
4035 switch(arg_type[0]) {
4036 case TYPE_NULL:
4037 /* no argument */
4038 ret = get_errno(ioctl(fd, ie->host_cmd));
4039 break;
4040 case TYPE_PTRVOID:
4041 case TYPE_INT:
31e31b8a
FB
4042 ret = get_errno(ioctl(fd, ie->host_cmd, arg));
4043 break;
4044 case TYPE_PTR:
4045 arg_type++;
53a5960a 4046 target_size = thunk_type_size(arg_type, 0);
31e31b8a
FB
4047 switch(ie->access) {
4048 case IOC_R:
4049 ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
4050 if (!is_error(ret)) {
579a97f7
FB
4051 argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
4052 if (!argptr)
4053 return -TARGET_EFAULT;
53a5960a
PB
4054 thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
4055 unlock_user(argptr, arg, target_size);
31e31b8a
FB
4056 }
4057 break;
4058 case IOC_W:
579a97f7
FB
4059 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
4060 if (!argptr)
4061 return -TARGET_EFAULT;
53a5960a
PB
4062 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
4063 unlock_user(argptr, arg, 0);
31e31b8a
FB
4064 ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
4065 break;
4066 default:
4067 case IOC_RW:
579a97f7
FB
4068 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
4069 if (!argptr)
4070 return -TARGET_EFAULT;
53a5960a
PB
4071 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
4072 unlock_user(argptr, arg, 0);
31e31b8a
FB
4073 ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
4074 if (!is_error(ret)) {
579a97f7
FB
4075 argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
4076 if (!argptr)
4077 return -TARGET_EFAULT;
53a5960a
PB
4078 thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
4079 unlock_user(argptr, arg, target_size);
31e31b8a
FB
4080 }
4081 break;
4082 }
4083 break;
4084 default:
32407103
JM
4085 gemu_log("Unsupported ioctl type: cmd=0x%04lx type=%d\n",
4086 (long)cmd, arg_type[0]);
0da46a6e 4087 ret = -TARGET_ENOSYS;
31e31b8a
FB
4088 break;
4089 }
4090 return ret;
4091}
4092
b39bc503 4093static const bitmask_transtbl iflag_tbl[] = {
31e31b8a
FB
4094 { TARGET_IGNBRK, TARGET_IGNBRK, IGNBRK, IGNBRK },
4095 { TARGET_BRKINT, TARGET_BRKINT, BRKINT, BRKINT },
4096 { TARGET_IGNPAR, TARGET_IGNPAR, IGNPAR, IGNPAR },
4097 { TARGET_PARMRK, TARGET_PARMRK, PARMRK, PARMRK },
4098 { TARGET_INPCK, TARGET_INPCK, INPCK, INPCK },
4099 { TARGET_ISTRIP, TARGET_ISTRIP, ISTRIP, ISTRIP },
4100 { TARGET_INLCR, TARGET_INLCR, INLCR, INLCR },
4101 { TARGET_IGNCR, TARGET_IGNCR, IGNCR, IGNCR },
4102 { TARGET_ICRNL, TARGET_ICRNL, ICRNL, ICRNL },
4103 { TARGET_IUCLC, TARGET_IUCLC, IUCLC, IUCLC },
4104 { TARGET_IXON, TARGET_IXON, IXON, IXON },
4105 { TARGET_IXANY, TARGET_IXANY, IXANY, IXANY },
4106 { TARGET_IXOFF, TARGET_IXOFF, IXOFF, IXOFF },
4107 { TARGET_IMAXBEL, TARGET_IMAXBEL, IMAXBEL, IMAXBEL },
4108 { 0, 0, 0, 0 }
4109};
4110
b39bc503 4111static const bitmask_transtbl oflag_tbl[] = {
31e31b8a
FB
4112 { TARGET_OPOST, TARGET_OPOST, OPOST, OPOST },
4113 { TARGET_OLCUC, TARGET_OLCUC, OLCUC, OLCUC },
4114 { TARGET_ONLCR, TARGET_ONLCR, ONLCR, ONLCR },
4115 { TARGET_OCRNL, TARGET_OCRNL, OCRNL, OCRNL },
4116 { TARGET_ONOCR, TARGET_ONOCR, ONOCR, ONOCR },
4117 { TARGET_ONLRET, TARGET_ONLRET, ONLRET, ONLRET },
4118 { TARGET_OFILL, TARGET_OFILL, OFILL, OFILL },
4119 { TARGET_OFDEL, TARGET_OFDEL, OFDEL, OFDEL },
4120 { TARGET_NLDLY, TARGET_NL0, NLDLY, NL0 },
4121 { TARGET_NLDLY, TARGET_NL1, NLDLY, NL1 },
4122 { TARGET_CRDLY, TARGET_CR0, CRDLY, CR0 },
4123 { TARGET_CRDLY, TARGET_CR1, CRDLY, CR1 },
4124 { TARGET_CRDLY, TARGET_CR2, CRDLY, CR2 },
4125 { TARGET_CRDLY, TARGET_CR3, CRDLY, CR3 },
4126 { TARGET_TABDLY, TARGET_TAB0, TABDLY, TAB0 },
4127 { TARGET_TABDLY, TARGET_TAB1, TABDLY, TAB1 },
4128 { TARGET_TABDLY, TARGET_TAB2, TABDLY, TAB2 },
4129 { TARGET_TABDLY, TARGET_TAB3, TABDLY, TAB3 },
4130 { TARGET_BSDLY, TARGET_BS0, BSDLY, BS0 },
4131 { TARGET_BSDLY, TARGET_BS1, BSDLY, BS1 },
4132 { TARGET_VTDLY, TARGET_VT0, VTDLY, VT0 },
4133 { TARGET_VTDLY, TARGET_VT1, VTDLY, VT1 },
4134 { TARGET_FFDLY, TARGET_FF0, FFDLY, FF0 },
4135 { TARGET_FFDLY, TARGET_FF1, FFDLY, FF1 },
4136 { 0, 0, 0, 0 }
4137};
4138
b39bc503 4139static const bitmask_transtbl cflag_tbl[] = {
31e31b8a
FB
4140 { TARGET_CBAUD, TARGET_B0, CBAUD, B0 },
4141 { TARGET_CBAUD, TARGET_B50, CBAUD, B50 },
4142 { TARGET_CBAUD, TARGET_B75, CBAUD, B75 },
4143 { TARGET_CBAUD, TARGET_B110, CBAUD, B110 },
4144 { TARGET_CBAUD, TARGET_B134, CBAUD, B134 },
4145 { TARGET_CBAUD, TARGET_B150, CBAUD, B150 },
4146 { TARGET_CBAUD, TARGET_B200, CBAUD, B200 },
4147 { TARGET_CBAUD, TARGET_B300, CBAUD, B300 },
4148 { TARGET_CBAUD, TARGET_B600, CBAUD, B600 },
4149 { TARGET_CBAUD, TARGET_B1200, CBAUD, B1200 },
4150 { TARGET_CBAUD, TARGET_B1800, CBAUD, B1800 },
4151 { TARGET_CBAUD, TARGET_B2400, CBAUD, B2400 },
4152 { TARGET_CBAUD, TARGET_B4800, CBAUD, B4800 },
4153 { TARGET_CBAUD, TARGET_B9600, CBAUD, B9600 },
4154 { TARGET_CBAUD, TARGET_B19200, CBAUD, B19200 },
4155 { TARGET_CBAUD, TARGET_B38400, CBAUD, B38400 },
4156 { TARGET_CBAUD, TARGET_B57600, CBAUD, B57600 },
4157 { TARGET_CBAUD, TARGET_B115200, CBAUD, B115200 },
4158 { TARGET_CBAUD, TARGET_B230400, CBAUD, B230400 },
4159 { TARGET_CBAUD, TARGET_B460800, CBAUD, B460800 },
4160 { TARGET_CSIZE, TARGET_CS5, CSIZE, CS5 },
4161 { TARGET_CSIZE, TARGET_CS6, CSIZE, CS6 },
4162 { TARGET_CSIZE, TARGET_CS7, CSIZE, CS7 },
4163 { TARGET_CSIZE, TARGET_CS8, CSIZE, CS8 },
4164 { TARGET_CSTOPB, TARGET_CSTOPB, CSTOPB, CSTOPB },
4165 { TARGET_CREAD, TARGET_CREAD, CREAD, CREAD },
4166 { TARGET_PARENB, TARGET_PARENB, PARENB, PARENB },
4167 { TARGET_PARODD, TARGET_PARODD, PARODD, PARODD },
4168 { TARGET_HUPCL, TARGET_HUPCL, HUPCL, HUPCL },
4169 { TARGET_CLOCAL, TARGET_CLOCAL, CLOCAL, CLOCAL },
4170 { TARGET_CRTSCTS, TARGET_CRTSCTS, CRTSCTS, CRTSCTS },
4171 { 0, 0, 0, 0 }
4172};
4173
b39bc503 4174static const bitmask_transtbl lflag_tbl[] = {
31e31b8a
FB
4175 { TARGET_ISIG, TARGET_ISIG, ISIG, ISIG },
4176 { TARGET_ICANON, TARGET_ICANON, ICANON, ICANON },
4177 { TARGET_XCASE, TARGET_XCASE, XCASE, XCASE },
4178 { TARGET_ECHO, TARGET_ECHO, ECHO, ECHO },
4179 { TARGET_ECHOE, TARGET_ECHOE, ECHOE, ECHOE },
4180 { TARGET_ECHOK, TARGET_ECHOK, ECHOK, ECHOK },
4181 { TARGET_ECHONL, TARGET_ECHONL, ECHONL, ECHONL },
4182 { TARGET_NOFLSH, TARGET_NOFLSH, NOFLSH, NOFLSH },
4183 { TARGET_TOSTOP, TARGET_TOSTOP, TOSTOP, TOSTOP },
4184 { TARGET_ECHOCTL, TARGET_ECHOCTL, ECHOCTL, ECHOCTL },
4185 { TARGET_ECHOPRT, TARGET_ECHOPRT, ECHOPRT, ECHOPRT },
4186 { TARGET_ECHOKE, TARGET_ECHOKE, ECHOKE, ECHOKE },
4187 { TARGET_FLUSHO, TARGET_FLUSHO, FLUSHO, FLUSHO },
4188 { TARGET_PENDIN, TARGET_PENDIN, PENDIN, PENDIN },
4189 { TARGET_IEXTEN, TARGET_IEXTEN, IEXTEN, IEXTEN },
4190 { 0, 0, 0, 0 }
4191};
4192
4193static void target_to_host_termios (void *dst, const void *src)
4194{
4195 struct host_termios *host = dst;
4196 const struct target_termios *target = src;
3b46e624 4197
5fafdf24 4198 host->c_iflag =
31e31b8a 4199 target_to_host_bitmask(tswap32(target->c_iflag), iflag_tbl);
5fafdf24 4200 host->c_oflag =
31e31b8a 4201 target_to_host_bitmask(tswap32(target->c_oflag), oflag_tbl);
5fafdf24 4202 host->c_cflag =
31e31b8a 4203 target_to_host_bitmask(tswap32(target->c_cflag), cflag_tbl);
5fafdf24 4204 host->c_lflag =
31e31b8a
FB
4205 target_to_host_bitmask(tswap32(target->c_lflag), lflag_tbl);
4206 host->c_line = target->c_line;
3b46e624 4207
44607123 4208 memset(host->c_cc, 0, sizeof(host->c_cc));
5fafdf24
TS
4209 host->c_cc[VINTR] = target->c_cc[TARGET_VINTR];
4210 host->c_cc[VQUIT] = target->c_cc[TARGET_VQUIT];
3b46e624 4211 host->c_cc[VERASE] = target->c_cc[TARGET_VERASE];
5fafdf24 4212 host->c_cc[VKILL] = target->c_cc[TARGET_VKILL];
3b46e624 4213 host->c_cc[VEOF] = target->c_cc[TARGET_VEOF];
5fafdf24 4214 host->c_cc[VTIME] = target->c_cc[TARGET_VTIME];
3b46e624 4215 host->c_cc[VMIN] = target->c_cc[TARGET_VMIN];
5fafdf24 4216 host->c_cc[VSWTC] = target->c_cc[TARGET_VSWTC];
3b46e624 4217 host->c_cc[VSTART] = target->c_cc[TARGET_VSTART];
5fafdf24
TS
4218 host->c_cc[VSTOP] = target->c_cc[TARGET_VSTOP];
4219 host->c_cc[VSUSP] = target->c_cc[TARGET_VSUSP];
3b46e624
TS
4220 host->c_cc[VEOL] = target->c_cc[TARGET_VEOL];
4221 host->c_cc[VREPRINT] = target->c_cc[TARGET_VREPRINT];
4222 host->c_cc[VDISCARD] = target->c_cc[TARGET_VDISCARD];
4223 host->c_cc[VWERASE] = target->c_cc[TARGET_VWERASE];
4224 host->c_cc[VLNEXT] = target->c_cc[TARGET_VLNEXT];
5fafdf24 4225 host->c_cc[VEOL2] = target->c_cc[TARGET_VEOL2];
31e31b8a 4226}
3b46e624 4227
31e31b8a
FB
4228static void host_to_target_termios (void *dst, const void *src)
4229{
4230 struct target_termios *target = dst;
4231 const struct host_termios *host = src;
4232
5fafdf24 4233 target->c_iflag =
31e31b8a 4234 tswap32(host_to_target_bitmask(host->c_iflag, iflag_tbl));
5fafdf24 4235 target->c_oflag =
31e31b8a 4236 tswap32(host_to_target_bitmask(host->c_oflag, oflag_tbl));
5fafdf24 4237 target->c_cflag =
31e31b8a 4238 tswap32(host_to_target_bitmask(host->c_cflag, cflag_tbl));
5fafdf24 4239 target->c_lflag =
31e31b8a
FB
4240 tswap32(host_to_target_bitmask(host->c_lflag, lflag_tbl));
4241 target->c_line = host->c_line;
3b46e624 4242
44607123 4243 memset(target->c_cc, 0, sizeof(target->c_cc));
31e31b8a
FB
4244 target->c_cc[TARGET_VINTR] = host->c_cc[VINTR];
4245 target->c_cc[TARGET_VQUIT] = host->c_cc[VQUIT];
4246 target->c_cc[TARGET_VERASE] = host->c_cc[VERASE];
4247 target->c_cc[TARGET_VKILL] = host->c_cc[VKILL];
4248 target->c_cc[TARGET_VEOF] = host->c_cc[VEOF];
4249 target->c_cc[TARGET_VTIME] = host->c_cc[VTIME];
4250 target->c_cc[TARGET_VMIN] = host->c_cc[VMIN];
4251 target->c_cc[TARGET_VSWTC] = host->c_cc[VSWTC];
4252 target->c_cc[TARGET_VSTART] = host->c_cc[VSTART];
4253 target->c_cc[TARGET_VSTOP] = host->c_cc[VSTOP];
4254 target->c_cc[TARGET_VSUSP] = host->c_cc[VSUSP];
4255 target->c_cc[TARGET_VEOL] = host->c_cc[VEOL];
4256 target->c_cc[TARGET_VREPRINT] = host->c_cc[VREPRINT];
4257 target->c_cc[TARGET_VDISCARD] = host->c_cc[VDISCARD];
4258 target->c_cc[TARGET_VWERASE] = host->c_cc[VWERASE];
4259 target->c_cc[TARGET_VLNEXT] = host->c_cc[VLNEXT];
4260 target->c_cc[TARGET_VEOL2] = host->c_cc[VEOL2];
4261}
4262
8e853dc7 4263static const StructEntry struct_termios_def = {
31e31b8a
FB
4264 .convert = { host_to_target_termios, target_to_host_termios },
4265 .size = { sizeof(struct target_termios), sizeof(struct host_termios) },
4266 .align = { __alignof__(struct target_termios), __alignof__(struct host_termios) },
4267};
4268
5286db75
FB
4269static bitmask_transtbl mmap_flags_tbl[] = {
4270 { TARGET_MAP_SHARED, TARGET_MAP_SHARED, MAP_SHARED, MAP_SHARED },
4271 { TARGET_MAP_PRIVATE, TARGET_MAP_PRIVATE, MAP_PRIVATE, MAP_PRIVATE },
4272 { TARGET_MAP_FIXED, TARGET_MAP_FIXED, MAP_FIXED, MAP_FIXED },
4273 { TARGET_MAP_ANONYMOUS, TARGET_MAP_ANONYMOUS, MAP_ANONYMOUS, MAP_ANONYMOUS },
4274 { TARGET_MAP_GROWSDOWN, TARGET_MAP_GROWSDOWN, MAP_GROWSDOWN, MAP_GROWSDOWN },
4275 { TARGET_MAP_DENYWRITE, TARGET_MAP_DENYWRITE, MAP_DENYWRITE, MAP_DENYWRITE },
4276 { TARGET_MAP_EXECUTABLE, TARGET_MAP_EXECUTABLE, MAP_EXECUTABLE, MAP_EXECUTABLE },
4277 { TARGET_MAP_LOCKED, TARGET_MAP_LOCKED, MAP_LOCKED, MAP_LOCKED },
e8efd8e7
CL
4278 { TARGET_MAP_NORESERVE, TARGET_MAP_NORESERVE, MAP_NORESERVE,
4279 MAP_NORESERVE },
5286db75
FB
4280 { 0, 0, 0, 0 }
4281};
4282
2ab83ea7 4283#if defined(TARGET_I386)
6dbad63e
FB
4284
4285/* NOTE: there is really one LDT for all the threads */
b1d8e52e 4286static uint8_t *ldt_table;
6dbad63e 4287
03acab66 4288static abi_long read_ldt(abi_ulong ptr, unsigned long bytecount)
6dbad63e
FB
4289{
4290 int size;
53a5960a 4291 void *p;
6dbad63e
FB
4292
4293 if (!ldt_table)
4294 return 0;
4295 size = TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE;
4296 if (size > bytecount)
4297 size = bytecount;
579a97f7
FB
4298 p = lock_user(VERIFY_WRITE, ptr, size, 0);
4299 if (!p)
03acab66 4300 return -TARGET_EFAULT;
579a97f7 4301 /* ??? Should this by byteswapped? */
53a5960a
PB
4302 memcpy(p, ldt_table, size);
4303 unlock_user(p, ptr, size);
6dbad63e
FB
4304 return size;
4305}
4306
4307/* XXX: add locking support */
03acab66
FB
4308static abi_long write_ldt(CPUX86State *env,
4309 abi_ulong ptr, unsigned long bytecount, int oldmode)
6dbad63e
FB
4310{
4311 struct target_modify_ldt_ldt_s ldt_info;
53a5960a 4312 struct target_modify_ldt_ldt_s *target_ldt_info;
6dbad63e 4313 int seg_32bit, contents, read_exec_only, limit_in_pages;
8d18e893 4314 int seg_not_present, useable, lm;
6dbad63e
FB
4315 uint32_t *lp, entry_1, entry_2;
4316
4317 if (bytecount != sizeof(ldt_info))
03acab66 4318 return -TARGET_EINVAL;
579a97f7 4319 if (!lock_user_struct(VERIFY_READ, target_ldt_info, ptr, 1))
03acab66 4320 return -TARGET_EFAULT;
53a5960a 4321 ldt_info.entry_number = tswap32(target_ldt_info->entry_number);
cbb21eed 4322 ldt_info.base_addr = tswapal(target_ldt_info->base_addr);
53a5960a
PB
4323 ldt_info.limit = tswap32(target_ldt_info->limit);
4324 ldt_info.flags = tswap32(target_ldt_info->flags);
4325 unlock_user_struct(target_ldt_info, ptr, 0);
3b46e624 4326
6dbad63e 4327 if (ldt_info.entry_number >= TARGET_LDT_ENTRIES)
03acab66 4328 return -TARGET_EINVAL;
6dbad63e
FB
4329 seg_32bit = ldt_info.flags & 1;
4330 contents = (ldt_info.flags >> 1) & 3;
4331 read_exec_only = (ldt_info.flags >> 3) & 1;
4332 limit_in_pages = (ldt_info.flags >> 4) & 1;
4333 seg_not_present = (ldt_info.flags >> 5) & 1;
4334 useable = (ldt_info.flags >> 6) & 1;
8d18e893
FB
4335#ifdef TARGET_ABI32
4336 lm = 0;
4337#else
4338 lm = (ldt_info.flags >> 7) & 1;
4339#endif
6dbad63e
FB
4340 if (contents == 3) {
4341 if (oldmode)
03acab66 4342 return -TARGET_EINVAL;
6dbad63e 4343 if (seg_not_present == 0)
03acab66 4344 return -TARGET_EINVAL;
6dbad63e
FB
4345 }
4346 /* allocate the LDT */
4347 if (!ldt_table) {
e441570f
AZ
4348 env->ldt.base = target_mmap(0,
4349 TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE,
4350 PROT_READ|PROT_WRITE,
4351 MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
4352 if (env->ldt.base == -1)
03acab66 4353 return -TARGET_ENOMEM;
e441570f
AZ
4354 memset(g2h(env->ldt.base), 0,
4355 TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE);
6dbad63e 4356 env->ldt.limit = 0xffff;
e441570f 4357 ldt_table = g2h(env->ldt.base);
6dbad63e
FB
4358 }
4359
4360 /* NOTE: same code as Linux kernel */
4361 /* Allow LDTs to be cleared by the user. */
4362 if (ldt_info.base_addr == 0 && ldt_info.limit == 0) {
4363 if (oldmode ||
4364 (contents == 0 &&
4365 read_exec_only == 1 &&
4366 seg_32bit == 0 &&
4367 limit_in_pages == 0 &&
4368 seg_not_present == 1 &&
4369 useable == 0 )) {
4370 entry_1 = 0;
4371 entry_2 = 0;
4372 goto install;
4373 }
4374 }
3b46e624 4375
6dbad63e
FB
4376 entry_1 = ((ldt_info.base_addr & 0x0000ffff) << 16) |
4377 (ldt_info.limit & 0x0ffff);
4378 entry_2 = (ldt_info.base_addr & 0xff000000) |
4379 ((ldt_info.base_addr & 0x00ff0000) >> 16) |
4380 (ldt_info.limit & 0xf0000) |
4381 ((read_exec_only ^ 1) << 9) |
4382 (contents << 10) |
4383 ((seg_not_present ^ 1) << 15) |
4384 (seg_32bit << 22) |
4385 (limit_in_pages << 23) |
8d18e893 4386 (lm << 21) |
6dbad63e
FB
4387 0x7000;
4388 if (!oldmode)
4389 entry_2 |= (useable << 20);
14ae3ba7 4390
6dbad63e
FB
4391 /* Install the new entry ... */
4392install:
4393 lp = (uint32_t *)(ldt_table + (ldt_info.entry_number << 3));
4394 lp[0] = tswap32(entry_1);
4395 lp[1] = tswap32(entry_2);
4396 return 0;
4397}
4398
4399/* specific and weird i386 syscalls */
8fcd3692
BS
4400static abi_long do_modify_ldt(CPUX86State *env, int func, abi_ulong ptr,
4401 unsigned long bytecount)
6dbad63e 4402{
03acab66 4403 abi_long ret;
3b46e624 4404
6dbad63e
FB
4405 switch (func) {
4406 case 0:
4407 ret = read_ldt(ptr, bytecount);
4408 break;
4409 case 1:
4410 ret = write_ldt(env, ptr, bytecount, 1);
4411 break;
4412 case 0x11:
4413 ret = write_ldt(env, ptr, bytecount, 0);
4414 break;
03acab66
FB
4415 default:
4416 ret = -TARGET_ENOSYS;
4417 break;
6dbad63e
FB
4418 }
4419 return ret;
4420}
1b6b029e 4421
4583f589 4422#if defined(TARGET_I386) && defined(TARGET_ABI32)
bc22eb44 4423abi_long do_set_thread_area(CPUX86State *env, abi_ulong ptr)
8d18e893
FB
4424{
4425 uint64_t *gdt_table = g2h(env->gdt.base);
4426 struct target_modify_ldt_ldt_s ldt_info;
4427 struct target_modify_ldt_ldt_s *target_ldt_info;
4428 int seg_32bit, contents, read_exec_only, limit_in_pages;
4429 int seg_not_present, useable, lm;
4430 uint32_t *lp, entry_1, entry_2;
4431 int i;
4432
4433 lock_user_struct(VERIFY_WRITE, target_ldt_info, ptr, 1);
4434 if (!target_ldt_info)
4435 return -TARGET_EFAULT;
4436 ldt_info.entry_number = tswap32(target_ldt_info->entry_number);
cbb21eed 4437 ldt_info.base_addr = tswapal(target_ldt_info->base_addr);
8d18e893
FB
4438 ldt_info.limit = tswap32(target_ldt_info->limit);
4439 ldt_info.flags = tswap32(target_ldt_info->flags);
4440 if (ldt_info.entry_number == -1) {
4441 for (i=TARGET_GDT_ENTRY_TLS_MIN; i<=TARGET_GDT_ENTRY_TLS_MAX; i++) {
4442 if (gdt_table[i] == 0) {
4443 ldt_info.entry_number = i;
4444 target_ldt_info->entry_number = tswap32(i);
4445 break;
4446 }
4447 }
4448 }
4449 unlock_user_struct(target_ldt_info, ptr, 1);
4450
4451 if (ldt_info.entry_number < TARGET_GDT_ENTRY_TLS_MIN ||
4452 ldt_info.entry_number > TARGET_GDT_ENTRY_TLS_MAX)
4453 return -TARGET_EINVAL;
4454 seg_32bit = ldt_info.flags & 1;
4455 contents = (ldt_info.flags >> 1) & 3;
4456 read_exec_only = (ldt_info.flags >> 3) & 1;
4457 limit_in_pages = (ldt_info.flags >> 4) & 1;
4458 seg_not_present = (ldt_info.flags >> 5) & 1;
4459 useable = (ldt_info.flags >> 6) & 1;
4460#ifdef TARGET_ABI32
4461 lm = 0;
4462#else
4463 lm = (ldt_info.flags >> 7) & 1;
4464#endif
4465
4466 if (contents == 3) {
4467 if (seg_not_present == 0)
4468 return -TARGET_EINVAL;
4469 }
4470
4471 /* NOTE: same code as Linux kernel */
4472 /* Allow LDTs to be cleared by the user. */
4473 if (ldt_info.base_addr == 0 && ldt_info.limit == 0) {
4474 if ((contents == 0 &&
4475 read_exec_only == 1 &&
4476 seg_32bit == 0 &&
4477 limit_in_pages == 0 &&
4478 seg_not_present == 1 &&
4479 useable == 0 )) {
4480 entry_1 = 0;
4481 entry_2 = 0;
4482 goto install;
4483 }
4484 }
4485
4486 entry_1 = ((ldt_info.base_addr & 0x0000ffff) << 16) |
4487 (ldt_info.limit & 0x0ffff);
4488 entry_2 = (ldt_info.base_addr & 0xff000000) |
4489 ((ldt_info.base_addr & 0x00ff0000) >> 16) |
4490 (ldt_info.limit & 0xf0000) |
4491 ((read_exec_only ^ 1) << 9) |
4492 (contents << 10) |
4493 ((seg_not_present ^ 1) << 15) |
4494 (seg_32bit << 22) |
4495 (limit_in_pages << 23) |
4496 (useable << 20) |
4497 (lm << 21) |
4498 0x7000;
4499
4500 /* Install the new entry ... */
4501install:
4502 lp = (uint32_t *)(gdt_table + ldt_info.entry_number);
4503 lp[0] = tswap32(entry_1);
4504 lp[1] = tswap32(entry_2);
4505 return 0;
4506}
4507
8fcd3692 4508static abi_long do_get_thread_area(CPUX86State *env, abi_ulong ptr)
8d18e893
FB
4509{
4510 struct target_modify_ldt_ldt_s *target_ldt_info;
4511 uint64_t *gdt_table = g2h(env->gdt.base);
4512 uint32_t base_addr, limit, flags;
4513 int seg_32bit, contents, read_exec_only, limit_in_pages, idx;
4514 int seg_not_present, useable, lm;
4515 uint32_t *lp, entry_1, entry_2;
4516
4517 lock_user_struct(VERIFY_WRITE, target_ldt_info, ptr, 1);
4518 if (!target_ldt_info)
4519 return -TARGET_EFAULT;
4520 idx = tswap32(target_ldt_info->entry_number);
4521 if (idx < TARGET_GDT_ENTRY_TLS_MIN ||
4522 idx > TARGET_GDT_ENTRY_TLS_MAX) {
4523 unlock_user_struct(target_ldt_info, ptr, 1);
4524 return -TARGET_EINVAL;
4525 }
4526 lp = (uint32_t *)(gdt_table + idx);
4527 entry_1 = tswap32(lp[0]);
4528 entry_2 = tswap32(lp[1]);
4529
4530 read_exec_only = ((entry_2 >> 9) & 1) ^ 1;
4531 contents = (entry_2 >> 10) & 3;
4532 seg_not_present = ((entry_2 >> 15) & 1) ^ 1;
4533 seg_32bit = (entry_2 >> 22) & 1;
4534 limit_in_pages = (entry_2 >> 23) & 1;
4535 useable = (entry_2 >> 20) & 1;
4536#ifdef TARGET_ABI32
4537 lm = 0;
4538#else
4539 lm = (entry_2 >> 21) & 1;
4540#endif
4541 flags = (seg_32bit << 0) | (contents << 1) |
4542 (read_exec_only << 3) | (limit_in_pages << 4) |
4543 (seg_not_present << 5) | (useable << 6) | (lm << 7);
4544 limit = (entry_1 & 0xffff) | (entry_2 & 0xf0000);
4545 base_addr = (entry_1 >> 16) |
4546 (entry_2 & 0xff000000) |
4547 ((entry_2 & 0xff) << 16);
cbb21eed 4548 target_ldt_info->base_addr = tswapal(base_addr);
8d18e893
FB
4549 target_ldt_info->limit = tswap32(limit);
4550 target_ldt_info->flags = tswap32(flags);
4551 unlock_user_struct(target_ldt_info, ptr, 1);
4552 return 0;
4553}
4583f589 4554#endif /* TARGET_I386 && TARGET_ABI32 */
8d18e893 4555
d2fd1af7 4556#ifndef TARGET_ABI32
2667e71c 4557abi_long do_arch_prctl(CPUX86State *env, int code, abi_ulong addr)
d2fd1af7 4558{
1add8698 4559 abi_long ret = 0;
d2fd1af7
FB
4560 abi_ulong val;
4561 int idx;
1add8698 4562
d2fd1af7
FB
4563 switch(code) {
4564 case TARGET_ARCH_SET_GS:
4565 case TARGET_ARCH_SET_FS:
4566 if (code == TARGET_ARCH_SET_GS)
4567 idx = R_GS;
4568 else
4569 idx = R_FS;
4570 cpu_x86_load_seg(env, idx, 0);
4571 env->segs[idx].base = addr;
4572 break;
4573 case TARGET_ARCH_GET_GS:
4574 case TARGET_ARCH_GET_FS:
4575 if (code == TARGET_ARCH_GET_GS)
4576 idx = R_GS;
4577 else
4578 idx = R_FS;
4579 val = env->segs[idx].base;
4580 if (put_user(val, addr, abi_ulong))
1add8698 4581 ret = -TARGET_EFAULT;
d2fd1af7
FB
4582 break;
4583 default:
4584 ret = -TARGET_EINVAL;
4585 break;
4586 }
1add8698 4587 return ret;
d2fd1af7
FB
4588}
4589#endif
4590
2ab83ea7
FB
4591#endif /* defined(TARGET_I386) */
4592
05098a93 4593#define NEW_STACK_SIZE 0x40000
d865bab5 4594
d865bab5
PB
4595
4596static pthread_mutex_t clone_lock = PTHREAD_MUTEX_INITIALIZER;
4597typedef struct {
9349b4f9 4598 CPUArchState *env;
d865bab5
PB
4599 pthread_mutex_t mutex;
4600 pthread_cond_t cond;
4601 pthread_t thread;
4602 uint32_t tid;
4603 abi_ulong child_tidptr;
4604 abi_ulong parent_tidptr;
4605 sigset_t sigmask;
4606} new_thread_info;
4607
4608static void *clone_func(void *arg)
4609{
4610 new_thread_info *info = arg;
9349b4f9 4611 CPUArchState *env;
0d34282f 4612 CPUState *cpu;
edf8e2af 4613 TaskState *ts;
d865bab5 4614
70903763 4615 rcu_register_thread();
d865bab5 4616 env = info->env;
0d34282f 4617 cpu = ENV_GET_CPU(env);
a2247f8e 4618 thread_cpu = cpu;
0429a971 4619 ts = (TaskState *)cpu->opaque;
d865bab5 4620 info->tid = gettid();
0d34282f 4621 cpu->host_tid = info->tid;
edf8e2af 4622 task_settid(ts);
d865bab5
PB
4623 if (info->child_tidptr)
4624 put_user_u32(info->tid, info->child_tidptr);
4625 if (info->parent_tidptr)
4626 put_user_u32(info->tid, info->parent_tidptr);
4627 /* Enable signals. */
4628 sigprocmask(SIG_SETMASK, &info->sigmask, NULL);
4629 /* Signal to the parent that we're ready. */
4630 pthread_mutex_lock(&info->mutex);
4631 pthread_cond_broadcast(&info->cond);
4632 pthread_mutex_unlock(&info->mutex);
4633 /* Wait until the parent has finshed initializing the tls state. */
4634 pthread_mutex_lock(&clone_lock);
4635 pthread_mutex_unlock(&clone_lock);
4636 cpu_loop(env);
4637 /* never exits */
4638 return NULL;
4639}
1b6b029e 4640
0da46a6e
TS
4641/* do_fork() Must return host values and target errnos (unlike most
4642 do_*() functions). */
9349b4f9 4643static int do_fork(CPUArchState *env, unsigned int flags, abi_ulong newsp,
d865bab5
PB
4644 abi_ulong parent_tidptr, target_ulong newtls,
4645 abi_ulong child_tidptr)
1b6b029e 4646{
0429a971 4647 CPUState *cpu = ENV_GET_CPU(env);
1b6b029e 4648 int ret;
5cd4393b 4649 TaskState *ts;
0429a971 4650 CPUState *new_cpu;
9349b4f9 4651 CPUArchState *new_env;
d865bab5
PB
4652 unsigned int nptl_flags;
4653 sigset_t sigmask;
3b46e624 4654
436d124b
AZ
4655 /* Emulate vfork() with fork() */
4656 if (flags & CLONE_VFORK)
4657 flags &= ~(CLONE_VFORK | CLONE_VM);
4658
1b6b029e 4659 if (flags & CLONE_VM) {
0429a971 4660 TaskState *parent_ts = (TaskState *)cpu->opaque;
d865bab5
PB
4661 new_thread_info info;
4662 pthread_attr_t attr;
24cb36a6 4663
c78d65e8 4664 ts = g_new0(TaskState, 1);
624f7979 4665 init_task_state(ts);
1b6b029e 4666 /* we create a new CPU instance. */
c5be9f08 4667 new_env = cpu_copy(env);
6e68e076
PB
4668 /* Init regs that differ from the parent. */
4669 cpu_clone_regs(new_env, newsp);
0429a971
AF
4670 new_cpu = ENV_GET_CPU(new_env);
4671 new_cpu->opaque = ts;
edf8e2af
MW
4672 ts->bprm = parent_ts->bprm;
4673 ts->info = parent_ts->info;
d865bab5
PB
4674 nptl_flags = flags;
4675 flags &= ~CLONE_NPTL_FLAGS2;
4676
c2764719
PB
4677 if (nptl_flags & CLONE_CHILD_CLEARTID) {
4678 ts->child_tidptr = child_tidptr;
4679 }
4680
d865bab5
PB
4681 if (nptl_flags & CLONE_SETTLS)
4682 cpu_set_tls (new_env, newtls);
4683
4684 /* Grab a mutex so that thread setup appears atomic. */
4685 pthread_mutex_lock(&clone_lock);
4686
4687 memset(&info, 0, sizeof(info));
4688 pthread_mutex_init(&info.mutex, NULL);
4689 pthread_mutex_lock(&info.mutex);
4690 pthread_cond_init(&info.cond, NULL);
4691 info.env = new_env;
4692 if (nptl_flags & CLONE_CHILD_SETTID)
4693 info.child_tidptr = child_tidptr;
4694 if (nptl_flags & CLONE_PARENT_SETTID)
4695 info.parent_tidptr = parent_tidptr;
4696
4697 ret = pthread_attr_init(&attr);
48e15fc2
NF
4698 ret = pthread_attr_setstacksize(&attr, NEW_STACK_SIZE);
4699 ret = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
d865bab5
PB
4700 /* It is not safe to deliver signals until the child has finished
4701 initializing, so temporarily block all signals. */
4702 sigfillset(&sigmask);
4703 sigprocmask(SIG_BLOCK, &sigmask, &info.sigmask);
4704
4705 ret = pthread_create(&info.thread, &attr, clone_func, &info);
c2764719 4706 /* TODO: Free new CPU state if thread creation failed. */
d865bab5
PB
4707
4708 sigprocmask(SIG_SETMASK, &info.sigmask, NULL);
4709 pthread_attr_destroy(&attr);
4710 if (ret == 0) {
4711 /* Wait for the child to initialize. */
4712 pthread_cond_wait(&info.cond, &info.mutex);
4713 ret = info.tid;
4714 if (flags & CLONE_PARENT_SETTID)
4715 put_user_u32(ret, parent_tidptr);
4716 } else {
4717 ret = -1;
4718 }
4719 pthread_mutex_unlock(&info.mutex);
4720 pthread_cond_destroy(&info.cond);
4721 pthread_mutex_destroy(&info.mutex);
4722 pthread_mutex_unlock(&clone_lock);
1b6b029e
FB
4723 } else {
4724 /* if no CLONE_VM, we consider it is a fork */
93b4eff8
TB
4725 if ((flags & ~(CSIGNAL | CLONE_NPTL_FLAGS2)) != 0) {
4726 return -TARGET_EINVAL;
4727 }
d865bab5 4728 fork_start();
1b6b029e 4729 ret = fork();
d865bab5 4730 if (ret == 0) {
2b1319c8 4731 /* Child Process. */
a59629fc 4732 rcu_after_fork();
d865bab5
PB
4733 cpu_clone_regs(env, newsp);
4734 fork_end(1);
2b1319c8
AJ
4735 /* There is a race condition here. The parent process could
4736 theoretically read the TID in the child process before the child
4737 tid is set. This would require using either ptrace
4738 (not implemented) or having *_tidptr to point at a shared memory
4739 mapping. We can't repeat the spinlock hack used above because
4740 the child process gets its own copy of the lock. */
d865bab5
PB
4741 if (flags & CLONE_CHILD_SETTID)
4742 put_user_u32(gettid(), child_tidptr);
4743 if (flags & CLONE_PARENT_SETTID)
4744 put_user_u32(gettid(), parent_tidptr);
0429a971 4745 ts = (TaskState *)cpu->opaque;
d865bab5
PB
4746 if (flags & CLONE_SETTLS)
4747 cpu_set_tls (env, newtls);
c2764719
PB
4748 if (flags & CLONE_CHILD_CLEARTID)
4749 ts->child_tidptr = child_tidptr;
d865bab5
PB
4750 } else {
4751 fork_end(0);
4752 }
1b6b029e
FB
4753 }
4754 return ret;
4755}
4756
5f106811
APR
4757/* warning : doesn't handle linux specific flags... */
4758static int target_to_host_fcntl_cmd(int cmd)
4759{
4760 switch(cmd) {
4761 case TARGET_F_DUPFD:
4762 case TARGET_F_GETFD:
4763 case TARGET_F_SETFD:
4764 case TARGET_F_GETFL:
4765 case TARGET_F_SETFL:
4766 return cmd;
4767 case TARGET_F_GETLK:
4768 return F_GETLK;
4769 case TARGET_F_SETLK:
4770 return F_SETLK;
4771 case TARGET_F_SETLKW:
4772 return F_SETLKW;
4773 case TARGET_F_GETOWN:
4774 return F_GETOWN;
4775 case TARGET_F_SETOWN:
4776 return F_SETOWN;
4777 case TARGET_F_GETSIG:
4778 return F_GETSIG;
4779 case TARGET_F_SETSIG:
4780 return F_SETSIG;
4781#if TARGET_ABI_BITS == 32
4782 case TARGET_F_GETLK64:
4783 return F_GETLK64;
4784 case TARGET_F_SETLK64:
4785 return F_SETLK64;
4786 case TARGET_F_SETLKW64:
4787 return F_SETLKW64;
4788#endif
7e22e546
UH
4789 case TARGET_F_SETLEASE:
4790 return F_SETLEASE;
4791 case TARGET_F_GETLEASE:
4792 return F_GETLEASE;
fbd5de9b 4793#ifdef F_DUPFD_CLOEXEC
7e22e546
UH
4794 case TARGET_F_DUPFD_CLOEXEC:
4795 return F_DUPFD_CLOEXEC;
fbd5de9b 4796#endif
7e22e546
UH
4797 case TARGET_F_NOTIFY:
4798 return F_NOTIFY;
8d5d3004
AS
4799#ifdef F_GETOWN_EX
4800 case TARGET_F_GETOWN_EX:
4801 return F_GETOWN_EX;
4802#endif
4803#ifdef F_SETOWN_EX
4804 case TARGET_F_SETOWN_EX:
4805 return F_SETOWN_EX;
4806#endif
5f106811
APR
4807 default:
4808 return -TARGET_EINVAL;
4809 }
4810 return -TARGET_EINVAL;
4811}
4812
2ba7f730
LV
4813#define TRANSTBL_CONVERT(a) { -1, TARGET_##a, -1, a }
4814static const bitmask_transtbl flock_tbl[] = {
4815 TRANSTBL_CONVERT(F_RDLCK),
4816 TRANSTBL_CONVERT(F_WRLCK),
4817 TRANSTBL_CONVERT(F_UNLCK),
4818 TRANSTBL_CONVERT(F_EXLCK),
4819 TRANSTBL_CONVERT(F_SHLCK),
4820 { 0, 0, 0, 0 }
4821};
4822
992f48a0 4823static abi_long do_fcntl(int fd, int cmd, abi_ulong arg)
7775e9ec
FB
4824{
4825 struct flock fl;
53a5960a 4826 struct target_flock *target_fl;
43f238d7
TS
4827 struct flock64 fl64;
4828 struct target_flock64 *target_fl64;
8d5d3004
AS
4829#ifdef F_GETOWN_EX
4830 struct f_owner_ex fox;
4831 struct target_f_owner_ex *target_fox;
4832#endif
992f48a0 4833 abi_long ret;
5f106811
APR
4834 int host_cmd = target_to_host_fcntl_cmd(cmd);
4835
4836 if (host_cmd == -TARGET_EINVAL)
4837 return host_cmd;
53a5960a 4838
7775e9ec
FB
4839 switch(cmd) {
4840 case TARGET_F_GETLK:
579a97f7
FB
4841 if (!lock_user_struct(VERIFY_READ, target_fl, arg, 1))
4842 return -TARGET_EFAULT;
2ba7f730
LV
4843 fl.l_type =
4844 target_to_host_bitmask(tswap16(target_fl->l_type), flock_tbl);
5813427b 4845 fl.l_whence = tswap16(target_fl->l_whence);
cbb21eed
MB
4846 fl.l_start = tswapal(target_fl->l_start);
4847 fl.l_len = tswapal(target_fl->l_len);
7e22e546 4848 fl.l_pid = tswap32(target_fl->l_pid);
5813427b 4849 unlock_user_struct(target_fl, arg, 0);
5f106811 4850 ret = get_errno(fcntl(fd, host_cmd, &fl));
7775e9ec 4851 if (ret == 0) {
579a97f7
FB
4852 if (!lock_user_struct(VERIFY_WRITE, target_fl, arg, 0))
4853 return -TARGET_EFAULT;
2ba7f730
LV
4854 target_fl->l_type =
4855 host_to_target_bitmask(tswap16(fl.l_type), flock_tbl);
7775e9ec 4856 target_fl->l_whence = tswap16(fl.l_whence);
cbb21eed
MB
4857 target_fl->l_start = tswapal(fl.l_start);
4858 target_fl->l_len = tswapal(fl.l_len);
7e22e546 4859 target_fl->l_pid = tswap32(fl.l_pid);
53a5960a 4860 unlock_user_struct(target_fl, arg, 1);
7775e9ec
FB
4861 }
4862 break;
3b46e624 4863
7775e9ec
FB
4864 case TARGET_F_SETLK:
4865 case TARGET_F_SETLKW:
579a97f7
FB
4866 if (!lock_user_struct(VERIFY_READ, target_fl, arg, 1))
4867 return -TARGET_EFAULT;
2ba7f730
LV
4868 fl.l_type =
4869 target_to_host_bitmask(tswap16(target_fl->l_type), flock_tbl);
7775e9ec 4870 fl.l_whence = tswap16(target_fl->l_whence);
cbb21eed
MB
4871 fl.l_start = tswapal(target_fl->l_start);
4872 fl.l_len = tswapal(target_fl->l_len);
7e22e546 4873 fl.l_pid = tswap32(target_fl->l_pid);
53a5960a 4874 unlock_user_struct(target_fl, arg, 0);
5f106811 4875 ret = get_errno(fcntl(fd, host_cmd, &fl));
7775e9ec 4876 break;
3b46e624 4877
7775e9ec 4878 case TARGET_F_GETLK64:
579a97f7
FB
4879 if (!lock_user_struct(VERIFY_READ, target_fl64, arg, 1))
4880 return -TARGET_EFAULT;
2ba7f730
LV
4881 fl64.l_type =
4882 target_to_host_bitmask(tswap16(target_fl64->l_type), flock_tbl) >> 1;
5813427b 4883 fl64.l_whence = tswap16(target_fl64->l_whence);
cbb21eed
MB
4884 fl64.l_start = tswap64(target_fl64->l_start);
4885 fl64.l_len = tswap64(target_fl64->l_len);
7e22e546 4886 fl64.l_pid = tswap32(target_fl64->l_pid);
5813427b 4887 unlock_user_struct(target_fl64, arg, 0);
5f106811 4888 ret = get_errno(fcntl(fd, host_cmd, &fl64));
43f238d7 4889 if (ret == 0) {
579a97f7
FB
4890 if (!lock_user_struct(VERIFY_WRITE, target_fl64, arg, 0))
4891 return -TARGET_EFAULT;
2ba7f730
LV
4892 target_fl64->l_type =
4893 host_to_target_bitmask(tswap16(fl64.l_type), flock_tbl) >> 1;
43f238d7 4894 target_fl64->l_whence = tswap16(fl64.l_whence);
cbb21eed
MB
4895 target_fl64->l_start = tswap64(fl64.l_start);
4896 target_fl64->l_len = tswap64(fl64.l_len);
7e22e546 4897 target_fl64->l_pid = tswap32(fl64.l_pid);
43f238d7
TS
4898 unlock_user_struct(target_fl64, arg, 1);
4899 }
9ee1fa2c 4900 break;
7775e9ec
FB
4901 case TARGET_F_SETLK64:
4902 case TARGET_F_SETLKW64:
579a97f7
FB
4903 if (!lock_user_struct(VERIFY_READ, target_fl64, arg, 1))
4904 return -TARGET_EFAULT;
2ba7f730
LV
4905 fl64.l_type =
4906 target_to_host_bitmask(tswap16(target_fl64->l_type), flock_tbl) >> 1;
43f238d7 4907 fl64.l_whence = tswap16(target_fl64->l_whence);
cbb21eed
MB
4908 fl64.l_start = tswap64(target_fl64->l_start);
4909 fl64.l_len = tswap64(target_fl64->l_len);
7e22e546 4910 fl64.l_pid = tswap32(target_fl64->l_pid);
43f238d7 4911 unlock_user_struct(target_fl64, arg, 0);
5f106811 4912 ret = get_errno(fcntl(fd, host_cmd, &fl64));
7775e9ec
FB
4913 break;
4914
5f106811
APR
4915 case TARGET_F_GETFL:
4916 ret = get_errno(fcntl(fd, host_cmd, arg));
9ee1fa2c
FB
4917 if (ret >= 0) {
4918 ret = host_to_target_bitmask(ret, fcntl_flags_tbl);
4919 }
ffa65c3b
FB
4920 break;
4921
5f106811
APR
4922 case TARGET_F_SETFL:
4923 ret = get_errno(fcntl(fd, host_cmd, target_to_host_bitmask(arg, fcntl_flags_tbl)));
4924 break;
4925
8d5d3004
AS
4926#ifdef F_GETOWN_EX
4927 case TARGET_F_GETOWN_EX:
4928 ret = get_errno(fcntl(fd, host_cmd, &fox));
4929 if (ret >= 0) {
4930 if (!lock_user_struct(VERIFY_WRITE, target_fox, arg, 0))
4931 return -TARGET_EFAULT;
4932 target_fox->type = tswap32(fox.type);
4933 target_fox->pid = tswap32(fox.pid);
4934 unlock_user_struct(target_fox, arg, 1);
4935 }
4936 break;
4937#endif
4938
4939#ifdef F_SETOWN_EX
4940 case TARGET_F_SETOWN_EX:
4941 if (!lock_user_struct(VERIFY_READ, target_fox, arg, 1))
4942 return -TARGET_EFAULT;
4943 fox.type = tswap32(target_fox->type);
4944 fox.pid = tswap32(target_fox->pid);
4945 unlock_user_struct(target_fox, arg, 0);
4946 ret = get_errno(fcntl(fd, host_cmd, &fox));
4947 break;
4948#endif
4949
5f106811
APR
4950 case TARGET_F_SETOWN:
4951 case TARGET_F_GETOWN:
4952 case TARGET_F_SETSIG:
4953 case TARGET_F_GETSIG:
7e22e546
UH
4954 case TARGET_F_SETLEASE:
4955 case TARGET_F_GETLEASE:
5f106811 4956 ret = get_errno(fcntl(fd, host_cmd, arg));
ffa65c3b
FB
4957 break;
4958
7775e9ec 4959 default:
9ee1fa2c 4960 ret = get_errno(fcntl(fd, cmd, arg));
7775e9ec
FB
4961 break;
4962 }
4963 return ret;
4964}
4965
67867308 4966#ifdef USE_UID16
7775e9ec 4967
67867308
FB
4968static inline int high2lowuid(int uid)
4969{
4970 if (uid > 65535)
4971 return 65534;
4972 else
4973 return uid;
4974}
4975
4976static inline int high2lowgid(int gid)
4977{
4978 if (gid > 65535)
4979 return 65534;
4980 else
4981 return gid;
4982}
4983
4984static inline int low2highuid(int uid)
4985{
4986 if ((int16_t)uid == -1)
4987 return -1;
4988 else
4989 return uid;
4990}
4991
4992static inline int low2highgid(int gid)
4993{
4994 if ((int16_t)gid == -1)
4995 return -1;
4996 else
4997 return gid;
4998}
0c866a7e
RV
4999static inline int tswapid(int id)
5000{
5001 return tswap16(id);
5002}
76ca310a
PM
5003
5004#define put_user_id(x, gaddr) put_user_u16(x, gaddr)
5005
0c866a7e
RV
5006#else /* !USE_UID16 */
5007static inline int high2lowuid(int uid)
5008{
5009 return uid;
5010}
5011static inline int high2lowgid(int gid)
5012{
5013 return gid;
5014}
5015static inline int low2highuid(int uid)
5016{
5017 return uid;
5018}
5019static inline int low2highgid(int gid)
5020{
5021 return gid;
5022}
5023static inline int tswapid(int id)
5024{
5025 return tswap32(id);
5026}
76ca310a
PM
5027
5028#define put_user_id(x, gaddr) put_user_u32(x, gaddr)
5029
67867308 5030#endif /* USE_UID16 */
1b6b029e 5031
31e31b8a
FB
5032void syscall_init(void)
5033{
2ab83ea7
FB
5034 IOCTLEntry *ie;
5035 const argtype *arg_type;
5036 int size;
b92c47c1 5037 int i;
2ab83ea7 5038
8be656b8
AG
5039 thunk_init(STRUCT_MAX);
5040
001faf32 5041#define STRUCT(name, ...) thunk_register_struct(STRUCT_ ## name, #name, struct_ ## name ## _def);
5fafdf24 5042#define STRUCT_SPECIAL(name) thunk_register_struct_direct(STRUCT_ ## name, #name, &struct_ ## name ## _def);
31e31b8a
FB
5043#include "syscall_types.h"
5044#undef STRUCT
5045#undef STRUCT_SPECIAL
2ab83ea7 5046
dd6e957a
PM
5047 /* Build target_to_host_errno_table[] table from
5048 * host_to_target_errno_table[]. */
5049 for (i = 0; i < ERRNO_TABLE_SIZE; i++) {
5050 target_to_host_errno_table[host_to_target_errno_table[i]] = i;
5051 }
5052
2ab83ea7
FB
5053 /* we patch the ioctl size if necessary. We rely on the fact that
5054 no ioctl has all the bits at '1' in the size field */
5055 ie = ioctl_entries;
5056 while (ie->target_cmd != 0) {
5057 if (((ie->target_cmd >> TARGET_IOC_SIZESHIFT) & TARGET_IOC_SIZEMASK) ==
5058 TARGET_IOC_SIZEMASK) {
5059 arg_type = ie->arg_type;
5060 if (arg_type[0] != TYPE_PTR) {
5fafdf24 5061 fprintf(stderr, "cannot patch size for ioctl 0x%x\n",
2ab83ea7
FB
5062 ie->target_cmd);
5063 exit(1);
5064 }
5065 arg_type++;
5066 size = thunk_type_size(arg_type, 0);
5fafdf24 5067 ie->target_cmd = (ie->target_cmd &
2ab83ea7
FB
5068 ~(TARGET_IOC_SIZEMASK << TARGET_IOC_SIZESHIFT)) |
5069 (size << TARGET_IOC_SIZESHIFT);
5070 }
b92c47c1 5071
2ab83ea7 5072 /* automatic consistency check if same arch */
872ea0c0
AZ
5073#if (defined(__i386__) && defined(TARGET_I386) && defined(TARGET_ABI32)) || \
5074 (defined(__x86_64__) && defined(TARGET_X86_64))
5075 if (unlikely(ie->target_cmd != ie->host_cmd)) {
5076 fprintf(stderr, "ERROR: ioctl(%s): target=0x%x host=0x%x\n",
5077 ie->name, ie->target_cmd, ie->host_cmd);
2ab83ea7
FB
5078 }
5079#endif
5080 ie++;
5081 }
31e31b8a 5082}
c573ff67 5083
992f48a0 5084#if TARGET_ABI_BITS == 32
ce4defa0
PB
5085static inline uint64_t target_offset64(uint32_t word0, uint32_t word1)
5086{
af325d36 5087#ifdef TARGET_WORDS_BIGENDIAN
ce4defa0
PB
5088 return ((uint64_t)word0 << 32) | word1;
5089#else
5090 return ((uint64_t)word1 << 32) | word0;
5091#endif
5092}
992f48a0 5093#else /* TARGET_ABI_BITS == 32 */
32407103
JM
5094static inline uint64_t target_offset64(uint64_t word0, uint64_t word1)
5095{
5096 return word0;
5097}
992f48a0 5098#endif /* TARGET_ABI_BITS != 32 */
ce4defa0
PB
5099
5100#ifdef TARGET_NR_truncate64
992f48a0
BS
5101static inline abi_long target_truncate64(void *cpu_env, const char *arg1,
5102 abi_long arg2,
5103 abi_long arg3,
5104 abi_long arg4)
ce4defa0 5105{
48e515d4 5106 if (regpairs_aligned(cpu_env)) {
ce4defa0
PB
5107 arg2 = arg3;
5108 arg3 = arg4;
48e515d4 5109 }
ce4defa0
PB
5110 return get_errno(truncate64(arg1, target_offset64(arg2, arg3)));
5111}
5112#endif
5113
5114#ifdef TARGET_NR_ftruncate64
992f48a0
BS
5115static inline abi_long target_ftruncate64(void *cpu_env, abi_long arg1,
5116 abi_long arg2,
5117 abi_long arg3,
5118 abi_long arg4)
ce4defa0 5119{
48e515d4 5120 if (regpairs_aligned(cpu_env)) {
ce4defa0
PB
5121 arg2 = arg3;
5122 arg3 = arg4;
48e515d4 5123 }
ce4defa0
PB
5124 return get_errno(ftruncate64(arg1, target_offset64(arg2, arg3)));
5125}
5126#endif
5127
579a97f7
FB
5128static inline abi_long target_to_host_timespec(struct timespec *host_ts,
5129 abi_ulong target_addr)
53a5960a
PB
5130{
5131 struct target_timespec *target_ts;
5132
579a97f7
FB
5133 if (!lock_user_struct(VERIFY_READ, target_ts, target_addr, 1))
5134 return -TARGET_EFAULT;
cbb21eed
MB
5135 host_ts->tv_sec = tswapal(target_ts->tv_sec);
5136 host_ts->tv_nsec = tswapal(target_ts->tv_nsec);
53a5960a 5137 unlock_user_struct(target_ts, target_addr, 0);
b255bfa8 5138 return 0;
53a5960a
PB
5139}
5140
579a97f7
FB
5141static inline abi_long host_to_target_timespec(abi_ulong target_addr,
5142 struct timespec *host_ts)
53a5960a
PB
5143{
5144 struct target_timespec *target_ts;
5145
579a97f7
FB
5146 if (!lock_user_struct(VERIFY_WRITE, target_ts, target_addr, 0))
5147 return -TARGET_EFAULT;
cbb21eed
MB
5148 target_ts->tv_sec = tswapal(host_ts->tv_sec);
5149 target_ts->tv_nsec = tswapal(host_ts->tv_nsec);
53a5960a 5150 unlock_user_struct(target_ts, target_addr, 1);
b255bfa8 5151 return 0;
53a5960a
PB
5152}
5153
f4f1e10a
ECL
5154static inline abi_long target_to_host_itimerspec(struct itimerspec *host_itspec,
5155 abi_ulong target_addr)
5156{
5157 struct target_itimerspec *target_itspec;
5158
5159 if (!lock_user_struct(VERIFY_READ, target_itspec, target_addr, 1)) {
5160 return -TARGET_EFAULT;
5161 }
5162
5163 host_itspec->it_interval.tv_sec =
5164 tswapal(target_itspec->it_interval.tv_sec);
5165 host_itspec->it_interval.tv_nsec =
5166 tswapal(target_itspec->it_interval.tv_nsec);
5167 host_itspec->it_value.tv_sec = tswapal(target_itspec->it_value.tv_sec);
5168 host_itspec->it_value.tv_nsec = tswapal(target_itspec->it_value.tv_nsec);
5169
5170 unlock_user_struct(target_itspec, target_addr, 1);
5171 return 0;
5172}
5173
5174static inline abi_long host_to_target_itimerspec(abi_ulong target_addr,
5175 struct itimerspec *host_its)
5176{
5177 struct target_itimerspec *target_itspec;
5178
5179 if (!lock_user_struct(VERIFY_WRITE, target_itspec, target_addr, 0)) {
5180 return -TARGET_EFAULT;
5181 }
5182
5183 target_itspec->it_interval.tv_sec = tswapal(host_its->it_interval.tv_sec);
5184 target_itspec->it_interval.tv_nsec = tswapal(host_its->it_interval.tv_nsec);
5185
5186 target_itspec->it_value.tv_sec = tswapal(host_its->it_value.tv_sec);
5187 target_itspec->it_value.tv_nsec = tswapal(host_its->it_value.tv_nsec);
5188
5189 unlock_user_struct(target_itspec, target_addr, 0);
5190 return 0;
5191}
5192
c065976f
PM
5193static inline abi_long target_to_host_sigevent(struct sigevent *host_sevp,
5194 abi_ulong target_addr)
5195{
5196 struct target_sigevent *target_sevp;
5197
5198 if (!lock_user_struct(VERIFY_READ, target_sevp, target_addr, 1)) {
5199 return -TARGET_EFAULT;
5200 }
5201
5202 /* This union is awkward on 64 bit systems because it has a 32 bit
5203 * integer and a pointer in it; we follow the conversion approach
5204 * used for handling sigval types in signal.c so the guest should get
5205 * the correct value back even if we did a 64 bit byteswap and it's
5206 * using the 32 bit integer.
5207 */
5208 host_sevp->sigev_value.sival_ptr =
5209 (void *)(uintptr_t)tswapal(target_sevp->sigev_value.sival_ptr);
5210 host_sevp->sigev_signo =
5211 target_to_host_signal(tswap32(target_sevp->sigev_signo));
5212 host_sevp->sigev_notify = tswap32(target_sevp->sigev_notify);
5213 host_sevp->_sigev_un._tid = tswap32(target_sevp->_sigev_un._tid);
5214
5215 unlock_user_struct(target_sevp, target_addr, 1);
5216 return 0;
5217}
5218
6f6a4032
TM
5219#if defined(TARGET_NR_mlockall)
5220static inline int target_to_host_mlockall_arg(int arg)
5221{
5222 int result = 0;
5223
5224 if (arg & TARGET_MLOCKALL_MCL_CURRENT) {
5225 result |= MCL_CURRENT;
5226 }
5227 if (arg & TARGET_MLOCKALL_MCL_FUTURE) {
5228 result |= MCL_FUTURE;
5229 }
5230 return result;
5231}
5232#endif
5233
6a24a778
AZ
5234static inline abi_long host_to_target_stat64(void *cpu_env,
5235 abi_ulong target_addr,
5236 struct stat *host_st)
5237{
09701199 5238#if defined(TARGET_ARM) && defined(TARGET_ABI32)
6a24a778
AZ
5239 if (((CPUARMState *)cpu_env)->eabi) {
5240 struct target_eabi_stat64 *target_st;
5241
5242 if (!lock_user_struct(VERIFY_WRITE, target_st, target_addr, 0))
5243 return -TARGET_EFAULT;
5244 memset(target_st, 0, sizeof(struct target_eabi_stat64));
5245 __put_user(host_st->st_dev, &target_st->st_dev);
5246 __put_user(host_st->st_ino, &target_st->st_ino);
5247#ifdef TARGET_STAT64_HAS_BROKEN_ST_INO
5248 __put_user(host_st->st_ino, &target_st->__st_ino);
5249#endif
5250 __put_user(host_st->st_mode, &target_st->st_mode);
5251 __put_user(host_st->st_nlink, &target_st->st_nlink);
5252 __put_user(host_st->st_uid, &target_st->st_uid);
5253 __put_user(host_st->st_gid, &target_st->st_gid);
5254 __put_user(host_st->st_rdev, &target_st->st_rdev);
5255 __put_user(host_st->st_size, &target_st->st_size);
5256 __put_user(host_st->st_blksize, &target_st->st_blksize);
5257 __put_user(host_st->st_blocks, &target_st->st_blocks);
5258 __put_user(host_st->st_atime, &target_st->target_st_atime);
5259 __put_user(host_st->st_mtime, &target_st->target_st_mtime);
5260 __put_user(host_st->st_ctime, &target_st->target_st_ctime);
5261 unlock_user_struct(target_st, target_addr, 1);
5262 } else
5263#endif
5264 {
20d155bc 5265#if defined(TARGET_HAS_STRUCT_STAT64)
6a24a778 5266 struct target_stat64 *target_st;
20d155bc
SW
5267#else
5268 struct target_stat *target_st;
9d33b76b 5269#endif
6a24a778
AZ
5270
5271 if (!lock_user_struct(VERIFY_WRITE, target_st, target_addr, 0))
5272 return -TARGET_EFAULT;
9d33b76b 5273 memset(target_st, 0, sizeof(*target_st));
6a24a778
AZ
5274 __put_user(host_st->st_dev, &target_st->st_dev);
5275 __put_user(host_st->st_ino, &target_st->st_ino);
5276#ifdef TARGET_STAT64_HAS_BROKEN_ST_INO
5277 __put_user(host_st->st_ino, &target_st->__st_ino);
5278#endif
5279 __put_user(host_st->st_mode, &target_st->st_mode);
5280 __put_user(host_st->st_nlink, &target_st->st_nlink);
5281 __put_user(host_st->st_uid, &target_st->st_uid);
5282 __put_user(host_st->st_gid, &target_st->st_gid);
5283 __put_user(host_st->st_rdev, &target_st->st_rdev);
5284 /* XXX: better use of kernel struct */
5285 __put_user(host_st->st_size, &target_st->st_size);
5286 __put_user(host_st->st_blksize, &target_st->st_blksize);
5287 __put_user(host_st->st_blocks, &target_st->st_blocks);
5288 __put_user(host_st->st_atime, &target_st->target_st_atime);
5289 __put_user(host_st->st_mtime, &target_st->target_st_mtime);
5290 __put_user(host_st->st_ctime, &target_st->target_st_ctime);
5291 unlock_user_struct(target_st, target_addr, 1);
5292 }
5293
5294 return 0;
5295}
6a24a778 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}