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