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