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