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