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