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