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