]> git.proxmox.com Git - qemu.git/blame - linux-user/syscall.c
Fix some warnings that would be generated by gcc -Wredundant-decls
[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
4583f589 198#if defined(TARGET_NR_fchownat) && defined(__NR_fchownat) && defined(USE_UID16)
ccfa72b7
TS
199_syscall5(int,sys_fchownat,int,dirfd,const char *,pathname,
200 uid_t,owner,gid_t,group,int,flags)
201#endif
72f03900 202_syscall2(int,sys_getcwd1,char *,buf,size_t,size)
4583f589 203#if TARGET_ABI_BITS == 32
72f03900 204_syscall3(int, sys_getdents, uint, fd, struct dirent *, dirp, uint, count);
4583f589 205#endif
3ae43202 206#if defined(TARGET_NR_getdents64) && defined(__NR_getdents64)
dab2ed99 207_syscall3(int, sys_getdents64, uint, fd, struct dirent64 *, dirp, uint, count);
3ae43202 208#endif
c6cda17a 209_syscall2(int, sys_getpriority, int, which, int, who);
8fcd3692 210#if !defined (__x86_64__)
31e31b8a
FB
211_syscall5(int, _llseek, uint, fd, ulong, hi, ulong, lo,
212 loff_t *, res, uint, wh);
8fcd3692 213#endif
64f0ce4c
TS
214#if defined(TARGET_NR_linkat) && defined(__NR_linkat)
215_syscall5(int,sys_linkat,int,olddirfd,const char *,oldpath,
216 int,newdirfd,const char *,newpath,int,flags)
217#endif
4472ad0d
TS
218#if defined(TARGET_NR_mkdirat) && defined(__NR_mkdirat)
219_syscall3(int,sys_mkdirat,int,dirfd,const char *,pathname,mode_t,mode)
220#endif
75ac37a0
TS
221#if defined(TARGET_NR_mknodat) && defined(__NR_mknodat)
222_syscall4(int,sys_mknodat,int,dirfd,const char *,pathname,
223 mode_t,mode,dev_t,dev)
224#endif
82424832
TS
225#if defined(TARGET_NR_openat) && defined(__NR_openat)
226_syscall4(int,sys_openat,int,dirfd,const char *,pathname,int,flags,mode_t,mode)
227#endif
5e0ccb18
TS
228#if defined(TARGET_NR_readlinkat) && defined(__NR_readlinkat)
229_syscall4(int,sys_readlinkat,int,dirfd,const char *,pathname,
230 char *,buf,size_t,bufsize)
231#endif
722183f6
TS
232#if defined(TARGET_NR_renameat) && defined(__NR_renameat)
233_syscall4(int,sys_renameat,int,olddirfd,const char *,oldpath,
234 int,newdirfd,const char *,newpath)
235#endif
66fb9763 236_syscall3(int,sys_rt_sigqueueinfo,int,pid,int,sig,siginfo_t *,uinfo)
b51eaa82 237#if defined(TARGET_NR_symlinkat) && defined(__NR_symlinkat)
f0b6243d
TS
238_syscall3(int,sys_symlinkat,const char *,oldpath,
239 int,newdirfd,const char *,newpath)
240#endif
7494b0f9 241_syscall3(int,sys_syslog,int,type,char*,bufp,int,len)
3ae43202 242#if defined(TARGET_NR_tgkill) && defined(__NR_tgkill)
71455574 243_syscall3(int,sys_tgkill,int,tgid,int,pid,int,sig)
4cae1d16 244#endif
3ae43202 245#if defined(TARGET_NR_tkill) && defined(__NR_tkill)
4cae1d16
TS
246_syscall2(int,sys_tkill,int,tid,int,sig)
247#endif
ec86b0fb
FB
248#ifdef __NR_exit_group
249_syscall1(int,exit_group,int,error_code)
250#endif
6f5b89a0
TS
251#if defined(TARGET_NR_set_tid_address) && defined(__NR_set_tid_address)
252_syscall1(int,set_tid_address,int *,tidptr)
253#endif
8170f56b
TS
254#if defined(TARGET_NR_unlinkat) && defined(__NR_unlinkat)
255_syscall3(int,sys_unlinkat,int,dirfd,const char *,pathname,int,flags)
256#endif
9007f0ef
TS
257#if defined(TARGET_NR_utimensat) && defined(__NR_utimensat)
258_syscall4(int,sys_utimensat,int,dirfd,const char *,pathname,
259 const struct timespec *,tsp,int,flags)
260#endif
8fcd3692 261#if defined(USE_NPTL)
bd0c5661
PB
262#if defined(TARGET_NR_futex) && defined(__NR_futex)
263_syscall6(int,sys_futex,int *,uaddr,int,op,int,val,
264 const struct timespec *,timeout,int *,uaddr2,int,val3)
8fcd3692 265#endif
bd0c5661 266#endif
66fb9763
FB
267
268extern int personality(int);
9de5e440
FB
269extern int flock(int, int);
270extern int setfsuid(int);
271extern int setfsgid(int);
19b84f3c 272extern int setgroups(int, gid_t *);
31e31b8a 273
b92c47c1
TS
274#define ERRNO_TABLE_SIZE 1200
275
276/* target_to_host_errno_table[] is initialized from
277 * host_to_target_errno_table[] in syscall_init(). */
278static uint16_t target_to_host_errno_table[ERRNO_TABLE_SIZE] = {
279};
280
637947f1 281/*
fe8f096b 282 * This list is the union of errno values overridden in asm-<arch>/errno.h
637947f1
TS
283 * minus the errnos that are not actually generic to all archs.
284 */
b92c47c1 285static uint16_t host_to_target_errno_table[ERRNO_TABLE_SIZE] = {
637947f1
TS
286 [EIDRM] = TARGET_EIDRM,
287 [ECHRNG] = TARGET_ECHRNG,
288 [EL2NSYNC] = TARGET_EL2NSYNC,
289 [EL3HLT] = TARGET_EL3HLT,
290 [EL3RST] = TARGET_EL3RST,
291 [ELNRNG] = TARGET_ELNRNG,
292 [EUNATCH] = TARGET_EUNATCH,
293 [ENOCSI] = TARGET_ENOCSI,
294 [EL2HLT] = TARGET_EL2HLT,
295 [EDEADLK] = TARGET_EDEADLK,
296 [ENOLCK] = TARGET_ENOLCK,
297 [EBADE] = TARGET_EBADE,
298 [EBADR] = TARGET_EBADR,
299 [EXFULL] = TARGET_EXFULL,
300 [ENOANO] = TARGET_ENOANO,
301 [EBADRQC] = TARGET_EBADRQC,
302 [EBADSLT] = TARGET_EBADSLT,
303 [EBFONT] = TARGET_EBFONT,
304 [ENOSTR] = TARGET_ENOSTR,
305 [ENODATA] = TARGET_ENODATA,
306 [ETIME] = TARGET_ETIME,
307 [ENOSR] = TARGET_ENOSR,
308 [ENONET] = TARGET_ENONET,
309 [ENOPKG] = TARGET_ENOPKG,
310 [EREMOTE] = TARGET_EREMOTE,
311 [ENOLINK] = TARGET_ENOLINK,
312 [EADV] = TARGET_EADV,
313 [ESRMNT] = TARGET_ESRMNT,
314 [ECOMM] = TARGET_ECOMM,
315 [EPROTO] = TARGET_EPROTO,
316 [EDOTDOT] = TARGET_EDOTDOT,
317 [EMULTIHOP] = TARGET_EMULTIHOP,
318 [EBADMSG] = TARGET_EBADMSG,
319 [ENAMETOOLONG] = TARGET_ENAMETOOLONG,
320 [EOVERFLOW] = TARGET_EOVERFLOW,
321 [ENOTUNIQ] = TARGET_ENOTUNIQ,
322 [EBADFD] = TARGET_EBADFD,
323 [EREMCHG] = TARGET_EREMCHG,
324 [ELIBACC] = TARGET_ELIBACC,
325 [ELIBBAD] = TARGET_ELIBBAD,
326 [ELIBSCN] = TARGET_ELIBSCN,
327 [ELIBMAX] = TARGET_ELIBMAX,
328 [ELIBEXEC] = TARGET_ELIBEXEC,
329 [EILSEQ] = TARGET_EILSEQ,
330 [ENOSYS] = TARGET_ENOSYS,
331 [ELOOP] = TARGET_ELOOP,
332 [ERESTART] = TARGET_ERESTART,
333 [ESTRPIPE] = TARGET_ESTRPIPE,
334 [ENOTEMPTY] = TARGET_ENOTEMPTY,
335 [EUSERS] = TARGET_EUSERS,
336 [ENOTSOCK] = TARGET_ENOTSOCK,
337 [EDESTADDRREQ] = TARGET_EDESTADDRREQ,
338 [EMSGSIZE] = TARGET_EMSGSIZE,
339 [EPROTOTYPE] = TARGET_EPROTOTYPE,
340 [ENOPROTOOPT] = TARGET_ENOPROTOOPT,
341 [EPROTONOSUPPORT] = TARGET_EPROTONOSUPPORT,
342 [ESOCKTNOSUPPORT] = TARGET_ESOCKTNOSUPPORT,
343 [EOPNOTSUPP] = TARGET_EOPNOTSUPP,
344 [EPFNOSUPPORT] = TARGET_EPFNOSUPPORT,
345 [EAFNOSUPPORT] = TARGET_EAFNOSUPPORT,
346 [EADDRINUSE] = TARGET_EADDRINUSE,
347 [EADDRNOTAVAIL] = TARGET_EADDRNOTAVAIL,
348 [ENETDOWN] = TARGET_ENETDOWN,
349 [ENETUNREACH] = TARGET_ENETUNREACH,
350 [ENETRESET] = TARGET_ENETRESET,
351 [ECONNABORTED] = TARGET_ECONNABORTED,
352 [ECONNRESET] = TARGET_ECONNRESET,
353 [ENOBUFS] = TARGET_ENOBUFS,
354 [EISCONN] = TARGET_EISCONN,
355 [ENOTCONN] = TARGET_ENOTCONN,
356 [EUCLEAN] = TARGET_EUCLEAN,
357 [ENOTNAM] = TARGET_ENOTNAM,
358 [ENAVAIL] = TARGET_ENAVAIL,
359 [EISNAM] = TARGET_EISNAM,
360 [EREMOTEIO] = TARGET_EREMOTEIO,
361 [ESHUTDOWN] = TARGET_ESHUTDOWN,
362 [ETOOMANYREFS] = TARGET_ETOOMANYREFS,
363 [ETIMEDOUT] = TARGET_ETIMEDOUT,
364 [ECONNREFUSED] = TARGET_ECONNREFUSED,
365 [EHOSTDOWN] = TARGET_EHOSTDOWN,
366 [EHOSTUNREACH] = TARGET_EHOSTUNREACH,
367 [EALREADY] = TARGET_EALREADY,
368 [EINPROGRESS] = TARGET_EINPROGRESS,
369 [ESTALE] = TARGET_ESTALE,
370 [ECANCELED] = TARGET_ECANCELED,
371 [ENOMEDIUM] = TARGET_ENOMEDIUM,
372 [EMEDIUMTYPE] = TARGET_EMEDIUMTYPE,
b7fe5db7 373#ifdef ENOKEY
637947f1 374 [ENOKEY] = TARGET_ENOKEY,
b7fe5db7
TS
375#endif
376#ifdef EKEYEXPIRED
637947f1 377 [EKEYEXPIRED] = TARGET_EKEYEXPIRED,
b7fe5db7
TS
378#endif
379#ifdef EKEYREVOKED
637947f1 380 [EKEYREVOKED] = TARGET_EKEYREVOKED,
b7fe5db7
TS
381#endif
382#ifdef EKEYREJECTED
637947f1 383 [EKEYREJECTED] = TARGET_EKEYREJECTED,
b7fe5db7
TS
384#endif
385#ifdef EOWNERDEAD
637947f1 386 [EOWNERDEAD] = TARGET_EOWNERDEAD,
b7fe5db7
TS
387#endif
388#ifdef ENOTRECOVERABLE
637947f1 389 [ENOTRECOVERABLE] = TARGET_ENOTRECOVERABLE,
b7fe5db7 390#endif
b92c47c1 391};
637947f1
TS
392
393static inline int host_to_target_errno(int err)
394{
395 if(host_to_target_errno_table[err])
396 return host_to_target_errno_table[err];
397 return err;
398}
399
b92c47c1
TS
400static inline int target_to_host_errno(int err)
401{
402 if (target_to_host_errno_table[err])
403 return target_to_host_errno_table[err];
404 return err;
405}
406
992f48a0 407static inline abi_long get_errno(abi_long ret)
31e31b8a
FB
408{
409 if (ret == -1)
637947f1 410 return -host_to_target_errno(errno);
31e31b8a
FB
411 else
412 return ret;
413}
414
992f48a0 415static inline int is_error(abi_long ret)
31e31b8a 416{
992f48a0 417 return (abi_ulong)ret >= (abi_ulong)(-4096);
31e31b8a
FB
418}
419
b92c47c1
TS
420char *target_strerror(int err)
421{
422 return strerror(target_to_host_errno(err));
423}
424
992f48a0
BS
425static abi_ulong target_brk;
426static abi_ulong target_original_brk;
31e31b8a 427
992f48a0 428void target_set_brk(abi_ulong new_brk)
31e31b8a 429{
4c1de73d 430 target_original_brk = target_brk = HOST_PAGE_ALIGN(new_brk);
31e31b8a
FB
431}
432
0da46a6e 433/* do_brk() must return target values and target errnos. */
992f48a0 434abi_long do_brk(abi_ulong new_brk)
31e31b8a 435{
992f48a0
BS
436 abi_ulong brk_page;
437 abi_long mapped_addr;
31e31b8a
FB
438 int new_alloc_size;
439
440 if (!new_brk)
53a5960a 441 return target_brk;
31e31b8a 442 if (new_brk < target_original_brk)
7ab240ad 443 return target_brk;
3b46e624 444
53a5960a 445 brk_page = HOST_PAGE_ALIGN(target_brk);
31e31b8a
FB
446
447 /* If the new brk is less than this, set it and we're done... */
448 if (new_brk < brk_page) {
449 target_brk = new_brk;
53a5960a 450 return target_brk;
31e31b8a
FB
451 }
452
453 /* We need to allocate more memory after the brk... */
54936004 454 new_alloc_size = HOST_PAGE_ALIGN(new_brk - brk_page + 1);
5fafdf24 455 mapped_addr = get_errno(target_mmap(brk_page, new_alloc_size,
54936004
FB
456 PROT_READ|PROT_WRITE,
457 MAP_ANON|MAP_FIXED|MAP_PRIVATE, 0, 0));
7ab240ad
AZ
458
459 if (!is_error(mapped_addr))
31e31b8a 460 target_brk = new_brk;
7ab240ad
AZ
461
462 return target_brk;
31e31b8a
FB
463}
464
26edcf41
TS
465static inline abi_long copy_from_user_fdset(fd_set *fds,
466 abi_ulong target_fds_addr,
467 int n)
31e31b8a 468{
26edcf41
TS
469 int i, nw, j, k;
470 abi_ulong b, *target_fds;
471
472 nw = (n + TARGET_ABI_BITS - 1) / TARGET_ABI_BITS;
473 if (!(target_fds = lock_user(VERIFY_READ,
474 target_fds_addr,
475 sizeof(abi_ulong) * nw,
476 1)))
477 return -TARGET_EFAULT;
478
479 FD_ZERO(fds);
480 k = 0;
481 for (i = 0; i < nw; i++) {
482 /* grab the abi_ulong */
483 __get_user(b, &target_fds[i]);
484 for (j = 0; j < TARGET_ABI_BITS; j++) {
485 /* check the bit inside the abi_ulong */
486 if ((b >> j) & 1)
487 FD_SET(k, fds);
488 k++;
31e31b8a 489 }
31e31b8a 490 }
26edcf41
TS
491
492 unlock_user(target_fds, target_fds_addr, 0);
493
494 return 0;
31e31b8a
FB
495}
496
26edcf41
TS
497static inline abi_long copy_to_user_fdset(abi_ulong target_fds_addr,
498 const fd_set *fds,
499 int n)
31e31b8a 500{
31e31b8a 501 int i, nw, j, k;
992f48a0 502 abi_long v;
26edcf41 503 abi_ulong *target_fds;
31e31b8a 504
26edcf41
TS
505 nw = (n + TARGET_ABI_BITS - 1) / TARGET_ABI_BITS;
506 if (!(target_fds = lock_user(VERIFY_WRITE,
507 target_fds_addr,
508 sizeof(abi_ulong) * nw,
509 0)))
510 return -TARGET_EFAULT;
511
512 k = 0;
513 for (i = 0; i < nw; i++) {
514 v = 0;
515 for (j = 0; j < TARGET_ABI_BITS; j++) {
516 v |= ((FD_ISSET(k, fds) != 0) << j);
517 k++;
31e31b8a 518 }
26edcf41 519 __put_user(v, &target_fds[i]);
31e31b8a 520 }
26edcf41
TS
521
522 unlock_user(target_fds, target_fds_addr, sizeof(abi_ulong) * nw);
523
524 return 0;
31e31b8a
FB
525}
526
c596ed17
FB
527#if defined(__alpha__)
528#define HOST_HZ 1024
529#else
530#define HOST_HZ 100
531#endif
532
992f48a0 533static inline abi_long host_to_target_clock_t(long ticks)
c596ed17
FB
534{
535#if HOST_HZ == TARGET_HZ
536 return ticks;
537#else
538 return ((int64_t)ticks * TARGET_HZ) / HOST_HZ;
539#endif
540}
541
579a97f7
FB
542static inline abi_long host_to_target_rusage(abi_ulong target_addr,
543 const struct rusage *rusage)
b409186b 544{
53a5960a
PB
545 struct target_rusage *target_rusage;
546
579a97f7
FB
547 if (!lock_user_struct(VERIFY_WRITE, target_rusage, target_addr, 0))
548 return -TARGET_EFAULT;
b409186b
FB
549 target_rusage->ru_utime.tv_sec = tswapl(rusage->ru_utime.tv_sec);
550 target_rusage->ru_utime.tv_usec = tswapl(rusage->ru_utime.tv_usec);
551 target_rusage->ru_stime.tv_sec = tswapl(rusage->ru_stime.tv_sec);
552 target_rusage->ru_stime.tv_usec = tswapl(rusage->ru_stime.tv_usec);
553 target_rusage->ru_maxrss = tswapl(rusage->ru_maxrss);
554 target_rusage->ru_ixrss = tswapl(rusage->ru_ixrss);
555 target_rusage->ru_idrss = tswapl(rusage->ru_idrss);
556 target_rusage->ru_isrss = tswapl(rusage->ru_isrss);
557 target_rusage->ru_minflt = tswapl(rusage->ru_minflt);
558 target_rusage->ru_majflt = tswapl(rusage->ru_majflt);
559 target_rusage->ru_nswap = tswapl(rusage->ru_nswap);
560 target_rusage->ru_inblock = tswapl(rusage->ru_inblock);
561 target_rusage->ru_oublock = tswapl(rusage->ru_oublock);
562 target_rusage->ru_msgsnd = tswapl(rusage->ru_msgsnd);
563 target_rusage->ru_msgrcv = tswapl(rusage->ru_msgrcv);
564 target_rusage->ru_nsignals = tswapl(rusage->ru_nsignals);
565 target_rusage->ru_nvcsw = tswapl(rusage->ru_nvcsw);
566 target_rusage->ru_nivcsw = tswapl(rusage->ru_nivcsw);
53a5960a 567 unlock_user_struct(target_rusage, target_addr, 1);
579a97f7
FB
568
569 return 0;
b409186b
FB
570}
571
788f5ec4
TS
572static inline abi_long copy_from_user_timeval(struct timeval *tv,
573 abi_ulong target_tv_addr)
31e31b8a 574{
53a5960a
PB
575 struct target_timeval *target_tv;
576
788f5ec4 577 if (!lock_user_struct(VERIFY_READ, target_tv, target_tv_addr, 1))
579a97f7 578 return -TARGET_EFAULT;
788f5ec4
TS
579
580 __get_user(tv->tv_sec, &target_tv->tv_sec);
581 __get_user(tv->tv_usec, &target_tv->tv_usec);
582
583 unlock_user_struct(target_tv, target_tv_addr, 0);
579a97f7
FB
584
585 return 0;
31e31b8a
FB
586}
587
788f5ec4
TS
588static inline abi_long copy_to_user_timeval(abi_ulong target_tv_addr,
589 const struct timeval *tv)
31e31b8a 590{
53a5960a
PB
591 struct target_timeval *target_tv;
592
788f5ec4 593 if (!lock_user_struct(VERIFY_WRITE, target_tv, target_tv_addr, 0))
579a97f7 594 return -TARGET_EFAULT;
788f5ec4
TS
595
596 __put_user(tv->tv_sec, &target_tv->tv_sec);
597 __put_user(tv->tv_usec, &target_tv->tv_usec);
598
599 unlock_user_struct(target_tv, target_tv_addr, 1);
579a97f7
FB
600
601 return 0;
31e31b8a
FB
602}
603
604
0da46a6e 605/* do_select() must return target values and target errnos. */
992f48a0 606static abi_long do_select(int n,
26edcf41
TS
607 abi_ulong rfd_addr, abi_ulong wfd_addr,
608 abi_ulong efd_addr, abi_ulong target_tv_addr)
31e31b8a
FB
609{
610 fd_set rfds, wfds, efds;
611 fd_set *rfds_ptr, *wfds_ptr, *efds_ptr;
612 struct timeval tv, *tv_ptr;
992f48a0 613 abi_long ret;
31e31b8a 614
26edcf41
TS
615 if (rfd_addr) {
616 if (copy_from_user_fdset(&rfds, rfd_addr, n))
617 return -TARGET_EFAULT;
618 rfds_ptr = &rfds;
53a5960a 619 } else {
53a5960a
PB
620 rfds_ptr = NULL;
621 }
26edcf41
TS
622 if (wfd_addr) {
623 if (copy_from_user_fdset(&wfds, wfd_addr, n))
624 return -TARGET_EFAULT;
625 wfds_ptr = &wfds;
53a5960a 626 } else {
53a5960a
PB
627 wfds_ptr = NULL;
628 }
26edcf41
TS
629 if (efd_addr) {
630 if (copy_from_user_fdset(&efds, efd_addr, n))
631 return -TARGET_EFAULT;
632 efds_ptr = &efds;
53a5960a 633 } else {
53a5960a
PB
634 efds_ptr = NULL;
635 }
3b46e624 636
26edcf41 637 if (target_tv_addr) {
788f5ec4
TS
638 if (copy_from_user_timeval(&tv, target_tv_addr))
639 return -TARGET_EFAULT;
31e31b8a
FB
640 tv_ptr = &tv;
641 } else {
642 tv_ptr = NULL;
643 }
26edcf41 644
31e31b8a 645 ret = get_errno(select(n, rfds_ptr, wfds_ptr, efds_ptr, tv_ptr));
53a5960a 646
26edcf41
TS
647 if (!is_error(ret)) {
648 if (rfd_addr && copy_to_user_fdset(rfd_addr, &rfds, n))
649 return -TARGET_EFAULT;
650 if (wfd_addr && copy_to_user_fdset(wfd_addr, &wfds, n))
651 return -TARGET_EFAULT;
652 if (efd_addr && copy_to_user_fdset(efd_addr, &efds, n))
653 return -TARGET_EFAULT;
31e31b8a 654
788f5ec4
TS
655 if (target_tv_addr && copy_to_user_timeval(target_tv_addr, &tv))
656 return -TARGET_EFAULT;
31e31b8a 657 }
579a97f7 658
31e31b8a
FB
659 return ret;
660}
661
579a97f7
FB
662static inline abi_long target_to_host_sockaddr(struct sockaddr *addr,
663 abi_ulong target_addr,
664 socklen_t len)
7854b056 665{
53a5960a
PB
666 struct target_sockaddr *target_saddr;
667
579a97f7
FB
668 target_saddr = lock_user(VERIFY_READ, target_addr, len, 1);
669 if (!target_saddr)
670 return -TARGET_EFAULT;
53a5960a
PB
671 memcpy(addr, target_saddr, len);
672 addr->sa_family = tswap16(target_saddr->sa_family);
673 unlock_user(target_saddr, target_addr, 0);
579a97f7
FB
674
675 return 0;
7854b056
FB
676}
677
579a97f7
FB
678static inline abi_long host_to_target_sockaddr(abi_ulong target_addr,
679 struct sockaddr *addr,
680 socklen_t len)
7854b056 681{
53a5960a
PB
682 struct target_sockaddr *target_saddr;
683
579a97f7
FB
684 target_saddr = lock_user(VERIFY_WRITE, target_addr, len, 0);
685 if (!target_saddr)
686 return -TARGET_EFAULT;
53a5960a
PB
687 memcpy(target_saddr, addr, len);
688 target_saddr->sa_family = tswap16(addr->sa_family);
689 unlock_user(target_saddr, target_addr, len);
579a97f7
FB
690
691 return 0;
7854b056
FB
692}
693
53a5960a 694/* ??? Should this also swap msgh->name? */
5a4a898d
FB
695static inline abi_long target_to_host_cmsg(struct msghdr *msgh,
696 struct target_msghdr *target_msgh)
7854b056
FB
697{
698 struct cmsghdr *cmsg = CMSG_FIRSTHDR(msgh);
5a4a898d
FB
699 abi_long msg_controllen;
700 abi_ulong target_cmsg_addr;
701 struct target_cmsghdr *target_cmsg;
7854b056 702 socklen_t space = 0;
5a4a898d
FB
703
704 msg_controllen = tswapl(target_msgh->msg_controllen);
705 if (msg_controllen < sizeof (struct target_cmsghdr))
706 goto the_end;
707 target_cmsg_addr = tswapl(target_msgh->msg_control);
708 target_cmsg = lock_user(VERIFY_READ, target_cmsg_addr, msg_controllen, 1);
709 if (!target_cmsg)
710 return -TARGET_EFAULT;
7854b056
FB
711
712 while (cmsg && target_cmsg) {
713 void *data = CMSG_DATA(cmsg);
714 void *target_data = TARGET_CMSG_DATA(target_cmsg);
715
5fafdf24 716 int len = tswapl(target_cmsg->cmsg_len)
7854b056
FB
717 - TARGET_CMSG_ALIGN(sizeof (struct target_cmsghdr));
718
719 space += CMSG_SPACE(len);
720 if (space > msgh->msg_controllen) {
721 space -= CMSG_SPACE(len);
31febb71 722 gemu_log("Host cmsg overflow\n");
7854b056
FB
723 break;
724 }
725
726 cmsg->cmsg_level = tswap32(target_cmsg->cmsg_level);
727 cmsg->cmsg_type = tswap32(target_cmsg->cmsg_type);
728 cmsg->cmsg_len = CMSG_LEN(len);
729
3532fa74 730 if (cmsg->cmsg_level != TARGET_SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS) {
7854b056
FB
731 gemu_log("Unsupported ancillary data: %d/%d\n", cmsg->cmsg_level, cmsg->cmsg_type);
732 memcpy(data, target_data, len);
733 } else {
734 int *fd = (int *)data;
735 int *target_fd = (int *)target_data;
736 int i, numfds = len / sizeof(int);
737
738 for (i = 0; i < numfds; i++)
739 fd[i] = tswap32(target_fd[i]);
740 }
741
742 cmsg = CMSG_NXTHDR(msgh, cmsg);
743 target_cmsg = TARGET_CMSG_NXTHDR(target_msgh, target_cmsg);
744 }
5a4a898d
FB
745 unlock_user(target_cmsg, target_cmsg_addr, 0);
746 the_end:
7854b056 747 msgh->msg_controllen = space;
5a4a898d 748 return 0;
7854b056
FB
749}
750
53a5960a 751/* ??? Should this also swap msgh->name? */
5a4a898d
FB
752static inline abi_long host_to_target_cmsg(struct target_msghdr *target_msgh,
753 struct msghdr *msgh)
7854b056
FB
754{
755 struct cmsghdr *cmsg = CMSG_FIRSTHDR(msgh);
5a4a898d
FB
756 abi_long msg_controllen;
757 abi_ulong target_cmsg_addr;
758 struct target_cmsghdr *target_cmsg;
7854b056
FB
759 socklen_t space = 0;
760
5a4a898d
FB
761 msg_controllen = tswapl(target_msgh->msg_controllen);
762 if (msg_controllen < sizeof (struct target_cmsghdr))
763 goto the_end;
764 target_cmsg_addr = tswapl(target_msgh->msg_control);
765 target_cmsg = lock_user(VERIFY_WRITE, target_cmsg_addr, msg_controllen, 0);
766 if (!target_cmsg)
767 return -TARGET_EFAULT;
768
7854b056
FB
769 while (cmsg && target_cmsg) {
770 void *data = CMSG_DATA(cmsg);
771 void *target_data = TARGET_CMSG_DATA(target_cmsg);
772
773 int len = cmsg->cmsg_len - CMSG_ALIGN(sizeof (struct cmsghdr));
774
775 space += TARGET_CMSG_SPACE(len);
5a4a898d 776 if (space > msg_controllen) {
7854b056 777 space -= TARGET_CMSG_SPACE(len);
31febb71 778 gemu_log("Target cmsg overflow\n");
7854b056
FB
779 break;
780 }
781
782 target_cmsg->cmsg_level = tswap32(cmsg->cmsg_level);
783 target_cmsg->cmsg_type = tswap32(cmsg->cmsg_type);
784 target_cmsg->cmsg_len = tswapl(TARGET_CMSG_LEN(len));
785
3532fa74 786 if (cmsg->cmsg_level != TARGET_SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS) {
7854b056
FB
787 gemu_log("Unsupported ancillary data: %d/%d\n", cmsg->cmsg_level, cmsg->cmsg_type);
788 memcpy(target_data, data, len);
789 } else {
790 int *fd = (int *)data;
791 int *target_fd = (int *)target_data;
792 int i, numfds = len / sizeof(int);
793
794 for (i = 0; i < numfds; i++)
795 target_fd[i] = tswap32(fd[i]);
796 }
797
798 cmsg = CMSG_NXTHDR(msgh, cmsg);
799 target_cmsg = TARGET_CMSG_NXTHDR(target_msgh, target_cmsg);
800 }
5a4a898d
FB
801 unlock_user(target_cmsg, target_cmsg_addr, space);
802 the_end:
803 target_msgh->msg_controllen = tswapl(space);
804 return 0;
7854b056
FB
805}
806
0da46a6e 807/* do_setsockopt() Must return target values and target errnos. */
992f48a0 808static abi_long do_setsockopt(int sockfd, int level, int optname,
2f619698 809 abi_ulong optval_addr, socklen_t optlen)
7854b056 810{
992f48a0 811 abi_long ret;
32407103 812 int val;
3b46e624 813
8853f86e
FB
814 switch(level) {
815 case SOL_TCP:
7854b056 816 /* TCP options all take an 'int' value. */
7854b056 817 if (optlen < sizeof(uint32_t))
0da46a6e 818 return -TARGET_EINVAL;
3b46e624 819
2f619698
FB
820 if (get_user_u32(val, optval_addr))
821 return -TARGET_EFAULT;
8853f86e
FB
822 ret = get_errno(setsockopt(sockfd, level, optname, &val, sizeof(val)));
823 break;
824 case SOL_IP:
825 switch(optname) {
2efbe911
FB
826 case IP_TOS:
827 case IP_TTL:
8853f86e 828 case IP_HDRINCL:
2efbe911
FB
829 case IP_ROUTER_ALERT:
830 case IP_RECVOPTS:
831 case IP_RETOPTS:
832 case IP_PKTINFO:
833 case IP_MTU_DISCOVER:
834 case IP_RECVERR:
835 case IP_RECVTOS:
836#ifdef IP_FREEBIND
837 case IP_FREEBIND:
838#endif
839 case IP_MULTICAST_TTL:
840 case IP_MULTICAST_LOOP:
8853f86e
FB
841 val = 0;
842 if (optlen >= sizeof(uint32_t)) {
2f619698
FB
843 if (get_user_u32(val, optval_addr))
844 return -TARGET_EFAULT;
8853f86e 845 } else if (optlen >= 1) {
2f619698
FB
846 if (get_user_u8(val, optval_addr))
847 return -TARGET_EFAULT;
8853f86e
FB
848 }
849 ret = get_errno(setsockopt(sockfd, level, optname, &val, sizeof(val)));
850 break;
851 default:
852 goto unimplemented;
853 }
854 break;
3532fa74 855 case TARGET_SOL_SOCKET:
8853f86e
FB
856 switch (optname) {
857 /* Options with 'int' argument. */
3532fa74
FB
858 case TARGET_SO_DEBUG:
859 optname = SO_DEBUG;
860 break;
861 case TARGET_SO_REUSEADDR:
862 optname = SO_REUSEADDR;
863 break;
864 case TARGET_SO_TYPE:
865 optname = SO_TYPE;
866 break;
867 case TARGET_SO_ERROR:
868 optname = SO_ERROR;
869 break;
870 case TARGET_SO_DONTROUTE:
871 optname = SO_DONTROUTE;
872 break;
873 case TARGET_SO_BROADCAST:
874 optname = SO_BROADCAST;
875 break;
876 case TARGET_SO_SNDBUF:
877 optname = SO_SNDBUF;
878 break;
879 case TARGET_SO_RCVBUF:
880 optname = SO_RCVBUF;
881 break;
882 case TARGET_SO_KEEPALIVE:
883 optname = SO_KEEPALIVE;
884 break;
885 case TARGET_SO_OOBINLINE:
886 optname = SO_OOBINLINE;
887 break;
888 case TARGET_SO_NO_CHECK:
889 optname = SO_NO_CHECK;
890 break;
891 case TARGET_SO_PRIORITY:
892 optname = SO_PRIORITY;
893 break;
5e83e8e3 894#ifdef SO_BSDCOMPAT
3532fa74
FB
895 case TARGET_SO_BSDCOMPAT:
896 optname = SO_BSDCOMPAT;
897 break;
5e83e8e3 898#endif
3532fa74
FB
899 case TARGET_SO_PASSCRED:
900 optname = SO_PASSCRED;
901 break;
902 case TARGET_SO_TIMESTAMP:
903 optname = SO_TIMESTAMP;
904 break;
905 case TARGET_SO_RCVLOWAT:
906 optname = SO_RCVLOWAT;
907 break;
908 case TARGET_SO_RCVTIMEO:
909 optname = SO_RCVTIMEO;
910 break;
911 case TARGET_SO_SNDTIMEO:
912 optname = SO_SNDTIMEO;
913 break;
8853f86e
FB
914 break;
915 default:
916 goto unimplemented;
917 }
3532fa74 918 if (optlen < sizeof(uint32_t))
2f619698 919 return -TARGET_EINVAL;
3532fa74 920
2f619698
FB
921 if (get_user_u32(val, optval_addr))
922 return -TARGET_EFAULT;
3532fa74 923 ret = get_errno(setsockopt(sockfd, SOL_SOCKET, optname, &val, sizeof(val)));
8853f86e 924 break;
7854b056 925 default:
8853f86e
FB
926 unimplemented:
927 gemu_log("Unsupported setsockopt level=%d optname=%d \n", level, optname);
6fa13c17 928 ret = -TARGET_ENOPROTOOPT;
7854b056 929 }
8853f86e 930 return ret;
7854b056
FB
931}
932
0da46a6e 933/* do_getsockopt() Must return target values and target errnos. */
992f48a0 934static abi_long do_getsockopt(int sockfd, int level, int optname,
2f619698 935 abi_ulong optval_addr, abi_ulong optlen)
7854b056 936{
992f48a0 937 abi_long ret;
32407103 938 int len, lv, val;
8853f86e
FB
939
940 switch(level) {
3532fa74
FB
941 case TARGET_SOL_SOCKET:
942 level = SOL_SOCKET;
8853f86e 943 switch (optname) {
3532fa74
FB
944 case TARGET_SO_LINGER:
945 case TARGET_SO_RCVTIMEO:
946 case TARGET_SO_SNDTIMEO:
947 case TARGET_SO_PEERCRED:
948 case TARGET_SO_PEERNAME:
8853f86e
FB
949 /* These don't just return a single integer */
950 goto unimplemented;
951 default:
2efbe911
FB
952 goto int_case;
953 }
954 break;
955 case SOL_TCP:
956 /* TCP options all take an 'int' value. */
957 int_case:
2f619698
FB
958 if (get_user_u32(len, optlen))
959 return -TARGET_EFAULT;
2efbe911 960 if (len < 0)
0da46a6e 961 return -TARGET_EINVAL;
2efbe911
FB
962 lv = sizeof(int);
963 ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
964 if (ret < 0)
965 return ret;
966 val = tswap32(val);
967 if (len > lv)
968 len = lv;
2f619698
FB
969 if (len == 4) {
970 if (put_user_u32(val, optval_addr))
971 return -TARGET_EFAULT;
972 } else {
973 if (put_user_u8(val, optval_addr))
974 return -TARGET_EFAULT;
975 }
976 if (put_user_u32(len, optlen))
977 return -TARGET_EFAULT;
2efbe911
FB
978 break;
979 case SOL_IP:
980 switch(optname) {
981 case IP_TOS:
982 case IP_TTL:
983 case IP_HDRINCL:
984 case IP_ROUTER_ALERT:
985 case IP_RECVOPTS:
986 case IP_RETOPTS:
987 case IP_PKTINFO:
988 case IP_MTU_DISCOVER:
989 case IP_RECVERR:
990 case IP_RECVTOS:
991#ifdef IP_FREEBIND
992 case IP_FREEBIND:
993#endif
994 case IP_MULTICAST_TTL:
995 case IP_MULTICAST_LOOP:
2f619698
FB
996 if (get_user_u32(len, optlen))
997 return -TARGET_EFAULT;
8853f86e 998 if (len < 0)
0da46a6e 999 return -TARGET_EINVAL;
8853f86e
FB
1000 lv = sizeof(int);
1001 ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
1002 if (ret < 0)
1003 return ret;
2efbe911 1004 if (len < sizeof(int) && len > 0 && val >= 0 && val < 255) {
2efbe911 1005 len = 1;
2f619698
FB
1006 if (put_user_u32(len, optlen)
1007 || put_user_u8(val, optval_addr))
1008 return -TARGET_EFAULT;
2efbe911 1009 } else {
2efbe911
FB
1010 if (len > sizeof(int))
1011 len = sizeof(int);
2f619698
FB
1012 if (put_user_u32(len, optlen)
1013 || put_user_u32(val, optval_addr))
1014 return -TARGET_EFAULT;
2efbe911 1015 }
8853f86e 1016 break;
2efbe911 1017 default:
c02f499e
TS
1018 ret = -TARGET_ENOPROTOOPT;
1019 break;
8853f86e
FB
1020 }
1021 break;
1022 default:
1023 unimplemented:
1024 gemu_log("getsockopt level=%d optname=%d not yet supported\n",
1025 level, optname);
c02f499e 1026 ret = -TARGET_EOPNOTSUPP;
8853f86e
FB
1027 break;
1028 }
1029 return ret;
7854b056
FB
1030}
1031
579a97f7
FB
1032/* FIXME
1033 * lock_iovec()/unlock_iovec() have a return code of 0 for success where
1034 * other lock functions have a return code of 0 for failure.
1035 */
1036static abi_long lock_iovec(int type, struct iovec *vec, abi_ulong target_addr,
1037 int count, int copy)
53a5960a
PB
1038{
1039 struct target_iovec *target_vec;
992f48a0 1040 abi_ulong base;
579a97f7 1041 int i, j;
53a5960a 1042
579a97f7
FB
1043 target_vec = lock_user(VERIFY_READ, target_addr, count * sizeof(struct target_iovec), 1);
1044 if (!target_vec)
1045 return -TARGET_EFAULT;
53a5960a
PB
1046 for(i = 0;i < count; i++) {
1047 base = tswapl(target_vec[i].iov_base);
1048 vec[i].iov_len = tswapl(target_vec[i].iov_len);
41df8411
FB
1049 if (vec[i].iov_len != 0) {
1050 vec[i].iov_base = lock_user(type, base, vec[i].iov_len, copy);
7bedce8d 1051 if (!vec[i].iov_base && vec[i].iov_len)
41df8411
FB
1052 goto fail;
1053 } else {
1054 /* zero length pointer is ignored */
1055 vec[i].iov_base = NULL;
1056 }
579a97f7
FB
1057 }
1058 unlock_user (target_vec, target_addr, 0);
1059 return 0;
1060 fail:
1061 /* failure - unwind locks */
1062 for (j = 0; j < i; j++) {
1063 base = tswapl(target_vec[j].iov_base);
1064 unlock_user(vec[j].iov_base, base, 0);
53a5960a
PB
1065 }
1066 unlock_user (target_vec, target_addr, 0);
579a97f7 1067 return -TARGET_EFAULT;
53a5960a
PB
1068}
1069
579a97f7
FB
1070static abi_long unlock_iovec(struct iovec *vec, abi_ulong target_addr,
1071 int count, int copy)
53a5960a
PB
1072{
1073 struct target_iovec *target_vec;
992f48a0 1074 abi_ulong base;
53a5960a
PB
1075 int i;
1076
579a97f7
FB
1077 target_vec = lock_user(VERIFY_READ, target_addr, count * sizeof(struct target_iovec), 1);
1078 if (!target_vec)
1079 return -TARGET_EFAULT;
53a5960a
PB
1080 for(i = 0;i < count; i++) {
1081 base = tswapl(target_vec[i].iov_base);
1082 unlock_user(vec[i].iov_base, base, copy ? vec[i].iov_len : 0);
1083 }
1084 unlock_user (target_vec, target_addr, 0);
579a97f7
FB
1085
1086 return 0;
53a5960a
PB
1087}
1088
0da46a6e 1089/* do_socket() Must return target values and target errnos. */
992f48a0 1090static abi_long do_socket(int domain, int type, int protocol)
3532fa74
FB
1091{
1092#if defined(TARGET_MIPS)
1093 switch(type) {
1094 case TARGET_SOCK_DGRAM:
1095 type = SOCK_DGRAM;
1096 break;
1097 case TARGET_SOCK_STREAM:
1098 type = SOCK_STREAM;
1099 break;
1100 case TARGET_SOCK_RAW:
1101 type = SOCK_RAW;
1102 break;
1103 case TARGET_SOCK_RDM:
1104 type = SOCK_RDM;
1105 break;
1106 case TARGET_SOCK_SEQPACKET:
1107 type = SOCK_SEQPACKET;
1108 break;
1109 case TARGET_SOCK_PACKET:
1110 type = SOCK_PACKET;
1111 break;
1112 }
1113#endif
12bc92ab
AZ
1114 if (domain == PF_NETLINK)
1115 return -EAFNOSUPPORT; /* do not NETLINK socket connections possible */
3532fa74
FB
1116 return get_errno(socket(domain, type, protocol));
1117}
1118
0da46a6e 1119/* do_bind() Must return target values and target errnos. */
992f48a0
BS
1120static abi_long do_bind(int sockfd, abi_ulong target_addr,
1121 socklen_t addrlen)
3532fa74
FB
1122{
1123 void *addr = alloca(addrlen);
3b46e624 1124
3532fa74
FB
1125 target_to_host_sockaddr(addr, target_addr, addrlen);
1126 return get_errno(bind(sockfd, addr, addrlen));
1127}
1128
0da46a6e 1129/* do_connect() Must return target values and target errnos. */
992f48a0
BS
1130static abi_long do_connect(int sockfd, abi_ulong target_addr,
1131 socklen_t addrlen)
3532fa74
FB
1132{
1133 void *addr = alloca(addrlen);
3b46e624 1134
3532fa74
FB
1135 target_to_host_sockaddr(addr, target_addr, addrlen);
1136 return get_errno(connect(sockfd, addr, addrlen));
1137}
1138
0da46a6e 1139/* do_sendrecvmsg() Must return target values and target errnos. */
992f48a0
BS
1140static abi_long do_sendrecvmsg(int fd, abi_ulong target_msg,
1141 int flags, int send)
3532fa74 1142{
992f48a0 1143 abi_long ret;
3532fa74
FB
1144 struct target_msghdr *msgp;
1145 struct msghdr msg;
1146 int count;
1147 struct iovec *vec;
992f48a0 1148 abi_ulong target_vec;
3532fa74 1149
579a97f7
FB
1150 /* FIXME */
1151 if (!lock_user_struct(send ? VERIFY_READ : VERIFY_WRITE,
1152 msgp,
1153 target_msg,
1154 send ? 1 : 0))
1155 return -TARGET_EFAULT;
3532fa74
FB
1156 if (msgp->msg_name) {
1157 msg.msg_namelen = tswap32(msgp->msg_namelen);
1158 msg.msg_name = alloca(msg.msg_namelen);
1159 target_to_host_sockaddr(msg.msg_name, tswapl(msgp->msg_name),
1160 msg.msg_namelen);
1161 } else {
1162 msg.msg_name = NULL;
1163 msg.msg_namelen = 0;
1164 }
1165 msg.msg_controllen = 2 * tswapl(msgp->msg_controllen);
1166 msg.msg_control = alloca(msg.msg_controllen);
1167 msg.msg_flags = tswap32(msgp->msg_flags);
3b46e624 1168
3532fa74
FB
1169 count = tswapl(msgp->msg_iovlen);
1170 vec = alloca(count * sizeof(struct iovec));
1171 target_vec = tswapl(msgp->msg_iov);
579a97f7 1172 lock_iovec(send ? VERIFY_READ : VERIFY_WRITE, vec, target_vec, count, send);
3532fa74
FB
1173 msg.msg_iovlen = count;
1174 msg.msg_iov = vec;
3b46e624 1175
3532fa74 1176 if (send) {
5a4a898d
FB
1177 ret = target_to_host_cmsg(&msg, msgp);
1178 if (ret == 0)
1179 ret = get_errno(sendmsg(fd, &msg, flags));
3532fa74
FB
1180 } else {
1181 ret = get_errno(recvmsg(fd, &msg, flags));
1182 if (!is_error(ret))
5a4a898d 1183 ret = host_to_target_cmsg(msgp, &msg);
3532fa74
FB
1184 }
1185 unlock_iovec(vec, target_vec, count, !send);
579a97f7 1186 unlock_user_struct(msgp, target_msg, send ? 0 : 1);
3532fa74
FB
1187 return ret;
1188}
1189
0da46a6e 1190/* do_accept() Must return target values and target errnos. */
992f48a0 1191static abi_long do_accept(int fd, abi_ulong target_addr,
2f619698 1192 abi_ulong target_addrlen_addr)
1be9e1dc 1193{
2f619698
FB
1194 socklen_t addrlen;
1195 void *addr;
992f48a0 1196 abi_long ret;
1be9e1dc 1197
2f619698
FB
1198 if (get_user_u32(addrlen, target_addrlen_addr))
1199 return -TARGET_EFAULT;
1200
1201 addr = alloca(addrlen);
1202
1be9e1dc
PB
1203 ret = get_errno(accept(fd, addr, &addrlen));
1204 if (!is_error(ret)) {
1205 host_to_target_sockaddr(target_addr, addr, addrlen);
2f619698
FB
1206 if (put_user_u32(addrlen, target_addrlen_addr))
1207 ret = -TARGET_EFAULT;
1be9e1dc
PB
1208 }
1209 return ret;
1210}
1211
0da46a6e 1212/* do_getpeername() Must return target values and target errnos. */
992f48a0 1213static abi_long do_getpeername(int fd, abi_ulong target_addr,
2f619698 1214 abi_ulong target_addrlen_addr)
1be9e1dc 1215{
2f619698
FB
1216 socklen_t addrlen;
1217 void *addr;
992f48a0 1218 abi_long ret;
1be9e1dc 1219
2f619698
FB
1220 if (get_user_u32(addrlen, target_addrlen_addr))
1221 return -TARGET_EFAULT;
1222
1223 addr = alloca(addrlen);
1224
1be9e1dc
PB
1225 ret = get_errno(getpeername(fd, addr, &addrlen));
1226 if (!is_error(ret)) {
1227 host_to_target_sockaddr(target_addr, addr, addrlen);
2f619698
FB
1228 if (put_user_u32(addrlen, target_addrlen_addr))
1229 ret = -TARGET_EFAULT;
1be9e1dc
PB
1230 }
1231 return ret;
1232}
1233
0da46a6e 1234/* do_getsockname() Must return target values and target errnos. */
992f48a0 1235static abi_long do_getsockname(int fd, abi_ulong target_addr,
2f619698 1236 abi_ulong target_addrlen_addr)
1be9e1dc 1237{
2f619698
FB
1238 socklen_t addrlen;
1239 void *addr;
992f48a0 1240 abi_long ret;
1be9e1dc 1241
2f619698
FB
1242 if (get_user_u32(addrlen, target_addrlen_addr))
1243 return -TARGET_EFAULT;
1244
1245 addr = alloca(addrlen);
1246
1be9e1dc
PB
1247 ret = get_errno(getsockname(fd, addr, &addrlen));
1248 if (!is_error(ret)) {
1249 host_to_target_sockaddr(target_addr, addr, addrlen);
2f619698
FB
1250 if (put_user_u32(addrlen, target_addrlen_addr))
1251 ret = -TARGET_EFAULT;
1be9e1dc
PB
1252 }
1253 return ret;
1254}
1255
0da46a6e 1256/* do_socketpair() Must return target values and target errnos. */
992f48a0 1257static abi_long do_socketpair(int domain, int type, int protocol,
2f619698 1258 abi_ulong target_tab_addr)
1be9e1dc
PB
1259{
1260 int tab[2];
992f48a0 1261 abi_long ret;
1be9e1dc
PB
1262
1263 ret = get_errno(socketpair(domain, type, protocol, tab));
1264 if (!is_error(ret)) {
2f619698
FB
1265 if (put_user_s32(tab[0], target_tab_addr)
1266 || put_user_s32(tab[1], target_tab_addr + sizeof(tab[0])))
1267 ret = -TARGET_EFAULT;
1be9e1dc
PB
1268 }
1269 return ret;
1270}
1271
0da46a6e 1272/* do_sendto() Must return target values and target errnos. */
992f48a0
BS
1273static abi_long do_sendto(int fd, abi_ulong msg, size_t len, int flags,
1274 abi_ulong target_addr, socklen_t addrlen)
1be9e1dc
PB
1275{
1276 void *addr;
1277 void *host_msg;
992f48a0 1278 abi_long ret;
1be9e1dc 1279
579a97f7
FB
1280 host_msg = lock_user(VERIFY_READ, msg, len, 1);
1281 if (!host_msg)
1282 return -TARGET_EFAULT;
1be9e1dc
PB
1283 if (target_addr) {
1284 addr = alloca(addrlen);
1285 target_to_host_sockaddr(addr, target_addr, addrlen);
1286 ret = get_errno(sendto(fd, host_msg, len, flags, addr, addrlen));
1287 } else {
1288 ret = get_errno(send(fd, host_msg, len, flags));
1289 }
1290 unlock_user(host_msg, msg, 0);
1291 return ret;
1292}
1293
0da46a6e 1294/* do_recvfrom() Must return target values and target errnos. */
992f48a0
BS
1295static abi_long do_recvfrom(int fd, abi_ulong msg, size_t len, int flags,
1296 abi_ulong target_addr,
1297 abi_ulong target_addrlen)
1be9e1dc
PB
1298{
1299 socklen_t addrlen;
1300 void *addr;
1301 void *host_msg;
992f48a0 1302 abi_long ret;
1be9e1dc 1303
579a97f7
FB
1304 host_msg = lock_user(VERIFY_WRITE, msg, len, 0);
1305 if (!host_msg)
1306 return -TARGET_EFAULT;
1be9e1dc 1307 if (target_addr) {
2f619698
FB
1308 if (get_user_u32(addrlen, target_addrlen)) {
1309 ret = -TARGET_EFAULT;
1310 goto fail;
1311 }
1be9e1dc
PB
1312 addr = alloca(addrlen);
1313 ret = get_errno(recvfrom(fd, host_msg, len, flags, addr, &addrlen));
1314 } else {
1315 addr = NULL; /* To keep compiler quiet. */
1316 ret = get_errno(recv(fd, host_msg, len, flags));
1317 }
1318 if (!is_error(ret)) {
1319 if (target_addr) {
1320 host_to_target_sockaddr(target_addr, addr, addrlen);
2f619698
FB
1321 if (put_user_u32(addrlen, target_addrlen)) {
1322 ret = -TARGET_EFAULT;
1323 goto fail;
1324 }
1be9e1dc
PB
1325 }
1326 unlock_user(host_msg, msg, len);
1327 } else {
2f619698 1328fail:
1be9e1dc
PB
1329 unlock_user(host_msg, msg, 0);
1330 }
1331 return ret;
1332}
1333
32407103 1334#ifdef TARGET_NR_socketcall
0da46a6e 1335/* do_socketcall() Must return target values and target errnos. */
992f48a0 1336static abi_long do_socketcall(int num, abi_ulong vptr)
31e31b8a 1337{
992f48a0
BS
1338 abi_long ret;
1339 const int n = sizeof(abi_ulong);
31e31b8a
FB
1340
1341 switch(num) {
1342 case SOCKOP_socket:
7854b056 1343 {
2f619698
FB
1344 int domain, type, protocol;
1345
1346 if (get_user_s32(domain, vptr)
1347 || get_user_s32(type, vptr + n)
1348 || get_user_s32(protocol, vptr + 2 * n))
1349 return -TARGET_EFAULT;
1350
3532fa74 1351 ret = do_socket(domain, type, protocol);
7854b056 1352 }
31e31b8a
FB
1353 break;
1354 case SOCKOP_bind:
7854b056 1355 {
2f619698
FB
1356 int sockfd;
1357 abi_ulong target_addr;
1358 socklen_t addrlen;
1359
1360 if (get_user_s32(sockfd, vptr)
1361 || get_user_ual(target_addr, vptr + n)
1362 || get_user_u32(addrlen, vptr + 2 * n))
1363 return -TARGET_EFAULT;
1364
3532fa74 1365 ret = do_bind(sockfd, target_addr, addrlen);
7854b056 1366 }
31e31b8a
FB
1367 break;
1368 case SOCKOP_connect:
7854b056 1369 {
2f619698
FB
1370 int sockfd;
1371 abi_ulong target_addr;
1372 socklen_t addrlen;
1373
1374 if (get_user_s32(sockfd, vptr)
1375 || get_user_ual(target_addr, vptr + n)
1376 || get_user_u32(addrlen, vptr + 2 * n))
1377 return -TARGET_EFAULT;
1378
3532fa74 1379 ret = do_connect(sockfd, target_addr, addrlen);
7854b056 1380 }
31e31b8a
FB
1381 break;
1382 case SOCKOP_listen:
7854b056 1383 {
2f619698
FB
1384 int sockfd, backlog;
1385
1386 if (get_user_s32(sockfd, vptr)
1387 || get_user_s32(backlog, vptr + n))
1388 return -TARGET_EFAULT;
1389
7854b056
FB
1390 ret = get_errno(listen(sockfd, backlog));
1391 }
31e31b8a
FB
1392 break;
1393 case SOCKOP_accept:
1394 {
2f619698
FB
1395 int sockfd;
1396 abi_ulong target_addr, target_addrlen;
1397
1398 if (get_user_s32(sockfd, vptr)
1399 || get_user_ual(target_addr, vptr + n)
1400 || get_user_u32(target_addrlen, vptr + 2 * n))
1401 return -TARGET_EFAULT;
1402
1be9e1dc 1403 ret = do_accept(sockfd, target_addr, target_addrlen);
31e31b8a
FB
1404 }
1405 break;
1406 case SOCKOP_getsockname:
1407 {
2f619698
FB
1408 int sockfd;
1409 abi_ulong target_addr, target_addrlen;
1410
1411 if (get_user_s32(sockfd, vptr)
1412 || get_user_ual(target_addr, vptr + n)
1413 || get_user_u32(target_addrlen, vptr + 2 * n))
1414 return -TARGET_EFAULT;
1415
1be9e1dc 1416 ret = do_getsockname(sockfd, target_addr, target_addrlen);
31e31b8a
FB
1417 }
1418 break;
1419 case SOCKOP_getpeername:
1420 {
2f619698
FB
1421 int sockfd;
1422 abi_ulong target_addr, target_addrlen;
1423
1424 if (get_user_s32(sockfd, vptr)
1425 || get_user_ual(target_addr, vptr + n)
1426 || get_user_u32(target_addrlen, vptr + 2 * n))
1427 return -TARGET_EFAULT;
1428
1be9e1dc 1429 ret = do_getpeername(sockfd, target_addr, target_addrlen);
31e31b8a
FB
1430 }
1431 break;
1432 case SOCKOP_socketpair:
1433 {
2f619698
FB
1434 int domain, type, protocol;
1435 abi_ulong tab;
1436
1437 if (get_user_s32(domain, vptr)
1438 || get_user_s32(type, vptr + n)
1439 || get_user_s32(protocol, vptr + 2 * n)
1440 || get_user_ual(tab, vptr + 3 * n))
1441 return -TARGET_EFAULT;
1442
1be9e1dc 1443 ret = do_socketpair(domain, type, protocol, tab);
31e31b8a
FB
1444 }
1445 break;
1446 case SOCKOP_send:
7854b056 1447 {
2f619698
FB
1448 int sockfd;
1449 abi_ulong msg;
1450 size_t len;
1451 int flags;
1452
1453 if (get_user_s32(sockfd, vptr)
1454 || get_user_ual(msg, vptr + n)
1455 || get_user_ual(len, vptr + 2 * n)
1456 || get_user_s32(flags, vptr + 3 * n))
1457 return -TARGET_EFAULT;
1458
1be9e1dc 1459 ret = do_sendto(sockfd, msg, len, flags, 0, 0);
7854b056 1460 }
31e31b8a
FB
1461 break;
1462 case SOCKOP_recv:
7854b056 1463 {
2f619698
FB
1464 int sockfd;
1465 abi_ulong msg;
1466 size_t len;
1467 int flags;
1468
1469 if (get_user_s32(sockfd, vptr)
1470 || get_user_ual(msg, vptr + n)
1471 || get_user_ual(len, vptr + 2 * n)
1472 || get_user_s32(flags, vptr + 3 * n))
1473 return -TARGET_EFAULT;
1474
1be9e1dc 1475 ret = do_recvfrom(sockfd, msg, len, flags, 0, 0);
7854b056 1476 }
31e31b8a
FB
1477 break;
1478 case SOCKOP_sendto:
7854b056 1479 {
2f619698
FB
1480 int sockfd;
1481 abi_ulong msg;
1482 size_t len;
1483 int flags;
1484 abi_ulong addr;
1485 socklen_t addrlen;
1486
1487 if (get_user_s32(sockfd, vptr)
1488 || get_user_ual(msg, vptr + n)
1489 || get_user_ual(len, vptr + 2 * n)
1490 || get_user_s32(flags, vptr + 3 * n)
1491 || get_user_ual(addr, vptr + 4 * n)
1492 || get_user_u32(addrlen, vptr + 5 * n))
1493 return -TARGET_EFAULT;
1494
1be9e1dc 1495 ret = do_sendto(sockfd, msg, len, flags, addr, addrlen);
7854b056 1496 }
31e31b8a
FB
1497 break;
1498 case SOCKOP_recvfrom:
1499 {
2f619698
FB
1500 int sockfd;
1501 abi_ulong msg;
1502 size_t len;
1503 int flags;
1504 abi_ulong addr;
1505 socklen_t addrlen;
1506
1507 if (get_user_s32(sockfd, vptr)
1508 || get_user_ual(msg, vptr + n)
1509 || get_user_ual(len, vptr + 2 * n)
1510 || get_user_s32(flags, vptr + 3 * n)
1511 || get_user_ual(addr, vptr + 4 * n)
1512 || get_user_u32(addrlen, vptr + 5 * n))
1513 return -TARGET_EFAULT;
1514
1be9e1dc 1515 ret = do_recvfrom(sockfd, msg, len, flags, addr, addrlen);
31e31b8a
FB
1516 }
1517 break;
1518 case SOCKOP_shutdown:
7854b056 1519 {
2f619698
FB
1520 int sockfd, how;
1521
1522 if (get_user_s32(sockfd, vptr)
1523 || get_user_s32(how, vptr + n))
1524 return -TARGET_EFAULT;
7854b056
FB
1525
1526 ret = get_errno(shutdown(sockfd, how));
1527 }
31e31b8a
FB
1528 break;
1529 case SOCKOP_sendmsg:
1530 case SOCKOP_recvmsg:
1a9353d2
FB
1531 {
1532 int fd;
992f48a0 1533 abi_ulong target_msg;
3532fa74 1534 int flags;
1a9353d2 1535
2f619698
FB
1536 if (get_user_s32(fd, vptr)
1537 || get_user_ual(target_msg, vptr + n)
1538 || get_user_s32(flags, vptr + 2 * n))
1539 return -TARGET_EFAULT;
3532fa74 1540
5fafdf24 1541 ret = do_sendrecvmsg(fd, target_msg, flags,
3532fa74 1542 (num == SOCKOP_sendmsg));
1a9353d2
FB
1543 }
1544 break;
31e31b8a 1545 case SOCKOP_setsockopt:
7854b056 1546 {
2f619698
FB
1547 int sockfd;
1548 int level;
1549 int optname;
1550 abi_ulong optval;
1551 socklen_t optlen;
1552
1553 if (get_user_s32(sockfd, vptr)
1554 || get_user_s32(level, vptr + n)
1555 || get_user_s32(optname, vptr + 2 * n)
1556 || get_user_ual(optval, vptr + 3 * n)
1557 || get_user_u32(optlen, vptr + 4 * n))
1558 return -TARGET_EFAULT;
7854b056
FB
1559
1560 ret = do_setsockopt(sockfd, level, optname, optval, optlen);
1561 }
1562 break;
31e31b8a 1563 case SOCKOP_getsockopt:
7854b056 1564 {
2f619698
FB
1565 int sockfd;
1566 int level;
1567 int optname;
1568 abi_ulong optval;
1569 socklen_t optlen;
1570
1571 if (get_user_s32(sockfd, vptr)
1572 || get_user_s32(level, vptr + n)
1573 || get_user_s32(optname, vptr + 2 * n)
1574 || get_user_ual(optval, vptr + 3 * n)
1575 || get_user_u32(optlen, vptr + 4 * n))
1576 return -TARGET_EFAULT;
7854b056 1577
2f619698 1578 ret = do_getsockopt(sockfd, level, optname, optval, optlen);
7854b056
FB
1579 }
1580 break;
31e31b8a
FB
1581 default:
1582 gemu_log("Unsupported socketcall: %d\n", num);
0da46a6e 1583 ret = -TARGET_ENOSYS;
31e31b8a
FB
1584 break;
1585 }
1586 return ret;
1587}
32407103 1588#endif
31e31b8a 1589
32407103 1590#ifdef TARGET_NR_ipc
8853f86e
FB
1591#define N_SHM_REGIONS 32
1592
1593static struct shm_region {
5a4a898d
FB
1594 abi_ulong start;
1595 abi_ulong size;
8853f86e
FB
1596} shm_regions[N_SHM_REGIONS];
1597
3eb6b044
TS
1598struct target_ipc_perm
1599{
992f48a0
BS
1600 abi_long __key;
1601 abi_ulong uid;
1602 abi_ulong gid;
1603 abi_ulong cuid;
1604 abi_ulong cgid;
3eb6b044
TS
1605 unsigned short int mode;
1606 unsigned short int __pad1;
1607 unsigned short int __seq;
1608 unsigned short int __pad2;
992f48a0
BS
1609 abi_ulong __unused1;
1610 abi_ulong __unused2;
3eb6b044
TS
1611};
1612
1613struct target_semid_ds
1614{
1615 struct target_ipc_perm sem_perm;
992f48a0
BS
1616 abi_ulong sem_otime;
1617 abi_ulong __unused1;
1618 abi_ulong sem_ctime;
1619 abi_ulong __unused2;
1620 abi_ulong sem_nsems;
1621 abi_ulong __unused3;
1622 abi_ulong __unused4;
3eb6b044
TS
1623};
1624
579a97f7
FB
1625static inline abi_long target_to_host_ipc_perm(struct ipc_perm *host_ip,
1626 abi_ulong target_addr)
3eb6b044
TS
1627{
1628 struct target_ipc_perm *target_ip;
1629 struct target_semid_ds *target_sd;
1630
579a97f7
FB
1631 if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
1632 return -TARGET_EFAULT;
3eb6b044
TS
1633 target_ip=&(target_sd->sem_perm);
1634 host_ip->__key = tswapl(target_ip->__key);
1635 host_ip->uid = tswapl(target_ip->uid);
1636 host_ip->gid = tswapl(target_ip->gid);
1637 host_ip->cuid = tswapl(target_ip->cuid);
1638 host_ip->cgid = tswapl(target_ip->cgid);
1639 host_ip->mode = tswapl(target_ip->mode);
1640 unlock_user_struct(target_sd, target_addr, 0);
579a97f7 1641 return 0;
3eb6b044
TS
1642}
1643
579a97f7
FB
1644static inline abi_long host_to_target_ipc_perm(abi_ulong target_addr,
1645 struct ipc_perm *host_ip)
3eb6b044
TS
1646{
1647 struct target_ipc_perm *target_ip;
1648 struct target_semid_ds *target_sd;
1649
579a97f7
FB
1650 if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
1651 return -TARGET_EFAULT;
3eb6b044
TS
1652 target_ip = &(target_sd->sem_perm);
1653 target_ip->__key = tswapl(host_ip->__key);
1654 target_ip->uid = tswapl(host_ip->uid);
1655 target_ip->gid = tswapl(host_ip->gid);
1656 target_ip->cuid = tswapl(host_ip->cuid);
1657 target_ip->cgid = tswapl(host_ip->cgid);
1658 target_ip->mode = tswapl(host_ip->mode);
1659 unlock_user_struct(target_sd, target_addr, 1);
579a97f7 1660 return 0;
3eb6b044
TS
1661}
1662
579a97f7
FB
1663static inline abi_long target_to_host_semid_ds(struct semid_ds *host_sd,
1664 abi_ulong target_addr)
3eb6b044
TS
1665{
1666 struct target_semid_ds *target_sd;
1667
579a97f7
FB
1668 if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
1669 return -TARGET_EFAULT;
3eb6b044
TS
1670 target_to_host_ipc_perm(&(host_sd->sem_perm),target_addr);
1671 host_sd->sem_nsems = tswapl(target_sd->sem_nsems);
1672 host_sd->sem_otime = tswapl(target_sd->sem_otime);
1673 host_sd->sem_ctime = tswapl(target_sd->sem_ctime);
1674 unlock_user_struct(target_sd, target_addr, 0);
579a97f7 1675 return 0;
3eb6b044
TS
1676}
1677
579a97f7
FB
1678static inline abi_long host_to_target_semid_ds(abi_ulong target_addr,
1679 struct semid_ds *host_sd)
3eb6b044
TS
1680{
1681 struct target_semid_ds *target_sd;
1682
579a97f7
FB
1683 if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
1684 return -TARGET_EFAULT;
3eb6b044
TS
1685 host_to_target_ipc_perm(target_addr,&(host_sd->sem_perm));
1686 target_sd->sem_nsems = tswapl(host_sd->sem_nsems);
1687 target_sd->sem_otime = tswapl(host_sd->sem_otime);
1688 target_sd->sem_ctime = tswapl(host_sd->sem_ctime);
1689 unlock_user_struct(target_sd, target_addr, 1);
579a97f7 1690 return 0;
3eb6b044
TS
1691}
1692
fa294816
TS
1693union semun {
1694 int val;
3eb6b044 1695 struct semid_ds *buf;
fa294816
TS
1696 unsigned short *array;
1697};
1698
3eb6b044
TS
1699union target_semun {
1700 int val;
992f48a0 1701 abi_long buf;
3eb6b044
TS
1702 unsigned short int *array;
1703};
1704
579a97f7
FB
1705static inline abi_long target_to_host_semun(int cmd,
1706 union semun *host_su,
1707 abi_ulong target_addr,
1708 struct semid_ds *ds)
3eb6b044
TS
1709{
1710 union target_semun *target_su;
1711
1712 switch( cmd ) {
1713 case IPC_STAT:
1714 case IPC_SET:
579a97f7
FB
1715 if (!lock_user_struct(VERIFY_READ, target_su, target_addr, 1))
1716 return -TARGET_EFAULT;
3eb6b044
TS
1717 target_to_host_semid_ds(ds,target_su->buf);
1718 host_su->buf = ds;
1719 unlock_user_struct(target_su, target_addr, 0);
1720 break;
1721 case GETVAL:
1722 case SETVAL:
579a97f7
FB
1723 if (!lock_user_struct(VERIFY_READ, target_su, target_addr, 1))
1724 return -TARGET_EFAULT;
3eb6b044
TS
1725 host_su->val = tswapl(target_su->val);
1726 unlock_user_struct(target_su, target_addr, 0);
1727 break;
1728 case GETALL:
1729 case SETALL:
579a97f7
FB
1730 if (!lock_user_struct(VERIFY_READ, target_su, target_addr, 1))
1731 return -TARGET_EFAULT;
3eb6b044
TS
1732 *host_su->array = tswap16(*target_su->array);
1733 unlock_user_struct(target_su, target_addr, 0);
1734 break;
1735 default:
1736 gemu_log("semun operation not fully supported: %d\n", (int)cmd);
1737 }
579a97f7 1738 return 0;
3eb6b044
TS
1739}
1740
579a97f7
FB
1741static inline abi_long host_to_target_semun(int cmd,
1742 abi_ulong target_addr,
1743 union semun *host_su,
1744 struct semid_ds *ds)
3eb6b044
TS
1745{
1746 union target_semun *target_su;
1747
1748 switch( cmd ) {
1749 case IPC_STAT:
1750 case IPC_SET:
579a97f7
FB
1751 if (lock_user_struct(VERIFY_WRITE, target_su, target_addr, 0))
1752 return -TARGET_EFAULT;
3eb6b044
TS
1753 host_to_target_semid_ds(target_su->buf,ds);
1754 unlock_user_struct(target_su, target_addr, 1);
1755 break;
1756 case GETVAL:
1757 case SETVAL:
579a97f7
FB
1758 if (lock_user_struct(VERIFY_WRITE, target_su, target_addr, 0))
1759 return -TARGET_EFAULT;
3eb6b044
TS
1760 target_su->val = tswapl(host_su->val);
1761 unlock_user_struct(target_su, target_addr, 1);
1762 break;
1763 case GETALL:
1764 case SETALL:
579a97f7
FB
1765 if (lock_user_struct(VERIFY_WRITE, target_su, target_addr, 0))
1766 return -TARGET_EFAULT;
3eb6b044
TS
1767 *target_su->array = tswap16(*host_su->array);
1768 unlock_user_struct(target_su, target_addr, 1);
1769 break;
1770 default:
1771 gemu_log("semun operation not fully supported: %d\n", (int)cmd);
1772 }
579a97f7 1773 return 0;
3eb6b044
TS
1774}
1775
992f48a0
BS
1776static inline abi_long do_semctl(int first, int second, int third,
1777 abi_long ptr)
3eb6b044
TS
1778{
1779 union semun arg;
1780 struct semid_ds dsarg;
1781 int cmd = third&0xff;
992f48a0 1782 abi_long ret = 0;
3eb6b044
TS
1783
1784 switch( cmd ) {
1785 case GETVAL:
1786 target_to_host_semun(cmd,&arg,ptr,&dsarg);
1787 ret = get_errno(semctl(first, second, cmd, arg));
1788 host_to_target_semun(cmd,ptr,&arg,&dsarg);
1789 break;
1790 case SETVAL:
1791 target_to_host_semun(cmd,&arg,ptr,&dsarg);
1792 ret = get_errno(semctl(first, second, cmd, arg));
1793 host_to_target_semun(cmd,ptr,&arg,&dsarg);
1794 break;
1795 case GETALL:
1796 target_to_host_semun(cmd,&arg,ptr,&dsarg);
1797 ret = get_errno(semctl(first, second, cmd, arg));
1798 host_to_target_semun(cmd,ptr,&arg,&dsarg);
1799 break;
1800 case SETALL:
1801 target_to_host_semun(cmd,&arg,ptr,&dsarg);
1802 ret = get_errno(semctl(first, second, cmd, arg));
1803 host_to_target_semun(cmd,ptr,&arg,&dsarg);
1804 break;
1805 case IPC_STAT:
1806 target_to_host_semun(cmd,&arg,ptr,&dsarg);
1807 ret = get_errno(semctl(first, second, cmd, arg));
1808 host_to_target_semun(cmd,ptr,&arg,&dsarg);
1809 break;
1810 case IPC_SET:
1811 target_to_host_semun(cmd,&arg,ptr,&dsarg);
1812 ret = get_errno(semctl(first, second, cmd, arg));
1813 host_to_target_semun(cmd,ptr,&arg,&dsarg);
1814 break;
1815 default:
1816 ret = get_errno(semctl(first, second, cmd, arg));
1817 }
1818
1819 return ret;
1820}
1821
1bc012f6
TS
1822struct target_msqid_ds
1823{
1824 struct target_ipc_perm msg_perm;
992f48a0
BS
1825 abi_ulong msg_stime;
1826 abi_ulong __unused1;
1827 abi_ulong msg_rtime;
1828 abi_ulong __unused2;
1829 abi_ulong msg_ctime;
1830 abi_ulong __unused3;
1831 abi_ulong __msg_cbytes;
1832 abi_ulong msg_qnum;
1833 abi_ulong msg_qbytes;
1834 abi_ulong msg_lspid;
1835 abi_ulong msg_lrpid;
1836 abi_ulong __unused4;
1837 abi_ulong __unused5;
1bc012f6
TS
1838};
1839
579a97f7
FB
1840static inline abi_long target_to_host_msqid_ds(struct msqid_ds *host_md,
1841 abi_ulong target_addr)
1bc012f6
TS
1842{
1843 struct target_msqid_ds *target_md;
1844
579a97f7
FB
1845 if (!lock_user_struct(VERIFY_READ, target_md, target_addr, 1))
1846 return -TARGET_EFAULT;
1bc012f6
TS
1847 target_to_host_ipc_perm(&(host_md->msg_perm),target_addr);
1848 host_md->msg_stime = tswapl(target_md->msg_stime);
1849 host_md->msg_rtime = tswapl(target_md->msg_rtime);
1850 host_md->msg_ctime = tswapl(target_md->msg_ctime);
1851 host_md->__msg_cbytes = tswapl(target_md->__msg_cbytes);
1852 host_md->msg_qnum = tswapl(target_md->msg_qnum);
1853 host_md->msg_qbytes = tswapl(target_md->msg_qbytes);
1854 host_md->msg_lspid = tswapl(target_md->msg_lspid);
1855 host_md->msg_lrpid = tswapl(target_md->msg_lrpid);
1856 unlock_user_struct(target_md, target_addr, 0);
579a97f7 1857 return 0;
1bc012f6
TS
1858}
1859
579a97f7
FB
1860static inline abi_long host_to_target_msqid_ds(abi_ulong target_addr,
1861 struct msqid_ds *host_md)
1bc012f6
TS
1862{
1863 struct target_msqid_ds *target_md;
1864
579a97f7
FB
1865 if (!lock_user_struct(VERIFY_WRITE, target_md, target_addr, 0))
1866 return -TARGET_EFAULT;
1bc012f6
TS
1867 host_to_target_ipc_perm(target_addr,&(host_md->msg_perm));
1868 target_md->msg_stime = tswapl(host_md->msg_stime);
1869 target_md->msg_rtime = tswapl(host_md->msg_rtime);
1870 target_md->msg_ctime = tswapl(host_md->msg_ctime);
1871 target_md->__msg_cbytes = tswapl(host_md->__msg_cbytes);
1872 target_md->msg_qnum = tswapl(host_md->msg_qnum);
1873 target_md->msg_qbytes = tswapl(host_md->msg_qbytes);
1874 target_md->msg_lspid = tswapl(host_md->msg_lspid);
1875 target_md->msg_lrpid = tswapl(host_md->msg_lrpid);
1876 unlock_user_struct(target_md, target_addr, 1);
579a97f7 1877 return 0;
1bc012f6
TS
1878}
1879
992f48a0 1880static inline abi_long do_msgctl(int first, int second, abi_long ptr)
1bc012f6
TS
1881{
1882 struct msqid_ds dsarg;
1883 int cmd = second&0xff;
992f48a0 1884 abi_long ret = 0;
1bc012f6
TS
1885 switch( cmd ) {
1886 case IPC_STAT:
1887 case IPC_SET:
1888 target_to_host_msqid_ds(&dsarg,ptr);
1889 ret = get_errno(msgctl(first, cmd, &dsarg));
1890 host_to_target_msqid_ds(ptr,&dsarg);
1891 default:
1892 ret = get_errno(msgctl(first, cmd, &dsarg));
1893 }
1894 return ret;
1895}
1896
1897struct target_msgbuf {
992f48a0 1898 abi_ulong mtype;
1bc012f6
TS
1899 char mtext[1];
1900};
1901
992f48a0
BS
1902static inline abi_long do_msgsnd(int msqid, abi_long msgp,
1903 unsigned int msgsz, int msgflg)
1bc012f6
TS
1904{
1905 struct target_msgbuf *target_mb;
1906 struct msgbuf *host_mb;
992f48a0 1907 abi_long ret = 0;
1bc012f6 1908
579a97f7
FB
1909 if (!lock_user_struct(VERIFY_READ, target_mb, msgp, 0))
1910 return -TARGET_EFAULT;
1bc012f6
TS
1911 host_mb = malloc(msgsz+sizeof(long));
1912 host_mb->mtype = tswapl(target_mb->mtype);
1913 memcpy(host_mb->mtext,target_mb->mtext,msgsz);
1914 ret = get_errno(msgsnd(msqid, host_mb, msgsz, msgflg));
1915 free(host_mb);
1916 unlock_user_struct(target_mb, msgp, 0);
1917
1918 return ret;
1919}
1920
992f48a0
BS
1921static inline abi_long do_msgrcv(int msqid, abi_long msgp,
1922 unsigned int msgsz, int msgtype,
1923 int msgflg)
1bc012f6
TS
1924{
1925 struct target_msgbuf *target_mb;
579a97f7 1926 char *target_mtext;
1bc012f6 1927 struct msgbuf *host_mb;
992f48a0 1928 abi_long ret = 0;
1bc012f6 1929
579a97f7
FB
1930 if (!lock_user_struct(VERIFY_WRITE, target_mb, msgp, 0))
1931 return -TARGET_EFAULT;
1bc012f6
TS
1932 host_mb = malloc(msgsz+sizeof(long));
1933 ret = get_errno(msgrcv(msqid, host_mb, msgsz, 1, msgflg));
579a97f7
FB
1934 if (ret > 0) {
1935 abi_ulong target_mtext_addr = msgp + sizeof(abi_ulong);
1936 target_mtext = lock_user(VERIFY_WRITE, target_mtext_addr, ret, 0);
1937 if (!target_mtext) {
1938 ret = -TARGET_EFAULT;
1939 goto end;
1940 }
1bc012f6 1941 memcpy(target_mb->mtext, host_mb->mtext, ret);
579a97f7
FB
1942 unlock_user(target_mtext, target_mtext_addr, ret);
1943 }
1bc012f6
TS
1944 target_mb->mtype = tswapl(host_mb->mtype);
1945 free(host_mb);
1bc012f6 1946
579a97f7
FB
1947end:
1948 if (target_mb)
1949 unlock_user_struct(target_mb, msgp, 1);
1bc012f6
TS
1950 return ret;
1951}
1952
53a5960a 1953/* ??? This only works with linear mappings. */
0da46a6e 1954/* do_ipc() must return target values and target errnos. */
992f48a0
BS
1955static abi_long do_ipc(unsigned int call, int first,
1956 int second, int third,
1957 abi_long ptr, abi_long fifth)
8853f86e
FB
1958{
1959 int version;
992f48a0 1960 abi_long ret = 0;
8853f86e
FB
1961 struct shmid_ds shm_info;
1962 int i;
1963
1964 version = call >> 16;
1965 call &= 0xffff;
1966
1967 switch (call) {
fa294816 1968 case IPCOP_semop:
579a97f7 1969 ret = get_errno(semop(first,(struct sembuf *)g2h(ptr), second));
fa294816
TS
1970 break;
1971
1972 case IPCOP_semget:
1973 ret = get_errno(semget(first, second, third));
1974 break;
1975
1976 case IPCOP_semctl:
3eb6b044 1977 ret = do_semctl(first, second, third, ptr);
fa294816
TS
1978 break;
1979
1980 case IPCOP_semtimedop:
32407103 1981 gemu_log("Unsupported ipc call: %d (version %d)\n", call, version);
0da46a6e 1982 ret = -TARGET_ENOSYS;
fa294816 1983 break;
d96372ef
TS
1984
1985 case IPCOP_msgget:
1986 ret = get_errno(msgget(first, second));
1987 break;
1988
1989 case IPCOP_msgsnd:
1bc012f6 1990 ret = do_msgsnd(first, ptr, second, third);
d96372ef
TS
1991 break;
1992
1993 case IPCOP_msgctl:
1bc012f6 1994 ret = do_msgctl(first, second, ptr);
d96372ef
TS
1995 break;
1996
1997 case IPCOP_msgrcv:
1bc012f6 1998 {
579a97f7 1999 /* XXX: this code is not correct */
1bc012f6
TS
2000 struct ipc_kludge
2001 {
2002 void *__unbounded msgp;
2003 long int msgtyp;
2004 };
d96372ef 2005
579a97f7 2006 struct ipc_kludge *foo = (struct ipc_kludge *)g2h(ptr);
1bc012f6 2007 struct msgbuf *msgp = (struct msgbuf *) foo->msgp;
d96372ef 2008
1bc012f6 2009 ret = do_msgrcv(first, (long)msgp, second, 0, third);
d96372ef 2010
1bc012f6 2011 }
d96372ef
TS
2012 break;
2013
8853f86e 2014 case IPCOP_shmat:
5a4a898d
FB
2015 {
2016 abi_ulong raddr;
2017 void *host_addr;
2018 /* SHM_* flags are the same on all linux platforms */
2019 host_addr = shmat(first, (void *)g2h(ptr), second);
2020 if (host_addr == (void *)-1) {
2021 ret = get_errno((long)host_addr);
8853f86e 2022 break;
5a4a898d
FB
2023 }
2024 raddr = h2g((unsigned long)host_addr);
2025 /* find out the length of the shared memory segment */
2026
2027 ret = get_errno(shmctl(first, IPC_STAT, &shm_info));
2028 if (is_error(ret)) {
2029 /* can't get length, bail out */
2030 shmdt(host_addr);
2031 break;
2032 }
2033 page_set_flags(raddr, raddr + shm_info.shm_segsz,
2034 PAGE_VALID | PAGE_READ |
2035 ((second & SHM_RDONLY)? 0: PAGE_WRITE));
2036 for (i = 0; i < N_SHM_REGIONS; ++i) {
2037 if (shm_regions[i].start == 0) {
2038 shm_regions[i].start = raddr;
2039 shm_regions[i].size = shm_info.shm_segsz;
2040 break;
2041 }
2042 }
2f619698 2043 if (put_user_ual(raddr, third))
5a4a898d
FB
2044 return -TARGET_EFAULT;
2045 ret = 0;
2046 }
8853f86e
FB
2047 break;
2048 case IPCOP_shmdt:
2049 for (i = 0; i < N_SHM_REGIONS; ++i) {
2050 if (shm_regions[i].start == ptr) {
2051 shm_regions[i].start = 0;
2052 page_set_flags(ptr, shm_regions[i].size, 0);
2053 break;
2054 }
2055 }
5a4a898d 2056 ret = get_errno(shmdt((void *)g2h(ptr)));
8853f86e
FB
2057 break;
2058
2059 case IPCOP_shmget:
2060 /* IPC_* flag values are the same on all linux platforms */
2061 ret = get_errno(shmget(first, second, third));
2062 break;
2063
2064 /* IPC_* and SHM_* command values are the same on all linux platforms */
2065 case IPCOP_shmctl:
2066 switch(second) {
2067 case IPC_RMID:
2068 case SHM_LOCK:
2069 case SHM_UNLOCK:
2070 ret = get_errno(shmctl(first, second, NULL));
2071 break;
2072 default:
2073 goto unimplemented;
2074 }
2075 break;
2076 default:
2077 unimplemented:
32407103 2078 gemu_log("Unsupported ipc call: %d (version %d)\n", call, version);
0da46a6e 2079 ret = -TARGET_ENOSYS;
8853f86e
FB
2080 break;
2081 }
2082 return ret;
2083}
32407103 2084#endif
8853f86e 2085
31e31b8a
FB
2086/* kernel structure types definitions */
2087#define IFNAMSIZ 16
2088
2089#define STRUCT(name, list...) STRUCT_ ## name,
2090#define STRUCT_SPECIAL(name) STRUCT_ ## name,
2091enum {
2092#include "syscall_types.h"
2093};
2094#undef STRUCT
2095#undef STRUCT_SPECIAL
2096
2097#define STRUCT(name, list...) const argtype struct_ ## name ## _def[] = { list, TYPE_NULL };
2098#define STRUCT_SPECIAL(name)
2099#include "syscall_types.h"
2100#undef STRUCT
2101#undef STRUCT_SPECIAL
2102
2103typedef struct IOCTLEntry {
2ab83ea7
FB
2104 unsigned int target_cmd;
2105 unsigned int host_cmd;
31e31b8a
FB
2106 const char *name;
2107 int access;
1a9353d2 2108 const argtype arg_type[5];
31e31b8a
FB
2109} IOCTLEntry;
2110
2111#define IOC_R 0x0001
2112#define IOC_W 0x0002
2113#define IOC_RW (IOC_R | IOC_W)
2114
2115#define MAX_STRUCT_SIZE 4096
2116
2ab83ea7 2117IOCTLEntry ioctl_entries[] = {
31e31b8a
FB
2118#define IOCTL(cmd, access, types...) \
2119 { TARGET_ ## cmd, cmd, #cmd, access, { types } },
2120#include "ioctls.h"
2121 { 0, 0, },
2122};
2123
53a5960a 2124/* ??? Implement proper locking for ioctls. */
0da46a6e 2125/* do_ioctl() Must return target values and target errnos. */
992f48a0 2126static abi_long do_ioctl(int fd, abi_long cmd, abi_long arg)
31e31b8a
FB
2127{
2128 const IOCTLEntry *ie;
2129 const argtype *arg_type;
992f48a0 2130 abi_long ret;
31e31b8a 2131 uint8_t buf_temp[MAX_STRUCT_SIZE];
53a5960a
PB
2132 int target_size;
2133 void *argptr;
31e31b8a
FB
2134
2135 ie = ioctl_entries;
2136 for(;;) {
2137 if (ie->target_cmd == 0) {
32407103 2138 gemu_log("Unsupported ioctl: cmd=0x%04lx\n", (long)cmd);
0da46a6e 2139 return -TARGET_ENOSYS;
31e31b8a
FB
2140 }
2141 if (ie->target_cmd == cmd)
2142 break;
2143 ie++;
2144 }
2145 arg_type = ie->arg_type;
9de5e440 2146#if defined(DEBUG)
32407103 2147 gemu_log("ioctl: cmd=0x%04lx (%s)\n", (long)cmd, ie->name);
72f03900 2148#endif
31e31b8a
FB
2149 switch(arg_type[0]) {
2150 case TYPE_NULL:
2151 /* no argument */
2152 ret = get_errno(ioctl(fd, ie->host_cmd));
2153 break;
2154 case TYPE_PTRVOID:
2155 case TYPE_INT:
2156 /* int argment */
2157 ret = get_errno(ioctl(fd, ie->host_cmd, arg));
2158 break;
2159 case TYPE_PTR:
2160 arg_type++;
53a5960a 2161 target_size = thunk_type_size(arg_type, 0);
31e31b8a
FB
2162 switch(ie->access) {
2163 case IOC_R:
2164 ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
2165 if (!is_error(ret)) {
579a97f7
FB
2166 argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
2167 if (!argptr)
2168 return -TARGET_EFAULT;
53a5960a
PB
2169 thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
2170 unlock_user(argptr, arg, target_size);
31e31b8a
FB
2171 }
2172 break;
2173 case IOC_W:
579a97f7
FB
2174 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
2175 if (!argptr)
2176 return -TARGET_EFAULT;
53a5960a
PB
2177 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
2178 unlock_user(argptr, arg, 0);
31e31b8a
FB
2179 ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
2180 break;
2181 default:
2182 case IOC_RW:
579a97f7
FB
2183 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
2184 if (!argptr)
2185 return -TARGET_EFAULT;
53a5960a
PB
2186 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
2187 unlock_user(argptr, arg, 0);
31e31b8a
FB
2188 ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
2189 if (!is_error(ret)) {
579a97f7
FB
2190 argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
2191 if (!argptr)
2192 return -TARGET_EFAULT;
53a5960a
PB
2193 thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
2194 unlock_user(argptr, arg, target_size);
31e31b8a
FB
2195 }
2196 break;
2197 }
2198 break;
2199 default:
32407103
JM
2200 gemu_log("Unsupported ioctl type: cmd=0x%04lx type=%d\n",
2201 (long)cmd, arg_type[0]);
0da46a6e 2202 ret = -TARGET_ENOSYS;
31e31b8a
FB
2203 break;
2204 }
2205 return ret;
2206}
2207
2208bitmask_transtbl iflag_tbl[] = {
2209 { TARGET_IGNBRK, TARGET_IGNBRK, IGNBRK, IGNBRK },
2210 { TARGET_BRKINT, TARGET_BRKINT, BRKINT, BRKINT },
2211 { TARGET_IGNPAR, TARGET_IGNPAR, IGNPAR, IGNPAR },
2212 { TARGET_PARMRK, TARGET_PARMRK, PARMRK, PARMRK },
2213 { TARGET_INPCK, TARGET_INPCK, INPCK, INPCK },
2214 { TARGET_ISTRIP, TARGET_ISTRIP, ISTRIP, ISTRIP },
2215 { TARGET_INLCR, TARGET_INLCR, INLCR, INLCR },
2216 { TARGET_IGNCR, TARGET_IGNCR, IGNCR, IGNCR },
2217 { TARGET_ICRNL, TARGET_ICRNL, ICRNL, ICRNL },
2218 { TARGET_IUCLC, TARGET_IUCLC, IUCLC, IUCLC },
2219 { TARGET_IXON, TARGET_IXON, IXON, IXON },
2220 { TARGET_IXANY, TARGET_IXANY, IXANY, IXANY },
2221 { TARGET_IXOFF, TARGET_IXOFF, IXOFF, IXOFF },
2222 { TARGET_IMAXBEL, TARGET_IMAXBEL, IMAXBEL, IMAXBEL },
2223 { 0, 0, 0, 0 }
2224};
2225
2226bitmask_transtbl oflag_tbl[] = {
2227 { TARGET_OPOST, TARGET_OPOST, OPOST, OPOST },
2228 { TARGET_OLCUC, TARGET_OLCUC, OLCUC, OLCUC },
2229 { TARGET_ONLCR, TARGET_ONLCR, ONLCR, ONLCR },
2230 { TARGET_OCRNL, TARGET_OCRNL, OCRNL, OCRNL },
2231 { TARGET_ONOCR, TARGET_ONOCR, ONOCR, ONOCR },
2232 { TARGET_ONLRET, TARGET_ONLRET, ONLRET, ONLRET },
2233 { TARGET_OFILL, TARGET_OFILL, OFILL, OFILL },
2234 { TARGET_OFDEL, TARGET_OFDEL, OFDEL, OFDEL },
2235 { TARGET_NLDLY, TARGET_NL0, NLDLY, NL0 },
2236 { TARGET_NLDLY, TARGET_NL1, NLDLY, NL1 },
2237 { TARGET_CRDLY, TARGET_CR0, CRDLY, CR0 },
2238 { TARGET_CRDLY, TARGET_CR1, CRDLY, CR1 },
2239 { TARGET_CRDLY, TARGET_CR2, CRDLY, CR2 },
2240 { TARGET_CRDLY, TARGET_CR3, CRDLY, CR3 },
2241 { TARGET_TABDLY, TARGET_TAB0, TABDLY, TAB0 },
2242 { TARGET_TABDLY, TARGET_TAB1, TABDLY, TAB1 },
2243 { TARGET_TABDLY, TARGET_TAB2, TABDLY, TAB2 },
2244 { TARGET_TABDLY, TARGET_TAB3, TABDLY, TAB3 },
2245 { TARGET_BSDLY, TARGET_BS0, BSDLY, BS0 },
2246 { TARGET_BSDLY, TARGET_BS1, BSDLY, BS1 },
2247 { TARGET_VTDLY, TARGET_VT0, VTDLY, VT0 },
2248 { TARGET_VTDLY, TARGET_VT1, VTDLY, VT1 },
2249 { TARGET_FFDLY, TARGET_FF0, FFDLY, FF0 },
2250 { TARGET_FFDLY, TARGET_FF1, FFDLY, FF1 },
2251 { 0, 0, 0, 0 }
2252};
2253
2254bitmask_transtbl cflag_tbl[] = {
2255 { TARGET_CBAUD, TARGET_B0, CBAUD, B0 },
2256 { TARGET_CBAUD, TARGET_B50, CBAUD, B50 },
2257 { TARGET_CBAUD, TARGET_B75, CBAUD, B75 },
2258 { TARGET_CBAUD, TARGET_B110, CBAUD, B110 },
2259 { TARGET_CBAUD, TARGET_B134, CBAUD, B134 },
2260 { TARGET_CBAUD, TARGET_B150, CBAUD, B150 },
2261 { TARGET_CBAUD, TARGET_B200, CBAUD, B200 },
2262 { TARGET_CBAUD, TARGET_B300, CBAUD, B300 },
2263 { TARGET_CBAUD, TARGET_B600, CBAUD, B600 },
2264 { TARGET_CBAUD, TARGET_B1200, CBAUD, B1200 },
2265 { TARGET_CBAUD, TARGET_B1800, CBAUD, B1800 },
2266 { TARGET_CBAUD, TARGET_B2400, CBAUD, B2400 },
2267 { TARGET_CBAUD, TARGET_B4800, CBAUD, B4800 },
2268 { TARGET_CBAUD, TARGET_B9600, CBAUD, B9600 },
2269 { TARGET_CBAUD, TARGET_B19200, CBAUD, B19200 },
2270 { TARGET_CBAUD, TARGET_B38400, CBAUD, B38400 },
2271 { TARGET_CBAUD, TARGET_B57600, CBAUD, B57600 },
2272 { TARGET_CBAUD, TARGET_B115200, CBAUD, B115200 },
2273 { TARGET_CBAUD, TARGET_B230400, CBAUD, B230400 },
2274 { TARGET_CBAUD, TARGET_B460800, CBAUD, B460800 },
2275 { TARGET_CSIZE, TARGET_CS5, CSIZE, CS5 },
2276 { TARGET_CSIZE, TARGET_CS6, CSIZE, CS6 },
2277 { TARGET_CSIZE, TARGET_CS7, CSIZE, CS7 },
2278 { TARGET_CSIZE, TARGET_CS8, CSIZE, CS8 },
2279 { TARGET_CSTOPB, TARGET_CSTOPB, CSTOPB, CSTOPB },
2280 { TARGET_CREAD, TARGET_CREAD, CREAD, CREAD },
2281 { TARGET_PARENB, TARGET_PARENB, PARENB, PARENB },
2282 { TARGET_PARODD, TARGET_PARODD, PARODD, PARODD },
2283 { TARGET_HUPCL, TARGET_HUPCL, HUPCL, HUPCL },
2284 { TARGET_CLOCAL, TARGET_CLOCAL, CLOCAL, CLOCAL },
2285 { TARGET_CRTSCTS, TARGET_CRTSCTS, CRTSCTS, CRTSCTS },
2286 { 0, 0, 0, 0 }
2287};
2288
2289bitmask_transtbl lflag_tbl[] = {
2290 { TARGET_ISIG, TARGET_ISIG, ISIG, ISIG },
2291 { TARGET_ICANON, TARGET_ICANON, ICANON, ICANON },
2292 { TARGET_XCASE, TARGET_XCASE, XCASE, XCASE },
2293 { TARGET_ECHO, TARGET_ECHO, ECHO, ECHO },
2294 { TARGET_ECHOE, TARGET_ECHOE, ECHOE, ECHOE },
2295 { TARGET_ECHOK, TARGET_ECHOK, ECHOK, ECHOK },
2296 { TARGET_ECHONL, TARGET_ECHONL, ECHONL, ECHONL },
2297 { TARGET_NOFLSH, TARGET_NOFLSH, NOFLSH, NOFLSH },
2298 { TARGET_TOSTOP, TARGET_TOSTOP, TOSTOP, TOSTOP },
2299 { TARGET_ECHOCTL, TARGET_ECHOCTL, ECHOCTL, ECHOCTL },
2300 { TARGET_ECHOPRT, TARGET_ECHOPRT, ECHOPRT, ECHOPRT },
2301 { TARGET_ECHOKE, TARGET_ECHOKE, ECHOKE, ECHOKE },
2302 { TARGET_FLUSHO, TARGET_FLUSHO, FLUSHO, FLUSHO },
2303 { TARGET_PENDIN, TARGET_PENDIN, PENDIN, PENDIN },
2304 { TARGET_IEXTEN, TARGET_IEXTEN, IEXTEN, IEXTEN },
2305 { 0, 0, 0, 0 }
2306};
2307
2308static void target_to_host_termios (void *dst, const void *src)
2309{
2310 struct host_termios *host = dst;
2311 const struct target_termios *target = src;
3b46e624 2312
5fafdf24 2313 host->c_iflag =
31e31b8a 2314 target_to_host_bitmask(tswap32(target->c_iflag), iflag_tbl);
5fafdf24 2315 host->c_oflag =
31e31b8a 2316 target_to_host_bitmask(tswap32(target->c_oflag), oflag_tbl);
5fafdf24 2317 host->c_cflag =
31e31b8a 2318 target_to_host_bitmask(tswap32(target->c_cflag), cflag_tbl);
5fafdf24 2319 host->c_lflag =
31e31b8a
FB
2320 target_to_host_bitmask(tswap32(target->c_lflag), lflag_tbl);
2321 host->c_line = target->c_line;
3b46e624 2322
5fafdf24
TS
2323 host->c_cc[VINTR] = target->c_cc[TARGET_VINTR];
2324 host->c_cc[VQUIT] = target->c_cc[TARGET_VQUIT];
3b46e624 2325 host->c_cc[VERASE] = target->c_cc[TARGET_VERASE];
5fafdf24 2326 host->c_cc[VKILL] = target->c_cc[TARGET_VKILL];
3b46e624 2327 host->c_cc[VEOF] = target->c_cc[TARGET_VEOF];
5fafdf24 2328 host->c_cc[VTIME] = target->c_cc[TARGET_VTIME];
3b46e624 2329 host->c_cc[VMIN] = target->c_cc[TARGET_VMIN];
5fafdf24 2330 host->c_cc[VSWTC] = target->c_cc[TARGET_VSWTC];
3b46e624 2331 host->c_cc[VSTART] = target->c_cc[TARGET_VSTART];
5fafdf24
TS
2332 host->c_cc[VSTOP] = target->c_cc[TARGET_VSTOP];
2333 host->c_cc[VSUSP] = target->c_cc[TARGET_VSUSP];
3b46e624
TS
2334 host->c_cc[VEOL] = target->c_cc[TARGET_VEOL];
2335 host->c_cc[VREPRINT] = target->c_cc[TARGET_VREPRINT];
2336 host->c_cc[VDISCARD] = target->c_cc[TARGET_VDISCARD];
2337 host->c_cc[VWERASE] = target->c_cc[TARGET_VWERASE];
2338 host->c_cc[VLNEXT] = target->c_cc[TARGET_VLNEXT];
5fafdf24 2339 host->c_cc[VEOL2] = target->c_cc[TARGET_VEOL2];
31e31b8a 2340}
3b46e624 2341
31e31b8a
FB
2342static void host_to_target_termios (void *dst, const void *src)
2343{
2344 struct target_termios *target = dst;
2345 const struct host_termios *host = src;
2346
5fafdf24 2347 target->c_iflag =
31e31b8a 2348 tswap32(host_to_target_bitmask(host->c_iflag, iflag_tbl));
5fafdf24 2349 target->c_oflag =
31e31b8a 2350 tswap32(host_to_target_bitmask(host->c_oflag, oflag_tbl));
5fafdf24 2351 target->c_cflag =
31e31b8a 2352 tswap32(host_to_target_bitmask(host->c_cflag, cflag_tbl));
5fafdf24 2353 target->c_lflag =
31e31b8a
FB
2354 tswap32(host_to_target_bitmask(host->c_lflag, lflag_tbl));
2355 target->c_line = host->c_line;
3b46e624 2356
31e31b8a
FB
2357 target->c_cc[TARGET_VINTR] = host->c_cc[VINTR];
2358 target->c_cc[TARGET_VQUIT] = host->c_cc[VQUIT];
2359 target->c_cc[TARGET_VERASE] = host->c_cc[VERASE];
2360 target->c_cc[TARGET_VKILL] = host->c_cc[VKILL];
2361 target->c_cc[TARGET_VEOF] = host->c_cc[VEOF];
2362 target->c_cc[TARGET_VTIME] = host->c_cc[VTIME];
2363 target->c_cc[TARGET_VMIN] = host->c_cc[VMIN];
2364 target->c_cc[TARGET_VSWTC] = host->c_cc[VSWTC];
2365 target->c_cc[TARGET_VSTART] = host->c_cc[VSTART];
2366 target->c_cc[TARGET_VSTOP] = host->c_cc[VSTOP];
2367 target->c_cc[TARGET_VSUSP] = host->c_cc[VSUSP];
2368 target->c_cc[TARGET_VEOL] = host->c_cc[VEOL];
2369 target->c_cc[TARGET_VREPRINT] = host->c_cc[VREPRINT];
2370 target->c_cc[TARGET_VDISCARD] = host->c_cc[VDISCARD];
2371 target->c_cc[TARGET_VWERASE] = host->c_cc[VWERASE];
2372 target->c_cc[TARGET_VLNEXT] = host->c_cc[VLNEXT];
2373 target->c_cc[TARGET_VEOL2] = host->c_cc[VEOL2];
2374}
2375
2376StructEntry struct_termios_def = {
2377 .convert = { host_to_target_termios, target_to_host_termios },
2378 .size = { sizeof(struct target_termios), sizeof(struct host_termios) },
2379 .align = { __alignof__(struct target_termios), __alignof__(struct host_termios) },
2380};
2381
5286db75
FB
2382static bitmask_transtbl mmap_flags_tbl[] = {
2383 { TARGET_MAP_SHARED, TARGET_MAP_SHARED, MAP_SHARED, MAP_SHARED },
2384 { TARGET_MAP_PRIVATE, TARGET_MAP_PRIVATE, MAP_PRIVATE, MAP_PRIVATE },
2385 { TARGET_MAP_FIXED, TARGET_MAP_FIXED, MAP_FIXED, MAP_FIXED },
2386 { TARGET_MAP_ANONYMOUS, TARGET_MAP_ANONYMOUS, MAP_ANONYMOUS, MAP_ANONYMOUS },
2387 { TARGET_MAP_GROWSDOWN, TARGET_MAP_GROWSDOWN, MAP_GROWSDOWN, MAP_GROWSDOWN },
2388 { TARGET_MAP_DENYWRITE, TARGET_MAP_DENYWRITE, MAP_DENYWRITE, MAP_DENYWRITE },
2389 { TARGET_MAP_EXECUTABLE, TARGET_MAP_EXECUTABLE, MAP_EXECUTABLE, MAP_EXECUTABLE },
2390 { TARGET_MAP_LOCKED, TARGET_MAP_LOCKED, MAP_LOCKED, MAP_LOCKED },
2391 { 0, 0, 0, 0 }
2392};
2393
ffa65c3b
FB
2394static bitmask_transtbl fcntl_flags_tbl[] = {
2395 { TARGET_O_ACCMODE, TARGET_O_WRONLY, O_ACCMODE, O_WRONLY, },
2396 { TARGET_O_ACCMODE, TARGET_O_RDWR, O_ACCMODE, O_RDWR, },
2397 { TARGET_O_CREAT, TARGET_O_CREAT, O_CREAT, O_CREAT, },
2398 { TARGET_O_EXCL, TARGET_O_EXCL, O_EXCL, O_EXCL, },
2399 { TARGET_O_NOCTTY, TARGET_O_NOCTTY, O_NOCTTY, O_NOCTTY, },
2400 { TARGET_O_TRUNC, TARGET_O_TRUNC, O_TRUNC, O_TRUNC, },
2401 { TARGET_O_APPEND, TARGET_O_APPEND, O_APPEND, O_APPEND, },
2402 { TARGET_O_NONBLOCK, TARGET_O_NONBLOCK, O_NONBLOCK, O_NONBLOCK, },
2403 { TARGET_O_SYNC, TARGET_O_SYNC, O_SYNC, O_SYNC, },
2404 { TARGET_FASYNC, TARGET_FASYNC, FASYNC, FASYNC, },
2405 { TARGET_O_DIRECTORY, TARGET_O_DIRECTORY, O_DIRECTORY, O_DIRECTORY, },
2406 { TARGET_O_NOFOLLOW, TARGET_O_NOFOLLOW, O_NOFOLLOW, O_NOFOLLOW, },
2407 { TARGET_O_LARGEFILE, TARGET_O_LARGEFILE, O_LARGEFILE, O_LARGEFILE, },
121061dc 2408#if defined(O_DIRECT)
ffa65c3b 2409 { TARGET_O_DIRECT, TARGET_O_DIRECT, O_DIRECT, O_DIRECT, },
121061dc 2410#endif
ffa65c3b
FB
2411 { 0, 0, 0, 0 }
2412};
2413
2ab83ea7 2414#if defined(TARGET_I386)
6dbad63e
FB
2415
2416/* NOTE: there is really one LDT for all the threads */
2417uint8_t *ldt_table;
2418
03acab66 2419static abi_long read_ldt(abi_ulong ptr, unsigned long bytecount)
6dbad63e
FB
2420{
2421 int size;
53a5960a 2422 void *p;
6dbad63e
FB
2423
2424 if (!ldt_table)
2425 return 0;
2426 size = TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE;
2427 if (size > bytecount)
2428 size = bytecount;
579a97f7
FB
2429 p = lock_user(VERIFY_WRITE, ptr, size, 0);
2430 if (!p)
03acab66 2431 return -TARGET_EFAULT;
579a97f7 2432 /* ??? Should this by byteswapped? */
53a5960a
PB
2433 memcpy(p, ldt_table, size);
2434 unlock_user(p, ptr, size);
6dbad63e
FB
2435 return size;
2436}
2437
2438/* XXX: add locking support */
03acab66
FB
2439static abi_long write_ldt(CPUX86State *env,
2440 abi_ulong ptr, unsigned long bytecount, int oldmode)
6dbad63e
FB
2441{
2442 struct target_modify_ldt_ldt_s ldt_info;
53a5960a 2443 struct target_modify_ldt_ldt_s *target_ldt_info;
6dbad63e 2444 int seg_32bit, contents, read_exec_only, limit_in_pages;
8d18e893 2445 int seg_not_present, useable, lm;
6dbad63e
FB
2446 uint32_t *lp, entry_1, entry_2;
2447
2448 if (bytecount != sizeof(ldt_info))
03acab66 2449 return -TARGET_EINVAL;
579a97f7 2450 if (!lock_user_struct(VERIFY_READ, target_ldt_info, ptr, 1))
03acab66 2451 return -TARGET_EFAULT;
53a5960a
PB
2452 ldt_info.entry_number = tswap32(target_ldt_info->entry_number);
2453 ldt_info.base_addr = tswapl(target_ldt_info->base_addr);
2454 ldt_info.limit = tswap32(target_ldt_info->limit);
2455 ldt_info.flags = tswap32(target_ldt_info->flags);
2456 unlock_user_struct(target_ldt_info, ptr, 0);
3b46e624 2457
6dbad63e 2458 if (ldt_info.entry_number >= TARGET_LDT_ENTRIES)
03acab66 2459 return -TARGET_EINVAL;
6dbad63e
FB
2460 seg_32bit = ldt_info.flags & 1;
2461 contents = (ldt_info.flags >> 1) & 3;
2462 read_exec_only = (ldt_info.flags >> 3) & 1;
2463 limit_in_pages = (ldt_info.flags >> 4) & 1;
2464 seg_not_present = (ldt_info.flags >> 5) & 1;
2465 useable = (ldt_info.flags >> 6) & 1;
8d18e893
FB
2466#ifdef TARGET_ABI32
2467 lm = 0;
2468#else
2469 lm = (ldt_info.flags >> 7) & 1;
2470#endif
6dbad63e
FB
2471 if (contents == 3) {
2472 if (oldmode)
03acab66 2473 return -TARGET_EINVAL;
6dbad63e 2474 if (seg_not_present == 0)
03acab66 2475 return -TARGET_EINVAL;
6dbad63e
FB
2476 }
2477 /* allocate the LDT */
2478 if (!ldt_table) {
2479 ldt_table = malloc(TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE);
2480 if (!ldt_table)
03acab66 2481 return -TARGET_ENOMEM;
6dbad63e 2482 memset(ldt_table, 0, TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE);
eeeac3f3 2483 env->ldt.base = h2g((unsigned long)ldt_table);
6dbad63e
FB
2484 env->ldt.limit = 0xffff;
2485 }
2486
2487 /* NOTE: same code as Linux kernel */
2488 /* Allow LDTs to be cleared by the user. */
2489 if (ldt_info.base_addr == 0 && ldt_info.limit == 0) {
2490 if (oldmode ||
2491 (contents == 0 &&
2492 read_exec_only == 1 &&
2493 seg_32bit == 0 &&
2494 limit_in_pages == 0 &&
2495 seg_not_present == 1 &&
2496 useable == 0 )) {
2497 entry_1 = 0;
2498 entry_2 = 0;
2499 goto install;
2500 }
2501 }
3b46e624 2502
6dbad63e
FB
2503 entry_1 = ((ldt_info.base_addr & 0x0000ffff) << 16) |
2504 (ldt_info.limit & 0x0ffff);
2505 entry_2 = (ldt_info.base_addr & 0xff000000) |
2506 ((ldt_info.base_addr & 0x00ff0000) >> 16) |
2507 (ldt_info.limit & 0xf0000) |
2508 ((read_exec_only ^ 1) << 9) |
2509 (contents << 10) |
2510 ((seg_not_present ^ 1) << 15) |
2511 (seg_32bit << 22) |
2512 (limit_in_pages << 23) |
8d18e893 2513 (lm << 21) |
6dbad63e
FB
2514 0x7000;
2515 if (!oldmode)
2516 entry_2 |= (useable << 20);
14ae3ba7 2517
6dbad63e
FB
2518 /* Install the new entry ... */
2519install:
2520 lp = (uint32_t *)(ldt_table + (ldt_info.entry_number << 3));
2521 lp[0] = tswap32(entry_1);
2522 lp[1] = tswap32(entry_2);
2523 return 0;
2524}
2525
2526/* specific and weird i386 syscalls */
8fcd3692
BS
2527static abi_long do_modify_ldt(CPUX86State *env, int func, abi_ulong ptr,
2528 unsigned long bytecount)
6dbad63e 2529{
03acab66 2530 abi_long ret;
3b46e624 2531
6dbad63e
FB
2532 switch (func) {
2533 case 0:
2534 ret = read_ldt(ptr, bytecount);
2535 break;
2536 case 1:
2537 ret = write_ldt(env, ptr, bytecount, 1);
2538 break;
2539 case 0x11:
2540 ret = write_ldt(env, ptr, bytecount, 0);
2541 break;
03acab66
FB
2542 default:
2543 ret = -TARGET_ENOSYS;
2544 break;
6dbad63e
FB
2545 }
2546 return ret;
2547}
1b6b029e 2548
4583f589 2549#if defined(TARGET_I386) && defined(TARGET_ABI32)
8fcd3692 2550static abi_long do_set_thread_area(CPUX86State *env, abi_ulong ptr)
8d18e893
FB
2551{
2552 uint64_t *gdt_table = g2h(env->gdt.base);
2553 struct target_modify_ldt_ldt_s ldt_info;
2554 struct target_modify_ldt_ldt_s *target_ldt_info;
2555 int seg_32bit, contents, read_exec_only, limit_in_pages;
2556 int seg_not_present, useable, lm;
2557 uint32_t *lp, entry_1, entry_2;
2558 int i;
2559
2560 lock_user_struct(VERIFY_WRITE, target_ldt_info, ptr, 1);
2561 if (!target_ldt_info)
2562 return -TARGET_EFAULT;
2563 ldt_info.entry_number = tswap32(target_ldt_info->entry_number);
2564 ldt_info.base_addr = tswapl(target_ldt_info->base_addr);
2565 ldt_info.limit = tswap32(target_ldt_info->limit);
2566 ldt_info.flags = tswap32(target_ldt_info->flags);
2567 if (ldt_info.entry_number == -1) {
2568 for (i=TARGET_GDT_ENTRY_TLS_MIN; i<=TARGET_GDT_ENTRY_TLS_MAX; i++) {
2569 if (gdt_table[i] == 0) {
2570 ldt_info.entry_number = i;
2571 target_ldt_info->entry_number = tswap32(i);
2572 break;
2573 }
2574 }
2575 }
2576 unlock_user_struct(target_ldt_info, ptr, 1);
2577
2578 if (ldt_info.entry_number < TARGET_GDT_ENTRY_TLS_MIN ||
2579 ldt_info.entry_number > TARGET_GDT_ENTRY_TLS_MAX)
2580 return -TARGET_EINVAL;
2581 seg_32bit = ldt_info.flags & 1;
2582 contents = (ldt_info.flags >> 1) & 3;
2583 read_exec_only = (ldt_info.flags >> 3) & 1;
2584 limit_in_pages = (ldt_info.flags >> 4) & 1;
2585 seg_not_present = (ldt_info.flags >> 5) & 1;
2586 useable = (ldt_info.flags >> 6) & 1;
2587#ifdef TARGET_ABI32
2588 lm = 0;
2589#else
2590 lm = (ldt_info.flags >> 7) & 1;
2591#endif
2592
2593 if (contents == 3) {
2594 if (seg_not_present == 0)
2595 return -TARGET_EINVAL;
2596 }
2597
2598 /* NOTE: same code as Linux kernel */
2599 /* Allow LDTs to be cleared by the user. */
2600 if (ldt_info.base_addr == 0 && ldt_info.limit == 0) {
2601 if ((contents == 0 &&
2602 read_exec_only == 1 &&
2603 seg_32bit == 0 &&
2604 limit_in_pages == 0 &&
2605 seg_not_present == 1 &&
2606 useable == 0 )) {
2607 entry_1 = 0;
2608 entry_2 = 0;
2609 goto install;
2610 }
2611 }
2612
2613 entry_1 = ((ldt_info.base_addr & 0x0000ffff) << 16) |
2614 (ldt_info.limit & 0x0ffff);
2615 entry_2 = (ldt_info.base_addr & 0xff000000) |
2616 ((ldt_info.base_addr & 0x00ff0000) >> 16) |
2617 (ldt_info.limit & 0xf0000) |
2618 ((read_exec_only ^ 1) << 9) |
2619 (contents << 10) |
2620 ((seg_not_present ^ 1) << 15) |
2621 (seg_32bit << 22) |
2622 (limit_in_pages << 23) |
2623 (useable << 20) |
2624 (lm << 21) |
2625 0x7000;
2626
2627 /* Install the new entry ... */
2628install:
2629 lp = (uint32_t *)(gdt_table + ldt_info.entry_number);
2630 lp[0] = tswap32(entry_1);
2631 lp[1] = tswap32(entry_2);
2632 return 0;
2633}
2634
8fcd3692 2635static abi_long do_get_thread_area(CPUX86State *env, abi_ulong ptr)
8d18e893
FB
2636{
2637 struct target_modify_ldt_ldt_s *target_ldt_info;
2638 uint64_t *gdt_table = g2h(env->gdt.base);
2639 uint32_t base_addr, limit, flags;
2640 int seg_32bit, contents, read_exec_only, limit_in_pages, idx;
2641 int seg_not_present, useable, lm;
2642 uint32_t *lp, entry_1, entry_2;
2643
2644 lock_user_struct(VERIFY_WRITE, target_ldt_info, ptr, 1);
2645 if (!target_ldt_info)
2646 return -TARGET_EFAULT;
2647 idx = tswap32(target_ldt_info->entry_number);
2648 if (idx < TARGET_GDT_ENTRY_TLS_MIN ||
2649 idx > TARGET_GDT_ENTRY_TLS_MAX) {
2650 unlock_user_struct(target_ldt_info, ptr, 1);
2651 return -TARGET_EINVAL;
2652 }
2653 lp = (uint32_t *)(gdt_table + idx);
2654 entry_1 = tswap32(lp[0]);
2655 entry_2 = tswap32(lp[1]);
2656
2657 read_exec_only = ((entry_2 >> 9) & 1) ^ 1;
2658 contents = (entry_2 >> 10) & 3;
2659 seg_not_present = ((entry_2 >> 15) & 1) ^ 1;
2660 seg_32bit = (entry_2 >> 22) & 1;
2661 limit_in_pages = (entry_2 >> 23) & 1;
2662 useable = (entry_2 >> 20) & 1;
2663#ifdef TARGET_ABI32
2664 lm = 0;
2665#else
2666 lm = (entry_2 >> 21) & 1;
2667#endif
2668 flags = (seg_32bit << 0) | (contents << 1) |
2669 (read_exec_only << 3) | (limit_in_pages << 4) |
2670 (seg_not_present << 5) | (useable << 6) | (lm << 7);
2671 limit = (entry_1 & 0xffff) | (entry_2 & 0xf0000);
2672 base_addr = (entry_1 >> 16) |
2673 (entry_2 & 0xff000000) |
2674 ((entry_2 & 0xff) << 16);
2675 target_ldt_info->base_addr = tswapl(base_addr);
2676 target_ldt_info->limit = tswap32(limit);
2677 target_ldt_info->flags = tswap32(flags);
2678 unlock_user_struct(target_ldt_info, ptr, 1);
2679 return 0;
2680}
4583f589 2681#endif /* TARGET_I386 && TARGET_ABI32 */
8d18e893 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}