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