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