]> git.proxmox.com Git - mirror_qemu.git/blame - linux-user/syscall.c
linux-user: Added IP_(UN)BLOCK_SOURCE/IP_(ADD|DROP)_SOURCE_MEMBERSHIP flags to setsockopt
[mirror_qemu.git] / linux-user / syscall.c
CommitLineData
31e31b8a
FB
1/*
2 * Linux syscalls
5fafdf24 3 *
31e31b8a
FB
4 * Copyright (c) 2003 Fabrice Bellard
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
530e7615
BS
18 * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
19 * MA 02110-1301, USA.
31e31b8a
FB
20 */
21#include <stdlib.h>
22#include <stdio.h>
23#include <stdarg.h>
04369ff2 24#include <string.h>
31e31b8a
FB
25#include <elf.h>
26#include <endian.h>
27#include <errno.h>
28#include <unistd.h>
29#include <fcntl.h>
7854b056 30#include <time.h>
82e671d9 31#include <limits.h>
24e1003a 32#include <mqueue.h>
31e31b8a 33#include <sys/types.h>
d08d3bb8
TS
34#include <sys/ipc.h>
35#include <sys/msg.h>
31e31b8a
FB
36#include <sys/wait.h>
37#include <sys/time.h>
38#include <sys/stat.h>
39#include <sys/mount.h>
39b9aae1 40#include <sys/prctl.h>
31e31b8a
FB
41#include <sys/resource.h>
42#include <sys/mman.h>
43#include <sys/swap.h>
44#include <signal.h>
45#include <sched.h>
46#include <sys/socket.h>
607175e0 47#include <sys/un.h>
31e31b8a 48#include <sys/uio.h>
9de5e440 49#include <sys/poll.h>
32f36bce 50#include <sys/times.h>
8853f86e 51#include <sys/shm.h>
fa294816 52#include <sys/sem.h>
56c8f68f 53#include <sys/statfs.h>
ebc05488 54#include <utime.h>
a5448a7d 55#include <sys/sysinfo.h>
3b3f24ad 56#include <sys/utsname.h>
72f03900 57//#include <sys/user.h>
8853f86e 58#include <netinet/ip.h>
7854b056 59#include <netinet/tcp.h>
0b6d3ae0 60#include <qemu-common.h>
6d946cda
AJ
61#ifdef HAVE_GPROF
62#include <sys/gmon.h>
63#endif
31e31b8a
FB
64
65#define termios host_termios
66#define winsize host_winsize
67#define termio host_termio
04369ff2
FB
68#define sgttyb host_sgttyb /* same as target */
69#define tchars host_tchars /* same as target */
70#define ltchars host_ltchars /* same as target */
31e31b8a
FB
71
72#include <linux/termios.h>
73#include <linux/unistd.h>
74#include <linux/utsname.h>
75#include <linux/cdrom.h>
76#include <linux/hdreg.h>
77#include <linux/soundcard.h>
19b84f3c 78#include <linux/kd.h>
8fbd6b52 79#include <linux/mtio.h>
d7e4036e 80#include "linux_loop.h"
31e31b8a 81
3ef693a0 82#include "qemu.h"
526ccb7a 83#include "qemu-common.h"
31e31b8a 84
30813cea
PB
85#if defined(USE_NPTL)
86#include <linux/futex.h>
d865bab5
PB
87#define CLONE_NPTL_FLAGS2 (CLONE_SETTLS | \
88 CLONE_PARENT_SETTID | CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID)
89#else
90/* XXX: Hardcode the above values. */
91#define CLONE_NPTL_FLAGS2 0
30813cea
PB
92#endif
93
72f03900 94//#define DEBUG
31e31b8a 95
1a9353d2 96//#include <linux/msdos_fs.h>
6556a833
AJ
97#define VFAT_IOCTL_READDIR_BOTH _IOR('r', 1, struct linux_dirent [2])
98#define VFAT_IOCTL_READDIR_SHORT _IOR('r', 2, struct linux_dirent [2])
1a9353d2 99
70a194b9 100
70a194b9
FB
101#undef _syscall0
102#undef _syscall1
103#undef _syscall2
104#undef _syscall3
105#undef _syscall4
106#undef _syscall5
83fcb515 107#undef _syscall6
70a194b9 108
83fcb515 109#define _syscall0(type,name) \
8fcd3692 110static type name (void) \
83fcb515
FB
111{ \
112 return syscall(__NR_##name); \
113}
70a194b9 114
83fcb515 115#define _syscall1(type,name,type1,arg1) \
8fcd3692 116static type name (type1 arg1) \
83fcb515
FB
117{ \
118 return syscall(__NR_##name, arg1); \
70a194b9
FB
119}
120
83fcb515 121#define _syscall2(type,name,type1,arg1,type2,arg2) \
8fcd3692 122static type name (type1 arg1,type2 arg2) \
83fcb515
FB
123{ \
124 return syscall(__NR_##name, arg1, arg2); \
70a194b9
FB
125}
126
83fcb515 127#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \
8fcd3692 128static type name (type1 arg1,type2 arg2,type3 arg3) \
83fcb515
FB
129{ \
130 return syscall(__NR_##name, arg1, arg2, arg3); \
70a194b9
FB
131}
132
83fcb515 133#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \
8fcd3692 134static type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4) \
83fcb515
FB
135{ \
136 return syscall(__NR_##name, arg1, arg2, arg3, arg4); \
70a194b9
FB
137}
138
83fcb515
FB
139#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
140 type5,arg5) \
8fcd3692 141static type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \
83fcb515
FB
142{ \
143 return syscall(__NR_##name, arg1, arg2, arg3, arg4, arg5); \
70a194b9
FB
144}
145
83fcb515
FB
146
147#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
148 type5,arg5,type6,arg6) \
8fcd3692
BS
149static type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5, \
150 type6 arg6) \
83fcb515
FB
151{ \
152 return syscall(__NR_##name, arg1, arg2, arg3, arg4, arg5, arg6); \
70a194b9 153}
83fcb515 154
70a194b9 155
31e31b8a 156#define __NR_sys_uname __NR_uname
92a34c10 157#define __NR_sys_faccessat __NR_faccessat
814d7977 158#define __NR_sys_fchmodat __NR_fchmodat
ccfa72b7 159#define __NR_sys_fchownat __NR_fchownat
6a24a778 160#define __NR_sys_fstatat64 __NR_fstatat64
ac8a6556 161#define __NR_sys_futimesat __NR_futimesat
72f03900 162#define __NR_sys_getcwd1 __NR_getcwd
72f03900 163#define __NR_sys_getdents __NR_getdents
dab2ed99 164#define __NR_sys_getdents64 __NR_getdents64
c6cda17a 165#define __NR_sys_getpriority __NR_getpriority
64f0ce4c 166#define __NR_sys_linkat __NR_linkat
4472ad0d 167#define __NR_sys_mkdirat __NR_mkdirat
75ac37a0 168#define __NR_sys_mknodat __NR_mknodat
9d33b76b 169#define __NR_sys_newfstatat __NR_newfstatat
82424832 170#define __NR_sys_openat __NR_openat
5e0ccb18 171#define __NR_sys_readlinkat __NR_readlinkat
722183f6 172#define __NR_sys_renameat __NR_renameat
66fb9763 173#define __NR_sys_rt_sigqueueinfo __NR_rt_sigqueueinfo
f0b6243d 174#define __NR_sys_symlinkat __NR_symlinkat
7494b0f9 175#define __NR_sys_syslog __NR_syslog
71455574 176#define __NR_sys_tgkill __NR_tgkill
4cae1d16 177#define __NR_sys_tkill __NR_tkill
8170f56b 178#define __NR_sys_unlinkat __NR_unlinkat
9007f0ef 179#define __NR_sys_utimensat __NR_utimensat
bd0c5661 180#define __NR_sys_futex __NR_futex
39b59763
AJ
181#define __NR_sys_inotify_init __NR_inotify_init
182#define __NR_sys_inotify_add_watch __NR_inotify_add_watch
183#define __NR_sys_inotify_rm_watch __NR_inotify_rm_watch
31e31b8a 184
bc51c5c9 185#if defined(__alpha__) || defined (__ia64__) || defined(__x86_64__)
9af9eaaa
FB
186#define __NR__llseek __NR_lseek
187#endif
188
72f03900 189#ifdef __NR_gettid
31e31b8a 190_syscall0(int, gettid)
72f03900 191#else
0da46a6e
TS
192/* This is a replacement for the host gettid() and must return a host
193 errno. */
72f03900
FB
194static int gettid(void) {
195 return -ENOSYS;
196}
197#endif
3b3f24ad
AJ
198#if TARGET_ABI_BITS == 32
199_syscall3(int, sys_getdents, uint, fd, struct linux_dirent *, dirp, uint, count);
200#endif
201#if defined(TARGET_NR_getdents64) && defined(__NR_getdents64)
202_syscall3(int, sys_getdents64, uint, fd, struct linux_dirent64 *, dirp, uint, count);
203#endif
204_syscall2(int, sys_getpriority, int, which, int, who);
909b69cf 205#if defined(TARGET_NR__llseek) && !defined (__x86_64__)
3b3f24ad
AJ
206_syscall5(int, _llseek, uint, fd, ulong, hi, ulong, lo,
207 loff_t *, res, uint, wh);
208#endif
209_syscall3(int,sys_rt_sigqueueinfo,int,pid,int,sig,siginfo_t *,uinfo)
210_syscall3(int,sys_syslog,int,type,char*,bufp,int,len)
211#if defined(TARGET_NR_tgkill) && defined(__NR_tgkill)
212_syscall3(int,sys_tgkill,int,tgid,int,pid,int,sig)
213#endif
214#if defined(TARGET_NR_tkill) && defined(__NR_tkill)
215_syscall2(int,sys_tkill,int,tid,int,sig)
216#endif
217#ifdef __NR_exit_group
218_syscall1(int,exit_group,int,error_code)
219#endif
220#if defined(TARGET_NR_set_tid_address) && defined(__NR_set_tid_address)
221_syscall1(int,set_tid_address,int *,tidptr)
222#endif
223#if defined(USE_NPTL)
224#if defined(TARGET_NR_futex) && defined(__NR_futex)
225_syscall6(int,sys_futex,int *,uaddr,int,op,int,val,
226 const struct timespec *,timeout,int *,uaddr2,int,val3)
227#endif
228#endif
229
230static bitmask_transtbl fcntl_flags_tbl[] = {
231 { TARGET_O_ACCMODE, TARGET_O_WRONLY, O_ACCMODE, O_WRONLY, },
232 { TARGET_O_ACCMODE, TARGET_O_RDWR, O_ACCMODE, O_RDWR, },
233 { TARGET_O_CREAT, TARGET_O_CREAT, O_CREAT, O_CREAT, },
234 { TARGET_O_EXCL, TARGET_O_EXCL, O_EXCL, O_EXCL, },
235 { TARGET_O_NOCTTY, TARGET_O_NOCTTY, O_NOCTTY, O_NOCTTY, },
236 { TARGET_O_TRUNC, TARGET_O_TRUNC, O_TRUNC, O_TRUNC, },
237 { TARGET_O_APPEND, TARGET_O_APPEND, O_APPEND, O_APPEND, },
238 { TARGET_O_NONBLOCK, TARGET_O_NONBLOCK, O_NONBLOCK, O_NONBLOCK, },
239 { TARGET_O_SYNC, TARGET_O_SYNC, O_SYNC, O_SYNC, },
240 { TARGET_FASYNC, TARGET_FASYNC, FASYNC, FASYNC, },
241 { TARGET_O_DIRECTORY, TARGET_O_DIRECTORY, O_DIRECTORY, O_DIRECTORY, },
242 { TARGET_O_NOFOLLOW, TARGET_O_NOFOLLOW, O_NOFOLLOW, O_NOFOLLOW, },
243 { TARGET_O_LARGEFILE, TARGET_O_LARGEFILE, O_LARGEFILE, O_LARGEFILE, },
244#if defined(O_DIRECT)
245 { TARGET_O_DIRECT, TARGET_O_DIRECT, O_DIRECT, O_DIRECT, },
246#endif
247 { 0, 0, 0, 0 }
248};
249
250#define COPY_UTSNAME_FIELD(dest, src) \
251 do { \
252 /* __NEW_UTS_LEN doesn't include terminating null */ \
253 (void) strncpy((dest), (src), __NEW_UTS_LEN); \
254 (dest)[__NEW_UTS_LEN] = '\0'; \
255 } while (0)
256
257static int sys_uname(struct new_utsname *buf)
258{
259 struct utsname uts_buf;
260
261 if (uname(&uts_buf) < 0)
262 return (-1);
263
264 /*
265 * Just in case these have some differences, we
266 * translate utsname to new_utsname (which is the
267 * struct linux kernel uses).
268 */
269
270 bzero(buf, sizeof (*buf));
271 COPY_UTSNAME_FIELD(buf->sysname, uts_buf.sysname);
272 COPY_UTSNAME_FIELD(buf->nodename, uts_buf.nodename);
273 COPY_UTSNAME_FIELD(buf->release, uts_buf.release);
274 COPY_UTSNAME_FIELD(buf->version, uts_buf.version);
275 COPY_UTSNAME_FIELD(buf->machine, uts_buf.machine);
276#ifdef _GNU_SOURCE
277 COPY_UTSNAME_FIELD(buf->domainname, uts_buf.domainname);
278#endif
279 return (0);
280
281#undef COPY_UTSNAME_FIELD
282}
283
284static int sys_getcwd1(char *buf, size_t size)
285{
286 if (getcwd(buf, size) == NULL) {
287 /* getcwd() sets errno */
288 return (-1);
289 }
aaf4ad39 290 return strlen(buf)+1;
3b3f24ad
AJ
291}
292
293#ifdef CONFIG_ATFILE
294/*
295 * Host system seems to have atfile syscall stubs available. We
296 * now enable them one by one as specified by target syscall_nr.h.
297 */
298
299#ifdef TARGET_NR_faccessat
465c9f06 300static int sys_faccessat(int dirfd, const char *pathname, int mode)
3b3f24ad 301{
465c9f06 302 return (faccessat(dirfd, pathname, mode, 0));
3b3f24ad
AJ
303}
304#endif
305#ifdef TARGET_NR_fchmodat
465c9f06 306static int sys_fchmodat(int dirfd, const char *pathname, mode_t mode)
3b3f24ad 307{
465c9f06 308 return (fchmodat(dirfd, pathname, mode, 0));
3b3f24ad
AJ
309}
310#endif
fda33744 311#if defined(TARGET_NR_fchownat) && defined(USE_UID16)
3b3f24ad
AJ
312static int sys_fchownat(int dirfd, const char *pathname, uid_t owner,
313 gid_t group, int flags)
314{
315 return (fchownat(dirfd, pathname, owner, group, flags));
316}
317#endif
318#ifdef __NR_fstatat64
319static int sys_fstatat64(int dirfd, const char *pathname, struct stat *buf,
320 int flags)
321{
322 return (fstatat(dirfd, pathname, buf, flags));
323}
324#endif
325#ifdef __NR_newfstatat
326static int sys_newfstatat(int dirfd, const char *pathname, struct stat *buf,
327 int flags)
328{
329 return (fstatat(dirfd, pathname, buf, flags));
330}
331#endif
332#ifdef TARGET_NR_futimesat
333static int sys_futimesat(int dirfd, const char *pathname,
334 const struct timeval times[2])
335{
336 return (futimesat(dirfd, pathname, times));
337}
338#endif
339#ifdef TARGET_NR_linkat
340static int sys_linkat(int olddirfd, const char *oldpath,
341 int newdirfd, const char *newpath, int flags)
342{
343 return (linkat(olddirfd, oldpath, newdirfd, newpath, flags));
344}
345#endif
346#ifdef TARGET_NR_mkdirat
347static int sys_mkdirat(int dirfd, const char *pathname, mode_t mode)
348{
349 return (mkdirat(dirfd, pathname, mode));
350}
351#endif
352#ifdef TARGET_NR_mknodat
353static int sys_mknodat(int dirfd, const char *pathname, mode_t mode,
354 dev_t dev)
355{
356 return (mknodat(dirfd, pathname, mode, dev));
357}
358#endif
359#ifdef TARGET_NR_openat
360static int sys_openat(int dirfd, const char *pathname, int flags, ...)
361{
362 /*
363 * open(2) has extra parameter 'mode' when called with
364 * flag O_CREAT.
365 */
366 if ((flags & O_CREAT) != 0) {
367 va_list ap;
368 mode_t mode;
369
370 /*
371 * Get the 'mode' parameter and translate it to
372 * host bits.
373 */
374 va_start(ap, flags);
375 mode = va_arg(ap, mode_t);
376 mode = target_to_host_bitmask(mode, fcntl_flags_tbl);
377 va_end(ap);
378
379 return (openat(dirfd, pathname, flags, mode));
380 }
381 return (openat(dirfd, pathname, flags));
382}
383#endif
384#ifdef TARGET_NR_readlinkat
385static int sys_readlinkat(int dirfd, const char *pathname, char *buf, size_t bufsiz)
386{
387 return (readlinkat(dirfd, pathname, buf, bufsiz));
388}
389#endif
390#ifdef TARGET_NR_renameat
391static int sys_renameat(int olddirfd, const char *oldpath,
392 int newdirfd, const char *newpath)
393{
394 return (renameat(olddirfd, oldpath, newdirfd, newpath));
395}
396#endif
397#ifdef TARGET_NR_symlinkat
398static int sys_symlinkat(const char *oldpath, int newdirfd, const char *newpath)
399{
400 return (symlinkat(oldpath, newdirfd, newpath));
401}
402#endif
403#ifdef TARGET_NR_unlinkat
404static int sys_unlinkat(int dirfd, const char *pathname, int flags)
405{
406 return (unlinkat(dirfd, pathname, flags));
407}
408#endif
3b3f24ad
AJ
409#else /* !CONFIG_ATFILE */
410
411/*
412 * Try direct syscalls instead
413 */
92a34c10 414#if defined(TARGET_NR_faccessat) && defined(__NR_faccessat)
465c9f06 415_syscall3(int,sys_faccessat,int,dirfd,const char *,pathname,int,mode)
92a34c10 416#endif
814d7977 417#if defined(TARGET_NR_fchmodat) && defined(__NR_fchmodat)
465c9f06 418_syscall3(int,sys_fchmodat,int,dirfd,const char *,pathname, mode_t,mode)
814d7977 419#endif
4583f589 420#if defined(TARGET_NR_fchownat) && defined(__NR_fchownat) && defined(USE_UID16)
ccfa72b7
TS
421_syscall5(int,sys_fchownat,int,dirfd,const char *,pathname,
422 uid_t,owner,gid_t,group,int,flags)
423#endif
9d33b76b
AJ
424#if (defined(TARGET_NR_fstatat64) || defined(TARGET_NR_newfstatat)) && \
425 defined(__NR_fstatat64)
6a24a778
AZ
426_syscall4(int,sys_fstatat64,int,dirfd,const char *,pathname,
427 struct stat *,buf,int,flags)
428#endif
ac8a6556
AZ
429#if defined(TARGET_NR_futimesat) && defined(__NR_futimesat)
430_syscall3(int,sys_futimesat,int,dirfd,const char *,pathname,
431 const struct timeval *,times)
432#endif
3b3f24ad
AJ
433#if (defined(TARGET_NR_newfstatat) || defined(TARGET_NR_fstatat64) ) && \
434 defined(__NR_newfstatat)
435_syscall4(int,sys_newfstatat,int,dirfd,const char *,pathname,
436 struct stat *,buf,int,flags)
8fcd3692 437#endif
64f0ce4c
TS
438#if defined(TARGET_NR_linkat) && defined(__NR_linkat)
439_syscall5(int,sys_linkat,int,olddirfd,const char *,oldpath,
3b3f24ad 440 int,newdirfd,const char *,newpath,int,flags)
64f0ce4c 441#endif
4472ad0d
TS
442#if defined(TARGET_NR_mkdirat) && defined(__NR_mkdirat)
443_syscall3(int,sys_mkdirat,int,dirfd,const char *,pathname,mode_t,mode)
444#endif
75ac37a0
TS
445#if defined(TARGET_NR_mknodat) && defined(__NR_mknodat)
446_syscall4(int,sys_mknodat,int,dirfd,const char *,pathname,
447 mode_t,mode,dev_t,dev)
448#endif
82424832
TS
449#if defined(TARGET_NR_openat) && defined(__NR_openat)
450_syscall4(int,sys_openat,int,dirfd,const char *,pathname,int,flags,mode_t,mode)
451#endif
5e0ccb18
TS
452#if defined(TARGET_NR_readlinkat) && defined(__NR_readlinkat)
453_syscall4(int,sys_readlinkat,int,dirfd,const char *,pathname,
454 char *,buf,size_t,bufsize)
455#endif
722183f6
TS
456#if defined(TARGET_NR_renameat) && defined(__NR_renameat)
457_syscall4(int,sys_renameat,int,olddirfd,const char *,oldpath,
458 int,newdirfd,const char *,newpath)
459#endif
b51eaa82 460#if defined(TARGET_NR_symlinkat) && defined(__NR_symlinkat)
f0b6243d
TS
461_syscall3(int,sys_symlinkat,const char *,oldpath,
462 int,newdirfd,const char *,newpath)
463#endif
8170f56b
TS
464#if defined(TARGET_NR_unlinkat) && defined(__NR_unlinkat)
465_syscall3(int,sys_unlinkat,int,dirfd,const char *,pathname,int,flags)
466#endif
ebc996f3
RV
467
468#endif /* CONFIG_ATFILE */
469
470#ifdef CONFIG_UTIMENSAT
471static int sys_utimensat(int dirfd, const char *pathname,
472 const struct timespec times[2], int flags)
473{
474 if (pathname == NULL)
475 return futimens(dirfd, times);
476 else
477 return utimensat(dirfd, pathname, times, flags);
478}
479#else
9007f0ef
TS
480#if defined(TARGET_NR_utimensat) && defined(__NR_utimensat)
481_syscall4(int,sys_utimensat,int,dirfd,const char *,pathname,
482 const struct timespec *,tsp,int,flags)
483#endif
ebc996f3 484#endif /* CONFIG_UTIMENSAT */
3b3f24ad
AJ
485
486#ifdef CONFIG_INOTIFY
8690e420 487#include <sys/inotify.h>
3b3f24ad 488
39b59763 489#if defined(TARGET_NR_inotify_init) && defined(__NR_inotify_init)
3b3f24ad
AJ
490static int sys_inotify_init(void)
491{
492 return (inotify_init());
493}
39b59763
AJ
494#endif
495#if defined(TARGET_NR_inotify_add_watch) && defined(__NR_inotify_add_watch)
3b3f24ad
AJ
496static int sys_inotify_add_watch(int fd,const char *pathname, int32_t mask)
497{
498 return (inotify_add_watch(fd, pathname, mask));
499}
39b59763
AJ
500#endif
501#if defined(TARGET_NR_inotify_rm_watch) && defined(__NR_inotify_rm_watch)
3b3f24ad
AJ
502static int sys_inotify_rm_watch(int fd, int32_t wd)
503{
8690e420 504 return (inotify_rm_watch(fd, wd));
3b3f24ad 505}
bd0c5661 506#endif
3b3f24ad
AJ
507#else
508/* Userspace can usually survive runtime without inotify */
509#undef TARGET_NR_inotify_init
510#undef TARGET_NR_inotify_add_watch
511#undef TARGET_NR_inotify_rm_watch
512#endif /* CONFIG_INOTIFY */
513
66fb9763
FB
514
515extern int personality(int);
9de5e440
FB
516extern int flock(int, int);
517extern int setfsuid(int);
518extern int setfsgid(int);
19b84f3c 519extern int setgroups(int, gid_t *);
31e31b8a 520
b92c47c1
TS
521#define ERRNO_TABLE_SIZE 1200
522
523/* target_to_host_errno_table[] is initialized from
524 * host_to_target_errno_table[] in syscall_init(). */
525static uint16_t target_to_host_errno_table[ERRNO_TABLE_SIZE] = {
526};
527
637947f1 528/*
fe8f096b 529 * This list is the union of errno values overridden in asm-<arch>/errno.h
637947f1
TS
530 * minus the errnos that are not actually generic to all archs.
531 */
b92c47c1 532static uint16_t host_to_target_errno_table[ERRNO_TABLE_SIZE] = {
637947f1
TS
533 [EIDRM] = TARGET_EIDRM,
534 [ECHRNG] = TARGET_ECHRNG,
535 [EL2NSYNC] = TARGET_EL2NSYNC,
536 [EL3HLT] = TARGET_EL3HLT,
537 [EL3RST] = TARGET_EL3RST,
538 [ELNRNG] = TARGET_ELNRNG,
539 [EUNATCH] = TARGET_EUNATCH,
540 [ENOCSI] = TARGET_ENOCSI,
541 [EL2HLT] = TARGET_EL2HLT,
542 [EDEADLK] = TARGET_EDEADLK,
543 [ENOLCK] = TARGET_ENOLCK,
544 [EBADE] = TARGET_EBADE,
545 [EBADR] = TARGET_EBADR,
546 [EXFULL] = TARGET_EXFULL,
547 [ENOANO] = TARGET_ENOANO,
548 [EBADRQC] = TARGET_EBADRQC,
549 [EBADSLT] = TARGET_EBADSLT,
550 [EBFONT] = TARGET_EBFONT,
551 [ENOSTR] = TARGET_ENOSTR,
552 [ENODATA] = TARGET_ENODATA,
553 [ETIME] = TARGET_ETIME,
554 [ENOSR] = TARGET_ENOSR,
555 [ENONET] = TARGET_ENONET,
556 [ENOPKG] = TARGET_ENOPKG,
557 [EREMOTE] = TARGET_EREMOTE,
558 [ENOLINK] = TARGET_ENOLINK,
559 [EADV] = TARGET_EADV,
560 [ESRMNT] = TARGET_ESRMNT,
561 [ECOMM] = TARGET_ECOMM,
562 [EPROTO] = TARGET_EPROTO,
563 [EDOTDOT] = TARGET_EDOTDOT,
564 [EMULTIHOP] = TARGET_EMULTIHOP,
565 [EBADMSG] = TARGET_EBADMSG,
566 [ENAMETOOLONG] = TARGET_ENAMETOOLONG,
567 [EOVERFLOW] = TARGET_EOVERFLOW,
568 [ENOTUNIQ] = TARGET_ENOTUNIQ,
569 [EBADFD] = TARGET_EBADFD,
570 [EREMCHG] = TARGET_EREMCHG,
571 [ELIBACC] = TARGET_ELIBACC,
572 [ELIBBAD] = TARGET_ELIBBAD,
573 [ELIBSCN] = TARGET_ELIBSCN,
574 [ELIBMAX] = TARGET_ELIBMAX,
575 [ELIBEXEC] = TARGET_ELIBEXEC,
576 [EILSEQ] = TARGET_EILSEQ,
577 [ENOSYS] = TARGET_ENOSYS,
578 [ELOOP] = TARGET_ELOOP,
579 [ERESTART] = TARGET_ERESTART,
580 [ESTRPIPE] = TARGET_ESTRPIPE,
581 [ENOTEMPTY] = TARGET_ENOTEMPTY,
582 [EUSERS] = TARGET_EUSERS,
583 [ENOTSOCK] = TARGET_ENOTSOCK,
584 [EDESTADDRREQ] = TARGET_EDESTADDRREQ,
585 [EMSGSIZE] = TARGET_EMSGSIZE,
586 [EPROTOTYPE] = TARGET_EPROTOTYPE,
587 [ENOPROTOOPT] = TARGET_ENOPROTOOPT,
588 [EPROTONOSUPPORT] = TARGET_EPROTONOSUPPORT,
589 [ESOCKTNOSUPPORT] = TARGET_ESOCKTNOSUPPORT,
590 [EOPNOTSUPP] = TARGET_EOPNOTSUPP,
591 [EPFNOSUPPORT] = TARGET_EPFNOSUPPORT,
592 [EAFNOSUPPORT] = TARGET_EAFNOSUPPORT,
593 [EADDRINUSE] = TARGET_EADDRINUSE,
594 [EADDRNOTAVAIL] = TARGET_EADDRNOTAVAIL,
595 [ENETDOWN] = TARGET_ENETDOWN,
596 [ENETUNREACH] = TARGET_ENETUNREACH,
597 [ENETRESET] = TARGET_ENETRESET,
598 [ECONNABORTED] = TARGET_ECONNABORTED,
599 [ECONNRESET] = TARGET_ECONNRESET,
600 [ENOBUFS] = TARGET_ENOBUFS,
601 [EISCONN] = TARGET_EISCONN,
602 [ENOTCONN] = TARGET_ENOTCONN,
603 [EUCLEAN] = TARGET_EUCLEAN,
604 [ENOTNAM] = TARGET_ENOTNAM,
605 [ENAVAIL] = TARGET_ENAVAIL,
606 [EISNAM] = TARGET_EISNAM,
607 [EREMOTEIO] = TARGET_EREMOTEIO,
608 [ESHUTDOWN] = TARGET_ESHUTDOWN,
609 [ETOOMANYREFS] = TARGET_ETOOMANYREFS,
610 [ETIMEDOUT] = TARGET_ETIMEDOUT,
611 [ECONNREFUSED] = TARGET_ECONNREFUSED,
612 [EHOSTDOWN] = TARGET_EHOSTDOWN,
613 [EHOSTUNREACH] = TARGET_EHOSTUNREACH,
614 [EALREADY] = TARGET_EALREADY,
615 [EINPROGRESS] = TARGET_EINPROGRESS,
616 [ESTALE] = TARGET_ESTALE,
617 [ECANCELED] = TARGET_ECANCELED,
618 [ENOMEDIUM] = TARGET_ENOMEDIUM,
619 [EMEDIUMTYPE] = TARGET_EMEDIUMTYPE,
b7fe5db7 620#ifdef ENOKEY
637947f1 621 [ENOKEY] = TARGET_ENOKEY,
b7fe5db7
TS
622#endif
623#ifdef EKEYEXPIRED
637947f1 624 [EKEYEXPIRED] = TARGET_EKEYEXPIRED,
b7fe5db7
TS
625#endif
626#ifdef EKEYREVOKED
637947f1 627 [EKEYREVOKED] = TARGET_EKEYREVOKED,
b7fe5db7
TS
628#endif
629#ifdef EKEYREJECTED
637947f1 630 [EKEYREJECTED] = TARGET_EKEYREJECTED,
b7fe5db7
TS
631#endif
632#ifdef EOWNERDEAD
637947f1 633 [EOWNERDEAD] = TARGET_EOWNERDEAD,
b7fe5db7
TS
634#endif
635#ifdef ENOTRECOVERABLE
637947f1 636 [ENOTRECOVERABLE] = TARGET_ENOTRECOVERABLE,
b7fe5db7 637#endif
b92c47c1 638};
637947f1
TS
639
640static inline int host_to_target_errno(int err)
641{
642 if(host_to_target_errno_table[err])
643 return host_to_target_errno_table[err];
644 return err;
645}
646
b92c47c1
TS
647static inline int target_to_host_errno(int err)
648{
649 if (target_to_host_errno_table[err])
650 return target_to_host_errno_table[err];
651 return err;
652}
653
992f48a0 654static inline abi_long get_errno(abi_long ret)
31e31b8a
FB
655{
656 if (ret == -1)
637947f1 657 return -host_to_target_errno(errno);
31e31b8a
FB
658 else
659 return ret;
660}
661
992f48a0 662static inline int is_error(abi_long ret)
31e31b8a 663{
992f48a0 664 return (abi_ulong)ret >= (abi_ulong)(-4096);
31e31b8a
FB
665}
666
b92c47c1
TS
667char *target_strerror(int err)
668{
669 return strerror(target_to_host_errno(err));
670}
671
992f48a0
BS
672static abi_ulong target_brk;
673static abi_ulong target_original_brk;
31e31b8a 674
992f48a0 675void target_set_brk(abi_ulong new_brk)
31e31b8a 676{
4c1de73d 677 target_original_brk = target_brk = HOST_PAGE_ALIGN(new_brk);
31e31b8a
FB
678}
679
0da46a6e 680/* do_brk() must return target values and target errnos. */
992f48a0 681abi_long do_brk(abi_ulong new_brk)
31e31b8a 682{
992f48a0
BS
683 abi_ulong brk_page;
684 abi_long mapped_addr;
31e31b8a
FB
685 int new_alloc_size;
686
687 if (!new_brk)
53a5960a 688 return target_brk;
31e31b8a 689 if (new_brk < target_original_brk)
7ab240ad 690 return target_brk;
3b46e624 691
53a5960a 692 brk_page = HOST_PAGE_ALIGN(target_brk);
31e31b8a
FB
693
694 /* If the new brk is less than this, set it and we're done... */
695 if (new_brk < brk_page) {
696 target_brk = new_brk;
53a5960a 697 return target_brk;
31e31b8a
FB
698 }
699
700 /* We need to allocate more memory after the brk... */
54936004 701 new_alloc_size = HOST_PAGE_ALIGN(new_brk - brk_page + 1);
5fafdf24 702 mapped_addr = get_errno(target_mmap(brk_page, new_alloc_size,
54936004
FB
703 PROT_READ|PROT_WRITE,
704 MAP_ANON|MAP_FIXED|MAP_PRIVATE, 0, 0));
7ab240ad
AZ
705
706 if (!is_error(mapped_addr))
31e31b8a 707 target_brk = new_brk;
7ab240ad
AZ
708
709 return target_brk;
31e31b8a
FB
710}
711
26edcf41
TS
712static inline abi_long copy_from_user_fdset(fd_set *fds,
713 abi_ulong target_fds_addr,
714 int n)
31e31b8a 715{
26edcf41
TS
716 int i, nw, j, k;
717 abi_ulong b, *target_fds;
718
719 nw = (n + TARGET_ABI_BITS - 1) / TARGET_ABI_BITS;
720 if (!(target_fds = lock_user(VERIFY_READ,
721 target_fds_addr,
722 sizeof(abi_ulong) * nw,
723 1)))
724 return -TARGET_EFAULT;
725
726 FD_ZERO(fds);
727 k = 0;
728 for (i = 0; i < nw; i++) {
729 /* grab the abi_ulong */
730 __get_user(b, &target_fds[i]);
731 for (j = 0; j < TARGET_ABI_BITS; j++) {
732 /* check the bit inside the abi_ulong */
733 if ((b >> j) & 1)
734 FD_SET(k, fds);
735 k++;
31e31b8a 736 }
31e31b8a 737 }
26edcf41
TS
738
739 unlock_user(target_fds, target_fds_addr, 0);
740
741 return 0;
31e31b8a
FB
742}
743
26edcf41
TS
744static inline abi_long copy_to_user_fdset(abi_ulong target_fds_addr,
745 const fd_set *fds,
746 int n)
31e31b8a 747{
31e31b8a 748 int i, nw, j, k;
992f48a0 749 abi_long v;
26edcf41 750 abi_ulong *target_fds;
31e31b8a 751
26edcf41
TS
752 nw = (n + TARGET_ABI_BITS - 1) / TARGET_ABI_BITS;
753 if (!(target_fds = lock_user(VERIFY_WRITE,
754 target_fds_addr,
755 sizeof(abi_ulong) * nw,
756 0)))
757 return -TARGET_EFAULT;
758
759 k = 0;
760 for (i = 0; i < nw; i++) {
761 v = 0;
762 for (j = 0; j < TARGET_ABI_BITS; j++) {
763 v |= ((FD_ISSET(k, fds) != 0) << j);
764 k++;
31e31b8a 765 }
26edcf41 766 __put_user(v, &target_fds[i]);
31e31b8a 767 }
26edcf41
TS
768
769 unlock_user(target_fds, target_fds_addr, sizeof(abi_ulong) * nw);
770
771 return 0;
31e31b8a
FB
772}
773
c596ed17
FB
774#if defined(__alpha__)
775#define HOST_HZ 1024
776#else
777#define HOST_HZ 100
778#endif
779
992f48a0 780static inline abi_long host_to_target_clock_t(long ticks)
c596ed17
FB
781{
782#if HOST_HZ == TARGET_HZ
783 return ticks;
784#else
785 return ((int64_t)ticks * TARGET_HZ) / HOST_HZ;
786#endif
787}
788
579a97f7
FB
789static inline abi_long host_to_target_rusage(abi_ulong target_addr,
790 const struct rusage *rusage)
b409186b 791{
53a5960a
PB
792 struct target_rusage *target_rusage;
793
579a97f7
FB
794 if (!lock_user_struct(VERIFY_WRITE, target_rusage, target_addr, 0))
795 return -TARGET_EFAULT;
b409186b
FB
796 target_rusage->ru_utime.tv_sec = tswapl(rusage->ru_utime.tv_sec);
797 target_rusage->ru_utime.tv_usec = tswapl(rusage->ru_utime.tv_usec);
798 target_rusage->ru_stime.tv_sec = tswapl(rusage->ru_stime.tv_sec);
799 target_rusage->ru_stime.tv_usec = tswapl(rusage->ru_stime.tv_usec);
800 target_rusage->ru_maxrss = tswapl(rusage->ru_maxrss);
801 target_rusage->ru_ixrss = tswapl(rusage->ru_ixrss);
802 target_rusage->ru_idrss = tswapl(rusage->ru_idrss);
803 target_rusage->ru_isrss = tswapl(rusage->ru_isrss);
804 target_rusage->ru_minflt = tswapl(rusage->ru_minflt);
805 target_rusage->ru_majflt = tswapl(rusage->ru_majflt);
806 target_rusage->ru_nswap = tswapl(rusage->ru_nswap);
807 target_rusage->ru_inblock = tswapl(rusage->ru_inblock);
808 target_rusage->ru_oublock = tswapl(rusage->ru_oublock);
809 target_rusage->ru_msgsnd = tswapl(rusage->ru_msgsnd);
810 target_rusage->ru_msgrcv = tswapl(rusage->ru_msgrcv);
811 target_rusage->ru_nsignals = tswapl(rusage->ru_nsignals);
812 target_rusage->ru_nvcsw = tswapl(rusage->ru_nvcsw);
813 target_rusage->ru_nivcsw = tswapl(rusage->ru_nivcsw);
53a5960a 814 unlock_user_struct(target_rusage, target_addr, 1);
579a97f7
FB
815
816 return 0;
b409186b
FB
817}
818
788f5ec4
TS
819static inline abi_long copy_from_user_timeval(struct timeval *tv,
820 abi_ulong target_tv_addr)
31e31b8a 821{
53a5960a
PB
822 struct target_timeval *target_tv;
823
788f5ec4 824 if (!lock_user_struct(VERIFY_READ, target_tv, target_tv_addr, 1))
579a97f7 825 return -TARGET_EFAULT;
788f5ec4
TS
826
827 __get_user(tv->tv_sec, &target_tv->tv_sec);
828 __get_user(tv->tv_usec, &target_tv->tv_usec);
829
830 unlock_user_struct(target_tv, target_tv_addr, 0);
579a97f7
FB
831
832 return 0;
31e31b8a
FB
833}
834
788f5ec4
TS
835static inline abi_long copy_to_user_timeval(abi_ulong target_tv_addr,
836 const struct timeval *tv)
31e31b8a 837{
53a5960a
PB
838 struct target_timeval *target_tv;
839
788f5ec4 840 if (!lock_user_struct(VERIFY_WRITE, target_tv, target_tv_addr, 0))
579a97f7 841 return -TARGET_EFAULT;
788f5ec4
TS
842
843 __put_user(tv->tv_sec, &target_tv->tv_sec);
844 __put_user(tv->tv_usec, &target_tv->tv_usec);
845
846 unlock_user_struct(target_tv, target_tv_addr, 1);
579a97f7
FB
847
848 return 0;
31e31b8a
FB
849}
850
24e1003a
AJ
851static inline abi_long copy_from_user_mq_attr(struct mq_attr *attr,
852 abi_ulong target_mq_attr_addr)
853{
854 struct target_mq_attr *target_mq_attr;
855
856 if (!lock_user_struct(VERIFY_READ, target_mq_attr,
857 target_mq_attr_addr, 1))
858 return -TARGET_EFAULT;
859
860 __get_user(attr->mq_flags, &target_mq_attr->mq_flags);
861 __get_user(attr->mq_maxmsg, &target_mq_attr->mq_maxmsg);
862 __get_user(attr->mq_msgsize, &target_mq_attr->mq_msgsize);
863 __get_user(attr->mq_curmsgs, &target_mq_attr->mq_curmsgs);
864
865 unlock_user_struct(target_mq_attr, target_mq_attr_addr, 0);
866
867 return 0;
868}
869
870static inline abi_long copy_to_user_mq_attr(abi_ulong target_mq_attr_addr,
871 const struct mq_attr *attr)
872{
873 struct target_mq_attr *target_mq_attr;
874
875 if (!lock_user_struct(VERIFY_WRITE, target_mq_attr,
876 target_mq_attr_addr, 0))
877 return -TARGET_EFAULT;
878
879 __put_user(attr->mq_flags, &target_mq_attr->mq_flags);
880 __put_user(attr->mq_maxmsg, &target_mq_attr->mq_maxmsg);
881 __put_user(attr->mq_msgsize, &target_mq_attr->mq_msgsize);
882 __put_user(attr->mq_curmsgs, &target_mq_attr->mq_curmsgs);
883
884 unlock_user_struct(target_mq_attr, target_mq_attr_addr, 1);
885
886 return 0;
887}
31e31b8a 888
0da46a6e 889/* do_select() must return target values and target errnos. */
992f48a0 890static abi_long do_select(int n,
26edcf41
TS
891 abi_ulong rfd_addr, abi_ulong wfd_addr,
892 abi_ulong efd_addr, abi_ulong target_tv_addr)
31e31b8a
FB
893{
894 fd_set rfds, wfds, efds;
895 fd_set *rfds_ptr, *wfds_ptr, *efds_ptr;
896 struct timeval tv, *tv_ptr;
992f48a0 897 abi_long ret;
31e31b8a 898
26edcf41
TS
899 if (rfd_addr) {
900 if (copy_from_user_fdset(&rfds, rfd_addr, n))
901 return -TARGET_EFAULT;
902 rfds_ptr = &rfds;
53a5960a 903 } else {
53a5960a
PB
904 rfds_ptr = NULL;
905 }
26edcf41
TS
906 if (wfd_addr) {
907 if (copy_from_user_fdset(&wfds, wfd_addr, n))
908 return -TARGET_EFAULT;
909 wfds_ptr = &wfds;
53a5960a 910 } else {
53a5960a
PB
911 wfds_ptr = NULL;
912 }
26edcf41
TS
913 if (efd_addr) {
914 if (copy_from_user_fdset(&efds, efd_addr, n))
915 return -TARGET_EFAULT;
916 efds_ptr = &efds;
53a5960a 917 } else {
53a5960a
PB
918 efds_ptr = NULL;
919 }
3b46e624 920
26edcf41 921 if (target_tv_addr) {
788f5ec4
TS
922 if (copy_from_user_timeval(&tv, target_tv_addr))
923 return -TARGET_EFAULT;
31e31b8a
FB
924 tv_ptr = &tv;
925 } else {
926 tv_ptr = NULL;
927 }
26edcf41 928
31e31b8a 929 ret = get_errno(select(n, rfds_ptr, wfds_ptr, efds_ptr, tv_ptr));
53a5960a 930
26edcf41
TS
931 if (!is_error(ret)) {
932 if (rfd_addr && copy_to_user_fdset(rfd_addr, &rfds, n))
933 return -TARGET_EFAULT;
934 if (wfd_addr && copy_to_user_fdset(wfd_addr, &wfds, n))
935 return -TARGET_EFAULT;
936 if (efd_addr && copy_to_user_fdset(efd_addr, &efds, n))
937 return -TARGET_EFAULT;
31e31b8a 938
788f5ec4
TS
939 if (target_tv_addr && copy_to_user_timeval(target_tv_addr, &tv))
940 return -TARGET_EFAULT;
31e31b8a 941 }
579a97f7 942
31e31b8a
FB
943 return ret;
944}
945
b975b83b
LL
946static inline abi_long target_to_host_ip_mreq(struct ip_mreqn *mreqn,
947 abi_ulong target_addr,
948 socklen_t len)
949{
950 struct target_ip_mreqn *target_smreqn;
951
952 target_smreqn = lock_user(VERIFY_READ, target_addr, len, 1);
953 if (!target_smreqn)
954 return -TARGET_EFAULT;
955 mreqn->imr_multiaddr.s_addr = target_smreqn->imr_multiaddr.s_addr;
956 mreqn->imr_address.s_addr = target_smreqn->imr_address.s_addr;
957 if (len == sizeof(struct target_ip_mreqn))
958 mreqn->imr_ifindex = tswapl(target_smreqn->imr_ifindex);
959 unlock_user(target_smreqn, target_addr, 0);
960
961 return 0;
962}
963
579a97f7
FB
964static inline abi_long target_to_host_sockaddr(struct sockaddr *addr,
965 abi_ulong target_addr,
966 socklen_t len)
7854b056 967{
607175e0
AJ
968 const socklen_t unix_maxlen = sizeof (struct sockaddr_un);
969 sa_family_t sa_family;
53a5960a
PB
970 struct target_sockaddr *target_saddr;
971
579a97f7
FB
972 target_saddr = lock_user(VERIFY_READ, target_addr, len, 1);
973 if (!target_saddr)
974 return -TARGET_EFAULT;
607175e0
AJ
975
976 sa_family = tswap16(target_saddr->sa_family);
977
978 /* Oops. The caller might send a incomplete sun_path; sun_path
979 * must be terminated by \0 (see the manual page), but
980 * unfortunately it is quite common to specify sockaddr_un
981 * length as "strlen(x->sun_path)" while it should be
982 * "strlen(...) + 1". We'll fix that here if needed.
983 * Linux kernel has a similar feature.
984 */
985
986 if (sa_family == AF_UNIX) {
987 if (len < unix_maxlen && len > 0) {
988 char *cp = (char*)target_saddr;
989
990 if ( cp[len-1] && !cp[len] )
991 len++;
992 }
993 if (len > unix_maxlen)
994 len = unix_maxlen;
995 }
996
53a5960a 997 memcpy(addr, target_saddr, len);
607175e0 998 addr->sa_family = sa_family;
53a5960a 999 unlock_user(target_saddr, target_addr, 0);
579a97f7
FB
1000
1001 return 0;
7854b056
FB
1002}
1003
579a97f7
FB
1004static inline abi_long host_to_target_sockaddr(abi_ulong target_addr,
1005 struct sockaddr *addr,
1006 socklen_t len)
7854b056 1007{
53a5960a
PB
1008 struct target_sockaddr *target_saddr;
1009
579a97f7
FB
1010 target_saddr = lock_user(VERIFY_WRITE, target_addr, len, 0);
1011 if (!target_saddr)
1012 return -TARGET_EFAULT;
53a5960a
PB
1013 memcpy(target_saddr, addr, len);
1014 target_saddr->sa_family = tswap16(addr->sa_family);
1015 unlock_user(target_saddr, target_addr, len);
579a97f7
FB
1016
1017 return 0;
7854b056
FB
1018}
1019
53a5960a 1020/* ??? Should this also swap msgh->name? */
5a4a898d
FB
1021static inline abi_long target_to_host_cmsg(struct msghdr *msgh,
1022 struct target_msghdr *target_msgh)
7854b056
FB
1023{
1024 struct cmsghdr *cmsg = CMSG_FIRSTHDR(msgh);
5a4a898d
FB
1025 abi_long msg_controllen;
1026 abi_ulong target_cmsg_addr;
1027 struct target_cmsghdr *target_cmsg;
7854b056 1028 socklen_t space = 0;
5a4a898d
FB
1029
1030 msg_controllen = tswapl(target_msgh->msg_controllen);
1031 if (msg_controllen < sizeof (struct target_cmsghdr))
1032 goto the_end;
1033 target_cmsg_addr = tswapl(target_msgh->msg_control);
1034 target_cmsg = lock_user(VERIFY_READ, target_cmsg_addr, msg_controllen, 1);
1035 if (!target_cmsg)
1036 return -TARGET_EFAULT;
7854b056
FB
1037
1038 while (cmsg && target_cmsg) {
1039 void *data = CMSG_DATA(cmsg);
1040 void *target_data = TARGET_CMSG_DATA(target_cmsg);
1041
5fafdf24 1042 int len = tswapl(target_cmsg->cmsg_len)
7854b056
FB
1043 - TARGET_CMSG_ALIGN(sizeof (struct target_cmsghdr));
1044
1045 space += CMSG_SPACE(len);
1046 if (space > msgh->msg_controllen) {
1047 space -= CMSG_SPACE(len);
31febb71 1048 gemu_log("Host cmsg overflow\n");
7854b056
FB
1049 break;
1050 }
1051
1052 cmsg->cmsg_level = tswap32(target_cmsg->cmsg_level);
1053 cmsg->cmsg_type = tswap32(target_cmsg->cmsg_type);
1054 cmsg->cmsg_len = CMSG_LEN(len);
1055
3532fa74 1056 if (cmsg->cmsg_level != TARGET_SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS) {
7854b056
FB
1057 gemu_log("Unsupported ancillary data: %d/%d\n", cmsg->cmsg_level, cmsg->cmsg_type);
1058 memcpy(data, target_data, len);
1059 } else {
1060 int *fd = (int *)data;
1061 int *target_fd = (int *)target_data;
1062 int i, numfds = len / sizeof(int);
1063
1064 for (i = 0; i < numfds; i++)
1065 fd[i] = tswap32(target_fd[i]);
1066 }
1067
1068 cmsg = CMSG_NXTHDR(msgh, cmsg);
1069 target_cmsg = TARGET_CMSG_NXTHDR(target_msgh, target_cmsg);
1070 }
5a4a898d
FB
1071 unlock_user(target_cmsg, target_cmsg_addr, 0);
1072 the_end:
7854b056 1073 msgh->msg_controllen = space;
5a4a898d 1074 return 0;
7854b056
FB
1075}
1076
53a5960a 1077/* ??? Should this also swap msgh->name? */
5a4a898d
FB
1078static inline abi_long host_to_target_cmsg(struct target_msghdr *target_msgh,
1079 struct msghdr *msgh)
7854b056
FB
1080{
1081 struct cmsghdr *cmsg = CMSG_FIRSTHDR(msgh);
5a4a898d
FB
1082 abi_long msg_controllen;
1083 abi_ulong target_cmsg_addr;
1084 struct target_cmsghdr *target_cmsg;
7854b056
FB
1085 socklen_t space = 0;
1086
5a4a898d
FB
1087 msg_controllen = tswapl(target_msgh->msg_controllen);
1088 if (msg_controllen < sizeof (struct target_cmsghdr))
1089 goto the_end;
1090 target_cmsg_addr = tswapl(target_msgh->msg_control);
1091 target_cmsg = lock_user(VERIFY_WRITE, target_cmsg_addr, msg_controllen, 0);
1092 if (!target_cmsg)
1093 return -TARGET_EFAULT;
1094
7854b056
FB
1095 while (cmsg && target_cmsg) {
1096 void *data = CMSG_DATA(cmsg);
1097 void *target_data = TARGET_CMSG_DATA(target_cmsg);
1098
1099 int len = cmsg->cmsg_len - CMSG_ALIGN(sizeof (struct cmsghdr));
1100
1101 space += TARGET_CMSG_SPACE(len);
5a4a898d 1102 if (space > msg_controllen) {
7854b056 1103 space -= TARGET_CMSG_SPACE(len);
31febb71 1104 gemu_log("Target cmsg overflow\n");
7854b056
FB
1105 break;
1106 }
1107
1108 target_cmsg->cmsg_level = tswap32(cmsg->cmsg_level);
1109 target_cmsg->cmsg_type = tswap32(cmsg->cmsg_type);
1110 target_cmsg->cmsg_len = tswapl(TARGET_CMSG_LEN(len));
1111
3532fa74 1112 if (cmsg->cmsg_level != TARGET_SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS) {
7854b056
FB
1113 gemu_log("Unsupported ancillary data: %d/%d\n", cmsg->cmsg_level, cmsg->cmsg_type);
1114 memcpy(target_data, data, len);
1115 } else {
1116 int *fd = (int *)data;
1117 int *target_fd = (int *)target_data;
1118 int i, numfds = len / sizeof(int);
1119
1120 for (i = 0; i < numfds; i++)
1121 target_fd[i] = tswap32(fd[i]);
1122 }
1123
1124 cmsg = CMSG_NXTHDR(msgh, cmsg);
1125 target_cmsg = TARGET_CMSG_NXTHDR(target_msgh, target_cmsg);
1126 }
5a4a898d
FB
1127 unlock_user(target_cmsg, target_cmsg_addr, space);
1128 the_end:
1129 target_msgh->msg_controllen = tswapl(space);
1130 return 0;
7854b056
FB
1131}
1132
0da46a6e 1133/* do_setsockopt() Must return target values and target errnos. */
992f48a0 1134static abi_long do_setsockopt(int sockfd, int level, int optname,
2f619698 1135 abi_ulong optval_addr, socklen_t optlen)
7854b056 1136{
992f48a0 1137 abi_long ret;
32407103 1138 int val;
b975b83b 1139 struct ip_mreqn *ip_mreq;
6e3cb58f 1140 struct ip_mreq_source *ip_mreq_source;
3b46e624 1141
8853f86e
FB
1142 switch(level) {
1143 case SOL_TCP:
7854b056 1144 /* TCP options all take an 'int' value. */
7854b056 1145 if (optlen < sizeof(uint32_t))
0da46a6e 1146 return -TARGET_EINVAL;
3b46e624 1147
2f619698
FB
1148 if (get_user_u32(val, optval_addr))
1149 return -TARGET_EFAULT;
8853f86e
FB
1150 ret = get_errno(setsockopt(sockfd, level, optname, &val, sizeof(val)));
1151 break;
1152 case SOL_IP:
1153 switch(optname) {
2efbe911
FB
1154 case IP_TOS:
1155 case IP_TTL:
8853f86e 1156 case IP_HDRINCL:
2efbe911
FB
1157 case IP_ROUTER_ALERT:
1158 case IP_RECVOPTS:
1159 case IP_RETOPTS:
1160 case IP_PKTINFO:
1161 case IP_MTU_DISCOVER:
1162 case IP_RECVERR:
1163 case IP_RECVTOS:
1164#ifdef IP_FREEBIND
1165 case IP_FREEBIND:
1166#endif
1167 case IP_MULTICAST_TTL:
1168 case IP_MULTICAST_LOOP:
8853f86e
FB
1169 val = 0;
1170 if (optlen >= sizeof(uint32_t)) {
2f619698
FB
1171 if (get_user_u32(val, optval_addr))
1172 return -TARGET_EFAULT;
8853f86e 1173 } else if (optlen >= 1) {
2f619698
FB
1174 if (get_user_u8(val, optval_addr))
1175 return -TARGET_EFAULT;
8853f86e
FB
1176 }
1177 ret = get_errno(setsockopt(sockfd, level, optname, &val, sizeof(val)));
1178 break;
b975b83b
LL
1179 case IP_ADD_MEMBERSHIP:
1180 case IP_DROP_MEMBERSHIP:
1181 if (optlen < sizeof (struct target_ip_mreq) ||
1182 optlen > sizeof (struct target_ip_mreqn))
1183 return -TARGET_EINVAL;
1184
1185 ip_mreq = (struct ip_mreqn *) alloca(optlen);
1186 target_to_host_ip_mreq(ip_mreq, optval_addr, optlen);
1187 ret = get_errno(setsockopt(sockfd, level, optname, ip_mreq, optlen));
1188 break;
1189
6e3cb58f
LL
1190 case IP_BLOCK_SOURCE:
1191 case IP_UNBLOCK_SOURCE:
1192 case IP_ADD_SOURCE_MEMBERSHIP:
1193 case IP_DROP_SOURCE_MEMBERSHIP:
1194 if (optlen != sizeof (struct target_ip_mreq_source))
1195 return -TARGET_EINVAL;
1196
1197 ip_mreq_source = lock_user(VERIFY_READ, optval_addr, optlen, 1);
1198 ret = get_errno(setsockopt(sockfd, level, optname, ip_mreq_source, optlen));
1199 unlock_user (ip_mreq_source, optval_addr, 0);
1200 break;
1201
8853f86e
FB
1202 default:
1203 goto unimplemented;
1204 }
1205 break;
3532fa74 1206 case TARGET_SOL_SOCKET:
8853f86e
FB
1207 switch (optname) {
1208 /* Options with 'int' argument. */
3532fa74
FB
1209 case TARGET_SO_DEBUG:
1210 optname = SO_DEBUG;
1211 break;
1212 case TARGET_SO_REUSEADDR:
1213 optname = SO_REUSEADDR;
1214 break;
1215 case TARGET_SO_TYPE:
1216 optname = SO_TYPE;
1217 break;
1218 case TARGET_SO_ERROR:
1219 optname = SO_ERROR;
1220 break;
1221 case TARGET_SO_DONTROUTE:
1222 optname = SO_DONTROUTE;
1223 break;
1224 case TARGET_SO_BROADCAST:
1225 optname = SO_BROADCAST;
1226 break;
1227 case TARGET_SO_SNDBUF:
1228 optname = SO_SNDBUF;
1229 break;
1230 case TARGET_SO_RCVBUF:
1231 optname = SO_RCVBUF;
1232 break;
1233 case TARGET_SO_KEEPALIVE:
1234 optname = SO_KEEPALIVE;
1235 break;
1236 case TARGET_SO_OOBINLINE:
1237 optname = SO_OOBINLINE;
1238 break;
1239 case TARGET_SO_NO_CHECK:
1240 optname = SO_NO_CHECK;
1241 break;
1242 case TARGET_SO_PRIORITY:
1243 optname = SO_PRIORITY;
1244 break;
5e83e8e3 1245#ifdef SO_BSDCOMPAT
3532fa74
FB
1246 case TARGET_SO_BSDCOMPAT:
1247 optname = SO_BSDCOMPAT;
1248 break;
5e83e8e3 1249#endif
3532fa74
FB
1250 case TARGET_SO_PASSCRED:
1251 optname = SO_PASSCRED;
1252 break;
1253 case TARGET_SO_TIMESTAMP:
1254 optname = SO_TIMESTAMP;
1255 break;
1256 case TARGET_SO_RCVLOWAT:
1257 optname = SO_RCVLOWAT;
1258 break;
1259 case TARGET_SO_RCVTIMEO:
1260 optname = SO_RCVTIMEO;
1261 break;
1262 case TARGET_SO_SNDTIMEO:
1263 optname = SO_SNDTIMEO;
1264 break;
8853f86e
FB
1265 break;
1266 default:
1267 goto unimplemented;
1268 }
3532fa74 1269 if (optlen < sizeof(uint32_t))
2f619698 1270 return -TARGET_EINVAL;
3532fa74 1271
2f619698
FB
1272 if (get_user_u32(val, optval_addr))
1273 return -TARGET_EFAULT;
3532fa74 1274 ret = get_errno(setsockopt(sockfd, SOL_SOCKET, optname, &val, sizeof(val)));
8853f86e 1275 break;
7854b056 1276 default:
8853f86e
FB
1277 unimplemented:
1278 gemu_log("Unsupported setsockopt level=%d optname=%d \n", level, optname);
6fa13c17 1279 ret = -TARGET_ENOPROTOOPT;
7854b056 1280 }
8853f86e 1281 return ret;
7854b056
FB
1282}
1283
0da46a6e 1284/* do_getsockopt() Must return target values and target errnos. */
992f48a0 1285static abi_long do_getsockopt(int sockfd, int level, int optname,
2f619698 1286 abi_ulong optval_addr, abi_ulong optlen)
7854b056 1287{
992f48a0 1288 abi_long ret;
b55266b5
BS
1289 int len, val;
1290 socklen_t lv;
8853f86e
FB
1291
1292 switch(level) {
3532fa74
FB
1293 case TARGET_SOL_SOCKET:
1294 level = SOL_SOCKET;
8853f86e 1295 switch (optname) {
3532fa74
FB
1296 case TARGET_SO_LINGER:
1297 case TARGET_SO_RCVTIMEO:
1298 case TARGET_SO_SNDTIMEO:
1299 case TARGET_SO_PEERCRED:
1300 case TARGET_SO_PEERNAME:
8853f86e
FB
1301 /* These don't just return a single integer */
1302 goto unimplemented;
1303 default:
2efbe911
FB
1304 goto int_case;
1305 }
1306 break;
1307 case SOL_TCP:
1308 /* TCP options all take an 'int' value. */
1309 int_case:
2f619698
FB
1310 if (get_user_u32(len, optlen))
1311 return -TARGET_EFAULT;
2efbe911 1312 if (len < 0)
0da46a6e 1313 return -TARGET_EINVAL;
2efbe911
FB
1314 lv = sizeof(int);
1315 ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
1316 if (ret < 0)
1317 return ret;
1318 val = tswap32(val);
1319 if (len > lv)
1320 len = lv;
2f619698
FB
1321 if (len == 4) {
1322 if (put_user_u32(val, optval_addr))
1323 return -TARGET_EFAULT;
1324 } else {
1325 if (put_user_u8(val, optval_addr))
1326 return -TARGET_EFAULT;
1327 }
1328 if (put_user_u32(len, optlen))
1329 return -TARGET_EFAULT;
2efbe911
FB
1330 break;
1331 case SOL_IP:
1332 switch(optname) {
1333 case IP_TOS:
1334 case IP_TTL:
1335 case IP_HDRINCL:
1336 case IP_ROUTER_ALERT:
1337 case IP_RECVOPTS:
1338 case IP_RETOPTS:
1339 case IP_PKTINFO:
1340 case IP_MTU_DISCOVER:
1341 case IP_RECVERR:
1342 case IP_RECVTOS:
1343#ifdef IP_FREEBIND
1344 case IP_FREEBIND:
1345#endif
1346 case IP_MULTICAST_TTL:
1347 case IP_MULTICAST_LOOP:
2f619698
FB
1348 if (get_user_u32(len, optlen))
1349 return -TARGET_EFAULT;
8853f86e 1350 if (len < 0)
0da46a6e 1351 return -TARGET_EINVAL;
8853f86e
FB
1352 lv = sizeof(int);
1353 ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
1354 if (ret < 0)
1355 return ret;
2efbe911 1356 if (len < sizeof(int) && len > 0 && val >= 0 && val < 255) {
2efbe911 1357 len = 1;
2f619698
FB
1358 if (put_user_u32(len, optlen)
1359 || put_user_u8(val, optval_addr))
1360 return -TARGET_EFAULT;
2efbe911 1361 } else {
2efbe911
FB
1362 if (len > sizeof(int))
1363 len = sizeof(int);
2f619698
FB
1364 if (put_user_u32(len, optlen)
1365 || put_user_u32(val, optval_addr))
1366 return -TARGET_EFAULT;
2efbe911 1367 }
8853f86e 1368 break;
2efbe911 1369 default:
c02f499e
TS
1370 ret = -TARGET_ENOPROTOOPT;
1371 break;
8853f86e
FB
1372 }
1373 break;
1374 default:
1375 unimplemented:
1376 gemu_log("getsockopt level=%d optname=%d not yet supported\n",
1377 level, optname);
c02f499e 1378 ret = -TARGET_EOPNOTSUPP;
8853f86e
FB
1379 break;
1380 }
1381 return ret;
7854b056
FB
1382}
1383
579a97f7
FB
1384/* FIXME
1385 * lock_iovec()/unlock_iovec() have a return code of 0 for success where
1386 * other lock functions have a return code of 0 for failure.
1387 */
1388static abi_long lock_iovec(int type, struct iovec *vec, abi_ulong target_addr,
1389 int count, int copy)
53a5960a
PB
1390{
1391 struct target_iovec *target_vec;
992f48a0 1392 abi_ulong base;
d732dcb4 1393 int i;
53a5960a 1394
579a97f7
FB
1395 target_vec = lock_user(VERIFY_READ, target_addr, count * sizeof(struct target_iovec), 1);
1396 if (!target_vec)
1397 return -TARGET_EFAULT;
53a5960a
PB
1398 for(i = 0;i < count; i++) {
1399 base = tswapl(target_vec[i].iov_base);
1400 vec[i].iov_len = tswapl(target_vec[i].iov_len);
41df8411
FB
1401 if (vec[i].iov_len != 0) {
1402 vec[i].iov_base = lock_user(type, base, vec[i].iov_len, copy);
d732dcb4
AZ
1403 /* Don't check lock_user return value. We must call writev even
1404 if a element has invalid base address. */
41df8411
FB
1405 } else {
1406 /* zero length pointer is ignored */
1407 vec[i].iov_base = NULL;
1408 }
579a97f7
FB
1409 }
1410 unlock_user (target_vec, target_addr, 0);
1411 return 0;
53a5960a
PB
1412}
1413
579a97f7
FB
1414static abi_long unlock_iovec(struct iovec *vec, abi_ulong target_addr,
1415 int count, int copy)
53a5960a
PB
1416{
1417 struct target_iovec *target_vec;
992f48a0 1418 abi_ulong base;
53a5960a
PB
1419 int i;
1420
579a97f7
FB
1421 target_vec = lock_user(VERIFY_READ, target_addr, count * sizeof(struct target_iovec), 1);
1422 if (!target_vec)
1423 return -TARGET_EFAULT;
53a5960a 1424 for(i = 0;i < count; i++) {
d732dcb4
AZ
1425 if (target_vec[i].iov_base) {
1426 base = tswapl(target_vec[i].iov_base);
1427 unlock_user(vec[i].iov_base, base, copy ? vec[i].iov_len : 0);
1428 }
53a5960a
PB
1429 }
1430 unlock_user (target_vec, target_addr, 0);
579a97f7
FB
1431
1432 return 0;
53a5960a
PB
1433}
1434
0da46a6e 1435/* do_socket() Must return target values and target errnos. */
992f48a0 1436static abi_long do_socket(int domain, int type, int protocol)
3532fa74
FB
1437{
1438#if defined(TARGET_MIPS)
1439 switch(type) {
1440 case TARGET_SOCK_DGRAM:
1441 type = SOCK_DGRAM;
1442 break;
1443 case TARGET_SOCK_STREAM:
1444 type = SOCK_STREAM;
1445 break;
1446 case TARGET_SOCK_RAW:
1447 type = SOCK_RAW;
1448 break;
1449 case TARGET_SOCK_RDM:
1450 type = SOCK_RDM;
1451 break;
1452 case TARGET_SOCK_SEQPACKET:
1453 type = SOCK_SEQPACKET;
1454 break;
1455 case TARGET_SOCK_PACKET:
1456 type = SOCK_PACKET;
1457 break;
1458 }
1459#endif
12bc92ab
AZ
1460 if (domain == PF_NETLINK)
1461 return -EAFNOSUPPORT; /* do not NETLINK socket connections possible */
3532fa74
FB
1462 return get_errno(socket(domain, type, protocol));
1463}
1464
0da46a6e 1465/* do_bind() Must return target values and target errnos. */
992f48a0
BS
1466static abi_long do_bind(int sockfd, abi_ulong target_addr,
1467 socklen_t addrlen)
3532fa74 1468{
8f7aeaf6
AJ
1469 void *addr;
1470
be09ac41 1471 if (addrlen < 0)
8f7aeaf6
AJ
1472 return -TARGET_EINVAL;
1473
607175e0 1474 addr = alloca(addrlen+1);
3b46e624 1475
3532fa74
FB
1476 target_to_host_sockaddr(addr, target_addr, addrlen);
1477 return get_errno(bind(sockfd, addr, addrlen));
1478}
1479
0da46a6e 1480/* do_connect() Must return target values and target errnos. */
992f48a0
BS
1481static abi_long do_connect(int sockfd, abi_ulong target_addr,
1482 socklen_t addrlen)
3532fa74 1483{
8f7aeaf6
AJ
1484 void *addr;
1485
be09ac41 1486 if (addrlen < 0)
8f7aeaf6
AJ
1487 return -TARGET_EINVAL;
1488
1489 addr = alloca(addrlen);
3b46e624 1490
3532fa74
FB
1491 target_to_host_sockaddr(addr, target_addr, addrlen);
1492 return get_errno(connect(sockfd, addr, addrlen));
1493}
1494
0da46a6e 1495/* do_sendrecvmsg() Must return target values and target errnos. */
992f48a0
BS
1496static abi_long do_sendrecvmsg(int fd, abi_ulong target_msg,
1497 int flags, int send)
3532fa74 1498{
6de645c7 1499 abi_long ret, len;
3532fa74
FB
1500 struct target_msghdr *msgp;
1501 struct msghdr msg;
1502 int count;
1503 struct iovec *vec;
992f48a0 1504 abi_ulong target_vec;
3532fa74 1505
579a97f7
FB
1506 /* FIXME */
1507 if (!lock_user_struct(send ? VERIFY_READ : VERIFY_WRITE,
1508 msgp,
1509 target_msg,
1510 send ? 1 : 0))
1511 return -TARGET_EFAULT;
3532fa74
FB
1512 if (msgp->msg_name) {
1513 msg.msg_namelen = tswap32(msgp->msg_namelen);
1514 msg.msg_name = alloca(msg.msg_namelen);
1515 target_to_host_sockaddr(msg.msg_name, tswapl(msgp->msg_name),
1516 msg.msg_namelen);
1517 } else {
1518 msg.msg_name = NULL;
1519 msg.msg_namelen = 0;
1520 }
1521 msg.msg_controllen = 2 * tswapl(msgp->msg_controllen);
1522 msg.msg_control = alloca(msg.msg_controllen);
1523 msg.msg_flags = tswap32(msgp->msg_flags);
3b46e624 1524
3532fa74
FB
1525 count = tswapl(msgp->msg_iovlen);
1526 vec = alloca(count * sizeof(struct iovec));
1527 target_vec = tswapl(msgp->msg_iov);
579a97f7 1528 lock_iovec(send ? VERIFY_READ : VERIFY_WRITE, vec, target_vec, count, send);
3532fa74
FB
1529 msg.msg_iovlen = count;
1530 msg.msg_iov = vec;
3b46e624 1531
3532fa74 1532 if (send) {
5a4a898d
FB
1533 ret = target_to_host_cmsg(&msg, msgp);
1534 if (ret == 0)
1535 ret = get_errno(sendmsg(fd, &msg, flags));
3532fa74
FB
1536 } else {
1537 ret = get_errno(recvmsg(fd, &msg, flags));
6de645c7
AZ
1538 if (!is_error(ret)) {
1539 len = ret;
5a4a898d 1540 ret = host_to_target_cmsg(msgp, &msg);
6de645c7
AZ
1541 if (!is_error(ret))
1542 ret = len;
1543 }
3532fa74
FB
1544 }
1545 unlock_iovec(vec, target_vec, count, !send);
579a97f7 1546 unlock_user_struct(msgp, target_msg, send ? 0 : 1);
3532fa74
FB
1547 return ret;
1548}
1549
0da46a6e 1550/* do_accept() Must return target values and target errnos. */
992f48a0 1551static abi_long do_accept(int fd, abi_ulong target_addr,
2f619698 1552 abi_ulong target_addrlen_addr)
1be9e1dc 1553{
2f619698
FB
1554 socklen_t addrlen;
1555 void *addr;
992f48a0 1556 abi_long ret;
1be9e1dc 1557
2f619698
FB
1558 if (get_user_u32(addrlen, target_addrlen_addr))
1559 return -TARGET_EFAULT;
1560
be09ac41 1561 if (addrlen < 0)
8f7aeaf6
AJ
1562 return -TARGET_EINVAL;
1563
2f619698
FB
1564 addr = alloca(addrlen);
1565
1be9e1dc
PB
1566 ret = get_errno(accept(fd, addr, &addrlen));
1567 if (!is_error(ret)) {
1568 host_to_target_sockaddr(target_addr, addr, addrlen);
2f619698
FB
1569 if (put_user_u32(addrlen, target_addrlen_addr))
1570 ret = -TARGET_EFAULT;
1be9e1dc
PB
1571 }
1572 return ret;
1573}
1574
0da46a6e 1575/* do_getpeername() Must return target values and target errnos. */
992f48a0 1576static abi_long do_getpeername(int fd, abi_ulong target_addr,
2f619698 1577 abi_ulong target_addrlen_addr)
1be9e1dc 1578{
2f619698
FB
1579 socklen_t addrlen;
1580 void *addr;
992f48a0 1581 abi_long ret;
1be9e1dc 1582
2f619698
FB
1583 if (get_user_u32(addrlen, target_addrlen_addr))
1584 return -TARGET_EFAULT;
1585
be09ac41 1586 if (addrlen < 0)
8f7aeaf6
AJ
1587 return -TARGET_EINVAL;
1588
2f619698
FB
1589 addr = alloca(addrlen);
1590
1be9e1dc
PB
1591 ret = get_errno(getpeername(fd, addr, &addrlen));
1592 if (!is_error(ret)) {
1593 host_to_target_sockaddr(target_addr, addr, addrlen);
2f619698
FB
1594 if (put_user_u32(addrlen, target_addrlen_addr))
1595 ret = -TARGET_EFAULT;
1be9e1dc
PB
1596 }
1597 return ret;
1598}
1599
0da46a6e 1600/* do_getsockname() Must return target values and target errnos. */
992f48a0 1601static abi_long do_getsockname(int fd, abi_ulong target_addr,
2f619698 1602 abi_ulong target_addrlen_addr)
1be9e1dc 1603{
2f619698
FB
1604 socklen_t addrlen;
1605 void *addr;
992f48a0 1606 abi_long ret;
1be9e1dc 1607
8fea3602
AJ
1608 if (target_addr == 0)
1609 return get_errno(accept(fd, NULL, NULL));
1610
2f619698
FB
1611 if (get_user_u32(addrlen, target_addrlen_addr))
1612 return -TARGET_EFAULT;
1613
be09ac41 1614 if (addrlen < 0)
8f7aeaf6
AJ
1615 return -TARGET_EINVAL;
1616
2f619698
FB
1617 addr = alloca(addrlen);
1618
1be9e1dc
PB
1619 ret = get_errno(getsockname(fd, addr, &addrlen));
1620 if (!is_error(ret)) {
1621 host_to_target_sockaddr(target_addr, addr, addrlen);
2f619698
FB
1622 if (put_user_u32(addrlen, target_addrlen_addr))
1623 ret = -TARGET_EFAULT;
1be9e1dc
PB
1624 }
1625 return ret;
1626}
1627
0da46a6e 1628/* do_socketpair() Must return target values and target errnos. */
992f48a0 1629static abi_long do_socketpair(int domain, int type, int protocol,
2f619698 1630 abi_ulong target_tab_addr)
1be9e1dc
PB
1631{
1632 int tab[2];
992f48a0 1633 abi_long ret;
1be9e1dc
PB
1634
1635 ret = get_errno(socketpair(domain, type, protocol, tab));
1636 if (!is_error(ret)) {
2f619698
FB
1637 if (put_user_s32(tab[0], target_tab_addr)
1638 || put_user_s32(tab[1], target_tab_addr + sizeof(tab[0])))
1639 ret = -TARGET_EFAULT;
1be9e1dc
PB
1640 }
1641 return ret;
1642}
1643
0da46a6e 1644/* do_sendto() Must return target values and target errnos. */
992f48a0
BS
1645static abi_long do_sendto(int fd, abi_ulong msg, size_t len, int flags,
1646 abi_ulong target_addr, socklen_t addrlen)
1be9e1dc
PB
1647{
1648 void *addr;
1649 void *host_msg;
992f48a0 1650 abi_long ret;
1be9e1dc 1651
be09ac41 1652 if (addrlen < 0)
8f7aeaf6
AJ
1653 return -TARGET_EINVAL;
1654
579a97f7
FB
1655 host_msg = lock_user(VERIFY_READ, msg, len, 1);
1656 if (!host_msg)
1657 return -TARGET_EFAULT;
1be9e1dc
PB
1658 if (target_addr) {
1659 addr = alloca(addrlen);
1660 target_to_host_sockaddr(addr, target_addr, addrlen);
1661 ret = get_errno(sendto(fd, host_msg, len, flags, addr, addrlen));
1662 } else {
1663 ret = get_errno(send(fd, host_msg, len, flags));
1664 }
1665 unlock_user(host_msg, msg, 0);
1666 return ret;
1667}
1668
0da46a6e 1669/* do_recvfrom() Must return target values and target errnos. */
992f48a0
BS
1670static abi_long do_recvfrom(int fd, abi_ulong msg, size_t len, int flags,
1671 abi_ulong target_addr,
1672 abi_ulong target_addrlen)
1be9e1dc
PB
1673{
1674 socklen_t addrlen;
1675 void *addr;
1676 void *host_msg;
992f48a0 1677 abi_long ret;
1be9e1dc 1678
579a97f7
FB
1679 host_msg = lock_user(VERIFY_WRITE, msg, len, 0);
1680 if (!host_msg)
1681 return -TARGET_EFAULT;
1be9e1dc 1682 if (target_addr) {
2f619698
FB
1683 if (get_user_u32(addrlen, target_addrlen)) {
1684 ret = -TARGET_EFAULT;
1685 goto fail;
1686 }
be09ac41 1687 if (addrlen < 0) {
8f7aeaf6
AJ
1688 ret = -TARGET_EINVAL;
1689 goto fail;
1690 }
1be9e1dc
PB
1691 addr = alloca(addrlen);
1692 ret = get_errno(recvfrom(fd, host_msg, len, flags, addr, &addrlen));
1693 } else {
1694 addr = NULL; /* To keep compiler quiet. */
1695 ret = get_errno(recv(fd, host_msg, len, flags));
1696 }
1697 if (!is_error(ret)) {
1698 if (target_addr) {
1699 host_to_target_sockaddr(target_addr, addr, addrlen);
2f619698
FB
1700 if (put_user_u32(addrlen, target_addrlen)) {
1701 ret = -TARGET_EFAULT;
1702 goto fail;
1703 }
1be9e1dc
PB
1704 }
1705 unlock_user(host_msg, msg, len);
1706 } else {
2f619698 1707fail:
1be9e1dc
PB
1708 unlock_user(host_msg, msg, 0);
1709 }
1710 return ret;
1711}
1712
32407103 1713#ifdef TARGET_NR_socketcall
0da46a6e 1714/* do_socketcall() Must return target values and target errnos. */
992f48a0 1715static abi_long do_socketcall(int num, abi_ulong vptr)
31e31b8a 1716{
992f48a0
BS
1717 abi_long ret;
1718 const int n = sizeof(abi_ulong);
31e31b8a
FB
1719
1720 switch(num) {
1721 case SOCKOP_socket:
7854b056 1722 {
2f619698
FB
1723 int domain, type, protocol;
1724
1725 if (get_user_s32(domain, vptr)
1726 || get_user_s32(type, vptr + n)
1727 || get_user_s32(protocol, vptr + 2 * n))
1728 return -TARGET_EFAULT;
1729
3532fa74 1730 ret = do_socket(domain, type, protocol);
7854b056 1731 }
31e31b8a
FB
1732 break;
1733 case SOCKOP_bind:
7854b056 1734 {
2f619698
FB
1735 int sockfd;
1736 abi_ulong target_addr;
1737 socklen_t addrlen;
1738
1739 if (get_user_s32(sockfd, vptr)
1740 || get_user_ual(target_addr, vptr + n)
1741 || get_user_u32(addrlen, vptr + 2 * n))
1742 return -TARGET_EFAULT;
1743
3532fa74 1744 ret = do_bind(sockfd, target_addr, addrlen);
7854b056 1745 }
31e31b8a
FB
1746 break;
1747 case SOCKOP_connect:
7854b056 1748 {
2f619698
FB
1749 int sockfd;
1750 abi_ulong target_addr;
1751 socklen_t addrlen;
1752
1753 if (get_user_s32(sockfd, vptr)
1754 || get_user_ual(target_addr, vptr + n)
1755 || get_user_u32(addrlen, vptr + 2 * n))
1756 return -TARGET_EFAULT;
1757
3532fa74 1758 ret = do_connect(sockfd, target_addr, addrlen);
7854b056 1759 }
31e31b8a
FB
1760 break;
1761 case SOCKOP_listen:
7854b056 1762 {
2f619698
FB
1763 int sockfd, backlog;
1764
1765 if (get_user_s32(sockfd, vptr)
1766 || get_user_s32(backlog, vptr + n))
1767 return -TARGET_EFAULT;
1768
7854b056
FB
1769 ret = get_errno(listen(sockfd, backlog));
1770 }
31e31b8a
FB
1771 break;
1772 case SOCKOP_accept:
1773 {
2f619698
FB
1774 int sockfd;
1775 abi_ulong target_addr, target_addrlen;
1776
1777 if (get_user_s32(sockfd, vptr)
1778 || get_user_ual(target_addr, vptr + n)
1779 || get_user_u32(target_addrlen, vptr + 2 * n))
1780 return -TARGET_EFAULT;
1781
1be9e1dc 1782 ret = do_accept(sockfd, target_addr, target_addrlen);
31e31b8a
FB
1783 }
1784 break;
1785 case SOCKOP_getsockname:
1786 {
2f619698
FB
1787 int sockfd;
1788 abi_ulong target_addr, target_addrlen;
1789
1790 if (get_user_s32(sockfd, vptr)
1791 || get_user_ual(target_addr, vptr + n)
1792 || get_user_u32(target_addrlen, vptr + 2 * n))
1793 return -TARGET_EFAULT;
1794
1be9e1dc 1795 ret = do_getsockname(sockfd, target_addr, target_addrlen);
31e31b8a
FB
1796 }
1797 break;
1798 case SOCKOP_getpeername:
1799 {
2f619698
FB
1800 int sockfd;
1801 abi_ulong target_addr, target_addrlen;
1802
1803 if (get_user_s32(sockfd, vptr)
1804 || get_user_ual(target_addr, vptr + n)
1805 || get_user_u32(target_addrlen, vptr + 2 * n))
1806 return -TARGET_EFAULT;
1807
1be9e1dc 1808 ret = do_getpeername(sockfd, target_addr, target_addrlen);
31e31b8a
FB
1809 }
1810 break;
1811 case SOCKOP_socketpair:
1812 {
2f619698
FB
1813 int domain, type, protocol;
1814 abi_ulong tab;
1815
1816 if (get_user_s32(domain, vptr)
1817 || get_user_s32(type, vptr + n)
1818 || get_user_s32(protocol, vptr + 2 * n)
1819 || get_user_ual(tab, vptr + 3 * n))
1820 return -TARGET_EFAULT;
1821
1be9e1dc 1822 ret = do_socketpair(domain, type, protocol, tab);
31e31b8a
FB
1823 }
1824 break;
1825 case SOCKOP_send:
7854b056 1826 {
2f619698
FB
1827 int sockfd;
1828 abi_ulong msg;
1829 size_t len;
1830 int flags;
1831
1832 if (get_user_s32(sockfd, vptr)
1833 || get_user_ual(msg, vptr + n)
1834 || get_user_ual(len, vptr + 2 * n)
1835 || get_user_s32(flags, vptr + 3 * n))
1836 return -TARGET_EFAULT;
1837
1be9e1dc 1838 ret = do_sendto(sockfd, msg, len, flags, 0, 0);
7854b056 1839 }
31e31b8a
FB
1840 break;
1841 case SOCKOP_recv:
7854b056 1842 {
2f619698
FB
1843 int sockfd;
1844 abi_ulong msg;
1845 size_t len;
1846 int flags;
1847
1848 if (get_user_s32(sockfd, vptr)
1849 || get_user_ual(msg, vptr + n)
1850 || get_user_ual(len, vptr + 2 * n)
1851 || get_user_s32(flags, vptr + 3 * n))
1852 return -TARGET_EFAULT;
1853
1be9e1dc 1854 ret = do_recvfrom(sockfd, msg, len, flags, 0, 0);
7854b056 1855 }
31e31b8a
FB
1856 break;
1857 case SOCKOP_sendto:
7854b056 1858 {
2f619698
FB
1859 int sockfd;
1860 abi_ulong msg;
1861 size_t len;
1862 int flags;
1863 abi_ulong addr;
1864 socklen_t addrlen;
1865
1866 if (get_user_s32(sockfd, vptr)
1867 || get_user_ual(msg, vptr + n)
1868 || get_user_ual(len, vptr + 2 * n)
1869 || get_user_s32(flags, vptr + 3 * n)
1870 || get_user_ual(addr, vptr + 4 * n)
1871 || get_user_u32(addrlen, vptr + 5 * n))
1872 return -TARGET_EFAULT;
1873
1be9e1dc 1874 ret = do_sendto(sockfd, msg, len, flags, addr, addrlen);
7854b056 1875 }
31e31b8a
FB
1876 break;
1877 case SOCKOP_recvfrom:
1878 {
2f619698
FB
1879 int sockfd;
1880 abi_ulong msg;
1881 size_t len;
1882 int flags;
1883 abi_ulong addr;
1884 socklen_t addrlen;
1885
1886 if (get_user_s32(sockfd, vptr)
1887 || get_user_ual(msg, vptr + n)
1888 || get_user_ual(len, vptr + 2 * n)
1889 || get_user_s32(flags, vptr + 3 * n)
1890 || get_user_ual(addr, vptr + 4 * n)
1891 || get_user_u32(addrlen, vptr + 5 * n))
1892 return -TARGET_EFAULT;
1893
1be9e1dc 1894 ret = do_recvfrom(sockfd, msg, len, flags, addr, addrlen);
31e31b8a
FB
1895 }
1896 break;
1897 case SOCKOP_shutdown:
7854b056 1898 {
2f619698
FB
1899 int sockfd, how;
1900
1901 if (get_user_s32(sockfd, vptr)
1902 || get_user_s32(how, vptr + n))
1903 return -TARGET_EFAULT;
7854b056
FB
1904
1905 ret = get_errno(shutdown(sockfd, how));
1906 }
31e31b8a
FB
1907 break;
1908 case SOCKOP_sendmsg:
1909 case SOCKOP_recvmsg:
1a9353d2
FB
1910 {
1911 int fd;
992f48a0 1912 abi_ulong target_msg;
3532fa74 1913 int flags;
1a9353d2 1914
2f619698
FB
1915 if (get_user_s32(fd, vptr)
1916 || get_user_ual(target_msg, vptr + n)
1917 || get_user_s32(flags, vptr + 2 * n))
1918 return -TARGET_EFAULT;
3532fa74 1919
5fafdf24 1920 ret = do_sendrecvmsg(fd, target_msg, flags,
3532fa74 1921 (num == SOCKOP_sendmsg));
1a9353d2
FB
1922 }
1923 break;
31e31b8a 1924 case SOCKOP_setsockopt:
7854b056 1925 {
2f619698
FB
1926 int sockfd;
1927 int level;
1928 int optname;
1929 abi_ulong optval;
1930 socklen_t optlen;
1931
1932 if (get_user_s32(sockfd, vptr)
1933 || get_user_s32(level, vptr + n)
1934 || get_user_s32(optname, vptr + 2 * n)
1935 || get_user_ual(optval, vptr + 3 * n)
1936 || get_user_u32(optlen, vptr + 4 * n))
1937 return -TARGET_EFAULT;
7854b056
FB
1938
1939 ret = do_setsockopt(sockfd, level, optname, optval, optlen);
1940 }
1941 break;
31e31b8a 1942 case SOCKOP_getsockopt:
7854b056 1943 {
2f619698
FB
1944 int sockfd;
1945 int level;
1946 int optname;
1947 abi_ulong optval;
1948 socklen_t optlen;
1949
1950 if (get_user_s32(sockfd, vptr)
1951 || get_user_s32(level, vptr + n)
1952 || get_user_s32(optname, vptr + 2 * n)
1953 || get_user_ual(optval, vptr + 3 * n)
1954 || get_user_u32(optlen, vptr + 4 * n))
1955 return -TARGET_EFAULT;
7854b056 1956
2f619698 1957 ret = do_getsockopt(sockfd, level, optname, optval, optlen);
7854b056
FB
1958 }
1959 break;
31e31b8a
FB
1960 default:
1961 gemu_log("Unsupported socketcall: %d\n", num);
0da46a6e 1962 ret = -TARGET_ENOSYS;
31e31b8a
FB
1963 break;
1964 }
1965 return ret;
1966}
32407103 1967#endif
31e31b8a 1968
8853f86e
FB
1969#define N_SHM_REGIONS 32
1970
1971static struct shm_region {
5a4a898d
FB
1972 abi_ulong start;
1973 abi_ulong size;
8853f86e
FB
1974} shm_regions[N_SHM_REGIONS];
1975
3eb6b044
TS
1976struct target_ipc_perm
1977{
992f48a0
BS
1978 abi_long __key;
1979 abi_ulong uid;
1980 abi_ulong gid;
1981 abi_ulong cuid;
1982 abi_ulong cgid;
3eb6b044
TS
1983 unsigned short int mode;
1984 unsigned short int __pad1;
1985 unsigned short int __seq;
1986 unsigned short int __pad2;
992f48a0
BS
1987 abi_ulong __unused1;
1988 abi_ulong __unused2;
3eb6b044
TS
1989};
1990
1991struct target_semid_ds
1992{
1993 struct target_ipc_perm sem_perm;
992f48a0
BS
1994 abi_ulong sem_otime;
1995 abi_ulong __unused1;
1996 abi_ulong sem_ctime;
1997 abi_ulong __unused2;
1998 abi_ulong sem_nsems;
1999 abi_ulong __unused3;
2000 abi_ulong __unused4;
3eb6b044
TS
2001};
2002
579a97f7
FB
2003static inline abi_long target_to_host_ipc_perm(struct ipc_perm *host_ip,
2004 abi_ulong target_addr)
3eb6b044
TS
2005{
2006 struct target_ipc_perm *target_ip;
2007 struct target_semid_ds *target_sd;
2008
579a97f7
FB
2009 if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
2010 return -TARGET_EFAULT;
3eb6b044
TS
2011 target_ip=&(target_sd->sem_perm);
2012 host_ip->__key = tswapl(target_ip->__key);
2013 host_ip->uid = tswapl(target_ip->uid);
2014 host_ip->gid = tswapl(target_ip->gid);
2015 host_ip->cuid = tswapl(target_ip->cuid);
2016 host_ip->cgid = tswapl(target_ip->cgid);
2017 host_ip->mode = tswapl(target_ip->mode);
2018 unlock_user_struct(target_sd, target_addr, 0);
579a97f7 2019 return 0;
3eb6b044
TS
2020}
2021
579a97f7
FB
2022static inline abi_long host_to_target_ipc_perm(abi_ulong target_addr,
2023 struct ipc_perm *host_ip)
3eb6b044
TS
2024{
2025 struct target_ipc_perm *target_ip;
2026 struct target_semid_ds *target_sd;
2027
579a97f7
FB
2028 if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
2029 return -TARGET_EFAULT;
3eb6b044
TS
2030 target_ip = &(target_sd->sem_perm);
2031 target_ip->__key = tswapl(host_ip->__key);
2032 target_ip->uid = tswapl(host_ip->uid);
2033 target_ip->gid = tswapl(host_ip->gid);
2034 target_ip->cuid = tswapl(host_ip->cuid);
2035 target_ip->cgid = tswapl(host_ip->cgid);
2036 target_ip->mode = tswapl(host_ip->mode);
2037 unlock_user_struct(target_sd, target_addr, 1);
579a97f7 2038 return 0;
3eb6b044
TS
2039}
2040
579a97f7
FB
2041static inline abi_long target_to_host_semid_ds(struct semid_ds *host_sd,
2042 abi_ulong target_addr)
3eb6b044
TS
2043{
2044 struct target_semid_ds *target_sd;
2045
579a97f7
FB
2046 if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
2047 return -TARGET_EFAULT;
e5289087
AJ
2048 if (target_to_host_ipc_perm(&(host_sd->sem_perm),target_addr))
2049 return -TARGET_EFAULT;
3eb6b044
TS
2050 host_sd->sem_nsems = tswapl(target_sd->sem_nsems);
2051 host_sd->sem_otime = tswapl(target_sd->sem_otime);
2052 host_sd->sem_ctime = tswapl(target_sd->sem_ctime);
2053 unlock_user_struct(target_sd, target_addr, 0);
579a97f7 2054 return 0;
3eb6b044
TS
2055}
2056
579a97f7
FB
2057static inline abi_long host_to_target_semid_ds(abi_ulong target_addr,
2058 struct semid_ds *host_sd)
3eb6b044
TS
2059{
2060 struct target_semid_ds *target_sd;
2061
579a97f7
FB
2062 if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
2063 return -TARGET_EFAULT;
e5289087
AJ
2064 if (host_to_target_ipc_perm(target_addr,&(host_sd->sem_perm)))
2065 return -TARGET_EFAULT;;
3eb6b044
TS
2066 target_sd->sem_nsems = tswapl(host_sd->sem_nsems);
2067 target_sd->sem_otime = tswapl(host_sd->sem_otime);
2068 target_sd->sem_ctime = tswapl(host_sd->sem_ctime);
2069 unlock_user_struct(target_sd, target_addr, 1);
579a97f7 2070 return 0;
3eb6b044
TS
2071}
2072
e5289087
AJ
2073struct target_seminfo {
2074 int semmap;
2075 int semmni;
2076 int semmns;
2077 int semmnu;
2078 int semmsl;
2079 int semopm;
2080 int semume;
2081 int semusz;
2082 int semvmx;
2083 int semaem;
2084};
2085
2086static inline abi_long host_to_target_seminfo(abi_ulong target_addr,
2087 struct seminfo *host_seminfo)
2088{
2089 struct target_seminfo *target_seminfo;
2090 if (!lock_user_struct(VERIFY_WRITE, target_seminfo, target_addr, 0))
2091 return -TARGET_EFAULT;
2092 __put_user(host_seminfo->semmap, &target_seminfo->semmap);
2093 __put_user(host_seminfo->semmni, &target_seminfo->semmni);
2094 __put_user(host_seminfo->semmns, &target_seminfo->semmns);
2095 __put_user(host_seminfo->semmnu, &target_seminfo->semmnu);
2096 __put_user(host_seminfo->semmsl, &target_seminfo->semmsl);
2097 __put_user(host_seminfo->semopm, &target_seminfo->semopm);
2098 __put_user(host_seminfo->semume, &target_seminfo->semume);
2099 __put_user(host_seminfo->semusz, &target_seminfo->semusz);
2100 __put_user(host_seminfo->semvmx, &target_seminfo->semvmx);
2101 __put_user(host_seminfo->semaem, &target_seminfo->semaem);
2102 unlock_user_struct(target_seminfo, target_addr, 1);
2103 return 0;
2104}
2105
fa294816
TS
2106union semun {
2107 int val;
3eb6b044 2108 struct semid_ds *buf;
fa294816 2109 unsigned short *array;
e5289087 2110 struct seminfo *__buf;
fa294816
TS
2111};
2112
3eb6b044
TS
2113union target_semun {
2114 int val;
e5289087
AJ
2115 abi_ulong buf;
2116 abi_ulong array;
2117 abi_ulong __buf;
3eb6b044
TS
2118};
2119
e5289087
AJ
2120static inline abi_long target_to_host_semarray(int semid, unsigned short **host_array,
2121 abi_ulong target_addr)
3eb6b044 2122{
e5289087
AJ
2123 int nsems;
2124 unsigned short *array;
2125 union semun semun;
2126 struct semid_ds semid_ds;
2127 int i, ret;
3eb6b044 2128
e5289087
AJ
2129 semun.buf = &semid_ds;
2130
2131 ret = semctl(semid, 0, IPC_STAT, semun);
2132 if (ret == -1)
2133 return get_errno(ret);
2134
2135 nsems = semid_ds.sem_nsems;
2136
2137 *host_array = malloc(nsems*sizeof(unsigned short));
2138 array = lock_user(VERIFY_READ, target_addr,
2139 nsems*sizeof(unsigned short), 1);
2140 if (!array)
2141 return -TARGET_EFAULT;
2142
2143 for(i=0; i<nsems; i++) {
2144 __get_user((*host_array)[i], &array[i]);
3eb6b044 2145 }
e5289087
AJ
2146 unlock_user(array, target_addr, 0);
2147
579a97f7 2148 return 0;
3eb6b044
TS
2149}
2150
e5289087
AJ
2151static inline abi_long host_to_target_semarray(int semid, abi_ulong target_addr,
2152 unsigned short **host_array)
3eb6b044 2153{
e5289087
AJ
2154 int nsems;
2155 unsigned short *array;
2156 union semun semun;
2157 struct semid_ds semid_ds;
2158 int i, ret;
3eb6b044 2159
e5289087
AJ
2160 semun.buf = &semid_ds;
2161
2162 ret = semctl(semid, 0, IPC_STAT, semun);
2163 if (ret == -1)
2164 return get_errno(ret);
2165
2166 nsems = semid_ds.sem_nsems;
2167
2168 array = lock_user(VERIFY_WRITE, target_addr,
2169 nsems*sizeof(unsigned short), 0);
2170 if (!array)
2171 return -TARGET_EFAULT;
2172
2173 for(i=0; i<nsems; i++) {
2174 __put_user((*host_array)[i], &array[i]);
3eb6b044 2175 }
e5289087
AJ
2176 free(*host_array);
2177 unlock_user(array, target_addr, 1);
2178
579a97f7 2179 return 0;
3eb6b044
TS
2180}
2181
e5289087
AJ
2182static inline abi_long do_semctl(int semid, int semnum, int cmd,
2183 union target_semun target_su)
3eb6b044
TS
2184{
2185 union semun arg;
2186 struct semid_ds dsarg;
e5289087
AJ
2187 unsigned short *array;
2188 struct seminfo seminfo;
2189 abi_long ret = -TARGET_EINVAL;
2190 abi_long err;
2191 cmd &= 0xff;
3eb6b044
TS
2192
2193 switch( cmd ) {
2194 case GETVAL:
3eb6b044 2195 case SETVAL:
e5289087
AJ
2196 arg.val = tswapl(target_su.val);
2197 ret = get_errno(semctl(semid, semnum, cmd, arg));
2198 target_su.val = tswapl(arg.val);
3eb6b044
TS
2199 break;
2200 case GETALL:
3eb6b044 2201 case SETALL:
e5289087
AJ
2202 err = target_to_host_semarray(semid, &array, target_su.array);
2203 if (err)
2204 return err;
2205 arg.array = array;
2206 ret = get_errno(semctl(semid, semnum, cmd, arg));
2207 err = host_to_target_semarray(semid, target_su.array, &array);
2208 if (err)
2209 return err;
3eb6b044
TS
2210 break;
2211 case IPC_STAT:
3eb6b044 2212 case IPC_SET:
e5289087
AJ
2213 case SEM_STAT:
2214 err = target_to_host_semid_ds(&dsarg, target_su.buf);
2215 if (err)
2216 return err;
2217 arg.buf = &dsarg;
2218 ret = get_errno(semctl(semid, semnum, cmd, arg));
2219 err = host_to_target_semid_ds(target_su.buf, &dsarg);
2220 if (err)
2221 return err;
2222 break;
2223 case IPC_INFO:
2224 case SEM_INFO:
2225 arg.__buf = &seminfo;
2226 ret = get_errno(semctl(semid, semnum, cmd, arg));
2227 err = host_to_target_seminfo(target_su.__buf, &seminfo);
2228 if (err)
2229 return err;
2230 break;
2231 case IPC_RMID:
2232 case GETPID:
2233 case GETNCNT:
2234 case GETZCNT:
2235 ret = get_errno(semctl(semid, semnum, cmd, NULL));
3eb6b044 2236 break;
3eb6b044
TS
2237 }
2238
2239 return ret;
2240}
2241
e5289087
AJ
2242struct target_sembuf {
2243 unsigned short sem_num;
2244 short sem_op;
2245 short sem_flg;
2246};
2247
2248static inline abi_long target_to_host_sembuf(struct sembuf *host_sembuf,
2249 abi_ulong target_addr,
2250 unsigned nsops)
2251{
2252 struct target_sembuf *target_sembuf;
2253 int i;
2254
2255 target_sembuf = lock_user(VERIFY_READ, target_addr,
2256 nsops*sizeof(struct target_sembuf), 1);
2257 if (!target_sembuf)
2258 return -TARGET_EFAULT;
2259
2260 for(i=0; i<nsops; i++) {
2261 __get_user(host_sembuf[i].sem_num, &target_sembuf[i].sem_num);
2262 __get_user(host_sembuf[i].sem_op, &target_sembuf[i].sem_op);
2263 __get_user(host_sembuf[i].sem_flg, &target_sembuf[i].sem_flg);
2264 }
2265
2266 unlock_user(target_sembuf, target_addr, 0);
2267
2268 return 0;
2269}
2270
2271static inline abi_long do_semop(int semid, abi_long ptr, unsigned nsops)
2272{
2273 struct sembuf sops[nsops];
2274
2275 if (target_to_host_sembuf(sops, ptr, nsops))
2276 return -TARGET_EFAULT;
2277
2278 return semop(semid, sops, nsops);
2279}
2280
1bc012f6
TS
2281struct target_msqid_ds
2282{
1c54ff97
AJ
2283 struct target_ipc_perm msg_perm;
2284 abi_ulong msg_stime;
2285#if TARGET_ABI_BITS == 32
2286 abi_ulong __unused1;
2287#endif
2288 abi_ulong msg_rtime;
2289#if TARGET_ABI_BITS == 32
2290 abi_ulong __unused2;
2291#endif
2292 abi_ulong msg_ctime;
2293#if TARGET_ABI_BITS == 32
2294 abi_ulong __unused3;
2295#endif
2296 abi_ulong __msg_cbytes;
2297 abi_ulong msg_qnum;
2298 abi_ulong msg_qbytes;
2299 abi_ulong msg_lspid;
2300 abi_ulong msg_lrpid;
2301 abi_ulong __unused4;
2302 abi_ulong __unused5;
1bc012f6
TS
2303};
2304
579a97f7
FB
2305static inline abi_long target_to_host_msqid_ds(struct msqid_ds *host_md,
2306 abi_ulong target_addr)
1bc012f6
TS
2307{
2308 struct target_msqid_ds *target_md;
2309
579a97f7
FB
2310 if (!lock_user_struct(VERIFY_READ, target_md, target_addr, 1))
2311 return -TARGET_EFAULT;
1c54ff97
AJ
2312 if (target_to_host_ipc_perm(&(host_md->msg_perm),target_addr))
2313 return -TARGET_EFAULT;
1bc012f6
TS
2314 host_md->msg_stime = tswapl(target_md->msg_stime);
2315 host_md->msg_rtime = tswapl(target_md->msg_rtime);
2316 host_md->msg_ctime = tswapl(target_md->msg_ctime);
2317 host_md->__msg_cbytes = tswapl(target_md->__msg_cbytes);
2318 host_md->msg_qnum = tswapl(target_md->msg_qnum);
2319 host_md->msg_qbytes = tswapl(target_md->msg_qbytes);
2320 host_md->msg_lspid = tswapl(target_md->msg_lspid);
2321 host_md->msg_lrpid = tswapl(target_md->msg_lrpid);
2322 unlock_user_struct(target_md, target_addr, 0);
579a97f7 2323 return 0;
1bc012f6
TS
2324}
2325
579a97f7
FB
2326static inline abi_long host_to_target_msqid_ds(abi_ulong target_addr,
2327 struct msqid_ds *host_md)
1bc012f6
TS
2328{
2329 struct target_msqid_ds *target_md;
2330
579a97f7
FB
2331 if (!lock_user_struct(VERIFY_WRITE, target_md, target_addr, 0))
2332 return -TARGET_EFAULT;
1c54ff97
AJ
2333 if (host_to_target_ipc_perm(target_addr,&(host_md->msg_perm)))
2334 return -TARGET_EFAULT;
1bc012f6
TS
2335 target_md->msg_stime = tswapl(host_md->msg_stime);
2336 target_md->msg_rtime = tswapl(host_md->msg_rtime);
2337 target_md->msg_ctime = tswapl(host_md->msg_ctime);
2338 target_md->__msg_cbytes = tswapl(host_md->__msg_cbytes);
2339 target_md->msg_qnum = tswapl(host_md->msg_qnum);
2340 target_md->msg_qbytes = tswapl(host_md->msg_qbytes);
2341 target_md->msg_lspid = tswapl(host_md->msg_lspid);
2342 target_md->msg_lrpid = tswapl(host_md->msg_lrpid);
2343 unlock_user_struct(target_md, target_addr, 1);
579a97f7 2344 return 0;
1bc012f6
TS
2345}
2346
1c54ff97
AJ
2347struct target_msginfo {
2348 int msgpool;
2349 int msgmap;
2350 int msgmax;
2351 int msgmnb;
2352 int msgmni;
2353 int msgssz;
2354 int msgtql;
2355 unsigned short int msgseg;
2356};
2357
2358static inline abi_long host_to_target_msginfo(abi_ulong target_addr,
2359 struct msginfo *host_msginfo)
2360{
2361 struct target_msginfo *target_msginfo;
2362 if (!lock_user_struct(VERIFY_WRITE, target_msginfo, target_addr, 0))
2363 return -TARGET_EFAULT;
2364 __put_user(host_msginfo->msgpool, &target_msginfo->msgpool);
2365 __put_user(host_msginfo->msgmap, &target_msginfo->msgmap);
2366 __put_user(host_msginfo->msgmax, &target_msginfo->msgmax);
2367 __put_user(host_msginfo->msgmnb, &target_msginfo->msgmnb);
2368 __put_user(host_msginfo->msgmni, &target_msginfo->msgmni);
2369 __put_user(host_msginfo->msgssz, &target_msginfo->msgssz);
2370 __put_user(host_msginfo->msgtql, &target_msginfo->msgtql);
2371 __put_user(host_msginfo->msgseg, &target_msginfo->msgseg);
2372 unlock_user_struct(target_msginfo, target_addr, 1);
00b229ac 2373 return 0;
1c54ff97
AJ
2374}
2375
2376static inline abi_long do_msgctl(int msgid, int cmd, abi_long ptr)
1bc012f6
TS
2377{
2378 struct msqid_ds dsarg;
1c54ff97
AJ
2379 struct msginfo msginfo;
2380 abi_long ret = -TARGET_EINVAL;
2381
2382 cmd &= 0xff;
2383
2384 switch (cmd) {
1bc012f6
TS
2385 case IPC_STAT:
2386 case IPC_SET:
1c54ff97
AJ
2387 case MSG_STAT:
2388 if (target_to_host_msqid_ds(&dsarg,ptr))
2389 return -TARGET_EFAULT;
2390 ret = get_errno(msgctl(msgid, cmd, &dsarg));
2391 if (host_to_target_msqid_ds(ptr,&dsarg))
2392 return -TARGET_EFAULT;
2393 break;
2394 case IPC_RMID:
2395 ret = get_errno(msgctl(msgid, cmd, NULL));
2396 break;
2397 case IPC_INFO:
2398 case MSG_INFO:
2399 ret = get_errno(msgctl(msgid, cmd, (struct msqid_ds *)&msginfo));
2400 if (host_to_target_msginfo(ptr, &msginfo))
2401 return -TARGET_EFAULT;
2402 break;
1bc012f6 2403 }
1c54ff97 2404
1bc012f6
TS
2405 return ret;
2406}
2407
2408struct target_msgbuf {
1c54ff97
AJ
2409 abi_long mtype;
2410 char mtext[1];
1bc012f6
TS
2411};
2412
992f48a0
BS
2413static inline abi_long do_msgsnd(int msqid, abi_long msgp,
2414 unsigned int msgsz, int msgflg)
1bc012f6
TS
2415{
2416 struct target_msgbuf *target_mb;
2417 struct msgbuf *host_mb;
992f48a0 2418 abi_long ret = 0;
1bc012f6 2419
579a97f7
FB
2420 if (!lock_user_struct(VERIFY_READ, target_mb, msgp, 0))
2421 return -TARGET_EFAULT;
1bc012f6 2422 host_mb = malloc(msgsz+sizeof(long));
1c54ff97
AJ
2423 host_mb->mtype = (abi_long) tswapl(target_mb->mtype);
2424 memcpy(host_mb->mtext, target_mb->mtext, msgsz);
1bc012f6
TS
2425 ret = get_errno(msgsnd(msqid, host_mb, msgsz, msgflg));
2426 free(host_mb);
2427 unlock_user_struct(target_mb, msgp, 0);
2428
2429 return ret;
2430}
2431
992f48a0 2432static inline abi_long do_msgrcv(int msqid, abi_long msgp,
1c54ff97 2433 unsigned int msgsz, abi_long msgtyp,
992f48a0 2434 int msgflg)
1bc012f6
TS
2435{
2436 struct target_msgbuf *target_mb;
579a97f7 2437 char *target_mtext;
1bc012f6 2438 struct msgbuf *host_mb;
992f48a0 2439 abi_long ret = 0;
1bc012f6 2440
579a97f7
FB
2441 if (!lock_user_struct(VERIFY_WRITE, target_mb, msgp, 0))
2442 return -TARGET_EFAULT;
1c54ff97 2443
1bc012f6 2444 host_mb = malloc(msgsz+sizeof(long));
1c54ff97
AJ
2445 ret = get_errno(msgrcv(msqid, host_mb, msgsz, tswapl(msgtyp), msgflg));
2446
579a97f7
FB
2447 if (ret > 0) {
2448 abi_ulong target_mtext_addr = msgp + sizeof(abi_ulong);
2449 target_mtext = lock_user(VERIFY_WRITE, target_mtext_addr, ret, 0);
2450 if (!target_mtext) {
2451 ret = -TARGET_EFAULT;
2452 goto end;
2453 }
1c54ff97 2454 memcpy(target_mb->mtext, host_mb->mtext, ret);
579a97f7
FB
2455 unlock_user(target_mtext, target_mtext_addr, ret);
2456 }
1c54ff97 2457
1bc012f6
TS
2458 target_mb->mtype = tswapl(host_mb->mtype);
2459 free(host_mb);
1bc012f6 2460
579a97f7
FB
2461end:
2462 if (target_mb)
2463 unlock_user_struct(target_mb, msgp, 1);
1bc012f6
TS
2464 return ret;
2465}
2466
88a8c984
RV
2467struct target_shmid_ds
2468{
2469 struct target_ipc_perm shm_perm;
2470 abi_ulong shm_segsz;
2471 abi_ulong shm_atime;
2472#if TARGET_ABI_BITS == 32
2473 abi_ulong __unused1;
2474#endif
2475 abi_ulong shm_dtime;
2476#if TARGET_ABI_BITS == 32
2477 abi_ulong __unused2;
2478#endif
2479 abi_ulong shm_ctime;
2480#if TARGET_ABI_BITS == 32
2481 abi_ulong __unused3;
2482#endif
2483 int shm_cpid;
2484 int shm_lpid;
2485 abi_ulong shm_nattch;
2486 unsigned long int __unused4;
2487 unsigned long int __unused5;
2488};
2489
2490static inline abi_long target_to_host_shmid_ds(struct shmid_ds *host_sd,
2491 abi_ulong target_addr)
2492{
2493 struct target_shmid_ds *target_sd;
2494
2495 if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
2496 return -TARGET_EFAULT;
2497 if (target_to_host_ipc_perm(&(host_sd->shm_perm), target_addr))
2498 return -TARGET_EFAULT;
2499 __get_user(host_sd->shm_segsz, &target_sd->shm_segsz);
2500 __get_user(host_sd->shm_atime, &target_sd->shm_atime);
2501 __get_user(host_sd->shm_dtime, &target_sd->shm_dtime);
2502 __get_user(host_sd->shm_ctime, &target_sd->shm_ctime);
2503 __get_user(host_sd->shm_cpid, &target_sd->shm_cpid);
2504 __get_user(host_sd->shm_lpid, &target_sd->shm_lpid);
2505 __get_user(host_sd->shm_nattch, &target_sd->shm_nattch);
2506 unlock_user_struct(target_sd, target_addr, 0);
2507 return 0;
2508}
2509
2510static inline abi_long host_to_target_shmid_ds(abi_ulong target_addr,
2511 struct shmid_ds *host_sd)
2512{
2513 struct target_shmid_ds *target_sd;
2514
2515 if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
2516 return -TARGET_EFAULT;
2517 if (host_to_target_ipc_perm(target_addr, &(host_sd->shm_perm)))
2518 return -TARGET_EFAULT;
2519 __put_user(host_sd->shm_segsz, &target_sd->shm_segsz);
2520 __put_user(host_sd->shm_atime, &target_sd->shm_atime);
2521 __put_user(host_sd->shm_dtime, &target_sd->shm_dtime);
2522 __put_user(host_sd->shm_ctime, &target_sd->shm_ctime);
2523 __put_user(host_sd->shm_cpid, &target_sd->shm_cpid);
2524 __put_user(host_sd->shm_lpid, &target_sd->shm_lpid);
2525 __put_user(host_sd->shm_nattch, &target_sd->shm_nattch);
2526 unlock_user_struct(target_sd, target_addr, 1);
2527 return 0;
2528}
2529
2530struct target_shminfo {
2531 abi_ulong shmmax;
2532 abi_ulong shmmin;
2533 abi_ulong shmmni;
2534 abi_ulong shmseg;
2535 abi_ulong shmall;
2536};
2537
2538static inline abi_long host_to_target_shminfo(abi_ulong target_addr,
2539 struct shminfo *host_shminfo)
2540{
2541 struct target_shminfo *target_shminfo;
2542 if (!lock_user_struct(VERIFY_WRITE, target_shminfo, target_addr, 0))
2543 return -TARGET_EFAULT;
2544 __put_user(host_shminfo->shmmax, &target_shminfo->shmmax);
2545 __put_user(host_shminfo->shmmin, &target_shminfo->shmmin);
2546 __put_user(host_shminfo->shmmni, &target_shminfo->shmmni);
2547 __put_user(host_shminfo->shmseg, &target_shminfo->shmseg);
2548 __put_user(host_shminfo->shmall, &target_shminfo->shmall);
2549 unlock_user_struct(target_shminfo, target_addr, 1);
2550 return 0;
2551}
2552
2553struct target_shm_info {
2554 int used_ids;
2555 abi_ulong shm_tot;
2556 abi_ulong shm_rss;
2557 abi_ulong shm_swp;
2558 abi_ulong swap_attempts;
2559 abi_ulong swap_successes;
2560};
2561
2562static inline abi_long host_to_target_shm_info(abi_ulong target_addr,
2563 struct shm_info *host_shm_info)
2564{
2565 struct target_shm_info *target_shm_info;
2566 if (!lock_user_struct(VERIFY_WRITE, target_shm_info, target_addr, 0))
2567 return -TARGET_EFAULT;
2568 __put_user(host_shm_info->used_ids, &target_shm_info->used_ids);
2569 __put_user(host_shm_info->shm_tot, &target_shm_info->shm_tot);
2570 __put_user(host_shm_info->shm_rss, &target_shm_info->shm_rss);
2571 __put_user(host_shm_info->shm_swp, &target_shm_info->shm_swp);
2572 __put_user(host_shm_info->swap_attempts, &target_shm_info->swap_attempts);
2573 __put_user(host_shm_info->swap_successes, &target_shm_info->swap_successes);
2574 unlock_user_struct(target_shm_info, target_addr, 1);
2575 return 0;
2576}
2577
2578static inline abi_long do_shmctl(int shmid, int cmd, abi_long buf)
2579{
2580 struct shmid_ds dsarg;
2581 struct shminfo shminfo;
2582 struct shm_info shm_info;
2583 abi_long ret = -TARGET_EINVAL;
2584
2585 cmd &= 0xff;
2586
2587 switch(cmd) {
2588 case IPC_STAT:
2589 case IPC_SET:
2590 case SHM_STAT:
2591 if (target_to_host_shmid_ds(&dsarg, buf))
2592 return -TARGET_EFAULT;
2593 ret = get_errno(shmctl(shmid, cmd, &dsarg));
2594 if (host_to_target_shmid_ds(buf, &dsarg))
2595 return -TARGET_EFAULT;
2596 break;
2597 case IPC_INFO:
2598 ret = get_errno(shmctl(shmid, cmd, (struct shmid_ds *)&shminfo));
2599 if (host_to_target_shminfo(buf, &shminfo))
2600 return -TARGET_EFAULT;
2601 break;
2602 case SHM_INFO:
2603 ret = get_errno(shmctl(shmid, cmd, (struct shmid_ds *)&shm_info));
2604 if (host_to_target_shm_info(buf, &shm_info))
2605 return -TARGET_EFAULT;
2606 break;
2607 case IPC_RMID:
2608 case SHM_LOCK:
2609 case SHM_UNLOCK:
2610 ret = get_errno(shmctl(shmid, cmd, NULL));
2611 break;
2612 }
2613
2614 return ret;
2615}
2616
2617static inline abi_ulong do_shmat(int shmid, abi_ulong shmaddr, int shmflg)
2618{
2619 abi_long raddr;
2620 void *host_raddr;
2621 struct shmid_ds shm_info;
2622 int i,ret;
2623
2624 /* find out the length of the shared memory segment */
2625 ret = get_errno(shmctl(shmid, IPC_STAT, &shm_info));
2626 if (is_error(ret)) {
2627 /* can't get length, bail out */
2628 return ret;
2629 }
2630
2631 mmap_lock();
2632
2633 if (shmaddr)
2634 host_raddr = shmat(shmid, (void *)g2h(shmaddr), shmflg);
2635 else {
2636 abi_ulong mmap_start;
2637
2638 mmap_start = mmap_find_vma(0, shm_info.shm_segsz);
2639
2640 if (mmap_start == -1) {
2641 errno = ENOMEM;
2642 host_raddr = (void *)-1;
2643 } else
2644 host_raddr = shmat(shmid, g2h(mmap_start), shmflg | SHM_REMAP);
2645 }
2646
2647 if (host_raddr == (void *)-1) {
2648 mmap_unlock();
2649 return get_errno((long)host_raddr);
2650 }
2651 raddr=h2g((unsigned long)host_raddr);
2652
2653 page_set_flags(raddr, raddr + shm_info.shm_segsz,
2654 PAGE_VALID | PAGE_READ |
2655 ((shmflg & SHM_RDONLY)? 0 : PAGE_WRITE));
2656
2657 for (i = 0; i < N_SHM_REGIONS; i++) {
2658 if (shm_regions[i].start == 0) {
2659 shm_regions[i].start = raddr;
2660 shm_regions[i].size = shm_info.shm_segsz;
2661 break;
2662 }
2663 }
2664
2665 mmap_unlock();
2666 return raddr;
2667
2668}
2669
2670static inline abi_long do_shmdt(abi_ulong shmaddr)
2671{
2672 int i;
2673
2674 for (i = 0; i < N_SHM_REGIONS; ++i) {
2675 if (shm_regions[i].start == shmaddr) {
2676 shm_regions[i].start = 0;
2677 page_set_flags(shmaddr, shm_regions[i].size, 0);
2678 break;
2679 }
2680 }
2681
2682 return get_errno(shmdt(g2h(shmaddr)));
2683}
2684
1c54ff97 2685#ifdef TARGET_NR_ipc
53a5960a 2686/* ??? This only works with linear mappings. */
0da46a6e 2687/* do_ipc() must return target values and target errnos. */
992f48a0
BS
2688static abi_long do_ipc(unsigned int call, int first,
2689 int second, int third,
2690 abi_long ptr, abi_long fifth)
8853f86e
FB
2691{
2692 int version;
992f48a0 2693 abi_long ret = 0;
8853f86e
FB
2694
2695 version = call >> 16;
2696 call &= 0xffff;
2697
2698 switch (call) {
fa294816 2699 case IPCOP_semop:
e5289087 2700 ret = do_semop(first, ptr, second);
fa294816
TS
2701 break;
2702
2703 case IPCOP_semget:
2704 ret = get_errno(semget(first, second, third));
2705 break;
2706
2707 case IPCOP_semctl:
e5289087 2708 ret = do_semctl(first, second, third, (union target_semun)(abi_ulong) ptr);
fa294816 2709 break;
d96372ef 2710
1c54ff97
AJ
2711 case IPCOP_msgget:
2712 ret = get_errno(msgget(first, second));
2713 break;
d96372ef 2714
1c54ff97
AJ
2715 case IPCOP_msgsnd:
2716 ret = do_msgsnd(first, ptr, second, third);
2717 break;
d96372ef 2718
1c54ff97
AJ
2719 case IPCOP_msgctl:
2720 ret = do_msgctl(first, second, ptr);
2721 break;
d96372ef 2722
1c54ff97
AJ
2723 case IPCOP_msgrcv:
2724 switch (version) {
2725 case 0:
2726 {
2727 struct target_ipc_kludge {
2728 abi_long msgp;
2729 abi_long msgtyp;
2730 } *tmp;
2731
2732 if (!lock_user_struct(VERIFY_READ, tmp, ptr, 1)) {
2733 ret = -TARGET_EFAULT;
2734 break;
2735 }
d96372ef 2736
1c54ff97 2737 ret = do_msgrcv(first, tmp->msgp, second, tmp->msgtyp, third);
d96372ef 2738
1c54ff97
AJ
2739 unlock_user_struct(tmp, ptr, 0);
2740 break;
2741 }
2742 default:
2743 ret = do_msgrcv(first, ptr, second, fifth, third);
2744 }
2745 break;
d96372ef 2746
8853f86e 2747 case IPCOP_shmat:
88a8c984
RV
2748 switch (version) {
2749 default:
5a4a898d
FB
2750 {
2751 abi_ulong raddr;
88a8c984
RV
2752 raddr = do_shmat(first, ptr, second);
2753 if (is_error(raddr))
2754 return get_errno(raddr);
2f619698 2755 if (put_user_ual(raddr, third))
5a4a898d 2756 return -TARGET_EFAULT;
88a8c984
RV
2757 break;
2758 }
2759 case 1:
2760 ret = -TARGET_EINVAL;
2761 break;
5a4a898d 2762 }
8853f86e
FB
2763 break;
2764 case IPCOP_shmdt:
88a8c984 2765 ret = do_shmdt(ptr);
8853f86e
FB
2766 break;
2767
2768 case IPCOP_shmget:
2769 /* IPC_* flag values are the same on all linux platforms */
2770 ret = get_errno(shmget(first, second, third));
2771 break;
2772
2773 /* IPC_* and SHM_* command values are the same on all linux platforms */
2774 case IPCOP_shmctl:
88a8c984 2775 ret = do_shmctl(first, second, third);
8853f86e
FB
2776 break;
2777 default:
32407103 2778 gemu_log("Unsupported ipc call: %d (version %d)\n", call, version);
0da46a6e 2779 ret = -TARGET_ENOSYS;
8853f86e
FB
2780 break;
2781 }
2782 return ret;
2783}
32407103 2784#endif
8853f86e 2785
31e31b8a
FB
2786/* kernel structure types definitions */
2787#define IFNAMSIZ 16
2788
001faf32 2789#define STRUCT(name, ...) STRUCT_ ## name,
31e31b8a
FB
2790#define STRUCT_SPECIAL(name) STRUCT_ ## name,
2791enum {
2792#include "syscall_types.h"
2793};
2794#undef STRUCT
2795#undef STRUCT_SPECIAL
2796
001faf32 2797#define STRUCT(name, ...) static const argtype struct_ ## name ## _def[] = { __VA_ARGS__, TYPE_NULL };
31e31b8a
FB
2798#define STRUCT_SPECIAL(name)
2799#include "syscall_types.h"
2800#undef STRUCT
2801#undef STRUCT_SPECIAL
2802
2803typedef struct IOCTLEntry {
2ab83ea7
FB
2804 unsigned int target_cmd;
2805 unsigned int host_cmd;
31e31b8a
FB
2806 const char *name;
2807 int access;
1a9353d2 2808 const argtype arg_type[5];
31e31b8a
FB
2809} IOCTLEntry;
2810
2811#define IOC_R 0x0001
2812#define IOC_W 0x0002
2813#define IOC_RW (IOC_R | IOC_W)
2814
2815#define MAX_STRUCT_SIZE 4096
2816
9f106a75 2817static IOCTLEntry ioctl_entries[] = {
001faf32
BS
2818#define IOCTL(cmd, access, ...) \
2819 { TARGET_ ## cmd, cmd, #cmd, access, { __VA_ARGS__ } },
31e31b8a
FB
2820#include "ioctls.h"
2821 { 0, 0, },
2822};
2823
53a5960a 2824/* ??? Implement proper locking for ioctls. */
0da46a6e 2825/* do_ioctl() Must return target values and target errnos. */
992f48a0 2826static abi_long do_ioctl(int fd, abi_long cmd, abi_long arg)
31e31b8a
FB
2827{
2828 const IOCTLEntry *ie;
2829 const argtype *arg_type;
992f48a0 2830 abi_long ret;
31e31b8a 2831 uint8_t buf_temp[MAX_STRUCT_SIZE];
53a5960a
PB
2832 int target_size;
2833 void *argptr;
31e31b8a
FB
2834
2835 ie = ioctl_entries;
2836 for(;;) {
2837 if (ie->target_cmd == 0) {
32407103 2838 gemu_log("Unsupported ioctl: cmd=0x%04lx\n", (long)cmd);
0da46a6e 2839 return -TARGET_ENOSYS;
31e31b8a
FB
2840 }
2841 if (ie->target_cmd == cmd)
2842 break;
2843 ie++;
2844 }
2845 arg_type = ie->arg_type;
9de5e440 2846#if defined(DEBUG)
32407103 2847 gemu_log("ioctl: cmd=0x%04lx (%s)\n", (long)cmd, ie->name);
72f03900 2848#endif
31e31b8a
FB
2849 switch(arg_type[0]) {
2850 case TYPE_NULL:
2851 /* no argument */
2852 ret = get_errno(ioctl(fd, ie->host_cmd));
2853 break;
2854 case TYPE_PTRVOID:
2855 case TYPE_INT:
2856 /* int argment */
2857 ret = get_errno(ioctl(fd, ie->host_cmd, arg));
2858 break;
2859 case TYPE_PTR:
2860 arg_type++;
53a5960a 2861 target_size = thunk_type_size(arg_type, 0);
31e31b8a
FB
2862 switch(ie->access) {
2863 case IOC_R:
2864 ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
2865 if (!is_error(ret)) {
579a97f7
FB
2866 argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
2867 if (!argptr)
2868 return -TARGET_EFAULT;
53a5960a
PB
2869 thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
2870 unlock_user(argptr, arg, target_size);
31e31b8a
FB
2871 }
2872 break;
2873 case IOC_W:
579a97f7
FB
2874 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
2875 if (!argptr)
2876 return -TARGET_EFAULT;
53a5960a
PB
2877 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
2878 unlock_user(argptr, arg, 0);
31e31b8a
FB
2879 ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
2880 break;
2881 default:
2882 case IOC_RW:
579a97f7
FB
2883 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
2884 if (!argptr)
2885 return -TARGET_EFAULT;
53a5960a
PB
2886 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
2887 unlock_user(argptr, arg, 0);
31e31b8a
FB
2888 ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
2889 if (!is_error(ret)) {
579a97f7
FB
2890 argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
2891 if (!argptr)
2892 return -TARGET_EFAULT;
53a5960a
PB
2893 thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
2894 unlock_user(argptr, arg, target_size);
31e31b8a
FB
2895 }
2896 break;
2897 }
2898 break;
2899 default:
32407103
JM
2900 gemu_log("Unsupported ioctl type: cmd=0x%04lx type=%d\n",
2901 (long)cmd, arg_type[0]);
0da46a6e 2902 ret = -TARGET_ENOSYS;
31e31b8a
FB
2903 break;
2904 }
2905 return ret;
2906}
2907
b39bc503 2908static const bitmask_transtbl iflag_tbl[] = {
31e31b8a
FB
2909 { TARGET_IGNBRK, TARGET_IGNBRK, IGNBRK, IGNBRK },
2910 { TARGET_BRKINT, TARGET_BRKINT, BRKINT, BRKINT },
2911 { TARGET_IGNPAR, TARGET_IGNPAR, IGNPAR, IGNPAR },
2912 { TARGET_PARMRK, TARGET_PARMRK, PARMRK, PARMRK },
2913 { TARGET_INPCK, TARGET_INPCK, INPCK, INPCK },
2914 { TARGET_ISTRIP, TARGET_ISTRIP, ISTRIP, ISTRIP },
2915 { TARGET_INLCR, TARGET_INLCR, INLCR, INLCR },
2916 { TARGET_IGNCR, TARGET_IGNCR, IGNCR, IGNCR },
2917 { TARGET_ICRNL, TARGET_ICRNL, ICRNL, ICRNL },
2918 { TARGET_IUCLC, TARGET_IUCLC, IUCLC, IUCLC },
2919 { TARGET_IXON, TARGET_IXON, IXON, IXON },
2920 { TARGET_IXANY, TARGET_IXANY, IXANY, IXANY },
2921 { TARGET_IXOFF, TARGET_IXOFF, IXOFF, IXOFF },
2922 { TARGET_IMAXBEL, TARGET_IMAXBEL, IMAXBEL, IMAXBEL },
2923 { 0, 0, 0, 0 }
2924};
2925
b39bc503 2926static const bitmask_transtbl oflag_tbl[] = {
31e31b8a
FB
2927 { TARGET_OPOST, TARGET_OPOST, OPOST, OPOST },
2928 { TARGET_OLCUC, TARGET_OLCUC, OLCUC, OLCUC },
2929 { TARGET_ONLCR, TARGET_ONLCR, ONLCR, ONLCR },
2930 { TARGET_OCRNL, TARGET_OCRNL, OCRNL, OCRNL },
2931 { TARGET_ONOCR, TARGET_ONOCR, ONOCR, ONOCR },
2932 { TARGET_ONLRET, TARGET_ONLRET, ONLRET, ONLRET },
2933 { TARGET_OFILL, TARGET_OFILL, OFILL, OFILL },
2934 { TARGET_OFDEL, TARGET_OFDEL, OFDEL, OFDEL },
2935 { TARGET_NLDLY, TARGET_NL0, NLDLY, NL0 },
2936 { TARGET_NLDLY, TARGET_NL1, NLDLY, NL1 },
2937 { TARGET_CRDLY, TARGET_CR0, CRDLY, CR0 },
2938 { TARGET_CRDLY, TARGET_CR1, CRDLY, CR1 },
2939 { TARGET_CRDLY, TARGET_CR2, CRDLY, CR2 },
2940 { TARGET_CRDLY, TARGET_CR3, CRDLY, CR3 },
2941 { TARGET_TABDLY, TARGET_TAB0, TABDLY, TAB0 },
2942 { TARGET_TABDLY, TARGET_TAB1, TABDLY, TAB1 },
2943 { TARGET_TABDLY, TARGET_TAB2, TABDLY, TAB2 },
2944 { TARGET_TABDLY, TARGET_TAB3, TABDLY, TAB3 },
2945 { TARGET_BSDLY, TARGET_BS0, BSDLY, BS0 },
2946 { TARGET_BSDLY, TARGET_BS1, BSDLY, BS1 },
2947 { TARGET_VTDLY, TARGET_VT0, VTDLY, VT0 },
2948 { TARGET_VTDLY, TARGET_VT1, VTDLY, VT1 },
2949 { TARGET_FFDLY, TARGET_FF0, FFDLY, FF0 },
2950 { TARGET_FFDLY, TARGET_FF1, FFDLY, FF1 },
2951 { 0, 0, 0, 0 }
2952};
2953
b39bc503 2954static const bitmask_transtbl cflag_tbl[] = {
31e31b8a
FB
2955 { TARGET_CBAUD, TARGET_B0, CBAUD, B0 },
2956 { TARGET_CBAUD, TARGET_B50, CBAUD, B50 },
2957 { TARGET_CBAUD, TARGET_B75, CBAUD, B75 },
2958 { TARGET_CBAUD, TARGET_B110, CBAUD, B110 },
2959 { TARGET_CBAUD, TARGET_B134, CBAUD, B134 },
2960 { TARGET_CBAUD, TARGET_B150, CBAUD, B150 },
2961 { TARGET_CBAUD, TARGET_B200, CBAUD, B200 },
2962 { TARGET_CBAUD, TARGET_B300, CBAUD, B300 },
2963 { TARGET_CBAUD, TARGET_B600, CBAUD, B600 },
2964 { TARGET_CBAUD, TARGET_B1200, CBAUD, B1200 },
2965 { TARGET_CBAUD, TARGET_B1800, CBAUD, B1800 },
2966 { TARGET_CBAUD, TARGET_B2400, CBAUD, B2400 },
2967 { TARGET_CBAUD, TARGET_B4800, CBAUD, B4800 },
2968 { TARGET_CBAUD, TARGET_B9600, CBAUD, B9600 },
2969 { TARGET_CBAUD, TARGET_B19200, CBAUD, B19200 },
2970 { TARGET_CBAUD, TARGET_B38400, CBAUD, B38400 },
2971 { TARGET_CBAUD, TARGET_B57600, CBAUD, B57600 },
2972 { TARGET_CBAUD, TARGET_B115200, CBAUD, B115200 },
2973 { TARGET_CBAUD, TARGET_B230400, CBAUD, B230400 },
2974 { TARGET_CBAUD, TARGET_B460800, CBAUD, B460800 },
2975 { TARGET_CSIZE, TARGET_CS5, CSIZE, CS5 },
2976 { TARGET_CSIZE, TARGET_CS6, CSIZE, CS6 },
2977 { TARGET_CSIZE, TARGET_CS7, CSIZE, CS7 },
2978 { TARGET_CSIZE, TARGET_CS8, CSIZE, CS8 },
2979 { TARGET_CSTOPB, TARGET_CSTOPB, CSTOPB, CSTOPB },
2980 { TARGET_CREAD, TARGET_CREAD, CREAD, CREAD },
2981 { TARGET_PARENB, TARGET_PARENB, PARENB, PARENB },
2982 { TARGET_PARODD, TARGET_PARODD, PARODD, PARODD },
2983 { TARGET_HUPCL, TARGET_HUPCL, HUPCL, HUPCL },
2984 { TARGET_CLOCAL, TARGET_CLOCAL, CLOCAL, CLOCAL },
2985 { TARGET_CRTSCTS, TARGET_CRTSCTS, CRTSCTS, CRTSCTS },
2986 { 0, 0, 0, 0 }
2987};
2988
b39bc503 2989static const bitmask_transtbl lflag_tbl[] = {
31e31b8a
FB
2990 { TARGET_ISIG, TARGET_ISIG, ISIG, ISIG },
2991 { TARGET_ICANON, TARGET_ICANON, ICANON, ICANON },
2992 { TARGET_XCASE, TARGET_XCASE, XCASE, XCASE },
2993 { TARGET_ECHO, TARGET_ECHO, ECHO, ECHO },
2994 { TARGET_ECHOE, TARGET_ECHOE, ECHOE, ECHOE },
2995 { TARGET_ECHOK, TARGET_ECHOK, ECHOK, ECHOK },
2996 { TARGET_ECHONL, TARGET_ECHONL, ECHONL, ECHONL },
2997 { TARGET_NOFLSH, TARGET_NOFLSH, NOFLSH, NOFLSH },
2998 { TARGET_TOSTOP, TARGET_TOSTOP, TOSTOP, TOSTOP },
2999 { TARGET_ECHOCTL, TARGET_ECHOCTL, ECHOCTL, ECHOCTL },
3000 { TARGET_ECHOPRT, TARGET_ECHOPRT, ECHOPRT, ECHOPRT },
3001 { TARGET_ECHOKE, TARGET_ECHOKE, ECHOKE, ECHOKE },
3002 { TARGET_FLUSHO, TARGET_FLUSHO, FLUSHO, FLUSHO },
3003 { TARGET_PENDIN, TARGET_PENDIN, PENDIN, PENDIN },
3004 { TARGET_IEXTEN, TARGET_IEXTEN, IEXTEN, IEXTEN },
3005 { 0, 0, 0, 0 }
3006};
3007
3008static void target_to_host_termios (void *dst, const void *src)
3009{
3010 struct host_termios *host = dst;
3011 const struct target_termios *target = src;
3b46e624 3012
5fafdf24 3013 host->c_iflag =
31e31b8a 3014 target_to_host_bitmask(tswap32(target->c_iflag), iflag_tbl);
5fafdf24 3015 host->c_oflag =
31e31b8a 3016 target_to_host_bitmask(tswap32(target->c_oflag), oflag_tbl);
5fafdf24 3017 host->c_cflag =
31e31b8a 3018 target_to_host_bitmask(tswap32(target->c_cflag), cflag_tbl);
5fafdf24 3019 host->c_lflag =
31e31b8a
FB
3020 target_to_host_bitmask(tswap32(target->c_lflag), lflag_tbl);
3021 host->c_line = target->c_line;
3b46e624 3022
44607123 3023 memset(host->c_cc, 0, sizeof(host->c_cc));
5fafdf24
TS
3024 host->c_cc[VINTR] = target->c_cc[TARGET_VINTR];
3025 host->c_cc[VQUIT] = target->c_cc[TARGET_VQUIT];
3b46e624 3026 host->c_cc[VERASE] = target->c_cc[TARGET_VERASE];
5fafdf24 3027 host->c_cc[VKILL] = target->c_cc[TARGET_VKILL];
3b46e624 3028 host->c_cc[VEOF] = target->c_cc[TARGET_VEOF];
5fafdf24 3029 host->c_cc[VTIME] = target->c_cc[TARGET_VTIME];
3b46e624 3030 host->c_cc[VMIN] = target->c_cc[TARGET_VMIN];
5fafdf24 3031 host->c_cc[VSWTC] = target->c_cc[TARGET_VSWTC];
3b46e624 3032 host->c_cc[VSTART] = target->c_cc[TARGET_VSTART];
5fafdf24
TS
3033 host->c_cc[VSTOP] = target->c_cc[TARGET_VSTOP];
3034 host->c_cc[VSUSP] = target->c_cc[TARGET_VSUSP];
3b46e624
TS
3035 host->c_cc[VEOL] = target->c_cc[TARGET_VEOL];
3036 host->c_cc[VREPRINT] = target->c_cc[TARGET_VREPRINT];
3037 host->c_cc[VDISCARD] = target->c_cc[TARGET_VDISCARD];
3038 host->c_cc[VWERASE] = target->c_cc[TARGET_VWERASE];
3039 host->c_cc[VLNEXT] = target->c_cc[TARGET_VLNEXT];
5fafdf24 3040 host->c_cc[VEOL2] = target->c_cc[TARGET_VEOL2];
31e31b8a 3041}
3b46e624 3042
31e31b8a
FB
3043static void host_to_target_termios (void *dst, const void *src)
3044{
3045 struct target_termios *target = dst;
3046 const struct host_termios *host = src;
3047
5fafdf24 3048 target->c_iflag =
31e31b8a 3049 tswap32(host_to_target_bitmask(host->c_iflag, iflag_tbl));
5fafdf24 3050 target->c_oflag =
31e31b8a 3051 tswap32(host_to_target_bitmask(host->c_oflag, oflag_tbl));
5fafdf24 3052 target->c_cflag =
31e31b8a 3053 tswap32(host_to_target_bitmask(host->c_cflag, cflag_tbl));
5fafdf24 3054 target->c_lflag =
31e31b8a
FB
3055 tswap32(host_to_target_bitmask(host->c_lflag, lflag_tbl));
3056 target->c_line = host->c_line;
3b46e624 3057
44607123 3058 memset(target->c_cc, 0, sizeof(target->c_cc));
31e31b8a
FB
3059 target->c_cc[TARGET_VINTR] = host->c_cc[VINTR];
3060 target->c_cc[TARGET_VQUIT] = host->c_cc[VQUIT];
3061 target->c_cc[TARGET_VERASE] = host->c_cc[VERASE];
3062 target->c_cc[TARGET_VKILL] = host->c_cc[VKILL];
3063 target->c_cc[TARGET_VEOF] = host->c_cc[VEOF];
3064 target->c_cc[TARGET_VTIME] = host->c_cc[VTIME];
3065 target->c_cc[TARGET_VMIN] = host->c_cc[VMIN];
3066 target->c_cc[TARGET_VSWTC] = host->c_cc[VSWTC];
3067 target->c_cc[TARGET_VSTART] = host->c_cc[VSTART];
3068 target->c_cc[TARGET_VSTOP] = host->c_cc[VSTOP];
3069 target->c_cc[TARGET_VSUSP] = host->c_cc[VSUSP];
3070 target->c_cc[TARGET_VEOL] = host->c_cc[VEOL];
3071 target->c_cc[TARGET_VREPRINT] = host->c_cc[VREPRINT];
3072 target->c_cc[TARGET_VDISCARD] = host->c_cc[VDISCARD];
3073 target->c_cc[TARGET_VWERASE] = host->c_cc[VWERASE];
3074 target->c_cc[TARGET_VLNEXT] = host->c_cc[VLNEXT];
3075 target->c_cc[TARGET_VEOL2] = host->c_cc[VEOL2];
3076}
3077
8e853dc7 3078static const StructEntry struct_termios_def = {
31e31b8a
FB
3079 .convert = { host_to_target_termios, target_to_host_termios },
3080 .size = { sizeof(struct target_termios), sizeof(struct host_termios) },
3081 .align = { __alignof__(struct target_termios), __alignof__(struct host_termios) },
3082};
3083
5286db75
FB
3084static bitmask_transtbl mmap_flags_tbl[] = {
3085 { TARGET_MAP_SHARED, TARGET_MAP_SHARED, MAP_SHARED, MAP_SHARED },
3086 { TARGET_MAP_PRIVATE, TARGET_MAP_PRIVATE, MAP_PRIVATE, MAP_PRIVATE },
3087 { TARGET_MAP_FIXED, TARGET_MAP_FIXED, MAP_FIXED, MAP_FIXED },
3088 { TARGET_MAP_ANONYMOUS, TARGET_MAP_ANONYMOUS, MAP_ANONYMOUS, MAP_ANONYMOUS },
3089 { TARGET_MAP_GROWSDOWN, TARGET_MAP_GROWSDOWN, MAP_GROWSDOWN, MAP_GROWSDOWN },
3090 { TARGET_MAP_DENYWRITE, TARGET_MAP_DENYWRITE, MAP_DENYWRITE, MAP_DENYWRITE },
3091 { TARGET_MAP_EXECUTABLE, TARGET_MAP_EXECUTABLE, MAP_EXECUTABLE, MAP_EXECUTABLE },
3092 { TARGET_MAP_LOCKED, TARGET_MAP_LOCKED, MAP_LOCKED, MAP_LOCKED },
3093 { 0, 0, 0, 0 }
3094};
3095
2ab83ea7 3096#if defined(TARGET_I386)
6dbad63e
FB
3097
3098/* NOTE: there is really one LDT for all the threads */
b1d8e52e 3099static uint8_t *ldt_table;
6dbad63e 3100
03acab66 3101static abi_long read_ldt(abi_ulong ptr, unsigned long bytecount)
6dbad63e
FB
3102{
3103 int size;
53a5960a 3104 void *p;
6dbad63e
FB
3105
3106 if (!ldt_table)
3107 return 0;
3108 size = TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE;
3109 if (size > bytecount)
3110 size = bytecount;
579a97f7
FB
3111 p = lock_user(VERIFY_WRITE, ptr, size, 0);
3112 if (!p)
03acab66 3113 return -TARGET_EFAULT;
579a97f7 3114 /* ??? Should this by byteswapped? */
53a5960a
PB
3115 memcpy(p, ldt_table, size);
3116 unlock_user(p, ptr, size);
6dbad63e
FB
3117 return size;
3118}
3119
3120/* XXX: add locking support */
03acab66
FB
3121static abi_long write_ldt(CPUX86State *env,
3122 abi_ulong ptr, unsigned long bytecount, int oldmode)
6dbad63e
FB
3123{
3124 struct target_modify_ldt_ldt_s ldt_info;
53a5960a 3125 struct target_modify_ldt_ldt_s *target_ldt_info;
6dbad63e 3126 int seg_32bit, contents, read_exec_only, limit_in_pages;
8d18e893 3127 int seg_not_present, useable, lm;
6dbad63e
FB
3128 uint32_t *lp, entry_1, entry_2;
3129
3130 if (bytecount != sizeof(ldt_info))
03acab66 3131 return -TARGET_EINVAL;
579a97f7 3132 if (!lock_user_struct(VERIFY_READ, target_ldt_info, ptr, 1))
03acab66 3133 return -TARGET_EFAULT;
53a5960a
PB
3134 ldt_info.entry_number = tswap32(target_ldt_info->entry_number);
3135 ldt_info.base_addr = tswapl(target_ldt_info->base_addr);
3136 ldt_info.limit = tswap32(target_ldt_info->limit);
3137 ldt_info.flags = tswap32(target_ldt_info->flags);
3138 unlock_user_struct(target_ldt_info, ptr, 0);
3b46e624 3139
6dbad63e 3140 if (ldt_info.entry_number >= TARGET_LDT_ENTRIES)
03acab66 3141 return -TARGET_EINVAL;
6dbad63e
FB
3142 seg_32bit = ldt_info.flags & 1;
3143 contents = (ldt_info.flags >> 1) & 3;
3144 read_exec_only = (ldt_info.flags >> 3) & 1;
3145 limit_in_pages = (ldt_info.flags >> 4) & 1;
3146 seg_not_present = (ldt_info.flags >> 5) & 1;
3147 useable = (ldt_info.flags >> 6) & 1;
8d18e893
FB
3148#ifdef TARGET_ABI32
3149 lm = 0;
3150#else
3151 lm = (ldt_info.flags >> 7) & 1;
3152#endif
6dbad63e
FB
3153 if (contents == 3) {
3154 if (oldmode)
03acab66 3155 return -TARGET_EINVAL;
6dbad63e 3156 if (seg_not_present == 0)
03acab66 3157 return -TARGET_EINVAL;
6dbad63e
FB
3158 }
3159 /* allocate the LDT */
3160 if (!ldt_table) {
e441570f
AZ
3161 env->ldt.base = target_mmap(0,
3162 TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE,
3163 PROT_READ|PROT_WRITE,
3164 MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
3165 if (env->ldt.base == -1)
03acab66 3166 return -TARGET_ENOMEM;
e441570f
AZ
3167 memset(g2h(env->ldt.base), 0,
3168 TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE);
6dbad63e 3169 env->ldt.limit = 0xffff;
e441570f 3170 ldt_table = g2h(env->ldt.base);
6dbad63e
FB
3171 }
3172
3173 /* NOTE: same code as Linux kernel */
3174 /* Allow LDTs to be cleared by the user. */
3175 if (ldt_info.base_addr == 0 && ldt_info.limit == 0) {
3176 if (oldmode ||
3177 (contents == 0 &&
3178 read_exec_only == 1 &&
3179 seg_32bit == 0 &&
3180 limit_in_pages == 0 &&
3181 seg_not_present == 1 &&
3182 useable == 0 )) {
3183 entry_1 = 0;
3184 entry_2 = 0;
3185 goto install;
3186 }
3187 }
3b46e624 3188
6dbad63e
FB
3189 entry_1 = ((ldt_info.base_addr & 0x0000ffff) << 16) |
3190 (ldt_info.limit & 0x0ffff);
3191 entry_2 = (ldt_info.base_addr & 0xff000000) |
3192 ((ldt_info.base_addr & 0x00ff0000) >> 16) |
3193 (ldt_info.limit & 0xf0000) |
3194 ((read_exec_only ^ 1) << 9) |
3195 (contents << 10) |
3196 ((seg_not_present ^ 1) << 15) |
3197 (seg_32bit << 22) |
3198 (limit_in_pages << 23) |
8d18e893 3199 (lm << 21) |
6dbad63e
FB
3200 0x7000;
3201 if (!oldmode)
3202 entry_2 |= (useable << 20);
14ae3ba7 3203
6dbad63e
FB
3204 /* Install the new entry ... */
3205install:
3206 lp = (uint32_t *)(ldt_table + (ldt_info.entry_number << 3));
3207 lp[0] = tswap32(entry_1);
3208 lp[1] = tswap32(entry_2);
3209 return 0;
3210}
3211
3212/* specific and weird i386 syscalls */
8fcd3692
BS
3213static abi_long do_modify_ldt(CPUX86State *env, int func, abi_ulong ptr,
3214 unsigned long bytecount)
6dbad63e 3215{
03acab66 3216 abi_long ret;
3b46e624 3217
6dbad63e
FB
3218 switch (func) {
3219 case 0:
3220 ret = read_ldt(ptr, bytecount);
3221 break;
3222 case 1:
3223 ret = write_ldt(env, ptr, bytecount, 1);
3224 break;
3225 case 0x11:
3226 ret = write_ldt(env, ptr, bytecount, 0);
3227 break;
03acab66
FB
3228 default:
3229 ret = -TARGET_ENOSYS;
3230 break;
6dbad63e
FB
3231 }
3232 return ret;
3233}
1b6b029e 3234
4583f589 3235#if defined(TARGET_I386) && defined(TARGET_ABI32)
8fcd3692 3236static abi_long do_set_thread_area(CPUX86State *env, abi_ulong ptr)
8d18e893
FB
3237{
3238 uint64_t *gdt_table = g2h(env->gdt.base);
3239 struct target_modify_ldt_ldt_s ldt_info;
3240 struct target_modify_ldt_ldt_s *target_ldt_info;
3241 int seg_32bit, contents, read_exec_only, limit_in_pages;
3242 int seg_not_present, useable, lm;
3243 uint32_t *lp, entry_1, entry_2;
3244 int i;
3245
3246 lock_user_struct(VERIFY_WRITE, target_ldt_info, ptr, 1);
3247 if (!target_ldt_info)
3248 return -TARGET_EFAULT;
3249 ldt_info.entry_number = tswap32(target_ldt_info->entry_number);
3250 ldt_info.base_addr = tswapl(target_ldt_info->base_addr);
3251 ldt_info.limit = tswap32(target_ldt_info->limit);
3252 ldt_info.flags = tswap32(target_ldt_info->flags);
3253 if (ldt_info.entry_number == -1) {
3254 for (i=TARGET_GDT_ENTRY_TLS_MIN; i<=TARGET_GDT_ENTRY_TLS_MAX; i++) {
3255 if (gdt_table[i] == 0) {
3256 ldt_info.entry_number = i;
3257 target_ldt_info->entry_number = tswap32(i);
3258 break;
3259 }
3260 }
3261 }
3262 unlock_user_struct(target_ldt_info, ptr, 1);
3263
3264 if (ldt_info.entry_number < TARGET_GDT_ENTRY_TLS_MIN ||
3265 ldt_info.entry_number > TARGET_GDT_ENTRY_TLS_MAX)
3266 return -TARGET_EINVAL;
3267 seg_32bit = ldt_info.flags & 1;
3268 contents = (ldt_info.flags >> 1) & 3;
3269 read_exec_only = (ldt_info.flags >> 3) & 1;
3270 limit_in_pages = (ldt_info.flags >> 4) & 1;
3271 seg_not_present = (ldt_info.flags >> 5) & 1;
3272 useable = (ldt_info.flags >> 6) & 1;
3273#ifdef TARGET_ABI32
3274 lm = 0;
3275#else
3276 lm = (ldt_info.flags >> 7) & 1;
3277#endif
3278
3279 if (contents == 3) {
3280 if (seg_not_present == 0)
3281 return -TARGET_EINVAL;
3282 }
3283
3284 /* NOTE: same code as Linux kernel */
3285 /* Allow LDTs to be cleared by the user. */
3286 if (ldt_info.base_addr == 0 && ldt_info.limit == 0) {
3287 if ((contents == 0 &&
3288 read_exec_only == 1 &&
3289 seg_32bit == 0 &&
3290 limit_in_pages == 0 &&
3291 seg_not_present == 1 &&
3292 useable == 0 )) {
3293 entry_1 = 0;
3294 entry_2 = 0;
3295 goto install;
3296 }
3297 }
3298
3299 entry_1 = ((ldt_info.base_addr & 0x0000ffff) << 16) |
3300 (ldt_info.limit & 0x0ffff);
3301 entry_2 = (ldt_info.base_addr & 0xff000000) |
3302 ((ldt_info.base_addr & 0x00ff0000) >> 16) |
3303 (ldt_info.limit & 0xf0000) |
3304 ((read_exec_only ^ 1) << 9) |
3305 (contents << 10) |
3306 ((seg_not_present ^ 1) << 15) |
3307 (seg_32bit << 22) |
3308 (limit_in_pages << 23) |
3309 (useable << 20) |
3310 (lm << 21) |
3311 0x7000;
3312
3313 /* Install the new entry ... */
3314install:
3315 lp = (uint32_t *)(gdt_table + ldt_info.entry_number);
3316 lp[0] = tswap32(entry_1);
3317 lp[1] = tswap32(entry_2);
3318 return 0;
3319}
3320
8fcd3692 3321static abi_long do_get_thread_area(CPUX86State *env, abi_ulong ptr)
8d18e893
FB
3322{
3323 struct target_modify_ldt_ldt_s *target_ldt_info;
3324 uint64_t *gdt_table = g2h(env->gdt.base);
3325 uint32_t base_addr, limit, flags;
3326 int seg_32bit, contents, read_exec_only, limit_in_pages, idx;
3327 int seg_not_present, useable, lm;
3328 uint32_t *lp, entry_1, entry_2;
3329
3330 lock_user_struct(VERIFY_WRITE, target_ldt_info, ptr, 1);
3331 if (!target_ldt_info)
3332 return -TARGET_EFAULT;
3333 idx = tswap32(target_ldt_info->entry_number);
3334 if (idx < TARGET_GDT_ENTRY_TLS_MIN ||
3335 idx > TARGET_GDT_ENTRY_TLS_MAX) {
3336 unlock_user_struct(target_ldt_info, ptr, 1);
3337 return -TARGET_EINVAL;
3338 }
3339 lp = (uint32_t *)(gdt_table + idx);
3340 entry_1 = tswap32(lp[0]);
3341 entry_2 = tswap32(lp[1]);
3342
3343 read_exec_only = ((entry_2 >> 9) & 1) ^ 1;
3344 contents = (entry_2 >> 10) & 3;
3345 seg_not_present = ((entry_2 >> 15) & 1) ^ 1;
3346 seg_32bit = (entry_2 >> 22) & 1;
3347 limit_in_pages = (entry_2 >> 23) & 1;
3348 useable = (entry_2 >> 20) & 1;
3349#ifdef TARGET_ABI32
3350 lm = 0;
3351#else
3352 lm = (entry_2 >> 21) & 1;
3353#endif
3354 flags = (seg_32bit << 0) | (contents << 1) |
3355 (read_exec_only << 3) | (limit_in_pages << 4) |
3356 (seg_not_present << 5) | (useable << 6) | (lm << 7);
3357 limit = (entry_1 & 0xffff) | (entry_2 & 0xf0000);
3358 base_addr = (entry_1 >> 16) |
3359 (entry_2 & 0xff000000) |
3360 ((entry_2 & 0xff) << 16);
3361 target_ldt_info->base_addr = tswapl(base_addr);
3362 target_ldt_info->limit = tswap32(limit);
3363 target_ldt_info->flags = tswap32(flags);
3364 unlock_user_struct(target_ldt_info, ptr, 1);
3365 return 0;
3366}
4583f589 3367#endif /* TARGET_I386 && TARGET_ABI32 */
8d18e893 3368
d2fd1af7 3369#ifndef TARGET_ABI32
8fcd3692 3370static abi_long do_arch_prctl(CPUX86State *env, int code, abi_ulong addr)
d2fd1af7
FB
3371{
3372 abi_long ret;
3373 abi_ulong val;
3374 int idx;
3375
3376 switch(code) {
3377 case TARGET_ARCH_SET_GS:
3378 case TARGET_ARCH_SET_FS:
3379 if (code == TARGET_ARCH_SET_GS)
3380 idx = R_GS;
3381 else
3382 idx = R_FS;
3383 cpu_x86_load_seg(env, idx, 0);
3384 env->segs[idx].base = addr;
3385 break;
3386 case TARGET_ARCH_GET_GS:
3387 case TARGET_ARCH_GET_FS:
3388 if (code == TARGET_ARCH_GET_GS)
3389 idx = R_GS;
3390 else
3391 idx = R_FS;
3392 val = env->segs[idx].base;
3393 if (put_user(val, addr, abi_ulong))
3394 return -TARGET_EFAULT;
3395 break;
3396 default:
3397 ret = -TARGET_EINVAL;
3398 break;
3399 }
3400 return 0;
3401}
3402#endif
3403
2ab83ea7
FB
3404#endif /* defined(TARGET_I386) */
3405
d865bab5
PB
3406#if defined(USE_NPTL)
3407
3408#define NEW_STACK_SIZE PTHREAD_STACK_MIN
3409
3410static pthread_mutex_t clone_lock = PTHREAD_MUTEX_INITIALIZER;
3411typedef struct {
3412 CPUState *env;
3413 pthread_mutex_t mutex;
3414 pthread_cond_t cond;
3415 pthread_t thread;
3416 uint32_t tid;
3417 abi_ulong child_tidptr;
3418 abi_ulong parent_tidptr;
3419 sigset_t sigmask;
3420} new_thread_info;
3421
3422static void *clone_func(void *arg)
3423{
3424 new_thread_info *info = arg;
3425 CPUState *env;
edf8e2af 3426 TaskState *ts;
d865bab5
PB
3427
3428 env = info->env;
3429 thread_env = env;
edf8e2af 3430 ts = (TaskState *)thread_env->opaque;
d865bab5 3431 info->tid = gettid();
1e9fa730 3432 env->host_tid = info->tid;
edf8e2af 3433 task_settid(ts);
d865bab5
PB
3434 if (info->child_tidptr)
3435 put_user_u32(info->tid, info->child_tidptr);
3436 if (info->parent_tidptr)
3437 put_user_u32(info->tid, info->parent_tidptr);
3438 /* Enable signals. */
3439 sigprocmask(SIG_SETMASK, &info->sigmask, NULL);
3440 /* Signal to the parent that we're ready. */
3441 pthread_mutex_lock(&info->mutex);
3442 pthread_cond_broadcast(&info->cond);
3443 pthread_mutex_unlock(&info->mutex);
3444 /* Wait until the parent has finshed initializing the tls state. */
3445 pthread_mutex_lock(&clone_lock);
3446 pthread_mutex_unlock(&clone_lock);
3447 cpu_loop(env);
3448 /* never exits */
3449 return NULL;
3450}
3451#else
1b6b029e
FB
3452/* this stack is the equivalent of the kernel stack associated with a
3453 thread/process */
3454#define NEW_STACK_SIZE 8192
3455
3456static int clone_func(void *arg)
3457{
2ab83ea7 3458 CPUState *env = arg;
1b6b029e
FB
3459 cpu_loop(env);
3460 /* never exits */
3461 return 0;
3462}
d865bab5 3463#endif
1b6b029e 3464
0da46a6e
TS
3465/* do_fork() Must return host values and target errnos (unlike most
3466 do_*() functions). */
d865bab5
PB
3467static int do_fork(CPUState *env, unsigned int flags, abi_ulong newsp,
3468 abi_ulong parent_tidptr, target_ulong newtls,
3469 abi_ulong child_tidptr)
1b6b029e
FB
3470{
3471 int ret;
5cd4393b 3472 TaskState *ts;
1b6b029e 3473 uint8_t *new_stack;
2ab83ea7 3474 CPUState *new_env;
d865bab5
PB
3475#if defined(USE_NPTL)
3476 unsigned int nptl_flags;
3477 sigset_t sigmask;
3478#endif
3b46e624 3479
436d124b
AZ
3480 /* Emulate vfork() with fork() */
3481 if (flags & CLONE_VFORK)
3482 flags &= ~(CLONE_VFORK | CLONE_VM);
3483
1b6b029e 3484 if (flags & CLONE_VM) {
edf8e2af 3485 TaskState *parent_ts = (TaskState *)env->opaque;
bd0c5661 3486#if defined(USE_NPTL)
d865bab5
PB
3487 new_thread_info info;
3488 pthread_attr_t attr;
bd0c5661 3489#endif
c3a92833 3490 ts = qemu_mallocz(sizeof(TaskState) + NEW_STACK_SIZE);
624f7979 3491 init_task_state(ts);
5cd4393b 3492 new_stack = ts->stack;
1b6b029e 3493 /* we create a new CPU instance. */
c5be9f08 3494 new_env = cpu_copy(env);
6e68e076
PB
3495 /* Init regs that differ from the parent. */
3496 cpu_clone_regs(new_env, newsp);
5cd4393b 3497 new_env->opaque = ts;
edf8e2af
MW
3498 ts->bprm = parent_ts->bprm;
3499 ts->info = parent_ts->info;
d865bab5
PB
3500#if defined(USE_NPTL)
3501 nptl_flags = flags;
3502 flags &= ~CLONE_NPTL_FLAGS2;
3503
c2764719
PB
3504 if (nptl_flags & CLONE_CHILD_CLEARTID) {
3505 ts->child_tidptr = child_tidptr;
3506 }
3507
d865bab5
PB
3508 if (nptl_flags & CLONE_SETTLS)
3509 cpu_set_tls (new_env, newtls);
3510
3511 /* Grab a mutex so that thread setup appears atomic. */
3512 pthread_mutex_lock(&clone_lock);
3513
3514 memset(&info, 0, sizeof(info));
3515 pthread_mutex_init(&info.mutex, NULL);
3516 pthread_mutex_lock(&info.mutex);
3517 pthread_cond_init(&info.cond, NULL);
3518 info.env = new_env;
3519 if (nptl_flags & CLONE_CHILD_SETTID)
3520 info.child_tidptr = child_tidptr;
3521 if (nptl_flags & CLONE_PARENT_SETTID)
3522 info.parent_tidptr = parent_tidptr;
3523
3524 ret = pthread_attr_init(&attr);
3525 ret = pthread_attr_setstack(&attr, new_stack, NEW_STACK_SIZE);
3526 /* It is not safe to deliver signals until the child has finished
3527 initializing, so temporarily block all signals. */
3528 sigfillset(&sigmask);
3529 sigprocmask(SIG_BLOCK, &sigmask, &info.sigmask);
3530
3531 ret = pthread_create(&info.thread, &attr, clone_func, &info);
c2764719 3532 /* TODO: Free new CPU state if thread creation failed. */
d865bab5
PB
3533
3534 sigprocmask(SIG_SETMASK, &info.sigmask, NULL);
3535 pthread_attr_destroy(&attr);
3536 if (ret == 0) {
3537 /* Wait for the child to initialize. */
3538 pthread_cond_wait(&info.cond, &info.mutex);
3539 ret = info.tid;
3540 if (flags & CLONE_PARENT_SETTID)
3541 put_user_u32(ret, parent_tidptr);
3542 } else {
3543 ret = -1;
3544 }
3545 pthread_mutex_unlock(&info.mutex);
3546 pthread_cond_destroy(&info.cond);
3547 pthread_mutex_destroy(&info.mutex);
3548 pthread_mutex_unlock(&clone_lock);
3549#else
3550 if (flags & CLONE_NPTL_FLAGS2)
3551 return -EINVAL;
3552 /* This is probably going to die very quickly, but do it anyway. */
27725c1d 3553#ifdef __ia64__
fd4a43e4 3554 ret = __clone2(clone_func, new_stack + NEW_STACK_SIZE, flags, new_env);
27725c1d
FB
3555#else
3556 ret = clone(clone_func, new_stack + NEW_STACK_SIZE, flags, new_env);
d865bab5 3557#endif
27725c1d 3558#endif
1b6b029e
FB
3559 } else {
3560 /* if no CLONE_VM, we consider it is a fork */
d865bab5 3561 if ((flags & ~(CSIGNAL | CLONE_NPTL_FLAGS2)) != 0)
1b6b029e 3562 return -EINVAL;
d865bab5 3563 fork_start();
1b6b029e 3564 ret = fork();
d865bab5 3565 if (ret == 0) {
2b1319c8 3566 /* Child Process. */
d865bab5
PB
3567 cpu_clone_regs(env, newsp);
3568 fork_end(1);
2b1319c8
AJ
3569#if defined(USE_NPTL)
3570 /* There is a race condition here. The parent process could
3571 theoretically read the TID in the child process before the child
3572 tid is set. This would require using either ptrace
3573 (not implemented) or having *_tidptr to point at a shared memory
3574 mapping. We can't repeat the spinlock hack used above because
3575 the child process gets its own copy of the lock. */
d865bab5
PB
3576 if (flags & CLONE_CHILD_SETTID)
3577 put_user_u32(gettid(), child_tidptr);
3578 if (flags & CLONE_PARENT_SETTID)
3579 put_user_u32(gettid(), parent_tidptr);
3580 ts = (TaskState *)env->opaque;
3581 if (flags & CLONE_SETTLS)
3582 cpu_set_tls (env, newtls);
c2764719
PB
3583 if (flags & CLONE_CHILD_CLEARTID)
3584 ts->child_tidptr = child_tidptr;
2b1319c8 3585#endif
d865bab5
PB
3586 } else {
3587 fork_end(0);
3588 }
1b6b029e
FB
3589 }
3590 return ret;
3591}
3592
992f48a0 3593static abi_long do_fcntl(int fd, int cmd, abi_ulong arg)
7775e9ec
FB
3594{
3595 struct flock fl;
53a5960a 3596 struct target_flock *target_fl;
43f238d7
TS
3597 struct flock64 fl64;
3598 struct target_flock64 *target_fl64;
992f48a0 3599 abi_long ret;
53a5960a 3600
7775e9ec
FB
3601 switch(cmd) {
3602 case TARGET_F_GETLK:
579a97f7
FB
3603 if (!lock_user_struct(VERIFY_READ, target_fl, arg, 1))
3604 return -TARGET_EFAULT;
5813427b
TS
3605 fl.l_type = tswap16(target_fl->l_type);
3606 fl.l_whence = tswap16(target_fl->l_whence);
3607 fl.l_start = tswapl(target_fl->l_start);
3608 fl.l_len = tswapl(target_fl->l_len);
3609 fl.l_pid = tswapl(target_fl->l_pid);
3610 unlock_user_struct(target_fl, arg, 0);
9ee1fa2c 3611 ret = get_errno(fcntl(fd, cmd, &fl));
7775e9ec 3612 if (ret == 0) {
579a97f7
FB
3613 if (!lock_user_struct(VERIFY_WRITE, target_fl, arg, 0))
3614 return -TARGET_EFAULT;
7775e9ec
FB
3615 target_fl->l_type = tswap16(fl.l_type);
3616 target_fl->l_whence = tswap16(fl.l_whence);
3617 target_fl->l_start = tswapl(fl.l_start);
3618 target_fl->l_len = tswapl(fl.l_len);
3619 target_fl->l_pid = tswapl(fl.l_pid);
53a5960a 3620 unlock_user_struct(target_fl, arg, 1);
7775e9ec
FB
3621 }
3622 break;
3b46e624 3623
7775e9ec
FB
3624 case TARGET_F_SETLK:
3625 case TARGET_F_SETLKW:
579a97f7
FB
3626 if (!lock_user_struct(VERIFY_READ, target_fl, arg, 1))
3627 return -TARGET_EFAULT;
7775e9ec
FB
3628 fl.l_type = tswap16(target_fl->l_type);
3629 fl.l_whence = tswap16(target_fl->l_whence);
3630 fl.l_start = tswapl(target_fl->l_start);
3631 fl.l_len = tswapl(target_fl->l_len);
3632 fl.l_pid = tswapl(target_fl->l_pid);
53a5960a 3633 unlock_user_struct(target_fl, arg, 0);
9ee1fa2c 3634 ret = get_errno(fcntl(fd, cmd, &fl));
7775e9ec 3635 break;
3b46e624 3636
7775e9ec 3637 case TARGET_F_GETLK64:
579a97f7
FB
3638 if (!lock_user_struct(VERIFY_READ, target_fl64, arg, 1))
3639 return -TARGET_EFAULT;
5813427b
TS
3640 fl64.l_type = tswap16(target_fl64->l_type) >> 1;
3641 fl64.l_whence = tswap16(target_fl64->l_whence);
3642 fl64.l_start = tswapl(target_fl64->l_start);
3643 fl64.l_len = tswapl(target_fl64->l_len);
3644 fl64.l_pid = tswap16(target_fl64->l_pid);
3645 unlock_user_struct(target_fl64, arg, 0);
9ee1fa2c 3646 ret = get_errno(fcntl(fd, cmd >> 1, &fl64));
43f238d7 3647 if (ret == 0) {
579a97f7
FB
3648 if (!lock_user_struct(VERIFY_WRITE, target_fl64, arg, 0))
3649 return -TARGET_EFAULT;
43f238d7
TS
3650 target_fl64->l_type = tswap16(fl64.l_type) >> 1;
3651 target_fl64->l_whence = tswap16(fl64.l_whence);
3652 target_fl64->l_start = tswapl(fl64.l_start);
3653 target_fl64->l_len = tswapl(fl64.l_len);
3654 target_fl64->l_pid = tswapl(fl64.l_pid);
3655 unlock_user_struct(target_fl64, arg, 1);
3656 }
9ee1fa2c 3657 break;
7775e9ec
FB
3658 case TARGET_F_SETLK64:
3659 case TARGET_F_SETLKW64:
579a97f7
FB
3660 if (!lock_user_struct(VERIFY_READ, target_fl64, arg, 1))
3661 return -TARGET_EFAULT;
43f238d7
TS
3662 fl64.l_type = tswap16(target_fl64->l_type) >> 1;
3663 fl64.l_whence = tswap16(target_fl64->l_whence);
3664 fl64.l_start = tswapl(target_fl64->l_start);
3665 fl64.l_len = tswapl(target_fl64->l_len);
3666 fl64.l_pid = tswap16(target_fl64->l_pid);
3667 unlock_user_struct(target_fl64, arg, 0);
9ee1fa2c 3668 ret = get_errno(fcntl(fd, cmd >> 1, &fl64));
7775e9ec
FB
3669 break;
3670
ffa65c3b 3671 case F_GETFL:
9ee1fa2c
FB
3672 ret = get_errno(fcntl(fd, cmd, arg));
3673 if (ret >= 0) {
3674 ret = host_to_target_bitmask(ret, fcntl_flags_tbl);
3675 }
ffa65c3b
FB
3676 break;
3677
3678 case F_SETFL:
9ee1fa2c 3679 ret = get_errno(fcntl(fd, cmd, target_to_host_bitmask(arg, fcntl_flags_tbl)));
ffa65c3b
FB
3680 break;
3681
7775e9ec 3682 default:
9ee1fa2c 3683 ret = get_errno(fcntl(fd, cmd, arg));
7775e9ec
FB
3684 break;
3685 }
3686 return ret;
3687}
3688
67867308 3689#ifdef USE_UID16
7775e9ec 3690
67867308
FB
3691static inline int high2lowuid(int uid)
3692{
3693 if (uid > 65535)
3694 return 65534;
3695 else
3696 return uid;
3697}
3698
3699static inline int high2lowgid(int gid)
3700{
3701 if (gid > 65535)
3702 return 65534;
3703 else
3704 return gid;
3705}
3706
3707static inline int low2highuid(int uid)
3708{
3709 if ((int16_t)uid == -1)
3710 return -1;
3711 else
3712 return uid;
3713}
3714
3715static inline int low2highgid(int gid)
3716{
3717 if ((int16_t)gid == -1)
3718 return -1;
3719 else
3720 return gid;
3721}
3722
3723#endif /* USE_UID16 */
1b6b029e 3724
31e31b8a
FB
3725void syscall_init(void)
3726{
2ab83ea7
FB
3727 IOCTLEntry *ie;
3728 const argtype *arg_type;
3729 int size;
b92c47c1 3730 int i;
2ab83ea7 3731
001faf32 3732#define STRUCT(name, ...) thunk_register_struct(STRUCT_ ## name, #name, struct_ ## name ## _def);
5fafdf24 3733#define STRUCT_SPECIAL(name) thunk_register_struct_direct(STRUCT_ ## name, #name, &struct_ ## name ## _def);
31e31b8a
FB
3734#include "syscall_types.h"
3735#undef STRUCT
3736#undef STRUCT_SPECIAL
2ab83ea7
FB
3737
3738 /* we patch the ioctl size if necessary. We rely on the fact that
3739 no ioctl has all the bits at '1' in the size field */
3740 ie = ioctl_entries;
3741 while (ie->target_cmd != 0) {
3742 if (((ie->target_cmd >> TARGET_IOC_SIZESHIFT) & TARGET_IOC_SIZEMASK) ==
3743 TARGET_IOC_SIZEMASK) {
3744 arg_type = ie->arg_type;
3745 if (arg_type[0] != TYPE_PTR) {
5fafdf24 3746 fprintf(stderr, "cannot patch size for ioctl 0x%x\n",
2ab83ea7
FB
3747 ie->target_cmd);
3748 exit(1);
3749 }
3750 arg_type++;
3751 size = thunk_type_size(arg_type, 0);
5fafdf24 3752 ie->target_cmd = (ie->target_cmd &
2ab83ea7
FB
3753 ~(TARGET_IOC_SIZEMASK << TARGET_IOC_SIZESHIFT)) |
3754 (size << TARGET_IOC_SIZESHIFT);
3755 }
b92c47c1
TS
3756
3757 /* Build target_to_host_errno_table[] table from
3758 * host_to_target_errno_table[]. */
3759 for (i=0; i < ERRNO_TABLE_SIZE; i++)
3760 target_to_host_errno_table[host_to_target_errno_table[i]] = i;
3761
2ab83ea7 3762 /* automatic consistency check if same arch */
872ea0c0
AZ
3763#if (defined(__i386__) && defined(TARGET_I386) && defined(TARGET_ABI32)) || \
3764 (defined(__x86_64__) && defined(TARGET_X86_64))
3765 if (unlikely(ie->target_cmd != ie->host_cmd)) {
3766 fprintf(stderr, "ERROR: ioctl(%s): target=0x%x host=0x%x\n",
3767 ie->name, ie->target_cmd, ie->host_cmd);
2ab83ea7
FB
3768 }
3769#endif
3770 ie++;
3771 }
31e31b8a 3772}
c573ff67 3773
992f48a0 3774#if TARGET_ABI_BITS == 32
ce4defa0
PB
3775static inline uint64_t target_offset64(uint32_t word0, uint32_t word1)
3776{
af325d36 3777#ifdef TARGET_WORDS_BIGENDIAN
ce4defa0
PB
3778 return ((uint64_t)word0 << 32) | word1;
3779#else
3780 return ((uint64_t)word1 << 32) | word0;
3781#endif
3782}
992f48a0 3783#else /* TARGET_ABI_BITS == 32 */
32407103
JM
3784static inline uint64_t target_offset64(uint64_t word0, uint64_t word1)
3785{
3786 return word0;
3787}
992f48a0 3788#endif /* TARGET_ABI_BITS != 32 */
ce4defa0
PB
3789
3790#ifdef TARGET_NR_truncate64
992f48a0
BS
3791static inline abi_long target_truncate64(void *cpu_env, const char *arg1,
3792 abi_long arg2,
3793 abi_long arg3,
3794 abi_long arg4)
ce4defa0
PB
3795{
3796#ifdef TARGET_ARM
3797 if (((CPUARMState *)cpu_env)->eabi)
3798 {
3799 arg2 = arg3;
3800 arg3 = arg4;
3801 }
3802#endif
3803 return get_errno(truncate64(arg1, target_offset64(arg2, arg3)));
3804}
3805#endif
3806
3807#ifdef TARGET_NR_ftruncate64
992f48a0
BS
3808static inline abi_long target_ftruncate64(void *cpu_env, abi_long arg1,
3809 abi_long arg2,
3810 abi_long arg3,
3811 abi_long arg4)
ce4defa0
PB
3812{
3813#ifdef TARGET_ARM
3814 if (((CPUARMState *)cpu_env)->eabi)
3815 {
3816 arg2 = arg3;
3817 arg3 = arg4;
3818 }
3819#endif
3820 return get_errno(ftruncate64(arg1, target_offset64(arg2, arg3)));
3821}
3822#endif
3823
579a97f7
FB
3824static inline abi_long target_to_host_timespec(struct timespec *host_ts,
3825 abi_ulong target_addr)
53a5960a
PB
3826{
3827 struct target_timespec *target_ts;
3828
579a97f7
FB
3829 if (!lock_user_struct(VERIFY_READ, target_ts, target_addr, 1))
3830 return -TARGET_EFAULT;
53a5960a
PB
3831 host_ts->tv_sec = tswapl(target_ts->tv_sec);
3832 host_ts->tv_nsec = tswapl(target_ts->tv_nsec);
3833 unlock_user_struct(target_ts, target_addr, 0);
b255bfa8 3834 return 0;
53a5960a
PB
3835}
3836
579a97f7
FB
3837static inline abi_long host_to_target_timespec(abi_ulong target_addr,
3838 struct timespec *host_ts)
53a5960a
PB
3839{
3840 struct target_timespec *target_ts;
3841
579a97f7
FB
3842 if (!lock_user_struct(VERIFY_WRITE, target_ts, target_addr, 0))
3843 return -TARGET_EFAULT;
53a5960a
PB
3844 target_ts->tv_sec = tswapl(host_ts->tv_sec);
3845 target_ts->tv_nsec = tswapl(host_ts->tv_nsec);
3846 unlock_user_struct(target_ts, target_addr, 1);
b255bfa8 3847 return 0;
53a5960a
PB
3848}
3849
9d33b76b 3850#if defined(TARGET_NR_stat64) || defined(TARGET_NR_newfstatat)
6a24a778
AZ
3851static inline abi_long host_to_target_stat64(void *cpu_env,
3852 abi_ulong target_addr,
3853 struct stat *host_st)
3854{
3855#ifdef TARGET_ARM
3856 if (((CPUARMState *)cpu_env)->eabi) {
3857 struct target_eabi_stat64 *target_st;
3858
3859 if (!lock_user_struct(VERIFY_WRITE, target_st, target_addr, 0))
3860 return -TARGET_EFAULT;
3861 memset(target_st, 0, sizeof(struct target_eabi_stat64));
3862 __put_user(host_st->st_dev, &target_st->st_dev);
3863 __put_user(host_st->st_ino, &target_st->st_ino);
3864#ifdef TARGET_STAT64_HAS_BROKEN_ST_INO
3865 __put_user(host_st->st_ino, &target_st->__st_ino);
3866#endif
3867 __put_user(host_st->st_mode, &target_st->st_mode);
3868 __put_user(host_st->st_nlink, &target_st->st_nlink);
3869 __put_user(host_st->st_uid, &target_st->st_uid);
3870 __put_user(host_st->st_gid, &target_st->st_gid);
3871 __put_user(host_st->st_rdev, &target_st->st_rdev);
3872 __put_user(host_st->st_size, &target_st->st_size);
3873 __put_user(host_st->st_blksize, &target_st->st_blksize);
3874 __put_user(host_st->st_blocks, &target_st->st_blocks);
3875 __put_user(host_st->st_atime, &target_st->target_st_atime);
3876 __put_user(host_st->st_mtime, &target_st->target_st_mtime);
3877 __put_user(host_st->st_ctime, &target_st->target_st_ctime);
3878 unlock_user_struct(target_st, target_addr, 1);
3879 } else
3880#endif
3881 {
9d33b76b
AJ
3882#if TARGET_LONG_BITS == 64
3883 struct target_stat *target_st;
3884#else
6a24a778 3885 struct target_stat64 *target_st;
9d33b76b 3886#endif
6a24a778
AZ
3887
3888 if (!lock_user_struct(VERIFY_WRITE, target_st, target_addr, 0))
3889 return -TARGET_EFAULT;
9d33b76b 3890 memset(target_st, 0, sizeof(*target_st));
6a24a778
AZ
3891 __put_user(host_st->st_dev, &target_st->st_dev);
3892 __put_user(host_st->st_ino, &target_st->st_ino);
3893#ifdef TARGET_STAT64_HAS_BROKEN_ST_INO
3894 __put_user(host_st->st_ino, &target_st->__st_ino);
3895#endif
3896 __put_user(host_st->st_mode, &target_st->st_mode);
3897 __put_user(host_st->st_nlink, &target_st->st_nlink);
3898 __put_user(host_st->st_uid, &target_st->st_uid);
3899 __put_user(host_st->st_gid, &target_st->st_gid);
3900 __put_user(host_st->st_rdev, &target_st->st_rdev);
3901 /* XXX: better use of kernel struct */
3902 __put_user(host_st->st_size, &target_st->st_size);
3903 __put_user(host_st->st_blksize, &target_st->st_blksize);
3904 __put_user(host_st->st_blocks, &target_st->st_blocks);
3905 __put_user(host_st->st_atime, &target_st->target_st_atime);
3906 __put_user(host_st->st_mtime, &target_st->target_st_mtime);
3907 __put_user(host_st->st_ctime, &target_st->target_st_ctime);
3908 unlock_user_struct(target_st, target_addr, 1);
3909 }
3910
3911 return 0;
3912}
3913#endif
3914
bd0c5661
PB
3915#if defined(USE_NPTL)
3916/* ??? Using host futex calls even when target atomic operations
3917 are not really atomic probably breaks things. However implementing
3918 futexes locally would make futexes shared between multiple processes
3919 tricky. However they're probably useless because guest atomic
3920 operations won't work either. */
8fcd3692
BS
3921static int do_futex(target_ulong uaddr, int op, int val, target_ulong timeout,
3922 target_ulong uaddr2, int val3)
bd0c5661
PB
3923{
3924 struct timespec ts, *pts;
3925
3926 /* ??? We assume FUTEX_* constants are the same on both host
3927 and target. */
3928 switch (op) {
3929 case FUTEX_WAIT:
3930 if (timeout) {
3931 pts = &ts;
3932 target_to_host_timespec(pts, timeout);
3933 } else {
3934 pts = NULL;
3935 }
3936 return get_errno(sys_futex(g2h(uaddr), FUTEX_WAIT, tswap32(val),
3937 pts, NULL, 0));
3938 case FUTEX_WAKE:
3939 return get_errno(sys_futex(g2h(uaddr), FUTEX_WAKE, val, NULL, NULL, 0));
3940 case FUTEX_FD:
3941 return get_errno(sys_futex(g2h(uaddr), FUTEX_FD, val, NULL, NULL, 0));
3942 case FUTEX_REQUEUE:
3943 return get_errno(sys_futex(g2h(uaddr), FUTEX_REQUEUE, val,
3944 NULL, g2h(uaddr2), 0));
3945 case FUTEX_CMP_REQUEUE:
3946 return get_errno(sys_futex(g2h(uaddr), FUTEX_CMP_REQUEUE, val,
3947 NULL, g2h(uaddr2), tswap32(val3)));
3948 default:
3949 return -TARGET_ENOSYS;
3950 }
3951}
3952#endif
3953
1d9d8b55
PB
3954/* Map host to target signal numbers for the wait family of syscalls.
3955 Assume all other status bits are the same. */
3956static int host_to_target_waitstatus(int status)
3957{
3958 if (WIFSIGNALED(status)) {
3959 return host_to_target_signal(WTERMSIG(status)) | (status & ~0x7f);
3960 }
3961 if (WIFSTOPPED(status)) {
3962 return (host_to_target_signal(WSTOPSIG(status)) << 8)
3963 | (status & 0xff);
3964 }
3965 return status;
3966}
3967
a745ec6d
PB
3968int get_osversion(void)
3969{
3970 static int osversion;
3971 struct new_utsname buf;
3972 const char *s;
3973 int i, n, tmp;
3974 if (osversion)
3975 return osversion;
3976 if (qemu_uname_release && *qemu_uname_release) {
3977 s = qemu_uname_release;
3978 } else {
3979 if (sys_uname(&buf))
3980 return 0;
3981 s = buf.release;
3982 }
3983 tmp = 0;
3984 for (i = 0; i < 3; i++) {
3985 n = 0;
3986 while (*s >= '0' && *s <= '9') {
3987 n *= 10;
3988 n += *s - '0';
3989 s++;
3990 }
3991 tmp = (tmp << 8) + n;
3992 if (*s == '.')
3993 s++;
3994 }
3995 osversion = tmp;
3996 return osversion;
3997}
3998
0da46a6e
TS
3999/* do_syscall() should always have a single exit point at the end so
4000 that actions, such as logging of syscall results, can be performed.
4001 All errnos that do_syscall() returns must be -TARGET_<errcode>. */
992f48a0
BS
4002abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
4003 abi_long arg2, abi_long arg3, abi_long arg4,
4004 abi_long arg5, abi_long arg6)
31e31b8a 4005{
992f48a0 4006 abi_long ret;
31e31b8a 4007 struct stat st;
56c8f68f 4008 struct statfs stfs;
53a5960a 4009 void *p;
3b46e624 4010
72f03900 4011#ifdef DEBUG
c573ff67 4012 gemu_log("syscall %d", num);
72f03900 4013#endif
b92c47c1
TS
4014 if(do_strace)
4015 print_syscall(num, arg1, arg2, arg3, arg4, arg5, arg6);
4016
31e31b8a
FB
4017 switch(num) {
4018 case TARGET_NR_exit:
c2764719
PB
4019#ifdef USE_NPTL
4020 /* In old applications this may be used to implement _exit(2).
4021 However in threaded applictions it is used for thread termination,
4022 and _exit_group is used for application termination.
4023 Do thread termination if we have more then one thread. */
4024 /* FIXME: This probably breaks if a signal arrives. We should probably
4025 be disabling signals. */
4026 if (first_cpu->next_cpu) {
1e9fa730 4027 TaskState *ts;
c2764719
PB
4028 CPUState **lastp;
4029 CPUState *p;
4030
4031 cpu_list_lock();
4032 lastp = &first_cpu;
4033 p = first_cpu;
4034 while (p && p != (CPUState *)cpu_env) {
4035 lastp = &p->next_cpu;
4036 p = p->next_cpu;
4037 }
4038 /* If we didn't find the CPU for this thread then something is
4039 horribly wrong. */
4040 if (!p)
4041 abort();
4042 /* Remove the CPU from the list. */
4043 *lastp = p->next_cpu;
4044 cpu_list_unlock();
1e9fa730 4045 ts = ((CPUState *)cpu_env)->opaque;
c2764719
PB
4046 if (ts->child_tidptr) {
4047 put_user_u32(0, ts->child_tidptr);
4048 sys_futex(g2h(ts->child_tidptr), FUTEX_WAKE, INT_MAX,
4049 NULL, NULL, 0);
4050 }
4051 /* TODO: Free CPU state. */
4052 pthread_exit(NULL);
4053 }
4054#endif
7d13299d
FB
4055#ifdef HAVE_GPROF
4056 _mcleanup();
4057#endif
e9009676 4058 gdb_exit(cpu_env, arg1);
c2764719 4059 _exit(arg1);
31e31b8a
FB
4060 ret = 0; /* avoid warning */
4061 break;
4062 case TARGET_NR_read:
38d840e6
AJ
4063 if (arg3 == 0)
4064 ret = 0;
4065 else {
4066 if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
4067 goto efault;
4068 ret = get_errno(read(arg1, p, arg3));
4069 unlock_user(p, arg2, ret);
4070 }
31e31b8a
FB
4071 break;
4072 case TARGET_NR_write:
579a97f7
FB
4073 if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
4074 goto efault;
53a5960a
PB
4075 ret = get_errno(write(arg1, p, arg3));
4076 unlock_user(p, arg2, 0);
31e31b8a
FB
4077 break;
4078 case TARGET_NR_open:
2f619698
FB
4079 if (!(p = lock_user_string(arg1)))
4080 goto efault;
53a5960a 4081 ret = get_errno(open(path(p),
ffa65c3b
FB
4082 target_to_host_bitmask(arg2, fcntl_flags_tbl),
4083 arg3));
53a5960a 4084 unlock_user(p, arg1, 0);
31e31b8a 4085 break;
82424832
TS
4086#if defined(TARGET_NR_openat) && defined(__NR_openat)
4087 case TARGET_NR_openat:
579a97f7
FB
4088 if (!(p = lock_user_string(arg2)))
4089 goto efault;
4090 ret = get_errno(sys_openat(arg1,
4091 path(p),
4092 target_to_host_bitmask(arg3, fcntl_flags_tbl),
4093 arg4));
4094 unlock_user(p, arg2, 0);
82424832
TS
4095 break;
4096#endif
31e31b8a
FB
4097 case TARGET_NR_close:
4098 ret = get_errno(close(arg1));
4099 break;
4100 case TARGET_NR_brk:
53a5960a 4101 ret = do_brk(arg1);
31e31b8a
FB
4102 break;
4103 case TARGET_NR_fork:
d865bab5 4104 ret = get_errno(do_fork(cpu_env, SIGCHLD, 0, 0, 0, 0));
31e31b8a 4105 break;
e5febef5 4106#ifdef TARGET_NR_waitpid
31e31b8a
FB
4107 case TARGET_NR_waitpid:
4108 {
53a5960a
PB
4109 int status;
4110 ret = get_errno(waitpid(arg1, &status, arg3));
2f619698 4111 if (!is_error(ret) && arg2
1d9d8b55 4112 && put_user_s32(host_to_target_waitstatus(status), arg2))
2f619698 4113 goto efault;
31e31b8a
FB
4114 }
4115 break;
e5febef5 4116#endif
f0cbb613
PB
4117#ifdef TARGET_NR_waitid
4118 case TARGET_NR_waitid:
4119 {
4120 siginfo_t info;
4121 info.si_pid = 0;
4122 ret = get_errno(waitid(arg1, arg2, &info, arg4));
4123 if (!is_error(ret) && arg3 && info.si_pid != 0) {
4124 if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_siginfo_t), 0)))
4125 goto efault;
4126 host_to_target_siginfo(p, &info);
4127 unlock_user(p, arg3, sizeof(target_siginfo_t));
4128 }
4129 }
4130 break;
4131#endif
7a3148a9 4132#ifdef TARGET_NR_creat /* not on alpha */
31e31b8a 4133 case TARGET_NR_creat:
579a97f7
FB
4134 if (!(p = lock_user_string(arg1)))
4135 goto efault;
53a5960a
PB
4136 ret = get_errno(creat(p, arg2));
4137 unlock_user(p, arg1, 0);
31e31b8a 4138 break;
7a3148a9 4139#endif
31e31b8a 4140 case TARGET_NR_link:
53a5960a
PB
4141 {
4142 void * p2;
4143 p = lock_user_string(arg1);
4144 p2 = lock_user_string(arg2);
579a97f7
FB
4145 if (!p || !p2)
4146 ret = -TARGET_EFAULT;
4147 else
4148 ret = get_errno(link(p, p2));
53a5960a
PB
4149 unlock_user(p2, arg2, 0);
4150 unlock_user(p, arg1, 0);
4151 }
31e31b8a 4152 break;
64f0ce4c
TS
4153#if defined(TARGET_NR_linkat) && defined(__NR_linkat)
4154 case TARGET_NR_linkat:
64f0ce4c
TS
4155 {
4156 void * p2 = NULL;
579a97f7
FB
4157 if (!arg2 || !arg4)
4158 goto efault;
64f0ce4c
TS
4159 p = lock_user_string(arg2);
4160 p2 = lock_user_string(arg4);
579a97f7 4161 if (!p || !p2)
0da46a6e 4162 ret = -TARGET_EFAULT;
64f0ce4c
TS
4163 else
4164 ret = get_errno(sys_linkat(arg1, p, arg3, p2, arg5));
579a97f7
FB
4165 unlock_user(p, arg2, 0);
4166 unlock_user(p2, arg4, 0);
64f0ce4c
TS
4167 }
4168 break;
4169#endif
31e31b8a 4170 case TARGET_NR_unlink:
579a97f7
FB
4171 if (!(p = lock_user_string(arg1)))
4172 goto efault;
53a5960a
PB
4173 ret = get_errno(unlink(p));
4174 unlock_user(p, arg1, 0);
31e31b8a 4175 break;
8170f56b
TS
4176#if defined(TARGET_NR_unlinkat) && defined(__NR_unlinkat)
4177 case TARGET_NR_unlinkat:
579a97f7
FB
4178 if (!(p = lock_user_string(arg2)))
4179 goto efault;
4180 ret = get_errno(sys_unlinkat(arg1, p, arg3));
4181 unlock_user(p, arg2, 0);
ed494d87 4182 break;
b7d35e65 4183#endif
31e31b8a 4184 case TARGET_NR_execve:
7854b056
FB
4185 {
4186 char **argp, **envp;
f7341ff4 4187 int argc, envc;
992f48a0
BS
4188 abi_ulong gp;
4189 abi_ulong guest_argp;
4190 abi_ulong guest_envp;
4191 abi_ulong addr;
7854b056
FB
4192 char **q;
4193
f7341ff4 4194 argc = 0;
53a5960a 4195 guest_argp = arg2;
da94d263 4196 for (gp = guest_argp; gp; gp += sizeof(abi_ulong)) {
03aa1976 4197 if (get_user_ual(addr, gp))
2f619698 4198 goto efault;
03aa1976 4199 if (!addr)
2f619698 4200 break;
7854b056 4201 argc++;
2f619698 4202 }
f7341ff4 4203 envc = 0;
53a5960a 4204 guest_envp = arg3;
da94d263 4205 for (gp = guest_envp; gp; gp += sizeof(abi_ulong)) {
03aa1976 4206 if (get_user_ual(addr, gp))
2f619698 4207 goto efault;
03aa1976 4208 if (!addr)
2f619698 4209 break;
7854b056 4210 envc++;
2f619698 4211 }
7854b056 4212
f7341ff4
FB
4213 argp = alloca((argc + 1) * sizeof(void *));
4214 envp = alloca((envc + 1) * sizeof(void *));
7854b056 4215
da94d263 4216 for (gp = guest_argp, q = argp; gp;
992f48a0 4217 gp += sizeof(abi_ulong), q++) {
2f619698
FB
4218 if (get_user_ual(addr, gp))
4219 goto execve_efault;
53a5960a
PB
4220 if (!addr)
4221 break;
2f619698
FB
4222 if (!(*q = lock_user_string(addr)))
4223 goto execve_efault;
53a5960a 4224 }
f7341ff4
FB
4225 *q = NULL;
4226
da94d263 4227 for (gp = guest_envp, q = envp; gp;
992f48a0 4228 gp += sizeof(abi_ulong), q++) {
2f619698
FB
4229 if (get_user_ual(addr, gp))
4230 goto execve_efault;
53a5960a
PB
4231 if (!addr)
4232 break;
2f619698
FB
4233 if (!(*q = lock_user_string(addr)))
4234 goto execve_efault;
53a5960a 4235 }
f7341ff4 4236 *q = NULL;
7854b056 4237
2f619698
FB
4238 if (!(p = lock_user_string(arg1)))
4239 goto execve_efault;
53a5960a
PB
4240 ret = get_errno(execve(p, argp, envp));
4241 unlock_user(p, arg1, 0);
4242
2f619698
FB
4243 goto execve_end;
4244
4245 execve_efault:
4246 ret = -TARGET_EFAULT;
4247
4248 execve_end:
53a5960a 4249 for (gp = guest_argp, q = argp; *q;
992f48a0 4250 gp += sizeof(abi_ulong), q++) {
2f619698
FB
4251 if (get_user_ual(addr, gp)
4252 || !addr)
4253 break;
53a5960a
PB
4254 unlock_user(*q, addr, 0);
4255 }
4256 for (gp = guest_envp, q = envp; *q;
992f48a0 4257 gp += sizeof(abi_ulong), q++) {
2f619698
FB
4258 if (get_user_ual(addr, gp)
4259 || !addr)
4260 break;
53a5960a
PB
4261 unlock_user(*q, addr, 0);
4262 }
7854b056 4263 }
31e31b8a
FB
4264 break;
4265 case TARGET_NR_chdir:
579a97f7
FB
4266 if (!(p = lock_user_string(arg1)))
4267 goto efault;
53a5960a
PB
4268 ret = get_errno(chdir(p));
4269 unlock_user(p, arg1, 0);
31e31b8a 4270 break;
a315a145 4271#ifdef TARGET_NR_time
31e31b8a
FB
4272 case TARGET_NR_time:
4273 {
53a5960a
PB
4274 time_t host_time;
4275 ret = get_errno(time(&host_time));
2f619698
FB
4276 if (!is_error(ret)
4277 && arg1
4278 && put_user_sal(host_time, arg1))
4279 goto efault;
31e31b8a
FB
4280 }
4281 break;
a315a145 4282#endif
31e31b8a 4283 case TARGET_NR_mknod:
579a97f7
FB
4284 if (!(p = lock_user_string(arg1)))
4285 goto efault;
53a5960a
PB
4286 ret = get_errno(mknod(p, arg2, arg3));
4287 unlock_user(p, arg1, 0);
31e31b8a 4288 break;
75ac37a0
TS
4289#if defined(TARGET_NR_mknodat) && defined(__NR_mknodat)
4290 case TARGET_NR_mknodat:
579a97f7
FB
4291 if (!(p = lock_user_string(arg2)))
4292 goto efault;
4293 ret = get_errno(sys_mknodat(arg1, p, arg3, arg4));
4294 unlock_user(p, arg2, 0);
75ac37a0
TS
4295 break;
4296#endif
31e31b8a 4297 case TARGET_NR_chmod:
579a97f7
FB
4298 if (!(p = lock_user_string(arg1)))
4299 goto efault;
53a5960a
PB
4300 ret = get_errno(chmod(p, arg2));
4301 unlock_user(p, arg1, 0);
31e31b8a 4302 break;
ebc05488 4303#ifdef TARGET_NR_break
31e31b8a
FB
4304 case TARGET_NR_break:
4305 goto unimplemented;
ebc05488
FB
4306#endif
4307#ifdef TARGET_NR_oldstat
31e31b8a
FB
4308 case TARGET_NR_oldstat:
4309 goto unimplemented;
ebc05488 4310#endif
31e31b8a
FB
4311 case TARGET_NR_lseek:
4312 ret = get_errno(lseek(arg1, arg2, arg3));
4313 break;
7a3148a9
JM
4314#ifdef TARGET_NR_getxpid
4315 case TARGET_NR_getxpid:
4316#else
31e31b8a 4317 case TARGET_NR_getpid:
7a3148a9 4318#endif
31e31b8a
FB
4319 ret = get_errno(getpid());
4320 break;
4321 case TARGET_NR_mount:
80265918
TS
4322 {
4323 /* need to look at the data field */
4324 void *p2, *p3;
4325 p = lock_user_string(arg1);
4326 p2 = lock_user_string(arg2);
4327 p3 = lock_user_string(arg3);
579a97f7
FB
4328 if (!p || !p2 || !p3)
4329 ret = -TARGET_EFAULT;
4330 else
4331 /* FIXME - arg5 should be locked, but it isn't clear how to
4332 * do that since it's not guaranteed to be a NULL-terminated
4333 * string.
4334 */
4335 ret = get_errno(mount(p, p2, p3, (unsigned long)arg4, g2h(arg5)));
4336 unlock_user(p, arg1, 0);
4337 unlock_user(p2, arg2, 0);
4338 unlock_user(p3, arg3, 0);
80265918
TS
4339 break;
4340 }
e5febef5 4341#ifdef TARGET_NR_umount
31e31b8a 4342 case TARGET_NR_umount:
579a97f7
FB
4343 if (!(p = lock_user_string(arg1)))
4344 goto efault;
53a5960a
PB
4345 ret = get_errno(umount(p));
4346 unlock_user(p, arg1, 0);
31e31b8a 4347 break;
e5febef5 4348#endif
7a3148a9 4349#ifdef TARGET_NR_stime /* not on alpha */
31e31b8a
FB
4350 case TARGET_NR_stime:
4351 {
53a5960a 4352 time_t host_time;
2f619698
FB
4353 if (get_user_sal(host_time, arg1))
4354 goto efault;
53a5960a 4355 ret = get_errno(stime(&host_time));
31e31b8a
FB
4356 }
4357 break;
7a3148a9 4358#endif
31e31b8a
FB
4359 case TARGET_NR_ptrace:
4360 goto unimplemented;
7a3148a9 4361#ifdef TARGET_NR_alarm /* not on alpha */
31e31b8a
FB
4362 case TARGET_NR_alarm:
4363 ret = alarm(arg1);
4364 break;
7a3148a9 4365#endif
ebc05488 4366#ifdef TARGET_NR_oldfstat
31e31b8a
FB
4367 case TARGET_NR_oldfstat:
4368 goto unimplemented;
ebc05488 4369#endif
7a3148a9 4370#ifdef TARGET_NR_pause /* not on alpha */
31e31b8a
FB
4371 case TARGET_NR_pause:
4372 ret = get_errno(pause());
4373 break;
7a3148a9 4374#endif
e5febef5 4375#ifdef TARGET_NR_utime
31e31b8a 4376 case TARGET_NR_utime:
ebc05488 4377 {
53a5960a
PB
4378 struct utimbuf tbuf, *host_tbuf;
4379 struct target_utimbuf *target_tbuf;
4380 if (arg2) {
579a97f7
FB
4381 if (!lock_user_struct(VERIFY_READ, target_tbuf, arg2, 1))
4382 goto efault;
53a5960a
PB
4383 tbuf.actime = tswapl(target_tbuf->actime);
4384 tbuf.modtime = tswapl(target_tbuf->modtime);
4385 unlock_user_struct(target_tbuf, arg2, 0);
4386 host_tbuf = &tbuf;
f72e8ff4 4387 } else {
53a5960a 4388 host_tbuf = NULL;
f72e8ff4 4389 }
579a97f7
FB
4390 if (!(p = lock_user_string(arg1)))
4391 goto efault;
53a5960a
PB
4392 ret = get_errno(utime(p, host_tbuf));
4393 unlock_user(p, arg1, 0);
ebc05488
FB
4394 }
4395 break;
e5febef5 4396#endif
978a66ff
FB
4397 case TARGET_NR_utimes:
4398 {
978a66ff 4399 struct timeval *tvp, tv[2];
53a5960a 4400 if (arg2) {
788f5ec4
TS
4401 if (copy_from_user_timeval(&tv[0], arg2)
4402 || copy_from_user_timeval(&tv[1],
4403 arg2 + sizeof(struct target_timeval)))
4404 goto efault;
978a66ff
FB
4405 tvp = tv;
4406 } else {
4407 tvp = NULL;
4408 }
579a97f7
FB
4409 if (!(p = lock_user_string(arg1)))
4410 goto efault;
53a5960a
PB
4411 ret = get_errno(utimes(p, tvp));
4412 unlock_user(p, arg1, 0);
978a66ff
FB
4413 }
4414 break;
ac8a6556
AZ
4415#if defined(TARGET_NR_futimesat) && defined(__NR_futimesat)
4416 case TARGET_NR_futimesat:
4417 {
4418 struct timeval *tvp, tv[2];
4419 if (arg3) {
4420 if (copy_from_user_timeval(&tv[0], arg3)
4421 || copy_from_user_timeval(&tv[1],
4422 arg3 + sizeof(struct target_timeval)))
4423 goto efault;
4424 tvp = tv;
4425 } else {
4426 tvp = NULL;
4427 }
4428 if (!(p = lock_user_string(arg2)))
4429 goto efault;
4430 ret = get_errno(sys_futimesat(arg1, path(p), tvp));
4431 unlock_user(p, arg2, 0);
4432 }
4433 break;
4434#endif
ebc05488 4435#ifdef TARGET_NR_stty
31e31b8a
FB
4436 case TARGET_NR_stty:
4437 goto unimplemented;
ebc05488
FB
4438#endif
4439#ifdef TARGET_NR_gtty
31e31b8a
FB
4440 case TARGET_NR_gtty:
4441 goto unimplemented;
ebc05488 4442#endif
31e31b8a 4443 case TARGET_NR_access:
579a97f7
FB
4444 if (!(p = lock_user_string(arg1)))
4445 goto efault;
53a5960a
PB
4446 ret = get_errno(access(p, arg2));
4447 unlock_user(p, arg1, 0);
31e31b8a 4448 break;
92a34c10
TS
4449#if defined(TARGET_NR_faccessat) && defined(__NR_faccessat)
4450 case TARGET_NR_faccessat:
579a97f7
FB
4451 if (!(p = lock_user_string(arg2)))
4452 goto efault;
465c9f06 4453 ret = get_errno(sys_faccessat(arg1, p, arg3));
579a97f7 4454 unlock_user(p, arg2, 0);
92a34c10
TS
4455 break;
4456#endif
7a3148a9 4457#ifdef TARGET_NR_nice /* not on alpha */
31e31b8a
FB
4458 case TARGET_NR_nice:
4459 ret = get_errno(nice(arg1));
4460 break;
7a3148a9 4461#endif
ebc05488 4462#ifdef TARGET_NR_ftime
31e31b8a
FB
4463 case TARGET_NR_ftime:
4464 goto unimplemented;
ebc05488 4465#endif
31e31b8a 4466 case TARGET_NR_sync:
04369ff2
FB
4467 sync();
4468 ret = 0;
31e31b8a
FB
4469 break;
4470 case TARGET_NR_kill:
4cb05961 4471 ret = get_errno(kill(arg1, target_to_host_signal(arg2)));
31e31b8a
FB
4472 break;
4473 case TARGET_NR_rename:
53a5960a
PB
4474 {
4475 void *p2;
4476 p = lock_user_string(arg1);
4477 p2 = lock_user_string(arg2);
579a97f7
FB
4478 if (!p || !p2)
4479 ret = -TARGET_EFAULT;
4480 else
4481 ret = get_errno(rename(p, p2));
53a5960a
PB
4482 unlock_user(p2, arg2, 0);
4483 unlock_user(p, arg1, 0);
4484 }
31e31b8a 4485 break;
722183f6
TS
4486#if defined(TARGET_NR_renameat) && defined(__NR_renameat)
4487 case TARGET_NR_renameat:
722183f6 4488 {
579a97f7 4489 void *p2;
722183f6
TS
4490 p = lock_user_string(arg2);
4491 p2 = lock_user_string(arg4);
579a97f7 4492 if (!p || !p2)
0da46a6e 4493 ret = -TARGET_EFAULT;
722183f6
TS
4494 else
4495 ret = get_errno(sys_renameat(arg1, p, arg3, p2));
579a97f7
FB
4496 unlock_user(p2, arg4, 0);
4497 unlock_user(p, arg2, 0);
722183f6
TS
4498 }
4499 break;
4500#endif
31e31b8a 4501 case TARGET_NR_mkdir:
579a97f7
FB
4502 if (!(p = lock_user_string(arg1)))
4503 goto efault;
53a5960a
PB
4504 ret = get_errno(mkdir(p, arg2));
4505 unlock_user(p, arg1, 0);
31e31b8a 4506 break;
4472ad0d
TS
4507#if defined(TARGET_NR_mkdirat) && defined(__NR_mkdirat)
4508 case TARGET_NR_mkdirat:
579a97f7
FB
4509 if (!(p = lock_user_string(arg2)))
4510 goto efault;
4511 ret = get_errno(sys_mkdirat(arg1, p, arg3));
4512 unlock_user(p, arg2, 0);
4472ad0d
TS
4513 break;
4514#endif
31e31b8a 4515 case TARGET_NR_rmdir:
579a97f7
FB
4516 if (!(p = lock_user_string(arg1)))
4517 goto efault;
53a5960a
PB
4518 ret = get_errno(rmdir(p));
4519 unlock_user(p, arg1, 0);
31e31b8a
FB
4520 break;
4521 case TARGET_NR_dup:
4522 ret = get_errno(dup(arg1));
4523 break;
4524 case TARGET_NR_pipe:
4525 {
53a5960a
PB
4526 int host_pipe[2];
4527 ret = get_errno(pipe(host_pipe));
31e31b8a 4528 if (!is_error(ret)) {
c12ab05c 4529#if defined(TARGET_MIPS)
ead9360e 4530 CPUMIPSState *env = (CPUMIPSState*)cpu_env;
b5dc7732 4531 env->active_tc.gpr[3] = host_pipe[1];
c12ab05c 4532 ret = host_pipe[0];
b5eff355
AJ
4533#elif defined(TARGET_SH4)
4534 ((CPUSH4State*)cpu_env)->gregs[1] = host_pipe[1];
4535 ret = host_pipe[0];
c12ab05c 4536#else
2f619698
FB
4537 if (put_user_s32(host_pipe[0], arg1)
4538 || put_user_s32(host_pipe[1], arg1 + sizeof(host_pipe[0])))
4539 goto efault;
c12ab05c 4540#endif
31e31b8a
FB
4541 }
4542 }
4543 break;
4544 case TARGET_NR_times:
32f36bce 4545 {
53a5960a 4546 struct target_tms *tmsp;
32f36bce
FB
4547 struct tms tms;
4548 ret = get_errno(times(&tms));
53a5960a 4549 if (arg1) {
579a97f7
FB
4550 tmsp = lock_user(VERIFY_WRITE, arg1, sizeof(struct target_tms), 0);
4551 if (!tmsp)
4552 goto efault;
c596ed17
FB
4553 tmsp->tms_utime = tswapl(host_to_target_clock_t(tms.tms_utime));
4554 tmsp->tms_stime = tswapl(host_to_target_clock_t(tms.tms_stime));
4555 tmsp->tms_cutime = tswapl(host_to_target_clock_t(tms.tms_cutime));
4556 tmsp->tms_cstime = tswapl(host_to_target_clock_t(tms.tms_cstime));
32f36bce 4557 }
c596ed17
FB
4558 if (!is_error(ret))
4559 ret = host_to_target_clock_t(ret);
32f36bce
FB
4560 }
4561 break;
ebc05488 4562#ifdef TARGET_NR_prof
31e31b8a
FB
4563 case TARGET_NR_prof:
4564 goto unimplemented;
ebc05488 4565#endif
e5febef5 4566#ifdef TARGET_NR_signal
31e31b8a
FB
4567 case TARGET_NR_signal:
4568 goto unimplemented;
e5febef5 4569#endif
31e31b8a 4570 case TARGET_NR_acct:
38d840e6
AJ
4571 if (arg1 == 0) {
4572 ret = get_errno(acct(NULL));
4573 } else {
4574 if (!(p = lock_user_string(arg1)))
4575 goto efault;
4576 ret = get_errno(acct(path(p)));
4577 unlock_user(p, arg1, 0);
4578 }
24836689 4579 break;
7a3148a9 4580#ifdef TARGET_NR_umount2 /* not on alpha */
31e31b8a 4581 case TARGET_NR_umount2:
579a97f7
FB
4582 if (!(p = lock_user_string(arg1)))
4583 goto efault;
53a5960a
PB
4584 ret = get_errno(umount2(p, arg2));
4585 unlock_user(p, arg1, 0);
31e31b8a 4586 break;
7a3148a9 4587#endif
ebc05488 4588#ifdef TARGET_NR_lock
31e31b8a
FB
4589 case TARGET_NR_lock:
4590 goto unimplemented;
ebc05488 4591#endif
31e31b8a
FB
4592 case TARGET_NR_ioctl:
4593 ret = do_ioctl(arg1, arg2, arg3);
4594 break;
4595 case TARGET_NR_fcntl:
9ee1fa2c 4596 ret = do_fcntl(arg1, arg2, arg3);
31e31b8a 4597 break;
ebc05488 4598#ifdef TARGET_NR_mpx
31e31b8a
FB
4599 case TARGET_NR_mpx:
4600 goto unimplemented;
ebc05488 4601#endif
31e31b8a
FB
4602 case TARGET_NR_setpgid:
4603 ret = get_errno(setpgid(arg1, arg2));
4604 break;
ebc05488 4605#ifdef TARGET_NR_ulimit
31e31b8a
FB
4606 case TARGET_NR_ulimit:
4607 goto unimplemented;
ebc05488
FB
4608#endif
4609#ifdef TARGET_NR_oldolduname
31e31b8a
FB
4610 case TARGET_NR_oldolduname:
4611 goto unimplemented;
ebc05488 4612#endif
31e31b8a
FB
4613 case TARGET_NR_umask:
4614 ret = get_errno(umask(arg1));
4615 break;
4616 case TARGET_NR_chroot:
579a97f7
FB
4617 if (!(p = lock_user_string(arg1)))
4618 goto efault;
53a5960a
PB
4619 ret = get_errno(chroot(p));
4620 unlock_user(p, arg1, 0);
31e31b8a
FB
4621 break;
4622 case TARGET_NR_ustat:
4623 goto unimplemented;
4624 case TARGET_NR_dup2:
4625 ret = get_errno(dup2(arg1, arg2));
4626 break;
7a3148a9 4627#ifdef TARGET_NR_getppid /* not on alpha */
31e31b8a
FB
4628 case TARGET_NR_getppid:
4629 ret = get_errno(getppid());
4630 break;
7a3148a9 4631#endif
31e31b8a
FB
4632 case TARGET_NR_getpgrp:
4633 ret = get_errno(getpgrp());
4634 break;
4635 case TARGET_NR_setsid:
4636 ret = get_errno(setsid());
4637 break;
e5febef5 4638#ifdef TARGET_NR_sigaction
31e31b8a 4639 case TARGET_NR_sigaction:
31e31b8a 4640 {
388bb21a 4641#if !defined(TARGET_MIPS)
53a5960a 4642 struct target_old_sigaction *old_act;
66fb9763 4643 struct target_sigaction act, oact, *pact;
53a5960a 4644 if (arg2) {
579a97f7
FB
4645 if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1))
4646 goto efault;
66fb9763
FB
4647 act._sa_handler = old_act->_sa_handler;
4648 target_siginitset(&act.sa_mask, old_act->sa_mask);
4649 act.sa_flags = old_act->sa_flags;
4650 act.sa_restorer = old_act->sa_restorer;
53a5960a 4651 unlock_user_struct(old_act, arg2, 0);
66fb9763
FB
4652 pact = &act;
4653 } else {
4654 pact = NULL;
4655 }
4656 ret = get_errno(do_sigaction(arg1, pact, &oact));
53a5960a 4657 if (!is_error(ret) && arg3) {
579a97f7
FB
4658 if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0))
4659 goto efault;
53a5960a
PB
4660 old_act->_sa_handler = oact._sa_handler;
4661 old_act->sa_mask = oact.sa_mask.sig[0];
4662 old_act->sa_flags = oact.sa_flags;
4663 old_act->sa_restorer = oact.sa_restorer;
4664 unlock_user_struct(old_act, arg3, 1);
66fb9763 4665 }
388bb21a 4666#else
106ec879
FB
4667 struct target_sigaction act, oact, *pact, *old_act;
4668
4669 if (arg2) {
579a97f7
FB
4670 if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1))
4671 goto efault;
106ec879
FB
4672 act._sa_handler = old_act->_sa_handler;
4673 target_siginitset(&act.sa_mask, old_act->sa_mask.sig[0]);
4674 act.sa_flags = old_act->sa_flags;
4675 unlock_user_struct(old_act, arg2, 0);
4676 pact = &act;
4677 } else {
4678 pact = NULL;
4679 }
4680
4681 ret = get_errno(do_sigaction(arg1, pact, &oact));
4682
4683 if (!is_error(ret) && arg3) {
579a97f7
FB
4684 if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0))
4685 goto efault;
106ec879
FB
4686 old_act->_sa_handler = oact._sa_handler;
4687 old_act->sa_flags = oact.sa_flags;
4688 old_act->sa_mask.sig[0] = oact.sa_mask.sig[0];
4689 old_act->sa_mask.sig[1] = 0;
4690 old_act->sa_mask.sig[2] = 0;
4691 old_act->sa_mask.sig[3] = 0;
4692 unlock_user_struct(old_act, arg3, 1);
4693 }
388bb21a 4694#endif
31e31b8a
FB
4695 }
4696 break;
e5febef5 4697#endif
66fb9763 4698 case TARGET_NR_rt_sigaction:
53a5960a
PB
4699 {
4700 struct target_sigaction *act;
4701 struct target_sigaction *oact;
4702
579a97f7
FB
4703 if (arg2) {
4704 if (!lock_user_struct(VERIFY_READ, act, arg2, 1))
4705 goto efault;
4706 } else
53a5960a 4707 act = NULL;
579a97f7
FB
4708 if (arg3) {
4709 if (!lock_user_struct(VERIFY_WRITE, oact, arg3, 0)) {
4710 ret = -TARGET_EFAULT;
4711 goto rt_sigaction_fail;
4712 }
4713 } else
53a5960a
PB
4714 oact = NULL;
4715 ret = get_errno(do_sigaction(arg1, act, oact));
579a97f7
FB
4716 rt_sigaction_fail:
4717 if (act)
53a5960a 4718 unlock_user_struct(act, arg2, 0);
579a97f7 4719 if (oact)
53a5960a
PB
4720 unlock_user_struct(oact, arg3, 1);
4721 }
66fb9763 4722 break;
7a3148a9 4723#ifdef TARGET_NR_sgetmask /* not on alpha */
31e31b8a 4724 case TARGET_NR_sgetmask:
66fb9763
FB
4725 {
4726 sigset_t cur_set;
992f48a0 4727 abi_ulong target_set;
66fb9763
FB
4728 sigprocmask(0, NULL, &cur_set);
4729 host_to_target_old_sigset(&target_set, &cur_set);
4730 ret = target_set;
4731 }
4732 break;
7a3148a9
JM
4733#endif
4734#ifdef TARGET_NR_ssetmask /* not on alpha */
31e31b8a 4735 case TARGET_NR_ssetmask:
66fb9763
FB
4736 {
4737 sigset_t set, oset, cur_set;
992f48a0 4738 abi_ulong target_set = arg1;
66fb9763
FB
4739 sigprocmask(0, NULL, &cur_set);
4740 target_to_host_old_sigset(&set, &target_set);
4741 sigorset(&set, &set, &cur_set);
4742 sigprocmask(SIG_SETMASK, &set, &oset);
4743 host_to_target_old_sigset(&target_set, &oset);
4744 ret = target_set;
4745 }
4746 break;
7a3148a9 4747#endif
e5febef5 4748#ifdef TARGET_NR_sigprocmask
66fb9763
FB
4749 case TARGET_NR_sigprocmask:
4750 {
4751 int how = arg1;
4752 sigset_t set, oldset, *set_ptr;
3b46e624 4753
53a5960a 4754 if (arg2) {
66fb9763
FB
4755 switch(how) {
4756 case TARGET_SIG_BLOCK:
4757 how = SIG_BLOCK;
4758 break;
4759 case TARGET_SIG_UNBLOCK:
4760 how = SIG_UNBLOCK;
4761 break;
4762 case TARGET_SIG_SETMASK:
4763 how = SIG_SETMASK;
4764 break;
4765 default:
0da46a6e 4766 ret = -TARGET_EINVAL;
66fb9763
FB
4767 goto fail;
4768 }
579a97f7
FB
4769 if (!(p = lock_user(VERIFY_READ, arg2, sizeof(target_sigset_t), 1)))
4770 goto efault;
53a5960a
PB
4771 target_to_host_old_sigset(&set, p);
4772 unlock_user(p, arg2, 0);
66fb9763
FB
4773 set_ptr = &set;
4774 } else {
4775 how = 0;
4776 set_ptr = NULL;
4777 }
4778 ret = get_errno(sigprocmask(arg1, set_ptr, &oldset));
53a5960a 4779 if (!is_error(ret) && arg3) {
579a97f7
FB
4780 if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0)))
4781 goto efault;
53a5960a
PB
4782 host_to_target_old_sigset(p, &oldset);
4783 unlock_user(p, arg3, sizeof(target_sigset_t));
66fb9763
FB
4784 }
4785 }
4786 break;
e5febef5 4787#endif
66fb9763
FB
4788 case TARGET_NR_rt_sigprocmask:
4789 {
4790 int how = arg1;
4791 sigset_t set, oldset, *set_ptr;
3b46e624 4792
53a5960a 4793 if (arg2) {
66fb9763
FB
4794 switch(how) {
4795 case TARGET_SIG_BLOCK:
4796 how = SIG_BLOCK;
4797 break;
4798 case TARGET_SIG_UNBLOCK:
4799 how = SIG_UNBLOCK;
4800 break;
4801 case TARGET_SIG_SETMASK:
4802 how = SIG_SETMASK;
4803 break;
4804 default:
0da46a6e 4805 ret = -TARGET_EINVAL;
66fb9763
FB
4806 goto fail;
4807 }
579a97f7
FB
4808 if (!(p = lock_user(VERIFY_READ, arg2, sizeof(target_sigset_t), 1)))
4809 goto efault;
53a5960a
PB
4810 target_to_host_sigset(&set, p);
4811 unlock_user(p, arg2, 0);
66fb9763
FB
4812 set_ptr = &set;
4813 } else {
4814 how = 0;
4815 set_ptr = NULL;
4816 }
4817 ret = get_errno(sigprocmask(how, set_ptr, &oldset));
53a5960a 4818 if (!is_error(ret) && arg3) {
579a97f7
FB
4819 if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0)))
4820 goto efault;
53a5960a
PB
4821 host_to_target_sigset(p, &oldset);
4822 unlock_user(p, arg3, sizeof(target_sigset_t));
66fb9763
FB
4823 }
4824 }
4825 break;
e5febef5 4826#ifdef TARGET_NR_sigpending
66fb9763
FB
4827 case TARGET_NR_sigpending:
4828 {
4829 sigset_t set;
4830 ret = get_errno(sigpending(&set));
4831 if (!is_error(ret)) {
579a97f7
FB
4832 if (!(p = lock_user(VERIFY_WRITE, arg1, sizeof(target_sigset_t), 0)))
4833 goto efault;
53a5960a
PB
4834 host_to_target_old_sigset(p, &set);
4835 unlock_user(p, arg1, sizeof(target_sigset_t));
66fb9763
FB
4836 }
4837 }
4838 break;
e5febef5 4839#endif
66fb9763
FB
4840 case TARGET_NR_rt_sigpending:
4841 {
4842 sigset_t set;
4843 ret = get_errno(sigpending(&set));
4844 if (!is_error(ret)) {
579a97f7
FB
4845 if (!(p = lock_user(VERIFY_WRITE, arg1, sizeof(target_sigset_t), 0)))
4846 goto efault;
53a5960a
PB
4847 host_to_target_sigset(p, &set);
4848 unlock_user(p, arg1, sizeof(target_sigset_t));
66fb9763
FB
4849 }
4850 }
4851 break;
e5febef5 4852#ifdef TARGET_NR_sigsuspend
66fb9763
FB
4853 case TARGET_NR_sigsuspend:
4854 {
4855 sigset_t set;
579a97f7
FB
4856 if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
4857 goto efault;
53a5960a
PB
4858 target_to_host_old_sigset(&set, p);
4859 unlock_user(p, arg1, 0);
66fb9763
FB
4860 ret = get_errno(sigsuspend(&set));
4861 }
4862 break;
e5febef5 4863#endif
66fb9763
FB
4864 case TARGET_NR_rt_sigsuspend:
4865 {
4866 sigset_t set;
579a97f7
FB
4867 if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
4868 goto efault;
53a5960a
PB
4869 target_to_host_sigset(&set, p);
4870 unlock_user(p, arg1, 0);
66fb9763
FB
4871 ret = get_errno(sigsuspend(&set));
4872 }
4873 break;
4874 case TARGET_NR_rt_sigtimedwait:
4875 {
66fb9763
FB
4876 sigset_t set;
4877 struct timespec uts, *puts;
4878 siginfo_t uinfo;
3b46e624 4879
579a97f7
FB
4880 if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
4881 goto efault;
53a5960a
PB
4882 target_to_host_sigset(&set, p);
4883 unlock_user(p, arg1, 0);
4884 if (arg3) {
66fb9763 4885 puts = &uts;
53a5960a 4886 target_to_host_timespec(puts, arg3);
66fb9763
FB
4887 } else {
4888 puts = NULL;
4889 }
4890 ret = get_errno(sigtimedwait(&set, &uinfo, puts));
53a5960a 4891 if (!is_error(ret) && arg2) {
e1e3f30b 4892 if (!(p = lock_user(VERIFY_WRITE, arg2, sizeof(target_siginfo_t), 0)))
579a97f7 4893 goto efault;
53a5960a 4894 host_to_target_siginfo(p, &uinfo);
e1e3f30b 4895 unlock_user(p, arg2, sizeof(target_siginfo_t));
66fb9763
FB
4896 }
4897 }
4898 break;
4899 case TARGET_NR_rt_sigqueueinfo:
4900 {
4901 siginfo_t uinfo;
579a97f7
FB
4902 if (!(p = lock_user(VERIFY_READ, arg3, sizeof(target_sigset_t), 1)))
4903 goto efault;
53a5960a
PB
4904 target_to_host_siginfo(&uinfo, p);
4905 unlock_user(p, arg1, 0);
66fb9763
FB
4906 ret = get_errno(sys_rt_sigqueueinfo(arg1, arg2, &uinfo));
4907 }
4908 break;
e5febef5 4909#ifdef TARGET_NR_sigreturn
66fb9763
FB
4910 case TARGET_NR_sigreturn:
4911 /* NOTE: ret is eax, so not transcoding must be done */
4912 ret = do_sigreturn(cpu_env);
4913 break;
e5febef5 4914#endif
66fb9763
FB
4915 case TARGET_NR_rt_sigreturn:
4916 /* NOTE: ret is eax, so not transcoding must be done */
4917 ret = do_rt_sigreturn(cpu_env);
4918 break;
31e31b8a 4919 case TARGET_NR_sethostname:
579a97f7
FB
4920 if (!(p = lock_user_string(arg1)))
4921 goto efault;
53a5960a
PB
4922 ret = get_errno(sethostname(p, arg2));
4923 unlock_user(p, arg1, 0);
31e31b8a
FB
4924 break;
4925 case TARGET_NR_setrlimit:
9de5e440
FB
4926 {
4927 /* XXX: convert resource ? */
4928 int resource = arg1;
53a5960a 4929 struct target_rlimit *target_rlim;
9de5e440 4930 struct rlimit rlim;
579a97f7
FB
4931 if (!lock_user_struct(VERIFY_READ, target_rlim, arg2, 1))
4932 goto efault;
9de5e440
FB
4933 rlim.rlim_cur = tswapl(target_rlim->rlim_cur);
4934 rlim.rlim_max = tswapl(target_rlim->rlim_max);
53a5960a 4935 unlock_user_struct(target_rlim, arg2, 0);
9de5e440
FB
4936 ret = get_errno(setrlimit(resource, &rlim));
4937 }
4938 break;
31e31b8a 4939 case TARGET_NR_getrlimit:
9de5e440
FB
4940 {
4941 /* XXX: convert resource ? */
4942 int resource = arg1;
53a5960a 4943 struct target_rlimit *target_rlim;
9de5e440 4944 struct rlimit rlim;
3b46e624 4945
9de5e440
FB
4946 ret = get_errno(getrlimit(resource, &rlim));
4947 if (!is_error(ret)) {
579a97f7
FB
4948 if (!lock_user_struct(VERIFY_WRITE, target_rlim, arg2, 0))
4949 goto efault;
53a5960a
PB
4950 rlim.rlim_cur = tswapl(target_rlim->rlim_cur);
4951 rlim.rlim_max = tswapl(target_rlim->rlim_max);
4952 unlock_user_struct(target_rlim, arg2, 1);
9de5e440
FB
4953 }
4954 }
4955 break;
31e31b8a 4956 case TARGET_NR_getrusage:
b409186b
FB
4957 {
4958 struct rusage rusage;
b409186b
FB
4959 ret = get_errno(getrusage(arg1, &rusage));
4960 if (!is_error(ret)) {
53a5960a 4961 host_to_target_rusage(arg2, &rusage);
b409186b
FB
4962 }
4963 }
4964 break;
31e31b8a
FB
4965 case TARGET_NR_gettimeofday:
4966 {
31e31b8a
FB
4967 struct timeval tv;
4968 ret = get_errno(gettimeofday(&tv, NULL));
4969 if (!is_error(ret)) {
788f5ec4
TS
4970 if (copy_to_user_timeval(arg1, &tv))
4971 goto efault;
31e31b8a
FB
4972 }
4973 }
4974 break;
4975 case TARGET_NR_settimeofday:
4976 {
31e31b8a 4977 struct timeval tv;
788f5ec4
TS
4978 if (copy_from_user_timeval(&tv, arg1))
4979 goto efault;
31e31b8a
FB
4980 ret = get_errno(settimeofday(&tv, NULL));
4981 }
4982 break;
048f6b4d 4983#ifdef TARGET_NR_select
31e31b8a 4984 case TARGET_NR_select:
f2674e31 4985 {
53a5960a 4986 struct target_sel_arg_struct *sel;
992f48a0 4987 abi_ulong inp, outp, exp, tvp;
53a5960a
PB
4988 long nsel;
4989
579a97f7
FB
4990 if (!lock_user_struct(VERIFY_READ, sel, arg1, 1))
4991 goto efault;
53a5960a
PB
4992 nsel = tswapl(sel->n);
4993 inp = tswapl(sel->inp);
4994 outp = tswapl(sel->outp);
4995 exp = tswapl(sel->exp);
4996 tvp = tswapl(sel->tvp);
4997 unlock_user_struct(sel, arg1, 0);
4998 ret = do_select(nsel, inp, outp, exp, tvp);
f2674e31
FB
4999 }
5000 break;
048f6b4d 5001#endif
31e31b8a 5002 case TARGET_NR_symlink:
53a5960a
PB
5003 {
5004 void *p2;
5005 p = lock_user_string(arg1);
5006 p2 = lock_user_string(arg2);
579a97f7
FB
5007 if (!p || !p2)
5008 ret = -TARGET_EFAULT;
5009 else
5010 ret = get_errno(symlink(p, p2));
53a5960a
PB
5011 unlock_user(p2, arg2, 0);
5012 unlock_user(p, arg1, 0);
5013 }
31e31b8a 5014 break;
f0b6243d
TS
5015#if defined(TARGET_NR_symlinkat) && defined(__NR_symlinkat)
5016 case TARGET_NR_symlinkat:
f0b6243d 5017 {
579a97f7 5018 void *p2;
f0b6243d
TS
5019 p = lock_user_string(arg1);
5020 p2 = lock_user_string(arg3);
579a97f7 5021 if (!p || !p2)
0da46a6e 5022 ret = -TARGET_EFAULT;
f0b6243d
TS
5023 else
5024 ret = get_errno(sys_symlinkat(p, arg2, p2));
579a97f7
FB
5025 unlock_user(p2, arg3, 0);
5026 unlock_user(p, arg1, 0);
f0b6243d
TS
5027 }
5028 break;
5029#endif
ebc05488 5030#ifdef TARGET_NR_oldlstat
31e31b8a
FB
5031 case TARGET_NR_oldlstat:
5032 goto unimplemented;
ebc05488 5033#endif
31e31b8a 5034 case TARGET_NR_readlink:
53a5960a 5035 {
d088d664 5036 void *p2, *temp;
53a5960a 5037 p = lock_user_string(arg1);
579a97f7
FB
5038 p2 = lock_user(VERIFY_WRITE, arg2, arg3, 0);
5039 if (!p || !p2)
5040 ret = -TARGET_EFAULT;
d088d664
AJ
5041 else {
5042 if (strncmp((const char *)p, "/proc/self/exe", 14) == 0) {
5043 char real[PATH_MAX];
5044 temp = realpath(exec_path,real);
5045 ret = (temp==NULL) ? get_errno(-1) : strlen(real) ;
5046 snprintf((char *)p2, arg3, "%s", real);
5047 }
5048 else
5049 ret = get_errno(readlink(path(p), p2, arg3));
d088d664 5050 }
53a5960a
PB
5051 unlock_user(p2, arg2, ret);
5052 unlock_user(p, arg1, 0);
5053 }
31e31b8a 5054 break;
5e0ccb18
TS
5055#if defined(TARGET_NR_readlinkat) && defined(__NR_readlinkat)
5056 case TARGET_NR_readlinkat:
5e0ccb18 5057 {
579a97f7 5058 void *p2;
5e0ccb18 5059 p = lock_user_string(arg2);
579a97f7
FB
5060 p2 = lock_user(VERIFY_WRITE, arg3, arg4, 0);
5061 if (!p || !p2)
0da46a6e 5062 ret = -TARGET_EFAULT;
5e0ccb18
TS
5063 else
5064 ret = get_errno(sys_readlinkat(arg1, path(p), p2, arg4));
579a97f7
FB
5065 unlock_user(p2, arg3, ret);
5066 unlock_user(p, arg2, 0);
5e0ccb18
TS
5067 }
5068 break;
5069#endif
e5febef5 5070#ifdef TARGET_NR_uselib
31e31b8a
FB
5071 case TARGET_NR_uselib:
5072 goto unimplemented;
e5febef5
TS
5073#endif
5074#ifdef TARGET_NR_swapon
31e31b8a 5075 case TARGET_NR_swapon:
579a97f7
FB
5076 if (!(p = lock_user_string(arg1)))
5077 goto efault;
53a5960a
PB
5078 ret = get_errno(swapon(p, arg2));
5079 unlock_user(p, arg1, 0);
31e31b8a 5080 break;
e5febef5 5081#endif
31e31b8a
FB
5082 case TARGET_NR_reboot:
5083 goto unimplemented;
e5febef5 5084#ifdef TARGET_NR_readdir
31e31b8a
FB
5085 case TARGET_NR_readdir:
5086 goto unimplemented;
e5febef5
TS
5087#endif
5088#ifdef TARGET_NR_mmap
31e31b8a 5089 case TARGET_NR_mmap:
b779e29e 5090#if (defined(TARGET_I386) && defined(TARGET_ABI32)) || defined(TARGET_ARM) || defined(TARGET_M68K) || defined(TARGET_CRIS) || defined(TARGET_MICROBLAZE)
31e31b8a 5091 {
992f48a0
BS
5092 abi_ulong *v;
5093 abi_ulong v1, v2, v3, v4, v5, v6;
579a97f7
FB
5094 if (!(v = lock_user(VERIFY_READ, arg1, 6 * sizeof(abi_ulong), 1)))
5095 goto efault;
53a5960a
PB
5096 v1 = tswapl(v[0]);
5097 v2 = tswapl(v[1]);
5098 v3 = tswapl(v[2]);
5099 v4 = tswapl(v[3]);
5100 v5 = tswapl(v[4]);
5101 v6 = tswapl(v[5]);
5102 unlock_user(v, arg1, 0);
5fafdf24 5103 ret = get_errno(target_mmap(v1, v2, v3,
5286db75
FB
5104 target_to_host_bitmask(v4, mmap_flags_tbl),
5105 v5, v6));
31e31b8a 5106 }
31e31b8a 5107#else
5fafdf24
TS
5108 ret = get_errno(target_mmap(arg1, arg2, arg3,
5109 target_to_host_bitmask(arg4, mmap_flags_tbl),
6fb883e8
FB
5110 arg5,
5111 arg6));
31e31b8a 5112#endif
6fb883e8 5113 break;
e5febef5 5114#endif
a315a145 5115#ifdef TARGET_NR_mmap2
6fb883e8 5116 case TARGET_NR_mmap2:
bb7ec043 5117#ifndef MMAP_SHIFT
c573ff67 5118#define MMAP_SHIFT 12
c573ff67 5119#endif
5fafdf24
TS
5120 ret = get_errno(target_mmap(arg1, arg2, arg3,
5121 target_to_host_bitmask(arg4, mmap_flags_tbl),
5286db75 5122 arg5,
c573ff67 5123 arg6 << MMAP_SHIFT));
31e31b8a 5124 break;
a315a145 5125#endif
31e31b8a 5126 case TARGET_NR_munmap:
54936004 5127 ret = get_errno(target_munmap(arg1, arg2));
31e31b8a 5128 break;
9de5e440 5129 case TARGET_NR_mprotect:
54936004 5130 ret = get_errno(target_mprotect(arg1, arg2, arg3));
9de5e440 5131 break;
e5febef5 5132#ifdef TARGET_NR_mremap
9de5e440 5133 case TARGET_NR_mremap:
54936004 5134 ret = get_errno(target_mremap(arg1, arg2, arg3, arg4, arg5));
9de5e440 5135 break;
e5febef5 5136#endif
53a5960a 5137 /* ??? msync/mlock/munlock are broken for softmmu. */
e5febef5 5138#ifdef TARGET_NR_msync
9de5e440 5139 case TARGET_NR_msync:
53a5960a 5140 ret = get_errno(msync(g2h(arg1), arg2, arg3));
9de5e440 5141 break;
e5febef5
TS
5142#endif
5143#ifdef TARGET_NR_mlock
9de5e440 5144 case TARGET_NR_mlock:
53a5960a 5145 ret = get_errno(mlock(g2h(arg1), arg2));
9de5e440 5146 break;
e5febef5
TS
5147#endif
5148#ifdef TARGET_NR_munlock
9de5e440 5149 case TARGET_NR_munlock:
53a5960a 5150 ret = get_errno(munlock(g2h(arg1), arg2));
9de5e440 5151 break;
e5febef5
TS
5152#endif
5153#ifdef TARGET_NR_mlockall
9de5e440
FB
5154 case TARGET_NR_mlockall:
5155 ret = get_errno(mlockall(arg1));
5156 break;
e5febef5
TS
5157#endif
5158#ifdef TARGET_NR_munlockall
9de5e440
FB
5159 case TARGET_NR_munlockall:
5160 ret = get_errno(munlockall());
5161 break;
e5febef5 5162#endif
31e31b8a 5163 case TARGET_NR_truncate:
579a97f7
FB
5164 if (!(p = lock_user_string(arg1)))
5165 goto efault;
53a5960a
PB
5166 ret = get_errno(truncate(p, arg2));
5167 unlock_user(p, arg1, 0);
31e31b8a
FB
5168 break;
5169 case TARGET_NR_ftruncate:
5170 ret = get_errno(ftruncate(arg1, arg2));
5171 break;
5172 case TARGET_NR_fchmod:
5173 ret = get_errno(fchmod(arg1, arg2));
5174 break;
814d7977
TS
5175#if defined(TARGET_NR_fchmodat) && defined(__NR_fchmodat)
5176 case TARGET_NR_fchmodat:
579a97f7
FB
5177 if (!(p = lock_user_string(arg2)))
5178 goto efault;
465c9f06 5179 ret = get_errno(sys_fchmodat(arg1, p, arg3));
579a97f7 5180 unlock_user(p, arg2, 0);
814d7977
TS
5181 break;
5182#endif
31e31b8a 5183 case TARGET_NR_getpriority:
c6cda17a
TS
5184 /* libc does special remapping of the return value of
5185 * sys_getpriority() so it's just easiest to call
5186 * sys_getpriority() directly rather than through libc. */
5187 ret = sys_getpriority(arg1, arg2);
31e31b8a
FB
5188 break;
5189 case TARGET_NR_setpriority:
5190 ret = get_errno(setpriority(arg1, arg2, arg3));
5191 break;
ebc05488 5192#ifdef TARGET_NR_profil
31e31b8a
FB
5193 case TARGET_NR_profil:
5194 goto unimplemented;
ebc05488 5195#endif
31e31b8a 5196 case TARGET_NR_statfs:
579a97f7
FB
5197 if (!(p = lock_user_string(arg1)))
5198 goto efault;
53a5960a
PB
5199 ret = get_errno(statfs(path(p), &stfs));
5200 unlock_user(p, arg1, 0);
31e31b8a
FB
5201 convert_statfs:
5202 if (!is_error(ret)) {
53a5960a 5203 struct target_statfs *target_stfs;
3b46e624 5204
579a97f7
FB
5205 if (!lock_user_struct(VERIFY_WRITE, target_stfs, arg2, 0))
5206 goto efault;
5207 __put_user(stfs.f_type, &target_stfs->f_type);
5208 __put_user(stfs.f_bsize, &target_stfs->f_bsize);
5209 __put_user(stfs.f_blocks, &target_stfs->f_blocks);
5210 __put_user(stfs.f_bfree, &target_stfs->f_bfree);
5211 __put_user(stfs.f_bavail, &target_stfs->f_bavail);
5212 __put_user(stfs.f_files, &target_stfs->f_files);
5213 __put_user(stfs.f_ffree, &target_stfs->f_ffree);
5214 __put_user(stfs.f_fsid.__val[0], &target_stfs->f_fsid.val[0]);
5215 __put_user(stfs.f_fsid.__val[1], &target_stfs->f_fsid.val[1]);
5216 __put_user(stfs.f_namelen, &target_stfs->f_namelen);
53a5960a 5217 unlock_user_struct(target_stfs, arg2, 1);
31e31b8a
FB
5218 }
5219 break;
5220 case TARGET_NR_fstatfs:
56c8f68f 5221 ret = get_errno(fstatfs(arg1, &stfs));
31e31b8a 5222 goto convert_statfs;
56c8f68f
FB
5223#ifdef TARGET_NR_statfs64
5224 case TARGET_NR_statfs64:
579a97f7
FB
5225 if (!(p = lock_user_string(arg1)))
5226 goto efault;
53a5960a
PB
5227 ret = get_errno(statfs(path(p), &stfs));
5228 unlock_user(p, arg1, 0);
56c8f68f
FB
5229 convert_statfs64:
5230 if (!is_error(ret)) {
53a5960a 5231 struct target_statfs64 *target_stfs;
3b46e624 5232
579a97f7
FB
5233 if (!lock_user_struct(VERIFY_WRITE, target_stfs, arg3, 0))
5234 goto efault;
5235 __put_user(stfs.f_type, &target_stfs->f_type);
5236 __put_user(stfs.f_bsize, &target_stfs->f_bsize);
5237 __put_user(stfs.f_blocks, &target_stfs->f_blocks);
5238 __put_user(stfs.f_bfree, &target_stfs->f_bfree);
5239 __put_user(stfs.f_bavail, &target_stfs->f_bavail);
5240 __put_user(stfs.f_files, &target_stfs->f_files);
5241 __put_user(stfs.f_ffree, &target_stfs->f_ffree);
5242 __put_user(stfs.f_fsid.__val[0], &target_stfs->f_fsid.val[0]);
5243 __put_user(stfs.f_fsid.__val[1], &target_stfs->f_fsid.val[1]);
5244 __put_user(stfs.f_namelen, &target_stfs->f_namelen);
5245 unlock_user_struct(target_stfs, arg3, 1);
56c8f68f
FB
5246 }
5247 break;
5248 case TARGET_NR_fstatfs64:
5249 ret = get_errno(fstatfs(arg1, &stfs));
5250 goto convert_statfs64;
5251#endif
ebc05488 5252#ifdef TARGET_NR_ioperm
31e31b8a
FB
5253 case TARGET_NR_ioperm:
5254 goto unimplemented;
ebc05488 5255#endif
e5febef5 5256#ifdef TARGET_NR_socketcall
31e31b8a 5257 case TARGET_NR_socketcall:
53a5960a 5258 ret = do_socketcall(arg1, arg2);
31e31b8a 5259 break;
e5febef5 5260#endif
3532fa74
FB
5261#ifdef TARGET_NR_accept
5262 case TARGET_NR_accept:
1be9e1dc 5263 ret = do_accept(arg1, arg2, arg3);
3532fa74
FB
5264 break;
5265#endif
5266#ifdef TARGET_NR_bind
5267 case TARGET_NR_bind:
5268 ret = do_bind(arg1, arg2, arg3);
5269 break;
5270#endif
5271#ifdef TARGET_NR_connect
5272 case TARGET_NR_connect:
5273 ret = do_connect(arg1, arg2, arg3);
5274 break;
5275#endif
5276#ifdef TARGET_NR_getpeername
5277 case TARGET_NR_getpeername:
1be9e1dc 5278 ret = do_getpeername(arg1, arg2, arg3);
3532fa74
FB
5279 break;
5280#endif
5281#ifdef TARGET_NR_getsockname
5282 case TARGET_NR_getsockname:
1be9e1dc 5283 ret = do_getsockname(arg1, arg2, arg3);
3532fa74
FB
5284 break;
5285#endif
5286#ifdef TARGET_NR_getsockopt
5287 case TARGET_NR_getsockopt:
5288 ret = do_getsockopt(arg1, arg2, arg3, arg4, arg5);
5289 break;
5290#endif
5291#ifdef TARGET_NR_listen
5292 case TARGET_NR_listen:
1be9e1dc 5293 ret = get_errno(listen(arg1, arg2));
3532fa74
FB
5294 break;
5295#endif
5296#ifdef TARGET_NR_recv
5297 case TARGET_NR_recv:
214201bd 5298 ret = do_recvfrom(arg1, arg2, arg3, arg4, 0, 0);
3532fa74
FB
5299 break;
5300#endif
5301#ifdef TARGET_NR_recvfrom
5302 case TARGET_NR_recvfrom:
214201bd 5303 ret = do_recvfrom(arg1, arg2, arg3, arg4, arg5, arg6);
3532fa74
FB
5304 break;
5305#endif
5306#ifdef TARGET_NR_recvmsg
5307 case TARGET_NR_recvmsg:
5308 ret = do_sendrecvmsg(arg1, arg2, arg3, 0);
5309 break;
5310#endif
5311#ifdef TARGET_NR_send
5312 case TARGET_NR_send:
1be9e1dc 5313 ret = do_sendto(arg1, arg2, arg3, arg4, 0, 0);
3532fa74
FB
5314 break;
5315#endif
5316#ifdef TARGET_NR_sendmsg
5317 case TARGET_NR_sendmsg:
5318 ret = do_sendrecvmsg(arg1, arg2, arg3, 1);
5319 break;
5320#endif
5321#ifdef TARGET_NR_sendto
5322 case TARGET_NR_sendto:
1be9e1dc 5323 ret = do_sendto(arg1, arg2, arg3, arg4, arg5, arg6);
3532fa74
FB
5324 break;
5325#endif
5326#ifdef TARGET_NR_shutdown
5327 case TARGET_NR_shutdown:
1be9e1dc 5328 ret = get_errno(shutdown(arg1, arg2));
3532fa74
FB
5329 break;
5330#endif
5331#ifdef TARGET_NR_socket
5332 case TARGET_NR_socket:
5333 ret = do_socket(arg1, arg2, arg3);
5334 break;
5335#endif
5336#ifdef TARGET_NR_socketpair
5337 case TARGET_NR_socketpair:
1be9e1dc 5338 ret = do_socketpair(arg1, arg2, arg3, arg4);
3532fa74
FB
5339 break;
5340#endif
5341#ifdef TARGET_NR_setsockopt
5342 case TARGET_NR_setsockopt:
5343 ret = do_setsockopt(arg1, arg2, arg3, arg4, (socklen_t) arg5);
5344 break;
5345#endif
7494b0f9 5346
31e31b8a 5347 case TARGET_NR_syslog:
579a97f7
FB
5348 if (!(p = lock_user_string(arg2)))
5349 goto efault;
e5574487
TS
5350 ret = get_errno(sys_syslog((int)arg1, p, (int)arg3));
5351 unlock_user(p, arg2, 0);
7494b0f9
TS
5352 break;
5353
31e31b8a 5354 case TARGET_NR_setitimer:
66fb9763 5355 {
66fb9763
FB
5356 struct itimerval value, ovalue, *pvalue;
5357
53a5960a 5358 if (arg2) {
66fb9763 5359 pvalue = &value;
788f5ec4
TS
5360 if (copy_from_user_timeval(&pvalue->it_interval, arg2)
5361 || copy_from_user_timeval(&pvalue->it_value,
5362 arg2 + sizeof(struct target_timeval)))
5363 goto efault;
66fb9763
FB
5364 } else {
5365 pvalue = NULL;
5366 }
5367 ret = get_errno(setitimer(arg1, pvalue, &ovalue));
53a5960a 5368 if (!is_error(ret) && arg3) {
788f5ec4
TS
5369 if (copy_to_user_timeval(arg3,
5370 &ovalue.it_interval)
5371 || copy_to_user_timeval(arg3 + sizeof(struct target_timeval),
5372 &ovalue.it_value))
5373 goto efault;
66fb9763
FB
5374 }
5375 }
5376 break;
31e31b8a 5377 case TARGET_NR_getitimer:
66fb9763 5378 {
66fb9763 5379 struct itimerval value;
3b46e624 5380
66fb9763 5381 ret = get_errno(getitimer(arg1, &value));
53a5960a 5382 if (!is_error(ret) && arg2) {
788f5ec4
TS
5383 if (copy_to_user_timeval(arg2,
5384 &value.it_interval)
5385 || copy_to_user_timeval(arg2 + sizeof(struct target_timeval),
5386 &value.it_value))
5387 goto efault;
66fb9763
FB
5388 }
5389 }
5390 break;
31e31b8a 5391 case TARGET_NR_stat:
579a97f7
FB
5392 if (!(p = lock_user_string(arg1)))
5393 goto efault;
53a5960a
PB
5394 ret = get_errno(stat(path(p), &st));
5395 unlock_user(p, arg1, 0);
31e31b8a
FB
5396 goto do_stat;
5397 case TARGET_NR_lstat:
579a97f7
FB
5398 if (!(p = lock_user_string(arg1)))
5399 goto efault;
53a5960a
PB
5400 ret = get_errno(lstat(path(p), &st));
5401 unlock_user(p, arg1, 0);
31e31b8a
FB
5402 goto do_stat;
5403 case TARGET_NR_fstat:
5404 {
5405 ret = get_errno(fstat(arg1, &st));
5406 do_stat:
5407 if (!is_error(ret)) {
53a5960a 5408 struct target_stat *target_st;
e3584658 5409
579a97f7
FB
5410 if (!lock_user_struct(VERIFY_WRITE, target_st, arg2, 0))
5411 goto efault;
d2fd1af7
FB
5412 __put_user(st.st_dev, &target_st->st_dev);
5413 __put_user(st.st_ino, &target_st->st_ino);
5414 __put_user(st.st_mode, &target_st->st_mode);
5415 __put_user(st.st_uid, &target_st->st_uid);
5416 __put_user(st.st_gid, &target_st->st_gid);
5417 __put_user(st.st_nlink, &target_st->st_nlink);
5418 __put_user(st.st_rdev, &target_st->st_rdev);
5419 __put_user(st.st_size, &target_st->st_size);
5420 __put_user(st.st_blksize, &target_st->st_blksize);
5421 __put_user(st.st_blocks, &target_st->st_blocks);
5422 __put_user(st.st_atime, &target_st->target_st_atime);
5423 __put_user(st.st_mtime, &target_st->target_st_mtime);
5424 __put_user(st.st_ctime, &target_st->target_st_ctime);
53a5960a 5425 unlock_user_struct(target_st, arg2, 1);
31e31b8a
FB
5426 }
5427 }
5428 break;
ebc05488 5429#ifdef TARGET_NR_olduname
31e31b8a
FB
5430 case TARGET_NR_olduname:
5431 goto unimplemented;
ebc05488
FB
5432#endif
5433#ifdef TARGET_NR_iopl
31e31b8a
FB
5434 case TARGET_NR_iopl:
5435 goto unimplemented;
ebc05488 5436#endif
31e31b8a
FB
5437 case TARGET_NR_vhangup:
5438 ret = get_errno(vhangup());
5439 break;
ebc05488 5440#ifdef TARGET_NR_idle
31e31b8a
FB
5441 case TARGET_NR_idle:
5442 goto unimplemented;
42ad6ae9
FB
5443#endif
5444#ifdef TARGET_NR_syscall
5445 case TARGET_NR_syscall:
5446 ret = do_syscall(cpu_env,arg1 & 0xffff,arg2,arg3,arg4,arg5,arg6,0);
5447 break;
ebc05488 5448#endif
31e31b8a
FB
5449 case TARGET_NR_wait4:
5450 {
5451 int status;
992f48a0 5452 abi_long status_ptr = arg2;
31e31b8a 5453 struct rusage rusage, *rusage_ptr;
992f48a0 5454 abi_ulong target_rusage = arg4;
31e31b8a
FB
5455 if (target_rusage)
5456 rusage_ptr = &rusage;
5457 else
5458 rusage_ptr = NULL;
5459 ret = get_errno(wait4(arg1, &status, arg3, rusage_ptr));
5460 if (!is_error(ret)) {
2f619698 5461 if (status_ptr) {
1d9d8b55 5462 status = host_to_target_waitstatus(status);
2f619698
FB
5463 if (put_user_s32(status, status_ptr))
5464 goto efault;
31e31b8a 5465 }
2f619698
FB
5466 if (target_rusage)
5467 host_to_target_rusage(target_rusage, &rusage);
31e31b8a
FB
5468 }
5469 }
5470 break;
e5febef5 5471#ifdef TARGET_NR_swapoff
31e31b8a 5472 case TARGET_NR_swapoff:
579a97f7
FB
5473 if (!(p = lock_user_string(arg1)))
5474 goto efault;
53a5960a
PB
5475 ret = get_errno(swapoff(p));
5476 unlock_user(p, arg1, 0);
31e31b8a 5477 break;
e5febef5 5478#endif
31e31b8a 5479 case TARGET_NR_sysinfo:
a5448a7d 5480 {
53a5960a 5481 struct target_sysinfo *target_value;
a5448a7d
FB
5482 struct sysinfo value;
5483 ret = get_errno(sysinfo(&value));
53a5960a 5484 if (!is_error(ret) && arg1)
a5448a7d 5485 {
579a97f7
FB
5486 if (!lock_user_struct(VERIFY_WRITE, target_value, arg1, 0))
5487 goto efault;
a5448a7d
FB
5488 __put_user(value.uptime, &target_value->uptime);
5489 __put_user(value.loads[0], &target_value->loads[0]);
5490 __put_user(value.loads[1], &target_value->loads[1]);
5491 __put_user(value.loads[2], &target_value->loads[2]);
5492 __put_user(value.totalram, &target_value->totalram);
5493 __put_user(value.freeram, &target_value->freeram);
5494 __put_user(value.sharedram, &target_value->sharedram);
5495 __put_user(value.bufferram, &target_value->bufferram);
5496 __put_user(value.totalswap, &target_value->totalswap);
5497 __put_user(value.freeswap, &target_value->freeswap);
5498 __put_user(value.procs, &target_value->procs);
5499 __put_user(value.totalhigh, &target_value->totalhigh);
5500 __put_user(value.freehigh, &target_value->freehigh);
5501 __put_user(value.mem_unit, &target_value->mem_unit);
53a5960a 5502 unlock_user_struct(target_value, arg1, 1);
a5448a7d
FB
5503 }
5504 }
5505 break;
e5febef5 5506#ifdef TARGET_NR_ipc
31e31b8a 5507 case TARGET_NR_ipc:
8853f86e
FB
5508 ret = do_ipc(arg1, arg2, arg3, arg4, arg5, arg6);
5509 break;
e5febef5 5510#endif
e5289087
AJ
5511#ifdef TARGET_NR_semget
5512 case TARGET_NR_semget:
5513 ret = get_errno(semget(arg1, arg2, arg3));
5514 break;
5515#endif
5516#ifdef TARGET_NR_semop
5517 case TARGET_NR_semop:
5518 ret = get_errno(do_semop(arg1, arg2, arg3));
5519 break;
5520#endif
5521#ifdef TARGET_NR_semctl
5522 case TARGET_NR_semctl:
5523 ret = do_semctl(arg1, arg2, arg3, (union target_semun)(abi_ulong)arg4);
5524 break;
5525#endif
eeb438c1
AJ
5526#ifdef TARGET_NR_msgctl
5527 case TARGET_NR_msgctl:
5528 ret = do_msgctl(arg1, arg2, arg3);
5529 break;
5530#endif
5531#ifdef TARGET_NR_msgget
5532 case TARGET_NR_msgget:
5533 ret = get_errno(msgget(arg1, arg2));
5534 break;
5535#endif
5536#ifdef TARGET_NR_msgrcv
5537 case TARGET_NR_msgrcv:
5538 ret = do_msgrcv(arg1, arg2, arg3, arg4, arg5);
5539 break;
5540#endif
5541#ifdef TARGET_NR_msgsnd
5542 case TARGET_NR_msgsnd:
5543 ret = do_msgsnd(arg1, arg2, arg3, arg4);
5544 break;
88a8c984
RV
5545#endif
5546#ifdef TARGET_NR_shmget
5547 case TARGET_NR_shmget:
5548 ret = get_errno(shmget(arg1, arg2, arg3));
5549 break;
5550#endif
5551#ifdef TARGET_NR_shmctl
5552 case TARGET_NR_shmctl:
5553 ret = do_shmctl(arg1, arg2, arg3);
5554 break;
5555#endif
5556#ifdef TARGET_NR_shmat
5557 case TARGET_NR_shmat:
5558 ret = do_shmat(arg1, arg2, arg3);
5559 break;
5560#endif
5561#ifdef TARGET_NR_shmdt
5562 case TARGET_NR_shmdt:
5563 ret = do_shmdt(arg1);
5564 break;
eeb438c1 5565#endif
31e31b8a
FB
5566 case TARGET_NR_fsync:
5567 ret = get_errno(fsync(arg1));
5568 break;
31e31b8a 5569 case TARGET_NR_clone:
0b6d3ae0
AJ
5570#if defined(TARGET_SH4)
5571 ret = get_errno(do_fork(cpu_env, arg1, arg2, arg3, arg5, arg4));
b15ad61c
EI
5572#elif defined(TARGET_CRIS)
5573 ret = get_errno(do_fork(cpu_env, arg2, arg1, arg3, arg4, arg5));
0b6d3ae0 5574#else
d865bab5 5575 ret = get_errno(do_fork(cpu_env, arg1, arg2, arg3, arg4, arg5));
0b6d3ae0 5576#endif
1b6b029e 5577 break;
ec86b0fb
FB
5578#ifdef __NR_exit_group
5579 /* new thread calls */
5580 case TARGET_NR_exit_group:
6d946cda
AJ
5581#ifdef HAVE_GPROF
5582 _mcleanup();
5583#endif
e9009676 5584 gdb_exit(cpu_env, arg1);
ec86b0fb
FB
5585 ret = get_errno(exit_group(arg1));
5586 break;
5587#endif
31e31b8a 5588 case TARGET_NR_setdomainname:
579a97f7
FB
5589 if (!(p = lock_user_string(arg1)))
5590 goto efault;
53a5960a
PB
5591 ret = get_errno(setdomainname(p, arg2));
5592 unlock_user(p, arg1, 0);
31e31b8a
FB
5593 break;
5594 case TARGET_NR_uname:
5595 /* no need to transcode because we use the linux syscall */
29e619b1
FB
5596 {
5597 struct new_utsname * buf;
3b46e624 5598
579a97f7
FB
5599 if (!lock_user_struct(VERIFY_WRITE, buf, arg1, 0))
5600 goto efault;
29e619b1
FB
5601 ret = get_errno(sys_uname(buf));
5602 if (!is_error(ret)) {
5603 /* Overrite the native machine name with whatever is being
5604 emulated. */
5605 strcpy (buf->machine, UNAME_MACHINE);
c5937220
PB
5606 /* Allow the user to override the reported release. */
5607 if (qemu_uname_release && *qemu_uname_release)
5608 strcpy (buf->release, qemu_uname_release);
29e619b1 5609 }
53a5960a 5610 unlock_user_struct(buf, arg1, 1);
29e619b1 5611 }
31e31b8a 5612 break;
6dbad63e 5613#ifdef TARGET_I386
31e31b8a 5614 case TARGET_NR_modify_ldt:
03acab66 5615 ret = do_modify_ldt(cpu_env, arg1, arg2, arg3);
5cd4393b 5616 break;
84409ddb 5617#if !defined(TARGET_X86_64)
5cd4393b
FB
5618 case TARGET_NR_vm86old:
5619 goto unimplemented;
5620 case TARGET_NR_vm86:
53a5960a 5621 ret = do_vm86(cpu_env, arg1, arg2);
6dbad63e 5622 break;
84409ddb 5623#endif
6dbad63e 5624#endif
31e31b8a
FB
5625 case TARGET_NR_adjtimex:
5626 goto unimplemented;
e5febef5 5627#ifdef TARGET_NR_create_module
31e31b8a 5628 case TARGET_NR_create_module:
e5febef5 5629#endif
31e31b8a
FB
5630 case TARGET_NR_init_module:
5631 case TARGET_NR_delete_module:
e5febef5 5632#ifdef TARGET_NR_get_kernel_syms
31e31b8a 5633 case TARGET_NR_get_kernel_syms:
e5febef5 5634#endif
31e31b8a
FB
5635 goto unimplemented;
5636 case TARGET_NR_quotactl:
5637 goto unimplemented;
5638 case TARGET_NR_getpgid:
5639 ret = get_errno(getpgid(arg1));
5640 break;
5641 case TARGET_NR_fchdir:
5642 ret = get_errno(fchdir(arg1));
5643 break;
84409ddb 5644#ifdef TARGET_NR_bdflush /* not on x86_64 */
31e31b8a
FB
5645 case TARGET_NR_bdflush:
5646 goto unimplemented;
84409ddb 5647#endif
e5febef5 5648#ifdef TARGET_NR_sysfs
31e31b8a
FB
5649 case TARGET_NR_sysfs:
5650 goto unimplemented;
e5febef5 5651#endif
31e31b8a 5652 case TARGET_NR_personality:
1b6b029e 5653 ret = get_errno(personality(arg1));
31e31b8a 5654 break;
e5febef5 5655#ifdef TARGET_NR_afs_syscall
31e31b8a
FB
5656 case TARGET_NR_afs_syscall:
5657 goto unimplemented;
e5febef5 5658#endif
7a3148a9 5659#ifdef TARGET_NR__llseek /* Not on alpha */
31e31b8a
FB
5660 case TARGET_NR__llseek:
5661 {
4f2ac237
FB
5662#if defined (__x86_64__)
5663 ret = get_errno(lseek(arg1, ((uint64_t )arg2 << 32) | arg3, arg5));
2f619698
FB
5664 if (put_user_s64(ret, arg4))
5665 goto efault;
4f2ac237 5666#else
31e31b8a
FB
5667 int64_t res;
5668 ret = get_errno(_llseek(arg1, arg2, arg3, &res, arg5));
2f619698
FB
5669 if (put_user_s64(res, arg4))
5670 goto efault;
4f2ac237 5671#endif
31e31b8a
FB
5672 }
5673 break;
7a3148a9 5674#endif
31e31b8a 5675 case TARGET_NR_getdents:
992f48a0 5676#if TARGET_ABI_BITS != 32
53a5960a 5677 goto unimplemented;
992f48a0 5678#elif TARGET_ABI_BITS == 32 && HOST_LONG_BITS == 64
4add45b4 5679 {
53a5960a 5680 struct target_dirent *target_dirp;
6556a833 5681 struct linux_dirent *dirp;
992f48a0 5682 abi_long count = arg3;
4add45b4
FB
5683
5684 dirp = malloc(count);
0da46a6e 5685 if (!dirp) {
579a97f7 5686 ret = -TARGET_ENOMEM;
0da46a6e
TS
5687 goto fail;
5688 }
3b46e624 5689
4add45b4
FB
5690 ret = get_errno(sys_getdents(arg1, dirp, count));
5691 if (!is_error(ret)) {
6556a833 5692 struct linux_dirent *de;
4add45b4
FB
5693 struct target_dirent *tde;
5694 int len = ret;
5695 int reclen, treclen;
5696 int count1, tnamelen;
5697
5698 count1 = 0;
5699 de = dirp;
579a97f7
FB
5700 if (!(target_dirp = lock_user(VERIFY_WRITE, arg2, count, 0)))
5701 goto efault;
4add45b4
FB
5702 tde = target_dirp;
5703 while (len > 0) {
5704 reclen = de->d_reclen;
992f48a0 5705 treclen = reclen - (2 * (sizeof(long) - sizeof(abi_long)));
4add45b4
FB
5706 tde->d_reclen = tswap16(treclen);
5707 tde->d_ino = tswapl(de->d_ino);
5708 tde->d_off = tswapl(de->d_off);
992f48a0 5709 tnamelen = treclen - (2 * sizeof(abi_long) + 2);
4add45b4
FB
5710 if (tnamelen > 256)
5711 tnamelen = 256;
80a9d035 5712 /* XXX: may not be correct */
be15b141 5713 pstrcpy(tde->d_name, tnamelen, de->d_name);
6556a833 5714 de = (struct linux_dirent *)((char *)de + reclen);
4add45b4 5715 len -= reclen;
1c5bf3bf 5716 tde = (struct target_dirent *)((char *)tde + treclen);
4add45b4
FB
5717 count1 += treclen;
5718 }
5719 ret = count1;
579a97f7 5720 unlock_user(target_dirp, arg2, ret);
4add45b4
FB
5721 }
5722 free(dirp);
5723 }
5724#else
31e31b8a 5725 {
6556a833 5726 struct linux_dirent *dirp;
992f48a0 5727 abi_long count = arg3;
dab2ed99 5728
579a97f7
FB
5729 if (!(dirp = lock_user(VERIFY_WRITE, arg2, count, 0)))
5730 goto efault;
72f03900 5731 ret = get_errno(sys_getdents(arg1, dirp, count));
31e31b8a 5732 if (!is_error(ret)) {
6556a833 5733 struct linux_dirent *de;
31e31b8a
FB
5734 int len = ret;
5735 int reclen;
5736 de = dirp;
5737 while (len > 0) {
8083a3e5 5738 reclen = de->d_reclen;
31e31b8a
FB
5739 if (reclen > len)
5740 break;
8083a3e5 5741 de->d_reclen = tswap16(reclen);
31e31b8a
FB
5742 tswapls(&de->d_ino);
5743 tswapls(&de->d_off);
6556a833 5744 de = (struct linux_dirent *)((char *)de + reclen);
31e31b8a
FB
5745 len -= reclen;
5746 }
5747 }
53a5960a 5748 unlock_user(dirp, arg2, ret);
31e31b8a 5749 }
4add45b4 5750#endif
31e31b8a 5751 break;
3ae43202 5752#if defined(TARGET_NR_getdents64) && defined(__NR_getdents64)
dab2ed99
FB
5753 case TARGET_NR_getdents64:
5754 {
6556a833 5755 struct linux_dirent64 *dirp;
992f48a0 5756 abi_long count = arg3;
579a97f7
FB
5757 if (!(dirp = lock_user(VERIFY_WRITE, arg2, count, 0)))
5758 goto efault;
dab2ed99
FB
5759 ret = get_errno(sys_getdents64(arg1, dirp, count));
5760 if (!is_error(ret)) {
6556a833 5761 struct linux_dirent64 *de;
dab2ed99
FB
5762 int len = ret;
5763 int reclen;
5764 de = dirp;
5765 while (len > 0) {
8083a3e5 5766 reclen = de->d_reclen;
dab2ed99
FB
5767 if (reclen > len)
5768 break;
8083a3e5 5769 de->d_reclen = tswap16(reclen);
8582a53a
FB
5770 tswap64s((uint64_t *)&de->d_ino);
5771 tswap64s((uint64_t *)&de->d_off);
6556a833 5772 de = (struct linux_dirent64 *)((char *)de + reclen);
dab2ed99
FB
5773 len -= reclen;
5774 }
5775 }
53a5960a 5776 unlock_user(dirp, arg2, ret);
dab2ed99
FB
5777 }
5778 break;
a541f297 5779#endif /* TARGET_NR_getdents64 */
e5febef5 5780#ifdef TARGET_NR__newselect
31e31b8a 5781 case TARGET_NR__newselect:
53a5960a 5782 ret = do_select(arg1, arg2, arg3, arg4, arg5);
31e31b8a 5783 break;
e5febef5
TS
5784#endif
5785#ifdef TARGET_NR_poll
9de5e440
FB
5786 case TARGET_NR_poll:
5787 {
53a5960a 5788 struct target_pollfd *target_pfd;
9de5e440
FB
5789 unsigned int nfds = arg2;
5790 int timeout = arg3;
5791 struct pollfd *pfd;
7854b056 5792 unsigned int i;
9de5e440 5793
579a97f7
FB
5794 target_pfd = lock_user(VERIFY_WRITE, arg1, sizeof(struct target_pollfd) * nfds, 1);
5795 if (!target_pfd)
5796 goto efault;
9de5e440
FB
5797 pfd = alloca(sizeof(struct pollfd) * nfds);
5798 for(i = 0; i < nfds; i++) {
5cd4393b
FB
5799 pfd[i].fd = tswap32(target_pfd[i].fd);
5800 pfd[i].events = tswap16(target_pfd[i].events);
9de5e440
FB
5801 }
5802 ret = get_errno(poll(pfd, nfds, timeout));
5803 if (!is_error(ret)) {
5804 for(i = 0; i < nfds; i++) {
5cd4393b 5805 target_pfd[i].revents = tswap16(pfd[i].revents);
9de5e440 5806 }
53a5960a
PB
5807 ret += nfds * (sizeof(struct target_pollfd)
5808 - sizeof(struct pollfd));
9de5e440 5809 }
53a5960a 5810 unlock_user(target_pfd, arg1, ret);
9de5e440
FB
5811 }
5812 break;
e5febef5 5813#endif
31e31b8a 5814 case TARGET_NR_flock:
9de5e440
FB
5815 /* NOTE: the flock constant seems to be the same for every
5816 Linux platform */
5817 ret = get_errno(flock(arg1, arg2));
31e31b8a
FB
5818 break;
5819 case TARGET_NR_readv:
5820 {
5821 int count = arg3;
31e31b8a 5822 struct iovec *vec;
31e31b8a
FB
5823
5824 vec = alloca(count * sizeof(struct iovec));
41df8411
FB
5825 if (lock_iovec(VERIFY_WRITE, vec, arg2, count, 0) < 0)
5826 goto efault;
31e31b8a 5827 ret = get_errno(readv(arg1, vec, count));
53a5960a 5828 unlock_iovec(vec, arg2, count, 1);
31e31b8a
FB
5829 }
5830 break;
5831 case TARGET_NR_writev:
5832 {
5833 int count = arg3;
31e31b8a 5834 struct iovec *vec;
31e31b8a
FB
5835
5836 vec = alloca(count * sizeof(struct iovec));
41df8411
FB
5837 if (lock_iovec(VERIFY_READ, vec, arg2, count, 1) < 0)
5838 goto efault;
31e31b8a 5839 ret = get_errno(writev(arg1, vec, count));
53a5960a 5840 unlock_iovec(vec, arg2, count, 0);
31e31b8a
FB
5841 }
5842 break;
5843 case TARGET_NR_getsid:
5844 ret = get_errno(getsid(arg1));
5845 break;
7a3148a9 5846#if defined(TARGET_NR_fdatasync) /* Not on alpha (osf_datasync ?) */
31e31b8a 5847 case TARGET_NR_fdatasync:
5cd4393b
FB
5848 ret = get_errno(fdatasync(arg1));
5849 break;
7a3148a9 5850#endif
31e31b8a 5851 case TARGET_NR__sysctl:
0da46a6e 5852 /* We don't implement this, but ENOTDIR is always a safe
29e619b1 5853 return value. */
0da46a6e
TS
5854 ret = -TARGET_ENOTDIR;
5855 break;
31e31b8a 5856 case TARGET_NR_sched_setparam:
5cd4393b 5857 {
53a5960a 5858 struct sched_param *target_schp;
5cd4393b 5859 struct sched_param schp;
53a5960a 5860
579a97f7
FB
5861 if (!lock_user_struct(VERIFY_READ, target_schp, arg2, 1))
5862 goto efault;
5cd4393b 5863 schp.sched_priority = tswap32(target_schp->sched_priority);
53a5960a 5864 unlock_user_struct(target_schp, arg2, 0);
5cd4393b
FB
5865 ret = get_errno(sched_setparam(arg1, &schp));
5866 }
5867 break;
31e31b8a 5868 case TARGET_NR_sched_getparam:
5cd4393b 5869 {
53a5960a 5870 struct sched_param *target_schp;
5cd4393b
FB
5871 struct sched_param schp;
5872 ret = get_errno(sched_getparam(arg1, &schp));
5873 if (!is_error(ret)) {
579a97f7
FB
5874 if (!lock_user_struct(VERIFY_WRITE, target_schp, arg2, 0))
5875 goto efault;
5cd4393b 5876 target_schp->sched_priority = tswap32(schp.sched_priority);
53a5960a 5877 unlock_user_struct(target_schp, arg2, 1);
5cd4393b
FB
5878 }
5879 }
5880 break;
31e31b8a 5881 case TARGET_NR_sched_setscheduler:
5cd4393b 5882 {
53a5960a 5883 struct sched_param *target_schp;
5cd4393b 5884 struct sched_param schp;
579a97f7
FB
5885 if (!lock_user_struct(VERIFY_READ, target_schp, arg3, 1))
5886 goto efault;
5cd4393b 5887 schp.sched_priority = tswap32(target_schp->sched_priority);
53a5960a 5888 unlock_user_struct(target_schp, arg3, 0);
5cd4393b
FB
5889 ret = get_errno(sched_setscheduler(arg1, arg2, &schp));
5890 }
5891 break;
31e31b8a 5892 case TARGET_NR_sched_getscheduler:
5cd4393b
FB
5893 ret = get_errno(sched_getscheduler(arg1));
5894 break;
31e31b8a
FB
5895 case TARGET_NR_sched_yield:
5896 ret = get_errno(sched_yield());
5897 break;
5898 case TARGET_NR_sched_get_priority_max:
5cd4393b
FB
5899 ret = get_errno(sched_get_priority_max(arg1));
5900 break;
31e31b8a 5901 case TARGET_NR_sched_get_priority_min:
5cd4393b
FB
5902 ret = get_errno(sched_get_priority_min(arg1));
5903 break;
31e31b8a 5904 case TARGET_NR_sched_rr_get_interval:
5cd4393b 5905 {
5cd4393b
FB
5906 struct timespec ts;
5907 ret = get_errno(sched_rr_get_interval(arg1, &ts));
5908 if (!is_error(ret)) {
53a5960a 5909 host_to_target_timespec(arg2, &ts);
5cd4393b
FB
5910 }
5911 }
5912 break;
31e31b8a 5913 case TARGET_NR_nanosleep:
1b6b029e 5914 {
1b6b029e 5915 struct timespec req, rem;
53a5960a 5916 target_to_host_timespec(&req, arg1);
1b6b029e 5917 ret = get_errno(nanosleep(&req, &rem));
53a5960a
PB
5918 if (is_error(ret) && arg2) {
5919 host_to_target_timespec(arg2, &rem);
1b6b029e
FB
5920 }
5921 }
5922 break;
e5febef5 5923#ifdef TARGET_NR_query_module
31e31b8a 5924 case TARGET_NR_query_module:
5cd4393b 5925 goto unimplemented;
e5febef5
TS
5926#endif
5927#ifdef TARGET_NR_nfsservctl
31e31b8a 5928 case TARGET_NR_nfsservctl:
5cd4393b 5929 goto unimplemented;
e5febef5 5930#endif
31e31b8a 5931 case TARGET_NR_prctl:
e5574487
TS
5932 switch (arg1)
5933 {
5934 case PR_GET_PDEATHSIG:
5935 {
5936 int deathsig;
5937 ret = get_errno(prctl(arg1, &deathsig, arg3, arg4, arg5));
2f619698
FB
5938 if (!is_error(ret) && arg2
5939 && put_user_ual(deathsig, arg2))
5940 goto efault;
e5574487
TS
5941 }
5942 break;
5943 default:
5944 ret = get_errno(prctl(arg1, arg2, arg3, arg4, arg5));
5945 break;
5946 }
39b9aae1 5947 break;
d2fd1af7
FB
5948#ifdef TARGET_NR_arch_prctl
5949 case TARGET_NR_arch_prctl:
5950#if defined(TARGET_I386) && !defined(TARGET_ABI32)
5951 ret = do_arch_prctl(cpu_env, arg1, arg2);
5952 break;
5953#else
5954 goto unimplemented;
5955#endif
5956#endif
67867308 5957#ifdef TARGET_NR_pread
31e31b8a 5958 case TARGET_NR_pread:
a4ae00bc
AZ
5959#ifdef TARGET_ARM
5960 if (((CPUARMState *)cpu_env)->eabi)
5961 arg4 = arg5;
5962#endif
579a97f7
FB
5963 if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
5964 goto efault;
53a5960a
PB
5965 ret = get_errno(pread(arg1, p, arg3, arg4));
5966 unlock_user(p, arg2, ret);
206f0fa7 5967 break;
31e31b8a 5968 case TARGET_NR_pwrite:
a4ae00bc
AZ
5969#ifdef TARGET_ARM
5970 if (((CPUARMState *)cpu_env)->eabi)
5971 arg4 = arg5;
5972#endif
579a97f7
FB
5973 if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
5974 goto efault;
53a5960a
PB
5975 ret = get_errno(pwrite(arg1, p, arg3, arg4));
5976 unlock_user(p, arg2, 0);
206f0fa7 5977 break;
f2c7ba15
AJ
5978#endif
5979#ifdef TARGET_NR_pread64
5980 case TARGET_NR_pread64:
5981 if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
5982 goto efault;
5983 ret = get_errno(pread64(arg1, p, arg3, target_offset64(arg4, arg5)));
5984 unlock_user(p, arg2, ret);
5985 break;
5986 case TARGET_NR_pwrite64:
5987 if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
5988 goto efault;
5989 ret = get_errno(pwrite64(arg1, p, arg3, target_offset64(arg4, arg5)));
5990 unlock_user(p, arg2, 0);
5991 break;
67867308 5992#endif
31e31b8a 5993 case TARGET_NR_getcwd:
579a97f7
FB
5994 if (!(p = lock_user(VERIFY_WRITE, arg1, arg2, 0)))
5995 goto efault;
53a5960a
PB
5996 ret = get_errno(sys_getcwd1(p, arg2));
5997 unlock_user(p, arg1, ret);
31e31b8a
FB
5998 break;
5999 case TARGET_NR_capget:
5cd4393b 6000 goto unimplemented;
31e31b8a 6001 case TARGET_NR_capset:
5cd4393b 6002 goto unimplemented;
31e31b8a 6003 case TARGET_NR_sigaltstack:
198a74de
TS
6004#if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_MIPS) || \
6005 defined(TARGET_SPARC) || defined(TARGET_PPC) || defined(TARGET_ALPHA)
579a97f7 6006 ret = do_sigaltstack(arg1, arg2, get_sp_from_cpustate((CPUState *)cpu_env));
a04e134a
TS
6007 break;
6008#else
5cd4393b 6009 goto unimplemented;
a04e134a 6010#endif
31e31b8a 6011 case TARGET_NR_sendfile:
5cd4393b 6012 goto unimplemented;
ebc05488 6013#ifdef TARGET_NR_getpmsg
31e31b8a 6014 case TARGET_NR_getpmsg:
5cd4393b 6015 goto unimplemented;
ebc05488
FB
6016#endif
6017#ifdef TARGET_NR_putpmsg
31e31b8a 6018 case TARGET_NR_putpmsg:
5cd4393b 6019 goto unimplemented;
ebc05488 6020#endif
048f6b4d 6021#ifdef TARGET_NR_vfork
31e31b8a 6022 case TARGET_NR_vfork:
d865bab5
PB
6023 ret = get_errno(do_fork(cpu_env, CLONE_VFORK | CLONE_VM | SIGCHLD,
6024 0, 0, 0, 0));
31e31b8a 6025 break;
048f6b4d 6026#endif
ebc05488 6027#ifdef TARGET_NR_ugetrlimit
31e31b8a 6028 case TARGET_NR_ugetrlimit:
728584be
FB
6029 {
6030 struct rlimit rlim;
6031 ret = get_errno(getrlimit(arg1, &rlim));
6032 if (!is_error(ret)) {
53a5960a 6033 struct target_rlimit *target_rlim;
579a97f7
FB
6034 if (!lock_user_struct(VERIFY_WRITE, target_rlim, arg2, 0))
6035 goto efault;
728584be
FB
6036 target_rlim->rlim_cur = tswapl(rlim.rlim_cur);
6037 target_rlim->rlim_max = tswapl(rlim.rlim_max);
53a5960a 6038 unlock_user_struct(target_rlim, arg2, 1);
728584be
FB
6039 }
6040 break;
6041 }
ebc05488 6042#endif
a315a145 6043#ifdef TARGET_NR_truncate64
31e31b8a 6044 case TARGET_NR_truncate64:
579a97f7
FB
6045 if (!(p = lock_user_string(arg1)))
6046 goto efault;
53a5960a
PB
6047 ret = target_truncate64(cpu_env, p, arg2, arg3, arg4);
6048 unlock_user(p, arg1, 0);
667f38b1 6049 break;
a315a145
FB
6050#endif
6051#ifdef TARGET_NR_ftruncate64
31e31b8a 6052 case TARGET_NR_ftruncate64:
ce4defa0 6053 ret = target_ftruncate64(cpu_env, arg1, arg2, arg3, arg4);
667f38b1 6054 break;
a315a145
FB
6055#endif
6056#ifdef TARGET_NR_stat64
31e31b8a 6057 case TARGET_NR_stat64:
579a97f7
FB
6058 if (!(p = lock_user_string(arg1)))
6059 goto efault;
53a5960a
PB
6060 ret = get_errno(stat(path(p), &st));
6061 unlock_user(p, arg1, 0);
6a24a778
AZ
6062 if (!is_error(ret))
6063 ret = host_to_target_stat64(cpu_env, arg2, &st);
6064 break;
a315a145
FB
6065#endif
6066#ifdef TARGET_NR_lstat64
31e31b8a 6067 case TARGET_NR_lstat64:
579a97f7
FB
6068 if (!(p = lock_user_string(arg1)))
6069 goto efault;
53a5960a
PB
6070 ret = get_errno(lstat(path(p), &st));
6071 unlock_user(p, arg1, 0);
6a24a778
AZ
6072 if (!is_error(ret))
6073 ret = host_to_target_stat64(cpu_env, arg2, &st);
6074 break;
a315a145
FB
6075#endif
6076#ifdef TARGET_NR_fstat64
31e31b8a 6077 case TARGET_NR_fstat64:
6a24a778
AZ
6078 ret = get_errno(fstat(arg1, &st));
6079 if (!is_error(ret))
6080 ret = host_to_target_stat64(cpu_env, arg2, &st);
6081 break;
ce4defa0 6082#endif
9d33b76b
AJ
6083#if (defined(TARGET_NR_fstatat64) || defined(TARGET_NR_newfstatat)) && \
6084 (defined(__NR_fstatat64) || defined(__NR_newfstatat))
6085#ifdef TARGET_NR_fstatat64
6a24a778 6086 case TARGET_NR_fstatat64:
9d33b76b
AJ
6087#endif
6088#ifdef TARGET_NR_newfstatat
6089 case TARGET_NR_newfstatat:
6090#endif
6a24a778
AZ
6091 if (!(p = lock_user_string(arg2)))
6092 goto efault;
9d33b76b 6093#ifdef __NR_fstatat64
6a24a778 6094 ret = get_errno(sys_fstatat64(arg1, path(p), &st, arg4));
9d33b76b
AJ
6095#else
6096 ret = get_errno(sys_newfstatat(arg1, path(p), &st, arg4));
6097#endif
6a24a778
AZ
6098 if (!is_error(ret))
6099 ret = host_to_target_stat64(cpu_env, arg3, &st);
60cd49d5 6100 break;
a315a145 6101#endif
67867308
FB
6102#ifdef USE_UID16
6103 case TARGET_NR_lchown:
579a97f7
FB
6104 if (!(p = lock_user_string(arg1)))
6105 goto efault;
53a5960a
PB
6106 ret = get_errno(lchown(p, low2highuid(arg2), low2highgid(arg3)));
6107 unlock_user(p, arg1, 0);
67867308
FB
6108 break;
6109 case TARGET_NR_getuid:
6110 ret = get_errno(high2lowuid(getuid()));
6111 break;
6112 case TARGET_NR_getgid:
6113 ret = get_errno(high2lowgid(getgid()));
6114 break;
6115 case TARGET_NR_geteuid:
6116 ret = get_errno(high2lowuid(geteuid()));
6117 break;
6118 case TARGET_NR_getegid:
6119 ret = get_errno(high2lowgid(getegid()));
6120 break;
6121 case TARGET_NR_setreuid:
6122 ret = get_errno(setreuid(low2highuid(arg1), low2highuid(arg2)));
6123 break;
6124 case TARGET_NR_setregid:
6125 ret = get_errno(setregid(low2highgid(arg1), low2highgid(arg2)));
6126 break;
6127 case TARGET_NR_getgroups:
6128 {
6129 int gidsetsize = arg1;
53a5960a 6130 uint16_t *target_grouplist;
67867308
FB
6131 gid_t *grouplist;
6132 int i;
6133
6134 grouplist = alloca(gidsetsize * sizeof(gid_t));
6135 ret = get_errno(getgroups(gidsetsize, grouplist));
cb3bc233
AZ
6136 if (gidsetsize == 0)
6137 break;
67867308 6138 if (!is_error(ret)) {
579a97f7
FB
6139 target_grouplist = lock_user(VERIFY_WRITE, arg2, gidsetsize * 2, 0);
6140 if (!target_grouplist)
6141 goto efault;
a2155fcc 6142 for(i = 0;i < ret; i++)
67867308 6143 target_grouplist[i] = tswap16(grouplist[i]);
53a5960a 6144 unlock_user(target_grouplist, arg2, gidsetsize * 2);
67867308
FB
6145 }
6146 }
6147 break;
6148 case TARGET_NR_setgroups:
6149 {
6150 int gidsetsize = arg1;
53a5960a 6151 uint16_t *target_grouplist;
67867308
FB
6152 gid_t *grouplist;
6153 int i;
6154
6155 grouplist = alloca(gidsetsize * sizeof(gid_t));
579a97f7
FB
6156 target_grouplist = lock_user(VERIFY_READ, arg2, gidsetsize * 2, 1);
6157 if (!target_grouplist) {
6158 ret = -TARGET_EFAULT;
6159 goto fail;
6160 }
67867308
FB
6161 for(i = 0;i < gidsetsize; i++)
6162 grouplist[i] = tswap16(target_grouplist[i]);
53a5960a 6163 unlock_user(target_grouplist, arg2, 0);
67867308
FB
6164 ret = get_errno(setgroups(gidsetsize, grouplist));
6165 }
6166 break;
6167 case TARGET_NR_fchown:
6168 ret = get_errno(fchown(arg1, low2highuid(arg2), low2highgid(arg3)));
6169 break;
ccfa72b7
TS
6170#if defined(TARGET_NR_fchownat) && defined(__NR_fchownat)
6171 case TARGET_NR_fchownat:
579a97f7
FB
6172 if (!(p = lock_user_string(arg2)))
6173 goto efault;
6174 ret = get_errno(sys_fchownat(arg1, p, low2highuid(arg3), low2highgid(arg4), arg5));
6175 unlock_user(p, arg2, 0);
ccfa72b7
TS
6176 break;
6177#endif
67867308
FB
6178#ifdef TARGET_NR_setresuid
6179 case TARGET_NR_setresuid:
5fafdf24
TS
6180 ret = get_errno(setresuid(low2highuid(arg1),
6181 low2highuid(arg2),
67867308
FB
6182 low2highuid(arg3)));
6183 break;
6184#endif
6185#ifdef TARGET_NR_getresuid
6186 case TARGET_NR_getresuid:
6187 {
53a5960a 6188 uid_t ruid, euid, suid;
67867308
FB
6189 ret = get_errno(getresuid(&ruid, &euid, &suid));
6190 if (!is_error(ret)) {
2f619698
FB
6191 if (put_user_u16(high2lowuid(ruid), arg1)
6192 || put_user_u16(high2lowuid(euid), arg2)
6193 || put_user_u16(high2lowuid(suid), arg3))
6194 goto efault;
67867308
FB
6195 }
6196 }
6197 break;
6198#endif
6199#ifdef TARGET_NR_getresgid
6200 case TARGET_NR_setresgid:
5fafdf24
TS
6201 ret = get_errno(setresgid(low2highgid(arg1),
6202 low2highgid(arg2),
67867308
FB
6203 low2highgid(arg3)));
6204 break;
6205#endif
6206#ifdef TARGET_NR_getresgid
6207 case TARGET_NR_getresgid:
6208 {
53a5960a 6209 gid_t rgid, egid, sgid;
67867308
FB
6210 ret = get_errno(getresgid(&rgid, &egid, &sgid));
6211 if (!is_error(ret)) {
2f619698
FB
6212 if (put_user_u16(high2lowgid(rgid), arg1)
6213 || put_user_u16(high2lowgid(egid), arg2)
6214 || put_user_u16(high2lowgid(sgid), arg3))
6215 goto efault;
67867308
FB
6216 }
6217 }
6218 break;
6219#endif
6220 case TARGET_NR_chown:
579a97f7
FB
6221 if (!(p = lock_user_string(arg1)))
6222 goto efault;
53a5960a
PB
6223 ret = get_errno(chown(p, low2highuid(arg2), low2highgid(arg3)));
6224 unlock_user(p, arg1, 0);
67867308
FB
6225 break;
6226 case TARGET_NR_setuid:
6227 ret = get_errno(setuid(low2highuid(arg1)));
6228 break;
6229 case TARGET_NR_setgid:
6230 ret = get_errno(setgid(low2highgid(arg1)));
6231 break;
6232 case TARGET_NR_setfsuid:
6233 ret = get_errno(setfsuid(arg1));
6234 break;
6235 case TARGET_NR_setfsgid:
6236 ret = get_errno(setfsgid(arg1));
6237 break;
6238#endif /* USE_UID16 */
6239
a315a145 6240#ifdef TARGET_NR_lchown32
31e31b8a 6241 case TARGET_NR_lchown32:
579a97f7
FB
6242 if (!(p = lock_user_string(arg1)))
6243 goto efault;
53a5960a
PB
6244 ret = get_errno(lchown(p, arg2, arg3));
6245 unlock_user(p, arg1, 0);
b03c60f3 6246 break;
a315a145
FB
6247#endif
6248#ifdef TARGET_NR_getuid32
31e31b8a 6249 case TARGET_NR_getuid32:
b03c60f3
FB
6250 ret = get_errno(getuid());
6251 break;
a315a145 6252#endif
64b4d28c
AJ
6253
6254#if defined(TARGET_NR_getxuid) && defined(TARGET_ALPHA)
6255 /* Alpha specific */
6256 case TARGET_NR_getxuid:
6257 {
6258 uid_t euid;
6259 euid=geteuid();
6260 ((CPUAlphaState *)cpu_env)->ir[IR_A4]=euid;
6261 }
6262 ret = get_errno(getuid());
6263 break;
6264#endif
6265#if defined(TARGET_NR_getxgid) && defined(TARGET_ALPHA)
6266 /* Alpha specific */
6267 case TARGET_NR_getxgid:
6268 {
6269 uid_t egid;
6270 egid=getegid();
6271 ((CPUAlphaState *)cpu_env)->ir[IR_A4]=egid;
6272 }
6273 ret = get_errno(getgid());
6274 break;
6275#endif
6276
a315a145 6277#ifdef TARGET_NR_getgid32
31e31b8a 6278 case TARGET_NR_getgid32:
b03c60f3
FB
6279 ret = get_errno(getgid());
6280 break;
a315a145
FB
6281#endif
6282#ifdef TARGET_NR_geteuid32
31e31b8a 6283 case TARGET_NR_geteuid32:
b03c60f3
FB
6284 ret = get_errno(geteuid());
6285 break;
a315a145
FB
6286#endif
6287#ifdef TARGET_NR_getegid32
31e31b8a 6288 case TARGET_NR_getegid32:
b03c60f3
FB
6289 ret = get_errno(getegid());
6290 break;
a315a145
FB
6291#endif
6292#ifdef TARGET_NR_setreuid32
31e31b8a 6293 case TARGET_NR_setreuid32:
b03c60f3
FB
6294 ret = get_errno(setreuid(arg1, arg2));
6295 break;
a315a145
FB
6296#endif
6297#ifdef TARGET_NR_setregid32
31e31b8a 6298 case TARGET_NR_setregid32:
b03c60f3
FB
6299 ret = get_errno(setregid(arg1, arg2));
6300 break;
a315a145
FB
6301#endif
6302#ifdef TARGET_NR_getgroups32
31e31b8a 6303 case TARGET_NR_getgroups32:
99c475ab
FB
6304 {
6305 int gidsetsize = arg1;
53a5960a 6306 uint32_t *target_grouplist;
99c475ab
FB
6307 gid_t *grouplist;
6308 int i;
6309
6310 grouplist = alloca(gidsetsize * sizeof(gid_t));
6311 ret = get_errno(getgroups(gidsetsize, grouplist));
cb3bc233
AZ
6312 if (gidsetsize == 0)
6313 break;
99c475ab 6314 if (!is_error(ret)) {
579a97f7
FB
6315 target_grouplist = lock_user(VERIFY_WRITE, arg2, gidsetsize * 4, 0);
6316 if (!target_grouplist) {
6317 ret = -TARGET_EFAULT;
6318 goto fail;
6319 }
a2155fcc 6320 for(i = 0;i < ret; i++)
53a5960a
PB
6321 target_grouplist[i] = tswap32(grouplist[i]);
6322 unlock_user(target_grouplist, arg2, gidsetsize * 4);
99c475ab
FB
6323 }
6324 }
6325 break;
a315a145
FB
6326#endif
6327#ifdef TARGET_NR_setgroups32
31e31b8a 6328 case TARGET_NR_setgroups32:
99c475ab
FB
6329 {
6330 int gidsetsize = arg1;
53a5960a 6331 uint32_t *target_grouplist;
99c475ab
FB
6332 gid_t *grouplist;
6333 int i;
3b46e624 6334
99c475ab 6335 grouplist = alloca(gidsetsize * sizeof(gid_t));
579a97f7
FB
6336 target_grouplist = lock_user(VERIFY_READ, arg2, gidsetsize * 4, 1);
6337 if (!target_grouplist) {
6338 ret = -TARGET_EFAULT;
6339 goto fail;
6340 }
99c475ab 6341 for(i = 0;i < gidsetsize; i++)
53a5960a
PB
6342 grouplist[i] = tswap32(target_grouplist[i]);
6343 unlock_user(target_grouplist, arg2, 0);
99c475ab
FB
6344 ret = get_errno(setgroups(gidsetsize, grouplist));
6345 }
6346 break;
a315a145
FB
6347#endif
6348#ifdef TARGET_NR_fchown32
31e31b8a 6349 case TARGET_NR_fchown32:
b03c60f3
FB
6350 ret = get_errno(fchown(arg1, arg2, arg3));
6351 break;
a315a145
FB
6352#endif
6353#ifdef TARGET_NR_setresuid32
31e31b8a 6354 case TARGET_NR_setresuid32:
b03c60f3
FB
6355 ret = get_errno(setresuid(arg1, arg2, arg3));
6356 break;
a315a145
FB
6357#endif
6358#ifdef TARGET_NR_getresuid32
31e31b8a 6359 case TARGET_NR_getresuid32:
b03c60f3 6360 {
53a5960a 6361 uid_t ruid, euid, suid;
b03c60f3
FB
6362 ret = get_errno(getresuid(&ruid, &euid, &suid));
6363 if (!is_error(ret)) {
2f619698
FB
6364 if (put_user_u32(ruid, arg1)
6365 || put_user_u32(euid, arg2)
6366 || put_user_u32(suid, arg3))
6367 goto efault;
b03c60f3
FB
6368 }
6369 }
6370 break;
a315a145
FB
6371#endif
6372#ifdef TARGET_NR_setresgid32
31e31b8a 6373 case TARGET_NR_setresgid32:
b03c60f3
FB
6374 ret = get_errno(setresgid(arg1, arg2, arg3));
6375 break;
a315a145
FB
6376#endif
6377#ifdef TARGET_NR_getresgid32
31e31b8a 6378 case TARGET_NR_getresgid32:
b03c60f3 6379 {
53a5960a 6380 gid_t rgid, egid, sgid;
b03c60f3
FB
6381 ret = get_errno(getresgid(&rgid, &egid, &sgid));
6382 if (!is_error(ret)) {
2f619698
FB
6383 if (put_user_u32(rgid, arg1)
6384 || put_user_u32(egid, arg2)
6385 || put_user_u32(sgid, arg3))
6386 goto efault;
b03c60f3
FB
6387 }
6388 }
6389 break;
a315a145
FB
6390#endif
6391#ifdef TARGET_NR_chown32
31e31b8a 6392 case TARGET_NR_chown32:
579a97f7
FB
6393 if (!(p = lock_user_string(arg1)))
6394 goto efault;
53a5960a
PB
6395 ret = get_errno(chown(p, arg2, arg3));
6396 unlock_user(p, arg1, 0);
b03c60f3 6397 break;
a315a145
FB
6398#endif
6399#ifdef TARGET_NR_setuid32
31e31b8a 6400 case TARGET_NR_setuid32:
b03c60f3
FB
6401 ret = get_errno(setuid(arg1));
6402 break;
a315a145
FB
6403#endif
6404#ifdef TARGET_NR_setgid32
31e31b8a 6405 case TARGET_NR_setgid32:
b03c60f3
FB
6406 ret = get_errno(setgid(arg1));
6407 break;
a315a145
FB
6408#endif
6409#ifdef TARGET_NR_setfsuid32
31e31b8a 6410 case TARGET_NR_setfsuid32:
b03c60f3
FB
6411 ret = get_errno(setfsuid(arg1));
6412 break;
a315a145
FB
6413#endif
6414#ifdef TARGET_NR_setfsgid32
31e31b8a 6415 case TARGET_NR_setfsgid32:
b03c60f3
FB
6416 ret = get_errno(setfsgid(arg1));
6417 break;
a315a145 6418#endif
67867308 6419
31e31b8a 6420 case TARGET_NR_pivot_root:
b03c60f3 6421 goto unimplemented;
ffa65c3b 6422#ifdef TARGET_NR_mincore
31e31b8a 6423 case TARGET_NR_mincore:
04bb9ace
AJ
6424 {
6425 void *a;
6426 ret = -TARGET_EFAULT;
6427 if (!(a = lock_user(VERIFY_READ, arg1,arg2, 0)))
6428 goto efault;
6429 if (!(p = lock_user_string(arg3)))
6430 goto mincore_fail;
6431 ret = get_errno(mincore(a, arg2, p));
6432 unlock_user(p, arg3, ret);
6433 mincore_fail:
6434 unlock_user(a, arg1, 0);
6435 }
6436 break;
ffa65c3b 6437#endif
408321b6
AJ
6438#ifdef TARGET_NR_arm_fadvise64_64
6439 case TARGET_NR_arm_fadvise64_64:
6440 {
6441 /*
6442 * arm_fadvise64_64 looks like fadvise64_64 but
6443 * with different argument order
6444 */
6445 abi_long temp;
6446 temp = arg3;
6447 arg3 = arg4;
6448 arg4 = temp;
6449 }
6450#endif
6451#if defined(TARGET_NR_fadvise64_64) || defined(TARGET_NR_arm_fadvise64_64)
6452#ifdef TARGET_NR_fadvise64_64
6453 case TARGET_NR_fadvise64_64:
6454#endif
6455 /* This is a hint, so ignoring and returning success is ok. */
6456 ret = get_errno(0);
6457 break;
6458#endif
ffa65c3b 6459#ifdef TARGET_NR_madvise
31e31b8a 6460 case TARGET_NR_madvise:
24836689
PB
6461 /* A straight passthrough may not be safe because qemu sometimes
6462 turns private flie-backed mappings into anonymous mappings.
6463 This will break MADV_DONTNEED.
6464 This is a hint, so ignoring and returning success is ok. */
6465 ret = get_errno(0);
6466 break;
ffa65c3b 6467#endif
992f48a0 6468#if TARGET_ABI_BITS == 32
31e31b8a 6469 case TARGET_NR_fcntl64:
77e4672d 6470 {
b1e341eb 6471 int cmd;
77e4672d 6472 struct flock64 fl;
53a5960a 6473 struct target_flock64 *target_fl;
ce4defa0 6474#ifdef TARGET_ARM
53a5960a 6475 struct target_eabi_flock64 *target_efl;
ce4defa0 6476#endif
77e4672d 6477
b1e341eb
TS
6478 switch(arg2){
6479 case TARGET_F_GETLK64:
6480 cmd = F_GETLK64;
a7222580 6481 break;
b1e341eb
TS
6482 case TARGET_F_SETLK64:
6483 cmd = F_SETLK64;
a7222580 6484 break;
b1e341eb
TS
6485 case TARGET_F_SETLKW64:
6486 cmd = F_SETLK64;
a7222580 6487 break;
b1e341eb
TS
6488 default:
6489 cmd = arg2;
a7222580 6490 break;
b1e341eb
TS
6491 }
6492
60cd49d5 6493 switch(arg2) {
b1e341eb 6494 case TARGET_F_GETLK64:
5813427b
TS
6495#ifdef TARGET_ARM
6496 if (((CPUARMState *)cpu_env)->eabi) {
9ee1fa2c
FB
6497 if (!lock_user_struct(VERIFY_READ, target_efl, arg3, 1))
6498 goto efault;
5813427b
TS
6499 fl.l_type = tswap16(target_efl->l_type);
6500 fl.l_whence = tswap16(target_efl->l_whence);
6501 fl.l_start = tswap64(target_efl->l_start);
6502 fl.l_len = tswap64(target_efl->l_len);
6503 fl.l_pid = tswapl(target_efl->l_pid);
6504 unlock_user_struct(target_efl, arg3, 0);
6505 } else
6506#endif
6507 {
9ee1fa2c
FB
6508 if (!lock_user_struct(VERIFY_READ, target_fl, arg3, 1))
6509 goto efault;
5813427b
TS
6510 fl.l_type = tswap16(target_fl->l_type);
6511 fl.l_whence = tswap16(target_fl->l_whence);
6512 fl.l_start = tswap64(target_fl->l_start);
6513 fl.l_len = tswap64(target_fl->l_len);
6514 fl.l_pid = tswapl(target_fl->l_pid);
6515 unlock_user_struct(target_fl, arg3, 0);
6516 }
b1e341eb 6517 ret = get_errno(fcntl(arg1, cmd, &fl));
77e4672d 6518 if (ret == 0) {
ce4defa0
PB
6519#ifdef TARGET_ARM
6520 if (((CPUARMState *)cpu_env)->eabi) {
9ee1fa2c
FB
6521 if (!lock_user_struct(VERIFY_WRITE, target_efl, arg3, 0))
6522 goto efault;
ce4defa0
PB
6523 target_efl->l_type = tswap16(fl.l_type);
6524 target_efl->l_whence = tswap16(fl.l_whence);
6525 target_efl->l_start = tswap64(fl.l_start);
6526 target_efl->l_len = tswap64(fl.l_len);
6527 target_efl->l_pid = tswapl(fl.l_pid);
53a5960a 6528 unlock_user_struct(target_efl, arg3, 1);
ce4defa0
PB
6529 } else
6530#endif
6531 {
9ee1fa2c
FB
6532 if (!lock_user_struct(VERIFY_WRITE, target_fl, arg3, 0))
6533 goto efault;
ce4defa0
PB
6534 target_fl->l_type = tswap16(fl.l_type);
6535 target_fl->l_whence = tswap16(fl.l_whence);
6536 target_fl->l_start = tswap64(fl.l_start);
6537 target_fl->l_len = tswap64(fl.l_len);
6538 target_fl->l_pid = tswapl(fl.l_pid);
53a5960a 6539 unlock_user_struct(target_fl, arg3, 1);
ce4defa0 6540 }
77e4672d
FB
6541 }
6542 break;
6543
b1e341eb
TS
6544 case TARGET_F_SETLK64:
6545 case TARGET_F_SETLKW64:
ce4defa0
PB
6546#ifdef TARGET_ARM
6547 if (((CPUARMState *)cpu_env)->eabi) {
9ee1fa2c
FB
6548 if (!lock_user_struct(VERIFY_READ, target_efl, arg3, 1))
6549 goto efault;
ce4defa0
PB
6550 fl.l_type = tswap16(target_efl->l_type);
6551 fl.l_whence = tswap16(target_efl->l_whence);
6552 fl.l_start = tswap64(target_efl->l_start);
6553 fl.l_len = tswap64(target_efl->l_len);
6554 fl.l_pid = tswapl(target_efl->l_pid);
53a5960a 6555 unlock_user_struct(target_efl, arg3, 0);
ce4defa0
PB
6556 } else
6557#endif
6558 {
9ee1fa2c
FB
6559 if (!lock_user_struct(VERIFY_READ, target_fl, arg3, 1))
6560 goto efault;
ce4defa0
PB
6561 fl.l_type = tswap16(target_fl->l_type);
6562 fl.l_whence = tswap16(target_fl->l_whence);
6563 fl.l_start = tswap64(target_fl->l_start);
6564 fl.l_len = tswap64(target_fl->l_len);
6565 fl.l_pid = tswapl(target_fl->l_pid);
53a5960a 6566 unlock_user_struct(target_fl, arg3, 0);
ce4defa0 6567 }
b1e341eb 6568 ret = get_errno(fcntl(arg1, cmd, &fl));
77e4672d 6569 break;
60cd49d5 6570 default:
9ee1fa2c 6571 ret = do_fcntl(arg1, cmd, arg3);
60cd49d5
FB
6572 break;
6573 }
77e4672d
FB
6574 break;
6575 }
60cd49d5 6576#endif
7d600c80
TS
6577#ifdef TARGET_NR_cacheflush
6578 case TARGET_NR_cacheflush:
6579 /* self-modifying code is handled automatically, so nothing needed */
6580 ret = 0;
6581 break;
6582#endif
ebc05488 6583#ifdef TARGET_NR_security
31e31b8a
FB
6584 case TARGET_NR_security:
6585 goto unimplemented;
c573ff67
FB
6586#endif
6587#ifdef TARGET_NR_getpagesize
6588 case TARGET_NR_getpagesize:
6589 ret = TARGET_PAGE_SIZE;
6590 break;
ebc05488 6591#endif
31e31b8a
FB
6592 case TARGET_NR_gettid:
6593 ret = get_errno(gettid());
6594 break;
e5febef5 6595#ifdef TARGET_NR_readahead
31e31b8a 6596 case TARGET_NR_readahead:
2054ac9b
AJ
6597#if TARGET_ABI_BITS == 32
6598#ifdef TARGET_ARM
6599 if (((CPUARMState *)cpu_env)->eabi)
6600 {
6601 arg2 = arg3;
6602 arg3 = arg4;
6603 arg4 = arg5;
6604 }
6605#endif
6606 ret = get_errno(readahead(arg1, ((off64_t)arg3 << 32) | arg2, arg4));
6607#else
6608 ret = get_errno(readahead(arg1, arg2, arg3));
6609#endif
6610 break;
e5febef5 6611#endif
ebc05488 6612#ifdef TARGET_NR_setxattr
31e31b8a
FB
6613 case TARGET_NR_setxattr:
6614 case TARGET_NR_lsetxattr:
6615 case TARGET_NR_fsetxattr:
6616 case TARGET_NR_getxattr:
6617 case TARGET_NR_lgetxattr:
6618 case TARGET_NR_fgetxattr:
6619 case TARGET_NR_listxattr:
6620 case TARGET_NR_llistxattr:
6621 case TARGET_NR_flistxattr:
6622 case TARGET_NR_removexattr:
6623 case TARGET_NR_lremovexattr:
6624 case TARGET_NR_fremovexattr:
6f932f91
AP
6625 ret = -TARGET_EOPNOTSUPP;
6626 break;
ebc05488
FB
6627#endif
6628#ifdef TARGET_NR_set_thread_area
5cd4393b 6629 case TARGET_NR_set_thread_area:
8d18e893 6630#if defined(TARGET_MIPS)
6f5b89a0
TS
6631 ((CPUMIPSState *) cpu_env)->tls_value = arg1;
6632 ret = 0;
6633 break;
ef96779b
EI
6634#elif defined(TARGET_CRIS)
6635 if (arg1 & 0xff)
6636 ret = -TARGET_EINVAL;
6637 else {
6638 ((CPUCRISState *) cpu_env)->pregs[PR_PID] = arg1;
6639 ret = 0;
6640 }
6641 break;
8d18e893
FB
6642#elif defined(TARGET_I386) && defined(TARGET_ABI32)
6643 ret = do_set_thread_area(cpu_env, arg1);
6644 break;
6f5b89a0
TS
6645#else
6646 goto unimplemented_nowarn;
6647#endif
6648#endif
6649#ifdef TARGET_NR_get_thread_area
5cd4393b 6650 case TARGET_NR_get_thread_area:
8d18e893
FB
6651#if defined(TARGET_I386) && defined(TARGET_ABI32)
6652 ret = do_get_thread_area(cpu_env, arg1);
6653#else
5cd4393b 6654 goto unimplemented_nowarn;
48dc41eb 6655#endif
8d18e893 6656#endif
48dc41eb
FB
6657#ifdef TARGET_NR_getdomainname
6658 case TARGET_NR_getdomainname:
6659 goto unimplemented_nowarn;
ebc05488 6660#endif
6f5b89a0 6661
b5906f95
TS
6662#ifdef TARGET_NR_clock_gettime
6663 case TARGET_NR_clock_gettime:
6664 {
6665 struct timespec ts;
6666 ret = get_errno(clock_gettime(arg1, &ts));
6667 if (!is_error(ret)) {
6668 host_to_target_timespec(arg2, &ts);
6669 }
6670 break;
6671 }
6672#endif
6673#ifdef TARGET_NR_clock_getres
6674 case TARGET_NR_clock_getres:
6675 {
6676 struct timespec ts;
6677 ret = get_errno(clock_getres(arg1, &ts));
6678 if (!is_error(ret)) {
6679 host_to_target_timespec(arg2, &ts);
6680 }
6681 break;
6682 }
6683#endif
63d7651b
PB
6684#ifdef TARGET_NR_clock_nanosleep
6685 case TARGET_NR_clock_nanosleep:
6686 {
6687 struct timespec ts;
6688 target_to_host_timespec(&ts, arg3);
6689 ret = get_errno(clock_nanosleep(arg1, arg2, &ts, arg4 ? &ts : NULL));
6690 if (arg4)
6691 host_to_target_timespec(arg4, &ts);
6692 break;
6693 }
6694#endif
b5906f95 6695
6f5b89a0
TS
6696#if defined(TARGET_NR_set_tid_address) && defined(__NR_set_tid_address)
6697 case TARGET_NR_set_tid_address:
579a97f7
FB
6698 ret = get_errno(set_tid_address((int *)g2h(arg1)));
6699 break;
6f5b89a0
TS
6700#endif
6701
3ae43202 6702#if defined(TARGET_NR_tkill) && defined(__NR_tkill)
4cae1d16 6703 case TARGET_NR_tkill:
4cb05961 6704 ret = get_errno(sys_tkill((int)arg1, target_to_host_signal(arg2)));
4cae1d16
TS
6705 break;
6706#endif
6707
3ae43202 6708#if defined(TARGET_NR_tgkill) && defined(__NR_tgkill)
71455574 6709 case TARGET_NR_tgkill:
4cb05961
PB
6710 ret = get_errno(sys_tgkill((int)arg1, (int)arg2,
6711 target_to_host_signal(arg3)));
71455574
TS
6712 break;
6713#endif
6714
4f2b1fe8
TS
6715#ifdef TARGET_NR_set_robust_list
6716 case TARGET_NR_set_robust_list:
6717 goto unimplemented_nowarn;
6718#endif
6719
9007f0ef
TS
6720#if defined(TARGET_NR_utimensat) && defined(__NR_utimensat)
6721 case TARGET_NR_utimensat:
6722 {
ebc996f3
RV
6723 struct timespec *tsp, ts[2];
6724 if (!arg3) {
6725 tsp = NULL;
6726 } else {
6727 target_to_host_timespec(ts, arg3);
6728 target_to_host_timespec(ts+1, arg3+sizeof(struct target_timespec));
6729 tsp = ts;
6730 }
9007f0ef 6731 if (!arg2)
ebc996f3 6732 ret = get_errno(sys_utimensat(arg1, NULL, tsp, arg4));
9007f0ef 6733 else {
579a97f7 6734 if (!(p = lock_user_string(arg2))) {
0da46a6e 6735 ret = -TARGET_EFAULT;
579a97f7
FB
6736 goto fail;
6737 }
ebc996f3 6738 ret = get_errno(sys_utimensat(arg1, path(p), tsp, arg4));
579a97f7 6739 unlock_user(p, arg2, 0);
9007f0ef
TS
6740 }
6741 }
6742 break;
6743#endif
bd0c5661
PB
6744#if defined(USE_NPTL)
6745 case TARGET_NR_futex:
6746 ret = do_futex(arg1, arg2, arg3, arg4, arg5, arg6);
6747 break;
6748#endif
dbfe4c36 6749#if defined(TARGET_NR_inotify_init) && defined(__NR_inotify_init)
39b59763
AJ
6750 case TARGET_NR_inotify_init:
6751 ret = get_errno(sys_inotify_init());
6752 break;
6753#endif
dbfe4c36 6754#if defined(TARGET_NR_inotify_add_watch) && defined(__NR_inotify_add_watch)
39b59763
AJ
6755 case TARGET_NR_inotify_add_watch:
6756 p = lock_user_string(arg2);
6757 ret = get_errno(sys_inotify_add_watch(arg1, path(p), arg3));
6758 unlock_user(p, arg2, 0);
6759 break;
6760#endif
dbfe4c36 6761#if defined(TARGET_NR_inotify_rm_watch) && defined(__NR_inotify_rm_watch)
39b59763
AJ
6762 case TARGET_NR_inotify_rm_watch:
6763 ret = get_errno(sys_inotify_rm_watch(arg1, arg2));
6764 break;
6765#endif
9007f0ef 6766
24e1003a
AJ
6767#ifdef TARGET_NR_mq_open
6768 case TARGET_NR_mq_open:
6769 {
6770 struct mq_attr posix_mq_attr;
6771
6772 p = lock_user_string(arg1 - 1);
6773 if (arg4 != 0)
6774 copy_from_user_mq_attr (&posix_mq_attr, arg4);
6775 ret = get_errno(mq_open(p, arg2, arg3, &posix_mq_attr));
6776 unlock_user (p, arg1, 0);
6777 }
6778 break;
6779
6780 case TARGET_NR_mq_unlink:
6781 p = lock_user_string(arg1 - 1);
6782 ret = get_errno(mq_unlink(p));
6783 unlock_user (p, arg1, 0);
6784 break;
6785
6786 case TARGET_NR_mq_timedsend:
6787 {
6788 struct timespec ts;
6789
6790 p = lock_user (VERIFY_READ, arg2, arg3, 1);
6791 if (arg5 != 0) {
6792 target_to_host_timespec(&ts, arg5);
6793 ret = get_errno(mq_timedsend(arg1, p, arg3, arg4, &ts));
6794 host_to_target_timespec(arg5, &ts);
6795 }
6796 else
6797 ret = get_errno(mq_send(arg1, p, arg3, arg4));
6798 unlock_user (p, arg2, arg3);
6799 }
6800 break;
6801
6802 case TARGET_NR_mq_timedreceive:
6803 {
6804 struct timespec ts;
6805 unsigned int prio;
6806
6807 p = lock_user (VERIFY_READ, arg2, arg3, 1);
6808 if (arg5 != 0) {
6809 target_to_host_timespec(&ts, arg5);
6810 ret = get_errno(mq_timedreceive(arg1, p, arg3, &prio, &ts));
6811 host_to_target_timespec(arg5, &ts);
6812 }
6813 else
6814 ret = get_errno(mq_receive(arg1, p, arg3, &prio));
6815 unlock_user (p, arg2, arg3);
6816 if (arg4 != 0)
6817 put_user_u32(prio, arg4);
6818 }
6819 break;
6820
6821 /* Not implemented for now... */
6822/* case TARGET_NR_mq_notify: */
6823/* break; */
6824
6825 case TARGET_NR_mq_getsetattr:
6826 {
6827 struct mq_attr posix_mq_attr_in, posix_mq_attr_out;
6828 ret = 0;
6829 if (arg3 != 0) {
6830 ret = mq_getattr(arg1, &posix_mq_attr_out);
6831 copy_to_user_mq_attr(arg3, &posix_mq_attr_out);
6832 }
6833 if (arg2 != 0) {
6834 copy_from_user_mq_attr(&posix_mq_attr_in, arg2);
6835 ret |= mq_setattr(arg1, &posix_mq_attr_in, &posix_mq_attr_out);
6836 }
6837
6838 }
6839 break;
6840#endif
6841
31e31b8a
FB
6842 default:
6843 unimplemented:
5cd4393b 6844 gemu_log("qemu: Unsupported syscall: %d\n", num);
4f2b1fe8 6845#if defined(TARGET_NR_setxattr) || defined(TARGET_NR_get_thread_area) || defined(TARGET_NR_getdomainname) || defined(TARGET_NR_set_robust_list)
5cd4393b 6846 unimplemented_nowarn:
80a9d035 6847#endif
0da46a6e 6848 ret = -TARGET_ENOSYS;
31e31b8a
FB
6849 break;
6850 }
579a97f7 6851fail:
c573ff67
FB
6852#ifdef DEBUG
6853 gemu_log(" = %ld\n", ret);
6854#endif
b92c47c1
TS
6855 if(do_strace)
6856 print_syscall_ret(num, ret);
31e31b8a 6857 return ret;
579a97f7
FB
6858efault:
6859 ret = -TARGET_EFAULT;
6860 goto fail;
31e31b8a 6861}