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