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