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