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