blob: cf0834f77936aa5723b8cd569c099b6c1455eacb [file] [log] [blame]
bellard31e31b82003-02-18 22:55:36 +00001/*
2 * Linux syscalls
ths5fafdf22007-09-16 21:08:06 +00003 *
bellard31e31b82003-02-18 22:55:36 +00004 * Copyright (c) 2003 Fabrice Bellard
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20#include <stdlib.h>
21#include <stdio.h>
22#include <stdarg.h>
bellard04369ff2003-03-20 22:33:23 +000023#include <string.h>
bellard31e31b82003-02-18 22:55:36 +000024#include <elf.h>
25#include <endian.h>
26#include <errno.h>
27#include <unistd.h>
28#include <fcntl.h>
bellard7854b052003-03-29 17:22:23 +000029#include <time.h>
pbrook82e671d2008-06-09 12:10:22 +000030#include <limits.h>
bellard31e31b82003-02-18 22:55:36 +000031#include <sys/types.h>
thsd08d3bb2007-03-19 13:09:22 +000032#include <sys/ipc.h>
33#include <sys/msg.h>
bellard31e31b82003-02-18 22:55:36 +000034#include <sys/wait.h>
35#include <sys/time.h>
36#include <sys/stat.h>
37#include <sys/mount.h>
ths39b9aae2007-02-11 18:36:44 +000038#include <sys/prctl.h>
bellard31e31b82003-02-18 22:55:36 +000039#include <sys/resource.h>
40#include <sys/mman.h>
41#include <sys/swap.h>
42#include <signal.h>
43#include <sched.h>
44#include <sys/socket.h>
45#include <sys/uio.h>
bellard9de5e442003-03-23 16:49:39 +000046#include <sys/poll.h>
bellard32f36bc2003-03-30 21:29:48 +000047#include <sys/times.h>
bellard8853f862004-02-22 14:57:26 +000048#include <sys/shm.h>
thsfa294812007-02-02 22:05:00 +000049#include <sys/sem.h>
bellard56c8f682005-11-28 22:28:41 +000050#include <sys/statfs.h>
bellardebc05482003-09-30 21:08:41 +000051#include <utime.h>
bellarda5448a72004-06-19 16:59:03 +000052#include <sys/sysinfo.h>
bellard72f03902003-02-18 23:33:18 +000053//#include <sys/user.h>
bellard8853f862004-02-22 14:57:26 +000054#include <netinet/ip.h>
bellard7854b052003-03-29 17:22:23 +000055#include <netinet/tcp.h>
aurel320b6d3ae2008-09-15 07:43:43 +000056#include <qemu-common.h>
bellard31e31b82003-02-18 22:55:36 +000057
58#define termios host_termios
59#define winsize host_winsize
60#define termio host_termio
bellard04369ff2003-03-20 22:33:23 +000061#define sgttyb host_sgttyb /* same as target */
62#define tchars host_tchars /* same as target */
63#define ltchars host_ltchars /* same as target */
bellard31e31b82003-02-18 22:55:36 +000064
65#include <linux/termios.h>
66#include <linux/unistd.h>
67#include <linux/utsname.h>
68#include <linux/cdrom.h>
69#include <linux/hdreg.h>
70#include <linux/soundcard.h>
bellard19b84f32003-05-08 15:41:49 +000071#include <linux/kd.h>
balrog8fbd6b52008-09-20 03:03:09 +000072#include <linux/mtio.h>
pbrookd7e40362008-05-23 16:06:43 +000073#include "linux_loop.h"
bellard31e31b82003-02-18 22:55:36 +000074
bellard3ef693a2003-03-23 20:17:16 +000075#include "qemu.h"
balrog526ccb72008-07-16 12:13:52 +000076#include "qemu-common.h"
bellard31e31b82003-02-18 22:55:36 +000077
pbrook30813ce2008-06-02 15:45:44 +000078#if defined(USE_NPTL)
79#include <linux/futex.h>
pbrookd865bab2008-06-07 22:12:17 +000080#define CLONE_NPTL_FLAGS2 (CLONE_SETTLS | \
81 CLONE_PARENT_SETTID | CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID)
82#else
83/* XXX: Hardcode the above values. */
84#define CLONE_NPTL_FLAGS2 0
pbrook30813ce2008-06-02 15:45:44 +000085#endif
86
bellard72f03902003-02-18 23:33:18 +000087//#define DEBUG
bellard31e31b82003-02-18 22:55:36 +000088
pbrooke6e59062006-10-22 00:18:54 +000089#if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_SPARC) \
ths48733d12007-10-08 13:36:46 +000090 || defined(TARGET_M68K) || defined(TARGET_SH4) || defined(TARGET_CRIS)
bellard67867302003-11-23 17:05:30 +000091/* 16 bit uid wrappers emulation */
92#define USE_UID16
93#endif
94
bellard1a9353d2003-03-16 20:28:50 +000095//#include <linux/msdos_fs.h>
aurel326556a832008-10-13 21:08:17 +000096#define VFAT_IOCTL_READDIR_BOTH _IOR('r', 1, struct linux_dirent [2])
97#define VFAT_IOCTL_READDIR_SHORT _IOR('r', 2, struct linux_dirent [2])
bellard1a9353d2003-03-16 20:28:50 +000098
bellard70a194b2003-08-11 22:20:16 +000099
bellard70a194b2003-08-11 22:20:16 +0000100#undef _syscall0
101#undef _syscall1
102#undef _syscall2
103#undef _syscall3
104#undef _syscall4
105#undef _syscall5
bellard83fcb512006-06-14 13:37:16 +0000106#undef _syscall6
bellard70a194b2003-08-11 22:20:16 +0000107
bellard83fcb512006-06-14 13:37:16 +0000108#define _syscall0(type,name) \
blueswir18fcd3692008-08-17 20:26:25 +0000109static type name (void) \
bellard83fcb512006-06-14 13:37:16 +0000110{ \
111 return syscall(__NR_##name); \
bellard70a194b2003-08-11 22:20:16 +0000112}
113
bellard83fcb512006-06-14 13:37:16 +0000114#define _syscall1(type,name,type1,arg1) \
blueswir18fcd3692008-08-17 20:26:25 +0000115static type name (type1 arg1) \
bellard83fcb512006-06-14 13:37:16 +0000116{ \
117 return syscall(__NR_##name, arg1); \
bellard70a194b2003-08-11 22:20:16 +0000118}
119
bellard83fcb512006-06-14 13:37:16 +0000120#define _syscall2(type,name,type1,arg1,type2,arg2) \
blueswir18fcd3692008-08-17 20:26:25 +0000121static type name (type1 arg1,type2 arg2) \
bellard83fcb512006-06-14 13:37:16 +0000122{ \
123 return syscall(__NR_##name, arg1, arg2); \
bellard70a194b2003-08-11 22:20:16 +0000124}
125
bellard83fcb512006-06-14 13:37:16 +0000126#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \
blueswir18fcd3692008-08-17 20:26:25 +0000127static type name (type1 arg1,type2 arg2,type3 arg3) \
bellard83fcb512006-06-14 13:37:16 +0000128{ \
129 return syscall(__NR_##name, arg1, arg2, arg3); \
bellard70a194b2003-08-11 22:20:16 +0000130}
131
bellard83fcb512006-06-14 13:37:16 +0000132#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \
blueswir18fcd3692008-08-17 20:26:25 +0000133static type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4) \
bellard83fcb512006-06-14 13:37:16 +0000134{ \
135 return syscall(__NR_##name, arg1, arg2, arg3, arg4); \
bellard70a194b2003-08-11 22:20:16 +0000136}
137
bellard83fcb512006-06-14 13:37:16 +0000138#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
139 type5,arg5) \
blueswir18fcd3692008-08-17 20:26:25 +0000140static type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \
bellard83fcb512006-06-14 13:37:16 +0000141{ \
142 return syscall(__NR_##name, arg1, arg2, arg3, arg4, arg5); \
bellard70a194b2003-08-11 22:20:16 +0000143}
bellard83fcb512006-06-14 13:37:16 +0000144
145
146#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
147 type5,arg5,type6,arg6) \
blueswir18fcd3692008-08-17 20:26:25 +0000148static type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5, \
149 type6 arg6) \
bellard83fcb512006-06-14 13:37:16 +0000150{ \
151 return syscall(__NR_##name, arg1, arg2, arg3, arg4, arg5, arg6); \
152}
153
bellard70a194b2003-08-11 22:20:16 +0000154
bellard31e31b82003-02-18 22:55:36 +0000155#define __NR_sys_uname __NR_uname
ths92a34c12007-09-24 09:27:49 +0000156#define __NR_sys_faccessat __NR_faccessat
ths814d7972007-09-24 09:26:51 +0000157#define __NR_sys_fchmodat __NR_fchmodat
thsccfa72b2007-09-24 09:23:34 +0000158#define __NR_sys_fchownat __NR_fchownat
balrog6a24a772008-09-20 02:23:36 +0000159#define __NR_sys_fstatat64 __NR_fstatat64
balrogac8a6552008-09-20 02:25:39 +0000160#define __NR_sys_futimesat __NR_futimesat
bellard72f03902003-02-18 23:33:18 +0000161#define __NR_sys_getcwd1 __NR_getcwd
bellard72f03902003-02-18 23:33:18 +0000162#define __NR_sys_getdents __NR_getdents
bellarddab2ed92003-03-22 15:23:14 +0000163#define __NR_sys_getdents64 __NR_getdents64
thsc6cda172007-10-09 03:42:34 +0000164#define __NR_sys_getpriority __NR_getpriority
ths64f0ce42007-09-24 09:25:06 +0000165#define __NR_sys_linkat __NR_linkat
ths4472ad02007-09-24 09:22:32 +0000166#define __NR_sys_mkdirat __NR_mkdirat
ths75ac37a2007-09-24 09:23:05 +0000167#define __NR_sys_mknodat __NR_mknodat
ths82424832007-09-24 09:21:55 +0000168#define __NR_sys_openat __NR_openat
ths5e0ccb12007-09-24 09:26:10 +0000169#define __NR_sys_readlinkat __NR_readlinkat
ths722183f2007-09-24 09:24:37 +0000170#define __NR_sys_renameat __NR_renameat
bellard66fb9762003-03-23 01:06:05 +0000171#define __NR_sys_rt_sigqueueinfo __NR_rt_sigqueueinfo
thsf0b62432007-09-24 09:25:40 +0000172#define __NR_sys_symlinkat __NR_symlinkat
ths7494b0f2007-02-11 18:26:53 +0000173#define __NR_sys_syslog __NR_syslog
ths71455572007-06-21 21:45:30 +0000174#define __NR_sys_tgkill __NR_tgkill
ths4cae1d12007-07-12 11:06:53 +0000175#define __NR_sys_tkill __NR_tkill
ths8170f562007-09-24 09:24:11 +0000176#define __NR_sys_unlinkat __NR_unlinkat
ths9007f0e2007-09-25 17:50:37 +0000177#define __NR_sys_utimensat __NR_utimensat
pbrookbd0c5662008-05-29 14:34:11 +0000178#define __NR_sys_futex __NR_futex
aurel3239b59762008-10-01 21:46:50 +0000179#define __NR_sys_inotify_init __NR_inotify_init
180#define __NR_sys_inotify_add_watch __NR_inotify_add_watch
181#define __NR_sys_inotify_rm_watch __NR_inotify_rm_watch
bellard31e31b82003-02-18 22:55:36 +0000182
bellardbc51c5c2004-03-17 23:46:04 +0000183#if defined(__alpha__) || defined (__ia64__) || defined(__x86_64__)
bellard9af9eaa2003-04-07 21:34:41 +0000184#define __NR__llseek __NR_lseek
185#endif
186
bellard72f03902003-02-18 23:33:18 +0000187#ifdef __NR_gettid
bellard31e31b82003-02-18 22:55:36 +0000188_syscall0(int, gettid)
bellard72f03902003-02-18 23:33:18 +0000189#else
ths0da46a62007-10-20 20:23:07 +0000190/* This is a replacement for the host gettid() and must return a host
191 errno. */
bellard72f03902003-02-18 23:33:18 +0000192static int gettid(void) {
193 return -ENOSYS;
194}
195#endif
bellard31e31b82003-02-18 22:55:36 +0000196_syscall1(int,sys_uname,struct new_utsname *,buf)
ths92a34c12007-09-24 09:27:49 +0000197#if defined(TARGET_NR_faccessat) && defined(__NR_faccessat)
198_syscall4(int,sys_faccessat,int,dirfd,const char *,pathname,int,mode,int,flags)
199#endif
ths814d7972007-09-24 09:26:51 +0000200#if defined(TARGET_NR_fchmodat) && defined(__NR_fchmodat)
201_syscall4(int,sys_fchmodat,int,dirfd,const char *,pathname,
202 mode_t,mode,int,flags)
203#endif
blueswir14583f582008-08-24 10:35:55 +0000204#if defined(TARGET_NR_fchownat) && defined(__NR_fchownat) && defined(USE_UID16)
thsccfa72b2007-09-24 09:23:34 +0000205_syscall5(int,sys_fchownat,int,dirfd,const char *,pathname,
206 uid_t,owner,gid_t,group,int,flags)
207#endif
balrog6a24a772008-09-20 02:23:36 +0000208#if defined(TARGET_NR_fstatat64) && defined(__NR_fstatat64)
209_syscall4(int,sys_fstatat64,int,dirfd,const char *,pathname,
210 struct stat *,buf,int,flags)
211#endif
balrogac8a6552008-09-20 02:25:39 +0000212#if defined(TARGET_NR_futimesat) && defined(__NR_futimesat)
213_syscall3(int,sys_futimesat,int,dirfd,const char *,pathname,
214 const struct timeval *,times)
215#endif
bellard72f03902003-02-18 23:33:18 +0000216_syscall2(int,sys_getcwd1,char *,buf,size_t,size)
blueswir14583f582008-08-24 10:35:55 +0000217#if TARGET_ABI_BITS == 32
aurel326556a832008-10-13 21:08:17 +0000218_syscall3(int, sys_getdents, uint, fd, struct linux_dirent *, dirp, uint, count);
blueswir14583f582008-08-24 10:35:55 +0000219#endif
ths3ae43202007-09-16 21:39:48 +0000220#if defined(TARGET_NR_getdents64) && defined(__NR_getdents64)
aurel326556a832008-10-13 21:08:17 +0000221_syscall3(int, sys_getdents64, uint, fd, struct linux_dirent64 *, dirp, uint, count);
ths3ae43202007-09-16 21:39:48 +0000222#endif
thsc6cda172007-10-09 03:42:34 +0000223_syscall2(int, sys_getpriority, int, which, int, who);
blueswir18fcd3692008-08-17 20:26:25 +0000224#if !defined (__x86_64__)
bellard31e31b82003-02-18 22:55:36 +0000225_syscall5(int, _llseek, uint, fd, ulong, hi, ulong, lo,
226 loff_t *, res, uint, wh);
blueswir18fcd3692008-08-17 20:26:25 +0000227#endif
ths64f0ce42007-09-24 09:25:06 +0000228#if defined(TARGET_NR_linkat) && defined(__NR_linkat)
229_syscall5(int,sys_linkat,int,olddirfd,const char *,oldpath,
230 int,newdirfd,const char *,newpath,int,flags)
231#endif
ths4472ad02007-09-24 09:22:32 +0000232#if defined(TARGET_NR_mkdirat) && defined(__NR_mkdirat)
233_syscall3(int,sys_mkdirat,int,dirfd,const char *,pathname,mode_t,mode)
234#endif
ths75ac37a2007-09-24 09:23:05 +0000235#if defined(TARGET_NR_mknodat) && defined(__NR_mknodat)
236_syscall4(int,sys_mknodat,int,dirfd,const char *,pathname,
237 mode_t,mode,dev_t,dev)
238#endif
ths82424832007-09-24 09:21:55 +0000239#if defined(TARGET_NR_openat) && defined(__NR_openat)
240_syscall4(int,sys_openat,int,dirfd,const char *,pathname,int,flags,mode_t,mode)
241#endif
ths5e0ccb12007-09-24 09:26:10 +0000242#if defined(TARGET_NR_readlinkat) && defined(__NR_readlinkat)
243_syscall4(int,sys_readlinkat,int,dirfd,const char *,pathname,
244 char *,buf,size_t,bufsize)
245#endif
ths722183f2007-09-24 09:24:37 +0000246#if defined(TARGET_NR_renameat) && defined(__NR_renameat)
247_syscall4(int,sys_renameat,int,olddirfd,const char *,oldpath,
248 int,newdirfd,const char *,newpath)
249#endif
bellard66fb9762003-03-23 01:06:05 +0000250_syscall3(int,sys_rt_sigqueueinfo,int,pid,int,sig,siginfo_t *,uinfo)
thsb51eaa82007-09-25 16:09:22 +0000251#if defined(TARGET_NR_symlinkat) && defined(__NR_symlinkat)
thsf0b62432007-09-24 09:25:40 +0000252_syscall3(int,sys_symlinkat,const char *,oldpath,
253 int,newdirfd,const char *,newpath)
254#endif
ths7494b0f2007-02-11 18:26:53 +0000255_syscall3(int,sys_syslog,int,type,char*,bufp,int,len)
ths3ae43202007-09-16 21:39:48 +0000256#if defined(TARGET_NR_tgkill) && defined(__NR_tgkill)
ths71455572007-06-21 21:45:30 +0000257_syscall3(int,sys_tgkill,int,tgid,int,pid,int,sig)
ths4cae1d12007-07-12 11:06:53 +0000258#endif
ths3ae43202007-09-16 21:39:48 +0000259#if defined(TARGET_NR_tkill) && defined(__NR_tkill)
ths4cae1d12007-07-12 11:06:53 +0000260_syscall2(int,sys_tkill,int,tid,int,sig)
261#endif
bellardec86b0f2003-04-11 00:15:04 +0000262#ifdef __NR_exit_group
263_syscall1(int,exit_group,int,error_code)
264#endif
ths6f5b89a2007-03-02 20:48:00 +0000265#if defined(TARGET_NR_set_tid_address) && defined(__NR_set_tid_address)
266_syscall1(int,set_tid_address,int *,tidptr)
267#endif
ths8170f562007-09-24 09:24:11 +0000268#if defined(TARGET_NR_unlinkat) && defined(__NR_unlinkat)
269_syscall3(int,sys_unlinkat,int,dirfd,const char *,pathname,int,flags)
270#endif
ths9007f0e2007-09-25 17:50:37 +0000271#if defined(TARGET_NR_utimensat) && defined(__NR_utimensat)
272_syscall4(int,sys_utimensat,int,dirfd,const char *,pathname,
273 const struct timespec *,tsp,int,flags)
274#endif
aurel3239b59762008-10-01 21:46:50 +0000275#if defined(TARGET_NR_inotify_init) && defined(__NR_inotify_init)
276_syscall0(int,sys_inotify_init)
277#endif
278#if defined(TARGET_NR_inotify_add_watch) && defined(__NR_inotify_add_watch)
279_syscall3(int,sys_inotify_add_watch,int,fd,const char *,pathname,uint32_t,mask)
280#endif
281#if defined(TARGET_NR_inotify_rm_watch) && defined(__NR_inotify_rm_watch)
282_syscall2(int,sys_inotify_rm_watch,int,fd,uint32_t,wd)
283#endif
blueswir18fcd3692008-08-17 20:26:25 +0000284#if defined(USE_NPTL)
pbrookbd0c5662008-05-29 14:34:11 +0000285#if defined(TARGET_NR_futex) && defined(__NR_futex)
286_syscall6(int,sys_futex,int *,uaddr,int,op,int,val,
287 const struct timespec *,timeout,int *,uaddr2,int,val3)
blueswir18fcd3692008-08-17 20:26:25 +0000288#endif
pbrookbd0c5662008-05-29 14:34:11 +0000289#endif
bellard66fb9762003-03-23 01:06:05 +0000290
291extern int personality(int);
bellard9de5e442003-03-23 16:49:39 +0000292extern int flock(int, int);
293extern int setfsuid(int);
294extern int setfsgid(int);
bellard19b84f32003-05-08 15:41:49 +0000295extern int setgroups(int, gid_t *);
bellard31e31b82003-02-18 22:55:36 +0000296
thsb92c47c2007-11-01 00:07:38 +0000297#define ERRNO_TABLE_SIZE 1200
298
299/* target_to_host_errno_table[] is initialized from
300 * host_to_target_errno_table[] in syscall_init(). */
301static uint16_t target_to_host_errno_table[ERRNO_TABLE_SIZE] = {
302};
303
ths637947f2007-06-01 12:09:19 +0000304/*
thsfe8f0962007-07-12 10:59:21 +0000305 * This list is the union of errno values overridden in asm-<arch>/errno.h
ths637947f2007-06-01 12:09:19 +0000306 * minus the errnos that are not actually generic to all archs.
307 */
thsb92c47c2007-11-01 00:07:38 +0000308static uint16_t host_to_target_errno_table[ERRNO_TABLE_SIZE] = {
ths637947f2007-06-01 12:09:19 +0000309 [EIDRM] = TARGET_EIDRM,
310 [ECHRNG] = TARGET_ECHRNG,
311 [EL2NSYNC] = TARGET_EL2NSYNC,
312 [EL3HLT] = TARGET_EL3HLT,
313 [EL3RST] = TARGET_EL3RST,
314 [ELNRNG] = TARGET_ELNRNG,
315 [EUNATCH] = TARGET_EUNATCH,
316 [ENOCSI] = TARGET_ENOCSI,
317 [EL2HLT] = TARGET_EL2HLT,
318 [EDEADLK] = TARGET_EDEADLK,
319 [ENOLCK] = TARGET_ENOLCK,
320 [EBADE] = TARGET_EBADE,
321 [EBADR] = TARGET_EBADR,
322 [EXFULL] = TARGET_EXFULL,
323 [ENOANO] = TARGET_ENOANO,
324 [EBADRQC] = TARGET_EBADRQC,
325 [EBADSLT] = TARGET_EBADSLT,
326 [EBFONT] = TARGET_EBFONT,
327 [ENOSTR] = TARGET_ENOSTR,
328 [ENODATA] = TARGET_ENODATA,
329 [ETIME] = TARGET_ETIME,
330 [ENOSR] = TARGET_ENOSR,
331 [ENONET] = TARGET_ENONET,
332 [ENOPKG] = TARGET_ENOPKG,
333 [EREMOTE] = TARGET_EREMOTE,
334 [ENOLINK] = TARGET_ENOLINK,
335 [EADV] = TARGET_EADV,
336 [ESRMNT] = TARGET_ESRMNT,
337 [ECOMM] = TARGET_ECOMM,
338 [EPROTO] = TARGET_EPROTO,
339 [EDOTDOT] = TARGET_EDOTDOT,
340 [EMULTIHOP] = TARGET_EMULTIHOP,
341 [EBADMSG] = TARGET_EBADMSG,
342 [ENAMETOOLONG] = TARGET_ENAMETOOLONG,
343 [EOVERFLOW] = TARGET_EOVERFLOW,
344 [ENOTUNIQ] = TARGET_ENOTUNIQ,
345 [EBADFD] = TARGET_EBADFD,
346 [EREMCHG] = TARGET_EREMCHG,
347 [ELIBACC] = TARGET_ELIBACC,
348 [ELIBBAD] = TARGET_ELIBBAD,
349 [ELIBSCN] = TARGET_ELIBSCN,
350 [ELIBMAX] = TARGET_ELIBMAX,
351 [ELIBEXEC] = TARGET_ELIBEXEC,
352 [EILSEQ] = TARGET_EILSEQ,
353 [ENOSYS] = TARGET_ENOSYS,
354 [ELOOP] = TARGET_ELOOP,
355 [ERESTART] = TARGET_ERESTART,
356 [ESTRPIPE] = TARGET_ESTRPIPE,
357 [ENOTEMPTY] = TARGET_ENOTEMPTY,
358 [EUSERS] = TARGET_EUSERS,
359 [ENOTSOCK] = TARGET_ENOTSOCK,
360 [EDESTADDRREQ] = TARGET_EDESTADDRREQ,
361 [EMSGSIZE] = TARGET_EMSGSIZE,
362 [EPROTOTYPE] = TARGET_EPROTOTYPE,
363 [ENOPROTOOPT] = TARGET_ENOPROTOOPT,
364 [EPROTONOSUPPORT] = TARGET_EPROTONOSUPPORT,
365 [ESOCKTNOSUPPORT] = TARGET_ESOCKTNOSUPPORT,
366 [EOPNOTSUPP] = TARGET_EOPNOTSUPP,
367 [EPFNOSUPPORT] = TARGET_EPFNOSUPPORT,
368 [EAFNOSUPPORT] = TARGET_EAFNOSUPPORT,
369 [EADDRINUSE] = TARGET_EADDRINUSE,
370 [EADDRNOTAVAIL] = TARGET_EADDRNOTAVAIL,
371 [ENETDOWN] = TARGET_ENETDOWN,
372 [ENETUNREACH] = TARGET_ENETUNREACH,
373 [ENETRESET] = TARGET_ENETRESET,
374 [ECONNABORTED] = TARGET_ECONNABORTED,
375 [ECONNRESET] = TARGET_ECONNRESET,
376 [ENOBUFS] = TARGET_ENOBUFS,
377 [EISCONN] = TARGET_EISCONN,
378 [ENOTCONN] = TARGET_ENOTCONN,
379 [EUCLEAN] = TARGET_EUCLEAN,
380 [ENOTNAM] = TARGET_ENOTNAM,
381 [ENAVAIL] = TARGET_ENAVAIL,
382 [EISNAM] = TARGET_EISNAM,
383 [EREMOTEIO] = TARGET_EREMOTEIO,
384 [ESHUTDOWN] = TARGET_ESHUTDOWN,
385 [ETOOMANYREFS] = TARGET_ETOOMANYREFS,
386 [ETIMEDOUT] = TARGET_ETIMEDOUT,
387 [ECONNREFUSED] = TARGET_ECONNREFUSED,
388 [EHOSTDOWN] = TARGET_EHOSTDOWN,
389 [EHOSTUNREACH] = TARGET_EHOSTUNREACH,
390 [EALREADY] = TARGET_EALREADY,
391 [EINPROGRESS] = TARGET_EINPROGRESS,
392 [ESTALE] = TARGET_ESTALE,
393 [ECANCELED] = TARGET_ECANCELED,
394 [ENOMEDIUM] = TARGET_ENOMEDIUM,
395 [EMEDIUMTYPE] = TARGET_EMEDIUMTYPE,
thsb7fe5db2007-07-23 15:37:46 +0000396#ifdef ENOKEY
ths637947f2007-06-01 12:09:19 +0000397 [ENOKEY] = TARGET_ENOKEY,
thsb7fe5db2007-07-23 15:37:46 +0000398#endif
399#ifdef EKEYEXPIRED
ths637947f2007-06-01 12:09:19 +0000400 [EKEYEXPIRED] = TARGET_EKEYEXPIRED,
thsb7fe5db2007-07-23 15:37:46 +0000401#endif
402#ifdef EKEYREVOKED
ths637947f2007-06-01 12:09:19 +0000403 [EKEYREVOKED] = TARGET_EKEYREVOKED,
thsb7fe5db2007-07-23 15:37:46 +0000404#endif
405#ifdef EKEYREJECTED
ths637947f2007-06-01 12:09:19 +0000406 [EKEYREJECTED] = TARGET_EKEYREJECTED,
thsb7fe5db2007-07-23 15:37:46 +0000407#endif
408#ifdef EOWNERDEAD
ths637947f2007-06-01 12:09:19 +0000409 [EOWNERDEAD] = TARGET_EOWNERDEAD,
thsb7fe5db2007-07-23 15:37:46 +0000410#endif
411#ifdef ENOTRECOVERABLE
ths637947f2007-06-01 12:09:19 +0000412 [ENOTRECOVERABLE] = TARGET_ENOTRECOVERABLE,
thsb7fe5db2007-07-23 15:37:46 +0000413#endif
thsb92c47c2007-11-01 00:07:38 +0000414};
ths637947f2007-06-01 12:09:19 +0000415
416static inline int host_to_target_errno(int err)
417{
418 if(host_to_target_errno_table[err])
419 return host_to_target_errno_table[err];
420 return err;
421}
422
thsb92c47c2007-11-01 00:07:38 +0000423static inline int target_to_host_errno(int err)
424{
425 if (target_to_host_errno_table[err])
426 return target_to_host_errno_table[err];
427 return err;
428}
429
blueswir1992f48a2007-10-14 16:27:31 +0000430static inline abi_long get_errno(abi_long ret)
bellard31e31b82003-02-18 22:55:36 +0000431{
432 if (ret == -1)
ths637947f2007-06-01 12:09:19 +0000433 return -host_to_target_errno(errno);
bellard31e31b82003-02-18 22:55:36 +0000434 else
435 return ret;
436}
437
blueswir1992f48a2007-10-14 16:27:31 +0000438static inline int is_error(abi_long ret)
bellard31e31b82003-02-18 22:55:36 +0000439{
blueswir1992f48a2007-10-14 16:27:31 +0000440 return (abi_ulong)ret >= (abi_ulong)(-4096);
bellard31e31b82003-02-18 22:55:36 +0000441}
442
thsb92c47c2007-11-01 00:07:38 +0000443char *target_strerror(int err)
444{
445 return strerror(target_to_host_errno(err));
446}
447
blueswir1992f48a2007-10-14 16:27:31 +0000448static abi_ulong target_brk;
449static abi_ulong target_original_brk;
bellard31e31b82003-02-18 22:55:36 +0000450
blueswir1992f48a2007-10-14 16:27:31 +0000451void target_set_brk(abi_ulong new_brk)
bellard31e31b82003-02-18 22:55:36 +0000452{
blueswir14c1de732007-07-07 20:45:44 +0000453 target_original_brk = target_brk = HOST_PAGE_ALIGN(new_brk);
bellard31e31b82003-02-18 22:55:36 +0000454}
455
ths0da46a62007-10-20 20:23:07 +0000456/* do_brk() must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +0000457abi_long do_brk(abi_ulong new_brk)
bellard31e31b82003-02-18 22:55:36 +0000458{
blueswir1992f48a2007-10-14 16:27:31 +0000459 abi_ulong brk_page;
460 abi_long mapped_addr;
bellard31e31b82003-02-18 22:55:36 +0000461 int new_alloc_size;
462
463 if (!new_brk)
pbrook53a59602006-03-25 19:31:22 +0000464 return target_brk;
bellard31e31b82003-02-18 22:55:36 +0000465 if (new_brk < target_original_brk)
balrog7ab240a2008-04-26 12:17:34 +0000466 return target_brk;
ths3b46e622007-09-17 08:09:54 +0000467
pbrook53a59602006-03-25 19:31:22 +0000468 brk_page = HOST_PAGE_ALIGN(target_brk);
bellard31e31b82003-02-18 22:55:36 +0000469
470 /* If the new brk is less than this, set it and we're done... */
471 if (new_brk < brk_page) {
472 target_brk = new_brk;
pbrook53a59602006-03-25 19:31:22 +0000473 return target_brk;
bellard31e31b82003-02-18 22:55:36 +0000474 }
475
476 /* We need to allocate more memory after the brk... */
bellard54936002003-05-13 00:25:15 +0000477 new_alloc_size = HOST_PAGE_ALIGN(new_brk - brk_page + 1);
ths5fafdf22007-09-16 21:08:06 +0000478 mapped_addr = get_errno(target_mmap(brk_page, new_alloc_size,
bellard54936002003-05-13 00:25:15 +0000479 PROT_READ|PROT_WRITE,
480 MAP_ANON|MAP_FIXED|MAP_PRIVATE, 0, 0));
balrog7ab240a2008-04-26 12:17:34 +0000481
482 if (!is_error(mapped_addr))
bellard31e31b82003-02-18 22:55:36 +0000483 target_brk = new_brk;
balrog7ab240a2008-04-26 12:17:34 +0000484
485 return target_brk;
bellard31e31b82003-02-18 22:55:36 +0000486}
487
ths26edcf42007-12-09 02:25:24 +0000488static inline abi_long copy_from_user_fdset(fd_set *fds,
489 abi_ulong target_fds_addr,
490 int n)
bellard31e31b82003-02-18 22:55:36 +0000491{
ths26edcf42007-12-09 02:25:24 +0000492 int i, nw, j, k;
493 abi_ulong b, *target_fds;
494
495 nw = (n + TARGET_ABI_BITS - 1) / TARGET_ABI_BITS;
496 if (!(target_fds = lock_user(VERIFY_READ,
497 target_fds_addr,
498 sizeof(abi_ulong) * nw,
499 1)))
500 return -TARGET_EFAULT;
501
502 FD_ZERO(fds);
503 k = 0;
504 for (i = 0; i < nw; i++) {
505 /* grab the abi_ulong */
506 __get_user(b, &target_fds[i]);
507 for (j = 0; j < TARGET_ABI_BITS; j++) {
508 /* check the bit inside the abi_ulong */
509 if ((b >> j) & 1)
510 FD_SET(k, fds);
511 k++;
bellard31e31b82003-02-18 22:55:36 +0000512 }
bellard31e31b82003-02-18 22:55:36 +0000513 }
ths26edcf42007-12-09 02:25:24 +0000514
515 unlock_user(target_fds, target_fds_addr, 0);
516
517 return 0;
bellard31e31b82003-02-18 22:55:36 +0000518}
519
ths26edcf42007-12-09 02:25:24 +0000520static inline abi_long copy_to_user_fdset(abi_ulong target_fds_addr,
521 const fd_set *fds,
522 int n)
bellard31e31b82003-02-18 22:55:36 +0000523{
bellard31e31b82003-02-18 22:55:36 +0000524 int i, nw, j, k;
blueswir1992f48a2007-10-14 16:27:31 +0000525 abi_long v;
ths26edcf42007-12-09 02:25:24 +0000526 abi_ulong *target_fds;
bellard31e31b82003-02-18 22:55:36 +0000527
ths26edcf42007-12-09 02:25:24 +0000528 nw = (n + TARGET_ABI_BITS - 1) / TARGET_ABI_BITS;
529 if (!(target_fds = lock_user(VERIFY_WRITE,
530 target_fds_addr,
531 sizeof(abi_ulong) * nw,
532 0)))
533 return -TARGET_EFAULT;
534
535 k = 0;
536 for (i = 0; i < nw; i++) {
537 v = 0;
538 for (j = 0; j < TARGET_ABI_BITS; j++) {
539 v |= ((FD_ISSET(k, fds) != 0) << j);
540 k++;
bellard31e31b82003-02-18 22:55:36 +0000541 }
ths26edcf42007-12-09 02:25:24 +0000542 __put_user(v, &target_fds[i]);
bellard31e31b82003-02-18 22:55:36 +0000543 }
ths26edcf42007-12-09 02:25:24 +0000544
545 unlock_user(target_fds, target_fds_addr, sizeof(abi_ulong) * nw);
546
547 return 0;
bellard31e31b82003-02-18 22:55:36 +0000548}
549
bellardc596ed12003-07-13 17:32:31 +0000550#if defined(__alpha__)
551#define HOST_HZ 1024
552#else
553#define HOST_HZ 100
554#endif
555
blueswir1992f48a2007-10-14 16:27:31 +0000556static inline abi_long host_to_target_clock_t(long ticks)
bellardc596ed12003-07-13 17:32:31 +0000557{
558#if HOST_HZ == TARGET_HZ
559 return ticks;
560#else
561 return ((int64_t)ticks * TARGET_HZ) / HOST_HZ;
562#endif
563}
564
bellard579a97f2007-11-11 14:26:47 +0000565static inline abi_long host_to_target_rusage(abi_ulong target_addr,
566 const struct rusage *rusage)
bellardb4091862003-05-16 15:39:34 +0000567{
pbrook53a59602006-03-25 19:31:22 +0000568 struct target_rusage *target_rusage;
569
bellard579a97f2007-11-11 14:26:47 +0000570 if (!lock_user_struct(VERIFY_WRITE, target_rusage, target_addr, 0))
571 return -TARGET_EFAULT;
bellardb4091862003-05-16 15:39:34 +0000572 target_rusage->ru_utime.tv_sec = tswapl(rusage->ru_utime.tv_sec);
573 target_rusage->ru_utime.tv_usec = tswapl(rusage->ru_utime.tv_usec);
574 target_rusage->ru_stime.tv_sec = tswapl(rusage->ru_stime.tv_sec);
575 target_rusage->ru_stime.tv_usec = tswapl(rusage->ru_stime.tv_usec);
576 target_rusage->ru_maxrss = tswapl(rusage->ru_maxrss);
577 target_rusage->ru_ixrss = tswapl(rusage->ru_ixrss);
578 target_rusage->ru_idrss = tswapl(rusage->ru_idrss);
579 target_rusage->ru_isrss = tswapl(rusage->ru_isrss);
580 target_rusage->ru_minflt = tswapl(rusage->ru_minflt);
581 target_rusage->ru_majflt = tswapl(rusage->ru_majflt);
582 target_rusage->ru_nswap = tswapl(rusage->ru_nswap);
583 target_rusage->ru_inblock = tswapl(rusage->ru_inblock);
584 target_rusage->ru_oublock = tswapl(rusage->ru_oublock);
585 target_rusage->ru_msgsnd = tswapl(rusage->ru_msgsnd);
586 target_rusage->ru_msgrcv = tswapl(rusage->ru_msgrcv);
587 target_rusage->ru_nsignals = tswapl(rusage->ru_nsignals);
588 target_rusage->ru_nvcsw = tswapl(rusage->ru_nvcsw);
589 target_rusage->ru_nivcsw = tswapl(rusage->ru_nivcsw);
pbrook53a59602006-03-25 19:31:22 +0000590 unlock_user_struct(target_rusage, target_addr, 1);
bellard579a97f2007-11-11 14:26:47 +0000591
592 return 0;
bellardb4091862003-05-16 15:39:34 +0000593}
594
ths788f5ec2007-12-09 02:37:05 +0000595static inline abi_long copy_from_user_timeval(struct timeval *tv,
596 abi_ulong target_tv_addr)
bellard31e31b82003-02-18 22:55:36 +0000597{
pbrook53a59602006-03-25 19:31:22 +0000598 struct target_timeval *target_tv;
599
ths788f5ec2007-12-09 02:37:05 +0000600 if (!lock_user_struct(VERIFY_READ, target_tv, target_tv_addr, 1))
bellard579a97f2007-11-11 14:26:47 +0000601 return -TARGET_EFAULT;
ths788f5ec2007-12-09 02:37:05 +0000602
603 __get_user(tv->tv_sec, &target_tv->tv_sec);
604 __get_user(tv->tv_usec, &target_tv->tv_usec);
605
606 unlock_user_struct(target_tv, target_tv_addr, 0);
bellard579a97f2007-11-11 14:26:47 +0000607
608 return 0;
bellard31e31b82003-02-18 22:55:36 +0000609}
610
ths788f5ec2007-12-09 02:37:05 +0000611static inline abi_long copy_to_user_timeval(abi_ulong target_tv_addr,
612 const struct timeval *tv)
bellard31e31b82003-02-18 22:55:36 +0000613{
pbrook53a59602006-03-25 19:31:22 +0000614 struct target_timeval *target_tv;
615
ths788f5ec2007-12-09 02:37:05 +0000616 if (!lock_user_struct(VERIFY_WRITE, target_tv, target_tv_addr, 0))
bellard579a97f2007-11-11 14:26:47 +0000617 return -TARGET_EFAULT;
ths788f5ec2007-12-09 02:37:05 +0000618
619 __put_user(tv->tv_sec, &target_tv->tv_sec);
620 __put_user(tv->tv_usec, &target_tv->tv_usec);
621
622 unlock_user_struct(target_tv, target_tv_addr, 1);
bellard579a97f2007-11-11 14:26:47 +0000623
624 return 0;
bellard31e31b82003-02-18 22:55:36 +0000625}
626
627
ths0da46a62007-10-20 20:23:07 +0000628/* do_select() must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +0000629static abi_long do_select(int n,
ths26edcf42007-12-09 02:25:24 +0000630 abi_ulong rfd_addr, abi_ulong wfd_addr,
631 abi_ulong efd_addr, abi_ulong target_tv_addr)
bellard31e31b82003-02-18 22:55:36 +0000632{
633 fd_set rfds, wfds, efds;
634 fd_set *rfds_ptr, *wfds_ptr, *efds_ptr;
635 struct timeval tv, *tv_ptr;
blueswir1992f48a2007-10-14 16:27:31 +0000636 abi_long ret;
bellard31e31b82003-02-18 22:55:36 +0000637
ths26edcf42007-12-09 02:25:24 +0000638 if (rfd_addr) {
639 if (copy_from_user_fdset(&rfds, rfd_addr, n))
640 return -TARGET_EFAULT;
641 rfds_ptr = &rfds;
pbrook53a59602006-03-25 19:31:22 +0000642 } else {
pbrook53a59602006-03-25 19:31:22 +0000643 rfds_ptr = NULL;
644 }
ths26edcf42007-12-09 02:25:24 +0000645 if (wfd_addr) {
646 if (copy_from_user_fdset(&wfds, wfd_addr, n))
647 return -TARGET_EFAULT;
648 wfds_ptr = &wfds;
pbrook53a59602006-03-25 19:31:22 +0000649 } else {
pbrook53a59602006-03-25 19:31:22 +0000650 wfds_ptr = NULL;
651 }
ths26edcf42007-12-09 02:25:24 +0000652 if (efd_addr) {
653 if (copy_from_user_fdset(&efds, efd_addr, n))
654 return -TARGET_EFAULT;
655 efds_ptr = &efds;
pbrook53a59602006-03-25 19:31:22 +0000656 } else {
pbrook53a59602006-03-25 19:31:22 +0000657 efds_ptr = NULL;
658 }
ths3b46e622007-09-17 08:09:54 +0000659
ths26edcf42007-12-09 02:25:24 +0000660 if (target_tv_addr) {
ths788f5ec2007-12-09 02:37:05 +0000661 if (copy_from_user_timeval(&tv, target_tv_addr))
662 return -TARGET_EFAULT;
bellard31e31b82003-02-18 22:55:36 +0000663 tv_ptr = &tv;
664 } else {
665 tv_ptr = NULL;
666 }
ths26edcf42007-12-09 02:25:24 +0000667
bellard31e31b82003-02-18 22:55:36 +0000668 ret = get_errno(select(n, rfds_ptr, wfds_ptr, efds_ptr, tv_ptr));
pbrook53a59602006-03-25 19:31:22 +0000669
ths26edcf42007-12-09 02:25:24 +0000670 if (!is_error(ret)) {
671 if (rfd_addr && copy_to_user_fdset(rfd_addr, &rfds, n))
672 return -TARGET_EFAULT;
673 if (wfd_addr && copy_to_user_fdset(wfd_addr, &wfds, n))
674 return -TARGET_EFAULT;
675 if (efd_addr && copy_to_user_fdset(efd_addr, &efds, n))
676 return -TARGET_EFAULT;
bellard31e31b82003-02-18 22:55:36 +0000677
ths788f5ec2007-12-09 02:37:05 +0000678 if (target_tv_addr && copy_to_user_timeval(target_tv_addr, &tv))
679 return -TARGET_EFAULT;
bellard31e31b82003-02-18 22:55:36 +0000680 }
bellard579a97f2007-11-11 14:26:47 +0000681
bellard31e31b82003-02-18 22:55:36 +0000682 return ret;
683}
684
bellard579a97f2007-11-11 14:26:47 +0000685static inline abi_long target_to_host_sockaddr(struct sockaddr *addr,
686 abi_ulong target_addr,
687 socklen_t len)
bellard7854b052003-03-29 17:22:23 +0000688{
pbrook53a59602006-03-25 19:31:22 +0000689 struct target_sockaddr *target_saddr;
690
bellard579a97f2007-11-11 14:26:47 +0000691 target_saddr = lock_user(VERIFY_READ, target_addr, len, 1);
692 if (!target_saddr)
693 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +0000694 memcpy(addr, target_saddr, len);
695 addr->sa_family = tswap16(target_saddr->sa_family);
696 unlock_user(target_saddr, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +0000697
698 return 0;
bellard7854b052003-03-29 17:22:23 +0000699}
700
bellard579a97f2007-11-11 14:26:47 +0000701static inline abi_long host_to_target_sockaddr(abi_ulong target_addr,
702 struct sockaddr *addr,
703 socklen_t len)
bellard7854b052003-03-29 17:22:23 +0000704{
pbrook53a59602006-03-25 19:31:22 +0000705 struct target_sockaddr *target_saddr;
706
bellard579a97f2007-11-11 14:26:47 +0000707 target_saddr = lock_user(VERIFY_WRITE, target_addr, len, 0);
708 if (!target_saddr)
709 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +0000710 memcpy(target_saddr, addr, len);
711 target_saddr->sa_family = tswap16(addr->sa_family);
712 unlock_user(target_saddr, target_addr, len);
bellard579a97f2007-11-11 14:26:47 +0000713
714 return 0;
bellard7854b052003-03-29 17:22:23 +0000715}
716
pbrook53a59602006-03-25 19:31:22 +0000717/* ??? Should this also swap msgh->name? */
bellard5a4a8982007-11-11 17:39:18 +0000718static inline abi_long target_to_host_cmsg(struct msghdr *msgh,
719 struct target_msghdr *target_msgh)
bellard7854b052003-03-29 17:22:23 +0000720{
721 struct cmsghdr *cmsg = CMSG_FIRSTHDR(msgh);
bellard5a4a8982007-11-11 17:39:18 +0000722 abi_long msg_controllen;
723 abi_ulong target_cmsg_addr;
724 struct target_cmsghdr *target_cmsg;
bellard7854b052003-03-29 17:22:23 +0000725 socklen_t space = 0;
bellard5a4a8982007-11-11 17:39:18 +0000726
727 msg_controllen = tswapl(target_msgh->msg_controllen);
728 if (msg_controllen < sizeof (struct target_cmsghdr))
729 goto the_end;
730 target_cmsg_addr = tswapl(target_msgh->msg_control);
731 target_cmsg = lock_user(VERIFY_READ, target_cmsg_addr, msg_controllen, 1);
732 if (!target_cmsg)
733 return -TARGET_EFAULT;
bellard7854b052003-03-29 17:22:23 +0000734
735 while (cmsg && target_cmsg) {
736 void *data = CMSG_DATA(cmsg);
737 void *target_data = TARGET_CMSG_DATA(target_cmsg);
738
ths5fafdf22007-09-16 21:08:06 +0000739 int len = tswapl(target_cmsg->cmsg_len)
bellard7854b052003-03-29 17:22:23 +0000740 - TARGET_CMSG_ALIGN(sizeof (struct target_cmsghdr));
741
742 space += CMSG_SPACE(len);
743 if (space > msgh->msg_controllen) {
744 space -= CMSG_SPACE(len);
bellard31febb72005-12-18 20:03:27 +0000745 gemu_log("Host cmsg overflow\n");
bellard7854b052003-03-29 17:22:23 +0000746 break;
747 }
748
749 cmsg->cmsg_level = tswap32(target_cmsg->cmsg_level);
750 cmsg->cmsg_type = tswap32(target_cmsg->cmsg_type);
751 cmsg->cmsg_len = CMSG_LEN(len);
752
bellard3532fa72006-06-24 15:06:03 +0000753 if (cmsg->cmsg_level != TARGET_SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS) {
bellard7854b052003-03-29 17:22:23 +0000754 gemu_log("Unsupported ancillary data: %d/%d\n", cmsg->cmsg_level, cmsg->cmsg_type);
755 memcpy(data, target_data, len);
756 } else {
757 int *fd = (int *)data;
758 int *target_fd = (int *)target_data;
759 int i, numfds = len / sizeof(int);
760
761 for (i = 0; i < numfds; i++)
762 fd[i] = tswap32(target_fd[i]);
763 }
764
765 cmsg = CMSG_NXTHDR(msgh, cmsg);
766 target_cmsg = TARGET_CMSG_NXTHDR(target_msgh, target_cmsg);
767 }
bellard5a4a8982007-11-11 17:39:18 +0000768 unlock_user(target_cmsg, target_cmsg_addr, 0);
769 the_end:
bellard7854b052003-03-29 17:22:23 +0000770 msgh->msg_controllen = space;
bellard5a4a8982007-11-11 17:39:18 +0000771 return 0;
bellard7854b052003-03-29 17:22:23 +0000772}
773
pbrook53a59602006-03-25 19:31:22 +0000774/* ??? Should this also swap msgh->name? */
bellard5a4a8982007-11-11 17:39:18 +0000775static inline abi_long host_to_target_cmsg(struct target_msghdr *target_msgh,
776 struct msghdr *msgh)
bellard7854b052003-03-29 17:22:23 +0000777{
778 struct cmsghdr *cmsg = CMSG_FIRSTHDR(msgh);
bellard5a4a8982007-11-11 17:39:18 +0000779 abi_long msg_controllen;
780 abi_ulong target_cmsg_addr;
781 struct target_cmsghdr *target_cmsg;
bellard7854b052003-03-29 17:22:23 +0000782 socklen_t space = 0;
783
bellard5a4a8982007-11-11 17:39:18 +0000784 msg_controllen = tswapl(target_msgh->msg_controllen);
785 if (msg_controllen < sizeof (struct target_cmsghdr))
786 goto the_end;
787 target_cmsg_addr = tswapl(target_msgh->msg_control);
788 target_cmsg = lock_user(VERIFY_WRITE, target_cmsg_addr, msg_controllen, 0);
789 if (!target_cmsg)
790 return -TARGET_EFAULT;
791
bellard7854b052003-03-29 17:22:23 +0000792 while (cmsg && target_cmsg) {
793 void *data = CMSG_DATA(cmsg);
794 void *target_data = TARGET_CMSG_DATA(target_cmsg);
795
796 int len = cmsg->cmsg_len - CMSG_ALIGN(sizeof (struct cmsghdr));
797
798 space += TARGET_CMSG_SPACE(len);
bellard5a4a8982007-11-11 17:39:18 +0000799 if (space > msg_controllen) {
bellard7854b052003-03-29 17:22:23 +0000800 space -= TARGET_CMSG_SPACE(len);
bellard31febb72005-12-18 20:03:27 +0000801 gemu_log("Target cmsg overflow\n");
bellard7854b052003-03-29 17:22:23 +0000802 break;
803 }
804
805 target_cmsg->cmsg_level = tswap32(cmsg->cmsg_level);
806 target_cmsg->cmsg_type = tswap32(cmsg->cmsg_type);
807 target_cmsg->cmsg_len = tswapl(TARGET_CMSG_LEN(len));
808
bellard3532fa72006-06-24 15:06:03 +0000809 if (cmsg->cmsg_level != TARGET_SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS) {
bellard7854b052003-03-29 17:22:23 +0000810 gemu_log("Unsupported ancillary data: %d/%d\n", cmsg->cmsg_level, cmsg->cmsg_type);
811 memcpy(target_data, data, len);
812 } else {
813 int *fd = (int *)data;
814 int *target_fd = (int *)target_data;
815 int i, numfds = len / sizeof(int);
816
817 for (i = 0; i < numfds; i++)
818 target_fd[i] = tswap32(fd[i]);
819 }
820
821 cmsg = CMSG_NXTHDR(msgh, cmsg);
822 target_cmsg = TARGET_CMSG_NXTHDR(target_msgh, target_cmsg);
823 }
bellard5a4a8982007-11-11 17:39:18 +0000824 unlock_user(target_cmsg, target_cmsg_addr, space);
825 the_end:
826 target_msgh->msg_controllen = tswapl(space);
827 return 0;
bellard7854b052003-03-29 17:22:23 +0000828}
829
ths0da46a62007-10-20 20:23:07 +0000830/* do_setsockopt() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +0000831static abi_long do_setsockopt(int sockfd, int level, int optname,
bellard2f619692007-11-16 10:46:05 +0000832 abi_ulong optval_addr, socklen_t optlen)
bellard7854b052003-03-29 17:22:23 +0000833{
blueswir1992f48a2007-10-14 16:27:31 +0000834 abi_long ret;
j_mayer32407102007-09-26 23:01:49 +0000835 int val;
ths3b46e622007-09-17 08:09:54 +0000836
bellard8853f862004-02-22 14:57:26 +0000837 switch(level) {
838 case SOL_TCP:
bellard7854b052003-03-29 17:22:23 +0000839 /* TCP options all take an 'int' value. */
bellard7854b052003-03-29 17:22:23 +0000840 if (optlen < sizeof(uint32_t))
ths0da46a62007-10-20 20:23:07 +0000841 return -TARGET_EINVAL;
ths3b46e622007-09-17 08:09:54 +0000842
bellard2f619692007-11-16 10:46:05 +0000843 if (get_user_u32(val, optval_addr))
844 return -TARGET_EFAULT;
bellard8853f862004-02-22 14:57:26 +0000845 ret = get_errno(setsockopt(sockfd, level, optname, &val, sizeof(val)));
846 break;
847 case SOL_IP:
848 switch(optname) {
bellard2efbe912005-07-23 15:10:20 +0000849 case IP_TOS:
850 case IP_TTL:
bellard8853f862004-02-22 14:57:26 +0000851 case IP_HDRINCL:
bellard2efbe912005-07-23 15:10:20 +0000852 case IP_ROUTER_ALERT:
853 case IP_RECVOPTS:
854 case IP_RETOPTS:
855 case IP_PKTINFO:
856 case IP_MTU_DISCOVER:
857 case IP_RECVERR:
858 case IP_RECVTOS:
859#ifdef IP_FREEBIND
860 case IP_FREEBIND:
861#endif
862 case IP_MULTICAST_TTL:
863 case IP_MULTICAST_LOOP:
bellard8853f862004-02-22 14:57:26 +0000864 val = 0;
865 if (optlen >= sizeof(uint32_t)) {
bellard2f619692007-11-16 10:46:05 +0000866 if (get_user_u32(val, optval_addr))
867 return -TARGET_EFAULT;
bellard8853f862004-02-22 14:57:26 +0000868 } else if (optlen >= 1) {
bellard2f619692007-11-16 10:46:05 +0000869 if (get_user_u8(val, optval_addr))
870 return -TARGET_EFAULT;
bellard8853f862004-02-22 14:57:26 +0000871 }
872 ret = get_errno(setsockopt(sockfd, level, optname, &val, sizeof(val)));
873 break;
874 default:
875 goto unimplemented;
876 }
877 break;
bellard3532fa72006-06-24 15:06:03 +0000878 case TARGET_SOL_SOCKET:
bellard8853f862004-02-22 14:57:26 +0000879 switch (optname) {
880 /* Options with 'int' argument. */
bellard3532fa72006-06-24 15:06:03 +0000881 case TARGET_SO_DEBUG:
882 optname = SO_DEBUG;
883 break;
884 case TARGET_SO_REUSEADDR:
885 optname = SO_REUSEADDR;
886 break;
887 case TARGET_SO_TYPE:
888 optname = SO_TYPE;
889 break;
890 case TARGET_SO_ERROR:
891 optname = SO_ERROR;
892 break;
893 case TARGET_SO_DONTROUTE:
894 optname = SO_DONTROUTE;
895 break;
896 case TARGET_SO_BROADCAST:
897 optname = SO_BROADCAST;
898 break;
899 case TARGET_SO_SNDBUF:
900 optname = SO_SNDBUF;
901 break;
902 case TARGET_SO_RCVBUF:
903 optname = SO_RCVBUF;
904 break;
905 case TARGET_SO_KEEPALIVE:
906 optname = SO_KEEPALIVE;
907 break;
908 case TARGET_SO_OOBINLINE:
909 optname = SO_OOBINLINE;
910 break;
911 case TARGET_SO_NO_CHECK:
912 optname = SO_NO_CHECK;
913 break;
914 case TARGET_SO_PRIORITY:
915 optname = SO_PRIORITY;
916 break;
bellard5e83e8e2005-03-01 22:32:06 +0000917#ifdef SO_BSDCOMPAT
bellard3532fa72006-06-24 15:06:03 +0000918 case TARGET_SO_BSDCOMPAT:
919 optname = SO_BSDCOMPAT;
920 break;
bellard5e83e8e2005-03-01 22:32:06 +0000921#endif
bellard3532fa72006-06-24 15:06:03 +0000922 case TARGET_SO_PASSCRED:
923 optname = SO_PASSCRED;
924 break;
925 case TARGET_SO_TIMESTAMP:
926 optname = SO_TIMESTAMP;
927 break;
928 case TARGET_SO_RCVLOWAT:
929 optname = SO_RCVLOWAT;
930 break;
931 case TARGET_SO_RCVTIMEO:
932 optname = SO_RCVTIMEO;
933 break;
934 case TARGET_SO_SNDTIMEO:
935 optname = SO_SNDTIMEO;
936 break;
bellard8853f862004-02-22 14:57:26 +0000937 break;
938 default:
939 goto unimplemented;
940 }
bellard3532fa72006-06-24 15:06:03 +0000941 if (optlen < sizeof(uint32_t))
bellard2f619692007-11-16 10:46:05 +0000942 return -TARGET_EINVAL;
bellard3532fa72006-06-24 15:06:03 +0000943
bellard2f619692007-11-16 10:46:05 +0000944 if (get_user_u32(val, optval_addr))
945 return -TARGET_EFAULT;
bellard3532fa72006-06-24 15:06:03 +0000946 ret = get_errno(setsockopt(sockfd, SOL_SOCKET, optname, &val, sizeof(val)));
bellard8853f862004-02-22 14:57:26 +0000947 break;
bellard7854b052003-03-29 17:22:23 +0000948 default:
bellard8853f862004-02-22 14:57:26 +0000949 unimplemented:
950 gemu_log("Unsupported setsockopt level=%d optname=%d \n", level, optname);
ths6fa13c12007-12-18 02:41:04 +0000951 ret = -TARGET_ENOPROTOOPT;
bellard7854b052003-03-29 17:22:23 +0000952 }
bellard8853f862004-02-22 14:57:26 +0000953 return ret;
bellard7854b052003-03-29 17:22:23 +0000954}
955
ths0da46a62007-10-20 20:23:07 +0000956/* do_getsockopt() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +0000957static abi_long do_getsockopt(int sockfd, int level, int optname,
bellard2f619692007-11-16 10:46:05 +0000958 abi_ulong optval_addr, abi_ulong optlen)
bellard7854b052003-03-29 17:22:23 +0000959{
blueswir1992f48a2007-10-14 16:27:31 +0000960 abi_long ret;
blueswir1b55266b2008-09-20 08:07:15 +0000961 int len, val;
962 socklen_t lv;
bellard8853f862004-02-22 14:57:26 +0000963
964 switch(level) {
bellard3532fa72006-06-24 15:06:03 +0000965 case TARGET_SOL_SOCKET:
966 level = SOL_SOCKET;
bellard8853f862004-02-22 14:57:26 +0000967 switch (optname) {
bellard3532fa72006-06-24 15:06:03 +0000968 case TARGET_SO_LINGER:
969 case TARGET_SO_RCVTIMEO:
970 case TARGET_SO_SNDTIMEO:
971 case TARGET_SO_PEERCRED:
972 case TARGET_SO_PEERNAME:
bellard8853f862004-02-22 14:57:26 +0000973 /* These don't just return a single integer */
974 goto unimplemented;
975 default:
bellard2efbe912005-07-23 15:10:20 +0000976 goto int_case;
977 }
978 break;
979 case SOL_TCP:
980 /* TCP options all take an 'int' value. */
981 int_case:
bellard2f619692007-11-16 10:46:05 +0000982 if (get_user_u32(len, optlen))
983 return -TARGET_EFAULT;
bellard2efbe912005-07-23 15:10:20 +0000984 if (len < 0)
ths0da46a62007-10-20 20:23:07 +0000985 return -TARGET_EINVAL;
bellard2efbe912005-07-23 15:10:20 +0000986 lv = sizeof(int);
987 ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
988 if (ret < 0)
989 return ret;
990 val = tswap32(val);
991 if (len > lv)
992 len = lv;
bellard2f619692007-11-16 10:46:05 +0000993 if (len == 4) {
994 if (put_user_u32(val, optval_addr))
995 return -TARGET_EFAULT;
996 } else {
997 if (put_user_u8(val, optval_addr))
998 return -TARGET_EFAULT;
999 }
1000 if (put_user_u32(len, optlen))
1001 return -TARGET_EFAULT;
bellard2efbe912005-07-23 15:10:20 +00001002 break;
1003 case SOL_IP:
1004 switch(optname) {
1005 case IP_TOS:
1006 case IP_TTL:
1007 case IP_HDRINCL:
1008 case IP_ROUTER_ALERT:
1009 case IP_RECVOPTS:
1010 case IP_RETOPTS:
1011 case IP_PKTINFO:
1012 case IP_MTU_DISCOVER:
1013 case IP_RECVERR:
1014 case IP_RECVTOS:
1015#ifdef IP_FREEBIND
1016 case IP_FREEBIND:
1017#endif
1018 case IP_MULTICAST_TTL:
1019 case IP_MULTICAST_LOOP:
bellard2f619692007-11-16 10:46:05 +00001020 if (get_user_u32(len, optlen))
1021 return -TARGET_EFAULT;
bellard8853f862004-02-22 14:57:26 +00001022 if (len < 0)
ths0da46a62007-10-20 20:23:07 +00001023 return -TARGET_EINVAL;
bellard8853f862004-02-22 14:57:26 +00001024 lv = sizeof(int);
1025 ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
1026 if (ret < 0)
1027 return ret;
bellard2efbe912005-07-23 15:10:20 +00001028 if (len < sizeof(int) && len > 0 && val >= 0 && val < 255) {
bellard2efbe912005-07-23 15:10:20 +00001029 len = 1;
bellard2f619692007-11-16 10:46:05 +00001030 if (put_user_u32(len, optlen)
1031 || put_user_u8(val, optval_addr))
1032 return -TARGET_EFAULT;
bellard2efbe912005-07-23 15:10:20 +00001033 } else {
bellard2efbe912005-07-23 15:10:20 +00001034 if (len > sizeof(int))
1035 len = sizeof(int);
bellard2f619692007-11-16 10:46:05 +00001036 if (put_user_u32(len, optlen)
1037 || put_user_u32(val, optval_addr))
1038 return -TARGET_EFAULT;
bellard2efbe912005-07-23 15:10:20 +00001039 }
bellard8853f862004-02-22 14:57:26 +00001040 break;
bellard2efbe912005-07-23 15:10:20 +00001041 default:
thsc02f4992007-12-18 02:39:59 +00001042 ret = -TARGET_ENOPROTOOPT;
1043 break;
bellard8853f862004-02-22 14:57:26 +00001044 }
1045 break;
1046 default:
1047 unimplemented:
1048 gemu_log("getsockopt level=%d optname=%d not yet supported\n",
1049 level, optname);
thsc02f4992007-12-18 02:39:59 +00001050 ret = -TARGET_EOPNOTSUPP;
bellard8853f862004-02-22 14:57:26 +00001051 break;
1052 }
1053 return ret;
bellard7854b052003-03-29 17:22:23 +00001054}
1055
bellard579a97f2007-11-11 14:26:47 +00001056/* FIXME
1057 * lock_iovec()/unlock_iovec() have a return code of 0 for success where
1058 * other lock functions have a return code of 0 for failure.
1059 */
1060static abi_long lock_iovec(int type, struct iovec *vec, abi_ulong target_addr,
1061 int count, int copy)
pbrook53a59602006-03-25 19:31:22 +00001062{
1063 struct target_iovec *target_vec;
blueswir1992f48a2007-10-14 16:27:31 +00001064 abi_ulong base;
bellard579a97f2007-11-11 14:26:47 +00001065 int i, j;
pbrook53a59602006-03-25 19:31:22 +00001066
bellard579a97f2007-11-11 14:26:47 +00001067 target_vec = lock_user(VERIFY_READ, target_addr, count * sizeof(struct target_iovec), 1);
1068 if (!target_vec)
1069 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00001070 for(i = 0;i < count; i++) {
1071 base = tswapl(target_vec[i].iov_base);
1072 vec[i].iov_len = tswapl(target_vec[i].iov_len);
bellard41df8412008-02-04 22:26:57 +00001073 if (vec[i].iov_len != 0) {
1074 vec[i].iov_base = lock_user(type, base, vec[i].iov_len, copy);
balrog7bedce82008-02-10 13:28:08 +00001075 if (!vec[i].iov_base && vec[i].iov_len)
bellard41df8412008-02-04 22:26:57 +00001076 goto fail;
1077 } else {
1078 /* zero length pointer is ignored */
1079 vec[i].iov_base = NULL;
1080 }
pbrook53a59602006-03-25 19:31:22 +00001081 }
1082 unlock_user (target_vec, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00001083 return 0;
1084 fail:
1085 /* failure - unwind locks */
1086 for (j = 0; j < i; j++) {
1087 base = tswapl(target_vec[j].iov_base);
1088 unlock_user(vec[j].iov_base, base, 0);
1089 }
1090 unlock_user (target_vec, target_addr, 0);
1091 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00001092}
1093
bellard579a97f2007-11-11 14:26:47 +00001094static abi_long unlock_iovec(struct iovec *vec, abi_ulong target_addr,
1095 int count, int copy)
pbrook53a59602006-03-25 19:31:22 +00001096{
1097 struct target_iovec *target_vec;
blueswir1992f48a2007-10-14 16:27:31 +00001098 abi_ulong base;
pbrook53a59602006-03-25 19:31:22 +00001099 int i;
1100
bellard579a97f2007-11-11 14:26:47 +00001101 target_vec = lock_user(VERIFY_READ, target_addr, count * sizeof(struct target_iovec), 1);
1102 if (!target_vec)
1103 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00001104 for(i = 0;i < count; i++) {
1105 base = tswapl(target_vec[i].iov_base);
1106 unlock_user(vec[i].iov_base, base, copy ? vec[i].iov_len : 0);
1107 }
1108 unlock_user (target_vec, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00001109
1110 return 0;
pbrook53a59602006-03-25 19:31:22 +00001111}
1112
ths0da46a62007-10-20 20:23:07 +00001113/* do_socket() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001114static abi_long do_socket(int domain, int type, int protocol)
bellard3532fa72006-06-24 15:06:03 +00001115{
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
balrog12bc92a2007-10-30 21:06:14 +00001138 if (domain == PF_NETLINK)
1139 return -EAFNOSUPPORT; /* do not NETLINK socket connections possible */
bellard3532fa72006-06-24 15:06:03 +00001140 return get_errno(socket(domain, type, protocol));
1141}
1142
ths0da46a62007-10-20 20:23:07 +00001143/* do_bind() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001144static abi_long do_bind(int sockfd, abi_ulong target_addr,
1145 socklen_t addrlen)
bellard3532fa72006-06-24 15:06:03 +00001146{
1147 void *addr = alloca(addrlen);
ths3b46e622007-09-17 08:09:54 +00001148
bellard3532fa72006-06-24 15:06:03 +00001149 target_to_host_sockaddr(addr, target_addr, addrlen);
1150 return get_errno(bind(sockfd, addr, addrlen));
1151}
1152
ths0da46a62007-10-20 20:23:07 +00001153/* do_connect() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001154static abi_long do_connect(int sockfd, abi_ulong target_addr,
1155 socklen_t addrlen)
bellard3532fa72006-06-24 15:06:03 +00001156{
1157 void *addr = alloca(addrlen);
ths3b46e622007-09-17 08:09:54 +00001158
bellard3532fa72006-06-24 15:06:03 +00001159 target_to_host_sockaddr(addr, target_addr, addrlen);
1160 return get_errno(connect(sockfd, addr, addrlen));
1161}
1162
ths0da46a62007-10-20 20:23:07 +00001163/* do_sendrecvmsg() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001164static abi_long do_sendrecvmsg(int fd, abi_ulong target_msg,
1165 int flags, int send)
bellard3532fa72006-06-24 15:06:03 +00001166{
blueswir1992f48a2007-10-14 16:27:31 +00001167 abi_long ret;
bellard3532fa72006-06-24 15:06:03 +00001168 struct target_msghdr *msgp;
1169 struct msghdr msg;
1170 int count;
1171 struct iovec *vec;
blueswir1992f48a2007-10-14 16:27:31 +00001172 abi_ulong target_vec;
bellard3532fa72006-06-24 15:06:03 +00001173
bellard579a97f2007-11-11 14:26:47 +00001174 /* FIXME */
1175 if (!lock_user_struct(send ? VERIFY_READ : VERIFY_WRITE,
1176 msgp,
1177 target_msg,
1178 send ? 1 : 0))
1179 return -TARGET_EFAULT;
bellard3532fa72006-06-24 15:06:03 +00001180 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);
ths3b46e622007-09-17 08:09:54 +00001192
bellard3532fa72006-06-24 15:06:03 +00001193 count = tswapl(msgp->msg_iovlen);
1194 vec = alloca(count * sizeof(struct iovec));
1195 target_vec = tswapl(msgp->msg_iov);
bellard579a97f2007-11-11 14:26:47 +00001196 lock_iovec(send ? VERIFY_READ : VERIFY_WRITE, vec, target_vec, count, send);
bellard3532fa72006-06-24 15:06:03 +00001197 msg.msg_iovlen = count;
1198 msg.msg_iov = vec;
ths3b46e622007-09-17 08:09:54 +00001199
bellard3532fa72006-06-24 15:06:03 +00001200 if (send) {
bellard5a4a8982007-11-11 17:39:18 +00001201 ret = target_to_host_cmsg(&msg, msgp);
1202 if (ret == 0)
1203 ret = get_errno(sendmsg(fd, &msg, flags));
bellard3532fa72006-06-24 15:06:03 +00001204 } else {
1205 ret = get_errno(recvmsg(fd, &msg, flags));
1206 if (!is_error(ret))
bellard5a4a8982007-11-11 17:39:18 +00001207 ret = host_to_target_cmsg(msgp, &msg);
bellard3532fa72006-06-24 15:06:03 +00001208 }
1209 unlock_iovec(vec, target_vec, count, !send);
bellard579a97f2007-11-11 14:26:47 +00001210 unlock_user_struct(msgp, target_msg, send ? 0 : 1);
bellard3532fa72006-06-24 15:06:03 +00001211 return ret;
1212}
1213
ths0da46a62007-10-20 20:23:07 +00001214/* do_accept() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001215static abi_long do_accept(int fd, abi_ulong target_addr,
bellard2f619692007-11-16 10:46:05 +00001216 abi_ulong target_addrlen_addr)
pbrook1be9e1d2006-11-19 15:26:04 +00001217{
bellard2f619692007-11-16 10:46:05 +00001218 socklen_t addrlen;
1219 void *addr;
blueswir1992f48a2007-10-14 16:27:31 +00001220 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00001221
bellard2f619692007-11-16 10:46:05 +00001222 if (get_user_u32(addrlen, target_addrlen_addr))
1223 return -TARGET_EFAULT;
1224
1225 addr = alloca(addrlen);
1226
pbrook1be9e1d2006-11-19 15:26:04 +00001227 ret = get_errno(accept(fd, addr, &addrlen));
1228 if (!is_error(ret)) {
1229 host_to_target_sockaddr(target_addr, addr, addrlen);
bellard2f619692007-11-16 10:46:05 +00001230 if (put_user_u32(addrlen, target_addrlen_addr))
1231 ret = -TARGET_EFAULT;
pbrook1be9e1d2006-11-19 15:26:04 +00001232 }
1233 return ret;
1234}
1235
ths0da46a62007-10-20 20:23:07 +00001236/* do_getpeername() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001237static abi_long do_getpeername(int fd, abi_ulong target_addr,
bellard2f619692007-11-16 10:46:05 +00001238 abi_ulong target_addrlen_addr)
pbrook1be9e1d2006-11-19 15:26:04 +00001239{
bellard2f619692007-11-16 10:46:05 +00001240 socklen_t addrlen;
1241 void *addr;
blueswir1992f48a2007-10-14 16:27:31 +00001242 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00001243
bellard2f619692007-11-16 10:46:05 +00001244 if (get_user_u32(addrlen, target_addrlen_addr))
1245 return -TARGET_EFAULT;
1246
1247 addr = alloca(addrlen);
1248
pbrook1be9e1d2006-11-19 15:26:04 +00001249 ret = get_errno(getpeername(fd, addr, &addrlen));
1250 if (!is_error(ret)) {
1251 host_to_target_sockaddr(target_addr, addr, addrlen);
bellard2f619692007-11-16 10:46:05 +00001252 if (put_user_u32(addrlen, target_addrlen_addr))
1253 ret = -TARGET_EFAULT;
pbrook1be9e1d2006-11-19 15:26:04 +00001254 }
1255 return ret;
1256}
1257
ths0da46a62007-10-20 20:23:07 +00001258/* do_getsockname() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001259static abi_long do_getsockname(int fd, abi_ulong target_addr,
bellard2f619692007-11-16 10:46:05 +00001260 abi_ulong target_addrlen_addr)
pbrook1be9e1d2006-11-19 15:26:04 +00001261{
bellard2f619692007-11-16 10:46:05 +00001262 socklen_t addrlen;
1263 void *addr;
blueswir1992f48a2007-10-14 16:27:31 +00001264 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00001265
bellard2f619692007-11-16 10:46:05 +00001266 if (get_user_u32(addrlen, target_addrlen_addr))
1267 return -TARGET_EFAULT;
1268
1269 addr = alloca(addrlen);
1270
pbrook1be9e1d2006-11-19 15:26:04 +00001271 ret = get_errno(getsockname(fd, addr, &addrlen));
1272 if (!is_error(ret)) {
1273 host_to_target_sockaddr(target_addr, addr, addrlen);
bellard2f619692007-11-16 10:46:05 +00001274 if (put_user_u32(addrlen, target_addrlen_addr))
1275 ret = -TARGET_EFAULT;
pbrook1be9e1d2006-11-19 15:26:04 +00001276 }
1277 return ret;
1278}
1279
ths0da46a62007-10-20 20:23:07 +00001280/* do_socketpair() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001281static abi_long do_socketpair(int domain, int type, int protocol,
bellard2f619692007-11-16 10:46:05 +00001282 abi_ulong target_tab_addr)
pbrook1be9e1d2006-11-19 15:26:04 +00001283{
1284 int tab[2];
blueswir1992f48a2007-10-14 16:27:31 +00001285 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00001286
1287 ret = get_errno(socketpair(domain, type, protocol, tab));
1288 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +00001289 if (put_user_s32(tab[0], target_tab_addr)
1290 || put_user_s32(tab[1], target_tab_addr + sizeof(tab[0])))
1291 ret = -TARGET_EFAULT;
pbrook1be9e1d2006-11-19 15:26:04 +00001292 }
1293 return ret;
1294}
1295
ths0da46a62007-10-20 20:23:07 +00001296/* do_sendto() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001297static abi_long do_sendto(int fd, abi_ulong msg, size_t len, int flags,
1298 abi_ulong target_addr, socklen_t addrlen)
pbrook1be9e1d2006-11-19 15:26:04 +00001299{
1300 void *addr;
1301 void *host_msg;
blueswir1992f48a2007-10-14 16:27:31 +00001302 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00001303
bellard579a97f2007-11-11 14:26:47 +00001304 host_msg = lock_user(VERIFY_READ, msg, len, 1);
1305 if (!host_msg)
1306 return -TARGET_EFAULT;
pbrook1be9e1d2006-11-19 15:26:04 +00001307 if (target_addr) {
1308 addr = alloca(addrlen);
1309 target_to_host_sockaddr(addr, target_addr, addrlen);
1310 ret = get_errno(sendto(fd, host_msg, len, flags, addr, addrlen));
1311 } else {
1312 ret = get_errno(send(fd, host_msg, len, flags));
1313 }
1314 unlock_user(host_msg, msg, 0);
1315 return ret;
1316}
1317
ths0da46a62007-10-20 20:23:07 +00001318/* do_recvfrom() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001319static abi_long do_recvfrom(int fd, abi_ulong msg, size_t len, int flags,
1320 abi_ulong target_addr,
1321 abi_ulong target_addrlen)
pbrook1be9e1d2006-11-19 15:26:04 +00001322{
1323 socklen_t addrlen;
1324 void *addr;
1325 void *host_msg;
blueswir1992f48a2007-10-14 16:27:31 +00001326 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00001327
bellard579a97f2007-11-11 14:26:47 +00001328 host_msg = lock_user(VERIFY_WRITE, msg, len, 0);
1329 if (!host_msg)
1330 return -TARGET_EFAULT;
pbrook1be9e1d2006-11-19 15:26:04 +00001331 if (target_addr) {
bellard2f619692007-11-16 10:46:05 +00001332 if (get_user_u32(addrlen, target_addrlen)) {
1333 ret = -TARGET_EFAULT;
1334 goto fail;
1335 }
pbrook1be9e1d2006-11-19 15:26:04 +00001336 addr = alloca(addrlen);
1337 ret = get_errno(recvfrom(fd, host_msg, len, flags, addr, &addrlen));
1338 } else {
1339 addr = NULL; /* To keep compiler quiet. */
1340 ret = get_errno(recv(fd, host_msg, len, flags));
1341 }
1342 if (!is_error(ret)) {
1343 if (target_addr) {
1344 host_to_target_sockaddr(target_addr, addr, addrlen);
bellard2f619692007-11-16 10:46:05 +00001345 if (put_user_u32(addrlen, target_addrlen)) {
1346 ret = -TARGET_EFAULT;
1347 goto fail;
1348 }
pbrook1be9e1d2006-11-19 15:26:04 +00001349 }
1350 unlock_user(host_msg, msg, len);
1351 } else {
bellard2f619692007-11-16 10:46:05 +00001352fail:
pbrook1be9e1d2006-11-19 15:26:04 +00001353 unlock_user(host_msg, msg, 0);
1354 }
1355 return ret;
1356}
1357
j_mayer32407102007-09-26 23:01:49 +00001358#ifdef TARGET_NR_socketcall
ths0da46a62007-10-20 20:23:07 +00001359/* do_socketcall() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001360static abi_long do_socketcall(int num, abi_ulong vptr)
bellard31e31b82003-02-18 22:55:36 +00001361{
blueswir1992f48a2007-10-14 16:27:31 +00001362 abi_long ret;
1363 const int n = sizeof(abi_ulong);
bellard31e31b82003-02-18 22:55:36 +00001364
1365 switch(num) {
1366 case SOCKOP_socket:
bellard7854b052003-03-29 17:22:23 +00001367 {
bellard2f619692007-11-16 10:46:05 +00001368 int domain, type, protocol;
1369
1370 if (get_user_s32(domain, vptr)
1371 || get_user_s32(type, vptr + n)
1372 || get_user_s32(protocol, vptr + 2 * n))
1373 return -TARGET_EFAULT;
1374
bellard3532fa72006-06-24 15:06:03 +00001375 ret = do_socket(domain, type, protocol);
bellard7854b052003-03-29 17:22:23 +00001376 }
bellard31e31b82003-02-18 22:55:36 +00001377 break;
1378 case SOCKOP_bind:
bellard7854b052003-03-29 17:22:23 +00001379 {
bellard2f619692007-11-16 10:46:05 +00001380 int sockfd;
1381 abi_ulong target_addr;
1382 socklen_t addrlen;
1383
1384 if (get_user_s32(sockfd, vptr)
1385 || get_user_ual(target_addr, vptr + n)
1386 || get_user_u32(addrlen, vptr + 2 * n))
1387 return -TARGET_EFAULT;
1388
bellard3532fa72006-06-24 15:06:03 +00001389 ret = do_bind(sockfd, target_addr, addrlen);
bellard7854b052003-03-29 17:22:23 +00001390 }
bellard31e31b82003-02-18 22:55:36 +00001391 break;
1392 case SOCKOP_connect:
bellard7854b052003-03-29 17:22:23 +00001393 {
bellard2f619692007-11-16 10:46:05 +00001394 int sockfd;
1395 abi_ulong target_addr;
1396 socklen_t addrlen;
1397
1398 if (get_user_s32(sockfd, vptr)
1399 || get_user_ual(target_addr, vptr + n)
1400 || get_user_u32(addrlen, vptr + 2 * n))
1401 return -TARGET_EFAULT;
1402
bellard3532fa72006-06-24 15:06:03 +00001403 ret = do_connect(sockfd, target_addr, addrlen);
bellard7854b052003-03-29 17:22:23 +00001404 }
bellard31e31b82003-02-18 22:55:36 +00001405 break;
1406 case SOCKOP_listen:
bellard7854b052003-03-29 17:22:23 +00001407 {
bellard2f619692007-11-16 10:46:05 +00001408 int sockfd, backlog;
1409
1410 if (get_user_s32(sockfd, vptr)
1411 || get_user_s32(backlog, vptr + n))
1412 return -TARGET_EFAULT;
1413
bellard7854b052003-03-29 17:22:23 +00001414 ret = get_errno(listen(sockfd, backlog));
1415 }
bellard31e31b82003-02-18 22:55:36 +00001416 break;
1417 case SOCKOP_accept:
1418 {
bellard2f619692007-11-16 10:46:05 +00001419 int sockfd;
1420 abi_ulong target_addr, target_addrlen;
1421
1422 if (get_user_s32(sockfd, vptr)
1423 || get_user_ual(target_addr, vptr + n)
1424 || get_user_u32(target_addrlen, vptr + 2 * n))
1425 return -TARGET_EFAULT;
1426
pbrook1be9e1d2006-11-19 15:26:04 +00001427 ret = do_accept(sockfd, target_addr, target_addrlen);
bellard31e31b82003-02-18 22:55:36 +00001428 }
1429 break;
1430 case SOCKOP_getsockname:
1431 {
bellard2f619692007-11-16 10:46:05 +00001432 int sockfd;
1433 abi_ulong target_addr, target_addrlen;
1434
1435 if (get_user_s32(sockfd, vptr)
1436 || get_user_ual(target_addr, vptr + n)
1437 || get_user_u32(target_addrlen, vptr + 2 * n))
1438 return -TARGET_EFAULT;
1439
pbrook1be9e1d2006-11-19 15:26:04 +00001440 ret = do_getsockname(sockfd, target_addr, target_addrlen);
bellard31e31b82003-02-18 22:55:36 +00001441 }
1442 break;
1443 case SOCKOP_getpeername:
1444 {
bellard2f619692007-11-16 10:46:05 +00001445 int sockfd;
1446 abi_ulong target_addr, target_addrlen;
1447
1448 if (get_user_s32(sockfd, vptr)
1449 || get_user_ual(target_addr, vptr + n)
1450 || get_user_u32(target_addrlen, vptr + 2 * n))
1451 return -TARGET_EFAULT;
1452
pbrook1be9e1d2006-11-19 15:26:04 +00001453 ret = do_getpeername(sockfd, target_addr, target_addrlen);
bellard31e31b82003-02-18 22:55:36 +00001454 }
1455 break;
1456 case SOCKOP_socketpair:
1457 {
bellard2f619692007-11-16 10:46:05 +00001458 int domain, type, protocol;
1459 abi_ulong tab;
1460
1461 if (get_user_s32(domain, vptr)
1462 || get_user_s32(type, vptr + n)
1463 || get_user_s32(protocol, vptr + 2 * n)
1464 || get_user_ual(tab, vptr + 3 * n))
1465 return -TARGET_EFAULT;
1466
pbrook1be9e1d2006-11-19 15:26:04 +00001467 ret = do_socketpair(domain, type, protocol, tab);
bellard31e31b82003-02-18 22:55:36 +00001468 }
1469 break;
1470 case SOCKOP_send:
bellard7854b052003-03-29 17:22:23 +00001471 {
bellard2f619692007-11-16 10:46:05 +00001472 int sockfd;
1473 abi_ulong msg;
1474 size_t len;
1475 int flags;
1476
1477 if (get_user_s32(sockfd, vptr)
1478 || get_user_ual(msg, vptr + n)
1479 || get_user_ual(len, vptr + 2 * n)
1480 || get_user_s32(flags, vptr + 3 * n))
1481 return -TARGET_EFAULT;
1482
pbrook1be9e1d2006-11-19 15:26:04 +00001483 ret = do_sendto(sockfd, msg, len, flags, 0, 0);
bellard7854b052003-03-29 17:22:23 +00001484 }
bellard31e31b82003-02-18 22:55:36 +00001485 break;
1486 case SOCKOP_recv:
bellard7854b052003-03-29 17:22:23 +00001487 {
bellard2f619692007-11-16 10:46:05 +00001488 int sockfd;
1489 abi_ulong msg;
1490 size_t len;
1491 int flags;
1492
1493 if (get_user_s32(sockfd, vptr)
1494 || get_user_ual(msg, vptr + n)
1495 || get_user_ual(len, vptr + 2 * n)
1496 || get_user_s32(flags, vptr + 3 * n))
1497 return -TARGET_EFAULT;
1498
pbrook1be9e1d2006-11-19 15:26:04 +00001499 ret = do_recvfrom(sockfd, msg, len, flags, 0, 0);
bellard7854b052003-03-29 17:22:23 +00001500 }
bellard31e31b82003-02-18 22:55:36 +00001501 break;
1502 case SOCKOP_sendto:
bellard7854b052003-03-29 17:22:23 +00001503 {
bellard2f619692007-11-16 10:46:05 +00001504 int sockfd;
1505 abi_ulong msg;
1506 size_t len;
1507 int flags;
1508 abi_ulong addr;
1509 socklen_t addrlen;
1510
1511 if (get_user_s32(sockfd, vptr)
1512 || get_user_ual(msg, vptr + n)
1513 || get_user_ual(len, vptr + 2 * n)
1514 || get_user_s32(flags, vptr + 3 * n)
1515 || get_user_ual(addr, vptr + 4 * n)
1516 || get_user_u32(addrlen, vptr + 5 * n))
1517 return -TARGET_EFAULT;
1518
pbrook1be9e1d2006-11-19 15:26:04 +00001519 ret = do_sendto(sockfd, msg, len, flags, addr, addrlen);
bellard7854b052003-03-29 17:22:23 +00001520 }
bellard31e31b82003-02-18 22:55:36 +00001521 break;
1522 case SOCKOP_recvfrom:
1523 {
bellard2f619692007-11-16 10:46:05 +00001524 int sockfd;
1525 abi_ulong msg;
1526 size_t len;
1527 int flags;
1528 abi_ulong addr;
1529 socklen_t addrlen;
1530
1531 if (get_user_s32(sockfd, vptr)
1532 || get_user_ual(msg, vptr + n)
1533 || get_user_ual(len, vptr + 2 * n)
1534 || get_user_s32(flags, vptr + 3 * n)
1535 || get_user_ual(addr, vptr + 4 * n)
1536 || get_user_u32(addrlen, vptr + 5 * n))
1537 return -TARGET_EFAULT;
1538
pbrook1be9e1d2006-11-19 15:26:04 +00001539 ret = do_recvfrom(sockfd, msg, len, flags, addr, addrlen);
bellard31e31b82003-02-18 22:55:36 +00001540 }
1541 break;
1542 case SOCKOP_shutdown:
bellard7854b052003-03-29 17:22:23 +00001543 {
bellard2f619692007-11-16 10:46:05 +00001544 int sockfd, how;
1545
1546 if (get_user_s32(sockfd, vptr)
1547 || get_user_s32(how, vptr + n))
1548 return -TARGET_EFAULT;
bellard7854b052003-03-29 17:22:23 +00001549
1550 ret = get_errno(shutdown(sockfd, how));
1551 }
bellard31e31b82003-02-18 22:55:36 +00001552 break;
1553 case SOCKOP_sendmsg:
1554 case SOCKOP_recvmsg:
bellard1a9353d2003-03-16 20:28:50 +00001555 {
1556 int fd;
blueswir1992f48a2007-10-14 16:27:31 +00001557 abi_ulong target_msg;
bellard3532fa72006-06-24 15:06:03 +00001558 int flags;
bellard1a9353d2003-03-16 20:28:50 +00001559
bellard2f619692007-11-16 10:46:05 +00001560 if (get_user_s32(fd, vptr)
1561 || get_user_ual(target_msg, vptr + n)
1562 || get_user_s32(flags, vptr + 2 * n))
1563 return -TARGET_EFAULT;
bellard3532fa72006-06-24 15:06:03 +00001564
ths5fafdf22007-09-16 21:08:06 +00001565 ret = do_sendrecvmsg(fd, target_msg, flags,
bellard3532fa72006-06-24 15:06:03 +00001566 (num == SOCKOP_sendmsg));
bellard1a9353d2003-03-16 20:28:50 +00001567 }
1568 break;
bellard31e31b82003-02-18 22:55:36 +00001569 case SOCKOP_setsockopt:
bellard7854b052003-03-29 17:22:23 +00001570 {
bellard2f619692007-11-16 10:46:05 +00001571 int sockfd;
1572 int level;
1573 int optname;
1574 abi_ulong optval;
1575 socklen_t optlen;
1576
1577 if (get_user_s32(sockfd, vptr)
1578 || get_user_s32(level, vptr + n)
1579 || get_user_s32(optname, vptr + 2 * n)
1580 || get_user_ual(optval, vptr + 3 * n)
1581 || get_user_u32(optlen, vptr + 4 * n))
1582 return -TARGET_EFAULT;
bellard7854b052003-03-29 17:22:23 +00001583
1584 ret = do_setsockopt(sockfd, level, optname, optval, optlen);
1585 }
1586 break;
bellard31e31b82003-02-18 22:55:36 +00001587 case SOCKOP_getsockopt:
bellard7854b052003-03-29 17:22:23 +00001588 {
bellard2f619692007-11-16 10:46:05 +00001589 int sockfd;
1590 int level;
1591 int optname;
1592 abi_ulong optval;
1593 socklen_t optlen;
bellard7854b052003-03-29 17:22:23 +00001594
bellard2f619692007-11-16 10:46:05 +00001595 if (get_user_s32(sockfd, vptr)
1596 || get_user_s32(level, vptr + n)
1597 || get_user_s32(optname, vptr + 2 * n)
1598 || get_user_ual(optval, vptr + 3 * n)
1599 || get_user_u32(optlen, vptr + 4 * n))
1600 return -TARGET_EFAULT;
1601
1602 ret = do_getsockopt(sockfd, level, optname, optval, optlen);
bellard7854b052003-03-29 17:22:23 +00001603 }
1604 break;
bellard31e31b82003-02-18 22:55:36 +00001605 default:
1606 gemu_log("Unsupported socketcall: %d\n", num);
ths0da46a62007-10-20 20:23:07 +00001607 ret = -TARGET_ENOSYS;
bellard31e31b82003-02-18 22:55:36 +00001608 break;
1609 }
1610 return ret;
1611}
j_mayer32407102007-09-26 23:01:49 +00001612#endif
bellard31e31b82003-02-18 22:55:36 +00001613
bellard8853f862004-02-22 14:57:26 +00001614#define N_SHM_REGIONS 32
1615
1616static struct shm_region {
bellard5a4a8982007-11-11 17:39:18 +00001617 abi_ulong start;
1618 abi_ulong size;
bellard8853f862004-02-22 14:57:26 +00001619} shm_regions[N_SHM_REGIONS];
1620
ths3eb6b042007-06-03 14:26:27 +00001621struct target_ipc_perm
1622{
blueswir1992f48a2007-10-14 16:27:31 +00001623 abi_long __key;
1624 abi_ulong uid;
1625 abi_ulong gid;
1626 abi_ulong cuid;
1627 abi_ulong cgid;
ths3eb6b042007-06-03 14:26:27 +00001628 unsigned short int mode;
1629 unsigned short int __pad1;
1630 unsigned short int __seq;
1631 unsigned short int __pad2;
blueswir1992f48a2007-10-14 16:27:31 +00001632 abi_ulong __unused1;
1633 abi_ulong __unused2;
ths3eb6b042007-06-03 14:26:27 +00001634};
1635
1636struct target_semid_ds
1637{
1638 struct target_ipc_perm sem_perm;
blueswir1992f48a2007-10-14 16:27:31 +00001639 abi_ulong sem_otime;
1640 abi_ulong __unused1;
1641 abi_ulong sem_ctime;
1642 abi_ulong __unused2;
1643 abi_ulong sem_nsems;
1644 abi_ulong __unused3;
1645 abi_ulong __unused4;
ths3eb6b042007-06-03 14:26:27 +00001646};
1647
bellard579a97f2007-11-11 14:26:47 +00001648static inline abi_long target_to_host_ipc_perm(struct ipc_perm *host_ip,
1649 abi_ulong target_addr)
ths3eb6b042007-06-03 14:26:27 +00001650{
1651 struct target_ipc_perm *target_ip;
1652 struct target_semid_ds *target_sd;
1653
bellard579a97f2007-11-11 14:26:47 +00001654 if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
1655 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00001656 target_ip=&(target_sd->sem_perm);
1657 host_ip->__key = tswapl(target_ip->__key);
1658 host_ip->uid = tswapl(target_ip->uid);
1659 host_ip->gid = tswapl(target_ip->gid);
1660 host_ip->cuid = tswapl(target_ip->cuid);
1661 host_ip->cgid = tswapl(target_ip->cgid);
1662 host_ip->mode = tswapl(target_ip->mode);
1663 unlock_user_struct(target_sd, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00001664 return 0;
ths3eb6b042007-06-03 14:26:27 +00001665}
1666
bellard579a97f2007-11-11 14:26:47 +00001667static inline abi_long host_to_target_ipc_perm(abi_ulong target_addr,
1668 struct ipc_perm *host_ip)
ths3eb6b042007-06-03 14:26:27 +00001669{
1670 struct target_ipc_perm *target_ip;
1671 struct target_semid_ds *target_sd;
1672
bellard579a97f2007-11-11 14:26:47 +00001673 if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
1674 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00001675 target_ip = &(target_sd->sem_perm);
1676 target_ip->__key = tswapl(host_ip->__key);
1677 target_ip->uid = tswapl(host_ip->uid);
1678 target_ip->gid = tswapl(host_ip->gid);
1679 target_ip->cuid = tswapl(host_ip->cuid);
1680 target_ip->cgid = tswapl(host_ip->cgid);
1681 target_ip->mode = tswapl(host_ip->mode);
1682 unlock_user_struct(target_sd, target_addr, 1);
bellard579a97f2007-11-11 14:26:47 +00001683 return 0;
ths3eb6b042007-06-03 14:26:27 +00001684}
1685
bellard579a97f2007-11-11 14:26:47 +00001686static inline abi_long target_to_host_semid_ds(struct semid_ds *host_sd,
1687 abi_ulong target_addr)
ths3eb6b042007-06-03 14:26:27 +00001688{
1689 struct target_semid_ds *target_sd;
1690
bellard579a97f2007-11-11 14:26:47 +00001691 if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
1692 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00001693 target_to_host_ipc_perm(&(host_sd->sem_perm),target_addr);
1694 host_sd->sem_nsems = tswapl(target_sd->sem_nsems);
1695 host_sd->sem_otime = tswapl(target_sd->sem_otime);
1696 host_sd->sem_ctime = tswapl(target_sd->sem_ctime);
1697 unlock_user_struct(target_sd, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00001698 return 0;
ths3eb6b042007-06-03 14:26:27 +00001699}
1700
bellard579a97f2007-11-11 14:26:47 +00001701static inline abi_long host_to_target_semid_ds(abi_ulong target_addr,
1702 struct semid_ds *host_sd)
ths3eb6b042007-06-03 14:26:27 +00001703{
1704 struct target_semid_ds *target_sd;
1705
bellard579a97f2007-11-11 14:26:47 +00001706 if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
1707 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00001708 host_to_target_ipc_perm(target_addr,&(host_sd->sem_perm));
1709 target_sd->sem_nsems = tswapl(host_sd->sem_nsems);
1710 target_sd->sem_otime = tswapl(host_sd->sem_otime);
1711 target_sd->sem_ctime = tswapl(host_sd->sem_ctime);
1712 unlock_user_struct(target_sd, target_addr, 1);
bellard579a97f2007-11-11 14:26:47 +00001713 return 0;
ths3eb6b042007-06-03 14:26:27 +00001714}
1715
thsfa294812007-02-02 22:05:00 +00001716union semun {
1717 int val;
ths3eb6b042007-06-03 14:26:27 +00001718 struct semid_ds *buf;
thsfa294812007-02-02 22:05:00 +00001719 unsigned short *array;
1720};
1721
ths3eb6b042007-06-03 14:26:27 +00001722union target_semun {
1723 int val;
blueswir1992f48a2007-10-14 16:27:31 +00001724 abi_long buf;
ths3eb6b042007-06-03 14:26:27 +00001725 unsigned short int *array;
1726};
1727
bellard579a97f2007-11-11 14:26:47 +00001728static inline abi_long target_to_host_semun(int cmd,
1729 union semun *host_su,
1730 abi_ulong target_addr,
1731 struct semid_ds *ds)
ths3eb6b042007-06-03 14:26:27 +00001732{
1733 union target_semun *target_su;
1734
1735 switch( cmd ) {
1736 case IPC_STAT:
1737 case IPC_SET:
bellard579a97f2007-11-11 14:26:47 +00001738 if (!lock_user_struct(VERIFY_READ, target_su, target_addr, 1))
1739 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00001740 target_to_host_semid_ds(ds,target_su->buf);
1741 host_su->buf = ds;
1742 unlock_user_struct(target_su, target_addr, 0);
1743 break;
1744 case GETVAL:
1745 case SETVAL:
bellard579a97f2007-11-11 14:26:47 +00001746 if (!lock_user_struct(VERIFY_READ, target_su, target_addr, 1))
1747 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00001748 host_su->val = tswapl(target_su->val);
1749 unlock_user_struct(target_su, target_addr, 0);
1750 break;
1751 case GETALL:
1752 case SETALL:
bellard579a97f2007-11-11 14:26:47 +00001753 if (!lock_user_struct(VERIFY_READ, target_su, target_addr, 1))
1754 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00001755 *host_su->array = tswap16(*target_su->array);
1756 unlock_user_struct(target_su, target_addr, 0);
1757 break;
1758 default:
1759 gemu_log("semun operation not fully supported: %d\n", (int)cmd);
1760 }
bellard579a97f2007-11-11 14:26:47 +00001761 return 0;
ths3eb6b042007-06-03 14:26:27 +00001762}
1763
bellard579a97f2007-11-11 14:26:47 +00001764static inline abi_long host_to_target_semun(int cmd,
1765 abi_ulong target_addr,
1766 union semun *host_su,
1767 struct semid_ds *ds)
ths3eb6b042007-06-03 14:26:27 +00001768{
1769 union target_semun *target_su;
1770
1771 switch( cmd ) {
1772 case IPC_STAT:
1773 case IPC_SET:
bellard579a97f2007-11-11 14:26:47 +00001774 if (lock_user_struct(VERIFY_WRITE, target_su, target_addr, 0))
1775 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00001776 host_to_target_semid_ds(target_su->buf,ds);
1777 unlock_user_struct(target_su, target_addr, 1);
1778 break;
1779 case GETVAL:
1780 case SETVAL:
bellard579a97f2007-11-11 14:26:47 +00001781 if (lock_user_struct(VERIFY_WRITE, target_su, target_addr, 0))
1782 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00001783 target_su->val = tswapl(host_su->val);
1784 unlock_user_struct(target_su, target_addr, 1);
1785 break;
1786 case GETALL:
1787 case SETALL:
bellard579a97f2007-11-11 14:26:47 +00001788 if (lock_user_struct(VERIFY_WRITE, target_su, target_addr, 0))
1789 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00001790 *target_su->array = tswap16(*host_su->array);
1791 unlock_user_struct(target_su, target_addr, 1);
1792 break;
1793 default:
1794 gemu_log("semun operation not fully supported: %d\n", (int)cmd);
1795 }
bellard579a97f2007-11-11 14:26:47 +00001796 return 0;
ths3eb6b042007-06-03 14:26:27 +00001797}
1798
blueswir1992f48a2007-10-14 16:27:31 +00001799static inline abi_long do_semctl(int first, int second, int third,
1800 abi_long ptr)
ths3eb6b042007-06-03 14:26:27 +00001801{
1802 union semun arg;
1803 struct semid_ds dsarg;
1804 int cmd = third&0xff;
blueswir1992f48a2007-10-14 16:27:31 +00001805 abi_long ret = 0;
ths3eb6b042007-06-03 14:26:27 +00001806
1807 switch( cmd ) {
1808 case GETVAL:
1809 target_to_host_semun(cmd,&arg,ptr,&dsarg);
1810 ret = get_errno(semctl(first, second, cmd, arg));
1811 host_to_target_semun(cmd,ptr,&arg,&dsarg);
1812 break;
1813 case SETVAL:
1814 target_to_host_semun(cmd,&arg,ptr,&dsarg);
1815 ret = get_errno(semctl(first, second, cmd, arg));
1816 host_to_target_semun(cmd,ptr,&arg,&dsarg);
1817 break;
1818 case GETALL:
1819 target_to_host_semun(cmd,&arg,ptr,&dsarg);
1820 ret = get_errno(semctl(first, second, cmd, arg));
1821 host_to_target_semun(cmd,ptr,&arg,&dsarg);
1822 break;
1823 case SETALL:
1824 target_to_host_semun(cmd,&arg,ptr,&dsarg);
1825 ret = get_errno(semctl(first, second, cmd, arg));
1826 host_to_target_semun(cmd,ptr,&arg,&dsarg);
1827 break;
1828 case IPC_STAT:
1829 target_to_host_semun(cmd,&arg,ptr,&dsarg);
1830 ret = get_errno(semctl(first, second, cmd, arg));
1831 host_to_target_semun(cmd,ptr,&arg,&dsarg);
1832 break;
1833 case IPC_SET:
1834 target_to_host_semun(cmd,&arg,ptr,&dsarg);
1835 ret = get_errno(semctl(first, second, cmd, arg));
1836 host_to_target_semun(cmd,ptr,&arg,&dsarg);
1837 break;
1838 default:
1839 ret = get_errno(semctl(first, second, cmd, arg));
1840 }
1841
1842 return ret;
1843}
1844
ths1bc012f2007-06-03 14:27:49 +00001845struct target_msqid_ds
1846{
aurel321c54ff92008-10-13 21:08:44 +00001847 struct target_ipc_perm msg_perm;
1848 abi_ulong msg_stime;
1849#if TARGET_ABI_BITS == 32
1850 abi_ulong __unused1;
1851#endif
1852 abi_ulong msg_rtime;
1853#if TARGET_ABI_BITS == 32
1854 abi_ulong __unused2;
1855#endif
1856 abi_ulong msg_ctime;
1857#if TARGET_ABI_BITS == 32
1858 abi_ulong __unused3;
1859#endif
1860 abi_ulong __msg_cbytes;
1861 abi_ulong msg_qnum;
1862 abi_ulong msg_qbytes;
1863 abi_ulong msg_lspid;
1864 abi_ulong msg_lrpid;
1865 abi_ulong __unused4;
1866 abi_ulong __unused5;
ths1bc012f2007-06-03 14:27:49 +00001867};
1868
bellard579a97f2007-11-11 14:26:47 +00001869static inline abi_long target_to_host_msqid_ds(struct msqid_ds *host_md,
1870 abi_ulong target_addr)
ths1bc012f2007-06-03 14:27:49 +00001871{
1872 struct target_msqid_ds *target_md;
1873
bellard579a97f2007-11-11 14:26:47 +00001874 if (!lock_user_struct(VERIFY_READ, target_md, target_addr, 1))
1875 return -TARGET_EFAULT;
aurel321c54ff92008-10-13 21:08:44 +00001876 if (target_to_host_ipc_perm(&(host_md->msg_perm),target_addr))
1877 return -TARGET_EFAULT;
ths1bc012f2007-06-03 14:27:49 +00001878 host_md->msg_stime = tswapl(target_md->msg_stime);
1879 host_md->msg_rtime = tswapl(target_md->msg_rtime);
1880 host_md->msg_ctime = tswapl(target_md->msg_ctime);
1881 host_md->__msg_cbytes = tswapl(target_md->__msg_cbytes);
1882 host_md->msg_qnum = tswapl(target_md->msg_qnum);
1883 host_md->msg_qbytes = tswapl(target_md->msg_qbytes);
1884 host_md->msg_lspid = tswapl(target_md->msg_lspid);
1885 host_md->msg_lrpid = tswapl(target_md->msg_lrpid);
1886 unlock_user_struct(target_md, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00001887 return 0;
ths1bc012f2007-06-03 14:27:49 +00001888}
1889
bellard579a97f2007-11-11 14:26:47 +00001890static inline abi_long host_to_target_msqid_ds(abi_ulong target_addr,
1891 struct msqid_ds *host_md)
ths1bc012f2007-06-03 14:27:49 +00001892{
1893 struct target_msqid_ds *target_md;
1894
bellard579a97f2007-11-11 14:26:47 +00001895 if (!lock_user_struct(VERIFY_WRITE, target_md, target_addr, 0))
1896 return -TARGET_EFAULT;
aurel321c54ff92008-10-13 21:08:44 +00001897 if (host_to_target_ipc_perm(target_addr,&(host_md->msg_perm)))
1898 return -TARGET_EFAULT;
ths1bc012f2007-06-03 14:27:49 +00001899 target_md->msg_stime = tswapl(host_md->msg_stime);
1900 target_md->msg_rtime = tswapl(host_md->msg_rtime);
1901 target_md->msg_ctime = tswapl(host_md->msg_ctime);
1902 target_md->__msg_cbytes = tswapl(host_md->__msg_cbytes);
1903 target_md->msg_qnum = tswapl(host_md->msg_qnum);
1904 target_md->msg_qbytes = tswapl(host_md->msg_qbytes);
1905 target_md->msg_lspid = tswapl(host_md->msg_lspid);
1906 target_md->msg_lrpid = tswapl(host_md->msg_lrpid);
1907 unlock_user_struct(target_md, target_addr, 1);
bellard579a97f2007-11-11 14:26:47 +00001908 return 0;
ths1bc012f2007-06-03 14:27:49 +00001909}
1910
aurel321c54ff92008-10-13 21:08:44 +00001911struct target_msginfo {
1912 int msgpool;
1913 int msgmap;
1914 int msgmax;
1915 int msgmnb;
1916 int msgmni;
1917 int msgssz;
1918 int msgtql;
1919 unsigned short int msgseg;
1920};
1921
1922static inline abi_long host_to_target_msginfo(abi_ulong target_addr,
1923 struct msginfo *host_msginfo)
1924{
1925 struct target_msginfo *target_msginfo;
1926 if (!lock_user_struct(VERIFY_WRITE, target_msginfo, target_addr, 0))
1927 return -TARGET_EFAULT;
1928 __put_user(host_msginfo->msgpool, &target_msginfo->msgpool);
1929 __put_user(host_msginfo->msgmap, &target_msginfo->msgmap);
1930 __put_user(host_msginfo->msgmax, &target_msginfo->msgmax);
1931 __put_user(host_msginfo->msgmnb, &target_msginfo->msgmnb);
1932 __put_user(host_msginfo->msgmni, &target_msginfo->msgmni);
1933 __put_user(host_msginfo->msgssz, &target_msginfo->msgssz);
1934 __put_user(host_msginfo->msgtql, &target_msginfo->msgtql);
1935 __put_user(host_msginfo->msgseg, &target_msginfo->msgseg);
1936 unlock_user_struct(target_msginfo, target_addr, 1);
1937}
1938
1939static inline abi_long do_msgctl(int msgid, int cmd, abi_long ptr)
ths1bc012f2007-06-03 14:27:49 +00001940{
1941 struct msqid_ds dsarg;
aurel321c54ff92008-10-13 21:08:44 +00001942 struct msginfo msginfo;
1943 abi_long ret = -TARGET_EINVAL;
1944
1945 cmd &= 0xff;
1946
1947 switch (cmd) {
ths1bc012f2007-06-03 14:27:49 +00001948 case IPC_STAT:
1949 case IPC_SET:
aurel321c54ff92008-10-13 21:08:44 +00001950 case MSG_STAT:
1951 if (target_to_host_msqid_ds(&dsarg,ptr))
1952 return -TARGET_EFAULT;
1953 ret = get_errno(msgctl(msgid, cmd, &dsarg));
1954 if (host_to_target_msqid_ds(ptr,&dsarg))
1955 return -TARGET_EFAULT;
1956 break;
1957 case IPC_RMID:
1958 ret = get_errno(msgctl(msgid, cmd, NULL));
1959 break;
1960 case IPC_INFO:
1961 case MSG_INFO:
1962 ret = get_errno(msgctl(msgid, cmd, (struct msqid_ds *)&msginfo));
1963 if (host_to_target_msginfo(ptr, &msginfo))
1964 return -TARGET_EFAULT;
1965 break;
ths1bc012f2007-06-03 14:27:49 +00001966 }
aurel321c54ff92008-10-13 21:08:44 +00001967
ths1bc012f2007-06-03 14:27:49 +00001968 return ret;
1969}
1970
1971struct target_msgbuf {
aurel321c54ff92008-10-13 21:08:44 +00001972 abi_long mtype;
1973 char mtext[1];
ths1bc012f2007-06-03 14:27:49 +00001974};
1975
blueswir1992f48a2007-10-14 16:27:31 +00001976static inline abi_long do_msgsnd(int msqid, abi_long msgp,
1977 unsigned int msgsz, int msgflg)
ths1bc012f2007-06-03 14:27:49 +00001978{
1979 struct target_msgbuf *target_mb;
1980 struct msgbuf *host_mb;
blueswir1992f48a2007-10-14 16:27:31 +00001981 abi_long ret = 0;
ths1bc012f2007-06-03 14:27:49 +00001982
bellard579a97f2007-11-11 14:26:47 +00001983 if (!lock_user_struct(VERIFY_READ, target_mb, msgp, 0))
1984 return -TARGET_EFAULT;
ths1bc012f2007-06-03 14:27:49 +00001985 host_mb = malloc(msgsz+sizeof(long));
aurel321c54ff92008-10-13 21:08:44 +00001986 host_mb->mtype = (abi_long) tswapl(target_mb->mtype);
1987 memcpy(host_mb->mtext, target_mb->mtext, msgsz);
ths1bc012f2007-06-03 14:27:49 +00001988 ret = get_errno(msgsnd(msqid, host_mb, msgsz, msgflg));
1989 free(host_mb);
1990 unlock_user_struct(target_mb, msgp, 0);
1991
1992 return ret;
1993}
1994
blueswir1992f48a2007-10-14 16:27:31 +00001995static inline abi_long do_msgrcv(int msqid, abi_long msgp,
aurel321c54ff92008-10-13 21:08:44 +00001996 unsigned int msgsz, abi_long msgtyp,
blueswir1992f48a2007-10-14 16:27:31 +00001997 int msgflg)
ths1bc012f2007-06-03 14:27:49 +00001998{
1999 struct target_msgbuf *target_mb;
bellard579a97f2007-11-11 14:26:47 +00002000 char *target_mtext;
ths1bc012f2007-06-03 14:27:49 +00002001 struct msgbuf *host_mb;
blueswir1992f48a2007-10-14 16:27:31 +00002002 abi_long ret = 0;
ths1bc012f2007-06-03 14:27:49 +00002003
bellard579a97f2007-11-11 14:26:47 +00002004 if (!lock_user_struct(VERIFY_WRITE, target_mb, msgp, 0))
2005 return -TARGET_EFAULT;
aurel321c54ff92008-10-13 21:08:44 +00002006
ths1bc012f2007-06-03 14:27:49 +00002007 host_mb = malloc(msgsz+sizeof(long));
aurel321c54ff92008-10-13 21:08:44 +00002008 ret = get_errno(msgrcv(msqid, host_mb, msgsz, tswapl(msgtyp), msgflg));
2009
bellard579a97f2007-11-11 14:26:47 +00002010 if (ret > 0) {
2011 abi_ulong target_mtext_addr = msgp + sizeof(abi_ulong);
2012 target_mtext = lock_user(VERIFY_WRITE, target_mtext_addr, ret, 0);
2013 if (!target_mtext) {
2014 ret = -TARGET_EFAULT;
2015 goto end;
2016 }
aurel321c54ff92008-10-13 21:08:44 +00002017 memcpy(target_mb->mtext, host_mb->mtext, ret);
bellard579a97f2007-11-11 14:26:47 +00002018 unlock_user(target_mtext, target_mtext_addr, ret);
2019 }
aurel321c54ff92008-10-13 21:08:44 +00002020
ths1bc012f2007-06-03 14:27:49 +00002021 target_mb->mtype = tswapl(host_mb->mtype);
2022 free(host_mb);
ths1bc012f2007-06-03 14:27:49 +00002023
bellard579a97f2007-11-11 14:26:47 +00002024end:
2025 if (target_mb)
2026 unlock_user_struct(target_mb, msgp, 1);
ths1bc012f2007-06-03 14:27:49 +00002027 return ret;
2028}
2029
aurel321c54ff92008-10-13 21:08:44 +00002030#ifdef TARGET_NR_ipc
pbrook53a59602006-03-25 19:31:22 +00002031/* ??? This only works with linear mappings. */
ths0da46a62007-10-20 20:23:07 +00002032/* do_ipc() must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00002033static abi_long do_ipc(unsigned int call, int first,
2034 int second, int third,
2035 abi_long ptr, abi_long fifth)
bellard8853f862004-02-22 14:57:26 +00002036{
2037 int version;
blueswir1992f48a2007-10-14 16:27:31 +00002038 abi_long ret = 0;
bellard8853f862004-02-22 14:57:26 +00002039 struct shmid_ds shm_info;
2040 int i;
2041
2042 version = call >> 16;
2043 call &= 0xffff;
2044
2045 switch (call) {
thsfa294812007-02-02 22:05:00 +00002046 case IPCOP_semop:
bellard579a97f2007-11-11 14:26:47 +00002047 ret = get_errno(semop(first,(struct sembuf *)g2h(ptr), second));
thsfa294812007-02-02 22:05:00 +00002048 break;
2049
2050 case IPCOP_semget:
2051 ret = get_errno(semget(first, second, third));
2052 break;
2053
2054 case IPCOP_semctl:
ths3eb6b042007-06-03 14:26:27 +00002055 ret = do_semctl(first, second, third, ptr);
thsfa294812007-02-02 22:05:00 +00002056 break;
2057
2058 case IPCOP_semtimedop:
j_mayer32407102007-09-26 23:01:49 +00002059 gemu_log("Unsupported ipc call: %d (version %d)\n", call, version);
ths0da46a62007-10-20 20:23:07 +00002060 ret = -TARGET_ENOSYS;
thsfa294812007-02-02 22:05:00 +00002061 break;
thsd96372e2007-02-02 22:05:44 +00002062
aurel321c54ff92008-10-13 21:08:44 +00002063 case IPCOP_msgget:
2064 ret = get_errno(msgget(first, second));
2065 break;
thsd96372e2007-02-02 22:05:44 +00002066
aurel321c54ff92008-10-13 21:08:44 +00002067 case IPCOP_msgsnd:
2068 ret = do_msgsnd(first, ptr, second, third);
2069 break;
thsd96372e2007-02-02 22:05:44 +00002070
aurel321c54ff92008-10-13 21:08:44 +00002071 case IPCOP_msgctl:
2072 ret = do_msgctl(first, second, ptr);
2073 break;
thsd96372e2007-02-02 22:05:44 +00002074
aurel321c54ff92008-10-13 21:08:44 +00002075 case IPCOP_msgrcv:
2076 switch (version) {
2077 case 0:
2078 {
2079 struct target_ipc_kludge {
2080 abi_long msgp;
2081 abi_long msgtyp;
2082 } *tmp;
thsd96372e2007-02-02 22:05:44 +00002083
aurel321c54ff92008-10-13 21:08:44 +00002084 if (!lock_user_struct(VERIFY_READ, tmp, ptr, 1)) {
2085 ret = -TARGET_EFAULT;
2086 break;
ths1bc012f2007-06-03 14:27:49 +00002087 }
aurel321c54ff92008-10-13 21:08:44 +00002088
2089 ret = do_msgrcv(first, tmp->msgp, second, tmp->msgtyp, third);
2090
2091 unlock_user_struct(tmp, ptr, 0);
2092 break;
2093 }
2094 default:
2095 ret = do_msgrcv(first, ptr, second, fifth, third);
2096 }
2097 break;
thsd96372e2007-02-02 22:05:44 +00002098
bellard8853f862004-02-22 14:57:26 +00002099 case IPCOP_shmat:
bellard5a4a8982007-11-11 17:39:18 +00002100 {
2101 abi_ulong raddr;
2102 void *host_addr;
2103 /* SHM_* flags are the same on all linux platforms */
2104 host_addr = shmat(first, (void *)g2h(ptr), second);
2105 if (host_addr == (void *)-1) {
2106 ret = get_errno((long)host_addr);
bellard8853f862004-02-22 14:57:26 +00002107 break;
bellard5a4a8982007-11-11 17:39:18 +00002108 }
2109 raddr = h2g((unsigned long)host_addr);
2110 /* find out the length of the shared memory segment */
2111
2112 ret = get_errno(shmctl(first, IPC_STAT, &shm_info));
2113 if (is_error(ret)) {
2114 /* can't get length, bail out */
2115 shmdt(host_addr);
2116 break;
2117 }
2118 page_set_flags(raddr, raddr + shm_info.shm_segsz,
2119 PAGE_VALID | PAGE_READ |
2120 ((second & SHM_RDONLY)? 0: PAGE_WRITE));
2121 for (i = 0; i < N_SHM_REGIONS; ++i) {
2122 if (shm_regions[i].start == 0) {
2123 shm_regions[i].start = raddr;
2124 shm_regions[i].size = shm_info.shm_segsz;
2125 break;
2126 }
2127 }
bellard2f619692007-11-16 10:46:05 +00002128 if (put_user_ual(raddr, third))
bellard5a4a8982007-11-11 17:39:18 +00002129 return -TARGET_EFAULT;
2130 ret = 0;
2131 }
bellard8853f862004-02-22 14:57:26 +00002132 break;
2133 case IPCOP_shmdt:
2134 for (i = 0; i < N_SHM_REGIONS; ++i) {
2135 if (shm_regions[i].start == ptr) {
2136 shm_regions[i].start = 0;
2137 page_set_flags(ptr, shm_regions[i].size, 0);
2138 break;
2139 }
2140 }
bellard5a4a8982007-11-11 17:39:18 +00002141 ret = get_errno(shmdt((void *)g2h(ptr)));
bellard8853f862004-02-22 14:57:26 +00002142 break;
2143
2144 case IPCOP_shmget:
2145 /* IPC_* flag values are the same on all linux platforms */
2146 ret = get_errno(shmget(first, second, third));
2147 break;
2148
2149 /* IPC_* and SHM_* command values are the same on all linux platforms */
2150 case IPCOP_shmctl:
2151 switch(second) {
2152 case IPC_RMID:
2153 case SHM_LOCK:
2154 case SHM_UNLOCK:
2155 ret = get_errno(shmctl(first, second, NULL));
2156 break;
2157 default:
2158 goto unimplemented;
2159 }
2160 break;
2161 default:
2162 unimplemented:
j_mayer32407102007-09-26 23:01:49 +00002163 gemu_log("Unsupported ipc call: %d (version %d)\n", call, version);
ths0da46a62007-10-20 20:23:07 +00002164 ret = -TARGET_ENOSYS;
bellard8853f862004-02-22 14:57:26 +00002165 break;
2166 }
2167 return ret;
2168}
j_mayer32407102007-09-26 23:01:49 +00002169#endif
bellard8853f862004-02-22 14:57:26 +00002170
bellard31e31b82003-02-18 22:55:36 +00002171/* kernel structure types definitions */
2172#define IFNAMSIZ 16
2173
2174#define STRUCT(name, list...) STRUCT_ ## name,
2175#define STRUCT_SPECIAL(name) STRUCT_ ## name,
2176enum {
2177#include "syscall_types.h"
2178};
2179#undef STRUCT
2180#undef STRUCT_SPECIAL
2181
blueswir160dd3162008-10-05 11:45:25 +00002182#define STRUCT(name, list...) static const argtype struct_ ## name ## _def[] = { list, TYPE_NULL };
bellard31e31b82003-02-18 22:55:36 +00002183#define STRUCT_SPECIAL(name)
2184#include "syscall_types.h"
2185#undef STRUCT
2186#undef STRUCT_SPECIAL
2187
2188typedef struct IOCTLEntry {
bellard2ab83ea2003-06-15 19:56:46 +00002189 unsigned int target_cmd;
2190 unsigned int host_cmd;
bellard31e31b82003-02-18 22:55:36 +00002191 const char *name;
2192 int access;
bellard1a9353d2003-03-16 20:28:50 +00002193 const argtype arg_type[5];
bellard31e31b82003-02-18 22:55:36 +00002194} IOCTLEntry;
2195
2196#define IOC_R 0x0001
2197#define IOC_W 0x0002
2198#define IOC_RW (IOC_R | IOC_W)
2199
2200#define MAX_STRUCT_SIZE 4096
2201
blueswir19f106a72008-10-05 10:52:52 +00002202static IOCTLEntry ioctl_entries[] = {
bellard31e31b82003-02-18 22:55:36 +00002203#define IOCTL(cmd, access, types...) \
2204 { TARGET_ ## cmd, cmd, #cmd, access, { types } },
2205#include "ioctls.h"
2206 { 0, 0, },
2207};
2208
pbrook53a59602006-03-25 19:31:22 +00002209/* ??? Implement proper locking for ioctls. */
ths0da46a62007-10-20 20:23:07 +00002210/* do_ioctl() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00002211static abi_long do_ioctl(int fd, abi_long cmd, abi_long arg)
bellard31e31b82003-02-18 22:55:36 +00002212{
2213 const IOCTLEntry *ie;
2214 const argtype *arg_type;
blueswir1992f48a2007-10-14 16:27:31 +00002215 abi_long ret;
bellard31e31b82003-02-18 22:55:36 +00002216 uint8_t buf_temp[MAX_STRUCT_SIZE];
pbrook53a59602006-03-25 19:31:22 +00002217 int target_size;
2218 void *argptr;
bellard31e31b82003-02-18 22:55:36 +00002219
2220 ie = ioctl_entries;
2221 for(;;) {
2222 if (ie->target_cmd == 0) {
j_mayer32407102007-09-26 23:01:49 +00002223 gemu_log("Unsupported ioctl: cmd=0x%04lx\n", (long)cmd);
ths0da46a62007-10-20 20:23:07 +00002224 return -TARGET_ENOSYS;
bellard31e31b82003-02-18 22:55:36 +00002225 }
2226 if (ie->target_cmd == cmd)
2227 break;
2228 ie++;
2229 }
2230 arg_type = ie->arg_type;
bellard9de5e442003-03-23 16:49:39 +00002231#if defined(DEBUG)
j_mayer32407102007-09-26 23:01:49 +00002232 gemu_log("ioctl: cmd=0x%04lx (%s)\n", (long)cmd, ie->name);
bellard72f03902003-02-18 23:33:18 +00002233#endif
bellard31e31b82003-02-18 22:55:36 +00002234 switch(arg_type[0]) {
2235 case TYPE_NULL:
2236 /* no argument */
2237 ret = get_errno(ioctl(fd, ie->host_cmd));
2238 break;
2239 case TYPE_PTRVOID:
2240 case TYPE_INT:
2241 /* int argment */
2242 ret = get_errno(ioctl(fd, ie->host_cmd, arg));
2243 break;
2244 case TYPE_PTR:
2245 arg_type++;
pbrook53a59602006-03-25 19:31:22 +00002246 target_size = thunk_type_size(arg_type, 0);
bellard31e31b82003-02-18 22:55:36 +00002247 switch(ie->access) {
2248 case IOC_R:
2249 ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
2250 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00002251 argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
2252 if (!argptr)
2253 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00002254 thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
2255 unlock_user(argptr, arg, target_size);
bellard31e31b82003-02-18 22:55:36 +00002256 }
2257 break;
2258 case IOC_W:
bellard579a97f2007-11-11 14:26:47 +00002259 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
2260 if (!argptr)
2261 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00002262 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
2263 unlock_user(argptr, arg, 0);
bellard31e31b82003-02-18 22:55:36 +00002264 ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
2265 break;
2266 default:
2267 case IOC_RW:
bellard579a97f2007-11-11 14:26:47 +00002268 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
2269 if (!argptr)
2270 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00002271 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
2272 unlock_user(argptr, arg, 0);
bellard31e31b82003-02-18 22:55:36 +00002273 ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
2274 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00002275 argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
2276 if (!argptr)
2277 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00002278 thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
2279 unlock_user(argptr, arg, target_size);
bellard31e31b82003-02-18 22:55:36 +00002280 }
2281 break;
2282 }
2283 break;
2284 default:
j_mayer32407102007-09-26 23:01:49 +00002285 gemu_log("Unsupported ioctl type: cmd=0x%04lx type=%d\n",
2286 (long)cmd, arg_type[0]);
ths0da46a62007-10-20 20:23:07 +00002287 ret = -TARGET_ENOSYS;
bellard31e31b82003-02-18 22:55:36 +00002288 break;
2289 }
2290 return ret;
2291}
2292
blueswir1b39bc502008-10-05 10:51:10 +00002293static const bitmask_transtbl iflag_tbl[] = {
bellard31e31b82003-02-18 22:55:36 +00002294 { TARGET_IGNBRK, TARGET_IGNBRK, IGNBRK, IGNBRK },
2295 { TARGET_BRKINT, TARGET_BRKINT, BRKINT, BRKINT },
2296 { TARGET_IGNPAR, TARGET_IGNPAR, IGNPAR, IGNPAR },
2297 { TARGET_PARMRK, TARGET_PARMRK, PARMRK, PARMRK },
2298 { TARGET_INPCK, TARGET_INPCK, INPCK, INPCK },
2299 { TARGET_ISTRIP, TARGET_ISTRIP, ISTRIP, ISTRIP },
2300 { TARGET_INLCR, TARGET_INLCR, INLCR, INLCR },
2301 { TARGET_IGNCR, TARGET_IGNCR, IGNCR, IGNCR },
2302 { TARGET_ICRNL, TARGET_ICRNL, ICRNL, ICRNL },
2303 { TARGET_IUCLC, TARGET_IUCLC, IUCLC, IUCLC },
2304 { TARGET_IXON, TARGET_IXON, IXON, IXON },
2305 { TARGET_IXANY, TARGET_IXANY, IXANY, IXANY },
2306 { TARGET_IXOFF, TARGET_IXOFF, IXOFF, IXOFF },
2307 { TARGET_IMAXBEL, TARGET_IMAXBEL, IMAXBEL, IMAXBEL },
2308 { 0, 0, 0, 0 }
2309};
2310
blueswir1b39bc502008-10-05 10:51:10 +00002311static const bitmask_transtbl oflag_tbl[] = {
bellard31e31b82003-02-18 22:55:36 +00002312 { TARGET_OPOST, TARGET_OPOST, OPOST, OPOST },
2313 { TARGET_OLCUC, TARGET_OLCUC, OLCUC, OLCUC },
2314 { TARGET_ONLCR, TARGET_ONLCR, ONLCR, ONLCR },
2315 { TARGET_OCRNL, TARGET_OCRNL, OCRNL, OCRNL },
2316 { TARGET_ONOCR, TARGET_ONOCR, ONOCR, ONOCR },
2317 { TARGET_ONLRET, TARGET_ONLRET, ONLRET, ONLRET },
2318 { TARGET_OFILL, TARGET_OFILL, OFILL, OFILL },
2319 { TARGET_OFDEL, TARGET_OFDEL, OFDEL, OFDEL },
2320 { TARGET_NLDLY, TARGET_NL0, NLDLY, NL0 },
2321 { TARGET_NLDLY, TARGET_NL1, NLDLY, NL1 },
2322 { TARGET_CRDLY, TARGET_CR0, CRDLY, CR0 },
2323 { TARGET_CRDLY, TARGET_CR1, CRDLY, CR1 },
2324 { TARGET_CRDLY, TARGET_CR2, CRDLY, CR2 },
2325 { TARGET_CRDLY, TARGET_CR3, CRDLY, CR3 },
2326 { TARGET_TABDLY, TARGET_TAB0, TABDLY, TAB0 },
2327 { TARGET_TABDLY, TARGET_TAB1, TABDLY, TAB1 },
2328 { TARGET_TABDLY, TARGET_TAB2, TABDLY, TAB2 },
2329 { TARGET_TABDLY, TARGET_TAB3, TABDLY, TAB3 },
2330 { TARGET_BSDLY, TARGET_BS0, BSDLY, BS0 },
2331 { TARGET_BSDLY, TARGET_BS1, BSDLY, BS1 },
2332 { TARGET_VTDLY, TARGET_VT0, VTDLY, VT0 },
2333 { TARGET_VTDLY, TARGET_VT1, VTDLY, VT1 },
2334 { TARGET_FFDLY, TARGET_FF0, FFDLY, FF0 },
2335 { TARGET_FFDLY, TARGET_FF1, FFDLY, FF1 },
2336 { 0, 0, 0, 0 }
2337};
2338
blueswir1b39bc502008-10-05 10:51:10 +00002339static const bitmask_transtbl cflag_tbl[] = {
bellard31e31b82003-02-18 22:55:36 +00002340 { TARGET_CBAUD, TARGET_B0, CBAUD, B0 },
2341 { TARGET_CBAUD, TARGET_B50, CBAUD, B50 },
2342 { TARGET_CBAUD, TARGET_B75, CBAUD, B75 },
2343 { TARGET_CBAUD, TARGET_B110, CBAUD, B110 },
2344 { TARGET_CBAUD, TARGET_B134, CBAUD, B134 },
2345 { TARGET_CBAUD, TARGET_B150, CBAUD, B150 },
2346 { TARGET_CBAUD, TARGET_B200, CBAUD, B200 },
2347 { TARGET_CBAUD, TARGET_B300, CBAUD, B300 },
2348 { TARGET_CBAUD, TARGET_B600, CBAUD, B600 },
2349 { TARGET_CBAUD, TARGET_B1200, CBAUD, B1200 },
2350 { TARGET_CBAUD, TARGET_B1800, CBAUD, B1800 },
2351 { TARGET_CBAUD, TARGET_B2400, CBAUD, B2400 },
2352 { TARGET_CBAUD, TARGET_B4800, CBAUD, B4800 },
2353 { TARGET_CBAUD, TARGET_B9600, CBAUD, B9600 },
2354 { TARGET_CBAUD, TARGET_B19200, CBAUD, B19200 },
2355 { TARGET_CBAUD, TARGET_B38400, CBAUD, B38400 },
2356 { TARGET_CBAUD, TARGET_B57600, CBAUD, B57600 },
2357 { TARGET_CBAUD, TARGET_B115200, CBAUD, B115200 },
2358 { TARGET_CBAUD, TARGET_B230400, CBAUD, B230400 },
2359 { TARGET_CBAUD, TARGET_B460800, CBAUD, B460800 },
2360 { TARGET_CSIZE, TARGET_CS5, CSIZE, CS5 },
2361 { TARGET_CSIZE, TARGET_CS6, CSIZE, CS6 },
2362 { TARGET_CSIZE, TARGET_CS7, CSIZE, CS7 },
2363 { TARGET_CSIZE, TARGET_CS8, CSIZE, CS8 },
2364 { TARGET_CSTOPB, TARGET_CSTOPB, CSTOPB, CSTOPB },
2365 { TARGET_CREAD, TARGET_CREAD, CREAD, CREAD },
2366 { TARGET_PARENB, TARGET_PARENB, PARENB, PARENB },
2367 { TARGET_PARODD, TARGET_PARODD, PARODD, PARODD },
2368 { TARGET_HUPCL, TARGET_HUPCL, HUPCL, HUPCL },
2369 { TARGET_CLOCAL, TARGET_CLOCAL, CLOCAL, CLOCAL },
2370 { TARGET_CRTSCTS, TARGET_CRTSCTS, CRTSCTS, CRTSCTS },
2371 { 0, 0, 0, 0 }
2372};
2373
blueswir1b39bc502008-10-05 10:51:10 +00002374static const bitmask_transtbl lflag_tbl[] = {
bellard31e31b82003-02-18 22:55:36 +00002375 { TARGET_ISIG, TARGET_ISIG, ISIG, ISIG },
2376 { TARGET_ICANON, TARGET_ICANON, ICANON, ICANON },
2377 { TARGET_XCASE, TARGET_XCASE, XCASE, XCASE },
2378 { TARGET_ECHO, TARGET_ECHO, ECHO, ECHO },
2379 { TARGET_ECHOE, TARGET_ECHOE, ECHOE, ECHOE },
2380 { TARGET_ECHOK, TARGET_ECHOK, ECHOK, ECHOK },
2381 { TARGET_ECHONL, TARGET_ECHONL, ECHONL, ECHONL },
2382 { TARGET_NOFLSH, TARGET_NOFLSH, NOFLSH, NOFLSH },
2383 { TARGET_TOSTOP, TARGET_TOSTOP, TOSTOP, TOSTOP },
2384 { TARGET_ECHOCTL, TARGET_ECHOCTL, ECHOCTL, ECHOCTL },
2385 { TARGET_ECHOPRT, TARGET_ECHOPRT, ECHOPRT, ECHOPRT },
2386 { TARGET_ECHOKE, TARGET_ECHOKE, ECHOKE, ECHOKE },
2387 { TARGET_FLUSHO, TARGET_FLUSHO, FLUSHO, FLUSHO },
2388 { TARGET_PENDIN, TARGET_PENDIN, PENDIN, PENDIN },
2389 { TARGET_IEXTEN, TARGET_IEXTEN, IEXTEN, IEXTEN },
2390 { 0, 0, 0, 0 }
2391};
2392
2393static void target_to_host_termios (void *dst, const void *src)
2394{
2395 struct host_termios *host = dst;
2396 const struct target_termios *target = src;
ths3b46e622007-09-17 08:09:54 +00002397
ths5fafdf22007-09-16 21:08:06 +00002398 host->c_iflag =
bellard31e31b82003-02-18 22:55:36 +00002399 target_to_host_bitmask(tswap32(target->c_iflag), iflag_tbl);
ths5fafdf22007-09-16 21:08:06 +00002400 host->c_oflag =
bellard31e31b82003-02-18 22:55:36 +00002401 target_to_host_bitmask(tswap32(target->c_oflag), oflag_tbl);
ths5fafdf22007-09-16 21:08:06 +00002402 host->c_cflag =
bellard31e31b82003-02-18 22:55:36 +00002403 target_to_host_bitmask(tswap32(target->c_cflag), cflag_tbl);
ths5fafdf22007-09-16 21:08:06 +00002404 host->c_lflag =
bellard31e31b82003-02-18 22:55:36 +00002405 target_to_host_bitmask(tswap32(target->c_lflag), lflag_tbl);
2406 host->c_line = target->c_line;
ths3b46e622007-09-17 08:09:54 +00002407
ths5fafdf22007-09-16 21:08:06 +00002408 host->c_cc[VINTR] = target->c_cc[TARGET_VINTR];
2409 host->c_cc[VQUIT] = target->c_cc[TARGET_VQUIT];
ths3b46e622007-09-17 08:09:54 +00002410 host->c_cc[VERASE] = target->c_cc[TARGET_VERASE];
ths5fafdf22007-09-16 21:08:06 +00002411 host->c_cc[VKILL] = target->c_cc[TARGET_VKILL];
ths3b46e622007-09-17 08:09:54 +00002412 host->c_cc[VEOF] = target->c_cc[TARGET_VEOF];
ths5fafdf22007-09-16 21:08:06 +00002413 host->c_cc[VTIME] = target->c_cc[TARGET_VTIME];
ths3b46e622007-09-17 08:09:54 +00002414 host->c_cc[VMIN] = target->c_cc[TARGET_VMIN];
ths5fafdf22007-09-16 21:08:06 +00002415 host->c_cc[VSWTC] = target->c_cc[TARGET_VSWTC];
ths3b46e622007-09-17 08:09:54 +00002416 host->c_cc[VSTART] = target->c_cc[TARGET_VSTART];
ths5fafdf22007-09-16 21:08:06 +00002417 host->c_cc[VSTOP] = target->c_cc[TARGET_VSTOP];
2418 host->c_cc[VSUSP] = target->c_cc[TARGET_VSUSP];
ths3b46e622007-09-17 08:09:54 +00002419 host->c_cc[VEOL] = target->c_cc[TARGET_VEOL];
2420 host->c_cc[VREPRINT] = target->c_cc[TARGET_VREPRINT];
2421 host->c_cc[VDISCARD] = target->c_cc[TARGET_VDISCARD];
2422 host->c_cc[VWERASE] = target->c_cc[TARGET_VWERASE];
2423 host->c_cc[VLNEXT] = target->c_cc[TARGET_VLNEXT];
ths5fafdf22007-09-16 21:08:06 +00002424 host->c_cc[VEOL2] = target->c_cc[TARGET_VEOL2];
bellard31e31b82003-02-18 22:55:36 +00002425}
ths3b46e622007-09-17 08:09:54 +00002426
bellard31e31b82003-02-18 22:55:36 +00002427static void host_to_target_termios (void *dst, const void *src)
2428{
2429 struct target_termios *target = dst;
2430 const struct host_termios *host = src;
2431
ths5fafdf22007-09-16 21:08:06 +00002432 target->c_iflag =
bellard31e31b82003-02-18 22:55:36 +00002433 tswap32(host_to_target_bitmask(host->c_iflag, iflag_tbl));
ths5fafdf22007-09-16 21:08:06 +00002434 target->c_oflag =
bellard31e31b82003-02-18 22:55:36 +00002435 tswap32(host_to_target_bitmask(host->c_oflag, oflag_tbl));
ths5fafdf22007-09-16 21:08:06 +00002436 target->c_cflag =
bellard31e31b82003-02-18 22:55:36 +00002437 tswap32(host_to_target_bitmask(host->c_cflag, cflag_tbl));
ths5fafdf22007-09-16 21:08:06 +00002438 target->c_lflag =
bellard31e31b82003-02-18 22:55:36 +00002439 tswap32(host_to_target_bitmask(host->c_lflag, lflag_tbl));
2440 target->c_line = host->c_line;
ths3b46e622007-09-17 08:09:54 +00002441
bellard31e31b82003-02-18 22:55:36 +00002442 target->c_cc[TARGET_VINTR] = host->c_cc[VINTR];
2443 target->c_cc[TARGET_VQUIT] = host->c_cc[VQUIT];
2444 target->c_cc[TARGET_VERASE] = host->c_cc[VERASE];
2445 target->c_cc[TARGET_VKILL] = host->c_cc[VKILL];
2446 target->c_cc[TARGET_VEOF] = host->c_cc[VEOF];
2447 target->c_cc[TARGET_VTIME] = host->c_cc[VTIME];
2448 target->c_cc[TARGET_VMIN] = host->c_cc[VMIN];
2449 target->c_cc[TARGET_VSWTC] = host->c_cc[VSWTC];
2450 target->c_cc[TARGET_VSTART] = host->c_cc[VSTART];
2451 target->c_cc[TARGET_VSTOP] = host->c_cc[VSTOP];
2452 target->c_cc[TARGET_VSUSP] = host->c_cc[VSUSP];
2453 target->c_cc[TARGET_VEOL] = host->c_cc[VEOL];
2454 target->c_cc[TARGET_VREPRINT] = host->c_cc[VREPRINT];
2455 target->c_cc[TARGET_VDISCARD] = host->c_cc[VDISCARD];
2456 target->c_cc[TARGET_VWERASE] = host->c_cc[VWERASE];
2457 target->c_cc[TARGET_VLNEXT] = host->c_cc[VLNEXT];
2458 target->c_cc[TARGET_VEOL2] = host->c_cc[VEOL2];
2459}
2460
blueswir18e853dc2008-10-05 10:49:32 +00002461static const StructEntry struct_termios_def = {
bellard31e31b82003-02-18 22:55:36 +00002462 .convert = { host_to_target_termios, target_to_host_termios },
2463 .size = { sizeof(struct target_termios), sizeof(struct host_termios) },
2464 .align = { __alignof__(struct target_termios), __alignof__(struct host_termios) },
2465};
2466
bellard5286db72003-06-05 00:57:30 +00002467static bitmask_transtbl mmap_flags_tbl[] = {
2468 { TARGET_MAP_SHARED, TARGET_MAP_SHARED, MAP_SHARED, MAP_SHARED },
2469 { TARGET_MAP_PRIVATE, TARGET_MAP_PRIVATE, MAP_PRIVATE, MAP_PRIVATE },
2470 { TARGET_MAP_FIXED, TARGET_MAP_FIXED, MAP_FIXED, MAP_FIXED },
2471 { TARGET_MAP_ANONYMOUS, TARGET_MAP_ANONYMOUS, MAP_ANONYMOUS, MAP_ANONYMOUS },
2472 { TARGET_MAP_GROWSDOWN, TARGET_MAP_GROWSDOWN, MAP_GROWSDOWN, MAP_GROWSDOWN },
2473 { TARGET_MAP_DENYWRITE, TARGET_MAP_DENYWRITE, MAP_DENYWRITE, MAP_DENYWRITE },
2474 { TARGET_MAP_EXECUTABLE, TARGET_MAP_EXECUTABLE, MAP_EXECUTABLE, MAP_EXECUTABLE },
2475 { TARGET_MAP_LOCKED, TARGET_MAP_LOCKED, MAP_LOCKED, MAP_LOCKED },
2476 { 0, 0, 0, 0 }
2477};
2478
bellardffa65c32004-01-04 23:57:22 +00002479static bitmask_transtbl fcntl_flags_tbl[] = {
2480 { TARGET_O_ACCMODE, TARGET_O_WRONLY, O_ACCMODE, O_WRONLY, },
2481 { TARGET_O_ACCMODE, TARGET_O_RDWR, O_ACCMODE, O_RDWR, },
2482 { TARGET_O_CREAT, TARGET_O_CREAT, O_CREAT, O_CREAT, },
2483 { TARGET_O_EXCL, TARGET_O_EXCL, O_EXCL, O_EXCL, },
2484 { TARGET_O_NOCTTY, TARGET_O_NOCTTY, O_NOCTTY, O_NOCTTY, },
2485 { TARGET_O_TRUNC, TARGET_O_TRUNC, O_TRUNC, O_TRUNC, },
2486 { TARGET_O_APPEND, TARGET_O_APPEND, O_APPEND, O_APPEND, },
2487 { TARGET_O_NONBLOCK, TARGET_O_NONBLOCK, O_NONBLOCK, O_NONBLOCK, },
2488 { TARGET_O_SYNC, TARGET_O_SYNC, O_SYNC, O_SYNC, },
2489 { TARGET_FASYNC, TARGET_FASYNC, FASYNC, FASYNC, },
2490 { TARGET_O_DIRECTORY, TARGET_O_DIRECTORY, O_DIRECTORY, O_DIRECTORY, },
2491 { TARGET_O_NOFOLLOW, TARGET_O_NOFOLLOW, O_NOFOLLOW, O_NOFOLLOW, },
2492 { TARGET_O_LARGEFILE, TARGET_O_LARGEFILE, O_LARGEFILE, O_LARGEFILE, },
bellard121061d2004-02-22 11:56:01 +00002493#if defined(O_DIRECT)
bellardffa65c32004-01-04 23:57:22 +00002494 { TARGET_O_DIRECT, TARGET_O_DIRECT, O_DIRECT, O_DIRECT, },
bellard121061d2004-02-22 11:56:01 +00002495#endif
bellardffa65c32004-01-04 23:57:22 +00002496 { 0, 0, 0, 0 }
2497};
2498
bellard2ab83ea2003-06-15 19:56:46 +00002499#if defined(TARGET_I386)
bellard6dbad632003-03-16 18:05:05 +00002500
2501/* NOTE: there is really one LDT for all the threads */
2502uint8_t *ldt_table;
2503
bellard03acab62007-11-11 14:57:14 +00002504static abi_long read_ldt(abi_ulong ptr, unsigned long bytecount)
bellard6dbad632003-03-16 18:05:05 +00002505{
2506 int size;
pbrook53a59602006-03-25 19:31:22 +00002507 void *p;
bellard6dbad632003-03-16 18:05:05 +00002508
2509 if (!ldt_table)
2510 return 0;
2511 size = TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE;
2512 if (size > bytecount)
2513 size = bytecount;
bellard579a97f2007-11-11 14:26:47 +00002514 p = lock_user(VERIFY_WRITE, ptr, size, 0);
2515 if (!p)
bellard03acab62007-11-11 14:57:14 +00002516 return -TARGET_EFAULT;
bellard579a97f2007-11-11 14:26:47 +00002517 /* ??? Should this by byteswapped? */
pbrook53a59602006-03-25 19:31:22 +00002518 memcpy(p, ldt_table, size);
2519 unlock_user(p, ptr, size);
bellard6dbad632003-03-16 18:05:05 +00002520 return size;
2521}
2522
2523/* XXX: add locking support */
bellard03acab62007-11-11 14:57:14 +00002524static abi_long write_ldt(CPUX86State *env,
2525 abi_ulong ptr, unsigned long bytecount, int oldmode)
bellard6dbad632003-03-16 18:05:05 +00002526{
2527 struct target_modify_ldt_ldt_s ldt_info;
pbrook53a59602006-03-25 19:31:22 +00002528 struct target_modify_ldt_ldt_s *target_ldt_info;
bellard6dbad632003-03-16 18:05:05 +00002529 int seg_32bit, contents, read_exec_only, limit_in_pages;
bellard8d18e892007-11-14 15:18:40 +00002530 int seg_not_present, useable, lm;
bellard6dbad632003-03-16 18:05:05 +00002531 uint32_t *lp, entry_1, entry_2;
2532
2533 if (bytecount != sizeof(ldt_info))
bellard03acab62007-11-11 14:57:14 +00002534 return -TARGET_EINVAL;
bellard579a97f2007-11-11 14:26:47 +00002535 if (!lock_user_struct(VERIFY_READ, target_ldt_info, ptr, 1))
bellard03acab62007-11-11 14:57:14 +00002536 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00002537 ldt_info.entry_number = tswap32(target_ldt_info->entry_number);
2538 ldt_info.base_addr = tswapl(target_ldt_info->base_addr);
2539 ldt_info.limit = tswap32(target_ldt_info->limit);
2540 ldt_info.flags = tswap32(target_ldt_info->flags);
2541 unlock_user_struct(target_ldt_info, ptr, 0);
ths3b46e622007-09-17 08:09:54 +00002542
bellard6dbad632003-03-16 18:05:05 +00002543 if (ldt_info.entry_number >= TARGET_LDT_ENTRIES)
bellard03acab62007-11-11 14:57:14 +00002544 return -TARGET_EINVAL;
bellard6dbad632003-03-16 18:05:05 +00002545 seg_32bit = ldt_info.flags & 1;
2546 contents = (ldt_info.flags >> 1) & 3;
2547 read_exec_only = (ldt_info.flags >> 3) & 1;
2548 limit_in_pages = (ldt_info.flags >> 4) & 1;
2549 seg_not_present = (ldt_info.flags >> 5) & 1;
2550 useable = (ldt_info.flags >> 6) & 1;
bellard8d18e892007-11-14 15:18:40 +00002551#ifdef TARGET_ABI32
2552 lm = 0;
2553#else
2554 lm = (ldt_info.flags >> 7) & 1;
2555#endif
bellard6dbad632003-03-16 18:05:05 +00002556 if (contents == 3) {
2557 if (oldmode)
bellard03acab62007-11-11 14:57:14 +00002558 return -TARGET_EINVAL;
bellard6dbad632003-03-16 18:05:05 +00002559 if (seg_not_present == 0)
bellard03acab62007-11-11 14:57:14 +00002560 return -TARGET_EINVAL;
bellard6dbad632003-03-16 18:05:05 +00002561 }
2562 /* allocate the LDT */
2563 if (!ldt_table) {
2564 ldt_table = malloc(TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE);
2565 if (!ldt_table)
bellard03acab62007-11-11 14:57:14 +00002566 return -TARGET_ENOMEM;
bellard6dbad632003-03-16 18:05:05 +00002567 memset(ldt_table, 0, TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE);
bellardeeeac3f2007-11-11 19:34:32 +00002568 env->ldt.base = h2g((unsigned long)ldt_table);
bellard6dbad632003-03-16 18:05:05 +00002569 env->ldt.limit = 0xffff;
2570 }
2571
2572 /* NOTE: same code as Linux kernel */
2573 /* Allow LDTs to be cleared by the user. */
2574 if (ldt_info.base_addr == 0 && ldt_info.limit == 0) {
2575 if (oldmode ||
2576 (contents == 0 &&
2577 read_exec_only == 1 &&
2578 seg_32bit == 0 &&
2579 limit_in_pages == 0 &&
2580 seg_not_present == 1 &&
2581 useable == 0 )) {
2582 entry_1 = 0;
2583 entry_2 = 0;
2584 goto install;
2585 }
2586 }
ths3b46e622007-09-17 08:09:54 +00002587
bellard6dbad632003-03-16 18:05:05 +00002588 entry_1 = ((ldt_info.base_addr & 0x0000ffff) << 16) |
2589 (ldt_info.limit & 0x0ffff);
2590 entry_2 = (ldt_info.base_addr & 0xff000000) |
2591 ((ldt_info.base_addr & 0x00ff0000) >> 16) |
2592 (ldt_info.limit & 0xf0000) |
2593 ((read_exec_only ^ 1) << 9) |
2594 (contents << 10) |
2595 ((seg_not_present ^ 1) << 15) |
2596 (seg_32bit << 22) |
2597 (limit_in_pages << 23) |
bellard8d18e892007-11-14 15:18:40 +00002598 (lm << 21) |
bellard6dbad632003-03-16 18:05:05 +00002599 0x7000;
2600 if (!oldmode)
2601 entry_2 |= (useable << 20);
bellard14ae3ba2003-05-27 23:25:06 +00002602
bellard6dbad632003-03-16 18:05:05 +00002603 /* Install the new entry ... */
2604install:
2605 lp = (uint32_t *)(ldt_table + (ldt_info.entry_number << 3));
2606 lp[0] = tswap32(entry_1);
2607 lp[1] = tswap32(entry_2);
2608 return 0;
2609}
2610
2611/* specific and weird i386 syscalls */
blueswir18fcd3692008-08-17 20:26:25 +00002612static abi_long do_modify_ldt(CPUX86State *env, int func, abi_ulong ptr,
2613 unsigned long bytecount)
bellard6dbad632003-03-16 18:05:05 +00002614{
bellard03acab62007-11-11 14:57:14 +00002615 abi_long ret;
ths3b46e622007-09-17 08:09:54 +00002616
bellard6dbad632003-03-16 18:05:05 +00002617 switch (func) {
2618 case 0:
2619 ret = read_ldt(ptr, bytecount);
2620 break;
2621 case 1:
2622 ret = write_ldt(env, ptr, bytecount, 1);
2623 break;
2624 case 0x11:
2625 ret = write_ldt(env, ptr, bytecount, 0);
2626 break;
bellard03acab62007-11-11 14:57:14 +00002627 default:
2628 ret = -TARGET_ENOSYS;
2629 break;
bellard6dbad632003-03-16 18:05:05 +00002630 }
2631 return ret;
2632}
bellard1b6b0292003-03-22 17:31:38 +00002633
blueswir14583f582008-08-24 10:35:55 +00002634#if defined(TARGET_I386) && defined(TARGET_ABI32)
blueswir18fcd3692008-08-17 20:26:25 +00002635static abi_long do_set_thread_area(CPUX86State *env, abi_ulong ptr)
bellard8d18e892007-11-14 15:18:40 +00002636{
2637 uint64_t *gdt_table = g2h(env->gdt.base);
2638 struct target_modify_ldt_ldt_s ldt_info;
2639 struct target_modify_ldt_ldt_s *target_ldt_info;
2640 int seg_32bit, contents, read_exec_only, limit_in_pages;
2641 int seg_not_present, useable, lm;
2642 uint32_t *lp, entry_1, entry_2;
2643 int i;
2644
2645 lock_user_struct(VERIFY_WRITE, target_ldt_info, ptr, 1);
2646 if (!target_ldt_info)
2647 return -TARGET_EFAULT;
2648 ldt_info.entry_number = tswap32(target_ldt_info->entry_number);
2649 ldt_info.base_addr = tswapl(target_ldt_info->base_addr);
2650 ldt_info.limit = tswap32(target_ldt_info->limit);
2651 ldt_info.flags = tswap32(target_ldt_info->flags);
2652 if (ldt_info.entry_number == -1) {
2653 for (i=TARGET_GDT_ENTRY_TLS_MIN; i<=TARGET_GDT_ENTRY_TLS_MAX; i++) {
2654 if (gdt_table[i] == 0) {
2655 ldt_info.entry_number = i;
2656 target_ldt_info->entry_number = tswap32(i);
2657 break;
2658 }
2659 }
2660 }
2661 unlock_user_struct(target_ldt_info, ptr, 1);
2662
2663 if (ldt_info.entry_number < TARGET_GDT_ENTRY_TLS_MIN ||
2664 ldt_info.entry_number > TARGET_GDT_ENTRY_TLS_MAX)
2665 return -TARGET_EINVAL;
2666 seg_32bit = ldt_info.flags & 1;
2667 contents = (ldt_info.flags >> 1) & 3;
2668 read_exec_only = (ldt_info.flags >> 3) & 1;
2669 limit_in_pages = (ldt_info.flags >> 4) & 1;
2670 seg_not_present = (ldt_info.flags >> 5) & 1;
2671 useable = (ldt_info.flags >> 6) & 1;
2672#ifdef TARGET_ABI32
2673 lm = 0;
2674#else
2675 lm = (ldt_info.flags >> 7) & 1;
2676#endif
2677
2678 if (contents == 3) {
2679 if (seg_not_present == 0)
2680 return -TARGET_EINVAL;
2681 }
2682
2683 /* NOTE: same code as Linux kernel */
2684 /* Allow LDTs to be cleared by the user. */
2685 if (ldt_info.base_addr == 0 && ldt_info.limit == 0) {
2686 if ((contents == 0 &&
2687 read_exec_only == 1 &&
2688 seg_32bit == 0 &&
2689 limit_in_pages == 0 &&
2690 seg_not_present == 1 &&
2691 useable == 0 )) {
2692 entry_1 = 0;
2693 entry_2 = 0;
2694 goto install;
2695 }
2696 }
2697
2698 entry_1 = ((ldt_info.base_addr & 0x0000ffff) << 16) |
2699 (ldt_info.limit & 0x0ffff);
2700 entry_2 = (ldt_info.base_addr & 0xff000000) |
2701 ((ldt_info.base_addr & 0x00ff0000) >> 16) |
2702 (ldt_info.limit & 0xf0000) |
2703 ((read_exec_only ^ 1) << 9) |
2704 (contents << 10) |
2705 ((seg_not_present ^ 1) << 15) |
2706 (seg_32bit << 22) |
2707 (limit_in_pages << 23) |
2708 (useable << 20) |
2709 (lm << 21) |
2710 0x7000;
2711
2712 /* Install the new entry ... */
2713install:
2714 lp = (uint32_t *)(gdt_table + ldt_info.entry_number);
2715 lp[0] = tswap32(entry_1);
2716 lp[1] = tswap32(entry_2);
2717 return 0;
2718}
2719
blueswir18fcd3692008-08-17 20:26:25 +00002720static abi_long do_get_thread_area(CPUX86State *env, abi_ulong ptr)
bellard8d18e892007-11-14 15:18:40 +00002721{
2722 struct target_modify_ldt_ldt_s *target_ldt_info;
2723 uint64_t *gdt_table = g2h(env->gdt.base);
2724 uint32_t base_addr, limit, flags;
2725 int seg_32bit, contents, read_exec_only, limit_in_pages, idx;
2726 int seg_not_present, useable, lm;
2727 uint32_t *lp, entry_1, entry_2;
2728
2729 lock_user_struct(VERIFY_WRITE, target_ldt_info, ptr, 1);
2730 if (!target_ldt_info)
2731 return -TARGET_EFAULT;
2732 idx = tswap32(target_ldt_info->entry_number);
2733 if (idx < TARGET_GDT_ENTRY_TLS_MIN ||
2734 idx > TARGET_GDT_ENTRY_TLS_MAX) {
2735 unlock_user_struct(target_ldt_info, ptr, 1);
2736 return -TARGET_EINVAL;
2737 }
2738 lp = (uint32_t *)(gdt_table + idx);
2739 entry_1 = tswap32(lp[0]);
2740 entry_2 = tswap32(lp[1]);
2741
2742 read_exec_only = ((entry_2 >> 9) & 1) ^ 1;
2743 contents = (entry_2 >> 10) & 3;
2744 seg_not_present = ((entry_2 >> 15) & 1) ^ 1;
2745 seg_32bit = (entry_2 >> 22) & 1;
2746 limit_in_pages = (entry_2 >> 23) & 1;
2747 useable = (entry_2 >> 20) & 1;
2748#ifdef TARGET_ABI32
2749 lm = 0;
2750#else
2751 lm = (entry_2 >> 21) & 1;
2752#endif
2753 flags = (seg_32bit << 0) | (contents << 1) |
2754 (read_exec_only << 3) | (limit_in_pages << 4) |
2755 (seg_not_present << 5) | (useable << 6) | (lm << 7);
2756 limit = (entry_1 & 0xffff) | (entry_2 & 0xf0000);
2757 base_addr = (entry_1 >> 16) |
2758 (entry_2 & 0xff000000) |
2759 ((entry_2 & 0xff) << 16);
2760 target_ldt_info->base_addr = tswapl(base_addr);
2761 target_ldt_info->limit = tswap32(limit);
2762 target_ldt_info->flags = tswap32(flags);
2763 unlock_user_struct(target_ldt_info, ptr, 1);
2764 return 0;
2765}
blueswir14583f582008-08-24 10:35:55 +00002766#endif /* TARGET_I386 && TARGET_ABI32 */
bellard8d18e892007-11-14 15:18:40 +00002767
bellardd2fd1af2007-11-14 18:08:56 +00002768#ifndef TARGET_ABI32
blueswir18fcd3692008-08-17 20:26:25 +00002769static abi_long do_arch_prctl(CPUX86State *env, int code, abi_ulong addr)
bellardd2fd1af2007-11-14 18:08:56 +00002770{
2771 abi_long ret;
2772 abi_ulong val;
2773 int idx;
2774
2775 switch(code) {
2776 case TARGET_ARCH_SET_GS:
2777 case TARGET_ARCH_SET_FS:
2778 if (code == TARGET_ARCH_SET_GS)
2779 idx = R_GS;
2780 else
2781 idx = R_FS;
2782 cpu_x86_load_seg(env, idx, 0);
2783 env->segs[idx].base = addr;
2784 break;
2785 case TARGET_ARCH_GET_GS:
2786 case TARGET_ARCH_GET_FS:
2787 if (code == TARGET_ARCH_GET_GS)
2788 idx = R_GS;
2789 else
2790 idx = R_FS;
2791 val = env->segs[idx].base;
2792 if (put_user(val, addr, abi_ulong))
2793 return -TARGET_EFAULT;
2794 break;
2795 default:
2796 ret = -TARGET_EINVAL;
2797 break;
2798 }
2799 return 0;
2800}
2801#endif
2802
bellard2ab83ea2003-06-15 19:56:46 +00002803#endif /* defined(TARGET_I386) */
2804
pbrookd865bab2008-06-07 22:12:17 +00002805#if defined(USE_NPTL)
2806
2807#define NEW_STACK_SIZE PTHREAD_STACK_MIN
2808
2809static pthread_mutex_t clone_lock = PTHREAD_MUTEX_INITIALIZER;
2810typedef struct {
2811 CPUState *env;
2812 pthread_mutex_t mutex;
2813 pthread_cond_t cond;
2814 pthread_t thread;
2815 uint32_t tid;
2816 abi_ulong child_tidptr;
2817 abi_ulong parent_tidptr;
2818 sigset_t sigmask;
2819} new_thread_info;
2820
2821static void *clone_func(void *arg)
2822{
2823 new_thread_info *info = arg;
2824 CPUState *env;
2825
2826 env = info->env;
2827 thread_env = env;
2828 info->tid = gettid();
2829 if (info->child_tidptr)
2830 put_user_u32(info->tid, info->child_tidptr);
2831 if (info->parent_tidptr)
2832 put_user_u32(info->tid, info->parent_tidptr);
2833 /* Enable signals. */
2834 sigprocmask(SIG_SETMASK, &info->sigmask, NULL);
2835 /* Signal to the parent that we're ready. */
2836 pthread_mutex_lock(&info->mutex);
2837 pthread_cond_broadcast(&info->cond);
2838 pthread_mutex_unlock(&info->mutex);
2839 /* Wait until the parent has finshed initializing the tls state. */
2840 pthread_mutex_lock(&clone_lock);
2841 pthread_mutex_unlock(&clone_lock);
2842 cpu_loop(env);
2843 /* never exits */
2844 return NULL;
2845}
2846#else
bellard1b6b0292003-03-22 17:31:38 +00002847/* this stack is the equivalent of the kernel stack associated with a
2848 thread/process */
2849#define NEW_STACK_SIZE 8192
2850
2851static int clone_func(void *arg)
2852{
bellard2ab83ea2003-06-15 19:56:46 +00002853 CPUState *env = arg;
bellard1b6b0292003-03-22 17:31:38 +00002854 cpu_loop(env);
2855 /* never exits */
2856 return 0;
2857}
pbrookd865bab2008-06-07 22:12:17 +00002858#endif
bellard1b6b0292003-03-22 17:31:38 +00002859
ths0da46a62007-10-20 20:23:07 +00002860/* do_fork() Must return host values and target errnos (unlike most
2861 do_*() functions). */
pbrookd865bab2008-06-07 22:12:17 +00002862static int do_fork(CPUState *env, unsigned int flags, abi_ulong newsp,
2863 abi_ulong parent_tidptr, target_ulong newtls,
2864 abi_ulong child_tidptr)
bellard1b6b0292003-03-22 17:31:38 +00002865{
2866 int ret;
bellard5cd43932003-03-29 16:54:36 +00002867 TaskState *ts;
bellard1b6b0292003-03-22 17:31:38 +00002868 uint8_t *new_stack;
bellard2ab83ea2003-06-15 19:56:46 +00002869 CPUState *new_env;
pbrookd865bab2008-06-07 22:12:17 +00002870#if defined(USE_NPTL)
2871 unsigned int nptl_flags;
2872 sigset_t sigmask;
2873#endif
ths3b46e622007-09-17 08:09:54 +00002874
balrog436d1242008-09-21 02:39:45 +00002875 /* Emulate vfork() with fork() */
2876 if (flags & CLONE_VFORK)
2877 flags &= ~(CLONE_VFORK | CLONE_VM);
2878
bellard1b6b0292003-03-22 17:31:38 +00002879 if (flags & CLONE_VM) {
pbrookbd0c5662008-05-29 14:34:11 +00002880#if defined(USE_NPTL)
pbrookd865bab2008-06-07 22:12:17 +00002881 new_thread_info info;
2882 pthread_attr_t attr;
pbrookbd0c5662008-05-29 14:34:11 +00002883#endif
pbrookc3a92832008-06-09 14:02:50 +00002884 ts = qemu_mallocz(sizeof(TaskState) + NEW_STACK_SIZE);
pbrook624f7972008-05-31 16:11:38 +00002885 init_task_state(ts);
bellard5cd43932003-03-29 16:54:36 +00002886 new_stack = ts->stack;
bellard1b6b0292003-03-22 17:31:38 +00002887 /* we create a new CPU instance. */
thsc5be9f02007-02-28 20:20:53 +00002888 new_env = cpu_copy(env);
pbrook6e68e072008-05-30 17:22:15 +00002889 /* Init regs that differ from the parent. */
2890 cpu_clone_regs(new_env, newsp);
bellard5cd43932003-03-29 16:54:36 +00002891 new_env->opaque = ts;
pbrookd865bab2008-06-07 22:12:17 +00002892#if defined(USE_NPTL)
2893 nptl_flags = flags;
2894 flags &= ~CLONE_NPTL_FLAGS2;
2895
2896 /* TODO: Implement CLONE_CHILD_CLEARTID. */
2897 if (nptl_flags & CLONE_SETTLS)
2898 cpu_set_tls (new_env, newtls);
2899
2900 /* Grab a mutex so that thread setup appears atomic. */
2901 pthread_mutex_lock(&clone_lock);
2902
2903 memset(&info, 0, sizeof(info));
2904 pthread_mutex_init(&info.mutex, NULL);
2905 pthread_mutex_lock(&info.mutex);
2906 pthread_cond_init(&info.cond, NULL);
2907 info.env = new_env;
2908 if (nptl_flags & CLONE_CHILD_SETTID)
2909 info.child_tidptr = child_tidptr;
2910 if (nptl_flags & CLONE_PARENT_SETTID)
2911 info.parent_tidptr = parent_tidptr;
2912
2913 ret = pthread_attr_init(&attr);
2914 ret = pthread_attr_setstack(&attr, new_stack, NEW_STACK_SIZE);
2915 /* It is not safe to deliver signals until the child has finished
2916 initializing, so temporarily block all signals. */
2917 sigfillset(&sigmask);
2918 sigprocmask(SIG_BLOCK, &sigmask, &info.sigmask);
2919
2920 ret = pthread_create(&info.thread, &attr, clone_func, &info);
2921
2922 sigprocmask(SIG_SETMASK, &info.sigmask, NULL);
2923 pthread_attr_destroy(&attr);
2924 if (ret == 0) {
2925 /* Wait for the child to initialize. */
2926 pthread_cond_wait(&info.cond, &info.mutex);
2927 ret = info.tid;
2928 if (flags & CLONE_PARENT_SETTID)
2929 put_user_u32(ret, parent_tidptr);
2930 } else {
2931 ret = -1;
2932 }
2933 pthread_mutex_unlock(&info.mutex);
2934 pthread_cond_destroy(&info.cond);
2935 pthread_mutex_destroy(&info.mutex);
2936 pthread_mutex_unlock(&clone_lock);
2937#else
2938 if (flags & CLONE_NPTL_FLAGS2)
2939 return -EINVAL;
2940 /* This is probably going to die very quickly, but do it anyway. */
bellard27725c12003-04-29 21:08:18 +00002941#ifdef __ia64__
bellardfd4a43e2006-04-24 20:32:17 +00002942 ret = __clone2(clone_func, new_stack + NEW_STACK_SIZE, flags, new_env);
bellard27725c12003-04-29 21:08:18 +00002943#else
2944 ret = clone(clone_func, new_stack + NEW_STACK_SIZE, flags, new_env);
2945#endif
pbrookd865bab2008-06-07 22:12:17 +00002946#endif
bellard1b6b0292003-03-22 17:31:38 +00002947 } else {
2948 /* if no CLONE_VM, we consider it is a fork */
pbrookd865bab2008-06-07 22:12:17 +00002949 if ((flags & ~(CSIGNAL | CLONE_NPTL_FLAGS2)) != 0)
bellard1b6b0292003-03-22 17:31:38 +00002950 return -EINVAL;
pbrookd865bab2008-06-07 22:12:17 +00002951 fork_start();
bellard1b6b0292003-03-22 17:31:38 +00002952 ret = fork();
pbrookd865bab2008-06-07 22:12:17 +00002953#if defined(USE_NPTL)
2954 /* There is a race condition here. The parent process could
2955 theoretically read the TID in the child process before the child
2956 tid is set. This would require using either ptrace
2957 (not implemented) or having *_tidptr to point at a shared memory
2958 mapping. We can't repeat the spinlock hack used above because
2959 the child process gets its own copy of the lock. */
2960 if (ret == 0) {
2961 cpu_clone_regs(env, newsp);
2962 fork_end(1);
2963 /* Child Process. */
2964 if (flags & CLONE_CHILD_SETTID)
2965 put_user_u32(gettid(), child_tidptr);
2966 if (flags & CLONE_PARENT_SETTID)
2967 put_user_u32(gettid(), parent_tidptr);
2968 ts = (TaskState *)env->opaque;
2969 if (flags & CLONE_SETTLS)
2970 cpu_set_tls (env, newtls);
2971 /* TODO: Implement CLONE_CHILD_CLEARTID. */
2972 } else {
2973 fork_end(0);
2974 }
2975#else
pbrook6e68e072008-05-30 17:22:15 +00002976 if (ret == 0) {
2977 cpu_clone_regs(env, newsp);
2978 }
pbrookd865bab2008-06-07 22:12:17 +00002979#endif
bellard1b6b0292003-03-22 17:31:38 +00002980 }
2981 return ret;
2982}
2983
blueswir1992f48a2007-10-14 16:27:31 +00002984static abi_long do_fcntl(int fd, int cmd, abi_ulong arg)
bellard7775e9e2003-05-14 22:46:48 +00002985{
2986 struct flock fl;
pbrook53a59602006-03-25 19:31:22 +00002987 struct target_flock *target_fl;
ths43f238d2007-01-05 20:55:49 +00002988 struct flock64 fl64;
2989 struct target_flock64 *target_fl64;
blueswir1992f48a2007-10-14 16:27:31 +00002990 abi_long ret;
pbrook53a59602006-03-25 19:31:22 +00002991
bellard7775e9e2003-05-14 22:46:48 +00002992 switch(cmd) {
2993 case TARGET_F_GETLK:
bellard579a97f2007-11-11 14:26:47 +00002994 if (!lock_user_struct(VERIFY_READ, target_fl, arg, 1))
2995 return -TARGET_EFAULT;
ths58134272007-03-31 18:59:32 +00002996 fl.l_type = tswap16(target_fl->l_type);
2997 fl.l_whence = tswap16(target_fl->l_whence);
2998 fl.l_start = tswapl(target_fl->l_start);
2999 fl.l_len = tswapl(target_fl->l_len);
3000 fl.l_pid = tswapl(target_fl->l_pid);
3001 unlock_user_struct(target_fl, arg, 0);
bellard9ee1fa22007-11-11 15:11:19 +00003002 ret = get_errno(fcntl(fd, cmd, &fl));
bellard7775e9e2003-05-14 22:46:48 +00003003 if (ret == 0) {
bellard579a97f2007-11-11 14:26:47 +00003004 if (!lock_user_struct(VERIFY_WRITE, target_fl, arg, 0))
3005 return -TARGET_EFAULT;
bellard7775e9e2003-05-14 22:46:48 +00003006 target_fl->l_type = tswap16(fl.l_type);
3007 target_fl->l_whence = tswap16(fl.l_whence);
3008 target_fl->l_start = tswapl(fl.l_start);
3009 target_fl->l_len = tswapl(fl.l_len);
3010 target_fl->l_pid = tswapl(fl.l_pid);
pbrook53a59602006-03-25 19:31:22 +00003011 unlock_user_struct(target_fl, arg, 1);
bellard7775e9e2003-05-14 22:46:48 +00003012 }
3013 break;
ths3b46e622007-09-17 08:09:54 +00003014
bellard7775e9e2003-05-14 22:46:48 +00003015 case TARGET_F_SETLK:
3016 case TARGET_F_SETLKW:
bellard579a97f2007-11-11 14:26:47 +00003017 if (!lock_user_struct(VERIFY_READ, target_fl, arg, 1))
3018 return -TARGET_EFAULT;
bellard7775e9e2003-05-14 22:46:48 +00003019 fl.l_type = tswap16(target_fl->l_type);
3020 fl.l_whence = tswap16(target_fl->l_whence);
3021 fl.l_start = tswapl(target_fl->l_start);
3022 fl.l_len = tswapl(target_fl->l_len);
3023 fl.l_pid = tswapl(target_fl->l_pid);
pbrook53a59602006-03-25 19:31:22 +00003024 unlock_user_struct(target_fl, arg, 0);
bellard9ee1fa22007-11-11 15:11:19 +00003025 ret = get_errno(fcntl(fd, cmd, &fl));
bellard7775e9e2003-05-14 22:46:48 +00003026 break;
ths3b46e622007-09-17 08:09:54 +00003027
bellard7775e9e2003-05-14 22:46:48 +00003028 case TARGET_F_GETLK64:
bellard579a97f2007-11-11 14:26:47 +00003029 if (!lock_user_struct(VERIFY_READ, target_fl64, arg, 1))
3030 return -TARGET_EFAULT;
ths58134272007-03-31 18:59:32 +00003031 fl64.l_type = tswap16(target_fl64->l_type) >> 1;
3032 fl64.l_whence = tswap16(target_fl64->l_whence);
3033 fl64.l_start = tswapl(target_fl64->l_start);
3034 fl64.l_len = tswapl(target_fl64->l_len);
3035 fl64.l_pid = tswap16(target_fl64->l_pid);
3036 unlock_user_struct(target_fl64, arg, 0);
bellard9ee1fa22007-11-11 15:11:19 +00003037 ret = get_errno(fcntl(fd, cmd >> 1, &fl64));
ths43f238d2007-01-05 20:55:49 +00003038 if (ret == 0) {
bellard579a97f2007-11-11 14:26:47 +00003039 if (!lock_user_struct(VERIFY_WRITE, target_fl64, arg, 0))
3040 return -TARGET_EFAULT;
ths43f238d2007-01-05 20:55:49 +00003041 target_fl64->l_type = tswap16(fl64.l_type) >> 1;
3042 target_fl64->l_whence = tswap16(fl64.l_whence);
3043 target_fl64->l_start = tswapl(fl64.l_start);
3044 target_fl64->l_len = tswapl(fl64.l_len);
3045 target_fl64->l_pid = tswapl(fl64.l_pid);
3046 unlock_user_struct(target_fl64, arg, 1);
3047 }
bellard9ee1fa22007-11-11 15:11:19 +00003048 break;
bellard7775e9e2003-05-14 22:46:48 +00003049 case TARGET_F_SETLK64:
3050 case TARGET_F_SETLKW64:
bellard579a97f2007-11-11 14:26:47 +00003051 if (!lock_user_struct(VERIFY_READ, target_fl64, arg, 1))
3052 return -TARGET_EFAULT;
ths43f238d2007-01-05 20:55:49 +00003053 fl64.l_type = tswap16(target_fl64->l_type) >> 1;
3054 fl64.l_whence = tswap16(target_fl64->l_whence);
3055 fl64.l_start = tswapl(target_fl64->l_start);
3056 fl64.l_len = tswapl(target_fl64->l_len);
3057 fl64.l_pid = tswap16(target_fl64->l_pid);
3058 unlock_user_struct(target_fl64, arg, 0);
bellard9ee1fa22007-11-11 15:11:19 +00003059 ret = get_errno(fcntl(fd, cmd >> 1, &fl64));
bellard7775e9e2003-05-14 22:46:48 +00003060 break;
3061
bellardffa65c32004-01-04 23:57:22 +00003062 case F_GETFL:
bellard9ee1fa22007-11-11 15:11:19 +00003063 ret = get_errno(fcntl(fd, cmd, arg));
3064 if (ret >= 0) {
3065 ret = host_to_target_bitmask(ret, fcntl_flags_tbl);
3066 }
bellardffa65c32004-01-04 23:57:22 +00003067 break;
3068
3069 case F_SETFL:
bellard9ee1fa22007-11-11 15:11:19 +00003070 ret = get_errno(fcntl(fd, cmd, target_to_host_bitmask(arg, fcntl_flags_tbl)));
bellardffa65c32004-01-04 23:57:22 +00003071 break;
3072
bellard7775e9e2003-05-14 22:46:48 +00003073 default:
bellard9ee1fa22007-11-11 15:11:19 +00003074 ret = get_errno(fcntl(fd, cmd, arg));
bellard7775e9e2003-05-14 22:46:48 +00003075 break;
3076 }
3077 return ret;
3078}
3079
bellard67867302003-11-23 17:05:30 +00003080#ifdef USE_UID16
bellard7775e9e2003-05-14 22:46:48 +00003081
bellard67867302003-11-23 17:05:30 +00003082static inline int high2lowuid(int uid)
3083{
3084 if (uid > 65535)
3085 return 65534;
3086 else
3087 return uid;
3088}
3089
3090static inline int high2lowgid(int gid)
3091{
3092 if (gid > 65535)
3093 return 65534;
3094 else
3095 return gid;
3096}
3097
3098static inline int low2highuid(int uid)
3099{
3100 if ((int16_t)uid == -1)
3101 return -1;
3102 else
3103 return uid;
3104}
3105
3106static inline int low2highgid(int gid)
3107{
3108 if ((int16_t)gid == -1)
3109 return -1;
3110 else
3111 return gid;
3112}
3113
3114#endif /* USE_UID16 */
bellard1b6b0292003-03-22 17:31:38 +00003115
bellard31e31b82003-02-18 22:55:36 +00003116void syscall_init(void)
3117{
bellard2ab83ea2003-06-15 19:56:46 +00003118 IOCTLEntry *ie;
3119 const argtype *arg_type;
3120 int size;
thsb92c47c2007-11-01 00:07:38 +00003121 int i;
bellard2ab83ea2003-06-15 19:56:46 +00003122
ths5fafdf22007-09-16 21:08:06 +00003123#define STRUCT(name, list...) thunk_register_struct(STRUCT_ ## name, #name, struct_ ## name ## _def);
3124#define STRUCT_SPECIAL(name) thunk_register_struct_direct(STRUCT_ ## name, #name, &struct_ ## name ## _def);
bellard31e31b82003-02-18 22:55:36 +00003125#include "syscall_types.h"
3126#undef STRUCT
3127#undef STRUCT_SPECIAL
bellard2ab83ea2003-06-15 19:56:46 +00003128
3129 /* we patch the ioctl size if necessary. We rely on the fact that
3130 no ioctl has all the bits at '1' in the size field */
3131 ie = ioctl_entries;
3132 while (ie->target_cmd != 0) {
3133 if (((ie->target_cmd >> TARGET_IOC_SIZESHIFT) & TARGET_IOC_SIZEMASK) ==
3134 TARGET_IOC_SIZEMASK) {
3135 arg_type = ie->arg_type;
3136 if (arg_type[0] != TYPE_PTR) {
ths5fafdf22007-09-16 21:08:06 +00003137 fprintf(stderr, "cannot patch size for ioctl 0x%x\n",
bellard2ab83ea2003-06-15 19:56:46 +00003138 ie->target_cmd);
3139 exit(1);
3140 }
3141 arg_type++;
3142 size = thunk_type_size(arg_type, 0);
ths5fafdf22007-09-16 21:08:06 +00003143 ie->target_cmd = (ie->target_cmd &
bellard2ab83ea2003-06-15 19:56:46 +00003144 ~(TARGET_IOC_SIZEMASK << TARGET_IOC_SIZESHIFT)) |
3145 (size << TARGET_IOC_SIZESHIFT);
3146 }
thsb92c47c2007-11-01 00:07:38 +00003147
3148 /* Build target_to_host_errno_table[] table from
3149 * host_to_target_errno_table[]. */
3150 for (i=0; i < ERRNO_TABLE_SIZE; i++)
3151 target_to_host_errno_table[host_to_target_errno_table[i]] = i;
3152
bellard2ab83ea2003-06-15 19:56:46 +00003153 /* automatic consistency check if same arch */
balrog872ea0c2008-09-21 02:31:19 +00003154#if (defined(__i386__) && defined(TARGET_I386) && defined(TARGET_ABI32)) || \
3155 (defined(__x86_64__) && defined(TARGET_X86_64))
3156 if (unlikely(ie->target_cmd != ie->host_cmd)) {
3157 fprintf(stderr, "ERROR: ioctl(%s): target=0x%x host=0x%x\n",
3158 ie->name, ie->target_cmd, ie->host_cmd);
bellard2ab83ea2003-06-15 19:56:46 +00003159 }
3160#endif
3161 ie++;
3162 }
bellard31e31b82003-02-18 22:55:36 +00003163}
bellardc573ff62004-01-04 15:51:36 +00003164
blueswir1992f48a2007-10-14 16:27:31 +00003165#if TARGET_ABI_BITS == 32
pbrookce4defa2006-02-09 16:49:55 +00003166static inline uint64_t target_offset64(uint32_t word0, uint32_t word1)
3167{
thsaf325d32008-06-10 15:29:15 +00003168#ifdef TARGET_WORDS_BIGENDIAN
pbrookce4defa2006-02-09 16:49:55 +00003169 return ((uint64_t)word0 << 32) | word1;
3170#else
3171 return ((uint64_t)word1 << 32) | word0;
3172#endif
3173}
blueswir1992f48a2007-10-14 16:27:31 +00003174#else /* TARGET_ABI_BITS == 32 */
j_mayer32407102007-09-26 23:01:49 +00003175static inline uint64_t target_offset64(uint64_t word0, uint64_t word1)
3176{
3177 return word0;
3178}
blueswir1992f48a2007-10-14 16:27:31 +00003179#endif /* TARGET_ABI_BITS != 32 */
pbrookce4defa2006-02-09 16:49:55 +00003180
3181#ifdef TARGET_NR_truncate64
blueswir1992f48a2007-10-14 16:27:31 +00003182static inline abi_long target_truncate64(void *cpu_env, const char *arg1,
3183 abi_long arg2,
3184 abi_long arg3,
3185 abi_long arg4)
pbrookce4defa2006-02-09 16:49:55 +00003186{
3187#ifdef TARGET_ARM
3188 if (((CPUARMState *)cpu_env)->eabi)
3189 {
3190 arg2 = arg3;
3191 arg3 = arg4;
3192 }
3193#endif
3194 return get_errno(truncate64(arg1, target_offset64(arg2, arg3)));
3195}
3196#endif
3197
3198#ifdef TARGET_NR_ftruncate64
blueswir1992f48a2007-10-14 16:27:31 +00003199static inline abi_long target_ftruncate64(void *cpu_env, abi_long arg1,
3200 abi_long arg2,
3201 abi_long arg3,
3202 abi_long arg4)
pbrookce4defa2006-02-09 16:49:55 +00003203{
3204#ifdef TARGET_ARM
3205 if (((CPUARMState *)cpu_env)->eabi)
3206 {
3207 arg2 = arg3;
3208 arg3 = arg4;
3209 }
3210#endif
3211 return get_errno(ftruncate64(arg1, target_offset64(arg2, arg3)));
3212}
3213#endif
3214
bellard579a97f2007-11-11 14:26:47 +00003215static inline abi_long target_to_host_timespec(struct timespec *host_ts,
3216 abi_ulong target_addr)
pbrook53a59602006-03-25 19:31:22 +00003217{
3218 struct target_timespec *target_ts;
3219
bellard579a97f2007-11-11 14:26:47 +00003220 if (!lock_user_struct(VERIFY_READ, target_ts, target_addr, 1))
3221 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00003222 host_ts->tv_sec = tswapl(target_ts->tv_sec);
3223 host_ts->tv_nsec = tswapl(target_ts->tv_nsec);
3224 unlock_user_struct(target_ts, target_addr, 0);
bellardb255bfa2008-05-10 21:51:02 +00003225 return 0;
pbrook53a59602006-03-25 19:31:22 +00003226}
3227
bellard579a97f2007-11-11 14:26:47 +00003228static inline abi_long host_to_target_timespec(abi_ulong target_addr,
3229 struct timespec *host_ts)
pbrook53a59602006-03-25 19:31:22 +00003230{
3231 struct target_timespec *target_ts;
3232
bellard579a97f2007-11-11 14:26:47 +00003233 if (!lock_user_struct(VERIFY_WRITE, target_ts, target_addr, 0))
3234 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00003235 target_ts->tv_sec = tswapl(host_ts->tv_sec);
3236 target_ts->tv_nsec = tswapl(host_ts->tv_nsec);
3237 unlock_user_struct(target_ts, target_addr, 1);
bellardb255bfa2008-05-10 21:51:02 +00003238 return 0;
pbrook53a59602006-03-25 19:31:22 +00003239}
3240
balrog6a24a772008-09-20 02:23:36 +00003241#ifdef TARGET_NR_stat64
3242static inline abi_long host_to_target_stat64(void *cpu_env,
3243 abi_ulong target_addr,
3244 struct stat *host_st)
3245{
3246#ifdef TARGET_ARM
3247 if (((CPUARMState *)cpu_env)->eabi) {
3248 struct target_eabi_stat64 *target_st;
3249
3250 if (!lock_user_struct(VERIFY_WRITE, target_st, target_addr, 0))
3251 return -TARGET_EFAULT;
3252 memset(target_st, 0, sizeof(struct target_eabi_stat64));
3253 __put_user(host_st->st_dev, &target_st->st_dev);
3254 __put_user(host_st->st_ino, &target_st->st_ino);
3255#ifdef TARGET_STAT64_HAS_BROKEN_ST_INO
3256 __put_user(host_st->st_ino, &target_st->__st_ino);
3257#endif
3258 __put_user(host_st->st_mode, &target_st->st_mode);
3259 __put_user(host_st->st_nlink, &target_st->st_nlink);
3260 __put_user(host_st->st_uid, &target_st->st_uid);
3261 __put_user(host_st->st_gid, &target_st->st_gid);
3262 __put_user(host_st->st_rdev, &target_st->st_rdev);
3263 __put_user(host_st->st_size, &target_st->st_size);
3264 __put_user(host_st->st_blksize, &target_st->st_blksize);
3265 __put_user(host_st->st_blocks, &target_st->st_blocks);
3266 __put_user(host_st->st_atime, &target_st->target_st_atime);
3267 __put_user(host_st->st_mtime, &target_st->target_st_mtime);
3268 __put_user(host_st->st_ctime, &target_st->target_st_ctime);
3269 unlock_user_struct(target_st, target_addr, 1);
3270 } else
3271#endif
3272 {
3273 struct target_stat64 *target_st;
3274
3275 if (!lock_user_struct(VERIFY_WRITE, target_st, target_addr, 0))
3276 return -TARGET_EFAULT;
3277 memset(target_st, 0, sizeof(struct target_stat64));
3278 __put_user(host_st->st_dev, &target_st->st_dev);
3279 __put_user(host_st->st_ino, &target_st->st_ino);
3280#ifdef TARGET_STAT64_HAS_BROKEN_ST_INO
3281 __put_user(host_st->st_ino, &target_st->__st_ino);
3282#endif
3283 __put_user(host_st->st_mode, &target_st->st_mode);
3284 __put_user(host_st->st_nlink, &target_st->st_nlink);
3285 __put_user(host_st->st_uid, &target_st->st_uid);
3286 __put_user(host_st->st_gid, &target_st->st_gid);
3287 __put_user(host_st->st_rdev, &target_st->st_rdev);
3288 /* XXX: better use of kernel struct */
3289 __put_user(host_st->st_size, &target_st->st_size);
3290 __put_user(host_st->st_blksize, &target_st->st_blksize);
3291 __put_user(host_st->st_blocks, &target_st->st_blocks);
3292 __put_user(host_st->st_atime, &target_st->target_st_atime);
3293 __put_user(host_st->st_mtime, &target_st->target_st_mtime);
3294 __put_user(host_st->st_ctime, &target_st->target_st_ctime);
3295 unlock_user_struct(target_st, target_addr, 1);
3296 }
3297
3298 return 0;
3299}
3300#endif
3301
pbrookbd0c5662008-05-29 14:34:11 +00003302#if defined(USE_NPTL)
3303/* ??? Using host futex calls even when target atomic operations
3304 are not really atomic probably breaks things. However implementing
3305 futexes locally would make futexes shared between multiple processes
3306 tricky. However they're probably useless because guest atomic
3307 operations won't work either. */
blueswir18fcd3692008-08-17 20:26:25 +00003308static int do_futex(target_ulong uaddr, int op, int val, target_ulong timeout,
3309 target_ulong uaddr2, int val3)
pbrookbd0c5662008-05-29 14:34:11 +00003310{
3311 struct timespec ts, *pts;
3312
3313 /* ??? We assume FUTEX_* constants are the same on both host
3314 and target. */
3315 switch (op) {
3316 case FUTEX_WAIT:
3317 if (timeout) {
3318 pts = &ts;
3319 target_to_host_timespec(pts, timeout);
3320 } else {
3321 pts = NULL;
3322 }
3323 return get_errno(sys_futex(g2h(uaddr), FUTEX_WAIT, tswap32(val),
3324 pts, NULL, 0));
3325 case FUTEX_WAKE:
3326 return get_errno(sys_futex(g2h(uaddr), FUTEX_WAKE, val, NULL, NULL, 0));
3327 case FUTEX_FD:
3328 return get_errno(sys_futex(g2h(uaddr), FUTEX_FD, val, NULL, NULL, 0));
3329 case FUTEX_REQUEUE:
3330 return get_errno(sys_futex(g2h(uaddr), FUTEX_REQUEUE, val,
3331 NULL, g2h(uaddr2), 0));
3332 case FUTEX_CMP_REQUEUE:
3333 return get_errno(sys_futex(g2h(uaddr), FUTEX_CMP_REQUEUE, val,
3334 NULL, g2h(uaddr2), tswap32(val3)));
3335 default:
3336 return -TARGET_ENOSYS;
3337 }
3338}
3339#endif
3340
pbrooka745ec62008-05-06 15:36:17 +00003341int get_osversion(void)
3342{
3343 static int osversion;
3344 struct new_utsname buf;
3345 const char *s;
3346 int i, n, tmp;
3347 if (osversion)
3348 return osversion;
3349 if (qemu_uname_release && *qemu_uname_release) {
3350 s = qemu_uname_release;
3351 } else {
3352 if (sys_uname(&buf))
3353 return 0;
3354 s = buf.release;
3355 }
3356 tmp = 0;
3357 for (i = 0; i < 3; i++) {
3358 n = 0;
3359 while (*s >= '0' && *s <= '9') {
3360 n *= 10;
3361 n += *s - '0';
3362 s++;
3363 }
3364 tmp = (tmp << 8) + n;
3365 if (*s == '.')
3366 s++;
3367 }
3368 osversion = tmp;
3369 return osversion;
3370}
3371
ths0da46a62007-10-20 20:23:07 +00003372/* do_syscall() should always have a single exit point at the end so
3373 that actions, such as logging of syscall results, can be performed.
3374 All errnos that do_syscall() returns must be -TARGET_<errcode>. */
blueswir1992f48a2007-10-14 16:27:31 +00003375abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
3376 abi_long arg2, abi_long arg3, abi_long arg4,
3377 abi_long arg5, abi_long arg6)
bellard31e31b82003-02-18 22:55:36 +00003378{
blueswir1992f48a2007-10-14 16:27:31 +00003379 abi_long ret;
bellard31e31b82003-02-18 22:55:36 +00003380 struct stat st;
bellard56c8f682005-11-28 22:28:41 +00003381 struct statfs stfs;
pbrook53a59602006-03-25 19:31:22 +00003382 void *p;
ths3b46e622007-09-17 08:09:54 +00003383
bellard72f03902003-02-18 23:33:18 +00003384#ifdef DEBUG
bellardc573ff62004-01-04 15:51:36 +00003385 gemu_log("syscall %d", num);
bellard72f03902003-02-18 23:33:18 +00003386#endif
thsb92c47c2007-11-01 00:07:38 +00003387 if(do_strace)
3388 print_syscall(num, arg1, arg2, arg3, arg4, arg5, arg6);
3389
bellard31e31b82003-02-18 22:55:36 +00003390 switch(num) {
3391 case TARGET_NR_exit:
bellard7d132992003-03-06 23:23:54 +00003392#ifdef HAVE_GPROF
3393 _mcleanup();
3394#endif
bellarde9009672005-04-26 20:42:36 +00003395 gdb_exit(cpu_env, arg1);
bellard1b6b0292003-03-22 17:31:38 +00003396 /* XXX: should free thread stack and CPU env */
bellard31e31b82003-02-18 22:55:36 +00003397 _exit(arg1);
3398 ret = 0; /* avoid warning */
3399 break;
3400 case TARGET_NR_read:
bellard579a97f2007-11-11 14:26:47 +00003401 if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
3402 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003403 ret = get_errno(read(arg1, p, arg3));
3404 unlock_user(p, arg2, ret);
bellard31e31b82003-02-18 22:55:36 +00003405 break;
3406 case TARGET_NR_write:
bellard579a97f2007-11-11 14:26:47 +00003407 if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
3408 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003409 ret = get_errno(write(arg1, p, arg3));
3410 unlock_user(p, arg2, 0);
bellard31e31b82003-02-18 22:55:36 +00003411 break;
3412 case TARGET_NR_open:
bellard2f619692007-11-16 10:46:05 +00003413 if (!(p = lock_user_string(arg1)))
3414 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003415 ret = get_errno(open(path(p),
bellardffa65c32004-01-04 23:57:22 +00003416 target_to_host_bitmask(arg2, fcntl_flags_tbl),
3417 arg3));
pbrook53a59602006-03-25 19:31:22 +00003418 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003419 break;
ths82424832007-09-24 09:21:55 +00003420#if defined(TARGET_NR_openat) && defined(__NR_openat)
3421 case TARGET_NR_openat:
bellard579a97f2007-11-11 14:26:47 +00003422 if (!(p = lock_user_string(arg2)))
3423 goto efault;
3424 ret = get_errno(sys_openat(arg1,
3425 path(p),
3426 target_to_host_bitmask(arg3, fcntl_flags_tbl),
3427 arg4));
3428 unlock_user(p, arg2, 0);
ths82424832007-09-24 09:21:55 +00003429 break;
3430#endif
bellard31e31b82003-02-18 22:55:36 +00003431 case TARGET_NR_close:
3432 ret = get_errno(close(arg1));
3433 break;
3434 case TARGET_NR_brk:
pbrook53a59602006-03-25 19:31:22 +00003435 ret = do_brk(arg1);
bellard31e31b82003-02-18 22:55:36 +00003436 break;
3437 case TARGET_NR_fork:
pbrookd865bab2008-06-07 22:12:17 +00003438 ret = get_errno(do_fork(cpu_env, SIGCHLD, 0, 0, 0, 0));
bellard31e31b82003-02-18 22:55:36 +00003439 break;
thse5febef2007-04-01 18:31:35 +00003440#ifdef TARGET_NR_waitpid
bellard31e31b82003-02-18 22:55:36 +00003441 case TARGET_NR_waitpid:
3442 {
pbrook53a59602006-03-25 19:31:22 +00003443 int status;
3444 ret = get_errno(waitpid(arg1, &status, arg3));
bellard2f619692007-11-16 10:46:05 +00003445 if (!is_error(ret) && arg2
3446 && put_user_s32(status, arg2))
3447 goto efault;
bellard31e31b82003-02-18 22:55:36 +00003448 }
3449 break;
thse5febef2007-04-01 18:31:35 +00003450#endif
pbrookf0cbb612008-05-30 18:20:05 +00003451#ifdef TARGET_NR_waitid
3452 case TARGET_NR_waitid:
3453 {
3454 siginfo_t info;
3455 info.si_pid = 0;
3456 ret = get_errno(waitid(arg1, arg2, &info, arg4));
3457 if (!is_error(ret) && arg3 && info.si_pid != 0) {
3458 if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_siginfo_t), 0)))
3459 goto efault;
3460 host_to_target_siginfo(p, &info);
3461 unlock_user(p, arg3, sizeof(target_siginfo_t));
3462 }
3463 }
3464 break;
3465#endif
j_mayer7a3148a2007-04-05 07:13:51 +00003466#ifdef TARGET_NR_creat /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00003467 case TARGET_NR_creat:
bellard579a97f2007-11-11 14:26:47 +00003468 if (!(p = lock_user_string(arg1)))
3469 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003470 ret = get_errno(creat(p, arg2));
3471 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003472 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003473#endif
bellard31e31b82003-02-18 22:55:36 +00003474 case TARGET_NR_link:
pbrook53a59602006-03-25 19:31:22 +00003475 {
3476 void * p2;
3477 p = lock_user_string(arg1);
3478 p2 = lock_user_string(arg2);
bellard579a97f2007-11-11 14:26:47 +00003479 if (!p || !p2)
3480 ret = -TARGET_EFAULT;
3481 else
3482 ret = get_errno(link(p, p2));
pbrook53a59602006-03-25 19:31:22 +00003483 unlock_user(p2, arg2, 0);
3484 unlock_user(p, arg1, 0);
3485 }
bellard31e31b82003-02-18 22:55:36 +00003486 break;
ths64f0ce42007-09-24 09:25:06 +00003487#if defined(TARGET_NR_linkat) && defined(__NR_linkat)
3488 case TARGET_NR_linkat:
ths64f0ce42007-09-24 09:25:06 +00003489 {
3490 void * p2 = NULL;
bellard579a97f2007-11-11 14:26:47 +00003491 if (!arg2 || !arg4)
3492 goto efault;
ths64f0ce42007-09-24 09:25:06 +00003493 p = lock_user_string(arg2);
3494 p2 = lock_user_string(arg4);
bellard579a97f2007-11-11 14:26:47 +00003495 if (!p || !p2)
ths0da46a62007-10-20 20:23:07 +00003496 ret = -TARGET_EFAULT;
ths64f0ce42007-09-24 09:25:06 +00003497 else
3498 ret = get_errno(sys_linkat(arg1, p, arg3, p2, arg5));
bellard579a97f2007-11-11 14:26:47 +00003499 unlock_user(p, arg2, 0);
3500 unlock_user(p2, arg4, 0);
ths64f0ce42007-09-24 09:25:06 +00003501 }
3502 break;
3503#endif
bellard31e31b82003-02-18 22:55:36 +00003504 case TARGET_NR_unlink:
bellard579a97f2007-11-11 14:26:47 +00003505 if (!(p = lock_user_string(arg1)))
3506 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003507 ret = get_errno(unlink(p));
3508 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003509 break;
ths8170f562007-09-24 09:24:11 +00003510#if defined(TARGET_NR_unlinkat) && defined(__NR_unlinkat)
3511 case TARGET_NR_unlinkat:
bellard579a97f2007-11-11 14:26:47 +00003512 if (!(p = lock_user_string(arg2)))
3513 goto efault;
3514 ret = get_errno(sys_unlinkat(arg1, p, arg3));
3515 unlock_user(p, arg2, 0);
balroged494d82007-12-11 23:23:52 +00003516 break;
balrogb7d35e62007-12-12 00:40:24 +00003517#endif
bellard31e31b82003-02-18 22:55:36 +00003518 case TARGET_NR_execve:
bellard7854b052003-03-29 17:22:23 +00003519 {
3520 char **argp, **envp;
bellardf7341ff2003-03-30 21:00:25 +00003521 int argc, envc;
blueswir1992f48a2007-10-14 16:27:31 +00003522 abi_ulong gp;
3523 abi_ulong guest_argp;
3524 abi_ulong guest_envp;
3525 abi_ulong addr;
bellard7854b052003-03-29 17:22:23 +00003526 char **q;
3527
bellardf7341ff2003-03-30 21:00:25 +00003528 argc = 0;
pbrook53a59602006-03-25 19:31:22 +00003529 guest_argp = arg2;
pbrookda94d262008-05-30 18:24:00 +00003530 for (gp = guest_argp; gp; gp += sizeof(abi_ulong)) {
ths03aa1972007-12-02 06:28:08 +00003531 if (get_user_ual(addr, gp))
bellard2f619692007-11-16 10:46:05 +00003532 goto efault;
ths03aa1972007-12-02 06:28:08 +00003533 if (!addr)
bellard2f619692007-11-16 10:46:05 +00003534 break;
bellard7854b052003-03-29 17:22:23 +00003535 argc++;
bellard2f619692007-11-16 10:46:05 +00003536 }
bellardf7341ff2003-03-30 21:00:25 +00003537 envc = 0;
pbrook53a59602006-03-25 19:31:22 +00003538 guest_envp = arg3;
pbrookda94d262008-05-30 18:24:00 +00003539 for (gp = guest_envp; gp; gp += sizeof(abi_ulong)) {
ths03aa1972007-12-02 06:28:08 +00003540 if (get_user_ual(addr, gp))
bellard2f619692007-11-16 10:46:05 +00003541 goto efault;
ths03aa1972007-12-02 06:28:08 +00003542 if (!addr)
bellard2f619692007-11-16 10:46:05 +00003543 break;
bellard7854b052003-03-29 17:22:23 +00003544 envc++;
bellard2f619692007-11-16 10:46:05 +00003545 }
bellard7854b052003-03-29 17:22:23 +00003546
bellardf7341ff2003-03-30 21:00:25 +00003547 argp = alloca((argc + 1) * sizeof(void *));
3548 envp = alloca((envc + 1) * sizeof(void *));
bellard7854b052003-03-29 17:22:23 +00003549
pbrookda94d262008-05-30 18:24:00 +00003550 for (gp = guest_argp, q = argp; gp;
blueswir1992f48a2007-10-14 16:27:31 +00003551 gp += sizeof(abi_ulong), q++) {
bellard2f619692007-11-16 10:46:05 +00003552 if (get_user_ual(addr, gp))
3553 goto execve_efault;
pbrook53a59602006-03-25 19:31:22 +00003554 if (!addr)
3555 break;
bellard2f619692007-11-16 10:46:05 +00003556 if (!(*q = lock_user_string(addr)))
3557 goto execve_efault;
pbrook53a59602006-03-25 19:31:22 +00003558 }
bellardf7341ff2003-03-30 21:00:25 +00003559 *q = NULL;
3560
pbrookda94d262008-05-30 18:24:00 +00003561 for (gp = guest_envp, q = envp; gp;
blueswir1992f48a2007-10-14 16:27:31 +00003562 gp += sizeof(abi_ulong), q++) {
bellard2f619692007-11-16 10:46:05 +00003563 if (get_user_ual(addr, gp))
3564 goto execve_efault;
pbrook53a59602006-03-25 19:31:22 +00003565 if (!addr)
3566 break;
bellard2f619692007-11-16 10:46:05 +00003567 if (!(*q = lock_user_string(addr)))
3568 goto execve_efault;
pbrook53a59602006-03-25 19:31:22 +00003569 }
bellardf7341ff2003-03-30 21:00:25 +00003570 *q = NULL;
bellard7854b052003-03-29 17:22:23 +00003571
bellard2f619692007-11-16 10:46:05 +00003572 if (!(p = lock_user_string(arg1)))
3573 goto execve_efault;
pbrook53a59602006-03-25 19:31:22 +00003574 ret = get_errno(execve(p, argp, envp));
3575 unlock_user(p, arg1, 0);
3576
bellard2f619692007-11-16 10:46:05 +00003577 goto execve_end;
3578
3579 execve_efault:
3580 ret = -TARGET_EFAULT;
3581
3582 execve_end:
pbrook53a59602006-03-25 19:31:22 +00003583 for (gp = guest_argp, q = argp; *q;
blueswir1992f48a2007-10-14 16:27:31 +00003584 gp += sizeof(abi_ulong), q++) {
bellard2f619692007-11-16 10:46:05 +00003585 if (get_user_ual(addr, gp)
3586 || !addr)
3587 break;
pbrook53a59602006-03-25 19:31:22 +00003588 unlock_user(*q, addr, 0);
3589 }
3590 for (gp = guest_envp, q = envp; *q;
blueswir1992f48a2007-10-14 16:27:31 +00003591 gp += sizeof(abi_ulong), q++) {
bellard2f619692007-11-16 10:46:05 +00003592 if (get_user_ual(addr, gp)
3593 || !addr)
3594 break;
pbrook53a59602006-03-25 19:31:22 +00003595 unlock_user(*q, addr, 0);
3596 }
bellard7854b052003-03-29 17:22:23 +00003597 }
bellard31e31b82003-02-18 22:55:36 +00003598 break;
3599 case TARGET_NR_chdir:
bellard579a97f2007-11-11 14:26:47 +00003600 if (!(p = lock_user_string(arg1)))
3601 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003602 ret = get_errno(chdir(p));
3603 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003604 break;
bellarda315a142005-01-30 22:59:18 +00003605#ifdef TARGET_NR_time
bellard31e31b82003-02-18 22:55:36 +00003606 case TARGET_NR_time:
3607 {
pbrook53a59602006-03-25 19:31:22 +00003608 time_t host_time;
3609 ret = get_errno(time(&host_time));
bellard2f619692007-11-16 10:46:05 +00003610 if (!is_error(ret)
3611 && arg1
3612 && put_user_sal(host_time, arg1))
3613 goto efault;
bellard31e31b82003-02-18 22:55:36 +00003614 }
3615 break;
bellarda315a142005-01-30 22:59:18 +00003616#endif
bellard31e31b82003-02-18 22:55:36 +00003617 case TARGET_NR_mknod:
bellard579a97f2007-11-11 14:26:47 +00003618 if (!(p = lock_user_string(arg1)))
3619 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003620 ret = get_errno(mknod(p, arg2, arg3));
3621 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003622 break;
ths75ac37a2007-09-24 09:23:05 +00003623#if defined(TARGET_NR_mknodat) && defined(__NR_mknodat)
3624 case TARGET_NR_mknodat:
bellard579a97f2007-11-11 14:26:47 +00003625 if (!(p = lock_user_string(arg2)))
3626 goto efault;
3627 ret = get_errno(sys_mknodat(arg1, p, arg3, arg4));
3628 unlock_user(p, arg2, 0);
ths75ac37a2007-09-24 09:23:05 +00003629 break;
3630#endif
bellard31e31b82003-02-18 22:55:36 +00003631 case TARGET_NR_chmod:
bellard579a97f2007-11-11 14:26:47 +00003632 if (!(p = lock_user_string(arg1)))
3633 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003634 ret = get_errno(chmod(p, arg2));
3635 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003636 break;
bellardebc05482003-09-30 21:08:41 +00003637#ifdef TARGET_NR_break
bellard31e31b82003-02-18 22:55:36 +00003638 case TARGET_NR_break:
3639 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00003640#endif
3641#ifdef TARGET_NR_oldstat
bellard31e31b82003-02-18 22:55:36 +00003642 case TARGET_NR_oldstat:
3643 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00003644#endif
bellard31e31b82003-02-18 22:55:36 +00003645 case TARGET_NR_lseek:
3646 ret = get_errno(lseek(arg1, arg2, arg3));
3647 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003648#ifdef TARGET_NR_getxpid
3649 case TARGET_NR_getxpid:
3650#else
bellard31e31b82003-02-18 22:55:36 +00003651 case TARGET_NR_getpid:
j_mayer7a3148a2007-04-05 07:13:51 +00003652#endif
bellard31e31b82003-02-18 22:55:36 +00003653 ret = get_errno(getpid());
3654 break;
3655 case TARGET_NR_mount:
ths80265912007-02-17 22:25:41 +00003656 {
3657 /* need to look at the data field */
3658 void *p2, *p3;
3659 p = lock_user_string(arg1);
3660 p2 = lock_user_string(arg2);
3661 p3 = lock_user_string(arg3);
bellard579a97f2007-11-11 14:26:47 +00003662 if (!p || !p2 || !p3)
3663 ret = -TARGET_EFAULT;
3664 else
3665 /* FIXME - arg5 should be locked, but it isn't clear how to
3666 * do that since it's not guaranteed to be a NULL-terminated
3667 * string.
3668 */
3669 ret = get_errno(mount(p, p2, p3, (unsigned long)arg4, g2h(arg5)));
3670 unlock_user(p, arg1, 0);
3671 unlock_user(p2, arg2, 0);
3672 unlock_user(p3, arg3, 0);
ths80265912007-02-17 22:25:41 +00003673 break;
3674 }
thse5febef2007-04-01 18:31:35 +00003675#ifdef TARGET_NR_umount
bellard31e31b82003-02-18 22:55:36 +00003676 case TARGET_NR_umount:
bellard579a97f2007-11-11 14:26:47 +00003677 if (!(p = lock_user_string(arg1)))
3678 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003679 ret = get_errno(umount(p));
3680 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003681 break;
thse5febef2007-04-01 18:31:35 +00003682#endif
j_mayer7a3148a2007-04-05 07:13:51 +00003683#ifdef TARGET_NR_stime /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00003684 case TARGET_NR_stime:
3685 {
pbrook53a59602006-03-25 19:31:22 +00003686 time_t host_time;
bellard2f619692007-11-16 10:46:05 +00003687 if (get_user_sal(host_time, arg1))
3688 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003689 ret = get_errno(stime(&host_time));
bellard31e31b82003-02-18 22:55:36 +00003690 }
3691 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003692#endif
bellard31e31b82003-02-18 22:55:36 +00003693 case TARGET_NR_ptrace:
3694 goto unimplemented;
j_mayer7a3148a2007-04-05 07:13:51 +00003695#ifdef TARGET_NR_alarm /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00003696 case TARGET_NR_alarm:
3697 ret = alarm(arg1);
3698 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003699#endif
bellardebc05482003-09-30 21:08:41 +00003700#ifdef TARGET_NR_oldfstat
bellard31e31b82003-02-18 22:55:36 +00003701 case TARGET_NR_oldfstat:
3702 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00003703#endif
j_mayer7a3148a2007-04-05 07:13:51 +00003704#ifdef TARGET_NR_pause /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00003705 case TARGET_NR_pause:
3706 ret = get_errno(pause());
3707 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003708#endif
thse5febef2007-04-01 18:31:35 +00003709#ifdef TARGET_NR_utime
bellard31e31b82003-02-18 22:55:36 +00003710 case TARGET_NR_utime:
bellardebc05482003-09-30 21:08:41 +00003711 {
pbrook53a59602006-03-25 19:31:22 +00003712 struct utimbuf tbuf, *host_tbuf;
3713 struct target_utimbuf *target_tbuf;
3714 if (arg2) {
bellard579a97f2007-11-11 14:26:47 +00003715 if (!lock_user_struct(VERIFY_READ, target_tbuf, arg2, 1))
3716 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003717 tbuf.actime = tswapl(target_tbuf->actime);
3718 tbuf.modtime = tswapl(target_tbuf->modtime);
3719 unlock_user_struct(target_tbuf, arg2, 0);
3720 host_tbuf = &tbuf;
bellardf72e8ff2004-05-03 19:23:07 +00003721 } else {
pbrook53a59602006-03-25 19:31:22 +00003722 host_tbuf = NULL;
bellardf72e8ff2004-05-03 19:23:07 +00003723 }
bellard579a97f2007-11-11 14:26:47 +00003724 if (!(p = lock_user_string(arg1)))
3725 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003726 ret = get_errno(utime(p, host_tbuf));
3727 unlock_user(p, arg1, 0);
bellardebc05482003-09-30 21:08:41 +00003728 }
3729 break;
thse5febef2007-04-01 18:31:35 +00003730#endif
bellard978a66f2004-12-06 22:58:05 +00003731 case TARGET_NR_utimes:
3732 {
bellard978a66f2004-12-06 22:58:05 +00003733 struct timeval *tvp, tv[2];
pbrook53a59602006-03-25 19:31:22 +00003734 if (arg2) {
ths788f5ec2007-12-09 02:37:05 +00003735 if (copy_from_user_timeval(&tv[0], arg2)
3736 || copy_from_user_timeval(&tv[1],
3737 arg2 + sizeof(struct target_timeval)))
3738 goto efault;
bellard978a66f2004-12-06 22:58:05 +00003739 tvp = tv;
3740 } else {
3741 tvp = NULL;
3742 }
bellard579a97f2007-11-11 14:26:47 +00003743 if (!(p = lock_user_string(arg1)))
3744 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003745 ret = get_errno(utimes(p, tvp));
3746 unlock_user(p, arg1, 0);
bellard978a66f2004-12-06 22:58:05 +00003747 }
3748 break;
balrogac8a6552008-09-20 02:25:39 +00003749#if defined(TARGET_NR_futimesat) && defined(__NR_futimesat)
3750 case TARGET_NR_futimesat:
3751 {
3752 struct timeval *tvp, tv[2];
3753 if (arg3) {
3754 if (copy_from_user_timeval(&tv[0], arg3)
3755 || copy_from_user_timeval(&tv[1],
3756 arg3 + sizeof(struct target_timeval)))
3757 goto efault;
3758 tvp = tv;
3759 } else {
3760 tvp = NULL;
3761 }
3762 if (!(p = lock_user_string(arg2)))
3763 goto efault;
3764 ret = get_errno(sys_futimesat(arg1, path(p), tvp));
3765 unlock_user(p, arg2, 0);
3766 }
3767 break;
3768#endif
bellardebc05482003-09-30 21:08:41 +00003769#ifdef TARGET_NR_stty
bellard31e31b82003-02-18 22:55:36 +00003770 case TARGET_NR_stty:
3771 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00003772#endif
3773#ifdef TARGET_NR_gtty
bellard31e31b82003-02-18 22:55:36 +00003774 case TARGET_NR_gtty:
3775 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00003776#endif
bellard31e31b82003-02-18 22:55:36 +00003777 case TARGET_NR_access:
bellard579a97f2007-11-11 14:26:47 +00003778 if (!(p = lock_user_string(arg1)))
3779 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003780 ret = get_errno(access(p, arg2));
3781 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003782 break;
ths92a34c12007-09-24 09:27:49 +00003783#if defined(TARGET_NR_faccessat) && defined(__NR_faccessat)
3784 case TARGET_NR_faccessat:
bellard579a97f2007-11-11 14:26:47 +00003785 if (!(p = lock_user_string(arg2)))
3786 goto efault;
3787 ret = get_errno(sys_faccessat(arg1, p, arg3, arg4));
3788 unlock_user(p, arg2, 0);
ths92a34c12007-09-24 09:27:49 +00003789 break;
3790#endif
j_mayer7a3148a2007-04-05 07:13:51 +00003791#ifdef TARGET_NR_nice /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00003792 case TARGET_NR_nice:
3793 ret = get_errno(nice(arg1));
3794 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003795#endif
bellardebc05482003-09-30 21:08:41 +00003796#ifdef TARGET_NR_ftime
bellard31e31b82003-02-18 22:55:36 +00003797 case TARGET_NR_ftime:
3798 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00003799#endif
bellard31e31b82003-02-18 22:55:36 +00003800 case TARGET_NR_sync:
bellard04369ff2003-03-20 22:33:23 +00003801 sync();
3802 ret = 0;
bellard31e31b82003-02-18 22:55:36 +00003803 break;
3804 case TARGET_NR_kill:
pbrook4cb05962008-05-30 18:05:19 +00003805 ret = get_errno(kill(arg1, target_to_host_signal(arg2)));
bellard31e31b82003-02-18 22:55:36 +00003806 break;
3807 case TARGET_NR_rename:
pbrook53a59602006-03-25 19:31:22 +00003808 {
3809 void *p2;
3810 p = lock_user_string(arg1);
3811 p2 = lock_user_string(arg2);
bellard579a97f2007-11-11 14:26:47 +00003812 if (!p || !p2)
3813 ret = -TARGET_EFAULT;
3814 else
3815 ret = get_errno(rename(p, p2));
pbrook53a59602006-03-25 19:31:22 +00003816 unlock_user(p2, arg2, 0);
3817 unlock_user(p, arg1, 0);
3818 }
bellard31e31b82003-02-18 22:55:36 +00003819 break;
ths722183f2007-09-24 09:24:37 +00003820#if defined(TARGET_NR_renameat) && defined(__NR_renameat)
3821 case TARGET_NR_renameat:
ths722183f2007-09-24 09:24:37 +00003822 {
bellard579a97f2007-11-11 14:26:47 +00003823 void *p2;
ths722183f2007-09-24 09:24:37 +00003824 p = lock_user_string(arg2);
3825 p2 = lock_user_string(arg4);
bellard579a97f2007-11-11 14:26:47 +00003826 if (!p || !p2)
ths0da46a62007-10-20 20:23:07 +00003827 ret = -TARGET_EFAULT;
ths722183f2007-09-24 09:24:37 +00003828 else
3829 ret = get_errno(sys_renameat(arg1, p, arg3, p2));
bellard579a97f2007-11-11 14:26:47 +00003830 unlock_user(p2, arg4, 0);
3831 unlock_user(p, arg2, 0);
ths722183f2007-09-24 09:24:37 +00003832 }
3833 break;
3834#endif
bellard31e31b82003-02-18 22:55:36 +00003835 case TARGET_NR_mkdir:
bellard579a97f2007-11-11 14:26:47 +00003836 if (!(p = lock_user_string(arg1)))
3837 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003838 ret = get_errno(mkdir(p, arg2));
3839 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003840 break;
ths4472ad02007-09-24 09:22:32 +00003841#if defined(TARGET_NR_mkdirat) && defined(__NR_mkdirat)
3842 case TARGET_NR_mkdirat:
bellard579a97f2007-11-11 14:26:47 +00003843 if (!(p = lock_user_string(arg2)))
3844 goto efault;
3845 ret = get_errno(sys_mkdirat(arg1, p, arg3));
3846 unlock_user(p, arg2, 0);
ths4472ad02007-09-24 09:22:32 +00003847 break;
3848#endif
bellard31e31b82003-02-18 22:55:36 +00003849 case TARGET_NR_rmdir:
bellard579a97f2007-11-11 14:26:47 +00003850 if (!(p = lock_user_string(arg1)))
3851 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003852 ret = get_errno(rmdir(p));
3853 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003854 break;
3855 case TARGET_NR_dup:
3856 ret = get_errno(dup(arg1));
3857 break;
3858 case TARGET_NR_pipe:
3859 {
pbrook53a59602006-03-25 19:31:22 +00003860 int host_pipe[2];
3861 ret = get_errno(pipe(host_pipe));
bellard31e31b82003-02-18 22:55:36 +00003862 if (!is_error(ret)) {
thsc12ab052007-06-01 11:50:36 +00003863#if defined(TARGET_MIPS)
thsead93602007-09-06 00:18:15 +00003864 CPUMIPSState *env = (CPUMIPSState*)cpu_env;
thsb5dc7732008-06-27 10:02:35 +00003865 env->active_tc.gpr[3] = host_pipe[1];
thsc12ab052007-06-01 11:50:36 +00003866 ret = host_pipe[0];
aurel32b5eff352008-03-11 23:30:22 +00003867#elif defined(TARGET_SH4)
3868 ((CPUSH4State*)cpu_env)->gregs[1] = host_pipe[1];
3869 ret = host_pipe[0];
thsc12ab052007-06-01 11:50:36 +00003870#else
bellard2f619692007-11-16 10:46:05 +00003871 if (put_user_s32(host_pipe[0], arg1)
3872 || put_user_s32(host_pipe[1], arg1 + sizeof(host_pipe[0])))
3873 goto efault;
thsc12ab052007-06-01 11:50:36 +00003874#endif
bellard31e31b82003-02-18 22:55:36 +00003875 }
3876 }
3877 break;
3878 case TARGET_NR_times:
bellard32f36bc2003-03-30 21:29:48 +00003879 {
pbrook53a59602006-03-25 19:31:22 +00003880 struct target_tms *tmsp;
bellard32f36bc2003-03-30 21:29:48 +00003881 struct tms tms;
3882 ret = get_errno(times(&tms));
pbrook53a59602006-03-25 19:31:22 +00003883 if (arg1) {
bellard579a97f2007-11-11 14:26:47 +00003884 tmsp = lock_user(VERIFY_WRITE, arg1, sizeof(struct target_tms), 0);
3885 if (!tmsp)
3886 goto efault;
bellardc596ed12003-07-13 17:32:31 +00003887 tmsp->tms_utime = tswapl(host_to_target_clock_t(tms.tms_utime));
3888 tmsp->tms_stime = tswapl(host_to_target_clock_t(tms.tms_stime));
3889 tmsp->tms_cutime = tswapl(host_to_target_clock_t(tms.tms_cutime));
3890 tmsp->tms_cstime = tswapl(host_to_target_clock_t(tms.tms_cstime));
bellard32f36bc2003-03-30 21:29:48 +00003891 }
bellardc596ed12003-07-13 17:32:31 +00003892 if (!is_error(ret))
3893 ret = host_to_target_clock_t(ret);
bellard32f36bc2003-03-30 21:29:48 +00003894 }
3895 break;
bellardebc05482003-09-30 21:08:41 +00003896#ifdef TARGET_NR_prof
bellard31e31b82003-02-18 22:55:36 +00003897 case TARGET_NR_prof:
3898 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00003899#endif
thse5febef2007-04-01 18:31:35 +00003900#ifdef TARGET_NR_signal
bellard31e31b82003-02-18 22:55:36 +00003901 case TARGET_NR_signal:
3902 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00003903#endif
bellard31e31b82003-02-18 22:55:36 +00003904 case TARGET_NR_acct:
bellard579a97f2007-11-11 14:26:47 +00003905 if (!(p = lock_user_string(arg1)))
3906 goto efault;
pbrook24836682006-04-16 14:14:53 +00003907 ret = get_errno(acct(path(p)));
3908 unlock_user(p, arg1, 0);
3909 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003910#ifdef TARGET_NR_umount2 /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00003911 case TARGET_NR_umount2:
bellard579a97f2007-11-11 14:26:47 +00003912 if (!(p = lock_user_string(arg1)))
3913 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003914 ret = get_errno(umount2(p, arg2));
3915 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003916 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003917#endif
bellardebc05482003-09-30 21:08:41 +00003918#ifdef TARGET_NR_lock
bellard31e31b82003-02-18 22:55:36 +00003919 case TARGET_NR_lock:
3920 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00003921#endif
bellard31e31b82003-02-18 22:55:36 +00003922 case TARGET_NR_ioctl:
3923 ret = do_ioctl(arg1, arg2, arg3);
3924 break;
3925 case TARGET_NR_fcntl:
bellard9ee1fa22007-11-11 15:11:19 +00003926 ret = do_fcntl(arg1, arg2, arg3);
bellard31e31b82003-02-18 22:55:36 +00003927 break;
bellardebc05482003-09-30 21:08:41 +00003928#ifdef TARGET_NR_mpx
bellard31e31b82003-02-18 22:55:36 +00003929 case TARGET_NR_mpx:
3930 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00003931#endif
bellard31e31b82003-02-18 22:55:36 +00003932 case TARGET_NR_setpgid:
3933 ret = get_errno(setpgid(arg1, arg2));
3934 break;
bellardebc05482003-09-30 21:08:41 +00003935#ifdef TARGET_NR_ulimit
bellard31e31b82003-02-18 22:55:36 +00003936 case TARGET_NR_ulimit:
3937 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00003938#endif
3939#ifdef TARGET_NR_oldolduname
bellard31e31b82003-02-18 22:55:36 +00003940 case TARGET_NR_oldolduname:
3941 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00003942#endif
bellard31e31b82003-02-18 22:55:36 +00003943 case TARGET_NR_umask:
3944 ret = get_errno(umask(arg1));
3945 break;
3946 case TARGET_NR_chroot:
bellard579a97f2007-11-11 14:26:47 +00003947 if (!(p = lock_user_string(arg1)))
3948 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003949 ret = get_errno(chroot(p));
3950 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003951 break;
3952 case TARGET_NR_ustat:
3953 goto unimplemented;
3954 case TARGET_NR_dup2:
3955 ret = get_errno(dup2(arg1, arg2));
3956 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003957#ifdef TARGET_NR_getppid /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00003958 case TARGET_NR_getppid:
3959 ret = get_errno(getppid());
3960 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003961#endif
bellard31e31b82003-02-18 22:55:36 +00003962 case TARGET_NR_getpgrp:
3963 ret = get_errno(getpgrp());
3964 break;
3965 case TARGET_NR_setsid:
3966 ret = get_errno(setsid());
3967 break;
thse5febef2007-04-01 18:31:35 +00003968#ifdef TARGET_NR_sigaction
bellard31e31b82003-02-18 22:55:36 +00003969 case TARGET_NR_sigaction:
bellard31e31b82003-02-18 22:55:36 +00003970 {
ths388bb212007-05-13 13:58:00 +00003971#if !defined(TARGET_MIPS)
pbrook53a59602006-03-25 19:31:22 +00003972 struct target_old_sigaction *old_act;
bellard66fb9762003-03-23 01:06:05 +00003973 struct target_sigaction act, oact, *pact;
pbrook53a59602006-03-25 19:31:22 +00003974 if (arg2) {
bellard579a97f2007-11-11 14:26:47 +00003975 if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1))
3976 goto efault;
bellard66fb9762003-03-23 01:06:05 +00003977 act._sa_handler = old_act->_sa_handler;
3978 target_siginitset(&act.sa_mask, old_act->sa_mask);
3979 act.sa_flags = old_act->sa_flags;
3980 act.sa_restorer = old_act->sa_restorer;
pbrook53a59602006-03-25 19:31:22 +00003981 unlock_user_struct(old_act, arg2, 0);
bellard66fb9762003-03-23 01:06:05 +00003982 pact = &act;
3983 } else {
3984 pact = NULL;
3985 }
3986 ret = get_errno(do_sigaction(arg1, pact, &oact));
pbrook53a59602006-03-25 19:31:22 +00003987 if (!is_error(ret) && arg3) {
bellard579a97f2007-11-11 14:26:47 +00003988 if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0))
3989 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003990 old_act->_sa_handler = oact._sa_handler;
3991 old_act->sa_mask = oact.sa_mask.sig[0];
3992 old_act->sa_flags = oact.sa_flags;
3993 old_act->sa_restorer = oact.sa_restorer;
3994 unlock_user_struct(old_act, arg3, 1);
bellard66fb9762003-03-23 01:06:05 +00003995 }
ths388bb212007-05-13 13:58:00 +00003996#else
bellard106ec872006-06-27 21:08:10 +00003997 struct target_sigaction act, oact, *pact, *old_act;
3998
3999 if (arg2) {
bellard579a97f2007-11-11 14:26:47 +00004000 if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1))
4001 goto efault;
bellard106ec872006-06-27 21:08:10 +00004002 act._sa_handler = old_act->_sa_handler;
4003 target_siginitset(&act.sa_mask, old_act->sa_mask.sig[0]);
4004 act.sa_flags = old_act->sa_flags;
4005 unlock_user_struct(old_act, arg2, 0);
4006 pact = &act;
4007 } else {
4008 pact = NULL;
4009 }
4010
4011 ret = get_errno(do_sigaction(arg1, pact, &oact));
4012
4013 if (!is_error(ret) && arg3) {
bellard579a97f2007-11-11 14:26:47 +00004014 if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0))
4015 goto efault;
bellard106ec872006-06-27 21:08:10 +00004016 old_act->_sa_handler = oact._sa_handler;
4017 old_act->sa_flags = oact.sa_flags;
4018 old_act->sa_mask.sig[0] = oact.sa_mask.sig[0];
4019 old_act->sa_mask.sig[1] = 0;
4020 old_act->sa_mask.sig[2] = 0;
4021 old_act->sa_mask.sig[3] = 0;
4022 unlock_user_struct(old_act, arg3, 1);
4023 }
ths388bb212007-05-13 13:58:00 +00004024#endif
bellard31e31b82003-02-18 22:55:36 +00004025 }
4026 break;
thse5febef2007-04-01 18:31:35 +00004027#endif
bellard66fb9762003-03-23 01:06:05 +00004028 case TARGET_NR_rt_sigaction:
pbrook53a59602006-03-25 19:31:22 +00004029 {
4030 struct target_sigaction *act;
4031 struct target_sigaction *oact;
4032
bellard579a97f2007-11-11 14:26:47 +00004033 if (arg2) {
4034 if (!lock_user_struct(VERIFY_READ, act, arg2, 1))
4035 goto efault;
4036 } else
pbrook53a59602006-03-25 19:31:22 +00004037 act = NULL;
bellard579a97f2007-11-11 14:26:47 +00004038 if (arg3) {
4039 if (!lock_user_struct(VERIFY_WRITE, oact, arg3, 0)) {
4040 ret = -TARGET_EFAULT;
4041 goto rt_sigaction_fail;
4042 }
4043 } else
pbrook53a59602006-03-25 19:31:22 +00004044 oact = NULL;
4045 ret = get_errno(do_sigaction(arg1, act, oact));
bellard579a97f2007-11-11 14:26:47 +00004046 rt_sigaction_fail:
4047 if (act)
pbrook53a59602006-03-25 19:31:22 +00004048 unlock_user_struct(act, arg2, 0);
bellard579a97f2007-11-11 14:26:47 +00004049 if (oact)
pbrook53a59602006-03-25 19:31:22 +00004050 unlock_user_struct(oact, arg3, 1);
4051 }
bellard66fb9762003-03-23 01:06:05 +00004052 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004053#ifdef TARGET_NR_sgetmask /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00004054 case TARGET_NR_sgetmask:
bellard66fb9762003-03-23 01:06:05 +00004055 {
4056 sigset_t cur_set;
blueswir1992f48a2007-10-14 16:27:31 +00004057 abi_ulong target_set;
bellard66fb9762003-03-23 01:06:05 +00004058 sigprocmask(0, NULL, &cur_set);
4059 host_to_target_old_sigset(&target_set, &cur_set);
4060 ret = target_set;
4061 }
4062 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004063#endif
4064#ifdef TARGET_NR_ssetmask /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00004065 case TARGET_NR_ssetmask:
bellard66fb9762003-03-23 01:06:05 +00004066 {
4067 sigset_t set, oset, cur_set;
blueswir1992f48a2007-10-14 16:27:31 +00004068 abi_ulong target_set = arg1;
bellard66fb9762003-03-23 01:06:05 +00004069 sigprocmask(0, NULL, &cur_set);
4070 target_to_host_old_sigset(&set, &target_set);
4071 sigorset(&set, &set, &cur_set);
4072 sigprocmask(SIG_SETMASK, &set, &oset);
4073 host_to_target_old_sigset(&target_set, &oset);
4074 ret = target_set;
4075 }
4076 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004077#endif
thse5febef2007-04-01 18:31:35 +00004078#ifdef TARGET_NR_sigprocmask
bellard66fb9762003-03-23 01:06:05 +00004079 case TARGET_NR_sigprocmask:
4080 {
4081 int how = arg1;
4082 sigset_t set, oldset, *set_ptr;
ths3b46e622007-09-17 08:09:54 +00004083
pbrook53a59602006-03-25 19:31:22 +00004084 if (arg2) {
bellard66fb9762003-03-23 01:06:05 +00004085 switch(how) {
4086 case TARGET_SIG_BLOCK:
4087 how = SIG_BLOCK;
4088 break;
4089 case TARGET_SIG_UNBLOCK:
4090 how = SIG_UNBLOCK;
4091 break;
4092 case TARGET_SIG_SETMASK:
4093 how = SIG_SETMASK;
4094 break;
4095 default:
ths0da46a62007-10-20 20:23:07 +00004096 ret = -TARGET_EINVAL;
bellard66fb9762003-03-23 01:06:05 +00004097 goto fail;
4098 }
bellard579a97f2007-11-11 14:26:47 +00004099 if (!(p = lock_user(VERIFY_READ, arg2, sizeof(target_sigset_t), 1)))
4100 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004101 target_to_host_old_sigset(&set, p);
4102 unlock_user(p, arg2, 0);
bellard66fb9762003-03-23 01:06:05 +00004103 set_ptr = &set;
4104 } else {
4105 how = 0;
4106 set_ptr = NULL;
4107 }
4108 ret = get_errno(sigprocmask(arg1, set_ptr, &oldset));
pbrook53a59602006-03-25 19:31:22 +00004109 if (!is_error(ret) && arg3) {
bellard579a97f2007-11-11 14:26:47 +00004110 if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0)))
4111 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004112 host_to_target_old_sigset(p, &oldset);
4113 unlock_user(p, arg3, sizeof(target_sigset_t));
bellard66fb9762003-03-23 01:06:05 +00004114 }
4115 }
4116 break;
thse5febef2007-04-01 18:31:35 +00004117#endif
bellard66fb9762003-03-23 01:06:05 +00004118 case TARGET_NR_rt_sigprocmask:
4119 {
4120 int how = arg1;
4121 sigset_t set, oldset, *set_ptr;
ths3b46e622007-09-17 08:09:54 +00004122
pbrook53a59602006-03-25 19:31:22 +00004123 if (arg2) {
bellard66fb9762003-03-23 01:06:05 +00004124 switch(how) {
4125 case TARGET_SIG_BLOCK:
4126 how = SIG_BLOCK;
4127 break;
4128 case TARGET_SIG_UNBLOCK:
4129 how = SIG_UNBLOCK;
4130 break;
4131 case TARGET_SIG_SETMASK:
4132 how = SIG_SETMASK;
4133 break;
4134 default:
ths0da46a62007-10-20 20:23:07 +00004135 ret = -TARGET_EINVAL;
bellard66fb9762003-03-23 01:06:05 +00004136 goto fail;
4137 }
bellard579a97f2007-11-11 14:26:47 +00004138 if (!(p = lock_user(VERIFY_READ, arg2, sizeof(target_sigset_t), 1)))
4139 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004140 target_to_host_sigset(&set, p);
4141 unlock_user(p, arg2, 0);
bellard66fb9762003-03-23 01:06:05 +00004142 set_ptr = &set;
4143 } else {
4144 how = 0;
4145 set_ptr = NULL;
4146 }
4147 ret = get_errno(sigprocmask(how, set_ptr, &oldset));
pbrook53a59602006-03-25 19:31:22 +00004148 if (!is_error(ret) && arg3) {
bellard579a97f2007-11-11 14:26:47 +00004149 if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0)))
4150 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004151 host_to_target_sigset(p, &oldset);
4152 unlock_user(p, arg3, sizeof(target_sigset_t));
bellard66fb9762003-03-23 01:06:05 +00004153 }
4154 }
4155 break;
thse5febef2007-04-01 18:31:35 +00004156#ifdef TARGET_NR_sigpending
bellard66fb9762003-03-23 01:06:05 +00004157 case TARGET_NR_sigpending:
4158 {
4159 sigset_t set;
4160 ret = get_errno(sigpending(&set));
4161 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00004162 if (!(p = lock_user(VERIFY_WRITE, arg1, sizeof(target_sigset_t), 0)))
4163 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004164 host_to_target_old_sigset(p, &set);
4165 unlock_user(p, arg1, sizeof(target_sigset_t));
bellard66fb9762003-03-23 01:06:05 +00004166 }
4167 }
4168 break;
thse5febef2007-04-01 18:31:35 +00004169#endif
bellard66fb9762003-03-23 01:06:05 +00004170 case TARGET_NR_rt_sigpending:
4171 {
4172 sigset_t set;
4173 ret = get_errno(sigpending(&set));
4174 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00004175 if (!(p = lock_user(VERIFY_WRITE, arg1, sizeof(target_sigset_t), 0)))
4176 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004177 host_to_target_sigset(p, &set);
4178 unlock_user(p, arg1, sizeof(target_sigset_t));
bellard66fb9762003-03-23 01:06:05 +00004179 }
4180 }
4181 break;
thse5febef2007-04-01 18:31:35 +00004182#ifdef TARGET_NR_sigsuspend
bellard66fb9762003-03-23 01:06:05 +00004183 case TARGET_NR_sigsuspend:
4184 {
4185 sigset_t set;
bellard579a97f2007-11-11 14:26:47 +00004186 if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
4187 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004188 target_to_host_old_sigset(&set, p);
4189 unlock_user(p, arg1, 0);
bellard66fb9762003-03-23 01:06:05 +00004190 ret = get_errno(sigsuspend(&set));
4191 }
4192 break;
thse5febef2007-04-01 18:31:35 +00004193#endif
bellard66fb9762003-03-23 01:06:05 +00004194 case TARGET_NR_rt_sigsuspend:
4195 {
4196 sigset_t set;
bellard579a97f2007-11-11 14:26:47 +00004197 if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
4198 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004199 target_to_host_sigset(&set, p);
4200 unlock_user(p, arg1, 0);
bellard66fb9762003-03-23 01:06:05 +00004201 ret = get_errno(sigsuspend(&set));
4202 }
4203 break;
4204 case TARGET_NR_rt_sigtimedwait:
4205 {
bellard66fb9762003-03-23 01:06:05 +00004206 sigset_t set;
4207 struct timespec uts, *puts;
4208 siginfo_t uinfo;
ths3b46e622007-09-17 08:09:54 +00004209
bellard579a97f2007-11-11 14:26:47 +00004210 if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
4211 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004212 target_to_host_sigset(&set, p);
4213 unlock_user(p, arg1, 0);
4214 if (arg3) {
bellard66fb9762003-03-23 01:06:05 +00004215 puts = &uts;
pbrook53a59602006-03-25 19:31:22 +00004216 target_to_host_timespec(puts, arg3);
bellard66fb9762003-03-23 01:06:05 +00004217 } else {
4218 puts = NULL;
4219 }
4220 ret = get_errno(sigtimedwait(&set, &uinfo, puts));
pbrook53a59602006-03-25 19:31:22 +00004221 if (!is_error(ret) && arg2) {
pbrooke1e3f302008-05-30 21:53:38 +00004222 if (!(p = lock_user(VERIFY_WRITE, arg2, sizeof(target_siginfo_t), 0)))
bellard579a97f2007-11-11 14:26:47 +00004223 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004224 host_to_target_siginfo(p, &uinfo);
pbrooke1e3f302008-05-30 21:53:38 +00004225 unlock_user(p, arg2, sizeof(target_siginfo_t));
bellard66fb9762003-03-23 01:06:05 +00004226 }
4227 }
4228 break;
4229 case TARGET_NR_rt_sigqueueinfo:
4230 {
4231 siginfo_t uinfo;
bellard579a97f2007-11-11 14:26:47 +00004232 if (!(p = lock_user(VERIFY_READ, arg3, sizeof(target_sigset_t), 1)))
4233 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004234 target_to_host_siginfo(&uinfo, p);
4235 unlock_user(p, arg1, 0);
bellard66fb9762003-03-23 01:06:05 +00004236 ret = get_errno(sys_rt_sigqueueinfo(arg1, arg2, &uinfo));
4237 }
4238 break;
thse5febef2007-04-01 18:31:35 +00004239#ifdef TARGET_NR_sigreturn
bellard66fb9762003-03-23 01:06:05 +00004240 case TARGET_NR_sigreturn:
4241 /* NOTE: ret is eax, so not transcoding must be done */
4242 ret = do_sigreturn(cpu_env);
4243 break;
thse5febef2007-04-01 18:31:35 +00004244#endif
bellard66fb9762003-03-23 01:06:05 +00004245 case TARGET_NR_rt_sigreturn:
4246 /* NOTE: ret is eax, so not transcoding must be done */
4247 ret = do_rt_sigreturn(cpu_env);
4248 break;
bellard31e31b82003-02-18 22:55:36 +00004249 case TARGET_NR_sethostname:
bellard579a97f2007-11-11 14:26:47 +00004250 if (!(p = lock_user_string(arg1)))
4251 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004252 ret = get_errno(sethostname(p, arg2));
4253 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004254 break;
4255 case TARGET_NR_setrlimit:
bellard9de5e442003-03-23 16:49:39 +00004256 {
4257 /* XXX: convert resource ? */
4258 int resource = arg1;
pbrook53a59602006-03-25 19:31:22 +00004259 struct target_rlimit *target_rlim;
bellard9de5e442003-03-23 16:49:39 +00004260 struct rlimit rlim;
bellard579a97f2007-11-11 14:26:47 +00004261 if (!lock_user_struct(VERIFY_READ, target_rlim, arg2, 1))
4262 goto efault;
bellard9de5e442003-03-23 16:49:39 +00004263 rlim.rlim_cur = tswapl(target_rlim->rlim_cur);
4264 rlim.rlim_max = tswapl(target_rlim->rlim_max);
pbrook53a59602006-03-25 19:31:22 +00004265 unlock_user_struct(target_rlim, arg2, 0);
bellard9de5e442003-03-23 16:49:39 +00004266 ret = get_errno(setrlimit(resource, &rlim));
4267 }
4268 break;
bellard31e31b82003-02-18 22:55:36 +00004269 case TARGET_NR_getrlimit:
bellard9de5e442003-03-23 16:49:39 +00004270 {
4271 /* XXX: convert resource ? */
4272 int resource = arg1;
pbrook53a59602006-03-25 19:31:22 +00004273 struct target_rlimit *target_rlim;
bellard9de5e442003-03-23 16:49:39 +00004274 struct rlimit rlim;
ths3b46e622007-09-17 08:09:54 +00004275
bellard9de5e442003-03-23 16:49:39 +00004276 ret = get_errno(getrlimit(resource, &rlim));
4277 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00004278 if (!lock_user_struct(VERIFY_WRITE, target_rlim, arg2, 0))
4279 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004280 rlim.rlim_cur = tswapl(target_rlim->rlim_cur);
4281 rlim.rlim_max = tswapl(target_rlim->rlim_max);
4282 unlock_user_struct(target_rlim, arg2, 1);
bellard9de5e442003-03-23 16:49:39 +00004283 }
4284 }
4285 break;
bellard31e31b82003-02-18 22:55:36 +00004286 case TARGET_NR_getrusage:
bellardb4091862003-05-16 15:39:34 +00004287 {
4288 struct rusage rusage;
bellardb4091862003-05-16 15:39:34 +00004289 ret = get_errno(getrusage(arg1, &rusage));
4290 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00004291 host_to_target_rusage(arg2, &rusage);
bellardb4091862003-05-16 15:39:34 +00004292 }
4293 }
4294 break;
bellard31e31b82003-02-18 22:55:36 +00004295 case TARGET_NR_gettimeofday:
4296 {
bellard31e31b82003-02-18 22:55:36 +00004297 struct timeval tv;
4298 ret = get_errno(gettimeofday(&tv, NULL));
4299 if (!is_error(ret)) {
ths788f5ec2007-12-09 02:37:05 +00004300 if (copy_to_user_timeval(arg1, &tv))
4301 goto efault;
bellard31e31b82003-02-18 22:55:36 +00004302 }
4303 }
4304 break;
4305 case TARGET_NR_settimeofday:
4306 {
bellard31e31b82003-02-18 22:55:36 +00004307 struct timeval tv;
ths788f5ec2007-12-09 02:37:05 +00004308 if (copy_from_user_timeval(&tv, arg1))
4309 goto efault;
bellard31e31b82003-02-18 22:55:36 +00004310 ret = get_errno(settimeofday(&tv, NULL));
4311 }
4312 break;
bellard048f6b42005-11-26 18:47:20 +00004313#ifdef TARGET_NR_select
bellard31e31b82003-02-18 22:55:36 +00004314 case TARGET_NR_select:
bellardf2674e32003-07-09 12:26:09 +00004315 {
pbrook53a59602006-03-25 19:31:22 +00004316 struct target_sel_arg_struct *sel;
blueswir1992f48a2007-10-14 16:27:31 +00004317 abi_ulong inp, outp, exp, tvp;
pbrook53a59602006-03-25 19:31:22 +00004318 long nsel;
4319
bellard579a97f2007-11-11 14:26:47 +00004320 if (!lock_user_struct(VERIFY_READ, sel, arg1, 1))
4321 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004322 nsel = tswapl(sel->n);
4323 inp = tswapl(sel->inp);
4324 outp = tswapl(sel->outp);
4325 exp = tswapl(sel->exp);
4326 tvp = tswapl(sel->tvp);
4327 unlock_user_struct(sel, arg1, 0);
4328 ret = do_select(nsel, inp, outp, exp, tvp);
bellardf2674e32003-07-09 12:26:09 +00004329 }
4330 break;
bellard048f6b42005-11-26 18:47:20 +00004331#endif
bellard31e31b82003-02-18 22:55:36 +00004332 case TARGET_NR_symlink:
pbrook53a59602006-03-25 19:31:22 +00004333 {
4334 void *p2;
4335 p = lock_user_string(arg1);
4336 p2 = lock_user_string(arg2);
bellard579a97f2007-11-11 14:26:47 +00004337 if (!p || !p2)
4338 ret = -TARGET_EFAULT;
4339 else
4340 ret = get_errno(symlink(p, p2));
pbrook53a59602006-03-25 19:31:22 +00004341 unlock_user(p2, arg2, 0);
4342 unlock_user(p, arg1, 0);
4343 }
bellard31e31b82003-02-18 22:55:36 +00004344 break;
thsf0b62432007-09-24 09:25:40 +00004345#if defined(TARGET_NR_symlinkat) && defined(__NR_symlinkat)
4346 case TARGET_NR_symlinkat:
thsf0b62432007-09-24 09:25:40 +00004347 {
bellard579a97f2007-11-11 14:26:47 +00004348 void *p2;
thsf0b62432007-09-24 09:25:40 +00004349 p = lock_user_string(arg1);
4350 p2 = lock_user_string(arg3);
bellard579a97f2007-11-11 14:26:47 +00004351 if (!p || !p2)
ths0da46a62007-10-20 20:23:07 +00004352 ret = -TARGET_EFAULT;
thsf0b62432007-09-24 09:25:40 +00004353 else
4354 ret = get_errno(sys_symlinkat(p, arg2, p2));
bellard579a97f2007-11-11 14:26:47 +00004355 unlock_user(p2, arg3, 0);
4356 unlock_user(p, arg1, 0);
thsf0b62432007-09-24 09:25:40 +00004357 }
4358 break;
4359#endif
bellardebc05482003-09-30 21:08:41 +00004360#ifdef TARGET_NR_oldlstat
bellard31e31b82003-02-18 22:55:36 +00004361 case TARGET_NR_oldlstat:
4362 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004363#endif
bellard31e31b82003-02-18 22:55:36 +00004364 case TARGET_NR_readlink:
pbrook53a59602006-03-25 19:31:22 +00004365 {
4366 void *p2;
4367 p = lock_user_string(arg1);
bellard579a97f2007-11-11 14:26:47 +00004368 p2 = lock_user(VERIFY_WRITE, arg2, arg3, 0);
4369 if (!p || !p2)
4370 ret = -TARGET_EFAULT;
4371 else
4372 ret = get_errno(readlink(path(p), p2, arg3));
pbrook53a59602006-03-25 19:31:22 +00004373 unlock_user(p2, arg2, ret);
4374 unlock_user(p, arg1, 0);
4375 }
bellard31e31b82003-02-18 22:55:36 +00004376 break;
ths5e0ccb12007-09-24 09:26:10 +00004377#if defined(TARGET_NR_readlinkat) && defined(__NR_readlinkat)
4378 case TARGET_NR_readlinkat:
ths5e0ccb12007-09-24 09:26:10 +00004379 {
bellard579a97f2007-11-11 14:26:47 +00004380 void *p2;
ths5e0ccb12007-09-24 09:26:10 +00004381 p = lock_user_string(arg2);
bellard579a97f2007-11-11 14:26:47 +00004382 p2 = lock_user(VERIFY_WRITE, arg3, arg4, 0);
4383 if (!p || !p2)
ths0da46a62007-10-20 20:23:07 +00004384 ret = -TARGET_EFAULT;
ths5e0ccb12007-09-24 09:26:10 +00004385 else
4386 ret = get_errno(sys_readlinkat(arg1, path(p), p2, arg4));
bellard579a97f2007-11-11 14:26:47 +00004387 unlock_user(p2, arg3, ret);
4388 unlock_user(p, arg2, 0);
ths5e0ccb12007-09-24 09:26:10 +00004389 }
4390 break;
4391#endif
thse5febef2007-04-01 18:31:35 +00004392#ifdef TARGET_NR_uselib
bellard31e31b82003-02-18 22:55:36 +00004393 case TARGET_NR_uselib:
4394 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00004395#endif
4396#ifdef TARGET_NR_swapon
bellard31e31b82003-02-18 22:55:36 +00004397 case TARGET_NR_swapon:
bellard579a97f2007-11-11 14:26:47 +00004398 if (!(p = lock_user_string(arg1)))
4399 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004400 ret = get_errno(swapon(p, arg2));
4401 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004402 break;
thse5febef2007-04-01 18:31:35 +00004403#endif
bellard31e31b82003-02-18 22:55:36 +00004404 case TARGET_NR_reboot:
4405 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00004406#ifdef TARGET_NR_readdir
bellard31e31b82003-02-18 22:55:36 +00004407 case TARGET_NR_readdir:
4408 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00004409#endif
4410#ifdef TARGET_NR_mmap
bellard31e31b82003-02-18 22:55:36 +00004411 case TARGET_NR_mmap:
bellardd2fd1af2007-11-14 18:08:56 +00004412#if (defined(TARGET_I386) && defined(TARGET_ABI32)) || defined(TARGET_ARM) || defined(TARGET_M68K) || defined(TARGET_CRIS)
bellard31e31b82003-02-18 22:55:36 +00004413 {
blueswir1992f48a2007-10-14 16:27:31 +00004414 abi_ulong *v;
4415 abi_ulong v1, v2, v3, v4, v5, v6;
bellard579a97f2007-11-11 14:26:47 +00004416 if (!(v = lock_user(VERIFY_READ, arg1, 6 * sizeof(abi_ulong), 1)))
4417 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004418 v1 = tswapl(v[0]);
4419 v2 = tswapl(v[1]);
4420 v3 = tswapl(v[2]);
4421 v4 = tswapl(v[3]);
4422 v5 = tswapl(v[4]);
4423 v6 = tswapl(v[5]);
4424 unlock_user(v, arg1, 0);
ths5fafdf22007-09-16 21:08:06 +00004425 ret = get_errno(target_mmap(v1, v2, v3,
bellard5286db72003-06-05 00:57:30 +00004426 target_to_host_bitmask(v4, mmap_flags_tbl),
4427 v5, v6));
bellard31e31b82003-02-18 22:55:36 +00004428 }
bellard31e31b82003-02-18 22:55:36 +00004429#else
ths5fafdf22007-09-16 21:08:06 +00004430 ret = get_errno(target_mmap(arg1, arg2, arg3,
4431 target_to_host_bitmask(arg4, mmap_flags_tbl),
bellard6fb883e2003-07-09 17:12:39 +00004432 arg5,
4433 arg6));
bellard31e31b82003-02-18 22:55:36 +00004434#endif
bellard6fb883e2003-07-09 17:12:39 +00004435 break;
thse5febef2007-04-01 18:31:35 +00004436#endif
bellarda315a142005-01-30 22:59:18 +00004437#ifdef TARGET_NR_mmap2
bellard6fb883e2003-07-09 17:12:39 +00004438 case TARGET_NR_mmap2:
pbrookbb7ec042008-03-25 22:28:25 +00004439#ifndef MMAP_SHIFT
bellardc573ff62004-01-04 15:51:36 +00004440#define MMAP_SHIFT 12
bellardc573ff62004-01-04 15:51:36 +00004441#endif
ths5fafdf22007-09-16 21:08:06 +00004442 ret = get_errno(target_mmap(arg1, arg2, arg3,
4443 target_to_host_bitmask(arg4, mmap_flags_tbl),
bellard5286db72003-06-05 00:57:30 +00004444 arg5,
bellardc573ff62004-01-04 15:51:36 +00004445 arg6 << MMAP_SHIFT));
bellard31e31b82003-02-18 22:55:36 +00004446 break;
bellarda315a142005-01-30 22:59:18 +00004447#endif
bellard31e31b82003-02-18 22:55:36 +00004448 case TARGET_NR_munmap:
bellard54936002003-05-13 00:25:15 +00004449 ret = get_errno(target_munmap(arg1, arg2));
bellard31e31b82003-02-18 22:55:36 +00004450 break;
bellard9de5e442003-03-23 16:49:39 +00004451 case TARGET_NR_mprotect:
bellard54936002003-05-13 00:25:15 +00004452 ret = get_errno(target_mprotect(arg1, arg2, arg3));
bellard9de5e442003-03-23 16:49:39 +00004453 break;
thse5febef2007-04-01 18:31:35 +00004454#ifdef TARGET_NR_mremap
bellard9de5e442003-03-23 16:49:39 +00004455 case TARGET_NR_mremap:
bellard54936002003-05-13 00:25:15 +00004456 ret = get_errno(target_mremap(arg1, arg2, arg3, arg4, arg5));
bellard9de5e442003-03-23 16:49:39 +00004457 break;
thse5febef2007-04-01 18:31:35 +00004458#endif
pbrook53a59602006-03-25 19:31:22 +00004459 /* ??? msync/mlock/munlock are broken for softmmu. */
thse5febef2007-04-01 18:31:35 +00004460#ifdef TARGET_NR_msync
bellard9de5e442003-03-23 16:49:39 +00004461 case TARGET_NR_msync:
pbrook53a59602006-03-25 19:31:22 +00004462 ret = get_errno(msync(g2h(arg1), arg2, arg3));
bellard9de5e442003-03-23 16:49:39 +00004463 break;
thse5febef2007-04-01 18:31:35 +00004464#endif
4465#ifdef TARGET_NR_mlock
bellard9de5e442003-03-23 16:49:39 +00004466 case TARGET_NR_mlock:
pbrook53a59602006-03-25 19:31:22 +00004467 ret = get_errno(mlock(g2h(arg1), arg2));
bellard9de5e442003-03-23 16:49:39 +00004468 break;
thse5febef2007-04-01 18:31:35 +00004469#endif
4470#ifdef TARGET_NR_munlock
bellard9de5e442003-03-23 16:49:39 +00004471 case TARGET_NR_munlock:
pbrook53a59602006-03-25 19:31:22 +00004472 ret = get_errno(munlock(g2h(arg1), arg2));
bellard9de5e442003-03-23 16:49:39 +00004473 break;
thse5febef2007-04-01 18:31:35 +00004474#endif
4475#ifdef TARGET_NR_mlockall
bellard9de5e442003-03-23 16:49:39 +00004476 case TARGET_NR_mlockall:
4477 ret = get_errno(mlockall(arg1));
4478 break;
thse5febef2007-04-01 18:31:35 +00004479#endif
4480#ifdef TARGET_NR_munlockall
bellard9de5e442003-03-23 16:49:39 +00004481 case TARGET_NR_munlockall:
4482 ret = get_errno(munlockall());
4483 break;
thse5febef2007-04-01 18:31:35 +00004484#endif
bellard31e31b82003-02-18 22:55:36 +00004485 case TARGET_NR_truncate:
bellard579a97f2007-11-11 14:26:47 +00004486 if (!(p = lock_user_string(arg1)))
4487 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004488 ret = get_errno(truncate(p, arg2));
4489 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004490 break;
4491 case TARGET_NR_ftruncate:
4492 ret = get_errno(ftruncate(arg1, arg2));
4493 break;
4494 case TARGET_NR_fchmod:
4495 ret = get_errno(fchmod(arg1, arg2));
4496 break;
ths814d7972007-09-24 09:26:51 +00004497#if defined(TARGET_NR_fchmodat) && defined(__NR_fchmodat)
4498 case TARGET_NR_fchmodat:
bellard579a97f2007-11-11 14:26:47 +00004499 if (!(p = lock_user_string(arg2)))
4500 goto efault;
4501 ret = get_errno(sys_fchmodat(arg1, p, arg3, arg4));
4502 unlock_user(p, arg2, 0);
ths814d7972007-09-24 09:26:51 +00004503 break;
4504#endif
bellard31e31b82003-02-18 22:55:36 +00004505 case TARGET_NR_getpriority:
thsc6cda172007-10-09 03:42:34 +00004506 /* libc does special remapping of the return value of
4507 * sys_getpriority() so it's just easiest to call
4508 * sys_getpriority() directly rather than through libc. */
4509 ret = sys_getpriority(arg1, arg2);
bellard31e31b82003-02-18 22:55:36 +00004510 break;
4511 case TARGET_NR_setpriority:
4512 ret = get_errno(setpriority(arg1, arg2, arg3));
4513 break;
bellardebc05482003-09-30 21:08:41 +00004514#ifdef TARGET_NR_profil
bellard31e31b82003-02-18 22:55:36 +00004515 case TARGET_NR_profil:
4516 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004517#endif
bellard31e31b82003-02-18 22:55:36 +00004518 case TARGET_NR_statfs:
bellard579a97f2007-11-11 14:26:47 +00004519 if (!(p = lock_user_string(arg1)))
4520 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004521 ret = get_errno(statfs(path(p), &stfs));
4522 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004523 convert_statfs:
4524 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00004525 struct target_statfs *target_stfs;
ths3b46e622007-09-17 08:09:54 +00004526
bellard579a97f2007-11-11 14:26:47 +00004527 if (!lock_user_struct(VERIFY_WRITE, target_stfs, arg2, 0))
4528 goto efault;
4529 __put_user(stfs.f_type, &target_stfs->f_type);
4530 __put_user(stfs.f_bsize, &target_stfs->f_bsize);
4531 __put_user(stfs.f_blocks, &target_stfs->f_blocks);
4532 __put_user(stfs.f_bfree, &target_stfs->f_bfree);
4533 __put_user(stfs.f_bavail, &target_stfs->f_bavail);
4534 __put_user(stfs.f_files, &target_stfs->f_files);
4535 __put_user(stfs.f_ffree, &target_stfs->f_ffree);
4536 __put_user(stfs.f_fsid.__val[0], &target_stfs->f_fsid.val[0]);
4537 __put_user(stfs.f_fsid.__val[1], &target_stfs->f_fsid.val[1]);
4538 __put_user(stfs.f_namelen, &target_stfs->f_namelen);
pbrook53a59602006-03-25 19:31:22 +00004539 unlock_user_struct(target_stfs, arg2, 1);
bellard31e31b82003-02-18 22:55:36 +00004540 }
4541 break;
4542 case TARGET_NR_fstatfs:
bellard56c8f682005-11-28 22:28:41 +00004543 ret = get_errno(fstatfs(arg1, &stfs));
bellard31e31b82003-02-18 22:55:36 +00004544 goto convert_statfs;
bellard56c8f682005-11-28 22:28:41 +00004545#ifdef TARGET_NR_statfs64
4546 case TARGET_NR_statfs64:
bellard579a97f2007-11-11 14:26:47 +00004547 if (!(p = lock_user_string(arg1)))
4548 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004549 ret = get_errno(statfs(path(p), &stfs));
4550 unlock_user(p, arg1, 0);
bellard56c8f682005-11-28 22:28:41 +00004551 convert_statfs64:
4552 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00004553 struct target_statfs64 *target_stfs;
ths3b46e622007-09-17 08:09:54 +00004554
bellard579a97f2007-11-11 14:26:47 +00004555 if (!lock_user_struct(VERIFY_WRITE, target_stfs, arg3, 0))
4556 goto efault;
4557 __put_user(stfs.f_type, &target_stfs->f_type);
4558 __put_user(stfs.f_bsize, &target_stfs->f_bsize);
4559 __put_user(stfs.f_blocks, &target_stfs->f_blocks);
4560 __put_user(stfs.f_bfree, &target_stfs->f_bfree);
4561 __put_user(stfs.f_bavail, &target_stfs->f_bavail);
4562 __put_user(stfs.f_files, &target_stfs->f_files);
4563 __put_user(stfs.f_ffree, &target_stfs->f_ffree);
4564 __put_user(stfs.f_fsid.__val[0], &target_stfs->f_fsid.val[0]);
4565 __put_user(stfs.f_fsid.__val[1], &target_stfs->f_fsid.val[1]);
4566 __put_user(stfs.f_namelen, &target_stfs->f_namelen);
4567 unlock_user_struct(target_stfs, arg3, 1);
bellard56c8f682005-11-28 22:28:41 +00004568 }
4569 break;
4570 case TARGET_NR_fstatfs64:
4571 ret = get_errno(fstatfs(arg1, &stfs));
4572 goto convert_statfs64;
4573#endif
bellardebc05482003-09-30 21:08:41 +00004574#ifdef TARGET_NR_ioperm
bellard31e31b82003-02-18 22:55:36 +00004575 case TARGET_NR_ioperm:
4576 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004577#endif
thse5febef2007-04-01 18:31:35 +00004578#ifdef TARGET_NR_socketcall
bellard31e31b82003-02-18 22:55:36 +00004579 case TARGET_NR_socketcall:
pbrook53a59602006-03-25 19:31:22 +00004580 ret = do_socketcall(arg1, arg2);
bellard31e31b82003-02-18 22:55:36 +00004581 break;
thse5febef2007-04-01 18:31:35 +00004582#endif
bellard3532fa72006-06-24 15:06:03 +00004583#ifdef TARGET_NR_accept
4584 case TARGET_NR_accept:
pbrook1be9e1d2006-11-19 15:26:04 +00004585 ret = do_accept(arg1, arg2, arg3);
bellard3532fa72006-06-24 15:06:03 +00004586 break;
4587#endif
4588#ifdef TARGET_NR_bind
4589 case TARGET_NR_bind:
4590 ret = do_bind(arg1, arg2, arg3);
4591 break;
4592#endif
4593#ifdef TARGET_NR_connect
4594 case TARGET_NR_connect:
4595 ret = do_connect(arg1, arg2, arg3);
4596 break;
4597#endif
4598#ifdef TARGET_NR_getpeername
4599 case TARGET_NR_getpeername:
pbrook1be9e1d2006-11-19 15:26:04 +00004600 ret = do_getpeername(arg1, arg2, arg3);
bellard3532fa72006-06-24 15:06:03 +00004601 break;
4602#endif
4603#ifdef TARGET_NR_getsockname
4604 case TARGET_NR_getsockname:
pbrook1be9e1d2006-11-19 15:26:04 +00004605 ret = do_getsockname(arg1, arg2, arg3);
bellard3532fa72006-06-24 15:06:03 +00004606 break;
4607#endif
4608#ifdef TARGET_NR_getsockopt
4609 case TARGET_NR_getsockopt:
4610 ret = do_getsockopt(arg1, arg2, arg3, arg4, arg5);
4611 break;
4612#endif
4613#ifdef TARGET_NR_listen
4614 case TARGET_NR_listen:
pbrook1be9e1d2006-11-19 15:26:04 +00004615 ret = get_errno(listen(arg1, arg2));
bellard3532fa72006-06-24 15:06:03 +00004616 break;
4617#endif
4618#ifdef TARGET_NR_recv
4619 case TARGET_NR_recv:
pbrook214201b2007-03-17 01:27:24 +00004620 ret = do_recvfrom(arg1, arg2, arg3, arg4, 0, 0);
bellard3532fa72006-06-24 15:06:03 +00004621 break;
4622#endif
4623#ifdef TARGET_NR_recvfrom
4624 case TARGET_NR_recvfrom:
pbrook214201b2007-03-17 01:27:24 +00004625 ret = do_recvfrom(arg1, arg2, arg3, arg4, arg5, arg6);
bellard3532fa72006-06-24 15:06:03 +00004626 break;
4627#endif
4628#ifdef TARGET_NR_recvmsg
4629 case TARGET_NR_recvmsg:
4630 ret = do_sendrecvmsg(arg1, arg2, arg3, 0);
4631 break;
4632#endif
4633#ifdef TARGET_NR_send
4634 case TARGET_NR_send:
pbrook1be9e1d2006-11-19 15:26:04 +00004635 ret = do_sendto(arg1, arg2, arg3, arg4, 0, 0);
bellard3532fa72006-06-24 15:06:03 +00004636 break;
4637#endif
4638#ifdef TARGET_NR_sendmsg
4639 case TARGET_NR_sendmsg:
4640 ret = do_sendrecvmsg(arg1, arg2, arg3, 1);
4641 break;
4642#endif
4643#ifdef TARGET_NR_sendto
4644 case TARGET_NR_sendto:
pbrook1be9e1d2006-11-19 15:26:04 +00004645 ret = do_sendto(arg1, arg2, arg3, arg4, arg5, arg6);
bellard3532fa72006-06-24 15:06:03 +00004646 break;
4647#endif
4648#ifdef TARGET_NR_shutdown
4649 case TARGET_NR_shutdown:
pbrook1be9e1d2006-11-19 15:26:04 +00004650 ret = get_errno(shutdown(arg1, arg2));
bellard3532fa72006-06-24 15:06:03 +00004651 break;
4652#endif
4653#ifdef TARGET_NR_socket
4654 case TARGET_NR_socket:
4655 ret = do_socket(arg1, arg2, arg3);
4656 break;
4657#endif
4658#ifdef TARGET_NR_socketpair
4659 case TARGET_NR_socketpair:
pbrook1be9e1d2006-11-19 15:26:04 +00004660 ret = do_socketpair(arg1, arg2, arg3, arg4);
bellard3532fa72006-06-24 15:06:03 +00004661 break;
4662#endif
4663#ifdef TARGET_NR_setsockopt
4664 case TARGET_NR_setsockopt:
4665 ret = do_setsockopt(arg1, arg2, arg3, arg4, (socklen_t) arg5);
4666 break;
4667#endif
ths7494b0f2007-02-11 18:26:53 +00004668
bellard31e31b82003-02-18 22:55:36 +00004669 case TARGET_NR_syslog:
bellard579a97f2007-11-11 14:26:47 +00004670 if (!(p = lock_user_string(arg2)))
4671 goto efault;
thse5574482007-02-11 20:03:13 +00004672 ret = get_errno(sys_syslog((int)arg1, p, (int)arg3));
4673 unlock_user(p, arg2, 0);
ths7494b0f2007-02-11 18:26:53 +00004674 break;
4675
bellard31e31b82003-02-18 22:55:36 +00004676 case TARGET_NR_setitimer:
bellard66fb9762003-03-23 01:06:05 +00004677 {
bellard66fb9762003-03-23 01:06:05 +00004678 struct itimerval value, ovalue, *pvalue;
4679
pbrook53a59602006-03-25 19:31:22 +00004680 if (arg2) {
bellard66fb9762003-03-23 01:06:05 +00004681 pvalue = &value;
ths788f5ec2007-12-09 02:37:05 +00004682 if (copy_from_user_timeval(&pvalue->it_interval, arg2)
4683 || copy_from_user_timeval(&pvalue->it_value,
4684 arg2 + sizeof(struct target_timeval)))
4685 goto efault;
bellard66fb9762003-03-23 01:06:05 +00004686 } else {
4687 pvalue = NULL;
4688 }
4689 ret = get_errno(setitimer(arg1, pvalue, &ovalue));
pbrook53a59602006-03-25 19:31:22 +00004690 if (!is_error(ret) && arg3) {
ths788f5ec2007-12-09 02:37:05 +00004691 if (copy_to_user_timeval(arg3,
4692 &ovalue.it_interval)
4693 || copy_to_user_timeval(arg3 + sizeof(struct target_timeval),
4694 &ovalue.it_value))
4695 goto efault;
bellard66fb9762003-03-23 01:06:05 +00004696 }
4697 }
4698 break;
bellard31e31b82003-02-18 22:55:36 +00004699 case TARGET_NR_getitimer:
bellard66fb9762003-03-23 01:06:05 +00004700 {
bellard66fb9762003-03-23 01:06:05 +00004701 struct itimerval value;
ths3b46e622007-09-17 08:09:54 +00004702
bellard66fb9762003-03-23 01:06:05 +00004703 ret = get_errno(getitimer(arg1, &value));
pbrook53a59602006-03-25 19:31:22 +00004704 if (!is_error(ret) && arg2) {
ths788f5ec2007-12-09 02:37:05 +00004705 if (copy_to_user_timeval(arg2,
4706 &value.it_interval)
4707 || copy_to_user_timeval(arg2 + sizeof(struct target_timeval),
4708 &value.it_value))
4709 goto efault;
bellard66fb9762003-03-23 01:06:05 +00004710 }
4711 }
4712 break;
bellard31e31b82003-02-18 22:55:36 +00004713 case TARGET_NR_stat:
bellard579a97f2007-11-11 14:26:47 +00004714 if (!(p = lock_user_string(arg1)))
4715 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004716 ret = get_errno(stat(path(p), &st));
4717 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004718 goto do_stat;
4719 case TARGET_NR_lstat:
bellard579a97f2007-11-11 14:26:47 +00004720 if (!(p = lock_user_string(arg1)))
4721 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004722 ret = get_errno(lstat(path(p), &st));
4723 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004724 goto do_stat;
4725 case TARGET_NR_fstat:
4726 {
4727 ret = get_errno(fstat(arg1, &st));
4728 do_stat:
4729 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00004730 struct target_stat *target_st;
thse3584652007-06-01 11:49:38 +00004731
bellard579a97f2007-11-11 14:26:47 +00004732 if (!lock_user_struct(VERIFY_WRITE, target_st, arg2, 0))
4733 goto efault;
bellardd2fd1af2007-11-14 18:08:56 +00004734 __put_user(st.st_dev, &target_st->st_dev);
4735 __put_user(st.st_ino, &target_st->st_ino);
4736 __put_user(st.st_mode, &target_st->st_mode);
4737 __put_user(st.st_uid, &target_st->st_uid);
4738 __put_user(st.st_gid, &target_st->st_gid);
4739 __put_user(st.st_nlink, &target_st->st_nlink);
4740 __put_user(st.st_rdev, &target_st->st_rdev);
4741 __put_user(st.st_size, &target_st->st_size);
4742 __put_user(st.st_blksize, &target_st->st_blksize);
4743 __put_user(st.st_blocks, &target_st->st_blocks);
4744 __put_user(st.st_atime, &target_st->target_st_atime);
4745 __put_user(st.st_mtime, &target_st->target_st_mtime);
4746 __put_user(st.st_ctime, &target_st->target_st_ctime);
pbrook53a59602006-03-25 19:31:22 +00004747 unlock_user_struct(target_st, arg2, 1);
bellard31e31b82003-02-18 22:55:36 +00004748 }
4749 }
4750 break;
bellardebc05482003-09-30 21:08:41 +00004751#ifdef TARGET_NR_olduname
bellard31e31b82003-02-18 22:55:36 +00004752 case TARGET_NR_olduname:
4753 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004754#endif
4755#ifdef TARGET_NR_iopl
bellard31e31b82003-02-18 22:55:36 +00004756 case TARGET_NR_iopl:
4757 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004758#endif
bellard31e31b82003-02-18 22:55:36 +00004759 case TARGET_NR_vhangup:
4760 ret = get_errno(vhangup());
4761 break;
bellardebc05482003-09-30 21:08:41 +00004762#ifdef TARGET_NR_idle
bellard31e31b82003-02-18 22:55:36 +00004763 case TARGET_NR_idle:
4764 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004765#endif
bellard42ad6ae2005-01-03 22:48:11 +00004766#ifdef TARGET_NR_syscall
4767 case TARGET_NR_syscall:
4768 ret = do_syscall(cpu_env,arg1 & 0xffff,arg2,arg3,arg4,arg5,arg6,0);
4769 break;
4770#endif
bellard31e31b82003-02-18 22:55:36 +00004771 case TARGET_NR_wait4:
4772 {
4773 int status;
blueswir1992f48a2007-10-14 16:27:31 +00004774 abi_long status_ptr = arg2;
bellard31e31b82003-02-18 22:55:36 +00004775 struct rusage rusage, *rusage_ptr;
blueswir1992f48a2007-10-14 16:27:31 +00004776 abi_ulong target_rusage = arg4;
bellard31e31b82003-02-18 22:55:36 +00004777 if (target_rusage)
4778 rusage_ptr = &rusage;
4779 else
4780 rusage_ptr = NULL;
4781 ret = get_errno(wait4(arg1, &status, arg3, rusage_ptr));
4782 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +00004783 if (status_ptr) {
4784 if (put_user_s32(status, status_ptr))
4785 goto efault;
bellard31e31b82003-02-18 22:55:36 +00004786 }
bellard2f619692007-11-16 10:46:05 +00004787 if (target_rusage)
4788 host_to_target_rusage(target_rusage, &rusage);
bellard31e31b82003-02-18 22:55:36 +00004789 }
4790 }
4791 break;
thse5febef2007-04-01 18:31:35 +00004792#ifdef TARGET_NR_swapoff
bellard31e31b82003-02-18 22:55:36 +00004793 case TARGET_NR_swapoff:
bellard579a97f2007-11-11 14:26:47 +00004794 if (!(p = lock_user_string(arg1)))
4795 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004796 ret = get_errno(swapoff(p));
4797 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004798 break;
thse5febef2007-04-01 18:31:35 +00004799#endif
bellard31e31b82003-02-18 22:55:36 +00004800 case TARGET_NR_sysinfo:
bellarda5448a72004-06-19 16:59:03 +00004801 {
pbrook53a59602006-03-25 19:31:22 +00004802 struct target_sysinfo *target_value;
bellarda5448a72004-06-19 16:59:03 +00004803 struct sysinfo value;
4804 ret = get_errno(sysinfo(&value));
pbrook53a59602006-03-25 19:31:22 +00004805 if (!is_error(ret) && arg1)
bellarda5448a72004-06-19 16:59:03 +00004806 {
bellard579a97f2007-11-11 14:26:47 +00004807 if (!lock_user_struct(VERIFY_WRITE, target_value, arg1, 0))
4808 goto efault;
bellarda5448a72004-06-19 16:59:03 +00004809 __put_user(value.uptime, &target_value->uptime);
4810 __put_user(value.loads[0], &target_value->loads[0]);
4811 __put_user(value.loads[1], &target_value->loads[1]);
4812 __put_user(value.loads[2], &target_value->loads[2]);
4813 __put_user(value.totalram, &target_value->totalram);
4814 __put_user(value.freeram, &target_value->freeram);
4815 __put_user(value.sharedram, &target_value->sharedram);
4816 __put_user(value.bufferram, &target_value->bufferram);
4817 __put_user(value.totalswap, &target_value->totalswap);
4818 __put_user(value.freeswap, &target_value->freeswap);
4819 __put_user(value.procs, &target_value->procs);
4820 __put_user(value.totalhigh, &target_value->totalhigh);
4821 __put_user(value.freehigh, &target_value->freehigh);
4822 __put_user(value.mem_unit, &target_value->mem_unit);
pbrook53a59602006-03-25 19:31:22 +00004823 unlock_user_struct(target_value, arg1, 1);
bellarda5448a72004-06-19 16:59:03 +00004824 }
4825 }
4826 break;
thse5febef2007-04-01 18:31:35 +00004827#ifdef TARGET_NR_ipc
bellard31e31b82003-02-18 22:55:36 +00004828 case TARGET_NR_ipc:
bellard8853f862004-02-22 14:57:26 +00004829 ret = do_ipc(arg1, arg2, arg3, arg4, arg5, arg6);
4830 break;
thse5febef2007-04-01 18:31:35 +00004831#endif
aurel32eeb438c2008-10-13 21:08:55 +00004832
4833#ifdef TARGET_NR_msgctl
4834 case TARGET_NR_msgctl:
4835 ret = do_msgctl(arg1, arg2, arg3);
4836 break;
4837#endif
4838#ifdef TARGET_NR_msgget
4839 case TARGET_NR_msgget:
4840 ret = get_errno(msgget(arg1, arg2));
4841 break;
4842#endif
4843#ifdef TARGET_NR_msgrcv
4844 case TARGET_NR_msgrcv:
4845 ret = do_msgrcv(arg1, arg2, arg3, arg4, arg5);
4846 break;
4847#endif
4848#ifdef TARGET_NR_msgsnd
4849 case TARGET_NR_msgsnd:
4850 ret = do_msgsnd(arg1, arg2, arg3, arg4);
4851 break;
4852#endif
bellard31e31b82003-02-18 22:55:36 +00004853 case TARGET_NR_fsync:
4854 ret = get_errno(fsync(arg1));
4855 break;
bellard31e31b82003-02-18 22:55:36 +00004856 case TARGET_NR_clone:
aurel320b6d3ae2008-09-15 07:43:43 +00004857#if defined(TARGET_SH4)
4858 ret = get_errno(do_fork(cpu_env, arg1, arg2, arg3, arg5, arg4));
4859#else
pbrookd865bab2008-06-07 22:12:17 +00004860 ret = get_errno(do_fork(cpu_env, arg1, arg2, arg3, arg4, arg5));
aurel320b6d3ae2008-09-15 07:43:43 +00004861#endif
bellard1b6b0292003-03-22 17:31:38 +00004862 break;
bellardec86b0f2003-04-11 00:15:04 +00004863#ifdef __NR_exit_group
4864 /* new thread calls */
4865 case TARGET_NR_exit_group:
bellarde9009672005-04-26 20:42:36 +00004866 gdb_exit(cpu_env, arg1);
bellardec86b0f2003-04-11 00:15:04 +00004867 ret = get_errno(exit_group(arg1));
4868 break;
4869#endif
bellard31e31b82003-02-18 22:55:36 +00004870 case TARGET_NR_setdomainname:
bellard579a97f2007-11-11 14:26:47 +00004871 if (!(p = lock_user_string(arg1)))
4872 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004873 ret = get_errno(setdomainname(p, arg2));
4874 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004875 break;
4876 case TARGET_NR_uname:
4877 /* no need to transcode because we use the linux syscall */
bellard29e619b2004-09-13 21:41:04 +00004878 {
4879 struct new_utsname * buf;
ths3b46e622007-09-17 08:09:54 +00004880
bellard579a97f2007-11-11 14:26:47 +00004881 if (!lock_user_struct(VERIFY_WRITE, buf, arg1, 0))
4882 goto efault;
bellard29e619b2004-09-13 21:41:04 +00004883 ret = get_errno(sys_uname(buf));
4884 if (!is_error(ret)) {
4885 /* Overrite the native machine name with whatever is being
4886 emulated. */
4887 strcpy (buf->machine, UNAME_MACHINE);
pbrookc5937222006-05-14 11:30:38 +00004888 /* Allow the user to override the reported release. */
4889 if (qemu_uname_release && *qemu_uname_release)
4890 strcpy (buf->release, qemu_uname_release);
bellard29e619b2004-09-13 21:41:04 +00004891 }
pbrook53a59602006-03-25 19:31:22 +00004892 unlock_user_struct(buf, arg1, 1);
bellard29e619b2004-09-13 21:41:04 +00004893 }
bellard31e31b82003-02-18 22:55:36 +00004894 break;
bellard6dbad632003-03-16 18:05:05 +00004895#ifdef TARGET_I386
bellard31e31b82003-02-18 22:55:36 +00004896 case TARGET_NR_modify_ldt:
bellard03acab62007-11-11 14:57:14 +00004897 ret = do_modify_ldt(cpu_env, arg1, arg2, arg3);
bellard5cd43932003-03-29 16:54:36 +00004898 break;
j_mayer84409dd2007-04-06 08:56:50 +00004899#if !defined(TARGET_X86_64)
bellard5cd43932003-03-29 16:54:36 +00004900 case TARGET_NR_vm86old:
4901 goto unimplemented;
4902 case TARGET_NR_vm86:
pbrook53a59602006-03-25 19:31:22 +00004903 ret = do_vm86(cpu_env, arg1, arg2);
bellard6dbad632003-03-16 18:05:05 +00004904 break;
4905#endif
j_mayer84409dd2007-04-06 08:56:50 +00004906#endif
bellard31e31b82003-02-18 22:55:36 +00004907 case TARGET_NR_adjtimex:
4908 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00004909#ifdef TARGET_NR_create_module
bellard31e31b82003-02-18 22:55:36 +00004910 case TARGET_NR_create_module:
thse5febef2007-04-01 18:31:35 +00004911#endif
bellard31e31b82003-02-18 22:55:36 +00004912 case TARGET_NR_init_module:
4913 case TARGET_NR_delete_module:
thse5febef2007-04-01 18:31:35 +00004914#ifdef TARGET_NR_get_kernel_syms
bellard31e31b82003-02-18 22:55:36 +00004915 case TARGET_NR_get_kernel_syms:
thse5febef2007-04-01 18:31:35 +00004916#endif
bellard31e31b82003-02-18 22:55:36 +00004917 goto unimplemented;
4918 case TARGET_NR_quotactl:
4919 goto unimplemented;
4920 case TARGET_NR_getpgid:
4921 ret = get_errno(getpgid(arg1));
4922 break;
4923 case TARGET_NR_fchdir:
4924 ret = get_errno(fchdir(arg1));
4925 break;
j_mayer84409dd2007-04-06 08:56:50 +00004926#ifdef TARGET_NR_bdflush /* not on x86_64 */
bellard31e31b82003-02-18 22:55:36 +00004927 case TARGET_NR_bdflush:
4928 goto unimplemented;
j_mayer84409dd2007-04-06 08:56:50 +00004929#endif
thse5febef2007-04-01 18:31:35 +00004930#ifdef TARGET_NR_sysfs
bellard31e31b82003-02-18 22:55:36 +00004931 case TARGET_NR_sysfs:
4932 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00004933#endif
bellard31e31b82003-02-18 22:55:36 +00004934 case TARGET_NR_personality:
bellard1b6b0292003-03-22 17:31:38 +00004935 ret = get_errno(personality(arg1));
bellard31e31b82003-02-18 22:55:36 +00004936 break;
thse5febef2007-04-01 18:31:35 +00004937#ifdef TARGET_NR_afs_syscall
bellard31e31b82003-02-18 22:55:36 +00004938 case TARGET_NR_afs_syscall:
4939 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00004940#endif
j_mayer7a3148a2007-04-05 07:13:51 +00004941#ifdef TARGET_NR__llseek /* Not on alpha */
bellard31e31b82003-02-18 22:55:36 +00004942 case TARGET_NR__llseek:
4943 {
bellard4f2ac232004-04-26 19:44:02 +00004944#if defined (__x86_64__)
4945 ret = get_errno(lseek(arg1, ((uint64_t )arg2 << 32) | arg3, arg5));
bellard2f619692007-11-16 10:46:05 +00004946 if (put_user_s64(ret, arg4))
4947 goto efault;
bellard4f2ac232004-04-26 19:44:02 +00004948#else
bellard31e31b82003-02-18 22:55:36 +00004949 int64_t res;
4950 ret = get_errno(_llseek(arg1, arg2, arg3, &res, arg5));
bellard2f619692007-11-16 10:46:05 +00004951 if (put_user_s64(res, arg4))
4952 goto efault;
bellard4f2ac232004-04-26 19:44:02 +00004953#endif
bellard31e31b82003-02-18 22:55:36 +00004954 }
4955 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004956#endif
bellard31e31b82003-02-18 22:55:36 +00004957 case TARGET_NR_getdents:
blueswir1992f48a2007-10-14 16:27:31 +00004958#if TARGET_ABI_BITS != 32
pbrook53a59602006-03-25 19:31:22 +00004959 goto unimplemented;
blueswir1992f48a2007-10-14 16:27:31 +00004960#elif TARGET_ABI_BITS == 32 && HOST_LONG_BITS == 64
bellard4add45b2003-06-05 01:52:59 +00004961 {
pbrook53a59602006-03-25 19:31:22 +00004962 struct target_dirent *target_dirp;
aurel326556a832008-10-13 21:08:17 +00004963 struct linux_dirent *dirp;
blueswir1992f48a2007-10-14 16:27:31 +00004964 abi_long count = arg3;
bellard4add45b2003-06-05 01:52:59 +00004965
4966 dirp = malloc(count);
ths0da46a62007-10-20 20:23:07 +00004967 if (!dirp) {
bellard579a97f2007-11-11 14:26:47 +00004968 ret = -TARGET_ENOMEM;
ths0da46a62007-10-20 20:23:07 +00004969 goto fail;
4970 }
ths3b46e622007-09-17 08:09:54 +00004971
bellard4add45b2003-06-05 01:52:59 +00004972 ret = get_errno(sys_getdents(arg1, dirp, count));
4973 if (!is_error(ret)) {
aurel326556a832008-10-13 21:08:17 +00004974 struct linux_dirent *de;
bellard4add45b2003-06-05 01:52:59 +00004975 struct target_dirent *tde;
4976 int len = ret;
4977 int reclen, treclen;
4978 int count1, tnamelen;
4979
4980 count1 = 0;
4981 de = dirp;
bellard579a97f2007-11-11 14:26:47 +00004982 if (!(target_dirp = lock_user(VERIFY_WRITE, arg2, count, 0)))
4983 goto efault;
bellard4add45b2003-06-05 01:52:59 +00004984 tde = target_dirp;
4985 while (len > 0) {
4986 reclen = de->d_reclen;
blueswir1992f48a2007-10-14 16:27:31 +00004987 treclen = reclen - (2 * (sizeof(long) - sizeof(abi_long)));
bellard4add45b2003-06-05 01:52:59 +00004988 tde->d_reclen = tswap16(treclen);
4989 tde->d_ino = tswapl(de->d_ino);
4990 tde->d_off = tswapl(de->d_off);
blueswir1992f48a2007-10-14 16:27:31 +00004991 tnamelen = treclen - (2 * sizeof(abi_long) + 2);
bellard4add45b2003-06-05 01:52:59 +00004992 if (tnamelen > 256)
4993 tnamelen = 256;
bellard80a9d032005-01-03 23:31:27 +00004994 /* XXX: may not be correct */
bellard4add45b2003-06-05 01:52:59 +00004995 strncpy(tde->d_name, de->d_name, tnamelen);
aurel326556a832008-10-13 21:08:17 +00004996 de = (struct linux_dirent *)((char *)de + reclen);
bellard4add45b2003-06-05 01:52:59 +00004997 len -= reclen;
j_mayer1c5bf3b2007-04-14 12:17:59 +00004998 tde = (struct target_dirent *)((char *)tde + treclen);
bellard4add45b2003-06-05 01:52:59 +00004999 count1 += treclen;
5000 }
5001 ret = count1;
bellard579a97f2007-11-11 14:26:47 +00005002 unlock_user(target_dirp, arg2, ret);
bellard4add45b2003-06-05 01:52:59 +00005003 }
5004 free(dirp);
5005 }
5006#else
bellard31e31b82003-02-18 22:55:36 +00005007 {
aurel326556a832008-10-13 21:08:17 +00005008 struct linux_dirent *dirp;
blueswir1992f48a2007-10-14 16:27:31 +00005009 abi_long count = arg3;
bellarddab2ed92003-03-22 15:23:14 +00005010
bellard579a97f2007-11-11 14:26:47 +00005011 if (!(dirp = lock_user(VERIFY_WRITE, arg2, count, 0)))
5012 goto efault;
bellard72f03902003-02-18 23:33:18 +00005013 ret = get_errno(sys_getdents(arg1, dirp, count));
bellard31e31b82003-02-18 22:55:36 +00005014 if (!is_error(ret)) {
aurel326556a832008-10-13 21:08:17 +00005015 struct linux_dirent *de;
bellard31e31b82003-02-18 22:55:36 +00005016 int len = ret;
5017 int reclen;
5018 de = dirp;
5019 while (len > 0) {
bellard8083a3e2003-03-24 23:12:16 +00005020 reclen = de->d_reclen;
bellard31e31b82003-02-18 22:55:36 +00005021 if (reclen > len)
5022 break;
bellard8083a3e2003-03-24 23:12:16 +00005023 de->d_reclen = tswap16(reclen);
bellard31e31b82003-02-18 22:55:36 +00005024 tswapls(&de->d_ino);
5025 tswapls(&de->d_off);
aurel326556a832008-10-13 21:08:17 +00005026 de = (struct linux_dirent *)((char *)de + reclen);
bellard31e31b82003-02-18 22:55:36 +00005027 len -= reclen;
5028 }
5029 }
pbrook53a59602006-03-25 19:31:22 +00005030 unlock_user(dirp, arg2, ret);
bellard31e31b82003-02-18 22:55:36 +00005031 }
bellard4add45b2003-06-05 01:52:59 +00005032#endif
bellard31e31b82003-02-18 22:55:36 +00005033 break;
ths3ae43202007-09-16 21:39:48 +00005034#if defined(TARGET_NR_getdents64) && defined(__NR_getdents64)
bellarddab2ed92003-03-22 15:23:14 +00005035 case TARGET_NR_getdents64:
5036 {
aurel326556a832008-10-13 21:08:17 +00005037 struct linux_dirent64 *dirp;
blueswir1992f48a2007-10-14 16:27:31 +00005038 abi_long count = arg3;
bellard579a97f2007-11-11 14:26:47 +00005039 if (!(dirp = lock_user(VERIFY_WRITE, arg2, count, 0)))
5040 goto efault;
bellarddab2ed92003-03-22 15:23:14 +00005041 ret = get_errno(sys_getdents64(arg1, dirp, count));
5042 if (!is_error(ret)) {
aurel326556a832008-10-13 21:08:17 +00005043 struct linux_dirent64 *de;
bellarddab2ed92003-03-22 15:23:14 +00005044 int len = ret;
5045 int reclen;
5046 de = dirp;
5047 while (len > 0) {
bellard8083a3e2003-03-24 23:12:16 +00005048 reclen = de->d_reclen;
bellarddab2ed92003-03-22 15:23:14 +00005049 if (reclen > len)
5050 break;
bellard8083a3e2003-03-24 23:12:16 +00005051 de->d_reclen = tswap16(reclen);
bellard8582a532007-11-11 23:11:36 +00005052 tswap64s((uint64_t *)&de->d_ino);
5053 tswap64s((uint64_t *)&de->d_off);
aurel326556a832008-10-13 21:08:17 +00005054 de = (struct linux_dirent64 *)((char *)de + reclen);
bellarddab2ed92003-03-22 15:23:14 +00005055 len -= reclen;
5056 }
5057 }
pbrook53a59602006-03-25 19:31:22 +00005058 unlock_user(dirp, arg2, ret);
bellarddab2ed92003-03-22 15:23:14 +00005059 }
5060 break;
bellarda541f292004-04-12 20:39:29 +00005061#endif /* TARGET_NR_getdents64 */
thse5febef2007-04-01 18:31:35 +00005062#ifdef TARGET_NR__newselect
bellard31e31b82003-02-18 22:55:36 +00005063 case TARGET_NR__newselect:
pbrook53a59602006-03-25 19:31:22 +00005064 ret = do_select(arg1, arg2, arg3, arg4, arg5);
bellard31e31b82003-02-18 22:55:36 +00005065 break;
thse5febef2007-04-01 18:31:35 +00005066#endif
5067#ifdef TARGET_NR_poll
bellard9de5e442003-03-23 16:49:39 +00005068 case TARGET_NR_poll:
5069 {
pbrook53a59602006-03-25 19:31:22 +00005070 struct target_pollfd *target_pfd;
bellard9de5e442003-03-23 16:49:39 +00005071 unsigned int nfds = arg2;
5072 int timeout = arg3;
5073 struct pollfd *pfd;
bellard7854b052003-03-29 17:22:23 +00005074 unsigned int i;
bellard9de5e442003-03-23 16:49:39 +00005075
bellard579a97f2007-11-11 14:26:47 +00005076 target_pfd = lock_user(VERIFY_WRITE, arg1, sizeof(struct target_pollfd) * nfds, 1);
5077 if (!target_pfd)
5078 goto efault;
bellard9de5e442003-03-23 16:49:39 +00005079 pfd = alloca(sizeof(struct pollfd) * nfds);
5080 for(i = 0; i < nfds; i++) {
bellard5cd43932003-03-29 16:54:36 +00005081 pfd[i].fd = tswap32(target_pfd[i].fd);
5082 pfd[i].events = tswap16(target_pfd[i].events);
bellard9de5e442003-03-23 16:49:39 +00005083 }
5084 ret = get_errno(poll(pfd, nfds, timeout));
5085 if (!is_error(ret)) {
5086 for(i = 0; i < nfds; i++) {
bellard5cd43932003-03-29 16:54:36 +00005087 target_pfd[i].revents = tswap16(pfd[i].revents);
bellard9de5e442003-03-23 16:49:39 +00005088 }
pbrook53a59602006-03-25 19:31:22 +00005089 ret += nfds * (sizeof(struct target_pollfd)
5090 - sizeof(struct pollfd));
bellard9de5e442003-03-23 16:49:39 +00005091 }
pbrook53a59602006-03-25 19:31:22 +00005092 unlock_user(target_pfd, arg1, ret);
bellard9de5e442003-03-23 16:49:39 +00005093 }
5094 break;
thse5febef2007-04-01 18:31:35 +00005095#endif
bellard31e31b82003-02-18 22:55:36 +00005096 case TARGET_NR_flock:
bellard9de5e442003-03-23 16:49:39 +00005097 /* NOTE: the flock constant seems to be the same for every
5098 Linux platform */
5099 ret = get_errno(flock(arg1, arg2));
bellard31e31b82003-02-18 22:55:36 +00005100 break;
5101 case TARGET_NR_readv:
5102 {
5103 int count = arg3;
bellard31e31b82003-02-18 22:55:36 +00005104 struct iovec *vec;
bellard31e31b82003-02-18 22:55:36 +00005105
5106 vec = alloca(count * sizeof(struct iovec));
bellard41df8412008-02-04 22:26:57 +00005107 if (lock_iovec(VERIFY_WRITE, vec, arg2, count, 0) < 0)
5108 goto efault;
bellard31e31b82003-02-18 22:55:36 +00005109 ret = get_errno(readv(arg1, vec, count));
pbrook53a59602006-03-25 19:31:22 +00005110 unlock_iovec(vec, arg2, count, 1);
bellard31e31b82003-02-18 22:55:36 +00005111 }
5112 break;
5113 case TARGET_NR_writev:
5114 {
5115 int count = arg3;
bellard31e31b82003-02-18 22:55:36 +00005116 struct iovec *vec;
bellard31e31b82003-02-18 22:55:36 +00005117
5118 vec = alloca(count * sizeof(struct iovec));
bellard41df8412008-02-04 22:26:57 +00005119 if (lock_iovec(VERIFY_READ, vec, arg2, count, 1) < 0)
5120 goto efault;
bellard31e31b82003-02-18 22:55:36 +00005121 ret = get_errno(writev(arg1, vec, count));
pbrook53a59602006-03-25 19:31:22 +00005122 unlock_iovec(vec, arg2, count, 0);
bellard31e31b82003-02-18 22:55:36 +00005123 }
5124 break;
5125 case TARGET_NR_getsid:
5126 ret = get_errno(getsid(arg1));
5127 break;
j_mayer7a3148a2007-04-05 07:13:51 +00005128#if defined(TARGET_NR_fdatasync) /* Not on alpha (osf_datasync ?) */
bellard31e31b82003-02-18 22:55:36 +00005129 case TARGET_NR_fdatasync:
bellard5cd43932003-03-29 16:54:36 +00005130 ret = get_errno(fdatasync(arg1));
5131 break;
j_mayer7a3148a2007-04-05 07:13:51 +00005132#endif
bellard31e31b82003-02-18 22:55:36 +00005133 case TARGET_NR__sysctl:
ths0da46a62007-10-20 20:23:07 +00005134 /* We don't implement this, but ENOTDIR is always a safe
bellard29e619b2004-09-13 21:41:04 +00005135 return value. */
ths0da46a62007-10-20 20:23:07 +00005136 ret = -TARGET_ENOTDIR;
5137 break;
bellard31e31b82003-02-18 22:55:36 +00005138 case TARGET_NR_sched_setparam:
bellard5cd43932003-03-29 16:54:36 +00005139 {
pbrook53a59602006-03-25 19:31:22 +00005140 struct sched_param *target_schp;
bellard5cd43932003-03-29 16:54:36 +00005141 struct sched_param schp;
pbrook53a59602006-03-25 19:31:22 +00005142
bellard579a97f2007-11-11 14:26:47 +00005143 if (!lock_user_struct(VERIFY_READ, target_schp, arg2, 1))
5144 goto efault;
bellard5cd43932003-03-29 16:54:36 +00005145 schp.sched_priority = tswap32(target_schp->sched_priority);
pbrook53a59602006-03-25 19:31:22 +00005146 unlock_user_struct(target_schp, arg2, 0);
bellard5cd43932003-03-29 16:54:36 +00005147 ret = get_errno(sched_setparam(arg1, &schp));
5148 }
5149 break;
bellard31e31b82003-02-18 22:55:36 +00005150 case TARGET_NR_sched_getparam:
bellard5cd43932003-03-29 16:54:36 +00005151 {
pbrook53a59602006-03-25 19:31:22 +00005152 struct sched_param *target_schp;
bellard5cd43932003-03-29 16:54:36 +00005153 struct sched_param schp;
5154 ret = get_errno(sched_getparam(arg1, &schp));
5155 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00005156 if (!lock_user_struct(VERIFY_WRITE, target_schp, arg2, 0))
5157 goto efault;
bellard5cd43932003-03-29 16:54:36 +00005158 target_schp->sched_priority = tswap32(schp.sched_priority);
pbrook53a59602006-03-25 19:31:22 +00005159 unlock_user_struct(target_schp, arg2, 1);
bellard5cd43932003-03-29 16:54:36 +00005160 }
5161 }
5162 break;
bellard31e31b82003-02-18 22:55:36 +00005163 case TARGET_NR_sched_setscheduler:
bellard5cd43932003-03-29 16:54:36 +00005164 {
pbrook53a59602006-03-25 19:31:22 +00005165 struct sched_param *target_schp;
bellard5cd43932003-03-29 16:54:36 +00005166 struct sched_param schp;
bellard579a97f2007-11-11 14:26:47 +00005167 if (!lock_user_struct(VERIFY_READ, target_schp, arg3, 1))
5168 goto efault;
bellard5cd43932003-03-29 16:54:36 +00005169 schp.sched_priority = tswap32(target_schp->sched_priority);
pbrook53a59602006-03-25 19:31:22 +00005170 unlock_user_struct(target_schp, arg3, 0);
bellard5cd43932003-03-29 16:54:36 +00005171 ret = get_errno(sched_setscheduler(arg1, arg2, &schp));
5172 }
5173 break;
bellard31e31b82003-02-18 22:55:36 +00005174 case TARGET_NR_sched_getscheduler:
bellard5cd43932003-03-29 16:54:36 +00005175 ret = get_errno(sched_getscheduler(arg1));
5176 break;
bellard31e31b82003-02-18 22:55:36 +00005177 case TARGET_NR_sched_yield:
5178 ret = get_errno(sched_yield());
5179 break;
5180 case TARGET_NR_sched_get_priority_max:
bellard5cd43932003-03-29 16:54:36 +00005181 ret = get_errno(sched_get_priority_max(arg1));
5182 break;
bellard31e31b82003-02-18 22:55:36 +00005183 case TARGET_NR_sched_get_priority_min:
bellard5cd43932003-03-29 16:54:36 +00005184 ret = get_errno(sched_get_priority_min(arg1));
5185 break;
bellard31e31b82003-02-18 22:55:36 +00005186 case TARGET_NR_sched_rr_get_interval:
bellard5cd43932003-03-29 16:54:36 +00005187 {
bellard5cd43932003-03-29 16:54:36 +00005188 struct timespec ts;
5189 ret = get_errno(sched_rr_get_interval(arg1, &ts));
5190 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00005191 host_to_target_timespec(arg2, &ts);
bellard5cd43932003-03-29 16:54:36 +00005192 }
5193 }
5194 break;
bellard31e31b82003-02-18 22:55:36 +00005195 case TARGET_NR_nanosleep:
bellard1b6b0292003-03-22 17:31:38 +00005196 {
bellard1b6b0292003-03-22 17:31:38 +00005197 struct timespec req, rem;
pbrook53a59602006-03-25 19:31:22 +00005198 target_to_host_timespec(&req, arg1);
bellard1b6b0292003-03-22 17:31:38 +00005199 ret = get_errno(nanosleep(&req, &rem));
pbrook53a59602006-03-25 19:31:22 +00005200 if (is_error(ret) && arg2) {
5201 host_to_target_timespec(arg2, &rem);
bellard1b6b0292003-03-22 17:31:38 +00005202 }
5203 }
5204 break;
thse5febef2007-04-01 18:31:35 +00005205#ifdef TARGET_NR_query_module
bellard31e31b82003-02-18 22:55:36 +00005206 case TARGET_NR_query_module:
bellard5cd43932003-03-29 16:54:36 +00005207 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00005208#endif
5209#ifdef TARGET_NR_nfsservctl
bellard31e31b82003-02-18 22:55:36 +00005210 case TARGET_NR_nfsservctl:
bellard5cd43932003-03-29 16:54:36 +00005211 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00005212#endif
bellard31e31b82003-02-18 22:55:36 +00005213 case TARGET_NR_prctl:
thse5574482007-02-11 20:03:13 +00005214 switch (arg1)
5215 {
5216 case PR_GET_PDEATHSIG:
5217 {
5218 int deathsig;
5219 ret = get_errno(prctl(arg1, &deathsig, arg3, arg4, arg5));
bellard2f619692007-11-16 10:46:05 +00005220 if (!is_error(ret) && arg2
5221 && put_user_ual(deathsig, arg2))
5222 goto efault;
thse5574482007-02-11 20:03:13 +00005223 }
5224 break;
5225 default:
5226 ret = get_errno(prctl(arg1, arg2, arg3, arg4, arg5));
5227 break;
5228 }
ths39b9aae2007-02-11 18:36:44 +00005229 break;
bellardd2fd1af2007-11-14 18:08:56 +00005230#ifdef TARGET_NR_arch_prctl
5231 case TARGET_NR_arch_prctl:
5232#if defined(TARGET_I386) && !defined(TARGET_ABI32)
5233 ret = do_arch_prctl(cpu_env, arg1, arg2);
5234 break;
5235#else
5236 goto unimplemented;
5237#endif
5238#endif
bellard67867302003-11-23 17:05:30 +00005239#ifdef TARGET_NR_pread
bellard31e31b82003-02-18 22:55:36 +00005240 case TARGET_NR_pread:
balroga4ae00b2008-09-20 03:14:14 +00005241#ifdef TARGET_ARM
5242 if (((CPUARMState *)cpu_env)->eabi)
5243 arg4 = arg5;
5244#endif
bellard579a97f2007-11-11 14:26:47 +00005245 if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
5246 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005247 ret = get_errno(pread(arg1, p, arg3, arg4));
5248 unlock_user(p, arg2, ret);
bellard206f0fa2003-05-14 19:01:56 +00005249 break;
bellard31e31b82003-02-18 22:55:36 +00005250 case TARGET_NR_pwrite:
balroga4ae00b2008-09-20 03:14:14 +00005251#ifdef TARGET_ARM
5252 if (((CPUARMState *)cpu_env)->eabi)
5253 arg4 = arg5;
5254#endif
bellard579a97f2007-11-11 14:26:47 +00005255 if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
5256 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005257 ret = get_errno(pwrite(arg1, p, arg3, arg4));
5258 unlock_user(p, arg2, 0);
bellard206f0fa2003-05-14 19:01:56 +00005259 break;
bellard67867302003-11-23 17:05:30 +00005260#endif
aurel32f2c7ba12008-03-28 22:32:06 +00005261#ifdef TARGET_NR_pread64
5262 case TARGET_NR_pread64:
5263 if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
5264 goto efault;
5265 ret = get_errno(pread64(arg1, p, arg3, target_offset64(arg4, arg5)));
5266 unlock_user(p, arg2, ret);
5267 break;
5268 case TARGET_NR_pwrite64:
5269 if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
5270 goto efault;
5271 ret = get_errno(pwrite64(arg1, p, arg3, target_offset64(arg4, arg5)));
5272 unlock_user(p, arg2, 0);
5273 break;
5274#endif
bellard31e31b82003-02-18 22:55:36 +00005275 case TARGET_NR_getcwd:
bellard579a97f2007-11-11 14:26:47 +00005276 if (!(p = lock_user(VERIFY_WRITE, arg1, arg2, 0)))
5277 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005278 ret = get_errno(sys_getcwd1(p, arg2));
5279 unlock_user(p, arg1, ret);
bellard31e31b82003-02-18 22:55:36 +00005280 break;
5281 case TARGET_NR_capget:
bellard5cd43932003-03-29 16:54:36 +00005282 goto unimplemented;
bellard31e31b82003-02-18 22:55:36 +00005283 case TARGET_NR_capset:
bellard5cd43932003-03-29 16:54:36 +00005284 goto unimplemented;
bellard31e31b82003-02-18 22:55:36 +00005285 case TARGET_NR_sigaltstack:
ths198a74d2007-09-27 16:44:32 +00005286#if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_MIPS) || \
5287 defined(TARGET_SPARC) || defined(TARGET_PPC) || defined(TARGET_ALPHA)
bellard579a97f2007-11-11 14:26:47 +00005288 ret = do_sigaltstack(arg1, arg2, get_sp_from_cpustate((CPUState *)cpu_env));
thsa04e1342007-09-27 13:57:58 +00005289 break;
5290#else
bellard5cd43932003-03-29 16:54:36 +00005291 goto unimplemented;
thsa04e1342007-09-27 13:57:58 +00005292#endif
bellard31e31b82003-02-18 22:55:36 +00005293 case TARGET_NR_sendfile:
bellard5cd43932003-03-29 16:54:36 +00005294 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00005295#ifdef TARGET_NR_getpmsg
bellard31e31b82003-02-18 22:55:36 +00005296 case TARGET_NR_getpmsg:
bellard5cd43932003-03-29 16:54:36 +00005297 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00005298#endif
5299#ifdef TARGET_NR_putpmsg
bellard31e31b82003-02-18 22:55:36 +00005300 case TARGET_NR_putpmsg:
bellard5cd43932003-03-29 16:54:36 +00005301 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00005302#endif
bellard048f6b42005-11-26 18:47:20 +00005303#ifdef TARGET_NR_vfork
bellard31e31b82003-02-18 22:55:36 +00005304 case TARGET_NR_vfork:
pbrookd865bab2008-06-07 22:12:17 +00005305 ret = get_errno(do_fork(cpu_env, CLONE_VFORK | CLONE_VM | SIGCHLD,
5306 0, 0, 0, 0));
bellard31e31b82003-02-18 22:55:36 +00005307 break;
bellard048f6b42005-11-26 18:47:20 +00005308#endif
bellardebc05482003-09-30 21:08:41 +00005309#ifdef TARGET_NR_ugetrlimit
bellard31e31b82003-02-18 22:55:36 +00005310 case TARGET_NR_ugetrlimit:
bellard728584b2003-04-29 20:43:36 +00005311 {
5312 struct rlimit rlim;
5313 ret = get_errno(getrlimit(arg1, &rlim));
5314 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00005315 struct target_rlimit *target_rlim;
bellard579a97f2007-11-11 14:26:47 +00005316 if (!lock_user_struct(VERIFY_WRITE, target_rlim, arg2, 0))
5317 goto efault;
bellard728584b2003-04-29 20:43:36 +00005318 target_rlim->rlim_cur = tswapl(rlim.rlim_cur);
5319 target_rlim->rlim_max = tswapl(rlim.rlim_max);
pbrook53a59602006-03-25 19:31:22 +00005320 unlock_user_struct(target_rlim, arg2, 1);
bellard728584b2003-04-29 20:43:36 +00005321 }
5322 break;
5323 }
bellardebc05482003-09-30 21:08:41 +00005324#endif
bellarda315a142005-01-30 22:59:18 +00005325#ifdef TARGET_NR_truncate64
bellard31e31b82003-02-18 22:55:36 +00005326 case TARGET_NR_truncate64:
bellard579a97f2007-11-11 14:26:47 +00005327 if (!(p = lock_user_string(arg1)))
5328 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005329 ret = target_truncate64(cpu_env, p, arg2, arg3, arg4);
5330 unlock_user(p, arg1, 0);
bellard667f38b2005-07-23 14:46:27 +00005331 break;
bellarda315a142005-01-30 22:59:18 +00005332#endif
5333#ifdef TARGET_NR_ftruncate64
bellard31e31b82003-02-18 22:55:36 +00005334 case TARGET_NR_ftruncate64:
pbrookce4defa2006-02-09 16:49:55 +00005335 ret = target_ftruncate64(cpu_env, arg1, arg2, arg3, arg4);
bellard667f38b2005-07-23 14:46:27 +00005336 break;
bellarda315a142005-01-30 22:59:18 +00005337#endif
5338#ifdef TARGET_NR_stat64
bellard31e31b82003-02-18 22:55:36 +00005339 case TARGET_NR_stat64:
bellard579a97f2007-11-11 14:26:47 +00005340 if (!(p = lock_user_string(arg1)))
5341 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005342 ret = get_errno(stat(path(p), &st));
5343 unlock_user(p, arg1, 0);
balrog6a24a772008-09-20 02:23:36 +00005344 if (!is_error(ret))
5345 ret = host_to_target_stat64(cpu_env, arg2, &st);
5346 break;
bellarda315a142005-01-30 22:59:18 +00005347#endif
5348#ifdef TARGET_NR_lstat64
bellard31e31b82003-02-18 22:55:36 +00005349 case TARGET_NR_lstat64:
bellard579a97f2007-11-11 14:26:47 +00005350 if (!(p = lock_user_string(arg1)))
5351 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005352 ret = get_errno(lstat(path(p), &st));
5353 unlock_user(p, arg1, 0);
balrog6a24a772008-09-20 02:23:36 +00005354 if (!is_error(ret))
5355 ret = host_to_target_stat64(cpu_env, arg2, &st);
5356 break;
bellarda315a142005-01-30 22:59:18 +00005357#endif
5358#ifdef TARGET_NR_fstat64
bellard31e31b82003-02-18 22:55:36 +00005359 case TARGET_NR_fstat64:
balrog6a24a772008-09-20 02:23:36 +00005360 ret = get_errno(fstat(arg1, &st));
5361 if (!is_error(ret))
5362 ret = host_to_target_stat64(cpu_env, arg2, &st);
5363 break;
bellardec86b0f2003-04-11 00:15:04 +00005364#endif
balrog6a24a772008-09-20 02:23:36 +00005365#if defined(TARGET_NR_fstatat64) && defined(__NR_fstatat64)
5366 case TARGET_NR_fstatat64:
5367 if (!(p = lock_user_string(arg2)))
5368 goto efault;
5369 ret = get_errno(sys_fstatat64(arg1, path(p), &st, arg4));
5370 if (!is_error(ret))
5371 ret = host_to_target_stat64(cpu_env, arg3, &st);
bellard60cd49d2003-03-16 22:53:56 +00005372 break;
bellarda315a142005-01-30 22:59:18 +00005373#endif
bellard67867302003-11-23 17:05:30 +00005374#ifdef USE_UID16
5375 case TARGET_NR_lchown:
bellard579a97f2007-11-11 14:26:47 +00005376 if (!(p = lock_user_string(arg1)))
5377 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005378 ret = get_errno(lchown(p, low2highuid(arg2), low2highgid(arg3)));
5379 unlock_user(p, arg1, 0);
bellard67867302003-11-23 17:05:30 +00005380 break;
5381 case TARGET_NR_getuid:
5382 ret = get_errno(high2lowuid(getuid()));
5383 break;
5384 case TARGET_NR_getgid:
5385 ret = get_errno(high2lowgid(getgid()));
5386 break;
5387 case TARGET_NR_geteuid:
5388 ret = get_errno(high2lowuid(geteuid()));
5389 break;
5390 case TARGET_NR_getegid:
5391 ret = get_errno(high2lowgid(getegid()));
5392 break;
5393 case TARGET_NR_setreuid:
5394 ret = get_errno(setreuid(low2highuid(arg1), low2highuid(arg2)));
5395 break;
5396 case TARGET_NR_setregid:
5397 ret = get_errno(setregid(low2highgid(arg1), low2highgid(arg2)));
5398 break;
5399 case TARGET_NR_getgroups:
5400 {
5401 int gidsetsize = arg1;
pbrook53a59602006-03-25 19:31:22 +00005402 uint16_t *target_grouplist;
bellard67867302003-11-23 17:05:30 +00005403 gid_t *grouplist;
5404 int i;
5405
5406 grouplist = alloca(gidsetsize * sizeof(gid_t));
5407 ret = get_errno(getgroups(gidsetsize, grouplist));
balrogcb3bc232008-09-20 02:08:13 +00005408 if (gidsetsize == 0)
5409 break;
bellard67867302003-11-23 17:05:30 +00005410 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00005411 target_grouplist = lock_user(VERIFY_WRITE, arg2, gidsetsize * 2, 0);
5412 if (!target_grouplist)
5413 goto efault;
balroga2155fc2008-09-20 02:12:08 +00005414 for(i = 0;i < ret; i++)
bellard67867302003-11-23 17:05:30 +00005415 target_grouplist[i] = tswap16(grouplist[i]);
pbrook53a59602006-03-25 19:31:22 +00005416 unlock_user(target_grouplist, arg2, gidsetsize * 2);
bellard67867302003-11-23 17:05:30 +00005417 }
5418 }
5419 break;
5420 case TARGET_NR_setgroups:
5421 {
5422 int gidsetsize = arg1;
pbrook53a59602006-03-25 19:31:22 +00005423 uint16_t *target_grouplist;
bellard67867302003-11-23 17:05:30 +00005424 gid_t *grouplist;
5425 int i;
5426
5427 grouplist = alloca(gidsetsize * sizeof(gid_t));
bellard579a97f2007-11-11 14:26:47 +00005428 target_grouplist = lock_user(VERIFY_READ, arg2, gidsetsize * 2, 1);
5429 if (!target_grouplist) {
5430 ret = -TARGET_EFAULT;
5431 goto fail;
5432 }
bellard67867302003-11-23 17:05:30 +00005433 for(i = 0;i < gidsetsize; i++)
5434 grouplist[i] = tswap16(target_grouplist[i]);
pbrook53a59602006-03-25 19:31:22 +00005435 unlock_user(target_grouplist, arg2, 0);
bellard67867302003-11-23 17:05:30 +00005436 ret = get_errno(setgroups(gidsetsize, grouplist));
5437 }
5438 break;
5439 case TARGET_NR_fchown:
5440 ret = get_errno(fchown(arg1, low2highuid(arg2), low2highgid(arg3)));
5441 break;
thsccfa72b2007-09-24 09:23:34 +00005442#if defined(TARGET_NR_fchownat) && defined(__NR_fchownat)
5443 case TARGET_NR_fchownat:
bellard579a97f2007-11-11 14:26:47 +00005444 if (!(p = lock_user_string(arg2)))
5445 goto efault;
5446 ret = get_errno(sys_fchownat(arg1, p, low2highuid(arg3), low2highgid(arg4), arg5));
5447 unlock_user(p, arg2, 0);
thsccfa72b2007-09-24 09:23:34 +00005448 break;
5449#endif
bellard67867302003-11-23 17:05:30 +00005450#ifdef TARGET_NR_setresuid
5451 case TARGET_NR_setresuid:
ths5fafdf22007-09-16 21:08:06 +00005452 ret = get_errno(setresuid(low2highuid(arg1),
5453 low2highuid(arg2),
bellard67867302003-11-23 17:05:30 +00005454 low2highuid(arg3)));
5455 break;
5456#endif
5457#ifdef TARGET_NR_getresuid
5458 case TARGET_NR_getresuid:
5459 {
pbrook53a59602006-03-25 19:31:22 +00005460 uid_t ruid, euid, suid;
bellard67867302003-11-23 17:05:30 +00005461 ret = get_errno(getresuid(&ruid, &euid, &suid));
5462 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +00005463 if (put_user_u16(high2lowuid(ruid), arg1)
5464 || put_user_u16(high2lowuid(euid), arg2)
5465 || put_user_u16(high2lowuid(suid), arg3))
5466 goto efault;
bellard67867302003-11-23 17:05:30 +00005467 }
5468 }
5469 break;
5470#endif
5471#ifdef TARGET_NR_getresgid
5472 case TARGET_NR_setresgid:
ths5fafdf22007-09-16 21:08:06 +00005473 ret = get_errno(setresgid(low2highgid(arg1),
5474 low2highgid(arg2),
bellard67867302003-11-23 17:05:30 +00005475 low2highgid(arg3)));
5476 break;
5477#endif
5478#ifdef TARGET_NR_getresgid
5479 case TARGET_NR_getresgid:
5480 {
pbrook53a59602006-03-25 19:31:22 +00005481 gid_t rgid, egid, sgid;
bellard67867302003-11-23 17:05:30 +00005482 ret = get_errno(getresgid(&rgid, &egid, &sgid));
5483 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +00005484 if (put_user_u16(high2lowgid(rgid), arg1)
5485 || put_user_u16(high2lowgid(egid), arg2)
5486 || put_user_u16(high2lowgid(sgid), arg3))
5487 goto efault;
bellard67867302003-11-23 17:05:30 +00005488 }
5489 }
5490 break;
5491#endif
5492 case TARGET_NR_chown:
bellard579a97f2007-11-11 14:26:47 +00005493 if (!(p = lock_user_string(arg1)))
5494 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005495 ret = get_errno(chown(p, low2highuid(arg2), low2highgid(arg3)));
5496 unlock_user(p, arg1, 0);
bellard67867302003-11-23 17:05:30 +00005497 break;
5498 case TARGET_NR_setuid:
5499 ret = get_errno(setuid(low2highuid(arg1)));
5500 break;
5501 case TARGET_NR_setgid:
5502 ret = get_errno(setgid(low2highgid(arg1)));
5503 break;
5504 case TARGET_NR_setfsuid:
5505 ret = get_errno(setfsuid(arg1));
5506 break;
5507 case TARGET_NR_setfsgid:
5508 ret = get_errno(setfsgid(arg1));
5509 break;
5510#endif /* USE_UID16 */
5511
bellarda315a142005-01-30 22:59:18 +00005512#ifdef TARGET_NR_lchown32
bellard31e31b82003-02-18 22:55:36 +00005513 case TARGET_NR_lchown32:
bellard579a97f2007-11-11 14:26:47 +00005514 if (!(p = lock_user_string(arg1)))
5515 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005516 ret = get_errno(lchown(p, arg2, arg3));
5517 unlock_user(p, arg1, 0);
bellardb03c60f2003-03-23 17:19:56 +00005518 break;
bellarda315a142005-01-30 22:59:18 +00005519#endif
5520#ifdef TARGET_NR_getuid32
bellard31e31b82003-02-18 22:55:36 +00005521 case TARGET_NR_getuid32:
bellardb03c60f2003-03-23 17:19:56 +00005522 ret = get_errno(getuid());
5523 break;
bellarda315a142005-01-30 22:59:18 +00005524#endif
5525#ifdef TARGET_NR_getgid32
bellard31e31b82003-02-18 22:55:36 +00005526 case TARGET_NR_getgid32:
bellardb03c60f2003-03-23 17:19:56 +00005527 ret = get_errno(getgid());
5528 break;
bellarda315a142005-01-30 22:59:18 +00005529#endif
5530#ifdef TARGET_NR_geteuid32
bellard31e31b82003-02-18 22:55:36 +00005531 case TARGET_NR_geteuid32:
bellardb03c60f2003-03-23 17:19:56 +00005532 ret = get_errno(geteuid());
5533 break;
bellarda315a142005-01-30 22:59:18 +00005534#endif
5535#ifdef TARGET_NR_getegid32
bellard31e31b82003-02-18 22:55:36 +00005536 case TARGET_NR_getegid32:
bellardb03c60f2003-03-23 17:19:56 +00005537 ret = get_errno(getegid());
5538 break;
bellarda315a142005-01-30 22:59:18 +00005539#endif
5540#ifdef TARGET_NR_setreuid32
bellard31e31b82003-02-18 22:55:36 +00005541 case TARGET_NR_setreuid32:
bellardb03c60f2003-03-23 17:19:56 +00005542 ret = get_errno(setreuid(arg1, arg2));
5543 break;
bellarda315a142005-01-30 22:59:18 +00005544#endif
5545#ifdef TARGET_NR_setregid32
bellard31e31b82003-02-18 22:55:36 +00005546 case TARGET_NR_setregid32:
bellardb03c60f2003-03-23 17:19:56 +00005547 ret = get_errno(setregid(arg1, arg2));
5548 break;
bellarda315a142005-01-30 22:59:18 +00005549#endif
5550#ifdef TARGET_NR_getgroups32
bellard31e31b82003-02-18 22:55:36 +00005551 case TARGET_NR_getgroups32:
bellard99c475a2005-01-31 20:45:13 +00005552 {
5553 int gidsetsize = arg1;
pbrook53a59602006-03-25 19:31:22 +00005554 uint32_t *target_grouplist;
bellard99c475a2005-01-31 20:45:13 +00005555 gid_t *grouplist;
5556 int i;
5557
5558 grouplist = alloca(gidsetsize * sizeof(gid_t));
5559 ret = get_errno(getgroups(gidsetsize, grouplist));
balrogcb3bc232008-09-20 02:08:13 +00005560 if (gidsetsize == 0)
5561 break;
bellard99c475a2005-01-31 20:45:13 +00005562 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00005563 target_grouplist = lock_user(VERIFY_WRITE, arg2, gidsetsize * 4, 0);
5564 if (!target_grouplist) {
5565 ret = -TARGET_EFAULT;
5566 goto fail;
5567 }
balroga2155fc2008-09-20 02:12:08 +00005568 for(i = 0;i < ret; i++)
pbrook53a59602006-03-25 19:31:22 +00005569 target_grouplist[i] = tswap32(grouplist[i]);
5570 unlock_user(target_grouplist, arg2, gidsetsize * 4);
bellard99c475a2005-01-31 20:45:13 +00005571 }
5572 }
5573 break;
bellarda315a142005-01-30 22:59:18 +00005574#endif
5575#ifdef TARGET_NR_setgroups32
bellard31e31b82003-02-18 22:55:36 +00005576 case TARGET_NR_setgroups32:
bellard99c475a2005-01-31 20:45:13 +00005577 {
5578 int gidsetsize = arg1;
pbrook53a59602006-03-25 19:31:22 +00005579 uint32_t *target_grouplist;
bellard99c475a2005-01-31 20:45:13 +00005580 gid_t *grouplist;
5581 int i;
ths3b46e622007-09-17 08:09:54 +00005582
bellard99c475a2005-01-31 20:45:13 +00005583 grouplist = alloca(gidsetsize * sizeof(gid_t));
bellard579a97f2007-11-11 14:26:47 +00005584 target_grouplist = lock_user(VERIFY_READ, arg2, gidsetsize * 4, 1);
5585 if (!target_grouplist) {
5586 ret = -TARGET_EFAULT;
5587 goto fail;
5588 }
bellard99c475a2005-01-31 20:45:13 +00005589 for(i = 0;i < gidsetsize; i++)
pbrook53a59602006-03-25 19:31:22 +00005590 grouplist[i] = tswap32(target_grouplist[i]);
5591 unlock_user(target_grouplist, arg2, 0);
bellard99c475a2005-01-31 20:45:13 +00005592 ret = get_errno(setgroups(gidsetsize, grouplist));
5593 }
5594 break;
bellarda315a142005-01-30 22:59:18 +00005595#endif
5596#ifdef TARGET_NR_fchown32
bellard31e31b82003-02-18 22:55:36 +00005597 case TARGET_NR_fchown32:
bellardb03c60f2003-03-23 17:19:56 +00005598 ret = get_errno(fchown(arg1, arg2, arg3));
5599 break;
bellarda315a142005-01-30 22:59:18 +00005600#endif
5601#ifdef TARGET_NR_setresuid32
bellard31e31b82003-02-18 22:55:36 +00005602 case TARGET_NR_setresuid32:
bellardb03c60f2003-03-23 17:19:56 +00005603 ret = get_errno(setresuid(arg1, arg2, arg3));
5604 break;
bellarda315a142005-01-30 22:59:18 +00005605#endif
5606#ifdef TARGET_NR_getresuid32
bellard31e31b82003-02-18 22:55:36 +00005607 case TARGET_NR_getresuid32:
bellardb03c60f2003-03-23 17:19:56 +00005608 {
pbrook53a59602006-03-25 19:31:22 +00005609 uid_t ruid, euid, suid;
bellardb03c60f2003-03-23 17:19:56 +00005610 ret = get_errno(getresuid(&ruid, &euid, &suid));
5611 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +00005612 if (put_user_u32(ruid, arg1)
5613 || put_user_u32(euid, arg2)
5614 || put_user_u32(suid, arg3))
5615 goto efault;
bellardb03c60f2003-03-23 17:19:56 +00005616 }
5617 }
5618 break;
bellarda315a142005-01-30 22:59:18 +00005619#endif
5620#ifdef TARGET_NR_setresgid32
bellard31e31b82003-02-18 22:55:36 +00005621 case TARGET_NR_setresgid32:
bellardb03c60f2003-03-23 17:19:56 +00005622 ret = get_errno(setresgid(arg1, arg2, arg3));
5623 break;
bellarda315a142005-01-30 22:59:18 +00005624#endif
5625#ifdef TARGET_NR_getresgid32
bellard31e31b82003-02-18 22:55:36 +00005626 case TARGET_NR_getresgid32:
bellardb03c60f2003-03-23 17:19:56 +00005627 {
pbrook53a59602006-03-25 19:31:22 +00005628 gid_t rgid, egid, sgid;
bellardb03c60f2003-03-23 17:19:56 +00005629 ret = get_errno(getresgid(&rgid, &egid, &sgid));
5630 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +00005631 if (put_user_u32(rgid, arg1)
5632 || put_user_u32(egid, arg2)
5633 || put_user_u32(sgid, arg3))
5634 goto efault;
bellardb03c60f2003-03-23 17:19:56 +00005635 }
5636 }
5637 break;
bellarda315a142005-01-30 22:59:18 +00005638#endif
5639#ifdef TARGET_NR_chown32
bellard31e31b82003-02-18 22:55:36 +00005640 case TARGET_NR_chown32:
bellard579a97f2007-11-11 14:26:47 +00005641 if (!(p = lock_user_string(arg1)))
5642 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005643 ret = get_errno(chown(p, arg2, arg3));
5644 unlock_user(p, arg1, 0);
bellardb03c60f2003-03-23 17:19:56 +00005645 break;
bellarda315a142005-01-30 22:59:18 +00005646#endif
5647#ifdef TARGET_NR_setuid32
bellard31e31b82003-02-18 22:55:36 +00005648 case TARGET_NR_setuid32:
bellardb03c60f2003-03-23 17:19:56 +00005649 ret = get_errno(setuid(arg1));
5650 break;
bellarda315a142005-01-30 22:59:18 +00005651#endif
5652#ifdef TARGET_NR_setgid32
bellard31e31b82003-02-18 22:55:36 +00005653 case TARGET_NR_setgid32:
bellardb03c60f2003-03-23 17:19:56 +00005654 ret = get_errno(setgid(arg1));
5655 break;
bellarda315a142005-01-30 22:59:18 +00005656#endif
5657#ifdef TARGET_NR_setfsuid32
bellard31e31b82003-02-18 22:55:36 +00005658 case TARGET_NR_setfsuid32:
bellardb03c60f2003-03-23 17:19:56 +00005659 ret = get_errno(setfsuid(arg1));
5660 break;
bellarda315a142005-01-30 22:59:18 +00005661#endif
5662#ifdef TARGET_NR_setfsgid32
bellard31e31b82003-02-18 22:55:36 +00005663 case TARGET_NR_setfsgid32:
bellardb03c60f2003-03-23 17:19:56 +00005664 ret = get_errno(setfsgid(arg1));
5665 break;
bellarda315a142005-01-30 22:59:18 +00005666#endif
bellard67867302003-11-23 17:05:30 +00005667
bellard31e31b82003-02-18 22:55:36 +00005668 case TARGET_NR_pivot_root:
bellardb03c60f2003-03-23 17:19:56 +00005669 goto unimplemented;
bellardffa65c32004-01-04 23:57:22 +00005670#ifdef TARGET_NR_mincore
bellard31e31b82003-02-18 22:55:36 +00005671 case TARGET_NR_mincore:
aurel3204bb9ac2008-10-01 21:46:41 +00005672 {
5673 void *a;
5674 ret = -TARGET_EFAULT;
5675 if (!(a = lock_user(VERIFY_READ, arg1,arg2, 0)))
5676 goto efault;
5677 if (!(p = lock_user_string(arg3)))
5678 goto mincore_fail;
5679 ret = get_errno(mincore(a, arg2, p));
5680 unlock_user(p, arg3, ret);
5681 mincore_fail:
5682 unlock_user(a, arg1, 0);
5683 }
5684 break;
bellardffa65c32004-01-04 23:57:22 +00005685#endif
aurel32408321b2008-10-01 21:46:32 +00005686#ifdef TARGET_NR_arm_fadvise64_64
5687 case TARGET_NR_arm_fadvise64_64:
5688 {
5689 /*
5690 * arm_fadvise64_64 looks like fadvise64_64 but
5691 * with different argument order
5692 */
5693 abi_long temp;
5694 temp = arg3;
5695 arg3 = arg4;
5696 arg4 = temp;
5697 }
5698#endif
5699#if defined(TARGET_NR_fadvise64_64) || defined(TARGET_NR_arm_fadvise64_64)
5700#ifdef TARGET_NR_fadvise64_64
5701 case TARGET_NR_fadvise64_64:
5702#endif
5703 /* This is a hint, so ignoring and returning success is ok. */
5704 ret = get_errno(0);
5705 break;
5706#endif
bellardffa65c32004-01-04 23:57:22 +00005707#ifdef TARGET_NR_madvise
bellard31e31b82003-02-18 22:55:36 +00005708 case TARGET_NR_madvise:
pbrook24836682006-04-16 14:14:53 +00005709 /* A straight passthrough may not be safe because qemu sometimes
5710 turns private flie-backed mappings into anonymous mappings.
5711 This will break MADV_DONTNEED.
5712 This is a hint, so ignoring and returning success is ok. */
5713 ret = get_errno(0);
5714 break;
bellardffa65c32004-01-04 23:57:22 +00005715#endif
blueswir1992f48a2007-10-14 16:27:31 +00005716#if TARGET_ABI_BITS == 32
bellard31e31b82003-02-18 22:55:36 +00005717 case TARGET_NR_fcntl64:
bellard77e46722003-04-29 20:39:06 +00005718 {
thsb1e341e2007-03-20 21:50:52 +00005719 int cmd;
bellard77e46722003-04-29 20:39:06 +00005720 struct flock64 fl;
pbrook53a59602006-03-25 19:31:22 +00005721 struct target_flock64 *target_fl;
pbrookce4defa2006-02-09 16:49:55 +00005722#ifdef TARGET_ARM
pbrook53a59602006-03-25 19:31:22 +00005723 struct target_eabi_flock64 *target_efl;
pbrookce4defa2006-02-09 16:49:55 +00005724#endif
bellard77e46722003-04-29 20:39:06 +00005725
thsb1e341e2007-03-20 21:50:52 +00005726 switch(arg2){
5727 case TARGET_F_GETLK64:
5728 cmd = F_GETLK64;
thsa7222582007-03-22 15:08:55 +00005729 break;
thsb1e341e2007-03-20 21:50:52 +00005730 case TARGET_F_SETLK64:
5731 cmd = F_SETLK64;
thsa7222582007-03-22 15:08:55 +00005732 break;
thsb1e341e2007-03-20 21:50:52 +00005733 case TARGET_F_SETLKW64:
5734 cmd = F_SETLK64;
thsa7222582007-03-22 15:08:55 +00005735 break;
thsb1e341e2007-03-20 21:50:52 +00005736 default:
5737 cmd = arg2;
thsa7222582007-03-22 15:08:55 +00005738 break;
thsb1e341e2007-03-20 21:50:52 +00005739 }
5740
bellard60cd49d2003-03-16 22:53:56 +00005741 switch(arg2) {
thsb1e341e2007-03-20 21:50:52 +00005742 case TARGET_F_GETLK64:
ths58134272007-03-31 18:59:32 +00005743#ifdef TARGET_ARM
5744 if (((CPUARMState *)cpu_env)->eabi) {
bellard9ee1fa22007-11-11 15:11:19 +00005745 if (!lock_user_struct(VERIFY_READ, target_efl, arg3, 1))
5746 goto efault;
ths58134272007-03-31 18:59:32 +00005747 fl.l_type = tswap16(target_efl->l_type);
5748 fl.l_whence = tswap16(target_efl->l_whence);
5749 fl.l_start = tswap64(target_efl->l_start);
5750 fl.l_len = tswap64(target_efl->l_len);
5751 fl.l_pid = tswapl(target_efl->l_pid);
5752 unlock_user_struct(target_efl, arg3, 0);
5753 } else
5754#endif
5755 {
bellard9ee1fa22007-11-11 15:11:19 +00005756 if (!lock_user_struct(VERIFY_READ, target_fl, arg3, 1))
5757 goto efault;
ths58134272007-03-31 18:59:32 +00005758 fl.l_type = tswap16(target_fl->l_type);
5759 fl.l_whence = tswap16(target_fl->l_whence);
5760 fl.l_start = tswap64(target_fl->l_start);
5761 fl.l_len = tswap64(target_fl->l_len);
5762 fl.l_pid = tswapl(target_fl->l_pid);
5763 unlock_user_struct(target_fl, arg3, 0);
5764 }
thsb1e341e2007-03-20 21:50:52 +00005765 ret = get_errno(fcntl(arg1, cmd, &fl));
bellard77e46722003-04-29 20:39:06 +00005766 if (ret == 0) {
pbrookce4defa2006-02-09 16:49:55 +00005767#ifdef TARGET_ARM
5768 if (((CPUARMState *)cpu_env)->eabi) {
bellard9ee1fa22007-11-11 15:11:19 +00005769 if (!lock_user_struct(VERIFY_WRITE, target_efl, arg3, 0))
5770 goto efault;
pbrookce4defa2006-02-09 16:49:55 +00005771 target_efl->l_type = tswap16(fl.l_type);
5772 target_efl->l_whence = tswap16(fl.l_whence);
5773 target_efl->l_start = tswap64(fl.l_start);
5774 target_efl->l_len = tswap64(fl.l_len);
5775 target_efl->l_pid = tswapl(fl.l_pid);
pbrook53a59602006-03-25 19:31:22 +00005776 unlock_user_struct(target_efl, arg3, 1);
pbrookce4defa2006-02-09 16:49:55 +00005777 } else
5778#endif
5779 {
bellard9ee1fa22007-11-11 15:11:19 +00005780 if (!lock_user_struct(VERIFY_WRITE, target_fl, arg3, 0))
5781 goto efault;
pbrookce4defa2006-02-09 16:49:55 +00005782 target_fl->l_type = tswap16(fl.l_type);
5783 target_fl->l_whence = tswap16(fl.l_whence);
5784 target_fl->l_start = tswap64(fl.l_start);
5785 target_fl->l_len = tswap64(fl.l_len);
5786 target_fl->l_pid = tswapl(fl.l_pid);
pbrook53a59602006-03-25 19:31:22 +00005787 unlock_user_struct(target_fl, arg3, 1);
pbrookce4defa2006-02-09 16:49:55 +00005788 }
bellard77e46722003-04-29 20:39:06 +00005789 }
5790 break;
5791
thsb1e341e2007-03-20 21:50:52 +00005792 case TARGET_F_SETLK64:
5793 case TARGET_F_SETLKW64:
pbrookce4defa2006-02-09 16:49:55 +00005794#ifdef TARGET_ARM
5795 if (((CPUARMState *)cpu_env)->eabi) {
bellard9ee1fa22007-11-11 15:11:19 +00005796 if (!lock_user_struct(VERIFY_READ, target_efl, arg3, 1))
5797 goto efault;
pbrookce4defa2006-02-09 16:49:55 +00005798 fl.l_type = tswap16(target_efl->l_type);
5799 fl.l_whence = tswap16(target_efl->l_whence);
5800 fl.l_start = tswap64(target_efl->l_start);
5801 fl.l_len = tswap64(target_efl->l_len);
5802 fl.l_pid = tswapl(target_efl->l_pid);
pbrook53a59602006-03-25 19:31:22 +00005803 unlock_user_struct(target_efl, arg3, 0);
pbrookce4defa2006-02-09 16:49:55 +00005804 } else
5805#endif
5806 {
bellard9ee1fa22007-11-11 15:11:19 +00005807 if (!lock_user_struct(VERIFY_READ, target_fl, arg3, 1))
5808 goto efault;
pbrookce4defa2006-02-09 16:49:55 +00005809 fl.l_type = tswap16(target_fl->l_type);
5810 fl.l_whence = tswap16(target_fl->l_whence);
5811 fl.l_start = tswap64(target_fl->l_start);
5812 fl.l_len = tswap64(target_fl->l_len);
5813 fl.l_pid = tswapl(target_fl->l_pid);
pbrook53a59602006-03-25 19:31:22 +00005814 unlock_user_struct(target_fl, arg3, 0);
pbrookce4defa2006-02-09 16:49:55 +00005815 }
thsb1e341e2007-03-20 21:50:52 +00005816 ret = get_errno(fcntl(arg1, cmd, &fl));
bellard77e46722003-04-29 20:39:06 +00005817 break;
bellard60cd49d2003-03-16 22:53:56 +00005818 default:
bellard9ee1fa22007-11-11 15:11:19 +00005819 ret = do_fcntl(arg1, cmd, arg3);
bellard60cd49d2003-03-16 22:53:56 +00005820 break;
5821 }
bellard77e46722003-04-29 20:39:06 +00005822 break;
5823 }
bellard60cd49d2003-03-16 22:53:56 +00005824#endif
ths7d600c82006-12-08 01:32:58 +00005825#ifdef TARGET_NR_cacheflush
5826 case TARGET_NR_cacheflush:
5827 /* self-modifying code is handled automatically, so nothing needed */
5828 ret = 0;
5829 break;
5830#endif
bellardebc05482003-09-30 21:08:41 +00005831#ifdef TARGET_NR_security
bellard31e31b82003-02-18 22:55:36 +00005832 case TARGET_NR_security:
5833 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00005834#endif
bellardc573ff62004-01-04 15:51:36 +00005835#ifdef TARGET_NR_getpagesize
5836 case TARGET_NR_getpagesize:
5837 ret = TARGET_PAGE_SIZE;
5838 break;
5839#endif
bellard31e31b82003-02-18 22:55:36 +00005840 case TARGET_NR_gettid:
5841 ret = get_errno(gettid());
5842 break;
thse5febef2007-04-01 18:31:35 +00005843#ifdef TARGET_NR_readahead
bellard31e31b82003-02-18 22:55:36 +00005844 case TARGET_NR_readahead:
aurel322054ac92008-10-13 21:08:07 +00005845#if TARGET_ABI_BITS == 32
5846#ifdef TARGET_ARM
5847 if (((CPUARMState *)cpu_env)->eabi)
5848 {
5849 arg2 = arg3;
5850 arg3 = arg4;
5851 arg4 = arg5;
5852 }
5853#endif
5854 ret = get_errno(readahead(arg1, ((off64_t)arg3 << 32) | arg2, arg4));
5855#else
5856 ret = get_errno(readahead(arg1, arg2, arg3));
5857#endif
5858 break;
thse5febef2007-04-01 18:31:35 +00005859#endif
bellardebc05482003-09-30 21:08:41 +00005860#ifdef TARGET_NR_setxattr
bellard31e31b82003-02-18 22:55:36 +00005861 case TARGET_NR_setxattr:
5862 case TARGET_NR_lsetxattr:
5863 case TARGET_NR_fsetxattr:
5864 case TARGET_NR_getxattr:
5865 case TARGET_NR_lgetxattr:
5866 case TARGET_NR_fgetxattr:
5867 case TARGET_NR_listxattr:
5868 case TARGET_NR_llistxattr:
5869 case TARGET_NR_flistxattr:
5870 case TARGET_NR_removexattr:
5871 case TARGET_NR_lremovexattr:
5872 case TARGET_NR_fremovexattr:
bellard5cd43932003-03-29 16:54:36 +00005873 goto unimplemented_nowarn;
bellardebc05482003-09-30 21:08:41 +00005874#endif
5875#ifdef TARGET_NR_set_thread_area
bellard5cd43932003-03-29 16:54:36 +00005876 case TARGET_NR_set_thread_area:
bellard8d18e892007-11-14 15:18:40 +00005877#if defined(TARGET_MIPS)
ths6f5b89a2007-03-02 20:48:00 +00005878 ((CPUMIPSState *) cpu_env)->tls_value = arg1;
5879 ret = 0;
5880 break;
bellard8d18e892007-11-14 15:18:40 +00005881#elif defined(TARGET_I386) && defined(TARGET_ABI32)
5882 ret = do_set_thread_area(cpu_env, arg1);
5883 break;
ths6f5b89a2007-03-02 20:48:00 +00005884#else
5885 goto unimplemented_nowarn;
5886#endif
5887#endif
5888#ifdef TARGET_NR_get_thread_area
bellard5cd43932003-03-29 16:54:36 +00005889 case TARGET_NR_get_thread_area:
bellard8d18e892007-11-14 15:18:40 +00005890#if defined(TARGET_I386) && defined(TARGET_ABI32)
5891 ret = do_get_thread_area(cpu_env, arg1);
5892#else
bellard5cd43932003-03-29 16:54:36 +00005893 goto unimplemented_nowarn;
bellardebc05482003-09-30 21:08:41 +00005894#endif
bellard8d18e892007-11-14 15:18:40 +00005895#endif
bellard48dc41e2006-06-21 18:15:50 +00005896#ifdef TARGET_NR_getdomainname
5897 case TARGET_NR_getdomainname:
5898 goto unimplemented_nowarn;
5899#endif
ths6f5b89a2007-03-02 20:48:00 +00005900
thsb5906f92007-03-19 13:32:45 +00005901#ifdef TARGET_NR_clock_gettime
5902 case TARGET_NR_clock_gettime:
5903 {
5904 struct timespec ts;
5905 ret = get_errno(clock_gettime(arg1, &ts));
5906 if (!is_error(ret)) {
5907 host_to_target_timespec(arg2, &ts);
5908 }
5909 break;
5910 }
5911#endif
5912#ifdef TARGET_NR_clock_getres
5913 case TARGET_NR_clock_getres:
5914 {
5915 struct timespec ts;
5916 ret = get_errno(clock_getres(arg1, &ts));
5917 if (!is_error(ret)) {
5918 host_to_target_timespec(arg2, &ts);
5919 }
5920 break;
5921 }
5922#endif
pbrook63d76512008-05-29 13:43:29 +00005923#ifdef TARGET_NR_clock_nanosleep
5924 case TARGET_NR_clock_nanosleep:
5925 {
5926 struct timespec ts;
5927 target_to_host_timespec(&ts, arg3);
5928 ret = get_errno(clock_nanosleep(arg1, arg2, &ts, arg4 ? &ts : NULL));
5929 if (arg4)
5930 host_to_target_timespec(arg4, &ts);
5931 break;
5932 }
5933#endif
thsb5906f92007-03-19 13:32:45 +00005934
ths6f5b89a2007-03-02 20:48:00 +00005935#if defined(TARGET_NR_set_tid_address) && defined(__NR_set_tid_address)
5936 case TARGET_NR_set_tid_address:
bellard579a97f2007-11-11 14:26:47 +00005937 ret = get_errno(set_tid_address((int *)g2h(arg1)));
5938 break;
ths6f5b89a2007-03-02 20:48:00 +00005939#endif
5940
ths3ae43202007-09-16 21:39:48 +00005941#if defined(TARGET_NR_tkill) && defined(__NR_tkill)
ths4cae1d12007-07-12 11:06:53 +00005942 case TARGET_NR_tkill:
pbrook4cb05962008-05-30 18:05:19 +00005943 ret = get_errno(sys_tkill((int)arg1, target_to_host_signal(arg2)));
ths4cae1d12007-07-12 11:06:53 +00005944 break;
5945#endif
5946
ths3ae43202007-09-16 21:39:48 +00005947#if defined(TARGET_NR_tgkill) && defined(__NR_tgkill)
ths71455572007-06-21 21:45:30 +00005948 case TARGET_NR_tgkill:
pbrook4cb05962008-05-30 18:05:19 +00005949 ret = get_errno(sys_tgkill((int)arg1, (int)arg2,
5950 target_to_host_signal(arg3)));
ths71455572007-06-21 21:45:30 +00005951 break;
5952#endif
5953
ths4f2b1fe2007-06-21 21:57:12 +00005954#ifdef TARGET_NR_set_robust_list
5955 case TARGET_NR_set_robust_list:
5956 goto unimplemented_nowarn;
5957#endif
5958
ths9007f0e2007-09-25 17:50:37 +00005959#if defined(TARGET_NR_utimensat) && defined(__NR_utimensat)
5960 case TARGET_NR_utimensat:
5961 {
5962 struct timespec ts[2];
5963 target_to_host_timespec(ts, arg3);
5964 target_to_host_timespec(ts+1, arg3+sizeof(struct target_timespec));
5965 if (!arg2)
5966 ret = get_errno(sys_utimensat(arg1, NULL, ts, arg4));
5967 else {
bellard579a97f2007-11-11 14:26:47 +00005968 if (!(p = lock_user_string(arg2))) {
ths0da46a62007-10-20 20:23:07 +00005969 ret = -TARGET_EFAULT;
bellard579a97f2007-11-11 14:26:47 +00005970 goto fail;
5971 }
5972 ret = get_errno(sys_utimensat(arg1, path(p), ts, arg4));
5973 unlock_user(p, arg2, 0);
ths9007f0e2007-09-25 17:50:37 +00005974 }
5975 }
5976 break;
5977#endif
pbrookbd0c5662008-05-29 14:34:11 +00005978#if defined(USE_NPTL)
5979 case TARGET_NR_futex:
5980 ret = do_futex(arg1, arg2, arg3, arg4, arg5, arg6);
5981 break;
5982#endif
aurel3239b59762008-10-01 21:46:50 +00005983#ifdef TARGET_NR_inotify_init
5984 case TARGET_NR_inotify_init:
5985 ret = get_errno(sys_inotify_init());
5986 break;
5987#endif
5988#ifdef TARGET_NR_inotify_add_watch
5989 case TARGET_NR_inotify_add_watch:
5990 p = lock_user_string(arg2);
5991 ret = get_errno(sys_inotify_add_watch(arg1, path(p), arg3));
5992 unlock_user(p, arg2, 0);
5993 break;
5994#endif
5995#ifdef TARGET_NR_inotify_rm_watch
5996 case TARGET_NR_inotify_rm_watch:
5997 ret = get_errno(sys_inotify_rm_watch(arg1, arg2));
5998 break;
5999#endif
ths9007f0e2007-09-25 17:50:37 +00006000
bellard31e31b82003-02-18 22:55:36 +00006001 default:
6002 unimplemented:
bellard5cd43932003-03-29 16:54:36 +00006003 gemu_log("qemu: Unsupported syscall: %d\n", num);
ths4f2b1fe2007-06-21 21:57:12 +00006004#if defined(TARGET_NR_setxattr) || defined(TARGET_NR_get_thread_area) || defined(TARGET_NR_getdomainname) || defined(TARGET_NR_set_robust_list)
bellard5cd43932003-03-29 16:54:36 +00006005 unimplemented_nowarn:
bellard80a9d032005-01-03 23:31:27 +00006006#endif
ths0da46a62007-10-20 20:23:07 +00006007 ret = -TARGET_ENOSYS;
bellard31e31b82003-02-18 22:55:36 +00006008 break;
6009 }
bellard579a97f2007-11-11 14:26:47 +00006010fail:
bellardc573ff62004-01-04 15:51:36 +00006011#ifdef DEBUG
6012 gemu_log(" = %ld\n", ret);
6013#endif
thsb92c47c2007-11-01 00:07:38 +00006014 if(do_strace)
6015 print_syscall_ret(num, ret);
bellard31e31b82003-02-18 22:55:36 +00006016 return ret;
bellard579a97f2007-11-11 14:26:47 +00006017efault:
6018 ret = -TARGET_EFAULT;
6019 goto fail;
bellard31e31b82003-02-18 22:55:36 +00006020}