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