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