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