]> git.proxmox.com Git - mirror_qemu.git/blame - linux-user/syscall.c
Fix type mismatch.
[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 2738 ts = malloc(sizeof(TaskState) + NEW_STACK_SIZE);
624f7979 2739 init_task_state(ts);
5cd4393b 2740 new_stack = ts->stack;
1b6b029e 2741 /* we create a new CPU instance. */
c5be9f08 2742 new_env = cpu_copy(env);
6e68e076
PB
2743 /* Init regs that differ from the parent. */
2744 cpu_clone_regs(new_env, newsp);
5cd4393b 2745 new_env->opaque = ts;
27725c1d 2746#ifdef __ia64__
fd4a43e4 2747 ret = __clone2(clone_func, new_stack + NEW_STACK_SIZE, flags, new_env);
27725c1d
FB
2748#else
2749 ret = clone(clone_func, new_stack + NEW_STACK_SIZE, flags, new_env);
2750#endif
1b6b029e
FB
2751 } else {
2752 /* if no CLONE_VM, we consider it is a fork */
2753 if ((flags & ~CSIGNAL) != 0)
2754 return -EINVAL;
2755 ret = fork();
6e68e076
PB
2756 if (ret == 0) {
2757 cpu_clone_regs(env, newsp);
2758 }
1b6b029e
FB
2759 }
2760 return ret;
2761}
2762
992f48a0 2763static abi_long do_fcntl(int fd, int cmd, abi_ulong arg)
7775e9ec
FB
2764{
2765 struct flock fl;
53a5960a 2766 struct target_flock *target_fl;
43f238d7
TS
2767 struct flock64 fl64;
2768 struct target_flock64 *target_fl64;
992f48a0 2769 abi_long ret;
53a5960a 2770
7775e9ec
FB
2771 switch(cmd) {
2772 case TARGET_F_GETLK:
579a97f7
FB
2773 if (!lock_user_struct(VERIFY_READ, target_fl, arg, 1))
2774 return -TARGET_EFAULT;
5813427b
TS
2775 fl.l_type = tswap16(target_fl->l_type);
2776 fl.l_whence = tswap16(target_fl->l_whence);
2777 fl.l_start = tswapl(target_fl->l_start);
2778 fl.l_len = tswapl(target_fl->l_len);
2779 fl.l_pid = tswapl(target_fl->l_pid);
2780 unlock_user_struct(target_fl, arg, 0);
9ee1fa2c 2781 ret = get_errno(fcntl(fd, cmd, &fl));
7775e9ec 2782 if (ret == 0) {
579a97f7
FB
2783 if (!lock_user_struct(VERIFY_WRITE, target_fl, arg, 0))
2784 return -TARGET_EFAULT;
7775e9ec
FB
2785 target_fl->l_type = tswap16(fl.l_type);
2786 target_fl->l_whence = tswap16(fl.l_whence);
2787 target_fl->l_start = tswapl(fl.l_start);
2788 target_fl->l_len = tswapl(fl.l_len);
2789 target_fl->l_pid = tswapl(fl.l_pid);
53a5960a 2790 unlock_user_struct(target_fl, arg, 1);
7775e9ec
FB
2791 }
2792 break;
3b46e624 2793
7775e9ec
FB
2794 case TARGET_F_SETLK:
2795 case TARGET_F_SETLKW:
579a97f7
FB
2796 if (!lock_user_struct(VERIFY_READ, target_fl, arg, 1))
2797 return -TARGET_EFAULT;
7775e9ec
FB
2798 fl.l_type = tswap16(target_fl->l_type);
2799 fl.l_whence = tswap16(target_fl->l_whence);
2800 fl.l_start = tswapl(target_fl->l_start);
2801 fl.l_len = tswapl(target_fl->l_len);
2802 fl.l_pid = tswapl(target_fl->l_pid);
53a5960a 2803 unlock_user_struct(target_fl, arg, 0);
9ee1fa2c 2804 ret = get_errno(fcntl(fd, cmd, &fl));
7775e9ec 2805 break;
3b46e624 2806
7775e9ec 2807 case TARGET_F_GETLK64:
579a97f7
FB
2808 if (!lock_user_struct(VERIFY_READ, target_fl64, arg, 1))
2809 return -TARGET_EFAULT;
5813427b
TS
2810 fl64.l_type = tswap16(target_fl64->l_type) >> 1;
2811 fl64.l_whence = tswap16(target_fl64->l_whence);
2812 fl64.l_start = tswapl(target_fl64->l_start);
2813 fl64.l_len = tswapl(target_fl64->l_len);
2814 fl64.l_pid = tswap16(target_fl64->l_pid);
2815 unlock_user_struct(target_fl64, arg, 0);
9ee1fa2c 2816 ret = get_errno(fcntl(fd, cmd >> 1, &fl64));
43f238d7 2817 if (ret == 0) {
579a97f7
FB
2818 if (!lock_user_struct(VERIFY_WRITE, target_fl64, arg, 0))
2819 return -TARGET_EFAULT;
43f238d7
TS
2820 target_fl64->l_type = tswap16(fl64.l_type) >> 1;
2821 target_fl64->l_whence = tswap16(fl64.l_whence);
2822 target_fl64->l_start = tswapl(fl64.l_start);
2823 target_fl64->l_len = tswapl(fl64.l_len);
2824 target_fl64->l_pid = tswapl(fl64.l_pid);
2825 unlock_user_struct(target_fl64, arg, 1);
2826 }
9ee1fa2c 2827 break;
7775e9ec
FB
2828 case TARGET_F_SETLK64:
2829 case TARGET_F_SETLKW64:
579a97f7
FB
2830 if (!lock_user_struct(VERIFY_READ, target_fl64, arg, 1))
2831 return -TARGET_EFAULT;
43f238d7
TS
2832 fl64.l_type = tswap16(target_fl64->l_type) >> 1;
2833 fl64.l_whence = tswap16(target_fl64->l_whence);
2834 fl64.l_start = tswapl(target_fl64->l_start);
2835 fl64.l_len = tswapl(target_fl64->l_len);
2836 fl64.l_pid = tswap16(target_fl64->l_pid);
2837 unlock_user_struct(target_fl64, arg, 0);
9ee1fa2c 2838 ret = get_errno(fcntl(fd, cmd >> 1, &fl64));
7775e9ec
FB
2839 break;
2840
ffa65c3b 2841 case F_GETFL:
9ee1fa2c
FB
2842 ret = get_errno(fcntl(fd, cmd, arg));
2843 if (ret >= 0) {
2844 ret = host_to_target_bitmask(ret, fcntl_flags_tbl);
2845 }
ffa65c3b
FB
2846 break;
2847
2848 case F_SETFL:
9ee1fa2c 2849 ret = get_errno(fcntl(fd, cmd, target_to_host_bitmask(arg, fcntl_flags_tbl)));
ffa65c3b
FB
2850 break;
2851
7775e9ec 2852 default:
9ee1fa2c 2853 ret = get_errno(fcntl(fd, cmd, arg));
7775e9ec
FB
2854 break;
2855 }
2856 return ret;
2857}
2858
67867308 2859#ifdef USE_UID16
7775e9ec 2860
67867308
FB
2861static inline int high2lowuid(int uid)
2862{
2863 if (uid > 65535)
2864 return 65534;
2865 else
2866 return uid;
2867}
2868
2869static inline int high2lowgid(int gid)
2870{
2871 if (gid > 65535)
2872 return 65534;
2873 else
2874 return gid;
2875}
2876
2877static inline int low2highuid(int uid)
2878{
2879 if ((int16_t)uid == -1)
2880 return -1;
2881 else
2882 return uid;
2883}
2884
2885static inline int low2highgid(int gid)
2886{
2887 if ((int16_t)gid == -1)
2888 return -1;
2889 else
2890 return gid;
2891}
2892
2893#endif /* USE_UID16 */
1b6b029e 2894
31e31b8a
FB
2895void syscall_init(void)
2896{
2ab83ea7
FB
2897 IOCTLEntry *ie;
2898 const argtype *arg_type;
2899 int size;
b92c47c1 2900 int i;
2ab83ea7 2901
5fafdf24
TS
2902#define STRUCT(name, list...) thunk_register_struct(STRUCT_ ## name, #name, struct_ ## name ## _def);
2903#define STRUCT_SPECIAL(name) thunk_register_struct_direct(STRUCT_ ## name, #name, &struct_ ## name ## _def);
31e31b8a
FB
2904#include "syscall_types.h"
2905#undef STRUCT
2906#undef STRUCT_SPECIAL
2ab83ea7
FB
2907
2908 /* we patch the ioctl size if necessary. We rely on the fact that
2909 no ioctl has all the bits at '1' in the size field */
2910 ie = ioctl_entries;
2911 while (ie->target_cmd != 0) {
2912 if (((ie->target_cmd >> TARGET_IOC_SIZESHIFT) & TARGET_IOC_SIZEMASK) ==
2913 TARGET_IOC_SIZEMASK) {
2914 arg_type = ie->arg_type;
2915 if (arg_type[0] != TYPE_PTR) {
5fafdf24 2916 fprintf(stderr, "cannot patch size for ioctl 0x%x\n",
2ab83ea7
FB
2917 ie->target_cmd);
2918 exit(1);
2919 }
2920 arg_type++;
2921 size = thunk_type_size(arg_type, 0);
5fafdf24 2922 ie->target_cmd = (ie->target_cmd &
2ab83ea7
FB
2923 ~(TARGET_IOC_SIZEMASK << TARGET_IOC_SIZESHIFT)) |
2924 (size << TARGET_IOC_SIZESHIFT);
2925 }
b92c47c1
TS
2926
2927 /* Build target_to_host_errno_table[] table from
2928 * host_to_target_errno_table[]. */
2929 for (i=0; i < ERRNO_TABLE_SIZE; i++)
2930 target_to_host_errno_table[host_to_target_errno_table[i]] = i;
2931
2ab83ea7 2932 /* automatic consistency check if same arch */
d2fd1af7 2933#if defined(__i386__) && defined(TARGET_I386) && defined(TARGET_ABI32)
2ab83ea7 2934 if (ie->target_cmd != ie->host_cmd) {
5fafdf24 2935 fprintf(stderr, "ERROR: ioctl: target=0x%x host=0x%x\n",
2ab83ea7
FB
2936 ie->target_cmd, ie->host_cmd);
2937 }
2938#endif
2939 ie++;
2940 }
31e31b8a 2941}
c573ff67 2942
992f48a0 2943#if TARGET_ABI_BITS == 32
ce4defa0
PB
2944static inline uint64_t target_offset64(uint32_t word0, uint32_t word1)
2945{
2946#ifdef TARGET_WORDS_BIG_ENDIAN
2947 return ((uint64_t)word0 << 32) | word1;
2948#else
2949 return ((uint64_t)word1 << 32) | word0;
2950#endif
2951}
992f48a0 2952#else /* TARGET_ABI_BITS == 32 */
32407103
JM
2953static inline uint64_t target_offset64(uint64_t word0, uint64_t word1)
2954{
2955 return word0;
2956}
992f48a0 2957#endif /* TARGET_ABI_BITS != 32 */
ce4defa0
PB
2958
2959#ifdef TARGET_NR_truncate64
992f48a0
BS
2960static inline abi_long target_truncate64(void *cpu_env, const char *arg1,
2961 abi_long arg2,
2962 abi_long arg3,
2963 abi_long arg4)
ce4defa0
PB
2964{
2965#ifdef TARGET_ARM
2966 if (((CPUARMState *)cpu_env)->eabi)
2967 {
2968 arg2 = arg3;
2969 arg3 = arg4;
2970 }
2971#endif
2972 return get_errno(truncate64(arg1, target_offset64(arg2, arg3)));
2973}
2974#endif
2975
2976#ifdef TARGET_NR_ftruncate64
992f48a0
BS
2977static inline abi_long target_ftruncate64(void *cpu_env, abi_long arg1,
2978 abi_long arg2,
2979 abi_long arg3,
2980 abi_long arg4)
ce4defa0
PB
2981{
2982#ifdef TARGET_ARM
2983 if (((CPUARMState *)cpu_env)->eabi)
2984 {
2985 arg2 = arg3;
2986 arg3 = arg4;
2987 }
2988#endif
2989 return get_errno(ftruncate64(arg1, target_offset64(arg2, arg3)));
2990}
2991#endif
2992
579a97f7
FB
2993static inline abi_long target_to_host_timespec(struct timespec *host_ts,
2994 abi_ulong target_addr)
53a5960a
PB
2995{
2996 struct target_timespec *target_ts;
2997
579a97f7
FB
2998 if (!lock_user_struct(VERIFY_READ, target_ts, target_addr, 1))
2999 return -TARGET_EFAULT;
53a5960a
PB
3000 host_ts->tv_sec = tswapl(target_ts->tv_sec);
3001 host_ts->tv_nsec = tswapl(target_ts->tv_nsec);
3002 unlock_user_struct(target_ts, target_addr, 0);
b255bfa8 3003 return 0;
53a5960a
PB
3004}
3005
579a97f7
FB
3006static inline abi_long host_to_target_timespec(abi_ulong target_addr,
3007 struct timespec *host_ts)
53a5960a
PB
3008{
3009 struct target_timespec *target_ts;
3010
579a97f7
FB
3011 if (!lock_user_struct(VERIFY_WRITE, target_ts, target_addr, 0))
3012 return -TARGET_EFAULT;
53a5960a
PB
3013 target_ts->tv_sec = tswapl(host_ts->tv_sec);
3014 target_ts->tv_nsec = tswapl(host_ts->tv_nsec);
3015 unlock_user_struct(target_ts, target_addr, 1);
b255bfa8 3016 return 0;
53a5960a
PB
3017}
3018
bd0c5661
PB
3019#if defined(USE_NPTL)
3020/* ??? Using host futex calls even when target atomic operations
3021 are not really atomic probably breaks things. However implementing
3022 futexes locally would make futexes shared between multiple processes
3023 tricky. However they're probably useless because guest atomic
3024 operations won't work either. */
3025int do_futex(target_ulong uaddr, int op, int val, target_ulong timeout,
3026 target_ulong uaddr2, int val3)
3027{
3028 struct timespec ts, *pts;
3029
3030 /* ??? We assume FUTEX_* constants are the same on both host
3031 and target. */
3032 switch (op) {
3033 case FUTEX_WAIT:
3034 if (timeout) {
3035 pts = &ts;
3036 target_to_host_timespec(pts, timeout);
3037 } else {
3038 pts = NULL;
3039 }
3040 return get_errno(sys_futex(g2h(uaddr), FUTEX_WAIT, tswap32(val),
3041 pts, NULL, 0));
3042 case FUTEX_WAKE:
3043 return get_errno(sys_futex(g2h(uaddr), FUTEX_WAKE, val, NULL, NULL, 0));
3044 case FUTEX_FD:
3045 return get_errno(sys_futex(g2h(uaddr), FUTEX_FD, val, NULL, NULL, 0));
3046 case FUTEX_REQUEUE:
3047 return get_errno(sys_futex(g2h(uaddr), FUTEX_REQUEUE, val,
3048 NULL, g2h(uaddr2), 0));
3049 case FUTEX_CMP_REQUEUE:
3050 return get_errno(sys_futex(g2h(uaddr), FUTEX_CMP_REQUEUE, val,
3051 NULL, g2h(uaddr2), tswap32(val3)));
3052 default:
3053 return -TARGET_ENOSYS;
3054 }
3055}
3056#endif
3057
a745ec6d
PB
3058int get_osversion(void)
3059{
3060 static int osversion;
3061 struct new_utsname buf;
3062 const char *s;
3063 int i, n, tmp;
3064 if (osversion)
3065 return osversion;
3066 if (qemu_uname_release && *qemu_uname_release) {
3067 s = qemu_uname_release;
3068 } else {
3069 if (sys_uname(&buf))
3070 return 0;
3071 s = buf.release;
3072 }
3073 tmp = 0;
3074 for (i = 0; i < 3; i++) {
3075 n = 0;
3076 while (*s >= '0' && *s <= '9') {
3077 n *= 10;
3078 n += *s - '0';
3079 s++;
3080 }
3081 tmp = (tmp << 8) + n;
3082 if (*s == '.')
3083 s++;
3084 }
3085 osversion = tmp;
3086 return osversion;
3087}
3088
0da46a6e
TS
3089/* do_syscall() should always have a single exit point at the end so
3090 that actions, such as logging of syscall results, can be performed.
3091 All errnos that do_syscall() returns must be -TARGET_<errcode>. */
992f48a0
BS
3092abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
3093 abi_long arg2, abi_long arg3, abi_long arg4,
3094 abi_long arg5, abi_long arg6)
31e31b8a 3095{
992f48a0 3096 abi_long ret;
31e31b8a 3097 struct stat st;
56c8f68f 3098 struct statfs stfs;
53a5960a 3099 void *p;
3b46e624 3100
72f03900 3101#ifdef DEBUG
c573ff67 3102 gemu_log("syscall %d", num);
72f03900 3103#endif
b92c47c1
TS
3104 if(do_strace)
3105 print_syscall(num, arg1, arg2, arg3, arg4, arg5, arg6);
3106
31e31b8a
FB
3107 switch(num) {
3108 case TARGET_NR_exit:
7d13299d
FB
3109#ifdef HAVE_GPROF
3110 _mcleanup();
3111#endif
e9009676 3112 gdb_exit(cpu_env, arg1);
1b6b029e 3113 /* XXX: should free thread stack and CPU env */
31e31b8a
FB
3114 _exit(arg1);
3115 ret = 0; /* avoid warning */
3116 break;
3117 case TARGET_NR_read:
579a97f7
FB
3118 if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
3119 goto efault;
53a5960a
PB
3120 ret = get_errno(read(arg1, p, arg3));
3121 unlock_user(p, arg2, ret);
31e31b8a
FB
3122 break;
3123 case TARGET_NR_write:
579a97f7
FB
3124 if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
3125 goto efault;
53a5960a
PB
3126 ret = get_errno(write(arg1, p, arg3));
3127 unlock_user(p, arg2, 0);
31e31b8a
FB
3128 break;
3129 case TARGET_NR_open:
2f619698
FB
3130 if (!(p = lock_user_string(arg1)))
3131 goto efault;
53a5960a 3132 ret = get_errno(open(path(p),
ffa65c3b
FB
3133 target_to_host_bitmask(arg2, fcntl_flags_tbl),
3134 arg3));
53a5960a 3135 unlock_user(p, arg1, 0);
31e31b8a 3136 break;
82424832
TS
3137#if defined(TARGET_NR_openat) && defined(__NR_openat)
3138 case TARGET_NR_openat:
579a97f7
FB
3139 if (!(p = lock_user_string(arg2)))
3140 goto efault;
3141 ret = get_errno(sys_openat(arg1,
3142 path(p),
3143 target_to_host_bitmask(arg3, fcntl_flags_tbl),
3144 arg4));
3145 unlock_user(p, arg2, 0);
82424832
TS
3146 break;
3147#endif
31e31b8a
FB
3148 case TARGET_NR_close:
3149 ret = get_errno(close(arg1));
3150 break;
3151 case TARGET_NR_brk:
53a5960a 3152 ret = do_brk(arg1);
31e31b8a
FB
3153 break;
3154 case TARGET_NR_fork:
1b6b029e 3155 ret = get_errno(do_fork(cpu_env, SIGCHLD, 0));
31e31b8a 3156 break;
e5febef5 3157#ifdef TARGET_NR_waitpid
31e31b8a
FB
3158 case TARGET_NR_waitpid:
3159 {
53a5960a
PB
3160 int status;
3161 ret = get_errno(waitpid(arg1, &status, arg3));
2f619698
FB
3162 if (!is_error(ret) && arg2
3163 && put_user_s32(status, arg2))
3164 goto efault;
31e31b8a
FB
3165 }
3166 break;
e5febef5 3167#endif
f0cbb613
PB
3168#ifdef TARGET_NR_waitid
3169 case TARGET_NR_waitid:
3170 {
3171 siginfo_t info;
3172 info.si_pid = 0;
3173 ret = get_errno(waitid(arg1, arg2, &info, arg4));
3174 if (!is_error(ret) && arg3 && info.si_pid != 0) {
3175 if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_siginfo_t), 0)))
3176 goto efault;
3177 host_to_target_siginfo(p, &info);
3178 unlock_user(p, arg3, sizeof(target_siginfo_t));
3179 }
3180 }
3181 break;
3182#endif
7a3148a9 3183#ifdef TARGET_NR_creat /* not on alpha */
31e31b8a 3184 case TARGET_NR_creat:
579a97f7
FB
3185 if (!(p = lock_user_string(arg1)))
3186 goto efault;
53a5960a
PB
3187 ret = get_errno(creat(p, arg2));
3188 unlock_user(p, arg1, 0);
31e31b8a 3189 break;
7a3148a9 3190#endif
31e31b8a 3191 case TARGET_NR_link:
53a5960a
PB
3192 {
3193 void * p2;
3194 p = lock_user_string(arg1);
3195 p2 = lock_user_string(arg2);
579a97f7
FB
3196 if (!p || !p2)
3197 ret = -TARGET_EFAULT;
3198 else
3199 ret = get_errno(link(p, p2));
53a5960a
PB
3200 unlock_user(p2, arg2, 0);
3201 unlock_user(p, arg1, 0);
3202 }
31e31b8a 3203 break;
64f0ce4c
TS
3204#if defined(TARGET_NR_linkat) && defined(__NR_linkat)
3205 case TARGET_NR_linkat:
64f0ce4c
TS
3206 {
3207 void * p2 = NULL;
579a97f7
FB
3208 if (!arg2 || !arg4)
3209 goto efault;
64f0ce4c
TS
3210 p = lock_user_string(arg2);
3211 p2 = lock_user_string(arg4);
579a97f7 3212 if (!p || !p2)
0da46a6e 3213 ret = -TARGET_EFAULT;
64f0ce4c
TS
3214 else
3215 ret = get_errno(sys_linkat(arg1, p, arg3, p2, arg5));
579a97f7
FB
3216 unlock_user(p, arg2, 0);
3217 unlock_user(p2, arg4, 0);
64f0ce4c
TS
3218 }
3219 break;
3220#endif
31e31b8a 3221 case TARGET_NR_unlink:
579a97f7
FB
3222 if (!(p = lock_user_string(arg1)))
3223 goto efault;
53a5960a
PB
3224 ret = get_errno(unlink(p));
3225 unlock_user(p, arg1, 0);
31e31b8a 3226 break;
8170f56b
TS
3227#if defined(TARGET_NR_unlinkat) && defined(__NR_unlinkat)
3228 case TARGET_NR_unlinkat:
579a97f7
FB
3229 if (!(p = lock_user_string(arg2)))
3230 goto efault;
3231 ret = get_errno(sys_unlinkat(arg1, p, arg3));
3232 unlock_user(p, arg2, 0);
ed494d87 3233 break;
b7d35e65 3234#endif
31e31b8a 3235 case TARGET_NR_execve:
7854b056
FB
3236 {
3237 char **argp, **envp;
f7341ff4 3238 int argc, envc;
992f48a0
BS
3239 abi_ulong gp;
3240 abi_ulong guest_argp;
3241 abi_ulong guest_envp;
3242 abi_ulong addr;
7854b056
FB
3243 char **q;
3244
f7341ff4 3245 argc = 0;
53a5960a 3246 guest_argp = arg2;
da94d263 3247 for (gp = guest_argp; gp; gp += sizeof(abi_ulong)) {
03aa1976 3248 if (get_user_ual(addr, gp))
2f619698 3249 goto efault;
03aa1976 3250 if (!addr)
2f619698 3251 break;
7854b056 3252 argc++;
2f619698 3253 }
f7341ff4 3254 envc = 0;
53a5960a 3255 guest_envp = arg3;
da94d263 3256 for (gp = guest_envp; gp; gp += sizeof(abi_ulong)) {
03aa1976 3257 if (get_user_ual(addr, gp))
2f619698 3258 goto efault;
03aa1976 3259 if (!addr)
2f619698 3260 break;
7854b056 3261 envc++;
2f619698 3262 }
7854b056 3263
f7341ff4
FB
3264 argp = alloca((argc + 1) * sizeof(void *));
3265 envp = alloca((envc + 1) * sizeof(void *));
7854b056 3266
da94d263 3267 for (gp = guest_argp, q = argp; gp;
992f48a0 3268 gp += sizeof(abi_ulong), q++) {
2f619698
FB
3269 if (get_user_ual(addr, gp))
3270 goto execve_efault;
53a5960a
PB
3271 if (!addr)
3272 break;
2f619698
FB
3273 if (!(*q = lock_user_string(addr)))
3274 goto execve_efault;
53a5960a 3275 }
f7341ff4
FB
3276 *q = NULL;
3277
da94d263 3278 for (gp = guest_envp, q = envp; gp;
992f48a0 3279 gp += sizeof(abi_ulong), q++) {
2f619698
FB
3280 if (get_user_ual(addr, gp))
3281 goto execve_efault;
53a5960a
PB
3282 if (!addr)
3283 break;
2f619698
FB
3284 if (!(*q = lock_user_string(addr)))
3285 goto execve_efault;
53a5960a 3286 }
f7341ff4 3287 *q = NULL;
7854b056 3288
2f619698
FB
3289 if (!(p = lock_user_string(arg1)))
3290 goto execve_efault;
53a5960a
PB
3291 ret = get_errno(execve(p, argp, envp));
3292 unlock_user(p, arg1, 0);
3293
2f619698
FB
3294 goto execve_end;
3295
3296 execve_efault:
3297 ret = -TARGET_EFAULT;
3298
3299 execve_end:
53a5960a 3300 for (gp = guest_argp, q = argp; *q;
992f48a0 3301 gp += sizeof(abi_ulong), q++) {
2f619698
FB
3302 if (get_user_ual(addr, gp)
3303 || !addr)
3304 break;
53a5960a
PB
3305 unlock_user(*q, addr, 0);
3306 }
3307 for (gp = guest_envp, q = envp; *q;
992f48a0 3308 gp += sizeof(abi_ulong), q++) {
2f619698
FB
3309 if (get_user_ual(addr, gp)
3310 || !addr)
3311 break;
53a5960a
PB
3312 unlock_user(*q, addr, 0);
3313 }
7854b056 3314 }
31e31b8a
FB
3315 break;
3316 case TARGET_NR_chdir:
579a97f7
FB
3317 if (!(p = lock_user_string(arg1)))
3318 goto efault;
53a5960a
PB
3319 ret = get_errno(chdir(p));
3320 unlock_user(p, arg1, 0);
31e31b8a 3321 break;
a315a145 3322#ifdef TARGET_NR_time
31e31b8a
FB
3323 case TARGET_NR_time:
3324 {
53a5960a
PB
3325 time_t host_time;
3326 ret = get_errno(time(&host_time));
2f619698
FB
3327 if (!is_error(ret)
3328 && arg1
3329 && put_user_sal(host_time, arg1))
3330 goto efault;
31e31b8a
FB
3331 }
3332 break;
a315a145 3333#endif
31e31b8a 3334 case TARGET_NR_mknod:
579a97f7
FB
3335 if (!(p = lock_user_string(arg1)))
3336 goto efault;
53a5960a
PB
3337 ret = get_errno(mknod(p, arg2, arg3));
3338 unlock_user(p, arg1, 0);
31e31b8a 3339 break;
75ac37a0
TS
3340#if defined(TARGET_NR_mknodat) && defined(__NR_mknodat)
3341 case TARGET_NR_mknodat:
579a97f7
FB
3342 if (!(p = lock_user_string(arg2)))
3343 goto efault;
3344 ret = get_errno(sys_mknodat(arg1, p, arg3, arg4));
3345 unlock_user(p, arg2, 0);
75ac37a0
TS
3346 break;
3347#endif
31e31b8a 3348 case TARGET_NR_chmod:
579a97f7
FB
3349 if (!(p = lock_user_string(arg1)))
3350 goto efault;
53a5960a
PB
3351 ret = get_errno(chmod(p, arg2));
3352 unlock_user(p, arg1, 0);
31e31b8a 3353 break;
ebc05488 3354#ifdef TARGET_NR_break
31e31b8a
FB
3355 case TARGET_NR_break:
3356 goto unimplemented;
ebc05488
FB
3357#endif
3358#ifdef TARGET_NR_oldstat
31e31b8a
FB
3359 case TARGET_NR_oldstat:
3360 goto unimplemented;
ebc05488 3361#endif
31e31b8a
FB
3362 case TARGET_NR_lseek:
3363 ret = get_errno(lseek(arg1, arg2, arg3));
3364 break;
7a3148a9
JM
3365#ifdef TARGET_NR_getxpid
3366 case TARGET_NR_getxpid:
3367#else
31e31b8a 3368 case TARGET_NR_getpid:
7a3148a9 3369#endif
31e31b8a
FB
3370 ret = get_errno(getpid());
3371 break;
3372 case TARGET_NR_mount:
80265918
TS
3373 {
3374 /* need to look at the data field */
3375 void *p2, *p3;
3376 p = lock_user_string(arg1);
3377 p2 = lock_user_string(arg2);
3378 p3 = lock_user_string(arg3);
579a97f7
FB
3379 if (!p || !p2 || !p3)
3380 ret = -TARGET_EFAULT;
3381 else
3382 /* FIXME - arg5 should be locked, but it isn't clear how to
3383 * do that since it's not guaranteed to be a NULL-terminated
3384 * string.
3385 */
3386 ret = get_errno(mount(p, p2, p3, (unsigned long)arg4, g2h(arg5)));
3387 unlock_user(p, arg1, 0);
3388 unlock_user(p2, arg2, 0);
3389 unlock_user(p3, arg3, 0);
80265918
TS
3390 break;
3391 }
e5febef5 3392#ifdef TARGET_NR_umount
31e31b8a 3393 case TARGET_NR_umount:
579a97f7
FB
3394 if (!(p = lock_user_string(arg1)))
3395 goto efault;
53a5960a
PB
3396 ret = get_errno(umount(p));
3397 unlock_user(p, arg1, 0);
31e31b8a 3398 break;
e5febef5 3399#endif
7a3148a9 3400#ifdef TARGET_NR_stime /* not on alpha */
31e31b8a
FB
3401 case TARGET_NR_stime:
3402 {
53a5960a 3403 time_t host_time;
2f619698
FB
3404 if (get_user_sal(host_time, arg1))
3405 goto efault;
53a5960a 3406 ret = get_errno(stime(&host_time));
31e31b8a
FB
3407 }
3408 break;
7a3148a9 3409#endif
31e31b8a
FB
3410 case TARGET_NR_ptrace:
3411 goto unimplemented;
7a3148a9 3412#ifdef TARGET_NR_alarm /* not on alpha */
31e31b8a
FB
3413 case TARGET_NR_alarm:
3414 ret = alarm(arg1);
3415 break;
7a3148a9 3416#endif
ebc05488 3417#ifdef TARGET_NR_oldfstat
31e31b8a
FB
3418 case TARGET_NR_oldfstat:
3419 goto unimplemented;
ebc05488 3420#endif
7a3148a9 3421#ifdef TARGET_NR_pause /* not on alpha */
31e31b8a
FB
3422 case TARGET_NR_pause:
3423 ret = get_errno(pause());
3424 break;
7a3148a9 3425#endif
e5febef5 3426#ifdef TARGET_NR_utime
31e31b8a 3427 case TARGET_NR_utime:
ebc05488 3428 {
53a5960a
PB
3429 struct utimbuf tbuf, *host_tbuf;
3430 struct target_utimbuf *target_tbuf;
3431 if (arg2) {
579a97f7
FB
3432 if (!lock_user_struct(VERIFY_READ, target_tbuf, arg2, 1))
3433 goto efault;
53a5960a
PB
3434 tbuf.actime = tswapl(target_tbuf->actime);
3435 tbuf.modtime = tswapl(target_tbuf->modtime);
3436 unlock_user_struct(target_tbuf, arg2, 0);
3437 host_tbuf = &tbuf;
f72e8ff4 3438 } else {
53a5960a 3439 host_tbuf = NULL;
f72e8ff4 3440 }
579a97f7
FB
3441 if (!(p = lock_user_string(arg1)))
3442 goto efault;
53a5960a
PB
3443 ret = get_errno(utime(p, host_tbuf));
3444 unlock_user(p, arg1, 0);
ebc05488
FB
3445 }
3446 break;
e5febef5 3447#endif
978a66ff
FB
3448 case TARGET_NR_utimes:
3449 {
978a66ff 3450 struct timeval *tvp, tv[2];
53a5960a 3451 if (arg2) {
788f5ec4
TS
3452 if (copy_from_user_timeval(&tv[0], arg2)
3453 || copy_from_user_timeval(&tv[1],
3454 arg2 + sizeof(struct target_timeval)))
3455 goto efault;
978a66ff
FB
3456 tvp = tv;
3457 } else {
3458 tvp = NULL;
3459 }
579a97f7
FB
3460 if (!(p = lock_user_string(arg1)))
3461 goto efault;
53a5960a
PB
3462 ret = get_errno(utimes(p, tvp));
3463 unlock_user(p, arg1, 0);
978a66ff
FB
3464 }
3465 break;
ebc05488 3466#ifdef TARGET_NR_stty
31e31b8a
FB
3467 case TARGET_NR_stty:
3468 goto unimplemented;
ebc05488
FB
3469#endif
3470#ifdef TARGET_NR_gtty
31e31b8a
FB
3471 case TARGET_NR_gtty:
3472 goto unimplemented;
ebc05488 3473#endif
31e31b8a 3474 case TARGET_NR_access:
579a97f7
FB
3475 if (!(p = lock_user_string(arg1)))
3476 goto efault;
53a5960a
PB
3477 ret = get_errno(access(p, arg2));
3478 unlock_user(p, arg1, 0);
31e31b8a 3479 break;
92a34c10
TS
3480#if defined(TARGET_NR_faccessat) && defined(__NR_faccessat)
3481 case TARGET_NR_faccessat:
579a97f7
FB
3482 if (!(p = lock_user_string(arg2)))
3483 goto efault;
3484 ret = get_errno(sys_faccessat(arg1, p, arg3, arg4));
3485 unlock_user(p, arg2, 0);
92a34c10
TS
3486 break;
3487#endif
7a3148a9 3488#ifdef TARGET_NR_nice /* not on alpha */
31e31b8a
FB
3489 case TARGET_NR_nice:
3490 ret = get_errno(nice(arg1));
3491 break;
7a3148a9 3492#endif
ebc05488 3493#ifdef TARGET_NR_ftime
31e31b8a
FB
3494 case TARGET_NR_ftime:
3495 goto unimplemented;
ebc05488 3496#endif
31e31b8a 3497 case TARGET_NR_sync:
04369ff2
FB
3498 sync();
3499 ret = 0;
31e31b8a
FB
3500 break;
3501 case TARGET_NR_kill:
4cb05961 3502 ret = get_errno(kill(arg1, target_to_host_signal(arg2)));
31e31b8a
FB
3503 break;
3504 case TARGET_NR_rename:
53a5960a
PB
3505 {
3506 void *p2;
3507 p = lock_user_string(arg1);
3508 p2 = lock_user_string(arg2);
579a97f7
FB
3509 if (!p || !p2)
3510 ret = -TARGET_EFAULT;
3511 else
3512 ret = get_errno(rename(p, p2));
53a5960a
PB
3513 unlock_user(p2, arg2, 0);
3514 unlock_user(p, arg1, 0);
3515 }
31e31b8a 3516 break;
722183f6
TS
3517#if defined(TARGET_NR_renameat) && defined(__NR_renameat)
3518 case TARGET_NR_renameat:
722183f6 3519 {
579a97f7 3520 void *p2;
722183f6
TS
3521 p = lock_user_string(arg2);
3522 p2 = lock_user_string(arg4);
579a97f7 3523 if (!p || !p2)
0da46a6e 3524 ret = -TARGET_EFAULT;
722183f6
TS
3525 else
3526 ret = get_errno(sys_renameat(arg1, p, arg3, p2));
579a97f7
FB
3527 unlock_user(p2, arg4, 0);
3528 unlock_user(p, arg2, 0);
722183f6
TS
3529 }
3530 break;
3531#endif
31e31b8a 3532 case TARGET_NR_mkdir:
579a97f7
FB
3533 if (!(p = lock_user_string(arg1)))
3534 goto efault;
53a5960a
PB
3535 ret = get_errno(mkdir(p, arg2));
3536 unlock_user(p, arg1, 0);
31e31b8a 3537 break;
4472ad0d
TS
3538#if defined(TARGET_NR_mkdirat) && defined(__NR_mkdirat)
3539 case TARGET_NR_mkdirat:
579a97f7
FB
3540 if (!(p = lock_user_string(arg2)))
3541 goto efault;
3542 ret = get_errno(sys_mkdirat(arg1, p, arg3));
3543 unlock_user(p, arg2, 0);
4472ad0d
TS
3544 break;
3545#endif
31e31b8a 3546 case TARGET_NR_rmdir:
579a97f7
FB
3547 if (!(p = lock_user_string(arg1)))
3548 goto efault;
53a5960a
PB
3549 ret = get_errno(rmdir(p));
3550 unlock_user(p, arg1, 0);
31e31b8a
FB
3551 break;
3552 case TARGET_NR_dup:
3553 ret = get_errno(dup(arg1));
3554 break;
3555 case TARGET_NR_pipe:
3556 {
53a5960a
PB
3557 int host_pipe[2];
3558 ret = get_errno(pipe(host_pipe));
31e31b8a 3559 if (!is_error(ret)) {
c12ab05c 3560#if defined(TARGET_MIPS)
ead9360e 3561 CPUMIPSState *env = (CPUMIPSState*)cpu_env;
d0dc7dc3 3562 env->gpr[env->current_tc][3] = host_pipe[1];
c12ab05c 3563 ret = host_pipe[0];
b5eff355
AJ
3564#elif defined(TARGET_SH4)
3565 ((CPUSH4State*)cpu_env)->gregs[1] = host_pipe[1];
3566 ret = host_pipe[0];
c12ab05c 3567#else
2f619698
FB
3568 if (put_user_s32(host_pipe[0], arg1)
3569 || put_user_s32(host_pipe[1], arg1 + sizeof(host_pipe[0])))
3570 goto efault;
c12ab05c 3571#endif
31e31b8a
FB
3572 }
3573 }
3574 break;
3575 case TARGET_NR_times:
32f36bce 3576 {
53a5960a 3577 struct target_tms *tmsp;
32f36bce
FB
3578 struct tms tms;
3579 ret = get_errno(times(&tms));
53a5960a 3580 if (arg1) {
579a97f7
FB
3581 tmsp = lock_user(VERIFY_WRITE, arg1, sizeof(struct target_tms), 0);
3582 if (!tmsp)
3583 goto efault;
c596ed17
FB
3584 tmsp->tms_utime = tswapl(host_to_target_clock_t(tms.tms_utime));
3585 tmsp->tms_stime = tswapl(host_to_target_clock_t(tms.tms_stime));
3586 tmsp->tms_cutime = tswapl(host_to_target_clock_t(tms.tms_cutime));
3587 tmsp->tms_cstime = tswapl(host_to_target_clock_t(tms.tms_cstime));
32f36bce 3588 }
c596ed17
FB
3589 if (!is_error(ret))
3590 ret = host_to_target_clock_t(ret);
32f36bce
FB
3591 }
3592 break;
ebc05488 3593#ifdef TARGET_NR_prof
31e31b8a
FB
3594 case TARGET_NR_prof:
3595 goto unimplemented;
ebc05488 3596#endif
e5febef5 3597#ifdef TARGET_NR_signal
31e31b8a
FB
3598 case TARGET_NR_signal:
3599 goto unimplemented;
e5febef5 3600#endif
31e31b8a 3601 case TARGET_NR_acct:
579a97f7
FB
3602 if (!(p = lock_user_string(arg1)))
3603 goto efault;
24836689
PB
3604 ret = get_errno(acct(path(p)));
3605 unlock_user(p, arg1, 0);
3606 break;
7a3148a9 3607#ifdef TARGET_NR_umount2 /* not on alpha */
31e31b8a 3608 case TARGET_NR_umount2:
579a97f7
FB
3609 if (!(p = lock_user_string(arg1)))
3610 goto efault;
53a5960a
PB
3611 ret = get_errno(umount2(p, arg2));
3612 unlock_user(p, arg1, 0);
31e31b8a 3613 break;
7a3148a9 3614#endif
ebc05488 3615#ifdef TARGET_NR_lock
31e31b8a
FB
3616 case TARGET_NR_lock:
3617 goto unimplemented;
ebc05488 3618#endif
31e31b8a
FB
3619 case TARGET_NR_ioctl:
3620 ret = do_ioctl(arg1, arg2, arg3);
3621 break;
3622 case TARGET_NR_fcntl:
9ee1fa2c 3623 ret = do_fcntl(arg1, arg2, arg3);
31e31b8a 3624 break;
ebc05488 3625#ifdef TARGET_NR_mpx
31e31b8a
FB
3626 case TARGET_NR_mpx:
3627 goto unimplemented;
ebc05488 3628#endif
31e31b8a
FB
3629 case TARGET_NR_setpgid:
3630 ret = get_errno(setpgid(arg1, arg2));
3631 break;
ebc05488 3632#ifdef TARGET_NR_ulimit
31e31b8a
FB
3633 case TARGET_NR_ulimit:
3634 goto unimplemented;
ebc05488
FB
3635#endif
3636#ifdef TARGET_NR_oldolduname
31e31b8a
FB
3637 case TARGET_NR_oldolduname:
3638 goto unimplemented;
ebc05488 3639#endif
31e31b8a
FB
3640 case TARGET_NR_umask:
3641 ret = get_errno(umask(arg1));
3642 break;
3643 case TARGET_NR_chroot:
579a97f7
FB
3644 if (!(p = lock_user_string(arg1)))
3645 goto efault;
53a5960a
PB
3646 ret = get_errno(chroot(p));
3647 unlock_user(p, arg1, 0);
31e31b8a
FB
3648 break;
3649 case TARGET_NR_ustat:
3650 goto unimplemented;
3651 case TARGET_NR_dup2:
3652 ret = get_errno(dup2(arg1, arg2));
3653 break;
7a3148a9 3654#ifdef TARGET_NR_getppid /* not on alpha */
31e31b8a
FB
3655 case TARGET_NR_getppid:
3656 ret = get_errno(getppid());
3657 break;
7a3148a9 3658#endif
31e31b8a
FB
3659 case TARGET_NR_getpgrp:
3660 ret = get_errno(getpgrp());
3661 break;
3662 case TARGET_NR_setsid:
3663 ret = get_errno(setsid());
3664 break;
e5febef5 3665#ifdef TARGET_NR_sigaction
31e31b8a 3666 case TARGET_NR_sigaction:
31e31b8a 3667 {
388bb21a 3668#if !defined(TARGET_MIPS)
53a5960a 3669 struct target_old_sigaction *old_act;
66fb9763 3670 struct target_sigaction act, oact, *pact;
53a5960a 3671 if (arg2) {
579a97f7
FB
3672 if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1))
3673 goto efault;
66fb9763
FB
3674 act._sa_handler = old_act->_sa_handler;
3675 target_siginitset(&act.sa_mask, old_act->sa_mask);
3676 act.sa_flags = old_act->sa_flags;
3677 act.sa_restorer = old_act->sa_restorer;
53a5960a 3678 unlock_user_struct(old_act, arg2, 0);
66fb9763
FB
3679 pact = &act;
3680 } else {
3681 pact = NULL;
3682 }
3683 ret = get_errno(do_sigaction(arg1, pact, &oact));
53a5960a 3684 if (!is_error(ret) && arg3) {
579a97f7
FB
3685 if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0))
3686 goto efault;
53a5960a
PB
3687 old_act->_sa_handler = oact._sa_handler;
3688 old_act->sa_mask = oact.sa_mask.sig[0];
3689 old_act->sa_flags = oact.sa_flags;
3690 old_act->sa_restorer = oact.sa_restorer;
3691 unlock_user_struct(old_act, arg3, 1);
66fb9763 3692 }
388bb21a 3693#else
106ec879
FB
3694 struct target_sigaction act, oact, *pact, *old_act;
3695
3696 if (arg2) {
579a97f7
FB
3697 if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1))
3698 goto efault;
106ec879
FB
3699 act._sa_handler = old_act->_sa_handler;
3700 target_siginitset(&act.sa_mask, old_act->sa_mask.sig[0]);
3701 act.sa_flags = old_act->sa_flags;
3702 unlock_user_struct(old_act, arg2, 0);
3703 pact = &act;
3704 } else {
3705 pact = NULL;
3706 }
3707
3708 ret = get_errno(do_sigaction(arg1, pact, &oact));
3709
3710 if (!is_error(ret) && arg3) {
579a97f7
FB
3711 if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0))
3712 goto efault;
106ec879
FB
3713 old_act->_sa_handler = oact._sa_handler;
3714 old_act->sa_flags = oact.sa_flags;
3715 old_act->sa_mask.sig[0] = oact.sa_mask.sig[0];
3716 old_act->sa_mask.sig[1] = 0;
3717 old_act->sa_mask.sig[2] = 0;
3718 old_act->sa_mask.sig[3] = 0;
3719 unlock_user_struct(old_act, arg3, 1);
3720 }
388bb21a 3721#endif
31e31b8a
FB
3722 }
3723 break;
e5febef5 3724#endif
66fb9763 3725 case TARGET_NR_rt_sigaction:
53a5960a
PB
3726 {
3727 struct target_sigaction *act;
3728 struct target_sigaction *oact;
3729
579a97f7
FB
3730 if (arg2) {
3731 if (!lock_user_struct(VERIFY_READ, act, arg2, 1))
3732 goto efault;
3733 } else
53a5960a 3734 act = NULL;
579a97f7
FB
3735 if (arg3) {
3736 if (!lock_user_struct(VERIFY_WRITE, oact, arg3, 0)) {
3737 ret = -TARGET_EFAULT;
3738 goto rt_sigaction_fail;
3739 }
3740 } else
53a5960a
PB
3741 oact = NULL;
3742 ret = get_errno(do_sigaction(arg1, act, oact));
579a97f7
FB
3743 rt_sigaction_fail:
3744 if (act)
53a5960a 3745 unlock_user_struct(act, arg2, 0);
579a97f7 3746 if (oact)
53a5960a
PB
3747 unlock_user_struct(oact, arg3, 1);
3748 }
66fb9763 3749 break;
7a3148a9 3750#ifdef TARGET_NR_sgetmask /* not on alpha */
31e31b8a 3751 case TARGET_NR_sgetmask:
66fb9763
FB
3752 {
3753 sigset_t cur_set;
992f48a0 3754 abi_ulong target_set;
66fb9763
FB
3755 sigprocmask(0, NULL, &cur_set);
3756 host_to_target_old_sigset(&target_set, &cur_set);
3757 ret = target_set;
3758 }
3759 break;
7a3148a9
JM
3760#endif
3761#ifdef TARGET_NR_ssetmask /* not on alpha */
31e31b8a 3762 case TARGET_NR_ssetmask:
66fb9763
FB
3763 {
3764 sigset_t set, oset, cur_set;
992f48a0 3765 abi_ulong target_set = arg1;
66fb9763
FB
3766 sigprocmask(0, NULL, &cur_set);
3767 target_to_host_old_sigset(&set, &target_set);
3768 sigorset(&set, &set, &cur_set);
3769 sigprocmask(SIG_SETMASK, &set, &oset);
3770 host_to_target_old_sigset(&target_set, &oset);
3771 ret = target_set;
3772 }
3773 break;
7a3148a9 3774#endif
e5febef5 3775#ifdef TARGET_NR_sigprocmask
66fb9763
FB
3776 case TARGET_NR_sigprocmask:
3777 {
3778 int how = arg1;
3779 sigset_t set, oldset, *set_ptr;
3b46e624 3780
53a5960a 3781 if (arg2) {
66fb9763
FB
3782 switch(how) {
3783 case TARGET_SIG_BLOCK:
3784 how = SIG_BLOCK;
3785 break;
3786 case TARGET_SIG_UNBLOCK:
3787 how = SIG_UNBLOCK;
3788 break;
3789 case TARGET_SIG_SETMASK:
3790 how = SIG_SETMASK;
3791 break;
3792 default:
0da46a6e 3793 ret = -TARGET_EINVAL;
66fb9763
FB
3794 goto fail;
3795 }
579a97f7
FB
3796 if (!(p = lock_user(VERIFY_READ, arg2, sizeof(target_sigset_t), 1)))
3797 goto efault;
53a5960a
PB
3798 target_to_host_old_sigset(&set, p);
3799 unlock_user(p, arg2, 0);
66fb9763
FB
3800 set_ptr = &set;
3801 } else {
3802 how = 0;
3803 set_ptr = NULL;
3804 }
3805 ret = get_errno(sigprocmask(arg1, set_ptr, &oldset));
53a5960a 3806 if (!is_error(ret) && arg3) {
579a97f7
FB
3807 if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0)))
3808 goto efault;
53a5960a
PB
3809 host_to_target_old_sigset(p, &oldset);
3810 unlock_user(p, arg3, sizeof(target_sigset_t));
66fb9763
FB
3811 }
3812 }
3813 break;
e5febef5 3814#endif
66fb9763
FB
3815 case TARGET_NR_rt_sigprocmask:
3816 {
3817 int how = arg1;
3818 sigset_t set, oldset, *set_ptr;
3b46e624 3819
53a5960a 3820 if (arg2) {
66fb9763
FB
3821 switch(how) {
3822 case TARGET_SIG_BLOCK:
3823 how = SIG_BLOCK;
3824 break;
3825 case TARGET_SIG_UNBLOCK:
3826 how = SIG_UNBLOCK;
3827 break;
3828 case TARGET_SIG_SETMASK:
3829 how = SIG_SETMASK;
3830 break;
3831 default:
0da46a6e 3832 ret = -TARGET_EINVAL;
66fb9763
FB
3833 goto fail;
3834 }
579a97f7
FB
3835 if (!(p = lock_user(VERIFY_READ, arg2, sizeof(target_sigset_t), 1)))
3836 goto efault;
53a5960a
PB
3837 target_to_host_sigset(&set, p);
3838 unlock_user(p, arg2, 0);
66fb9763
FB
3839 set_ptr = &set;
3840 } else {
3841 how = 0;
3842 set_ptr = NULL;
3843 }
3844 ret = get_errno(sigprocmask(how, set_ptr, &oldset));
53a5960a 3845 if (!is_error(ret) && arg3) {
579a97f7
FB
3846 if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0)))
3847 goto efault;
53a5960a
PB
3848 host_to_target_sigset(p, &oldset);
3849 unlock_user(p, arg3, sizeof(target_sigset_t));
66fb9763
FB
3850 }
3851 }
3852 break;
e5febef5 3853#ifdef TARGET_NR_sigpending
66fb9763
FB
3854 case TARGET_NR_sigpending:
3855 {
3856 sigset_t set;
3857 ret = get_errno(sigpending(&set));
3858 if (!is_error(ret)) {
579a97f7
FB
3859 if (!(p = lock_user(VERIFY_WRITE, arg1, sizeof(target_sigset_t), 0)))
3860 goto efault;
53a5960a
PB
3861 host_to_target_old_sigset(p, &set);
3862 unlock_user(p, arg1, sizeof(target_sigset_t));
66fb9763
FB
3863 }
3864 }
3865 break;
e5febef5 3866#endif
66fb9763
FB
3867 case TARGET_NR_rt_sigpending:
3868 {
3869 sigset_t set;
3870 ret = get_errno(sigpending(&set));
3871 if (!is_error(ret)) {
579a97f7
FB
3872 if (!(p = lock_user(VERIFY_WRITE, arg1, sizeof(target_sigset_t), 0)))
3873 goto efault;
53a5960a
PB
3874 host_to_target_sigset(p, &set);
3875 unlock_user(p, arg1, sizeof(target_sigset_t));
66fb9763
FB
3876 }
3877 }
3878 break;
e5febef5 3879#ifdef TARGET_NR_sigsuspend
66fb9763
FB
3880 case TARGET_NR_sigsuspend:
3881 {
3882 sigset_t set;
579a97f7
FB
3883 if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
3884 goto efault;
53a5960a
PB
3885 target_to_host_old_sigset(&set, p);
3886 unlock_user(p, arg1, 0);
66fb9763
FB
3887 ret = get_errno(sigsuspend(&set));
3888 }
3889 break;
e5febef5 3890#endif
66fb9763
FB
3891 case TARGET_NR_rt_sigsuspend:
3892 {
3893 sigset_t set;
579a97f7
FB
3894 if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
3895 goto efault;
53a5960a
PB
3896 target_to_host_sigset(&set, p);
3897 unlock_user(p, arg1, 0);
66fb9763
FB
3898 ret = get_errno(sigsuspend(&set));
3899 }
3900 break;
3901 case TARGET_NR_rt_sigtimedwait:
3902 {
66fb9763
FB
3903 sigset_t set;
3904 struct timespec uts, *puts;
3905 siginfo_t uinfo;
3b46e624 3906
579a97f7
FB
3907 if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
3908 goto efault;
53a5960a
PB
3909 target_to_host_sigset(&set, p);
3910 unlock_user(p, arg1, 0);
3911 if (arg3) {
66fb9763 3912 puts = &uts;
53a5960a 3913 target_to_host_timespec(puts, arg3);
66fb9763
FB
3914 } else {
3915 puts = NULL;
3916 }
3917 ret = get_errno(sigtimedwait(&set, &uinfo, puts));
53a5960a 3918 if (!is_error(ret) && arg2) {
e1e3f30b 3919 if (!(p = lock_user(VERIFY_WRITE, arg2, sizeof(target_siginfo_t), 0)))
579a97f7 3920 goto efault;
53a5960a 3921 host_to_target_siginfo(p, &uinfo);
e1e3f30b 3922 unlock_user(p, arg2, sizeof(target_siginfo_t));
66fb9763
FB
3923 }
3924 }
3925 break;
3926 case TARGET_NR_rt_sigqueueinfo:
3927 {
3928 siginfo_t uinfo;
579a97f7
FB
3929 if (!(p = lock_user(VERIFY_READ, arg3, sizeof(target_sigset_t), 1)))
3930 goto efault;
53a5960a
PB
3931 target_to_host_siginfo(&uinfo, p);
3932 unlock_user(p, arg1, 0);
66fb9763
FB
3933 ret = get_errno(sys_rt_sigqueueinfo(arg1, arg2, &uinfo));
3934 }
3935 break;
e5febef5 3936#ifdef TARGET_NR_sigreturn
66fb9763
FB
3937 case TARGET_NR_sigreturn:
3938 /* NOTE: ret is eax, so not transcoding must be done */
3939 ret = do_sigreturn(cpu_env);
3940 break;
e5febef5 3941#endif
66fb9763
FB
3942 case TARGET_NR_rt_sigreturn:
3943 /* NOTE: ret is eax, so not transcoding must be done */
3944 ret = do_rt_sigreturn(cpu_env);
3945 break;
31e31b8a 3946 case TARGET_NR_sethostname:
579a97f7
FB
3947 if (!(p = lock_user_string(arg1)))
3948 goto efault;
53a5960a
PB
3949 ret = get_errno(sethostname(p, arg2));
3950 unlock_user(p, arg1, 0);
31e31b8a
FB
3951 break;
3952 case TARGET_NR_setrlimit:
9de5e440
FB
3953 {
3954 /* XXX: convert resource ? */
3955 int resource = arg1;
53a5960a 3956 struct target_rlimit *target_rlim;
9de5e440 3957 struct rlimit rlim;
579a97f7
FB
3958 if (!lock_user_struct(VERIFY_READ, target_rlim, arg2, 1))
3959 goto efault;
9de5e440
FB
3960 rlim.rlim_cur = tswapl(target_rlim->rlim_cur);
3961 rlim.rlim_max = tswapl(target_rlim->rlim_max);
53a5960a 3962 unlock_user_struct(target_rlim, arg2, 0);
9de5e440
FB
3963 ret = get_errno(setrlimit(resource, &rlim));
3964 }
3965 break;
31e31b8a 3966 case TARGET_NR_getrlimit:
9de5e440
FB
3967 {
3968 /* XXX: convert resource ? */
3969 int resource = arg1;
53a5960a 3970 struct target_rlimit *target_rlim;
9de5e440 3971 struct rlimit rlim;
3b46e624 3972
9de5e440
FB
3973 ret = get_errno(getrlimit(resource, &rlim));
3974 if (!is_error(ret)) {
579a97f7
FB
3975 if (!lock_user_struct(VERIFY_WRITE, target_rlim, arg2, 0))
3976 goto efault;
53a5960a
PB
3977 rlim.rlim_cur = tswapl(target_rlim->rlim_cur);
3978 rlim.rlim_max = tswapl(target_rlim->rlim_max);
3979 unlock_user_struct(target_rlim, arg2, 1);
9de5e440
FB
3980 }
3981 }
3982 break;
31e31b8a 3983 case TARGET_NR_getrusage:
b409186b
FB
3984 {
3985 struct rusage rusage;
b409186b
FB
3986 ret = get_errno(getrusage(arg1, &rusage));
3987 if (!is_error(ret)) {
53a5960a 3988 host_to_target_rusage(arg2, &rusage);
b409186b
FB
3989 }
3990 }
3991 break;
31e31b8a
FB
3992 case TARGET_NR_gettimeofday:
3993 {
31e31b8a
FB
3994 struct timeval tv;
3995 ret = get_errno(gettimeofday(&tv, NULL));
3996 if (!is_error(ret)) {
788f5ec4
TS
3997 if (copy_to_user_timeval(arg1, &tv))
3998 goto efault;
31e31b8a
FB
3999 }
4000 }
4001 break;
4002 case TARGET_NR_settimeofday:
4003 {
31e31b8a 4004 struct timeval tv;
788f5ec4
TS
4005 if (copy_from_user_timeval(&tv, arg1))
4006 goto efault;
31e31b8a
FB
4007 ret = get_errno(settimeofday(&tv, NULL));
4008 }
4009 break;
048f6b4d 4010#ifdef TARGET_NR_select
31e31b8a 4011 case TARGET_NR_select:
f2674e31 4012 {
53a5960a 4013 struct target_sel_arg_struct *sel;
992f48a0 4014 abi_ulong inp, outp, exp, tvp;
53a5960a
PB
4015 long nsel;
4016
579a97f7
FB
4017 if (!lock_user_struct(VERIFY_READ, sel, arg1, 1))
4018 goto efault;
53a5960a
PB
4019 nsel = tswapl(sel->n);
4020 inp = tswapl(sel->inp);
4021 outp = tswapl(sel->outp);
4022 exp = tswapl(sel->exp);
4023 tvp = tswapl(sel->tvp);
4024 unlock_user_struct(sel, arg1, 0);
4025 ret = do_select(nsel, inp, outp, exp, tvp);
f2674e31
FB
4026 }
4027 break;
048f6b4d 4028#endif
31e31b8a 4029 case TARGET_NR_symlink:
53a5960a
PB
4030 {
4031 void *p2;
4032 p = lock_user_string(arg1);
4033 p2 = lock_user_string(arg2);
579a97f7
FB
4034 if (!p || !p2)
4035 ret = -TARGET_EFAULT;
4036 else
4037 ret = get_errno(symlink(p, p2));
53a5960a
PB
4038 unlock_user(p2, arg2, 0);
4039 unlock_user(p, arg1, 0);
4040 }
31e31b8a 4041 break;
f0b6243d
TS
4042#if defined(TARGET_NR_symlinkat) && defined(__NR_symlinkat)
4043 case TARGET_NR_symlinkat:
f0b6243d 4044 {
579a97f7 4045 void *p2;
f0b6243d
TS
4046 p = lock_user_string(arg1);
4047 p2 = lock_user_string(arg3);
579a97f7 4048 if (!p || !p2)
0da46a6e 4049 ret = -TARGET_EFAULT;
f0b6243d
TS
4050 else
4051 ret = get_errno(sys_symlinkat(p, arg2, p2));
579a97f7
FB
4052 unlock_user(p2, arg3, 0);
4053 unlock_user(p, arg1, 0);
f0b6243d
TS
4054 }
4055 break;
4056#endif
ebc05488 4057#ifdef TARGET_NR_oldlstat
31e31b8a
FB
4058 case TARGET_NR_oldlstat:
4059 goto unimplemented;
ebc05488 4060#endif
31e31b8a 4061 case TARGET_NR_readlink:
53a5960a
PB
4062 {
4063 void *p2;
4064 p = lock_user_string(arg1);
579a97f7
FB
4065 p2 = lock_user(VERIFY_WRITE, arg2, arg3, 0);
4066 if (!p || !p2)
4067 ret = -TARGET_EFAULT;
4068 else
4069 ret = get_errno(readlink(path(p), p2, arg3));
53a5960a
PB
4070 unlock_user(p2, arg2, ret);
4071 unlock_user(p, arg1, 0);
4072 }
31e31b8a 4073 break;
5e0ccb18
TS
4074#if defined(TARGET_NR_readlinkat) && defined(__NR_readlinkat)
4075 case TARGET_NR_readlinkat:
5e0ccb18 4076 {
579a97f7 4077 void *p2;
5e0ccb18 4078 p = lock_user_string(arg2);
579a97f7
FB
4079 p2 = lock_user(VERIFY_WRITE, arg3, arg4, 0);
4080 if (!p || !p2)
0da46a6e 4081 ret = -TARGET_EFAULT;
5e0ccb18
TS
4082 else
4083 ret = get_errno(sys_readlinkat(arg1, path(p), p2, arg4));
579a97f7
FB
4084 unlock_user(p2, arg3, ret);
4085 unlock_user(p, arg2, 0);
5e0ccb18
TS
4086 }
4087 break;
4088#endif
e5febef5 4089#ifdef TARGET_NR_uselib
31e31b8a
FB
4090 case TARGET_NR_uselib:
4091 goto unimplemented;
e5febef5
TS
4092#endif
4093#ifdef TARGET_NR_swapon
31e31b8a 4094 case TARGET_NR_swapon:
579a97f7
FB
4095 if (!(p = lock_user_string(arg1)))
4096 goto efault;
53a5960a
PB
4097 ret = get_errno(swapon(p, arg2));
4098 unlock_user(p, arg1, 0);
31e31b8a 4099 break;
e5febef5 4100#endif
31e31b8a
FB
4101 case TARGET_NR_reboot:
4102 goto unimplemented;
e5febef5 4103#ifdef TARGET_NR_readdir
31e31b8a
FB
4104 case TARGET_NR_readdir:
4105 goto unimplemented;
e5febef5
TS
4106#endif
4107#ifdef TARGET_NR_mmap
31e31b8a 4108 case TARGET_NR_mmap:
d2fd1af7 4109#if (defined(TARGET_I386) && defined(TARGET_ABI32)) || defined(TARGET_ARM) || defined(TARGET_M68K) || defined(TARGET_CRIS)
31e31b8a 4110 {
992f48a0
BS
4111 abi_ulong *v;
4112 abi_ulong v1, v2, v3, v4, v5, v6;
579a97f7
FB
4113 if (!(v = lock_user(VERIFY_READ, arg1, 6 * sizeof(abi_ulong), 1)))
4114 goto efault;
53a5960a
PB
4115 v1 = tswapl(v[0]);
4116 v2 = tswapl(v[1]);
4117 v3 = tswapl(v[2]);
4118 v4 = tswapl(v[3]);
4119 v5 = tswapl(v[4]);
4120 v6 = tswapl(v[5]);
4121 unlock_user(v, arg1, 0);
5fafdf24 4122 ret = get_errno(target_mmap(v1, v2, v3,
5286db75
FB
4123 target_to_host_bitmask(v4, mmap_flags_tbl),
4124 v5, v6));
31e31b8a 4125 }
31e31b8a 4126#else
5fafdf24
TS
4127 ret = get_errno(target_mmap(arg1, arg2, arg3,
4128 target_to_host_bitmask(arg4, mmap_flags_tbl),
6fb883e8
FB
4129 arg5,
4130 arg6));
31e31b8a 4131#endif
6fb883e8 4132 break;
e5febef5 4133#endif
a315a145 4134#ifdef TARGET_NR_mmap2
6fb883e8 4135 case TARGET_NR_mmap2:
bb7ec043 4136#ifndef MMAP_SHIFT
c573ff67 4137#define MMAP_SHIFT 12
c573ff67 4138#endif
5fafdf24
TS
4139 ret = get_errno(target_mmap(arg1, arg2, arg3,
4140 target_to_host_bitmask(arg4, mmap_flags_tbl),
5286db75 4141 arg5,
c573ff67 4142 arg6 << MMAP_SHIFT));
31e31b8a 4143 break;
a315a145 4144#endif
31e31b8a 4145 case TARGET_NR_munmap:
54936004 4146 ret = get_errno(target_munmap(arg1, arg2));
31e31b8a 4147 break;
9de5e440 4148 case TARGET_NR_mprotect:
54936004 4149 ret = get_errno(target_mprotect(arg1, arg2, arg3));
9de5e440 4150 break;
e5febef5 4151#ifdef TARGET_NR_mremap
9de5e440 4152 case TARGET_NR_mremap:
54936004 4153 ret = get_errno(target_mremap(arg1, arg2, arg3, arg4, arg5));
9de5e440 4154 break;
e5febef5 4155#endif
53a5960a 4156 /* ??? msync/mlock/munlock are broken for softmmu. */
e5febef5 4157#ifdef TARGET_NR_msync
9de5e440 4158 case TARGET_NR_msync:
53a5960a 4159 ret = get_errno(msync(g2h(arg1), arg2, arg3));
9de5e440 4160 break;
e5febef5
TS
4161#endif
4162#ifdef TARGET_NR_mlock
9de5e440 4163 case TARGET_NR_mlock:
53a5960a 4164 ret = get_errno(mlock(g2h(arg1), arg2));
9de5e440 4165 break;
e5febef5
TS
4166#endif
4167#ifdef TARGET_NR_munlock
9de5e440 4168 case TARGET_NR_munlock:
53a5960a 4169 ret = get_errno(munlock(g2h(arg1), arg2));
9de5e440 4170 break;
e5febef5
TS
4171#endif
4172#ifdef TARGET_NR_mlockall
9de5e440
FB
4173 case TARGET_NR_mlockall:
4174 ret = get_errno(mlockall(arg1));
4175 break;
e5febef5
TS
4176#endif
4177#ifdef TARGET_NR_munlockall
9de5e440
FB
4178 case TARGET_NR_munlockall:
4179 ret = get_errno(munlockall());
4180 break;
e5febef5 4181#endif
31e31b8a 4182 case TARGET_NR_truncate:
579a97f7
FB
4183 if (!(p = lock_user_string(arg1)))
4184 goto efault;
53a5960a
PB
4185 ret = get_errno(truncate(p, arg2));
4186 unlock_user(p, arg1, 0);
31e31b8a
FB
4187 break;
4188 case TARGET_NR_ftruncate:
4189 ret = get_errno(ftruncate(arg1, arg2));
4190 break;
4191 case TARGET_NR_fchmod:
4192 ret = get_errno(fchmod(arg1, arg2));
4193 break;
814d7977
TS
4194#if defined(TARGET_NR_fchmodat) && defined(__NR_fchmodat)
4195 case TARGET_NR_fchmodat:
579a97f7
FB
4196 if (!(p = lock_user_string(arg2)))
4197 goto efault;
4198 ret = get_errno(sys_fchmodat(arg1, p, arg3, arg4));
4199 unlock_user(p, arg2, 0);
814d7977
TS
4200 break;
4201#endif
31e31b8a 4202 case TARGET_NR_getpriority:
c6cda17a
TS
4203 /* libc does special remapping of the return value of
4204 * sys_getpriority() so it's just easiest to call
4205 * sys_getpriority() directly rather than through libc. */
4206 ret = sys_getpriority(arg1, arg2);
31e31b8a
FB
4207 break;
4208 case TARGET_NR_setpriority:
4209 ret = get_errno(setpriority(arg1, arg2, arg3));
4210 break;
ebc05488 4211#ifdef TARGET_NR_profil
31e31b8a
FB
4212 case TARGET_NR_profil:
4213 goto unimplemented;
ebc05488 4214#endif
31e31b8a 4215 case TARGET_NR_statfs:
579a97f7
FB
4216 if (!(p = lock_user_string(arg1)))
4217 goto efault;
53a5960a
PB
4218 ret = get_errno(statfs(path(p), &stfs));
4219 unlock_user(p, arg1, 0);
31e31b8a
FB
4220 convert_statfs:
4221 if (!is_error(ret)) {
53a5960a 4222 struct target_statfs *target_stfs;
3b46e624 4223
579a97f7
FB
4224 if (!lock_user_struct(VERIFY_WRITE, target_stfs, arg2, 0))
4225 goto efault;
4226 __put_user(stfs.f_type, &target_stfs->f_type);
4227 __put_user(stfs.f_bsize, &target_stfs->f_bsize);
4228 __put_user(stfs.f_blocks, &target_stfs->f_blocks);
4229 __put_user(stfs.f_bfree, &target_stfs->f_bfree);
4230 __put_user(stfs.f_bavail, &target_stfs->f_bavail);
4231 __put_user(stfs.f_files, &target_stfs->f_files);
4232 __put_user(stfs.f_ffree, &target_stfs->f_ffree);
4233 __put_user(stfs.f_fsid.__val[0], &target_stfs->f_fsid.val[0]);
4234 __put_user(stfs.f_fsid.__val[1], &target_stfs->f_fsid.val[1]);
4235 __put_user(stfs.f_namelen, &target_stfs->f_namelen);
53a5960a 4236 unlock_user_struct(target_stfs, arg2, 1);
31e31b8a
FB
4237 }
4238 break;
4239 case TARGET_NR_fstatfs:
56c8f68f 4240 ret = get_errno(fstatfs(arg1, &stfs));
31e31b8a 4241 goto convert_statfs;
56c8f68f
FB
4242#ifdef TARGET_NR_statfs64
4243 case TARGET_NR_statfs64:
579a97f7
FB
4244 if (!(p = lock_user_string(arg1)))
4245 goto efault;
53a5960a
PB
4246 ret = get_errno(statfs(path(p), &stfs));
4247 unlock_user(p, arg1, 0);
56c8f68f
FB
4248 convert_statfs64:
4249 if (!is_error(ret)) {
53a5960a 4250 struct target_statfs64 *target_stfs;
3b46e624 4251
579a97f7
FB
4252 if (!lock_user_struct(VERIFY_WRITE, target_stfs, arg3, 0))
4253 goto efault;
4254 __put_user(stfs.f_type, &target_stfs->f_type);
4255 __put_user(stfs.f_bsize, &target_stfs->f_bsize);
4256 __put_user(stfs.f_blocks, &target_stfs->f_blocks);
4257 __put_user(stfs.f_bfree, &target_stfs->f_bfree);
4258 __put_user(stfs.f_bavail, &target_stfs->f_bavail);
4259 __put_user(stfs.f_files, &target_stfs->f_files);
4260 __put_user(stfs.f_ffree, &target_stfs->f_ffree);
4261 __put_user(stfs.f_fsid.__val[0], &target_stfs->f_fsid.val[0]);
4262 __put_user(stfs.f_fsid.__val[1], &target_stfs->f_fsid.val[1]);
4263 __put_user(stfs.f_namelen, &target_stfs->f_namelen);
4264 unlock_user_struct(target_stfs, arg3, 1);
56c8f68f
FB
4265 }
4266 break;
4267 case TARGET_NR_fstatfs64:
4268 ret = get_errno(fstatfs(arg1, &stfs));
4269 goto convert_statfs64;
4270#endif
ebc05488 4271#ifdef TARGET_NR_ioperm
31e31b8a
FB
4272 case TARGET_NR_ioperm:
4273 goto unimplemented;
ebc05488 4274#endif
e5febef5 4275#ifdef TARGET_NR_socketcall
31e31b8a 4276 case TARGET_NR_socketcall:
53a5960a 4277 ret = do_socketcall(arg1, arg2);
31e31b8a 4278 break;
e5febef5 4279#endif
3532fa74
FB
4280#ifdef TARGET_NR_accept
4281 case TARGET_NR_accept:
1be9e1dc 4282 ret = do_accept(arg1, arg2, arg3);
3532fa74
FB
4283 break;
4284#endif
4285#ifdef TARGET_NR_bind
4286 case TARGET_NR_bind:
4287 ret = do_bind(arg1, arg2, arg3);
4288 break;
4289#endif
4290#ifdef TARGET_NR_connect
4291 case TARGET_NR_connect:
4292 ret = do_connect(arg1, arg2, arg3);
4293 break;
4294#endif
4295#ifdef TARGET_NR_getpeername
4296 case TARGET_NR_getpeername:
1be9e1dc 4297 ret = do_getpeername(arg1, arg2, arg3);
3532fa74
FB
4298 break;
4299#endif
4300#ifdef TARGET_NR_getsockname
4301 case TARGET_NR_getsockname:
1be9e1dc 4302 ret = do_getsockname(arg1, arg2, arg3);
3532fa74
FB
4303 break;
4304#endif
4305#ifdef TARGET_NR_getsockopt
4306 case TARGET_NR_getsockopt:
4307 ret = do_getsockopt(arg1, arg2, arg3, arg4, arg5);
4308 break;
4309#endif
4310#ifdef TARGET_NR_listen
4311 case TARGET_NR_listen:
1be9e1dc 4312 ret = get_errno(listen(arg1, arg2));
3532fa74
FB
4313 break;
4314#endif
4315#ifdef TARGET_NR_recv
4316 case TARGET_NR_recv:
214201bd 4317 ret = do_recvfrom(arg1, arg2, arg3, arg4, 0, 0);
3532fa74
FB
4318 break;
4319#endif
4320#ifdef TARGET_NR_recvfrom
4321 case TARGET_NR_recvfrom:
214201bd 4322 ret = do_recvfrom(arg1, arg2, arg3, arg4, arg5, arg6);
3532fa74
FB
4323 break;
4324#endif
4325#ifdef TARGET_NR_recvmsg
4326 case TARGET_NR_recvmsg:
4327 ret = do_sendrecvmsg(arg1, arg2, arg3, 0);
4328 break;
4329#endif
4330#ifdef TARGET_NR_send
4331 case TARGET_NR_send:
1be9e1dc 4332 ret = do_sendto(arg1, arg2, arg3, arg4, 0, 0);
3532fa74
FB
4333 break;
4334#endif
4335#ifdef TARGET_NR_sendmsg
4336 case TARGET_NR_sendmsg:
4337 ret = do_sendrecvmsg(arg1, arg2, arg3, 1);
4338 break;
4339#endif
4340#ifdef TARGET_NR_sendto
4341 case TARGET_NR_sendto:
1be9e1dc 4342 ret = do_sendto(arg1, arg2, arg3, arg4, arg5, arg6);
3532fa74
FB
4343 break;
4344#endif
4345#ifdef TARGET_NR_shutdown
4346 case TARGET_NR_shutdown:
1be9e1dc 4347 ret = get_errno(shutdown(arg1, arg2));
3532fa74
FB
4348 break;
4349#endif
4350#ifdef TARGET_NR_socket
4351 case TARGET_NR_socket:
4352 ret = do_socket(arg1, arg2, arg3);
4353 break;
4354#endif
4355#ifdef TARGET_NR_socketpair
4356 case TARGET_NR_socketpair:
1be9e1dc 4357 ret = do_socketpair(arg1, arg2, arg3, arg4);
3532fa74
FB
4358 break;
4359#endif
4360#ifdef TARGET_NR_setsockopt
4361 case TARGET_NR_setsockopt:
4362 ret = do_setsockopt(arg1, arg2, arg3, arg4, (socklen_t) arg5);
4363 break;
4364#endif
7494b0f9 4365
31e31b8a 4366 case TARGET_NR_syslog:
579a97f7
FB
4367 if (!(p = lock_user_string(arg2)))
4368 goto efault;
e5574487
TS
4369 ret = get_errno(sys_syslog((int)arg1, p, (int)arg3));
4370 unlock_user(p, arg2, 0);
7494b0f9
TS
4371 break;
4372
31e31b8a 4373 case TARGET_NR_setitimer:
66fb9763 4374 {
66fb9763
FB
4375 struct itimerval value, ovalue, *pvalue;
4376
53a5960a 4377 if (arg2) {
66fb9763 4378 pvalue = &value;
788f5ec4
TS
4379 if (copy_from_user_timeval(&pvalue->it_interval, arg2)
4380 || copy_from_user_timeval(&pvalue->it_value,
4381 arg2 + sizeof(struct target_timeval)))
4382 goto efault;
66fb9763
FB
4383 } else {
4384 pvalue = NULL;
4385 }
4386 ret = get_errno(setitimer(arg1, pvalue, &ovalue));
53a5960a 4387 if (!is_error(ret) && arg3) {
788f5ec4
TS
4388 if (copy_to_user_timeval(arg3,
4389 &ovalue.it_interval)
4390 || copy_to_user_timeval(arg3 + sizeof(struct target_timeval),
4391 &ovalue.it_value))
4392 goto efault;
66fb9763
FB
4393 }
4394 }
4395 break;
31e31b8a 4396 case TARGET_NR_getitimer:
66fb9763 4397 {
66fb9763 4398 struct itimerval value;
3b46e624 4399
66fb9763 4400 ret = get_errno(getitimer(arg1, &value));
53a5960a 4401 if (!is_error(ret) && arg2) {
788f5ec4
TS
4402 if (copy_to_user_timeval(arg2,
4403 &value.it_interval)
4404 || copy_to_user_timeval(arg2 + sizeof(struct target_timeval),
4405 &value.it_value))
4406 goto efault;
66fb9763
FB
4407 }
4408 }
4409 break;
31e31b8a 4410 case TARGET_NR_stat:
579a97f7
FB
4411 if (!(p = lock_user_string(arg1)))
4412 goto efault;
53a5960a
PB
4413 ret = get_errno(stat(path(p), &st));
4414 unlock_user(p, arg1, 0);
31e31b8a
FB
4415 goto do_stat;
4416 case TARGET_NR_lstat:
579a97f7
FB
4417 if (!(p = lock_user_string(arg1)))
4418 goto efault;
53a5960a
PB
4419 ret = get_errno(lstat(path(p), &st));
4420 unlock_user(p, arg1, 0);
31e31b8a
FB
4421 goto do_stat;
4422 case TARGET_NR_fstat:
4423 {
4424 ret = get_errno(fstat(arg1, &st));
4425 do_stat:
4426 if (!is_error(ret)) {
53a5960a 4427 struct target_stat *target_st;
e3584658 4428
579a97f7
FB
4429 if (!lock_user_struct(VERIFY_WRITE, target_st, arg2, 0))
4430 goto efault;
d2fd1af7
FB
4431 __put_user(st.st_dev, &target_st->st_dev);
4432 __put_user(st.st_ino, &target_st->st_ino);
4433 __put_user(st.st_mode, &target_st->st_mode);
4434 __put_user(st.st_uid, &target_st->st_uid);
4435 __put_user(st.st_gid, &target_st->st_gid);
4436 __put_user(st.st_nlink, &target_st->st_nlink);
4437 __put_user(st.st_rdev, &target_st->st_rdev);
4438 __put_user(st.st_size, &target_st->st_size);
4439 __put_user(st.st_blksize, &target_st->st_blksize);
4440 __put_user(st.st_blocks, &target_st->st_blocks);
4441 __put_user(st.st_atime, &target_st->target_st_atime);
4442 __put_user(st.st_mtime, &target_st->target_st_mtime);
4443 __put_user(st.st_ctime, &target_st->target_st_ctime);
53a5960a 4444 unlock_user_struct(target_st, arg2, 1);
31e31b8a
FB
4445 }
4446 }
4447 break;
ebc05488 4448#ifdef TARGET_NR_olduname
31e31b8a
FB
4449 case TARGET_NR_olduname:
4450 goto unimplemented;
ebc05488
FB
4451#endif
4452#ifdef TARGET_NR_iopl
31e31b8a
FB
4453 case TARGET_NR_iopl:
4454 goto unimplemented;
ebc05488 4455#endif
31e31b8a
FB
4456 case TARGET_NR_vhangup:
4457 ret = get_errno(vhangup());
4458 break;
ebc05488 4459#ifdef TARGET_NR_idle
31e31b8a
FB
4460 case TARGET_NR_idle:
4461 goto unimplemented;
42ad6ae9
FB
4462#endif
4463#ifdef TARGET_NR_syscall
4464 case TARGET_NR_syscall:
4465 ret = do_syscall(cpu_env,arg1 & 0xffff,arg2,arg3,arg4,arg5,arg6,0);
4466 break;
ebc05488 4467#endif
31e31b8a
FB
4468 case TARGET_NR_wait4:
4469 {
4470 int status;
992f48a0 4471 abi_long status_ptr = arg2;
31e31b8a 4472 struct rusage rusage, *rusage_ptr;
992f48a0 4473 abi_ulong target_rusage = arg4;
31e31b8a
FB
4474 if (target_rusage)
4475 rusage_ptr = &rusage;
4476 else
4477 rusage_ptr = NULL;
4478 ret = get_errno(wait4(arg1, &status, arg3, rusage_ptr));
4479 if (!is_error(ret)) {
2f619698
FB
4480 if (status_ptr) {
4481 if (put_user_s32(status, status_ptr))
4482 goto efault;
31e31b8a 4483 }
2f619698
FB
4484 if (target_rusage)
4485 host_to_target_rusage(target_rusage, &rusage);
31e31b8a
FB
4486 }
4487 }
4488 break;
e5febef5 4489#ifdef TARGET_NR_swapoff
31e31b8a 4490 case TARGET_NR_swapoff:
579a97f7
FB
4491 if (!(p = lock_user_string(arg1)))
4492 goto efault;
53a5960a
PB
4493 ret = get_errno(swapoff(p));
4494 unlock_user(p, arg1, 0);
31e31b8a 4495 break;
e5febef5 4496#endif
31e31b8a 4497 case TARGET_NR_sysinfo:
a5448a7d 4498 {
53a5960a 4499 struct target_sysinfo *target_value;
a5448a7d
FB
4500 struct sysinfo value;
4501 ret = get_errno(sysinfo(&value));
53a5960a 4502 if (!is_error(ret) && arg1)
a5448a7d 4503 {
579a97f7
FB
4504 if (!lock_user_struct(VERIFY_WRITE, target_value, arg1, 0))
4505 goto efault;
a5448a7d
FB
4506 __put_user(value.uptime, &target_value->uptime);
4507 __put_user(value.loads[0], &target_value->loads[0]);
4508 __put_user(value.loads[1], &target_value->loads[1]);
4509 __put_user(value.loads[2], &target_value->loads[2]);
4510 __put_user(value.totalram, &target_value->totalram);
4511 __put_user(value.freeram, &target_value->freeram);
4512 __put_user(value.sharedram, &target_value->sharedram);
4513 __put_user(value.bufferram, &target_value->bufferram);
4514 __put_user(value.totalswap, &target_value->totalswap);
4515 __put_user(value.freeswap, &target_value->freeswap);
4516 __put_user(value.procs, &target_value->procs);
4517 __put_user(value.totalhigh, &target_value->totalhigh);
4518 __put_user(value.freehigh, &target_value->freehigh);
4519 __put_user(value.mem_unit, &target_value->mem_unit);
53a5960a 4520 unlock_user_struct(target_value, arg1, 1);
a5448a7d
FB
4521 }
4522 }
4523 break;
e5febef5 4524#ifdef TARGET_NR_ipc
31e31b8a 4525 case TARGET_NR_ipc:
8853f86e
FB
4526 ret = do_ipc(arg1, arg2, arg3, arg4, arg5, arg6);
4527 break;
e5febef5 4528#endif
31e31b8a
FB
4529 case TARGET_NR_fsync:
4530 ret = get_errno(fsync(arg1));
4531 break;
31e31b8a 4532 case TARGET_NR_clone:
1b6b029e
FB
4533 ret = get_errno(do_fork(cpu_env, arg1, arg2));
4534 break;
ec86b0fb
FB
4535#ifdef __NR_exit_group
4536 /* new thread calls */
4537 case TARGET_NR_exit_group:
e9009676 4538 gdb_exit(cpu_env, arg1);
ec86b0fb
FB
4539 ret = get_errno(exit_group(arg1));
4540 break;
4541#endif
31e31b8a 4542 case TARGET_NR_setdomainname:
579a97f7
FB
4543 if (!(p = lock_user_string(arg1)))
4544 goto efault;
53a5960a
PB
4545 ret = get_errno(setdomainname(p, arg2));
4546 unlock_user(p, arg1, 0);
31e31b8a
FB
4547 break;
4548 case TARGET_NR_uname:
4549 /* no need to transcode because we use the linux syscall */
29e619b1
FB
4550 {
4551 struct new_utsname * buf;
3b46e624 4552
579a97f7
FB
4553 if (!lock_user_struct(VERIFY_WRITE, buf, arg1, 0))
4554 goto efault;
29e619b1
FB
4555 ret = get_errno(sys_uname(buf));
4556 if (!is_error(ret)) {
4557 /* Overrite the native machine name with whatever is being
4558 emulated. */
4559 strcpy (buf->machine, UNAME_MACHINE);
c5937220
PB
4560 /* Allow the user to override the reported release. */
4561 if (qemu_uname_release && *qemu_uname_release)
4562 strcpy (buf->release, qemu_uname_release);
29e619b1 4563 }
53a5960a 4564 unlock_user_struct(buf, arg1, 1);
29e619b1 4565 }
31e31b8a 4566 break;
6dbad63e 4567#ifdef TARGET_I386
31e31b8a 4568 case TARGET_NR_modify_ldt:
03acab66 4569 ret = do_modify_ldt(cpu_env, arg1, arg2, arg3);
5cd4393b 4570 break;
84409ddb 4571#if !defined(TARGET_X86_64)
5cd4393b
FB
4572 case TARGET_NR_vm86old:
4573 goto unimplemented;
4574 case TARGET_NR_vm86:
53a5960a 4575 ret = do_vm86(cpu_env, arg1, arg2);
6dbad63e 4576 break;
84409ddb 4577#endif
6dbad63e 4578#endif
31e31b8a
FB
4579 case TARGET_NR_adjtimex:
4580 goto unimplemented;
e5febef5 4581#ifdef TARGET_NR_create_module
31e31b8a 4582 case TARGET_NR_create_module:
e5febef5 4583#endif
31e31b8a
FB
4584 case TARGET_NR_init_module:
4585 case TARGET_NR_delete_module:
e5febef5 4586#ifdef TARGET_NR_get_kernel_syms
31e31b8a 4587 case TARGET_NR_get_kernel_syms:
e5febef5 4588#endif
31e31b8a
FB
4589 goto unimplemented;
4590 case TARGET_NR_quotactl:
4591 goto unimplemented;
4592 case TARGET_NR_getpgid:
4593 ret = get_errno(getpgid(arg1));
4594 break;
4595 case TARGET_NR_fchdir:
4596 ret = get_errno(fchdir(arg1));
4597 break;
84409ddb 4598#ifdef TARGET_NR_bdflush /* not on x86_64 */
31e31b8a
FB
4599 case TARGET_NR_bdflush:
4600 goto unimplemented;
84409ddb 4601#endif
e5febef5 4602#ifdef TARGET_NR_sysfs
31e31b8a
FB
4603 case TARGET_NR_sysfs:
4604 goto unimplemented;
e5febef5 4605#endif
31e31b8a 4606 case TARGET_NR_personality:
1b6b029e 4607 ret = get_errno(personality(arg1));
31e31b8a 4608 break;
e5febef5 4609#ifdef TARGET_NR_afs_syscall
31e31b8a
FB
4610 case TARGET_NR_afs_syscall:
4611 goto unimplemented;
e5febef5 4612#endif
7a3148a9 4613#ifdef TARGET_NR__llseek /* Not on alpha */
31e31b8a
FB
4614 case TARGET_NR__llseek:
4615 {
4f2ac237
FB
4616#if defined (__x86_64__)
4617 ret = get_errno(lseek(arg1, ((uint64_t )arg2 << 32) | arg3, arg5));
2f619698
FB
4618 if (put_user_s64(ret, arg4))
4619 goto efault;
4f2ac237 4620#else
31e31b8a
FB
4621 int64_t res;
4622 ret = get_errno(_llseek(arg1, arg2, arg3, &res, arg5));
2f619698
FB
4623 if (put_user_s64(res, arg4))
4624 goto efault;
4f2ac237 4625#endif
31e31b8a
FB
4626 }
4627 break;
7a3148a9 4628#endif
31e31b8a 4629 case TARGET_NR_getdents:
992f48a0 4630#if TARGET_ABI_BITS != 32
53a5960a 4631 goto unimplemented;
992f48a0 4632#elif TARGET_ABI_BITS == 32 && HOST_LONG_BITS == 64
4add45b4 4633 {
53a5960a 4634 struct target_dirent *target_dirp;
4add45b4 4635 struct dirent *dirp;
992f48a0 4636 abi_long count = arg3;
4add45b4
FB
4637
4638 dirp = malloc(count);
0da46a6e 4639 if (!dirp) {
579a97f7 4640 ret = -TARGET_ENOMEM;
0da46a6e
TS
4641 goto fail;
4642 }
3b46e624 4643
4add45b4
FB
4644 ret = get_errno(sys_getdents(arg1, dirp, count));
4645 if (!is_error(ret)) {
4646 struct dirent *de;
4647 struct target_dirent *tde;
4648 int len = ret;
4649 int reclen, treclen;
4650 int count1, tnamelen;
4651
4652 count1 = 0;
4653 de = dirp;
579a97f7
FB
4654 if (!(target_dirp = lock_user(VERIFY_WRITE, arg2, count, 0)))
4655 goto efault;
4add45b4
FB
4656 tde = target_dirp;
4657 while (len > 0) {
4658 reclen = de->d_reclen;
992f48a0 4659 treclen = reclen - (2 * (sizeof(long) - sizeof(abi_long)));
4add45b4
FB
4660 tde->d_reclen = tswap16(treclen);
4661 tde->d_ino = tswapl(de->d_ino);
4662 tde->d_off = tswapl(de->d_off);
992f48a0 4663 tnamelen = treclen - (2 * sizeof(abi_long) + 2);
4add45b4
FB
4664 if (tnamelen > 256)
4665 tnamelen = 256;
80a9d035 4666 /* XXX: may not be correct */
4add45b4
FB
4667 strncpy(tde->d_name, de->d_name, tnamelen);
4668 de = (struct dirent *)((char *)de + reclen);
4669 len -= reclen;
1c5bf3bf 4670 tde = (struct target_dirent *)((char *)tde + treclen);
4add45b4
FB
4671 count1 += treclen;
4672 }
4673 ret = count1;
579a97f7 4674 unlock_user(target_dirp, arg2, ret);
4add45b4
FB
4675 }
4676 free(dirp);
4677 }
4678#else
31e31b8a 4679 {
53a5960a 4680 struct dirent *dirp;
992f48a0 4681 abi_long count = arg3;
dab2ed99 4682
579a97f7
FB
4683 if (!(dirp = lock_user(VERIFY_WRITE, arg2, count, 0)))
4684 goto efault;
72f03900 4685 ret = get_errno(sys_getdents(arg1, dirp, count));
31e31b8a
FB
4686 if (!is_error(ret)) {
4687 struct dirent *de;
4688 int len = ret;
4689 int reclen;
4690 de = dirp;
4691 while (len > 0) {
8083a3e5 4692 reclen = de->d_reclen;
31e31b8a
FB
4693 if (reclen > len)
4694 break;
8083a3e5 4695 de->d_reclen = tswap16(reclen);
31e31b8a
FB
4696 tswapls(&de->d_ino);
4697 tswapls(&de->d_off);
4698 de = (struct dirent *)((char *)de + reclen);
4699 len -= reclen;
4700 }
4701 }
53a5960a 4702 unlock_user(dirp, arg2, ret);
31e31b8a 4703 }
4add45b4 4704#endif
31e31b8a 4705 break;
3ae43202 4706#if defined(TARGET_NR_getdents64) && defined(__NR_getdents64)
dab2ed99
FB
4707 case TARGET_NR_getdents64:
4708 {
53a5960a 4709 struct dirent64 *dirp;
992f48a0 4710 abi_long count = arg3;
579a97f7
FB
4711 if (!(dirp = lock_user(VERIFY_WRITE, arg2, count, 0)))
4712 goto efault;
dab2ed99
FB
4713 ret = get_errno(sys_getdents64(arg1, dirp, count));
4714 if (!is_error(ret)) {
4715 struct dirent64 *de;
4716 int len = ret;
4717 int reclen;
4718 de = dirp;
4719 while (len > 0) {
8083a3e5 4720 reclen = de->d_reclen;
dab2ed99
FB
4721 if (reclen > len)
4722 break;
8083a3e5 4723 de->d_reclen = tswap16(reclen);
8582a53a
FB
4724 tswap64s((uint64_t *)&de->d_ino);
4725 tswap64s((uint64_t *)&de->d_off);
dab2ed99
FB
4726 de = (struct dirent64 *)((char *)de + reclen);
4727 len -= reclen;
4728 }
4729 }
53a5960a 4730 unlock_user(dirp, arg2, ret);
dab2ed99
FB
4731 }
4732 break;
a541f297 4733#endif /* TARGET_NR_getdents64 */
e5febef5 4734#ifdef TARGET_NR__newselect
31e31b8a 4735 case TARGET_NR__newselect:
53a5960a 4736 ret = do_select(arg1, arg2, arg3, arg4, arg5);
31e31b8a 4737 break;
e5febef5
TS
4738#endif
4739#ifdef TARGET_NR_poll
9de5e440
FB
4740 case TARGET_NR_poll:
4741 {
53a5960a 4742 struct target_pollfd *target_pfd;
9de5e440
FB
4743 unsigned int nfds = arg2;
4744 int timeout = arg3;
4745 struct pollfd *pfd;
7854b056 4746 unsigned int i;
9de5e440 4747
579a97f7
FB
4748 target_pfd = lock_user(VERIFY_WRITE, arg1, sizeof(struct target_pollfd) * nfds, 1);
4749 if (!target_pfd)
4750 goto efault;
9de5e440
FB
4751 pfd = alloca(sizeof(struct pollfd) * nfds);
4752 for(i = 0; i < nfds; i++) {
5cd4393b
FB
4753 pfd[i].fd = tswap32(target_pfd[i].fd);
4754 pfd[i].events = tswap16(target_pfd[i].events);
9de5e440
FB
4755 }
4756 ret = get_errno(poll(pfd, nfds, timeout));
4757 if (!is_error(ret)) {
4758 for(i = 0; i < nfds; i++) {
5cd4393b 4759 target_pfd[i].revents = tswap16(pfd[i].revents);
9de5e440 4760 }
53a5960a
PB
4761 ret += nfds * (sizeof(struct target_pollfd)
4762 - sizeof(struct pollfd));
9de5e440 4763 }
53a5960a 4764 unlock_user(target_pfd, arg1, ret);
9de5e440
FB
4765 }
4766 break;
e5febef5 4767#endif
31e31b8a 4768 case TARGET_NR_flock:
9de5e440
FB
4769 /* NOTE: the flock constant seems to be the same for every
4770 Linux platform */
4771 ret = get_errno(flock(arg1, arg2));
31e31b8a
FB
4772 break;
4773 case TARGET_NR_readv:
4774 {
4775 int count = arg3;
31e31b8a 4776 struct iovec *vec;
31e31b8a
FB
4777
4778 vec = alloca(count * sizeof(struct iovec));
41df8411
FB
4779 if (lock_iovec(VERIFY_WRITE, vec, arg2, count, 0) < 0)
4780 goto efault;
31e31b8a 4781 ret = get_errno(readv(arg1, vec, count));
53a5960a 4782 unlock_iovec(vec, arg2, count, 1);
31e31b8a
FB
4783 }
4784 break;
4785 case TARGET_NR_writev:
4786 {
4787 int count = arg3;
31e31b8a 4788 struct iovec *vec;
31e31b8a
FB
4789
4790 vec = alloca(count * sizeof(struct iovec));
41df8411
FB
4791 if (lock_iovec(VERIFY_READ, vec, arg2, count, 1) < 0)
4792 goto efault;
31e31b8a 4793 ret = get_errno(writev(arg1, vec, count));
53a5960a 4794 unlock_iovec(vec, arg2, count, 0);
31e31b8a
FB
4795 }
4796 break;
4797 case TARGET_NR_getsid:
4798 ret = get_errno(getsid(arg1));
4799 break;
7a3148a9 4800#if defined(TARGET_NR_fdatasync) /* Not on alpha (osf_datasync ?) */
31e31b8a 4801 case TARGET_NR_fdatasync:
5cd4393b
FB
4802 ret = get_errno(fdatasync(arg1));
4803 break;
7a3148a9 4804#endif
31e31b8a 4805 case TARGET_NR__sysctl:
0da46a6e 4806 /* We don't implement this, but ENOTDIR is always a safe
29e619b1 4807 return value. */
0da46a6e
TS
4808 ret = -TARGET_ENOTDIR;
4809 break;
31e31b8a 4810 case TARGET_NR_sched_setparam:
5cd4393b 4811 {
53a5960a 4812 struct sched_param *target_schp;
5cd4393b 4813 struct sched_param schp;
53a5960a 4814
579a97f7
FB
4815 if (!lock_user_struct(VERIFY_READ, target_schp, arg2, 1))
4816 goto efault;
5cd4393b 4817 schp.sched_priority = tswap32(target_schp->sched_priority);
53a5960a 4818 unlock_user_struct(target_schp, arg2, 0);
5cd4393b
FB
4819 ret = get_errno(sched_setparam(arg1, &schp));
4820 }
4821 break;
31e31b8a 4822 case TARGET_NR_sched_getparam:
5cd4393b 4823 {
53a5960a 4824 struct sched_param *target_schp;
5cd4393b
FB
4825 struct sched_param schp;
4826 ret = get_errno(sched_getparam(arg1, &schp));
4827 if (!is_error(ret)) {
579a97f7
FB
4828 if (!lock_user_struct(VERIFY_WRITE, target_schp, arg2, 0))
4829 goto efault;
5cd4393b 4830 target_schp->sched_priority = tswap32(schp.sched_priority);
53a5960a 4831 unlock_user_struct(target_schp, arg2, 1);
5cd4393b
FB
4832 }
4833 }
4834 break;
31e31b8a 4835 case TARGET_NR_sched_setscheduler:
5cd4393b 4836 {
53a5960a 4837 struct sched_param *target_schp;
5cd4393b 4838 struct sched_param schp;
579a97f7
FB
4839 if (!lock_user_struct(VERIFY_READ, target_schp, arg3, 1))
4840 goto efault;
5cd4393b 4841 schp.sched_priority = tswap32(target_schp->sched_priority);
53a5960a 4842 unlock_user_struct(target_schp, arg3, 0);
5cd4393b
FB
4843 ret = get_errno(sched_setscheduler(arg1, arg2, &schp));
4844 }
4845 break;
31e31b8a 4846 case TARGET_NR_sched_getscheduler:
5cd4393b
FB
4847 ret = get_errno(sched_getscheduler(arg1));
4848 break;
31e31b8a
FB
4849 case TARGET_NR_sched_yield:
4850 ret = get_errno(sched_yield());
4851 break;
4852 case TARGET_NR_sched_get_priority_max:
5cd4393b
FB
4853 ret = get_errno(sched_get_priority_max(arg1));
4854 break;
31e31b8a 4855 case TARGET_NR_sched_get_priority_min:
5cd4393b
FB
4856 ret = get_errno(sched_get_priority_min(arg1));
4857 break;
31e31b8a 4858 case TARGET_NR_sched_rr_get_interval:
5cd4393b 4859 {
5cd4393b
FB
4860 struct timespec ts;
4861 ret = get_errno(sched_rr_get_interval(arg1, &ts));
4862 if (!is_error(ret)) {
53a5960a 4863 host_to_target_timespec(arg2, &ts);
5cd4393b
FB
4864 }
4865 }
4866 break;
31e31b8a 4867 case TARGET_NR_nanosleep:
1b6b029e 4868 {
1b6b029e 4869 struct timespec req, rem;
53a5960a 4870 target_to_host_timespec(&req, arg1);
1b6b029e 4871 ret = get_errno(nanosleep(&req, &rem));
53a5960a
PB
4872 if (is_error(ret) && arg2) {
4873 host_to_target_timespec(arg2, &rem);
1b6b029e
FB
4874 }
4875 }
4876 break;
e5febef5 4877#ifdef TARGET_NR_query_module
31e31b8a 4878 case TARGET_NR_query_module:
5cd4393b 4879 goto unimplemented;
e5febef5
TS
4880#endif
4881#ifdef TARGET_NR_nfsservctl
31e31b8a 4882 case TARGET_NR_nfsservctl:
5cd4393b 4883 goto unimplemented;
e5febef5 4884#endif
31e31b8a 4885 case TARGET_NR_prctl:
e5574487
TS
4886 switch (arg1)
4887 {
4888 case PR_GET_PDEATHSIG:
4889 {
4890 int deathsig;
4891 ret = get_errno(prctl(arg1, &deathsig, arg3, arg4, arg5));
2f619698
FB
4892 if (!is_error(ret) && arg2
4893 && put_user_ual(deathsig, arg2))
4894 goto efault;
e5574487
TS
4895 }
4896 break;
4897 default:
4898 ret = get_errno(prctl(arg1, arg2, arg3, arg4, arg5));
4899 break;
4900 }
39b9aae1 4901 break;
d2fd1af7
FB
4902#ifdef TARGET_NR_arch_prctl
4903 case TARGET_NR_arch_prctl:
4904#if defined(TARGET_I386) && !defined(TARGET_ABI32)
4905 ret = do_arch_prctl(cpu_env, arg1, arg2);
4906 break;
4907#else
4908 goto unimplemented;
4909#endif
4910#endif
67867308 4911#ifdef TARGET_NR_pread
31e31b8a 4912 case TARGET_NR_pread:
579a97f7
FB
4913 if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
4914 goto efault;
53a5960a
PB
4915 ret = get_errno(pread(arg1, p, arg3, arg4));
4916 unlock_user(p, arg2, ret);
206f0fa7 4917 break;
31e31b8a 4918 case TARGET_NR_pwrite:
579a97f7
FB
4919 if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
4920 goto efault;
53a5960a
PB
4921 ret = get_errno(pwrite(arg1, p, arg3, arg4));
4922 unlock_user(p, arg2, 0);
206f0fa7 4923 break;
f2c7ba15
AJ
4924#endif
4925#ifdef TARGET_NR_pread64
4926 case TARGET_NR_pread64:
4927 if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
4928 goto efault;
4929 ret = get_errno(pread64(arg1, p, arg3, target_offset64(arg4, arg5)));
4930 unlock_user(p, arg2, ret);
4931 break;
4932 case TARGET_NR_pwrite64:
4933 if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
4934 goto efault;
4935 ret = get_errno(pwrite64(arg1, p, arg3, target_offset64(arg4, arg5)));
4936 unlock_user(p, arg2, 0);
4937 break;
67867308 4938#endif
31e31b8a 4939 case TARGET_NR_getcwd:
579a97f7
FB
4940 if (!(p = lock_user(VERIFY_WRITE, arg1, arg2, 0)))
4941 goto efault;
53a5960a
PB
4942 ret = get_errno(sys_getcwd1(p, arg2));
4943 unlock_user(p, arg1, ret);
31e31b8a
FB
4944 break;
4945 case TARGET_NR_capget:
5cd4393b 4946 goto unimplemented;
31e31b8a 4947 case TARGET_NR_capset:
5cd4393b 4948 goto unimplemented;
31e31b8a 4949 case TARGET_NR_sigaltstack:
198a74de
TS
4950#if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_MIPS) || \
4951 defined(TARGET_SPARC) || defined(TARGET_PPC) || defined(TARGET_ALPHA)
579a97f7 4952 ret = do_sigaltstack(arg1, arg2, get_sp_from_cpustate((CPUState *)cpu_env));
a04e134a
TS
4953 break;
4954#else
5cd4393b 4955 goto unimplemented;
a04e134a 4956#endif
31e31b8a 4957 case TARGET_NR_sendfile:
5cd4393b 4958 goto unimplemented;
ebc05488 4959#ifdef TARGET_NR_getpmsg
31e31b8a 4960 case TARGET_NR_getpmsg:
5cd4393b 4961 goto unimplemented;
ebc05488
FB
4962#endif
4963#ifdef TARGET_NR_putpmsg
31e31b8a 4964 case TARGET_NR_putpmsg:
5cd4393b 4965 goto unimplemented;
ebc05488 4966#endif
048f6b4d 4967#ifdef TARGET_NR_vfork
31e31b8a 4968 case TARGET_NR_vfork:
1b6b029e 4969 ret = get_errno(do_fork(cpu_env, CLONE_VFORK | CLONE_VM | SIGCHLD, 0));
31e31b8a 4970 break;
048f6b4d 4971#endif
ebc05488 4972#ifdef TARGET_NR_ugetrlimit
31e31b8a 4973 case TARGET_NR_ugetrlimit:
728584be
FB
4974 {
4975 struct rlimit rlim;
4976 ret = get_errno(getrlimit(arg1, &rlim));
4977 if (!is_error(ret)) {
53a5960a 4978 struct target_rlimit *target_rlim;
579a97f7
FB
4979 if (!lock_user_struct(VERIFY_WRITE, target_rlim, arg2, 0))
4980 goto efault;
728584be
FB
4981 target_rlim->rlim_cur = tswapl(rlim.rlim_cur);
4982 target_rlim->rlim_max = tswapl(rlim.rlim_max);
53a5960a 4983 unlock_user_struct(target_rlim, arg2, 1);
728584be
FB
4984 }
4985 break;
4986 }
ebc05488 4987#endif
a315a145 4988#ifdef TARGET_NR_truncate64
31e31b8a 4989 case TARGET_NR_truncate64:
579a97f7
FB
4990 if (!(p = lock_user_string(arg1)))
4991 goto efault;
53a5960a
PB
4992 ret = target_truncate64(cpu_env, p, arg2, arg3, arg4);
4993 unlock_user(p, arg1, 0);
667f38b1 4994 break;
a315a145
FB
4995#endif
4996#ifdef TARGET_NR_ftruncate64
31e31b8a 4997 case TARGET_NR_ftruncate64:
ce4defa0 4998 ret = target_ftruncate64(cpu_env, arg1, arg2, arg3, arg4);
667f38b1 4999 break;
a315a145
FB
5000#endif
5001#ifdef TARGET_NR_stat64
31e31b8a 5002 case TARGET_NR_stat64:
579a97f7
FB
5003 if (!(p = lock_user_string(arg1)))
5004 goto efault;
53a5960a
PB
5005 ret = get_errno(stat(path(p), &st));
5006 unlock_user(p, arg1, 0);
60cd49d5 5007 goto do_stat64;
a315a145
FB
5008#endif
5009#ifdef TARGET_NR_lstat64
31e31b8a 5010 case TARGET_NR_lstat64:
579a97f7
FB
5011 if (!(p = lock_user_string(arg1)))
5012 goto efault;
53a5960a
PB
5013 ret = get_errno(lstat(path(p), &st));
5014 unlock_user(p, arg1, 0);
60cd49d5 5015 goto do_stat64;
a315a145
FB
5016#endif
5017#ifdef TARGET_NR_fstat64
31e31b8a 5018 case TARGET_NR_fstat64:
60cd49d5
FB
5019 {
5020 ret = get_errno(fstat(arg1, &st));
5021 do_stat64:
5022 if (!is_error(ret)) {
ce4defa0
PB
5023#ifdef TARGET_ARM
5024 if (((CPUARMState *)cpu_env)->eabi) {
53a5960a 5025 struct target_eabi_stat64 *target_st;
579a97f7
FB
5026
5027 if (!lock_user_struct(VERIFY_WRITE, target_st, arg2, 0))
5028 goto efault;
ce4defa0 5029 memset(target_st, 0, sizeof(struct target_eabi_stat64));
579a97f7
FB
5030 __put_user(st.st_dev, &target_st->st_dev);
5031 __put_user(st.st_ino, &target_st->st_ino);
ce4defa0 5032#ifdef TARGET_STAT64_HAS_BROKEN_ST_INO
579a97f7
FB
5033 __put_user(st.st_ino, &target_st->__st_ino);
5034#endif
5035 __put_user(st.st_mode, &target_st->st_mode);
5036 __put_user(st.st_nlink, &target_st->st_nlink);
5037 __put_user(st.st_uid, &target_st->st_uid);
5038 __put_user(st.st_gid, &target_st->st_gid);
5039 __put_user(st.st_rdev, &target_st->st_rdev);
5040 __put_user(st.st_size, &target_st->st_size);
5041 __put_user(st.st_blksize, &target_st->st_blksize);
5042 __put_user(st.st_blocks, &target_st->st_blocks);
5043 __put_user(st.st_atime, &target_st->target_st_atime);
5044 __put_user(st.st_mtime, &target_st->target_st_mtime);
5045 __put_user(st.st_ctime, &target_st->target_st_ctime);
5046 unlock_user_struct(target_st, arg2, 1);
ce4defa0
PB
5047 } else
5048#endif
5049 {
53a5960a 5050 struct target_stat64 *target_st;
579a97f7
FB
5051
5052 if (!lock_user_struct(VERIFY_WRITE, target_st, arg2, 0))
5053 goto efault;
ce4defa0 5054 memset(target_st, 0, sizeof(struct target_stat64));
579a97f7
FB
5055 __put_user(st.st_dev, &target_st->st_dev);
5056 __put_user(st.st_ino, &target_st->st_ino);
ec86b0fb 5057#ifdef TARGET_STAT64_HAS_BROKEN_ST_INO
579a97f7 5058 __put_user(st.st_ino, &target_st->__st_ino);
ce4defa0 5059#endif
579a97f7
FB
5060 __put_user(st.st_mode, &target_st->st_mode);
5061 __put_user(st.st_nlink, &target_st->st_nlink);
5062 __put_user(st.st_uid, &target_st->st_uid);
5063 __put_user(st.st_gid, &target_st->st_gid);
5064 __put_user(st.st_rdev, &target_st->st_rdev);
ce4defa0 5065 /* XXX: better use of kernel struct */
579a97f7
FB
5066 __put_user(st.st_size, &target_st->st_size);
5067 __put_user(st.st_blksize, &target_st->st_blksize);
5068 __put_user(st.st_blocks, &target_st->st_blocks);
5069 __put_user(st.st_atime, &target_st->target_st_atime);
5070 __put_user(st.st_mtime, &target_st->target_st_mtime);
5071 __put_user(st.st_ctime, &target_st->target_st_ctime);
5072 unlock_user_struct(target_st, arg2, 1);
ce4defa0 5073 }
60cd49d5
FB
5074 }
5075 }
5076 break;
a315a145 5077#endif
67867308
FB
5078#ifdef USE_UID16
5079 case TARGET_NR_lchown:
579a97f7
FB
5080 if (!(p = lock_user_string(arg1)))
5081 goto efault;
53a5960a
PB
5082 ret = get_errno(lchown(p, low2highuid(arg2), low2highgid(arg3)));
5083 unlock_user(p, arg1, 0);
67867308
FB
5084 break;
5085 case TARGET_NR_getuid:
5086 ret = get_errno(high2lowuid(getuid()));
5087 break;
5088 case TARGET_NR_getgid:
5089 ret = get_errno(high2lowgid(getgid()));
5090 break;
5091 case TARGET_NR_geteuid:
5092 ret = get_errno(high2lowuid(geteuid()));
5093 break;
5094 case TARGET_NR_getegid:
5095 ret = get_errno(high2lowgid(getegid()));
5096 break;
5097 case TARGET_NR_setreuid:
5098 ret = get_errno(setreuid(low2highuid(arg1), low2highuid(arg2)));
5099 break;
5100 case TARGET_NR_setregid:
5101 ret = get_errno(setregid(low2highgid(arg1), low2highgid(arg2)));
5102 break;
5103 case TARGET_NR_getgroups:
5104 {
5105 int gidsetsize = arg1;
53a5960a 5106 uint16_t *target_grouplist;
67867308
FB
5107 gid_t *grouplist;
5108 int i;
5109
5110 grouplist = alloca(gidsetsize * sizeof(gid_t));
5111 ret = get_errno(getgroups(gidsetsize, grouplist));
5112 if (!is_error(ret)) {
579a97f7
FB
5113 target_grouplist = lock_user(VERIFY_WRITE, arg2, gidsetsize * 2, 0);
5114 if (!target_grouplist)
5115 goto efault;
67867308
FB
5116 for(i = 0;i < gidsetsize; i++)
5117 target_grouplist[i] = tswap16(grouplist[i]);
53a5960a 5118 unlock_user(target_grouplist, arg2, gidsetsize * 2);
67867308
FB
5119 }
5120 }
5121 break;
5122 case TARGET_NR_setgroups:
5123 {
5124 int gidsetsize = arg1;
53a5960a 5125 uint16_t *target_grouplist;
67867308
FB
5126 gid_t *grouplist;
5127 int i;
5128
5129 grouplist = alloca(gidsetsize * sizeof(gid_t));
579a97f7
FB
5130 target_grouplist = lock_user(VERIFY_READ, arg2, gidsetsize * 2, 1);
5131 if (!target_grouplist) {
5132 ret = -TARGET_EFAULT;
5133 goto fail;
5134 }
67867308
FB
5135 for(i = 0;i < gidsetsize; i++)
5136 grouplist[i] = tswap16(target_grouplist[i]);
53a5960a 5137 unlock_user(target_grouplist, arg2, 0);
67867308
FB
5138 ret = get_errno(setgroups(gidsetsize, grouplist));
5139 }
5140 break;
5141 case TARGET_NR_fchown:
5142 ret = get_errno(fchown(arg1, low2highuid(arg2), low2highgid(arg3)));
5143 break;
ccfa72b7
TS
5144#if defined(TARGET_NR_fchownat) && defined(__NR_fchownat)
5145 case TARGET_NR_fchownat:
579a97f7
FB
5146 if (!(p = lock_user_string(arg2)))
5147 goto efault;
5148 ret = get_errno(sys_fchownat(arg1, p, low2highuid(arg3), low2highgid(arg4), arg5));
5149 unlock_user(p, arg2, 0);
ccfa72b7
TS
5150 break;
5151#endif
67867308
FB
5152#ifdef TARGET_NR_setresuid
5153 case TARGET_NR_setresuid:
5fafdf24
TS
5154 ret = get_errno(setresuid(low2highuid(arg1),
5155 low2highuid(arg2),
67867308
FB
5156 low2highuid(arg3)));
5157 break;
5158#endif
5159#ifdef TARGET_NR_getresuid
5160 case TARGET_NR_getresuid:
5161 {
53a5960a 5162 uid_t ruid, euid, suid;
67867308
FB
5163 ret = get_errno(getresuid(&ruid, &euid, &suid));
5164 if (!is_error(ret)) {
2f619698
FB
5165 if (put_user_u16(high2lowuid(ruid), arg1)
5166 || put_user_u16(high2lowuid(euid), arg2)
5167 || put_user_u16(high2lowuid(suid), arg3))
5168 goto efault;
67867308
FB
5169 }
5170 }
5171 break;
5172#endif
5173#ifdef TARGET_NR_getresgid
5174 case TARGET_NR_setresgid:
5fafdf24
TS
5175 ret = get_errno(setresgid(low2highgid(arg1),
5176 low2highgid(arg2),
67867308
FB
5177 low2highgid(arg3)));
5178 break;
5179#endif
5180#ifdef TARGET_NR_getresgid
5181 case TARGET_NR_getresgid:
5182 {
53a5960a 5183 gid_t rgid, egid, sgid;
67867308
FB
5184 ret = get_errno(getresgid(&rgid, &egid, &sgid));
5185 if (!is_error(ret)) {
2f619698
FB
5186 if (put_user_u16(high2lowgid(rgid), arg1)
5187 || put_user_u16(high2lowgid(egid), arg2)
5188 || put_user_u16(high2lowgid(sgid), arg3))
5189 goto efault;
67867308
FB
5190 }
5191 }
5192 break;
5193#endif
5194 case TARGET_NR_chown:
579a97f7
FB
5195 if (!(p = lock_user_string(arg1)))
5196 goto efault;
53a5960a
PB
5197 ret = get_errno(chown(p, low2highuid(arg2), low2highgid(arg3)));
5198 unlock_user(p, arg1, 0);
67867308
FB
5199 break;
5200 case TARGET_NR_setuid:
5201 ret = get_errno(setuid(low2highuid(arg1)));
5202 break;
5203 case TARGET_NR_setgid:
5204 ret = get_errno(setgid(low2highgid(arg1)));
5205 break;
5206 case TARGET_NR_setfsuid:
5207 ret = get_errno(setfsuid(arg1));
5208 break;
5209 case TARGET_NR_setfsgid:
5210 ret = get_errno(setfsgid(arg1));
5211 break;
5212#endif /* USE_UID16 */
5213
a315a145 5214#ifdef TARGET_NR_lchown32
31e31b8a 5215 case TARGET_NR_lchown32:
579a97f7
FB
5216 if (!(p = lock_user_string(arg1)))
5217 goto efault;
53a5960a
PB
5218 ret = get_errno(lchown(p, arg2, arg3));
5219 unlock_user(p, arg1, 0);
b03c60f3 5220 break;
a315a145
FB
5221#endif
5222#ifdef TARGET_NR_getuid32
31e31b8a 5223 case TARGET_NR_getuid32:
b03c60f3
FB
5224 ret = get_errno(getuid());
5225 break;
a315a145
FB
5226#endif
5227#ifdef TARGET_NR_getgid32
31e31b8a 5228 case TARGET_NR_getgid32:
b03c60f3
FB
5229 ret = get_errno(getgid());
5230 break;
a315a145
FB
5231#endif
5232#ifdef TARGET_NR_geteuid32
31e31b8a 5233 case TARGET_NR_geteuid32:
b03c60f3
FB
5234 ret = get_errno(geteuid());
5235 break;
a315a145
FB
5236#endif
5237#ifdef TARGET_NR_getegid32
31e31b8a 5238 case TARGET_NR_getegid32:
b03c60f3
FB
5239 ret = get_errno(getegid());
5240 break;
a315a145
FB
5241#endif
5242#ifdef TARGET_NR_setreuid32
31e31b8a 5243 case TARGET_NR_setreuid32:
b03c60f3
FB
5244 ret = get_errno(setreuid(arg1, arg2));
5245 break;
a315a145
FB
5246#endif
5247#ifdef TARGET_NR_setregid32
31e31b8a 5248 case TARGET_NR_setregid32:
b03c60f3
FB
5249 ret = get_errno(setregid(arg1, arg2));
5250 break;
a315a145
FB
5251#endif
5252#ifdef TARGET_NR_getgroups32
31e31b8a 5253 case TARGET_NR_getgroups32:
99c475ab
FB
5254 {
5255 int gidsetsize = arg1;
53a5960a 5256 uint32_t *target_grouplist;
99c475ab
FB
5257 gid_t *grouplist;
5258 int i;
5259
5260 grouplist = alloca(gidsetsize * sizeof(gid_t));
5261 ret = get_errno(getgroups(gidsetsize, grouplist));
5262 if (!is_error(ret)) {
579a97f7
FB
5263 target_grouplist = lock_user(VERIFY_WRITE, arg2, gidsetsize * 4, 0);
5264 if (!target_grouplist) {
5265 ret = -TARGET_EFAULT;
5266 goto fail;
5267 }
99c475ab 5268 for(i = 0;i < gidsetsize; i++)
53a5960a
PB
5269 target_grouplist[i] = tswap32(grouplist[i]);
5270 unlock_user(target_grouplist, arg2, gidsetsize * 4);
99c475ab
FB
5271 }
5272 }
5273 break;
a315a145
FB
5274#endif
5275#ifdef TARGET_NR_setgroups32
31e31b8a 5276 case TARGET_NR_setgroups32:
99c475ab
FB
5277 {
5278 int gidsetsize = arg1;
53a5960a 5279 uint32_t *target_grouplist;
99c475ab
FB
5280 gid_t *grouplist;
5281 int i;
3b46e624 5282
99c475ab 5283 grouplist = alloca(gidsetsize * sizeof(gid_t));
579a97f7
FB
5284 target_grouplist = lock_user(VERIFY_READ, arg2, gidsetsize * 4, 1);
5285 if (!target_grouplist) {
5286 ret = -TARGET_EFAULT;
5287 goto fail;
5288 }
99c475ab 5289 for(i = 0;i < gidsetsize; i++)
53a5960a
PB
5290 grouplist[i] = tswap32(target_grouplist[i]);
5291 unlock_user(target_grouplist, arg2, 0);
99c475ab
FB
5292 ret = get_errno(setgroups(gidsetsize, grouplist));
5293 }
5294 break;
a315a145
FB
5295#endif
5296#ifdef TARGET_NR_fchown32
31e31b8a 5297 case TARGET_NR_fchown32:
b03c60f3
FB
5298 ret = get_errno(fchown(arg1, arg2, arg3));
5299 break;
a315a145
FB
5300#endif
5301#ifdef TARGET_NR_setresuid32
31e31b8a 5302 case TARGET_NR_setresuid32:
b03c60f3
FB
5303 ret = get_errno(setresuid(arg1, arg2, arg3));
5304 break;
a315a145
FB
5305#endif
5306#ifdef TARGET_NR_getresuid32
31e31b8a 5307 case TARGET_NR_getresuid32:
b03c60f3 5308 {
53a5960a 5309 uid_t ruid, euid, suid;
b03c60f3
FB
5310 ret = get_errno(getresuid(&ruid, &euid, &suid));
5311 if (!is_error(ret)) {
2f619698
FB
5312 if (put_user_u32(ruid, arg1)
5313 || put_user_u32(euid, arg2)
5314 || put_user_u32(suid, arg3))
5315 goto efault;
b03c60f3
FB
5316 }
5317 }
5318 break;
a315a145
FB
5319#endif
5320#ifdef TARGET_NR_setresgid32
31e31b8a 5321 case TARGET_NR_setresgid32:
b03c60f3
FB
5322 ret = get_errno(setresgid(arg1, arg2, arg3));
5323 break;
a315a145
FB
5324#endif
5325#ifdef TARGET_NR_getresgid32
31e31b8a 5326 case TARGET_NR_getresgid32:
b03c60f3 5327 {
53a5960a 5328 gid_t rgid, egid, sgid;
b03c60f3
FB
5329 ret = get_errno(getresgid(&rgid, &egid, &sgid));
5330 if (!is_error(ret)) {
2f619698
FB
5331 if (put_user_u32(rgid, arg1)
5332 || put_user_u32(egid, arg2)
5333 || put_user_u32(sgid, arg3))
5334 goto efault;
b03c60f3
FB
5335 }
5336 }
5337 break;
a315a145
FB
5338#endif
5339#ifdef TARGET_NR_chown32
31e31b8a 5340 case TARGET_NR_chown32:
579a97f7
FB
5341 if (!(p = lock_user_string(arg1)))
5342 goto efault;
53a5960a
PB
5343 ret = get_errno(chown(p, arg2, arg3));
5344 unlock_user(p, arg1, 0);
b03c60f3 5345 break;
a315a145
FB
5346#endif
5347#ifdef TARGET_NR_setuid32
31e31b8a 5348 case TARGET_NR_setuid32:
b03c60f3
FB
5349 ret = get_errno(setuid(arg1));
5350 break;
a315a145
FB
5351#endif
5352#ifdef TARGET_NR_setgid32
31e31b8a 5353 case TARGET_NR_setgid32:
b03c60f3
FB
5354 ret = get_errno(setgid(arg1));
5355 break;
a315a145
FB
5356#endif
5357#ifdef TARGET_NR_setfsuid32
31e31b8a 5358 case TARGET_NR_setfsuid32:
b03c60f3
FB
5359 ret = get_errno(setfsuid(arg1));
5360 break;
a315a145
FB
5361#endif
5362#ifdef TARGET_NR_setfsgid32
31e31b8a 5363 case TARGET_NR_setfsgid32:
b03c60f3
FB
5364 ret = get_errno(setfsgid(arg1));
5365 break;
a315a145 5366#endif
67867308 5367
31e31b8a 5368 case TARGET_NR_pivot_root:
b03c60f3 5369 goto unimplemented;
ffa65c3b 5370#ifdef TARGET_NR_mincore
31e31b8a 5371 case TARGET_NR_mincore:
b03c60f3 5372 goto unimplemented;
ffa65c3b
FB
5373#endif
5374#ifdef TARGET_NR_madvise
31e31b8a 5375 case TARGET_NR_madvise:
24836689
PB
5376 /* A straight passthrough may not be safe because qemu sometimes
5377 turns private flie-backed mappings into anonymous mappings.
5378 This will break MADV_DONTNEED.
5379 This is a hint, so ignoring and returning success is ok. */
5380 ret = get_errno(0);
5381 break;
ffa65c3b 5382#endif
992f48a0 5383#if TARGET_ABI_BITS == 32
31e31b8a 5384 case TARGET_NR_fcntl64:
77e4672d 5385 {
b1e341eb 5386 int cmd;
77e4672d 5387 struct flock64 fl;
53a5960a 5388 struct target_flock64 *target_fl;
ce4defa0 5389#ifdef TARGET_ARM
53a5960a 5390 struct target_eabi_flock64 *target_efl;
ce4defa0 5391#endif
77e4672d 5392
b1e341eb
TS
5393 switch(arg2){
5394 case TARGET_F_GETLK64:
5395 cmd = F_GETLK64;
a7222580 5396 break;
b1e341eb
TS
5397 case TARGET_F_SETLK64:
5398 cmd = F_SETLK64;
a7222580 5399 break;
b1e341eb
TS
5400 case TARGET_F_SETLKW64:
5401 cmd = F_SETLK64;
a7222580 5402 break;
b1e341eb
TS
5403 default:
5404 cmd = arg2;
a7222580 5405 break;
b1e341eb
TS
5406 }
5407
60cd49d5 5408 switch(arg2) {
b1e341eb 5409 case TARGET_F_GETLK64:
5813427b
TS
5410#ifdef TARGET_ARM
5411 if (((CPUARMState *)cpu_env)->eabi) {
9ee1fa2c
FB
5412 if (!lock_user_struct(VERIFY_READ, target_efl, arg3, 1))
5413 goto efault;
5813427b
TS
5414 fl.l_type = tswap16(target_efl->l_type);
5415 fl.l_whence = tswap16(target_efl->l_whence);
5416 fl.l_start = tswap64(target_efl->l_start);
5417 fl.l_len = tswap64(target_efl->l_len);
5418 fl.l_pid = tswapl(target_efl->l_pid);
5419 unlock_user_struct(target_efl, arg3, 0);
5420 } else
5421#endif
5422 {
9ee1fa2c
FB
5423 if (!lock_user_struct(VERIFY_READ, target_fl, arg3, 1))
5424 goto efault;
5813427b
TS
5425 fl.l_type = tswap16(target_fl->l_type);
5426 fl.l_whence = tswap16(target_fl->l_whence);
5427 fl.l_start = tswap64(target_fl->l_start);
5428 fl.l_len = tswap64(target_fl->l_len);
5429 fl.l_pid = tswapl(target_fl->l_pid);
5430 unlock_user_struct(target_fl, arg3, 0);
5431 }
b1e341eb 5432 ret = get_errno(fcntl(arg1, cmd, &fl));
77e4672d 5433 if (ret == 0) {
ce4defa0
PB
5434#ifdef TARGET_ARM
5435 if (((CPUARMState *)cpu_env)->eabi) {
9ee1fa2c
FB
5436 if (!lock_user_struct(VERIFY_WRITE, target_efl, arg3, 0))
5437 goto efault;
ce4defa0
PB
5438 target_efl->l_type = tswap16(fl.l_type);
5439 target_efl->l_whence = tswap16(fl.l_whence);
5440 target_efl->l_start = tswap64(fl.l_start);
5441 target_efl->l_len = tswap64(fl.l_len);
5442 target_efl->l_pid = tswapl(fl.l_pid);
53a5960a 5443 unlock_user_struct(target_efl, arg3, 1);
ce4defa0
PB
5444 } else
5445#endif
5446 {
9ee1fa2c
FB
5447 if (!lock_user_struct(VERIFY_WRITE, target_fl, arg3, 0))
5448 goto efault;
ce4defa0
PB
5449 target_fl->l_type = tswap16(fl.l_type);
5450 target_fl->l_whence = tswap16(fl.l_whence);
5451 target_fl->l_start = tswap64(fl.l_start);
5452 target_fl->l_len = tswap64(fl.l_len);
5453 target_fl->l_pid = tswapl(fl.l_pid);
53a5960a 5454 unlock_user_struct(target_fl, arg3, 1);
ce4defa0 5455 }
77e4672d
FB
5456 }
5457 break;
5458
b1e341eb
TS
5459 case TARGET_F_SETLK64:
5460 case TARGET_F_SETLKW64:
ce4defa0
PB
5461#ifdef TARGET_ARM
5462 if (((CPUARMState *)cpu_env)->eabi) {
9ee1fa2c
FB
5463 if (!lock_user_struct(VERIFY_READ, target_efl, arg3, 1))
5464 goto efault;
ce4defa0
PB
5465 fl.l_type = tswap16(target_efl->l_type);
5466 fl.l_whence = tswap16(target_efl->l_whence);
5467 fl.l_start = tswap64(target_efl->l_start);
5468 fl.l_len = tswap64(target_efl->l_len);
5469 fl.l_pid = tswapl(target_efl->l_pid);
53a5960a 5470 unlock_user_struct(target_efl, arg3, 0);
ce4defa0
PB
5471 } else
5472#endif
5473 {
9ee1fa2c
FB
5474 if (!lock_user_struct(VERIFY_READ, target_fl, arg3, 1))
5475 goto efault;
ce4defa0
PB
5476 fl.l_type = tswap16(target_fl->l_type);
5477 fl.l_whence = tswap16(target_fl->l_whence);
5478 fl.l_start = tswap64(target_fl->l_start);
5479 fl.l_len = tswap64(target_fl->l_len);
5480 fl.l_pid = tswapl(target_fl->l_pid);
53a5960a 5481 unlock_user_struct(target_fl, arg3, 0);
ce4defa0 5482 }
b1e341eb 5483 ret = get_errno(fcntl(arg1, cmd, &fl));
77e4672d 5484 break;
60cd49d5 5485 default:
9ee1fa2c 5486 ret = do_fcntl(arg1, cmd, arg3);
60cd49d5
FB
5487 break;
5488 }
77e4672d
FB
5489 break;
5490 }
60cd49d5 5491#endif
7d600c80
TS
5492#ifdef TARGET_NR_cacheflush
5493 case TARGET_NR_cacheflush:
5494 /* self-modifying code is handled automatically, so nothing needed */
5495 ret = 0;
5496 break;
5497#endif
ebc05488 5498#ifdef TARGET_NR_security
31e31b8a
FB
5499 case TARGET_NR_security:
5500 goto unimplemented;
c573ff67
FB
5501#endif
5502#ifdef TARGET_NR_getpagesize
5503 case TARGET_NR_getpagesize:
5504 ret = TARGET_PAGE_SIZE;
5505 break;
ebc05488 5506#endif
31e31b8a
FB
5507 case TARGET_NR_gettid:
5508 ret = get_errno(gettid());
5509 break;
e5febef5 5510#ifdef TARGET_NR_readahead
31e31b8a 5511 case TARGET_NR_readahead:
5cd4393b 5512 goto unimplemented;
e5febef5 5513#endif
ebc05488 5514#ifdef TARGET_NR_setxattr
31e31b8a
FB
5515 case TARGET_NR_setxattr:
5516 case TARGET_NR_lsetxattr:
5517 case TARGET_NR_fsetxattr:
5518 case TARGET_NR_getxattr:
5519 case TARGET_NR_lgetxattr:
5520 case TARGET_NR_fgetxattr:
5521 case TARGET_NR_listxattr:
5522 case TARGET_NR_llistxattr:
5523 case TARGET_NR_flistxattr:
5524 case TARGET_NR_removexattr:
5525 case TARGET_NR_lremovexattr:
5526 case TARGET_NR_fremovexattr:
5cd4393b 5527 goto unimplemented_nowarn;
ebc05488
FB
5528#endif
5529#ifdef TARGET_NR_set_thread_area
5cd4393b 5530 case TARGET_NR_set_thread_area:
8d18e893 5531#if defined(TARGET_MIPS)
6f5b89a0
TS
5532 ((CPUMIPSState *) cpu_env)->tls_value = arg1;
5533 ret = 0;
5534 break;
8d18e893
FB
5535#elif defined(TARGET_I386) && defined(TARGET_ABI32)
5536 ret = do_set_thread_area(cpu_env, arg1);
5537 break;
6f5b89a0
TS
5538#else
5539 goto unimplemented_nowarn;
5540#endif
5541#endif
5542#ifdef TARGET_NR_get_thread_area
5cd4393b 5543 case TARGET_NR_get_thread_area:
8d18e893
FB
5544#if defined(TARGET_I386) && defined(TARGET_ABI32)
5545 ret = do_get_thread_area(cpu_env, arg1);
5546#else
5cd4393b 5547 goto unimplemented_nowarn;
48dc41eb 5548#endif
8d18e893 5549#endif
48dc41eb
FB
5550#ifdef TARGET_NR_getdomainname
5551 case TARGET_NR_getdomainname:
5552 goto unimplemented_nowarn;
ebc05488 5553#endif
6f5b89a0 5554
b5906f95
TS
5555#ifdef TARGET_NR_clock_gettime
5556 case TARGET_NR_clock_gettime:
5557 {
5558 struct timespec ts;
5559 ret = get_errno(clock_gettime(arg1, &ts));
5560 if (!is_error(ret)) {
5561 host_to_target_timespec(arg2, &ts);
5562 }
5563 break;
5564 }
5565#endif
5566#ifdef TARGET_NR_clock_getres
5567 case TARGET_NR_clock_getres:
5568 {
5569 struct timespec ts;
5570 ret = get_errno(clock_getres(arg1, &ts));
5571 if (!is_error(ret)) {
5572 host_to_target_timespec(arg2, &ts);
5573 }
5574 break;
5575 }
5576#endif
63d7651b
PB
5577#ifdef TARGET_NR_clock_nanosleep
5578 case TARGET_NR_clock_nanosleep:
5579 {
5580 struct timespec ts;
5581 target_to_host_timespec(&ts, arg3);
5582 ret = get_errno(clock_nanosleep(arg1, arg2, &ts, arg4 ? &ts : NULL));
5583 if (arg4)
5584 host_to_target_timespec(arg4, &ts);
5585 break;
5586 }
5587#endif
b5906f95 5588
6f5b89a0
TS
5589#if defined(TARGET_NR_set_tid_address) && defined(__NR_set_tid_address)
5590 case TARGET_NR_set_tid_address:
579a97f7
FB
5591 ret = get_errno(set_tid_address((int *)g2h(arg1)));
5592 break;
6f5b89a0
TS
5593#endif
5594
3ae43202 5595#if defined(TARGET_NR_tkill) && defined(__NR_tkill)
4cae1d16 5596 case TARGET_NR_tkill:
4cb05961 5597 ret = get_errno(sys_tkill((int)arg1, target_to_host_signal(arg2)));
4cae1d16
TS
5598 break;
5599#endif
5600
3ae43202 5601#if defined(TARGET_NR_tgkill) && defined(__NR_tgkill)
71455574 5602 case TARGET_NR_tgkill:
4cb05961
PB
5603 ret = get_errno(sys_tgkill((int)arg1, (int)arg2,
5604 target_to_host_signal(arg3)));
71455574
TS
5605 break;
5606#endif
5607
4f2b1fe8
TS
5608#ifdef TARGET_NR_set_robust_list
5609 case TARGET_NR_set_robust_list:
5610 goto unimplemented_nowarn;
5611#endif
5612
9007f0ef
TS
5613#if defined(TARGET_NR_utimensat) && defined(__NR_utimensat)
5614 case TARGET_NR_utimensat:
5615 {
5616 struct timespec ts[2];
5617 target_to_host_timespec(ts, arg3);
5618 target_to_host_timespec(ts+1, arg3+sizeof(struct target_timespec));
5619 if (!arg2)
5620 ret = get_errno(sys_utimensat(arg1, NULL, ts, arg4));
5621 else {
579a97f7 5622 if (!(p = lock_user_string(arg2))) {
0da46a6e 5623 ret = -TARGET_EFAULT;
579a97f7
FB
5624 goto fail;
5625 }
5626 ret = get_errno(sys_utimensat(arg1, path(p), ts, arg4));
5627 unlock_user(p, arg2, 0);
9007f0ef
TS
5628 }
5629 }
5630 break;
5631#endif
bd0c5661
PB
5632#if defined(USE_NPTL)
5633 case TARGET_NR_futex:
5634 ret = do_futex(arg1, arg2, arg3, arg4, arg5, arg6);
5635 break;
5636#endif
9007f0ef 5637
31e31b8a
FB
5638 default:
5639 unimplemented:
5cd4393b 5640 gemu_log("qemu: Unsupported syscall: %d\n", num);
4f2b1fe8 5641#if defined(TARGET_NR_setxattr) || defined(TARGET_NR_get_thread_area) || defined(TARGET_NR_getdomainname) || defined(TARGET_NR_set_robust_list)
5cd4393b 5642 unimplemented_nowarn:
80a9d035 5643#endif
0da46a6e 5644 ret = -TARGET_ENOSYS;
31e31b8a
FB
5645 break;
5646 }
579a97f7 5647fail:
c573ff67
FB
5648#ifdef DEBUG
5649 gemu_log(" = %ld\n", ret);
5650#endif
b92c47c1
TS
5651 if(do_strace)
5652 print_syscall_ret(num, ret);
31e31b8a 5653 return ret;
579a97f7
FB
5654efault:
5655 ret = -TARGET_EFAULT;
5656 goto fail;
31e31b8a 5657}