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