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