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