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