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