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