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