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