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