blob: 40e985adecd912d2129df1006ae198be7b257ac9 [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
j_mayer32407102007-09-26 23:01:49 +00001614#ifdef TARGET_NR_ipc
bellard8853f862004-02-22 14:57:26 +00001615#define N_SHM_REGIONS 32
1616
1617static struct shm_region {
bellard5a4a8982007-11-11 17:39:18 +00001618 abi_ulong start;
1619 abi_ulong size;
bellard8853f862004-02-22 14:57:26 +00001620} shm_regions[N_SHM_REGIONS];
1621
ths3eb6b042007-06-03 14:26:27 +00001622struct target_ipc_perm
1623{
blueswir1992f48a2007-10-14 16:27:31 +00001624 abi_long __key;
1625 abi_ulong uid;
1626 abi_ulong gid;
1627 abi_ulong cuid;
1628 abi_ulong cgid;
ths3eb6b042007-06-03 14:26:27 +00001629 unsigned short int mode;
1630 unsigned short int __pad1;
1631 unsigned short int __seq;
1632 unsigned short int __pad2;
blueswir1992f48a2007-10-14 16:27:31 +00001633 abi_ulong __unused1;
1634 abi_ulong __unused2;
ths3eb6b042007-06-03 14:26:27 +00001635};
1636
1637struct target_semid_ds
1638{
1639 struct target_ipc_perm sem_perm;
blueswir1992f48a2007-10-14 16:27:31 +00001640 abi_ulong sem_otime;
1641 abi_ulong __unused1;
1642 abi_ulong sem_ctime;
1643 abi_ulong __unused2;
1644 abi_ulong sem_nsems;
1645 abi_ulong __unused3;
1646 abi_ulong __unused4;
ths3eb6b042007-06-03 14:26:27 +00001647};
1648
bellard579a97f2007-11-11 14:26:47 +00001649static inline abi_long target_to_host_ipc_perm(struct ipc_perm *host_ip,
1650 abi_ulong target_addr)
ths3eb6b042007-06-03 14:26:27 +00001651{
1652 struct target_ipc_perm *target_ip;
1653 struct target_semid_ds *target_sd;
1654
bellard579a97f2007-11-11 14:26:47 +00001655 if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
1656 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00001657 target_ip=&(target_sd->sem_perm);
1658 host_ip->__key = tswapl(target_ip->__key);
1659 host_ip->uid = tswapl(target_ip->uid);
1660 host_ip->gid = tswapl(target_ip->gid);
1661 host_ip->cuid = tswapl(target_ip->cuid);
1662 host_ip->cgid = tswapl(target_ip->cgid);
1663 host_ip->mode = tswapl(target_ip->mode);
1664 unlock_user_struct(target_sd, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00001665 return 0;
ths3eb6b042007-06-03 14:26:27 +00001666}
1667
bellard579a97f2007-11-11 14:26:47 +00001668static inline abi_long host_to_target_ipc_perm(abi_ulong target_addr,
1669 struct ipc_perm *host_ip)
ths3eb6b042007-06-03 14:26:27 +00001670{
1671 struct target_ipc_perm *target_ip;
1672 struct target_semid_ds *target_sd;
1673
bellard579a97f2007-11-11 14:26:47 +00001674 if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
1675 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00001676 target_ip = &(target_sd->sem_perm);
1677 target_ip->__key = tswapl(host_ip->__key);
1678 target_ip->uid = tswapl(host_ip->uid);
1679 target_ip->gid = tswapl(host_ip->gid);
1680 target_ip->cuid = tswapl(host_ip->cuid);
1681 target_ip->cgid = tswapl(host_ip->cgid);
1682 target_ip->mode = tswapl(host_ip->mode);
1683 unlock_user_struct(target_sd, target_addr, 1);
bellard579a97f2007-11-11 14:26:47 +00001684 return 0;
ths3eb6b042007-06-03 14:26:27 +00001685}
1686
bellard579a97f2007-11-11 14:26:47 +00001687static inline abi_long target_to_host_semid_ds(struct semid_ds *host_sd,
1688 abi_ulong target_addr)
ths3eb6b042007-06-03 14:26:27 +00001689{
1690 struct target_semid_ds *target_sd;
1691
bellard579a97f2007-11-11 14:26:47 +00001692 if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
1693 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00001694 target_to_host_ipc_perm(&(host_sd->sem_perm),target_addr);
1695 host_sd->sem_nsems = tswapl(target_sd->sem_nsems);
1696 host_sd->sem_otime = tswapl(target_sd->sem_otime);
1697 host_sd->sem_ctime = tswapl(target_sd->sem_ctime);
1698 unlock_user_struct(target_sd, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00001699 return 0;
ths3eb6b042007-06-03 14:26:27 +00001700}
1701
bellard579a97f2007-11-11 14:26:47 +00001702static inline abi_long host_to_target_semid_ds(abi_ulong target_addr,
1703 struct semid_ds *host_sd)
ths3eb6b042007-06-03 14:26:27 +00001704{
1705 struct target_semid_ds *target_sd;
1706
bellard579a97f2007-11-11 14:26:47 +00001707 if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
1708 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00001709 host_to_target_ipc_perm(target_addr,&(host_sd->sem_perm));
1710 target_sd->sem_nsems = tswapl(host_sd->sem_nsems);
1711 target_sd->sem_otime = tswapl(host_sd->sem_otime);
1712 target_sd->sem_ctime = tswapl(host_sd->sem_ctime);
1713 unlock_user_struct(target_sd, target_addr, 1);
bellard579a97f2007-11-11 14:26:47 +00001714 return 0;
ths3eb6b042007-06-03 14:26:27 +00001715}
1716
thsfa294812007-02-02 22:05:00 +00001717union semun {
1718 int val;
ths3eb6b042007-06-03 14:26:27 +00001719 struct semid_ds *buf;
thsfa294812007-02-02 22:05:00 +00001720 unsigned short *array;
1721};
1722
ths3eb6b042007-06-03 14:26:27 +00001723union target_semun {
1724 int val;
blueswir1992f48a2007-10-14 16:27:31 +00001725 abi_long buf;
ths3eb6b042007-06-03 14:26:27 +00001726 unsigned short int *array;
1727};
1728
bellard579a97f2007-11-11 14:26:47 +00001729static inline abi_long target_to_host_semun(int cmd,
1730 union semun *host_su,
1731 abi_ulong target_addr,
1732 struct semid_ds *ds)
ths3eb6b042007-06-03 14:26:27 +00001733{
1734 union target_semun *target_su;
1735
1736 switch( cmd ) {
1737 case IPC_STAT:
1738 case IPC_SET:
bellard579a97f2007-11-11 14:26:47 +00001739 if (!lock_user_struct(VERIFY_READ, target_su, target_addr, 1))
1740 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00001741 target_to_host_semid_ds(ds,target_su->buf);
1742 host_su->buf = ds;
1743 unlock_user_struct(target_su, target_addr, 0);
1744 break;
1745 case GETVAL:
1746 case SETVAL:
bellard579a97f2007-11-11 14:26:47 +00001747 if (!lock_user_struct(VERIFY_READ, target_su, target_addr, 1))
1748 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00001749 host_su->val = tswapl(target_su->val);
1750 unlock_user_struct(target_su, target_addr, 0);
1751 break;
1752 case GETALL:
1753 case SETALL:
bellard579a97f2007-11-11 14:26:47 +00001754 if (!lock_user_struct(VERIFY_READ, target_su, target_addr, 1))
1755 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00001756 *host_su->array = tswap16(*target_su->array);
1757 unlock_user_struct(target_su, target_addr, 0);
1758 break;
1759 default:
1760 gemu_log("semun operation not fully supported: %d\n", (int)cmd);
1761 }
bellard579a97f2007-11-11 14:26:47 +00001762 return 0;
ths3eb6b042007-06-03 14:26:27 +00001763}
1764
bellard579a97f2007-11-11 14:26:47 +00001765static inline abi_long host_to_target_semun(int cmd,
1766 abi_ulong target_addr,
1767 union semun *host_su,
1768 struct semid_ds *ds)
ths3eb6b042007-06-03 14:26:27 +00001769{
1770 union target_semun *target_su;
1771
1772 switch( cmd ) {
1773 case IPC_STAT:
1774 case IPC_SET:
bellard579a97f2007-11-11 14:26:47 +00001775 if (lock_user_struct(VERIFY_WRITE, target_su, target_addr, 0))
1776 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00001777 host_to_target_semid_ds(target_su->buf,ds);
1778 unlock_user_struct(target_su, target_addr, 1);
1779 break;
1780 case GETVAL:
1781 case SETVAL:
bellard579a97f2007-11-11 14:26:47 +00001782 if (lock_user_struct(VERIFY_WRITE, target_su, target_addr, 0))
1783 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00001784 target_su->val = tswapl(host_su->val);
1785 unlock_user_struct(target_su, target_addr, 1);
1786 break;
1787 case GETALL:
1788 case SETALL:
bellard579a97f2007-11-11 14:26:47 +00001789 if (lock_user_struct(VERIFY_WRITE, target_su, target_addr, 0))
1790 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00001791 *target_su->array = tswap16(*host_su->array);
1792 unlock_user_struct(target_su, target_addr, 1);
1793 break;
1794 default:
1795 gemu_log("semun operation not fully supported: %d\n", (int)cmd);
1796 }
bellard579a97f2007-11-11 14:26:47 +00001797 return 0;
ths3eb6b042007-06-03 14:26:27 +00001798}
1799
blueswir1992f48a2007-10-14 16:27:31 +00001800static inline abi_long do_semctl(int first, int second, int third,
1801 abi_long ptr)
ths3eb6b042007-06-03 14:26:27 +00001802{
1803 union semun arg;
1804 struct semid_ds dsarg;
1805 int cmd = third&0xff;
blueswir1992f48a2007-10-14 16:27:31 +00001806 abi_long ret = 0;
ths3eb6b042007-06-03 14:26:27 +00001807
1808 switch( cmd ) {
1809 case GETVAL:
1810 target_to_host_semun(cmd,&arg,ptr,&dsarg);
1811 ret = get_errno(semctl(first, second, cmd, arg));
1812 host_to_target_semun(cmd,ptr,&arg,&dsarg);
1813 break;
1814 case SETVAL:
1815 target_to_host_semun(cmd,&arg,ptr,&dsarg);
1816 ret = get_errno(semctl(first, second, cmd, arg));
1817 host_to_target_semun(cmd,ptr,&arg,&dsarg);
1818 break;
1819 case GETALL:
1820 target_to_host_semun(cmd,&arg,ptr,&dsarg);
1821 ret = get_errno(semctl(first, second, cmd, arg));
1822 host_to_target_semun(cmd,ptr,&arg,&dsarg);
1823 break;
1824 case SETALL:
1825 target_to_host_semun(cmd,&arg,ptr,&dsarg);
1826 ret = get_errno(semctl(first, second, cmd, arg));
1827 host_to_target_semun(cmd,ptr,&arg,&dsarg);
1828 break;
1829 case IPC_STAT:
1830 target_to_host_semun(cmd,&arg,ptr,&dsarg);
1831 ret = get_errno(semctl(first, second, cmd, arg));
1832 host_to_target_semun(cmd,ptr,&arg,&dsarg);
1833 break;
1834 case IPC_SET:
1835 target_to_host_semun(cmd,&arg,ptr,&dsarg);
1836 ret = get_errno(semctl(first, second, cmd, arg));
1837 host_to_target_semun(cmd,ptr,&arg,&dsarg);
1838 break;
1839 default:
1840 ret = get_errno(semctl(first, second, cmd, arg));
1841 }
1842
1843 return ret;
1844}
1845
ths1bc012f2007-06-03 14:27:49 +00001846struct target_msqid_ds
1847{
1848 struct target_ipc_perm msg_perm;
blueswir1992f48a2007-10-14 16:27:31 +00001849 abi_ulong msg_stime;
1850 abi_ulong __unused1;
1851 abi_ulong msg_rtime;
1852 abi_ulong __unused2;
1853 abi_ulong msg_ctime;
1854 abi_ulong __unused3;
1855 abi_ulong __msg_cbytes;
1856 abi_ulong msg_qnum;
1857 abi_ulong msg_qbytes;
1858 abi_ulong msg_lspid;
1859 abi_ulong msg_lrpid;
1860 abi_ulong __unused4;
1861 abi_ulong __unused5;
ths1bc012f2007-06-03 14:27:49 +00001862};
1863
bellard579a97f2007-11-11 14:26:47 +00001864static inline abi_long target_to_host_msqid_ds(struct msqid_ds *host_md,
1865 abi_ulong target_addr)
ths1bc012f2007-06-03 14:27:49 +00001866{
1867 struct target_msqid_ds *target_md;
1868
bellard579a97f2007-11-11 14:26:47 +00001869 if (!lock_user_struct(VERIFY_READ, target_md, target_addr, 1))
1870 return -TARGET_EFAULT;
ths1bc012f2007-06-03 14:27:49 +00001871 target_to_host_ipc_perm(&(host_md->msg_perm),target_addr);
1872 host_md->msg_stime = tswapl(target_md->msg_stime);
1873 host_md->msg_rtime = tswapl(target_md->msg_rtime);
1874 host_md->msg_ctime = tswapl(target_md->msg_ctime);
1875 host_md->__msg_cbytes = tswapl(target_md->__msg_cbytes);
1876 host_md->msg_qnum = tswapl(target_md->msg_qnum);
1877 host_md->msg_qbytes = tswapl(target_md->msg_qbytes);
1878 host_md->msg_lspid = tswapl(target_md->msg_lspid);
1879 host_md->msg_lrpid = tswapl(target_md->msg_lrpid);
1880 unlock_user_struct(target_md, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00001881 return 0;
ths1bc012f2007-06-03 14:27:49 +00001882}
1883
bellard579a97f2007-11-11 14:26:47 +00001884static inline abi_long host_to_target_msqid_ds(abi_ulong target_addr,
1885 struct msqid_ds *host_md)
ths1bc012f2007-06-03 14:27:49 +00001886{
1887 struct target_msqid_ds *target_md;
1888
bellard579a97f2007-11-11 14:26:47 +00001889 if (!lock_user_struct(VERIFY_WRITE, target_md, target_addr, 0))
1890 return -TARGET_EFAULT;
ths1bc012f2007-06-03 14:27:49 +00001891 host_to_target_ipc_perm(target_addr,&(host_md->msg_perm));
1892 target_md->msg_stime = tswapl(host_md->msg_stime);
1893 target_md->msg_rtime = tswapl(host_md->msg_rtime);
1894 target_md->msg_ctime = tswapl(host_md->msg_ctime);
1895 target_md->__msg_cbytes = tswapl(host_md->__msg_cbytes);
1896 target_md->msg_qnum = tswapl(host_md->msg_qnum);
1897 target_md->msg_qbytes = tswapl(host_md->msg_qbytes);
1898 target_md->msg_lspid = tswapl(host_md->msg_lspid);
1899 target_md->msg_lrpid = tswapl(host_md->msg_lrpid);
1900 unlock_user_struct(target_md, target_addr, 1);
bellard579a97f2007-11-11 14:26:47 +00001901 return 0;
ths1bc012f2007-06-03 14:27:49 +00001902}
1903
blueswir1992f48a2007-10-14 16:27:31 +00001904static inline abi_long do_msgctl(int first, int second, abi_long ptr)
ths1bc012f2007-06-03 14:27:49 +00001905{
1906 struct msqid_ds dsarg;
1907 int cmd = second&0xff;
blueswir1992f48a2007-10-14 16:27:31 +00001908 abi_long ret = 0;
ths1bc012f2007-06-03 14:27:49 +00001909 switch( cmd ) {
1910 case IPC_STAT:
1911 case IPC_SET:
1912 target_to_host_msqid_ds(&dsarg,ptr);
1913 ret = get_errno(msgctl(first, cmd, &dsarg));
1914 host_to_target_msqid_ds(ptr,&dsarg);
1915 default:
1916 ret = get_errno(msgctl(first, cmd, &dsarg));
1917 }
1918 return ret;
1919}
1920
1921struct target_msgbuf {
blueswir1992f48a2007-10-14 16:27:31 +00001922 abi_ulong mtype;
ths1bc012f2007-06-03 14:27:49 +00001923 char mtext[1];
1924};
1925
blueswir1992f48a2007-10-14 16:27:31 +00001926static inline abi_long do_msgsnd(int msqid, abi_long msgp,
1927 unsigned int msgsz, int msgflg)
ths1bc012f2007-06-03 14:27:49 +00001928{
1929 struct target_msgbuf *target_mb;
1930 struct msgbuf *host_mb;
blueswir1992f48a2007-10-14 16:27:31 +00001931 abi_long ret = 0;
ths1bc012f2007-06-03 14:27:49 +00001932
bellard579a97f2007-11-11 14:26:47 +00001933 if (!lock_user_struct(VERIFY_READ, target_mb, msgp, 0))
1934 return -TARGET_EFAULT;
ths1bc012f2007-06-03 14:27:49 +00001935 host_mb = malloc(msgsz+sizeof(long));
1936 host_mb->mtype = tswapl(target_mb->mtype);
1937 memcpy(host_mb->mtext,target_mb->mtext,msgsz);
1938 ret = get_errno(msgsnd(msqid, host_mb, msgsz, msgflg));
1939 free(host_mb);
1940 unlock_user_struct(target_mb, msgp, 0);
1941
1942 return ret;
1943}
1944
blueswir1992f48a2007-10-14 16:27:31 +00001945static inline abi_long do_msgrcv(int msqid, abi_long msgp,
1946 unsigned int msgsz, int msgtype,
1947 int msgflg)
ths1bc012f2007-06-03 14:27:49 +00001948{
1949 struct target_msgbuf *target_mb;
bellard579a97f2007-11-11 14:26:47 +00001950 char *target_mtext;
ths1bc012f2007-06-03 14:27:49 +00001951 struct msgbuf *host_mb;
blueswir1992f48a2007-10-14 16:27:31 +00001952 abi_long ret = 0;
ths1bc012f2007-06-03 14:27:49 +00001953
bellard579a97f2007-11-11 14:26:47 +00001954 if (!lock_user_struct(VERIFY_WRITE, target_mb, msgp, 0))
1955 return -TARGET_EFAULT;
ths1bc012f2007-06-03 14:27:49 +00001956 host_mb = malloc(msgsz+sizeof(long));
1957 ret = get_errno(msgrcv(msqid, host_mb, msgsz, 1, msgflg));
bellard579a97f2007-11-11 14:26:47 +00001958 if (ret > 0) {
1959 abi_ulong target_mtext_addr = msgp + sizeof(abi_ulong);
1960 target_mtext = lock_user(VERIFY_WRITE, target_mtext_addr, ret, 0);
1961 if (!target_mtext) {
1962 ret = -TARGET_EFAULT;
1963 goto end;
1964 }
ths1bc012f2007-06-03 14:27:49 +00001965 memcpy(target_mb->mtext, host_mb->mtext, ret);
bellard579a97f2007-11-11 14:26:47 +00001966 unlock_user(target_mtext, target_mtext_addr, ret);
1967 }
ths1bc012f2007-06-03 14:27:49 +00001968 target_mb->mtype = tswapl(host_mb->mtype);
1969 free(host_mb);
ths1bc012f2007-06-03 14:27:49 +00001970
bellard579a97f2007-11-11 14:26:47 +00001971end:
1972 if (target_mb)
1973 unlock_user_struct(target_mb, msgp, 1);
ths1bc012f2007-06-03 14:27:49 +00001974 return ret;
1975}
1976
pbrook53a59602006-03-25 19:31:22 +00001977/* ??? This only works with linear mappings. */
ths0da46a62007-10-20 20:23:07 +00001978/* do_ipc() must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001979static abi_long do_ipc(unsigned int call, int first,
1980 int second, int third,
1981 abi_long ptr, abi_long fifth)
bellard8853f862004-02-22 14:57:26 +00001982{
1983 int version;
blueswir1992f48a2007-10-14 16:27:31 +00001984 abi_long ret = 0;
bellard8853f862004-02-22 14:57:26 +00001985 struct shmid_ds shm_info;
1986 int i;
1987
1988 version = call >> 16;
1989 call &= 0xffff;
1990
1991 switch (call) {
thsfa294812007-02-02 22:05:00 +00001992 case IPCOP_semop:
bellard579a97f2007-11-11 14:26:47 +00001993 ret = get_errno(semop(first,(struct sembuf *)g2h(ptr), second));
thsfa294812007-02-02 22:05:00 +00001994 break;
1995
1996 case IPCOP_semget:
1997 ret = get_errno(semget(first, second, third));
1998 break;
1999
2000 case IPCOP_semctl:
ths3eb6b042007-06-03 14:26:27 +00002001 ret = do_semctl(first, second, third, ptr);
thsfa294812007-02-02 22:05:00 +00002002 break;
2003
2004 case IPCOP_semtimedop:
j_mayer32407102007-09-26 23:01:49 +00002005 gemu_log("Unsupported ipc call: %d (version %d)\n", call, version);
ths0da46a62007-10-20 20:23:07 +00002006 ret = -TARGET_ENOSYS;
thsfa294812007-02-02 22:05:00 +00002007 break;
thsd96372e2007-02-02 22:05:44 +00002008
2009 case IPCOP_msgget:
2010 ret = get_errno(msgget(first, second));
2011 break;
2012
2013 case IPCOP_msgsnd:
ths1bc012f2007-06-03 14:27:49 +00002014 ret = do_msgsnd(first, ptr, second, third);
thsd96372e2007-02-02 22:05:44 +00002015 break;
2016
2017 case IPCOP_msgctl:
ths1bc012f2007-06-03 14:27:49 +00002018 ret = do_msgctl(first, second, ptr);
thsd96372e2007-02-02 22:05:44 +00002019 break;
2020
2021 case IPCOP_msgrcv:
ths1bc012f2007-06-03 14:27:49 +00002022 {
bellard579a97f2007-11-11 14:26:47 +00002023 /* XXX: this code is not correct */
ths1bc012f2007-06-03 14:27:49 +00002024 struct ipc_kludge
2025 {
2026 void *__unbounded msgp;
2027 long int msgtyp;
2028 };
thsd96372e2007-02-02 22:05:44 +00002029
bellard579a97f2007-11-11 14:26:47 +00002030 struct ipc_kludge *foo = (struct ipc_kludge *)g2h(ptr);
ths1bc012f2007-06-03 14:27:49 +00002031 struct msgbuf *msgp = (struct msgbuf *) foo->msgp;
thsd96372e2007-02-02 22:05:44 +00002032
ths1bc012f2007-06-03 14:27:49 +00002033 ret = do_msgrcv(first, (long)msgp, second, 0, third);
thsd96372e2007-02-02 22:05:44 +00002034
ths1bc012f2007-06-03 14:27:49 +00002035 }
thsd96372e2007-02-02 22:05:44 +00002036 break;
2037
bellard8853f862004-02-22 14:57:26 +00002038 case IPCOP_shmat:
bellard5a4a8982007-11-11 17:39:18 +00002039 {
2040 abi_ulong raddr;
2041 void *host_addr;
2042 /* SHM_* flags are the same on all linux platforms */
2043 host_addr = shmat(first, (void *)g2h(ptr), second);
2044 if (host_addr == (void *)-1) {
2045 ret = get_errno((long)host_addr);
bellard8853f862004-02-22 14:57:26 +00002046 break;
bellard5a4a8982007-11-11 17:39:18 +00002047 }
2048 raddr = h2g((unsigned long)host_addr);
2049 /* find out the length of the shared memory segment */
2050
2051 ret = get_errno(shmctl(first, IPC_STAT, &shm_info));
2052 if (is_error(ret)) {
2053 /* can't get length, bail out */
2054 shmdt(host_addr);
2055 break;
2056 }
2057 page_set_flags(raddr, raddr + shm_info.shm_segsz,
2058 PAGE_VALID | PAGE_READ |
2059 ((second & SHM_RDONLY)? 0: PAGE_WRITE));
2060 for (i = 0; i < N_SHM_REGIONS; ++i) {
2061 if (shm_regions[i].start == 0) {
2062 shm_regions[i].start = raddr;
2063 shm_regions[i].size = shm_info.shm_segsz;
2064 break;
2065 }
2066 }
bellard2f619692007-11-16 10:46:05 +00002067 if (put_user_ual(raddr, third))
bellard5a4a8982007-11-11 17:39:18 +00002068 return -TARGET_EFAULT;
2069 ret = 0;
2070 }
bellard8853f862004-02-22 14:57:26 +00002071 break;
2072 case IPCOP_shmdt:
2073 for (i = 0; i < N_SHM_REGIONS; ++i) {
2074 if (shm_regions[i].start == ptr) {
2075 shm_regions[i].start = 0;
2076 page_set_flags(ptr, shm_regions[i].size, 0);
2077 break;
2078 }
2079 }
bellard5a4a8982007-11-11 17:39:18 +00002080 ret = get_errno(shmdt((void *)g2h(ptr)));
bellard8853f862004-02-22 14:57:26 +00002081 break;
2082
2083 case IPCOP_shmget:
2084 /* IPC_* flag values are the same on all linux platforms */
2085 ret = get_errno(shmget(first, second, third));
2086 break;
2087
2088 /* IPC_* and SHM_* command values are the same on all linux platforms */
2089 case IPCOP_shmctl:
2090 switch(second) {
2091 case IPC_RMID:
2092 case SHM_LOCK:
2093 case SHM_UNLOCK:
2094 ret = get_errno(shmctl(first, second, NULL));
2095 break;
2096 default:
2097 goto unimplemented;
2098 }
2099 break;
2100 default:
2101 unimplemented:
j_mayer32407102007-09-26 23:01:49 +00002102 gemu_log("Unsupported ipc call: %d (version %d)\n", call, version);
ths0da46a62007-10-20 20:23:07 +00002103 ret = -TARGET_ENOSYS;
bellard8853f862004-02-22 14:57:26 +00002104 break;
2105 }
2106 return ret;
2107}
j_mayer32407102007-09-26 23:01:49 +00002108#endif
bellard8853f862004-02-22 14:57:26 +00002109
bellard31e31b82003-02-18 22:55:36 +00002110/* kernel structure types definitions */
2111#define IFNAMSIZ 16
2112
2113#define STRUCT(name, list...) STRUCT_ ## name,
2114#define STRUCT_SPECIAL(name) STRUCT_ ## name,
2115enum {
2116#include "syscall_types.h"
2117};
2118#undef STRUCT
2119#undef STRUCT_SPECIAL
2120
blueswir160dd3162008-10-05 11:45:25 +00002121#define STRUCT(name, list...) static const argtype struct_ ## name ## _def[] = { list, TYPE_NULL };
bellard31e31b82003-02-18 22:55:36 +00002122#define STRUCT_SPECIAL(name)
2123#include "syscall_types.h"
2124#undef STRUCT
2125#undef STRUCT_SPECIAL
2126
2127typedef struct IOCTLEntry {
bellard2ab83ea2003-06-15 19:56:46 +00002128 unsigned int target_cmd;
2129 unsigned int host_cmd;
bellard31e31b82003-02-18 22:55:36 +00002130 const char *name;
2131 int access;
bellard1a9353d2003-03-16 20:28:50 +00002132 const argtype arg_type[5];
bellard31e31b82003-02-18 22:55:36 +00002133} IOCTLEntry;
2134
2135#define IOC_R 0x0001
2136#define IOC_W 0x0002
2137#define IOC_RW (IOC_R | IOC_W)
2138
2139#define MAX_STRUCT_SIZE 4096
2140
blueswir19f106a72008-10-05 10:52:52 +00002141static IOCTLEntry ioctl_entries[] = {
bellard31e31b82003-02-18 22:55:36 +00002142#define IOCTL(cmd, access, types...) \
2143 { TARGET_ ## cmd, cmd, #cmd, access, { types } },
2144#include "ioctls.h"
2145 { 0, 0, },
2146};
2147
pbrook53a59602006-03-25 19:31:22 +00002148/* ??? Implement proper locking for ioctls. */
ths0da46a62007-10-20 20:23:07 +00002149/* do_ioctl() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00002150static abi_long do_ioctl(int fd, abi_long cmd, abi_long arg)
bellard31e31b82003-02-18 22:55:36 +00002151{
2152 const IOCTLEntry *ie;
2153 const argtype *arg_type;
blueswir1992f48a2007-10-14 16:27:31 +00002154 abi_long ret;
bellard31e31b82003-02-18 22:55:36 +00002155 uint8_t buf_temp[MAX_STRUCT_SIZE];
pbrook53a59602006-03-25 19:31:22 +00002156 int target_size;
2157 void *argptr;
bellard31e31b82003-02-18 22:55:36 +00002158
2159 ie = ioctl_entries;
2160 for(;;) {
2161 if (ie->target_cmd == 0) {
j_mayer32407102007-09-26 23:01:49 +00002162 gemu_log("Unsupported ioctl: cmd=0x%04lx\n", (long)cmd);
ths0da46a62007-10-20 20:23:07 +00002163 return -TARGET_ENOSYS;
bellard31e31b82003-02-18 22:55:36 +00002164 }
2165 if (ie->target_cmd == cmd)
2166 break;
2167 ie++;
2168 }
2169 arg_type = ie->arg_type;
bellard9de5e442003-03-23 16:49:39 +00002170#if defined(DEBUG)
j_mayer32407102007-09-26 23:01:49 +00002171 gemu_log("ioctl: cmd=0x%04lx (%s)\n", (long)cmd, ie->name);
bellard72f03902003-02-18 23:33:18 +00002172#endif
bellard31e31b82003-02-18 22:55:36 +00002173 switch(arg_type[0]) {
2174 case TYPE_NULL:
2175 /* no argument */
2176 ret = get_errno(ioctl(fd, ie->host_cmd));
2177 break;
2178 case TYPE_PTRVOID:
2179 case TYPE_INT:
2180 /* int argment */
2181 ret = get_errno(ioctl(fd, ie->host_cmd, arg));
2182 break;
2183 case TYPE_PTR:
2184 arg_type++;
pbrook53a59602006-03-25 19:31:22 +00002185 target_size = thunk_type_size(arg_type, 0);
bellard31e31b82003-02-18 22:55:36 +00002186 switch(ie->access) {
2187 case IOC_R:
2188 ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
2189 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00002190 argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
2191 if (!argptr)
2192 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00002193 thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
2194 unlock_user(argptr, arg, target_size);
bellard31e31b82003-02-18 22:55:36 +00002195 }
2196 break;
2197 case IOC_W:
bellard579a97f2007-11-11 14:26:47 +00002198 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
2199 if (!argptr)
2200 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00002201 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
2202 unlock_user(argptr, arg, 0);
bellard31e31b82003-02-18 22:55:36 +00002203 ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
2204 break;
2205 default:
2206 case IOC_RW:
bellard579a97f2007-11-11 14:26:47 +00002207 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
2208 if (!argptr)
2209 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00002210 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
2211 unlock_user(argptr, arg, 0);
bellard31e31b82003-02-18 22:55:36 +00002212 ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
2213 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00002214 argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
2215 if (!argptr)
2216 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00002217 thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
2218 unlock_user(argptr, arg, target_size);
bellard31e31b82003-02-18 22:55:36 +00002219 }
2220 break;
2221 }
2222 break;
2223 default:
j_mayer32407102007-09-26 23:01:49 +00002224 gemu_log("Unsupported ioctl type: cmd=0x%04lx type=%d\n",
2225 (long)cmd, arg_type[0]);
ths0da46a62007-10-20 20:23:07 +00002226 ret = -TARGET_ENOSYS;
bellard31e31b82003-02-18 22:55:36 +00002227 break;
2228 }
2229 return ret;
2230}
2231
blueswir1b39bc502008-10-05 10:51:10 +00002232static const bitmask_transtbl iflag_tbl[] = {
bellard31e31b82003-02-18 22:55:36 +00002233 { TARGET_IGNBRK, TARGET_IGNBRK, IGNBRK, IGNBRK },
2234 { TARGET_BRKINT, TARGET_BRKINT, BRKINT, BRKINT },
2235 { TARGET_IGNPAR, TARGET_IGNPAR, IGNPAR, IGNPAR },
2236 { TARGET_PARMRK, TARGET_PARMRK, PARMRK, PARMRK },
2237 { TARGET_INPCK, TARGET_INPCK, INPCK, INPCK },
2238 { TARGET_ISTRIP, TARGET_ISTRIP, ISTRIP, ISTRIP },
2239 { TARGET_INLCR, TARGET_INLCR, INLCR, INLCR },
2240 { TARGET_IGNCR, TARGET_IGNCR, IGNCR, IGNCR },
2241 { TARGET_ICRNL, TARGET_ICRNL, ICRNL, ICRNL },
2242 { TARGET_IUCLC, TARGET_IUCLC, IUCLC, IUCLC },
2243 { TARGET_IXON, TARGET_IXON, IXON, IXON },
2244 { TARGET_IXANY, TARGET_IXANY, IXANY, IXANY },
2245 { TARGET_IXOFF, TARGET_IXOFF, IXOFF, IXOFF },
2246 { TARGET_IMAXBEL, TARGET_IMAXBEL, IMAXBEL, IMAXBEL },
2247 { 0, 0, 0, 0 }
2248};
2249
blueswir1b39bc502008-10-05 10:51:10 +00002250static const bitmask_transtbl oflag_tbl[] = {
bellard31e31b82003-02-18 22:55:36 +00002251 { TARGET_OPOST, TARGET_OPOST, OPOST, OPOST },
2252 { TARGET_OLCUC, TARGET_OLCUC, OLCUC, OLCUC },
2253 { TARGET_ONLCR, TARGET_ONLCR, ONLCR, ONLCR },
2254 { TARGET_OCRNL, TARGET_OCRNL, OCRNL, OCRNL },
2255 { TARGET_ONOCR, TARGET_ONOCR, ONOCR, ONOCR },
2256 { TARGET_ONLRET, TARGET_ONLRET, ONLRET, ONLRET },
2257 { TARGET_OFILL, TARGET_OFILL, OFILL, OFILL },
2258 { TARGET_OFDEL, TARGET_OFDEL, OFDEL, OFDEL },
2259 { TARGET_NLDLY, TARGET_NL0, NLDLY, NL0 },
2260 { TARGET_NLDLY, TARGET_NL1, NLDLY, NL1 },
2261 { TARGET_CRDLY, TARGET_CR0, CRDLY, CR0 },
2262 { TARGET_CRDLY, TARGET_CR1, CRDLY, CR1 },
2263 { TARGET_CRDLY, TARGET_CR2, CRDLY, CR2 },
2264 { TARGET_CRDLY, TARGET_CR3, CRDLY, CR3 },
2265 { TARGET_TABDLY, TARGET_TAB0, TABDLY, TAB0 },
2266 { TARGET_TABDLY, TARGET_TAB1, TABDLY, TAB1 },
2267 { TARGET_TABDLY, TARGET_TAB2, TABDLY, TAB2 },
2268 { TARGET_TABDLY, TARGET_TAB3, TABDLY, TAB3 },
2269 { TARGET_BSDLY, TARGET_BS0, BSDLY, BS0 },
2270 { TARGET_BSDLY, TARGET_BS1, BSDLY, BS1 },
2271 { TARGET_VTDLY, TARGET_VT0, VTDLY, VT0 },
2272 { TARGET_VTDLY, TARGET_VT1, VTDLY, VT1 },
2273 { TARGET_FFDLY, TARGET_FF0, FFDLY, FF0 },
2274 { TARGET_FFDLY, TARGET_FF1, FFDLY, FF1 },
2275 { 0, 0, 0, 0 }
2276};
2277
blueswir1b39bc502008-10-05 10:51:10 +00002278static const bitmask_transtbl cflag_tbl[] = {
bellard31e31b82003-02-18 22:55:36 +00002279 { TARGET_CBAUD, TARGET_B0, CBAUD, B0 },
2280 { TARGET_CBAUD, TARGET_B50, CBAUD, B50 },
2281 { TARGET_CBAUD, TARGET_B75, CBAUD, B75 },
2282 { TARGET_CBAUD, TARGET_B110, CBAUD, B110 },
2283 { TARGET_CBAUD, TARGET_B134, CBAUD, B134 },
2284 { TARGET_CBAUD, TARGET_B150, CBAUD, B150 },
2285 { TARGET_CBAUD, TARGET_B200, CBAUD, B200 },
2286 { TARGET_CBAUD, TARGET_B300, CBAUD, B300 },
2287 { TARGET_CBAUD, TARGET_B600, CBAUD, B600 },
2288 { TARGET_CBAUD, TARGET_B1200, CBAUD, B1200 },
2289 { TARGET_CBAUD, TARGET_B1800, CBAUD, B1800 },
2290 { TARGET_CBAUD, TARGET_B2400, CBAUD, B2400 },
2291 { TARGET_CBAUD, TARGET_B4800, CBAUD, B4800 },
2292 { TARGET_CBAUD, TARGET_B9600, CBAUD, B9600 },
2293 { TARGET_CBAUD, TARGET_B19200, CBAUD, B19200 },
2294 { TARGET_CBAUD, TARGET_B38400, CBAUD, B38400 },
2295 { TARGET_CBAUD, TARGET_B57600, CBAUD, B57600 },
2296 { TARGET_CBAUD, TARGET_B115200, CBAUD, B115200 },
2297 { TARGET_CBAUD, TARGET_B230400, CBAUD, B230400 },
2298 { TARGET_CBAUD, TARGET_B460800, CBAUD, B460800 },
2299 { TARGET_CSIZE, TARGET_CS5, CSIZE, CS5 },
2300 { TARGET_CSIZE, TARGET_CS6, CSIZE, CS6 },
2301 { TARGET_CSIZE, TARGET_CS7, CSIZE, CS7 },
2302 { TARGET_CSIZE, TARGET_CS8, CSIZE, CS8 },
2303 { TARGET_CSTOPB, TARGET_CSTOPB, CSTOPB, CSTOPB },
2304 { TARGET_CREAD, TARGET_CREAD, CREAD, CREAD },
2305 { TARGET_PARENB, TARGET_PARENB, PARENB, PARENB },
2306 { TARGET_PARODD, TARGET_PARODD, PARODD, PARODD },
2307 { TARGET_HUPCL, TARGET_HUPCL, HUPCL, HUPCL },
2308 { TARGET_CLOCAL, TARGET_CLOCAL, CLOCAL, CLOCAL },
2309 { TARGET_CRTSCTS, TARGET_CRTSCTS, CRTSCTS, CRTSCTS },
2310 { 0, 0, 0, 0 }
2311};
2312
blueswir1b39bc502008-10-05 10:51:10 +00002313static const bitmask_transtbl lflag_tbl[] = {
bellard31e31b82003-02-18 22:55:36 +00002314 { TARGET_ISIG, TARGET_ISIG, ISIG, ISIG },
2315 { TARGET_ICANON, TARGET_ICANON, ICANON, ICANON },
2316 { TARGET_XCASE, TARGET_XCASE, XCASE, XCASE },
2317 { TARGET_ECHO, TARGET_ECHO, ECHO, ECHO },
2318 { TARGET_ECHOE, TARGET_ECHOE, ECHOE, ECHOE },
2319 { TARGET_ECHOK, TARGET_ECHOK, ECHOK, ECHOK },
2320 { TARGET_ECHONL, TARGET_ECHONL, ECHONL, ECHONL },
2321 { TARGET_NOFLSH, TARGET_NOFLSH, NOFLSH, NOFLSH },
2322 { TARGET_TOSTOP, TARGET_TOSTOP, TOSTOP, TOSTOP },
2323 { TARGET_ECHOCTL, TARGET_ECHOCTL, ECHOCTL, ECHOCTL },
2324 { TARGET_ECHOPRT, TARGET_ECHOPRT, ECHOPRT, ECHOPRT },
2325 { TARGET_ECHOKE, TARGET_ECHOKE, ECHOKE, ECHOKE },
2326 { TARGET_FLUSHO, TARGET_FLUSHO, FLUSHO, FLUSHO },
2327 { TARGET_PENDIN, TARGET_PENDIN, PENDIN, PENDIN },
2328 { TARGET_IEXTEN, TARGET_IEXTEN, IEXTEN, IEXTEN },
2329 { 0, 0, 0, 0 }
2330};
2331
2332static void target_to_host_termios (void *dst, const void *src)
2333{
2334 struct host_termios *host = dst;
2335 const struct target_termios *target = src;
ths3b46e622007-09-17 08:09:54 +00002336
ths5fafdf22007-09-16 21:08:06 +00002337 host->c_iflag =
bellard31e31b82003-02-18 22:55:36 +00002338 target_to_host_bitmask(tswap32(target->c_iflag), iflag_tbl);
ths5fafdf22007-09-16 21:08:06 +00002339 host->c_oflag =
bellard31e31b82003-02-18 22:55:36 +00002340 target_to_host_bitmask(tswap32(target->c_oflag), oflag_tbl);
ths5fafdf22007-09-16 21:08:06 +00002341 host->c_cflag =
bellard31e31b82003-02-18 22:55:36 +00002342 target_to_host_bitmask(tswap32(target->c_cflag), cflag_tbl);
ths5fafdf22007-09-16 21:08:06 +00002343 host->c_lflag =
bellard31e31b82003-02-18 22:55:36 +00002344 target_to_host_bitmask(tswap32(target->c_lflag), lflag_tbl);
2345 host->c_line = target->c_line;
ths3b46e622007-09-17 08:09:54 +00002346
ths5fafdf22007-09-16 21:08:06 +00002347 host->c_cc[VINTR] = target->c_cc[TARGET_VINTR];
2348 host->c_cc[VQUIT] = target->c_cc[TARGET_VQUIT];
ths3b46e622007-09-17 08:09:54 +00002349 host->c_cc[VERASE] = target->c_cc[TARGET_VERASE];
ths5fafdf22007-09-16 21:08:06 +00002350 host->c_cc[VKILL] = target->c_cc[TARGET_VKILL];
ths3b46e622007-09-17 08:09:54 +00002351 host->c_cc[VEOF] = target->c_cc[TARGET_VEOF];
ths5fafdf22007-09-16 21:08:06 +00002352 host->c_cc[VTIME] = target->c_cc[TARGET_VTIME];
ths3b46e622007-09-17 08:09:54 +00002353 host->c_cc[VMIN] = target->c_cc[TARGET_VMIN];
ths5fafdf22007-09-16 21:08:06 +00002354 host->c_cc[VSWTC] = target->c_cc[TARGET_VSWTC];
ths3b46e622007-09-17 08:09:54 +00002355 host->c_cc[VSTART] = target->c_cc[TARGET_VSTART];
ths5fafdf22007-09-16 21:08:06 +00002356 host->c_cc[VSTOP] = target->c_cc[TARGET_VSTOP];
2357 host->c_cc[VSUSP] = target->c_cc[TARGET_VSUSP];
ths3b46e622007-09-17 08:09:54 +00002358 host->c_cc[VEOL] = target->c_cc[TARGET_VEOL];
2359 host->c_cc[VREPRINT] = target->c_cc[TARGET_VREPRINT];
2360 host->c_cc[VDISCARD] = target->c_cc[TARGET_VDISCARD];
2361 host->c_cc[VWERASE] = target->c_cc[TARGET_VWERASE];
2362 host->c_cc[VLNEXT] = target->c_cc[TARGET_VLNEXT];
ths5fafdf22007-09-16 21:08:06 +00002363 host->c_cc[VEOL2] = target->c_cc[TARGET_VEOL2];
bellard31e31b82003-02-18 22:55:36 +00002364}
ths3b46e622007-09-17 08:09:54 +00002365
bellard31e31b82003-02-18 22:55:36 +00002366static void host_to_target_termios (void *dst, const void *src)
2367{
2368 struct target_termios *target = dst;
2369 const struct host_termios *host = src;
2370
ths5fafdf22007-09-16 21:08:06 +00002371 target->c_iflag =
bellard31e31b82003-02-18 22:55:36 +00002372 tswap32(host_to_target_bitmask(host->c_iflag, iflag_tbl));
ths5fafdf22007-09-16 21:08:06 +00002373 target->c_oflag =
bellard31e31b82003-02-18 22:55:36 +00002374 tswap32(host_to_target_bitmask(host->c_oflag, oflag_tbl));
ths5fafdf22007-09-16 21:08:06 +00002375 target->c_cflag =
bellard31e31b82003-02-18 22:55:36 +00002376 tswap32(host_to_target_bitmask(host->c_cflag, cflag_tbl));
ths5fafdf22007-09-16 21:08:06 +00002377 target->c_lflag =
bellard31e31b82003-02-18 22:55:36 +00002378 tswap32(host_to_target_bitmask(host->c_lflag, lflag_tbl));
2379 target->c_line = host->c_line;
ths3b46e622007-09-17 08:09:54 +00002380
bellard31e31b82003-02-18 22:55:36 +00002381 target->c_cc[TARGET_VINTR] = host->c_cc[VINTR];
2382 target->c_cc[TARGET_VQUIT] = host->c_cc[VQUIT];
2383 target->c_cc[TARGET_VERASE] = host->c_cc[VERASE];
2384 target->c_cc[TARGET_VKILL] = host->c_cc[VKILL];
2385 target->c_cc[TARGET_VEOF] = host->c_cc[VEOF];
2386 target->c_cc[TARGET_VTIME] = host->c_cc[VTIME];
2387 target->c_cc[TARGET_VMIN] = host->c_cc[VMIN];
2388 target->c_cc[TARGET_VSWTC] = host->c_cc[VSWTC];
2389 target->c_cc[TARGET_VSTART] = host->c_cc[VSTART];
2390 target->c_cc[TARGET_VSTOP] = host->c_cc[VSTOP];
2391 target->c_cc[TARGET_VSUSP] = host->c_cc[VSUSP];
2392 target->c_cc[TARGET_VEOL] = host->c_cc[VEOL];
2393 target->c_cc[TARGET_VREPRINT] = host->c_cc[VREPRINT];
2394 target->c_cc[TARGET_VDISCARD] = host->c_cc[VDISCARD];
2395 target->c_cc[TARGET_VWERASE] = host->c_cc[VWERASE];
2396 target->c_cc[TARGET_VLNEXT] = host->c_cc[VLNEXT];
2397 target->c_cc[TARGET_VEOL2] = host->c_cc[VEOL2];
2398}
2399
blueswir18e853dc2008-10-05 10:49:32 +00002400static const StructEntry struct_termios_def = {
bellard31e31b82003-02-18 22:55:36 +00002401 .convert = { host_to_target_termios, target_to_host_termios },
2402 .size = { sizeof(struct target_termios), sizeof(struct host_termios) },
2403 .align = { __alignof__(struct target_termios), __alignof__(struct host_termios) },
2404};
2405
bellard5286db72003-06-05 00:57:30 +00002406static bitmask_transtbl mmap_flags_tbl[] = {
2407 { TARGET_MAP_SHARED, TARGET_MAP_SHARED, MAP_SHARED, MAP_SHARED },
2408 { TARGET_MAP_PRIVATE, TARGET_MAP_PRIVATE, MAP_PRIVATE, MAP_PRIVATE },
2409 { TARGET_MAP_FIXED, TARGET_MAP_FIXED, MAP_FIXED, MAP_FIXED },
2410 { TARGET_MAP_ANONYMOUS, TARGET_MAP_ANONYMOUS, MAP_ANONYMOUS, MAP_ANONYMOUS },
2411 { TARGET_MAP_GROWSDOWN, TARGET_MAP_GROWSDOWN, MAP_GROWSDOWN, MAP_GROWSDOWN },
2412 { TARGET_MAP_DENYWRITE, TARGET_MAP_DENYWRITE, MAP_DENYWRITE, MAP_DENYWRITE },
2413 { TARGET_MAP_EXECUTABLE, TARGET_MAP_EXECUTABLE, MAP_EXECUTABLE, MAP_EXECUTABLE },
2414 { TARGET_MAP_LOCKED, TARGET_MAP_LOCKED, MAP_LOCKED, MAP_LOCKED },
2415 { 0, 0, 0, 0 }
2416};
2417
bellardffa65c32004-01-04 23:57:22 +00002418static bitmask_transtbl fcntl_flags_tbl[] = {
2419 { TARGET_O_ACCMODE, TARGET_O_WRONLY, O_ACCMODE, O_WRONLY, },
2420 { TARGET_O_ACCMODE, TARGET_O_RDWR, O_ACCMODE, O_RDWR, },
2421 { TARGET_O_CREAT, TARGET_O_CREAT, O_CREAT, O_CREAT, },
2422 { TARGET_O_EXCL, TARGET_O_EXCL, O_EXCL, O_EXCL, },
2423 { TARGET_O_NOCTTY, TARGET_O_NOCTTY, O_NOCTTY, O_NOCTTY, },
2424 { TARGET_O_TRUNC, TARGET_O_TRUNC, O_TRUNC, O_TRUNC, },
2425 { TARGET_O_APPEND, TARGET_O_APPEND, O_APPEND, O_APPEND, },
2426 { TARGET_O_NONBLOCK, TARGET_O_NONBLOCK, O_NONBLOCK, O_NONBLOCK, },
2427 { TARGET_O_SYNC, TARGET_O_SYNC, O_SYNC, O_SYNC, },
2428 { TARGET_FASYNC, TARGET_FASYNC, FASYNC, FASYNC, },
2429 { TARGET_O_DIRECTORY, TARGET_O_DIRECTORY, O_DIRECTORY, O_DIRECTORY, },
2430 { TARGET_O_NOFOLLOW, TARGET_O_NOFOLLOW, O_NOFOLLOW, O_NOFOLLOW, },
2431 { TARGET_O_LARGEFILE, TARGET_O_LARGEFILE, O_LARGEFILE, O_LARGEFILE, },
bellard121061d2004-02-22 11:56:01 +00002432#if defined(O_DIRECT)
bellardffa65c32004-01-04 23:57:22 +00002433 { TARGET_O_DIRECT, TARGET_O_DIRECT, O_DIRECT, O_DIRECT, },
bellard121061d2004-02-22 11:56:01 +00002434#endif
bellardffa65c32004-01-04 23:57:22 +00002435 { 0, 0, 0, 0 }
2436};
2437
bellard2ab83ea2003-06-15 19:56:46 +00002438#if defined(TARGET_I386)
bellard6dbad632003-03-16 18:05:05 +00002439
2440/* NOTE: there is really one LDT for all the threads */
2441uint8_t *ldt_table;
2442
bellard03acab62007-11-11 14:57:14 +00002443static abi_long read_ldt(abi_ulong ptr, unsigned long bytecount)
bellard6dbad632003-03-16 18:05:05 +00002444{
2445 int size;
pbrook53a59602006-03-25 19:31:22 +00002446 void *p;
bellard6dbad632003-03-16 18:05:05 +00002447
2448 if (!ldt_table)
2449 return 0;
2450 size = TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE;
2451 if (size > bytecount)
2452 size = bytecount;
bellard579a97f2007-11-11 14:26:47 +00002453 p = lock_user(VERIFY_WRITE, ptr, size, 0);
2454 if (!p)
bellard03acab62007-11-11 14:57:14 +00002455 return -TARGET_EFAULT;
bellard579a97f2007-11-11 14:26:47 +00002456 /* ??? Should this by byteswapped? */
pbrook53a59602006-03-25 19:31:22 +00002457 memcpy(p, ldt_table, size);
2458 unlock_user(p, ptr, size);
bellard6dbad632003-03-16 18:05:05 +00002459 return size;
2460}
2461
2462/* XXX: add locking support */
bellard03acab62007-11-11 14:57:14 +00002463static abi_long write_ldt(CPUX86State *env,
2464 abi_ulong ptr, unsigned long bytecount, int oldmode)
bellard6dbad632003-03-16 18:05:05 +00002465{
2466 struct target_modify_ldt_ldt_s ldt_info;
pbrook53a59602006-03-25 19:31:22 +00002467 struct target_modify_ldt_ldt_s *target_ldt_info;
bellard6dbad632003-03-16 18:05:05 +00002468 int seg_32bit, contents, read_exec_only, limit_in_pages;
bellard8d18e892007-11-14 15:18:40 +00002469 int seg_not_present, useable, lm;
bellard6dbad632003-03-16 18:05:05 +00002470 uint32_t *lp, entry_1, entry_2;
2471
2472 if (bytecount != sizeof(ldt_info))
bellard03acab62007-11-11 14:57:14 +00002473 return -TARGET_EINVAL;
bellard579a97f2007-11-11 14:26:47 +00002474 if (!lock_user_struct(VERIFY_READ, target_ldt_info, ptr, 1))
bellard03acab62007-11-11 14:57:14 +00002475 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00002476 ldt_info.entry_number = tswap32(target_ldt_info->entry_number);
2477 ldt_info.base_addr = tswapl(target_ldt_info->base_addr);
2478 ldt_info.limit = tswap32(target_ldt_info->limit);
2479 ldt_info.flags = tswap32(target_ldt_info->flags);
2480 unlock_user_struct(target_ldt_info, ptr, 0);
ths3b46e622007-09-17 08:09:54 +00002481
bellard6dbad632003-03-16 18:05:05 +00002482 if (ldt_info.entry_number >= TARGET_LDT_ENTRIES)
bellard03acab62007-11-11 14:57:14 +00002483 return -TARGET_EINVAL;
bellard6dbad632003-03-16 18:05:05 +00002484 seg_32bit = ldt_info.flags & 1;
2485 contents = (ldt_info.flags >> 1) & 3;
2486 read_exec_only = (ldt_info.flags >> 3) & 1;
2487 limit_in_pages = (ldt_info.flags >> 4) & 1;
2488 seg_not_present = (ldt_info.flags >> 5) & 1;
2489 useable = (ldt_info.flags >> 6) & 1;
bellard8d18e892007-11-14 15:18:40 +00002490#ifdef TARGET_ABI32
2491 lm = 0;
2492#else
2493 lm = (ldt_info.flags >> 7) & 1;
2494#endif
bellard6dbad632003-03-16 18:05:05 +00002495 if (contents == 3) {
2496 if (oldmode)
bellard03acab62007-11-11 14:57:14 +00002497 return -TARGET_EINVAL;
bellard6dbad632003-03-16 18:05:05 +00002498 if (seg_not_present == 0)
bellard03acab62007-11-11 14:57:14 +00002499 return -TARGET_EINVAL;
bellard6dbad632003-03-16 18:05:05 +00002500 }
2501 /* allocate the LDT */
2502 if (!ldt_table) {
2503 ldt_table = malloc(TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE);
2504 if (!ldt_table)
bellard03acab62007-11-11 14:57:14 +00002505 return -TARGET_ENOMEM;
bellard6dbad632003-03-16 18:05:05 +00002506 memset(ldt_table, 0, TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE);
bellardeeeac3f2007-11-11 19:34:32 +00002507 env->ldt.base = h2g((unsigned long)ldt_table);
bellard6dbad632003-03-16 18:05:05 +00002508 env->ldt.limit = 0xffff;
2509 }
2510
2511 /* NOTE: same code as Linux kernel */
2512 /* Allow LDTs to be cleared by the user. */
2513 if (ldt_info.base_addr == 0 && ldt_info.limit == 0) {
2514 if (oldmode ||
2515 (contents == 0 &&
2516 read_exec_only == 1 &&
2517 seg_32bit == 0 &&
2518 limit_in_pages == 0 &&
2519 seg_not_present == 1 &&
2520 useable == 0 )) {
2521 entry_1 = 0;
2522 entry_2 = 0;
2523 goto install;
2524 }
2525 }
ths3b46e622007-09-17 08:09:54 +00002526
bellard6dbad632003-03-16 18:05:05 +00002527 entry_1 = ((ldt_info.base_addr & 0x0000ffff) << 16) |
2528 (ldt_info.limit & 0x0ffff);
2529 entry_2 = (ldt_info.base_addr & 0xff000000) |
2530 ((ldt_info.base_addr & 0x00ff0000) >> 16) |
2531 (ldt_info.limit & 0xf0000) |
2532 ((read_exec_only ^ 1) << 9) |
2533 (contents << 10) |
2534 ((seg_not_present ^ 1) << 15) |
2535 (seg_32bit << 22) |
2536 (limit_in_pages << 23) |
bellard8d18e892007-11-14 15:18:40 +00002537 (lm << 21) |
bellard6dbad632003-03-16 18:05:05 +00002538 0x7000;
2539 if (!oldmode)
2540 entry_2 |= (useable << 20);
bellard14ae3ba2003-05-27 23:25:06 +00002541
bellard6dbad632003-03-16 18:05:05 +00002542 /* Install the new entry ... */
2543install:
2544 lp = (uint32_t *)(ldt_table + (ldt_info.entry_number << 3));
2545 lp[0] = tswap32(entry_1);
2546 lp[1] = tswap32(entry_2);
2547 return 0;
2548}
2549
2550/* specific and weird i386 syscalls */
blueswir18fcd3692008-08-17 20:26:25 +00002551static abi_long do_modify_ldt(CPUX86State *env, int func, abi_ulong ptr,
2552 unsigned long bytecount)
bellard6dbad632003-03-16 18:05:05 +00002553{
bellard03acab62007-11-11 14:57:14 +00002554 abi_long ret;
ths3b46e622007-09-17 08:09:54 +00002555
bellard6dbad632003-03-16 18:05:05 +00002556 switch (func) {
2557 case 0:
2558 ret = read_ldt(ptr, bytecount);
2559 break;
2560 case 1:
2561 ret = write_ldt(env, ptr, bytecount, 1);
2562 break;
2563 case 0x11:
2564 ret = write_ldt(env, ptr, bytecount, 0);
2565 break;
bellard03acab62007-11-11 14:57:14 +00002566 default:
2567 ret = -TARGET_ENOSYS;
2568 break;
bellard6dbad632003-03-16 18:05:05 +00002569 }
2570 return ret;
2571}
bellard1b6b0292003-03-22 17:31:38 +00002572
blueswir14583f582008-08-24 10:35:55 +00002573#if defined(TARGET_I386) && defined(TARGET_ABI32)
blueswir18fcd3692008-08-17 20:26:25 +00002574static abi_long do_set_thread_area(CPUX86State *env, abi_ulong ptr)
bellard8d18e892007-11-14 15:18:40 +00002575{
2576 uint64_t *gdt_table = g2h(env->gdt.base);
2577 struct target_modify_ldt_ldt_s ldt_info;
2578 struct target_modify_ldt_ldt_s *target_ldt_info;
2579 int seg_32bit, contents, read_exec_only, limit_in_pages;
2580 int seg_not_present, useable, lm;
2581 uint32_t *lp, entry_1, entry_2;
2582 int i;
2583
2584 lock_user_struct(VERIFY_WRITE, target_ldt_info, ptr, 1);
2585 if (!target_ldt_info)
2586 return -TARGET_EFAULT;
2587 ldt_info.entry_number = tswap32(target_ldt_info->entry_number);
2588 ldt_info.base_addr = tswapl(target_ldt_info->base_addr);
2589 ldt_info.limit = tswap32(target_ldt_info->limit);
2590 ldt_info.flags = tswap32(target_ldt_info->flags);
2591 if (ldt_info.entry_number == -1) {
2592 for (i=TARGET_GDT_ENTRY_TLS_MIN; i<=TARGET_GDT_ENTRY_TLS_MAX; i++) {
2593 if (gdt_table[i] == 0) {
2594 ldt_info.entry_number = i;
2595 target_ldt_info->entry_number = tswap32(i);
2596 break;
2597 }
2598 }
2599 }
2600 unlock_user_struct(target_ldt_info, ptr, 1);
2601
2602 if (ldt_info.entry_number < TARGET_GDT_ENTRY_TLS_MIN ||
2603 ldt_info.entry_number > TARGET_GDT_ENTRY_TLS_MAX)
2604 return -TARGET_EINVAL;
2605 seg_32bit = ldt_info.flags & 1;
2606 contents = (ldt_info.flags >> 1) & 3;
2607 read_exec_only = (ldt_info.flags >> 3) & 1;
2608 limit_in_pages = (ldt_info.flags >> 4) & 1;
2609 seg_not_present = (ldt_info.flags >> 5) & 1;
2610 useable = (ldt_info.flags >> 6) & 1;
2611#ifdef TARGET_ABI32
2612 lm = 0;
2613#else
2614 lm = (ldt_info.flags >> 7) & 1;
2615#endif
2616
2617 if (contents == 3) {
2618 if (seg_not_present == 0)
2619 return -TARGET_EINVAL;
2620 }
2621
2622 /* NOTE: same code as Linux kernel */
2623 /* Allow LDTs to be cleared by the user. */
2624 if (ldt_info.base_addr == 0 && ldt_info.limit == 0) {
2625 if ((contents == 0 &&
2626 read_exec_only == 1 &&
2627 seg_32bit == 0 &&
2628 limit_in_pages == 0 &&
2629 seg_not_present == 1 &&
2630 useable == 0 )) {
2631 entry_1 = 0;
2632 entry_2 = 0;
2633 goto install;
2634 }
2635 }
2636
2637 entry_1 = ((ldt_info.base_addr & 0x0000ffff) << 16) |
2638 (ldt_info.limit & 0x0ffff);
2639 entry_2 = (ldt_info.base_addr & 0xff000000) |
2640 ((ldt_info.base_addr & 0x00ff0000) >> 16) |
2641 (ldt_info.limit & 0xf0000) |
2642 ((read_exec_only ^ 1) << 9) |
2643 (contents << 10) |
2644 ((seg_not_present ^ 1) << 15) |
2645 (seg_32bit << 22) |
2646 (limit_in_pages << 23) |
2647 (useable << 20) |
2648 (lm << 21) |
2649 0x7000;
2650
2651 /* Install the new entry ... */
2652install:
2653 lp = (uint32_t *)(gdt_table + ldt_info.entry_number);
2654 lp[0] = tswap32(entry_1);
2655 lp[1] = tswap32(entry_2);
2656 return 0;
2657}
2658
blueswir18fcd3692008-08-17 20:26:25 +00002659static abi_long do_get_thread_area(CPUX86State *env, abi_ulong ptr)
bellard8d18e892007-11-14 15:18:40 +00002660{
2661 struct target_modify_ldt_ldt_s *target_ldt_info;
2662 uint64_t *gdt_table = g2h(env->gdt.base);
2663 uint32_t base_addr, limit, flags;
2664 int seg_32bit, contents, read_exec_only, limit_in_pages, idx;
2665 int seg_not_present, useable, lm;
2666 uint32_t *lp, entry_1, entry_2;
2667
2668 lock_user_struct(VERIFY_WRITE, target_ldt_info, ptr, 1);
2669 if (!target_ldt_info)
2670 return -TARGET_EFAULT;
2671 idx = tswap32(target_ldt_info->entry_number);
2672 if (idx < TARGET_GDT_ENTRY_TLS_MIN ||
2673 idx > TARGET_GDT_ENTRY_TLS_MAX) {
2674 unlock_user_struct(target_ldt_info, ptr, 1);
2675 return -TARGET_EINVAL;
2676 }
2677 lp = (uint32_t *)(gdt_table + idx);
2678 entry_1 = tswap32(lp[0]);
2679 entry_2 = tswap32(lp[1]);
2680
2681 read_exec_only = ((entry_2 >> 9) & 1) ^ 1;
2682 contents = (entry_2 >> 10) & 3;
2683 seg_not_present = ((entry_2 >> 15) & 1) ^ 1;
2684 seg_32bit = (entry_2 >> 22) & 1;
2685 limit_in_pages = (entry_2 >> 23) & 1;
2686 useable = (entry_2 >> 20) & 1;
2687#ifdef TARGET_ABI32
2688 lm = 0;
2689#else
2690 lm = (entry_2 >> 21) & 1;
2691#endif
2692 flags = (seg_32bit << 0) | (contents << 1) |
2693 (read_exec_only << 3) | (limit_in_pages << 4) |
2694 (seg_not_present << 5) | (useable << 6) | (lm << 7);
2695 limit = (entry_1 & 0xffff) | (entry_2 & 0xf0000);
2696 base_addr = (entry_1 >> 16) |
2697 (entry_2 & 0xff000000) |
2698 ((entry_2 & 0xff) << 16);
2699 target_ldt_info->base_addr = tswapl(base_addr);
2700 target_ldt_info->limit = tswap32(limit);
2701 target_ldt_info->flags = tswap32(flags);
2702 unlock_user_struct(target_ldt_info, ptr, 1);
2703 return 0;
2704}
blueswir14583f582008-08-24 10:35:55 +00002705#endif /* TARGET_I386 && TARGET_ABI32 */
bellard8d18e892007-11-14 15:18:40 +00002706
bellardd2fd1af2007-11-14 18:08:56 +00002707#ifndef TARGET_ABI32
blueswir18fcd3692008-08-17 20:26:25 +00002708static abi_long do_arch_prctl(CPUX86State *env, int code, abi_ulong addr)
bellardd2fd1af2007-11-14 18:08:56 +00002709{
2710 abi_long ret;
2711 abi_ulong val;
2712 int idx;
2713
2714 switch(code) {
2715 case TARGET_ARCH_SET_GS:
2716 case TARGET_ARCH_SET_FS:
2717 if (code == TARGET_ARCH_SET_GS)
2718 idx = R_GS;
2719 else
2720 idx = R_FS;
2721 cpu_x86_load_seg(env, idx, 0);
2722 env->segs[idx].base = addr;
2723 break;
2724 case TARGET_ARCH_GET_GS:
2725 case TARGET_ARCH_GET_FS:
2726 if (code == TARGET_ARCH_GET_GS)
2727 idx = R_GS;
2728 else
2729 idx = R_FS;
2730 val = env->segs[idx].base;
2731 if (put_user(val, addr, abi_ulong))
2732 return -TARGET_EFAULT;
2733 break;
2734 default:
2735 ret = -TARGET_EINVAL;
2736 break;
2737 }
2738 return 0;
2739}
2740#endif
2741
bellard2ab83ea2003-06-15 19:56:46 +00002742#endif /* defined(TARGET_I386) */
2743
pbrookd865bab2008-06-07 22:12:17 +00002744#if defined(USE_NPTL)
2745
2746#define NEW_STACK_SIZE PTHREAD_STACK_MIN
2747
2748static pthread_mutex_t clone_lock = PTHREAD_MUTEX_INITIALIZER;
2749typedef struct {
2750 CPUState *env;
2751 pthread_mutex_t mutex;
2752 pthread_cond_t cond;
2753 pthread_t thread;
2754 uint32_t tid;
2755 abi_ulong child_tidptr;
2756 abi_ulong parent_tidptr;
2757 sigset_t sigmask;
2758} new_thread_info;
2759
2760static void *clone_func(void *arg)
2761{
2762 new_thread_info *info = arg;
2763 CPUState *env;
2764
2765 env = info->env;
2766 thread_env = env;
2767 info->tid = gettid();
2768 if (info->child_tidptr)
2769 put_user_u32(info->tid, info->child_tidptr);
2770 if (info->parent_tidptr)
2771 put_user_u32(info->tid, info->parent_tidptr);
2772 /* Enable signals. */
2773 sigprocmask(SIG_SETMASK, &info->sigmask, NULL);
2774 /* Signal to the parent that we're ready. */
2775 pthread_mutex_lock(&info->mutex);
2776 pthread_cond_broadcast(&info->cond);
2777 pthread_mutex_unlock(&info->mutex);
2778 /* Wait until the parent has finshed initializing the tls state. */
2779 pthread_mutex_lock(&clone_lock);
2780 pthread_mutex_unlock(&clone_lock);
2781 cpu_loop(env);
2782 /* never exits */
2783 return NULL;
2784}
2785#else
bellard1b6b0292003-03-22 17:31:38 +00002786/* this stack is the equivalent of the kernel stack associated with a
2787 thread/process */
2788#define NEW_STACK_SIZE 8192
2789
2790static int clone_func(void *arg)
2791{
bellard2ab83ea2003-06-15 19:56:46 +00002792 CPUState *env = arg;
bellard1b6b0292003-03-22 17:31:38 +00002793 cpu_loop(env);
2794 /* never exits */
2795 return 0;
2796}
pbrookd865bab2008-06-07 22:12:17 +00002797#endif
bellard1b6b0292003-03-22 17:31:38 +00002798
ths0da46a62007-10-20 20:23:07 +00002799/* do_fork() Must return host values and target errnos (unlike most
2800 do_*() functions). */
pbrookd865bab2008-06-07 22:12:17 +00002801static int do_fork(CPUState *env, unsigned int flags, abi_ulong newsp,
2802 abi_ulong parent_tidptr, target_ulong newtls,
2803 abi_ulong child_tidptr)
bellard1b6b0292003-03-22 17:31:38 +00002804{
2805 int ret;
bellard5cd43932003-03-29 16:54:36 +00002806 TaskState *ts;
bellard1b6b0292003-03-22 17:31:38 +00002807 uint8_t *new_stack;
bellard2ab83ea2003-06-15 19:56:46 +00002808 CPUState *new_env;
pbrookd865bab2008-06-07 22:12:17 +00002809#if defined(USE_NPTL)
2810 unsigned int nptl_flags;
2811 sigset_t sigmask;
2812#endif
ths3b46e622007-09-17 08:09:54 +00002813
balrog436d1242008-09-21 02:39:45 +00002814 /* Emulate vfork() with fork() */
2815 if (flags & CLONE_VFORK)
2816 flags &= ~(CLONE_VFORK | CLONE_VM);
2817
bellard1b6b0292003-03-22 17:31:38 +00002818 if (flags & CLONE_VM) {
pbrookbd0c5662008-05-29 14:34:11 +00002819#if defined(USE_NPTL)
pbrookd865bab2008-06-07 22:12:17 +00002820 new_thread_info info;
2821 pthread_attr_t attr;
pbrookbd0c5662008-05-29 14:34:11 +00002822#endif
pbrookc3a92832008-06-09 14:02:50 +00002823 ts = qemu_mallocz(sizeof(TaskState) + NEW_STACK_SIZE);
pbrook624f7972008-05-31 16:11:38 +00002824 init_task_state(ts);
bellard5cd43932003-03-29 16:54:36 +00002825 new_stack = ts->stack;
bellard1b6b0292003-03-22 17:31:38 +00002826 /* we create a new CPU instance. */
thsc5be9f02007-02-28 20:20:53 +00002827 new_env = cpu_copy(env);
pbrook6e68e072008-05-30 17:22:15 +00002828 /* Init regs that differ from the parent. */
2829 cpu_clone_regs(new_env, newsp);
bellard5cd43932003-03-29 16:54:36 +00002830 new_env->opaque = ts;
pbrookd865bab2008-06-07 22:12:17 +00002831#if defined(USE_NPTL)
2832 nptl_flags = flags;
2833 flags &= ~CLONE_NPTL_FLAGS2;
2834
2835 /* TODO: Implement CLONE_CHILD_CLEARTID. */
2836 if (nptl_flags & CLONE_SETTLS)
2837 cpu_set_tls (new_env, newtls);
2838
2839 /* Grab a mutex so that thread setup appears atomic. */
2840 pthread_mutex_lock(&clone_lock);
2841
2842 memset(&info, 0, sizeof(info));
2843 pthread_mutex_init(&info.mutex, NULL);
2844 pthread_mutex_lock(&info.mutex);
2845 pthread_cond_init(&info.cond, NULL);
2846 info.env = new_env;
2847 if (nptl_flags & CLONE_CHILD_SETTID)
2848 info.child_tidptr = child_tidptr;
2849 if (nptl_flags & CLONE_PARENT_SETTID)
2850 info.parent_tidptr = parent_tidptr;
2851
2852 ret = pthread_attr_init(&attr);
2853 ret = pthread_attr_setstack(&attr, new_stack, NEW_STACK_SIZE);
2854 /* It is not safe to deliver signals until the child has finished
2855 initializing, so temporarily block all signals. */
2856 sigfillset(&sigmask);
2857 sigprocmask(SIG_BLOCK, &sigmask, &info.sigmask);
2858
2859 ret = pthread_create(&info.thread, &attr, clone_func, &info);
2860
2861 sigprocmask(SIG_SETMASK, &info.sigmask, NULL);
2862 pthread_attr_destroy(&attr);
2863 if (ret == 0) {
2864 /* Wait for the child to initialize. */
2865 pthread_cond_wait(&info.cond, &info.mutex);
2866 ret = info.tid;
2867 if (flags & CLONE_PARENT_SETTID)
2868 put_user_u32(ret, parent_tidptr);
2869 } else {
2870 ret = -1;
2871 }
2872 pthread_mutex_unlock(&info.mutex);
2873 pthread_cond_destroy(&info.cond);
2874 pthread_mutex_destroy(&info.mutex);
2875 pthread_mutex_unlock(&clone_lock);
2876#else
2877 if (flags & CLONE_NPTL_FLAGS2)
2878 return -EINVAL;
2879 /* This is probably going to die very quickly, but do it anyway. */
bellard27725c12003-04-29 21:08:18 +00002880#ifdef __ia64__
bellardfd4a43e2006-04-24 20:32:17 +00002881 ret = __clone2(clone_func, new_stack + NEW_STACK_SIZE, flags, new_env);
bellard27725c12003-04-29 21:08:18 +00002882#else
2883 ret = clone(clone_func, new_stack + NEW_STACK_SIZE, flags, new_env);
2884#endif
pbrookd865bab2008-06-07 22:12:17 +00002885#endif
bellard1b6b0292003-03-22 17:31:38 +00002886 } else {
2887 /* if no CLONE_VM, we consider it is a fork */
pbrookd865bab2008-06-07 22:12:17 +00002888 if ((flags & ~(CSIGNAL | CLONE_NPTL_FLAGS2)) != 0)
bellard1b6b0292003-03-22 17:31:38 +00002889 return -EINVAL;
pbrookd865bab2008-06-07 22:12:17 +00002890 fork_start();
bellard1b6b0292003-03-22 17:31:38 +00002891 ret = fork();
pbrookd865bab2008-06-07 22:12:17 +00002892#if defined(USE_NPTL)
2893 /* There is a race condition here. The parent process could
2894 theoretically read the TID in the child process before the child
2895 tid is set. This would require using either ptrace
2896 (not implemented) or having *_tidptr to point at a shared memory
2897 mapping. We can't repeat the spinlock hack used above because
2898 the child process gets its own copy of the lock. */
2899 if (ret == 0) {
2900 cpu_clone_regs(env, newsp);
2901 fork_end(1);
2902 /* Child Process. */
2903 if (flags & CLONE_CHILD_SETTID)
2904 put_user_u32(gettid(), child_tidptr);
2905 if (flags & CLONE_PARENT_SETTID)
2906 put_user_u32(gettid(), parent_tidptr);
2907 ts = (TaskState *)env->opaque;
2908 if (flags & CLONE_SETTLS)
2909 cpu_set_tls (env, newtls);
2910 /* TODO: Implement CLONE_CHILD_CLEARTID. */
2911 } else {
2912 fork_end(0);
2913 }
2914#else
pbrook6e68e072008-05-30 17:22:15 +00002915 if (ret == 0) {
2916 cpu_clone_regs(env, newsp);
2917 }
pbrookd865bab2008-06-07 22:12:17 +00002918#endif
bellard1b6b0292003-03-22 17:31:38 +00002919 }
2920 return ret;
2921}
2922
blueswir1992f48a2007-10-14 16:27:31 +00002923static abi_long do_fcntl(int fd, int cmd, abi_ulong arg)
bellard7775e9e2003-05-14 22:46:48 +00002924{
2925 struct flock fl;
pbrook53a59602006-03-25 19:31:22 +00002926 struct target_flock *target_fl;
ths43f238d2007-01-05 20:55:49 +00002927 struct flock64 fl64;
2928 struct target_flock64 *target_fl64;
blueswir1992f48a2007-10-14 16:27:31 +00002929 abi_long ret;
pbrook53a59602006-03-25 19:31:22 +00002930
bellard7775e9e2003-05-14 22:46:48 +00002931 switch(cmd) {
2932 case TARGET_F_GETLK:
bellard579a97f2007-11-11 14:26:47 +00002933 if (!lock_user_struct(VERIFY_READ, target_fl, arg, 1))
2934 return -TARGET_EFAULT;
ths58134272007-03-31 18:59:32 +00002935 fl.l_type = tswap16(target_fl->l_type);
2936 fl.l_whence = tswap16(target_fl->l_whence);
2937 fl.l_start = tswapl(target_fl->l_start);
2938 fl.l_len = tswapl(target_fl->l_len);
2939 fl.l_pid = tswapl(target_fl->l_pid);
2940 unlock_user_struct(target_fl, arg, 0);
bellard9ee1fa22007-11-11 15:11:19 +00002941 ret = get_errno(fcntl(fd, cmd, &fl));
bellard7775e9e2003-05-14 22:46:48 +00002942 if (ret == 0) {
bellard579a97f2007-11-11 14:26:47 +00002943 if (!lock_user_struct(VERIFY_WRITE, target_fl, arg, 0))
2944 return -TARGET_EFAULT;
bellard7775e9e2003-05-14 22:46:48 +00002945 target_fl->l_type = tswap16(fl.l_type);
2946 target_fl->l_whence = tswap16(fl.l_whence);
2947 target_fl->l_start = tswapl(fl.l_start);
2948 target_fl->l_len = tswapl(fl.l_len);
2949 target_fl->l_pid = tswapl(fl.l_pid);
pbrook53a59602006-03-25 19:31:22 +00002950 unlock_user_struct(target_fl, arg, 1);
bellard7775e9e2003-05-14 22:46:48 +00002951 }
2952 break;
ths3b46e622007-09-17 08:09:54 +00002953
bellard7775e9e2003-05-14 22:46:48 +00002954 case TARGET_F_SETLK:
2955 case TARGET_F_SETLKW:
bellard579a97f2007-11-11 14:26:47 +00002956 if (!lock_user_struct(VERIFY_READ, target_fl, arg, 1))
2957 return -TARGET_EFAULT;
bellard7775e9e2003-05-14 22:46:48 +00002958 fl.l_type = tswap16(target_fl->l_type);
2959 fl.l_whence = tswap16(target_fl->l_whence);
2960 fl.l_start = tswapl(target_fl->l_start);
2961 fl.l_len = tswapl(target_fl->l_len);
2962 fl.l_pid = tswapl(target_fl->l_pid);
pbrook53a59602006-03-25 19:31:22 +00002963 unlock_user_struct(target_fl, arg, 0);
bellard9ee1fa22007-11-11 15:11:19 +00002964 ret = get_errno(fcntl(fd, cmd, &fl));
bellard7775e9e2003-05-14 22:46:48 +00002965 break;
ths3b46e622007-09-17 08:09:54 +00002966
bellard7775e9e2003-05-14 22:46:48 +00002967 case TARGET_F_GETLK64:
bellard579a97f2007-11-11 14:26:47 +00002968 if (!lock_user_struct(VERIFY_READ, target_fl64, arg, 1))
2969 return -TARGET_EFAULT;
ths58134272007-03-31 18:59:32 +00002970 fl64.l_type = tswap16(target_fl64->l_type) >> 1;
2971 fl64.l_whence = tswap16(target_fl64->l_whence);
2972 fl64.l_start = tswapl(target_fl64->l_start);
2973 fl64.l_len = tswapl(target_fl64->l_len);
2974 fl64.l_pid = tswap16(target_fl64->l_pid);
2975 unlock_user_struct(target_fl64, arg, 0);
bellard9ee1fa22007-11-11 15:11:19 +00002976 ret = get_errno(fcntl(fd, cmd >> 1, &fl64));
ths43f238d2007-01-05 20:55:49 +00002977 if (ret == 0) {
bellard579a97f2007-11-11 14:26:47 +00002978 if (!lock_user_struct(VERIFY_WRITE, target_fl64, arg, 0))
2979 return -TARGET_EFAULT;
ths43f238d2007-01-05 20:55:49 +00002980 target_fl64->l_type = tswap16(fl64.l_type) >> 1;
2981 target_fl64->l_whence = tswap16(fl64.l_whence);
2982 target_fl64->l_start = tswapl(fl64.l_start);
2983 target_fl64->l_len = tswapl(fl64.l_len);
2984 target_fl64->l_pid = tswapl(fl64.l_pid);
2985 unlock_user_struct(target_fl64, arg, 1);
2986 }
bellard9ee1fa22007-11-11 15:11:19 +00002987 break;
bellard7775e9e2003-05-14 22:46:48 +00002988 case TARGET_F_SETLK64:
2989 case TARGET_F_SETLKW64:
bellard579a97f2007-11-11 14:26:47 +00002990 if (!lock_user_struct(VERIFY_READ, target_fl64, arg, 1))
2991 return -TARGET_EFAULT;
ths43f238d2007-01-05 20:55:49 +00002992 fl64.l_type = tswap16(target_fl64->l_type) >> 1;
2993 fl64.l_whence = tswap16(target_fl64->l_whence);
2994 fl64.l_start = tswapl(target_fl64->l_start);
2995 fl64.l_len = tswapl(target_fl64->l_len);
2996 fl64.l_pid = tswap16(target_fl64->l_pid);
2997 unlock_user_struct(target_fl64, arg, 0);
bellard9ee1fa22007-11-11 15:11:19 +00002998 ret = get_errno(fcntl(fd, cmd >> 1, &fl64));
bellard7775e9e2003-05-14 22:46:48 +00002999 break;
3000
bellardffa65c32004-01-04 23:57:22 +00003001 case F_GETFL:
bellard9ee1fa22007-11-11 15:11:19 +00003002 ret = get_errno(fcntl(fd, cmd, arg));
3003 if (ret >= 0) {
3004 ret = host_to_target_bitmask(ret, fcntl_flags_tbl);
3005 }
bellardffa65c32004-01-04 23:57:22 +00003006 break;
3007
3008 case F_SETFL:
bellard9ee1fa22007-11-11 15:11:19 +00003009 ret = get_errno(fcntl(fd, cmd, target_to_host_bitmask(arg, fcntl_flags_tbl)));
bellardffa65c32004-01-04 23:57:22 +00003010 break;
3011
bellard7775e9e2003-05-14 22:46:48 +00003012 default:
bellard9ee1fa22007-11-11 15:11:19 +00003013 ret = get_errno(fcntl(fd, cmd, arg));
bellard7775e9e2003-05-14 22:46:48 +00003014 break;
3015 }
3016 return ret;
3017}
3018
bellard67867302003-11-23 17:05:30 +00003019#ifdef USE_UID16
bellard7775e9e2003-05-14 22:46:48 +00003020
bellard67867302003-11-23 17:05:30 +00003021static inline int high2lowuid(int uid)
3022{
3023 if (uid > 65535)
3024 return 65534;
3025 else
3026 return uid;
3027}
3028
3029static inline int high2lowgid(int gid)
3030{
3031 if (gid > 65535)
3032 return 65534;
3033 else
3034 return gid;
3035}
3036
3037static inline int low2highuid(int uid)
3038{
3039 if ((int16_t)uid == -1)
3040 return -1;
3041 else
3042 return uid;
3043}
3044
3045static inline int low2highgid(int gid)
3046{
3047 if ((int16_t)gid == -1)
3048 return -1;
3049 else
3050 return gid;
3051}
3052
3053#endif /* USE_UID16 */
bellard1b6b0292003-03-22 17:31:38 +00003054
bellard31e31b82003-02-18 22:55:36 +00003055void syscall_init(void)
3056{
bellard2ab83ea2003-06-15 19:56:46 +00003057 IOCTLEntry *ie;
3058 const argtype *arg_type;
3059 int size;
thsb92c47c2007-11-01 00:07:38 +00003060 int i;
bellard2ab83ea2003-06-15 19:56:46 +00003061
ths5fafdf22007-09-16 21:08:06 +00003062#define STRUCT(name, list...) thunk_register_struct(STRUCT_ ## name, #name, struct_ ## name ## _def);
3063#define STRUCT_SPECIAL(name) thunk_register_struct_direct(STRUCT_ ## name, #name, &struct_ ## name ## _def);
bellard31e31b82003-02-18 22:55:36 +00003064#include "syscall_types.h"
3065#undef STRUCT
3066#undef STRUCT_SPECIAL
bellard2ab83ea2003-06-15 19:56:46 +00003067
3068 /* we patch the ioctl size if necessary. We rely on the fact that
3069 no ioctl has all the bits at '1' in the size field */
3070 ie = ioctl_entries;
3071 while (ie->target_cmd != 0) {
3072 if (((ie->target_cmd >> TARGET_IOC_SIZESHIFT) & TARGET_IOC_SIZEMASK) ==
3073 TARGET_IOC_SIZEMASK) {
3074 arg_type = ie->arg_type;
3075 if (arg_type[0] != TYPE_PTR) {
ths5fafdf22007-09-16 21:08:06 +00003076 fprintf(stderr, "cannot patch size for ioctl 0x%x\n",
bellard2ab83ea2003-06-15 19:56:46 +00003077 ie->target_cmd);
3078 exit(1);
3079 }
3080 arg_type++;
3081 size = thunk_type_size(arg_type, 0);
ths5fafdf22007-09-16 21:08:06 +00003082 ie->target_cmd = (ie->target_cmd &
bellard2ab83ea2003-06-15 19:56:46 +00003083 ~(TARGET_IOC_SIZEMASK << TARGET_IOC_SIZESHIFT)) |
3084 (size << TARGET_IOC_SIZESHIFT);
3085 }
thsb92c47c2007-11-01 00:07:38 +00003086
3087 /* Build target_to_host_errno_table[] table from
3088 * host_to_target_errno_table[]. */
3089 for (i=0; i < ERRNO_TABLE_SIZE; i++)
3090 target_to_host_errno_table[host_to_target_errno_table[i]] = i;
3091
bellard2ab83ea2003-06-15 19:56:46 +00003092 /* automatic consistency check if same arch */
balrog872ea0c2008-09-21 02:31:19 +00003093#if (defined(__i386__) && defined(TARGET_I386) && defined(TARGET_ABI32)) || \
3094 (defined(__x86_64__) && defined(TARGET_X86_64))
3095 if (unlikely(ie->target_cmd != ie->host_cmd)) {
3096 fprintf(stderr, "ERROR: ioctl(%s): target=0x%x host=0x%x\n",
3097 ie->name, ie->target_cmd, ie->host_cmd);
bellard2ab83ea2003-06-15 19:56:46 +00003098 }
3099#endif
3100 ie++;
3101 }
bellard31e31b82003-02-18 22:55:36 +00003102}
bellardc573ff62004-01-04 15:51:36 +00003103
blueswir1992f48a2007-10-14 16:27:31 +00003104#if TARGET_ABI_BITS == 32
pbrookce4defa2006-02-09 16:49:55 +00003105static inline uint64_t target_offset64(uint32_t word0, uint32_t word1)
3106{
thsaf325d32008-06-10 15:29:15 +00003107#ifdef TARGET_WORDS_BIGENDIAN
pbrookce4defa2006-02-09 16:49:55 +00003108 return ((uint64_t)word0 << 32) | word1;
3109#else
3110 return ((uint64_t)word1 << 32) | word0;
3111#endif
3112}
blueswir1992f48a2007-10-14 16:27:31 +00003113#else /* TARGET_ABI_BITS == 32 */
j_mayer32407102007-09-26 23:01:49 +00003114static inline uint64_t target_offset64(uint64_t word0, uint64_t word1)
3115{
3116 return word0;
3117}
blueswir1992f48a2007-10-14 16:27:31 +00003118#endif /* TARGET_ABI_BITS != 32 */
pbrookce4defa2006-02-09 16:49:55 +00003119
3120#ifdef TARGET_NR_truncate64
blueswir1992f48a2007-10-14 16:27:31 +00003121static inline abi_long target_truncate64(void *cpu_env, const char *arg1,
3122 abi_long arg2,
3123 abi_long arg3,
3124 abi_long arg4)
pbrookce4defa2006-02-09 16:49:55 +00003125{
3126#ifdef TARGET_ARM
3127 if (((CPUARMState *)cpu_env)->eabi)
3128 {
3129 arg2 = arg3;
3130 arg3 = arg4;
3131 }
3132#endif
3133 return get_errno(truncate64(arg1, target_offset64(arg2, arg3)));
3134}
3135#endif
3136
3137#ifdef TARGET_NR_ftruncate64
blueswir1992f48a2007-10-14 16:27:31 +00003138static inline abi_long target_ftruncate64(void *cpu_env, abi_long arg1,
3139 abi_long arg2,
3140 abi_long arg3,
3141 abi_long arg4)
pbrookce4defa2006-02-09 16:49:55 +00003142{
3143#ifdef TARGET_ARM
3144 if (((CPUARMState *)cpu_env)->eabi)
3145 {
3146 arg2 = arg3;
3147 arg3 = arg4;
3148 }
3149#endif
3150 return get_errno(ftruncate64(arg1, target_offset64(arg2, arg3)));
3151}
3152#endif
3153
bellard579a97f2007-11-11 14:26:47 +00003154static inline abi_long target_to_host_timespec(struct timespec *host_ts,
3155 abi_ulong target_addr)
pbrook53a59602006-03-25 19:31:22 +00003156{
3157 struct target_timespec *target_ts;
3158
bellard579a97f2007-11-11 14:26:47 +00003159 if (!lock_user_struct(VERIFY_READ, target_ts, target_addr, 1))
3160 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00003161 host_ts->tv_sec = tswapl(target_ts->tv_sec);
3162 host_ts->tv_nsec = tswapl(target_ts->tv_nsec);
3163 unlock_user_struct(target_ts, target_addr, 0);
bellardb255bfa2008-05-10 21:51:02 +00003164 return 0;
pbrook53a59602006-03-25 19:31:22 +00003165}
3166
bellard579a97f2007-11-11 14:26:47 +00003167static inline abi_long host_to_target_timespec(abi_ulong target_addr,
3168 struct timespec *host_ts)
pbrook53a59602006-03-25 19:31:22 +00003169{
3170 struct target_timespec *target_ts;
3171
bellard579a97f2007-11-11 14:26:47 +00003172 if (!lock_user_struct(VERIFY_WRITE, target_ts, target_addr, 0))
3173 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00003174 target_ts->tv_sec = tswapl(host_ts->tv_sec);
3175 target_ts->tv_nsec = tswapl(host_ts->tv_nsec);
3176 unlock_user_struct(target_ts, target_addr, 1);
bellardb255bfa2008-05-10 21:51:02 +00003177 return 0;
pbrook53a59602006-03-25 19:31:22 +00003178}
3179
balrog6a24a772008-09-20 02:23:36 +00003180#ifdef TARGET_NR_stat64
3181static inline abi_long host_to_target_stat64(void *cpu_env,
3182 abi_ulong target_addr,
3183 struct stat *host_st)
3184{
3185#ifdef TARGET_ARM
3186 if (((CPUARMState *)cpu_env)->eabi) {
3187 struct target_eabi_stat64 *target_st;
3188
3189 if (!lock_user_struct(VERIFY_WRITE, target_st, target_addr, 0))
3190 return -TARGET_EFAULT;
3191 memset(target_st, 0, sizeof(struct target_eabi_stat64));
3192 __put_user(host_st->st_dev, &target_st->st_dev);
3193 __put_user(host_st->st_ino, &target_st->st_ino);
3194#ifdef TARGET_STAT64_HAS_BROKEN_ST_INO
3195 __put_user(host_st->st_ino, &target_st->__st_ino);
3196#endif
3197 __put_user(host_st->st_mode, &target_st->st_mode);
3198 __put_user(host_st->st_nlink, &target_st->st_nlink);
3199 __put_user(host_st->st_uid, &target_st->st_uid);
3200 __put_user(host_st->st_gid, &target_st->st_gid);
3201 __put_user(host_st->st_rdev, &target_st->st_rdev);
3202 __put_user(host_st->st_size, &target_st->st_size);
3203 __put_user(host_st->st_blksize, &target_st->st_blksize);
3204 __put_user(host_st->st_blocks, &target_st->st_blocks);
3205 __put_user(host_st->st_atime, &target_st->target_st_atime);
3206 __put_user(host_st->st_mtime, &target_st->target_st_mtime);
3207 __put_user(host_st->st_ctime, &target_st->target_st_ctime);
3208 unlock_user_struct(target_st, target_addr, 1);
3209 } else
3210#endif
3211 {
3212 struct target_stat64 *target_st;
3213
3214 if (!lock_user_struct(VERIFY_WRITE, target_st, target_addr, 0))
3215 return -TARGET_EFAULT;
3216 memset(target_st, 0, sizeof(struct target_stat64));
3217 __put_user(host_st->st_dev, &target_st->st_dev);
3218 __put_user(host_st->st_ino, &target_st->st_ino);
3219#ifdef TARGET_STAT64_HAS_BROKEN_ST_INO
3220 __put_user(host_st->st_ino, &target_st->__st_ino);
3221#endif
3222 __put_user(host_st->st_mode, &target_st->st_mode);
3223 __put_user(host_st->st_nlink, &target_st->st_nlink);
3224 __put_user(host_st->st_uid, &target_st->st_uid);
3225 __put_user(host_st->st_gid, &target_st->st_gid);
3226 __put_user(host_st->st_rdev, &target_st->st_rdev);
3227 /* XXX: better use of kernel struct */
3228 __put_user(host_st->st_size, &target_st->st_size);
3229 __put_user(host_st->st_blksize, &target_st->st_blksize);
3230 __put_user(host_st->st_blocks, &target_st->st_blocks);
3231 __put_user(host_st->st_atime, &target_st->target_st_atime);
3232 __put_user(host_st->st_mtime, &target_st->target_st_mtime);
3233 __put_user(host_st->st_ctime, &target_st->target_st_ctime);
3234 unlock_user_struct(target_st, target_addr, 1);
3235 }
3236
3237 return 0;
3238}
3239#endif
3240
pbrookbd0c5662008-05-29 14:34:11 +00003241#if defined(USE_NPTL)
3242/* ??? Using host futex calls even when target atomic operations
3243 are not really atomic probably breaks things. However implementing
3244 futexes locally would make futexes shared between multiple processes
3245 tricky. However they're probably useless because guest atomic
3246 operations won't work either. */
blueswir18fcd3692008-08-17 20:26:25 +00003247static int do_futex(target_ulong uaddr, int op, int val, target_ulong timeout,
3248 target_ulong uaddr2, int val3)
pbrookbd0c5662008-05-29 14:34:11 +00003249{
3250 struct timespec ts, *pts;
3251
3252 /* ??? We assume FUTEX_* constants are the same on both host
3253 and target. */
3254 switch (op) {
3255 case FUTEX_WAIT:
3256 if (timeout) {
3257 pts = &ts;
3258 target_to_host_timespec(pts, timeout);
3259 } else {
3260 pts = NULL;
3261 }
3262 return get_errno(sys_futex(g2h(uaddr), FUTEX_WAIT, tswap32(val),
3263 pts, NULL, 0));
3264 case FUTEX_WAKE:
3265 return get_errno(sys_futex(g2h(uaddr), FUTEX_WAKE, val, NULL, NULL, 0));
3266 case FUTEX_FD:
3267 return get_errno(sys_futex(g2h(uaddr), FUTEX_FD, val, NULL, NULL, 0));
3268 case FUTEX_REQUEUE:
3269 return get_errno(sys_futex(g2h(uaddr), FUTEX_REQUEUE, val,
3270 NULL, g2h(uaddr2), 0));
3271 case FUTEX_CMP_REQUEUE:
3272 return get_errno(sys_futex(g2h(uaddr), FUTEX_CMP_REQUEUE, val,
3273 NULL, g2h(uaddr2), tswap32(val3)));
3274 default:
3275 return -TARGET_ENOSYS;
3276 }
3277}
3278#endif
3279
pbrooka745ec62008-05-06 15:36:17 +00003280int get_osversion(void)
3281{
3282 static int osversion;
3283 struct new_utsname buf;
3284 const char *s;
3285 int i, n, tmp;
3286 if (osversion)
3287 return osversion;
3288 if (qemu_uname_release && *qemu_uname_release) {
3289 s = qemu_uname_release;
3290 } else {
3291 if (sys_uname(&buf))
3292 return 0;
3293 s = buf.release;
3294 }
3295 tmp = 0;
3296 for (i = 0; i < 3; i++) {
3297 n = 0;
3298 while (*s >= '0' && *s <= '9') {
3299 n *= 10;
3300 n += *s - '0';
3301 s++;
3302 }
3303 tmp = (tmp << 8) + n;
3304 if (*s == '.')
3305 s++;
3306 }
3307 osversion = tmp;
3308 return osversion;
3309}
3310
ths0da46a62007-10-20 20:23:07 +00003311/* do_syscall() should always have a single exit point at the end so
3312 that actions, such as logging of syscall results, can be performed.
3313 All errnos that do_syscall() returns must be -TARGET_<errcode>. */
blueswir1992f48a2007-10-14 16:27:31 +00003314abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
3315 abi_long arg2, abi_long arg3, abi_long arg4,
3316 abi_long arg5, abi_long arg6)
bellard31e31b82003-02-18 22:55:36 +00003317{
blueswir1992f48a2007-10-14 16:27:31 +00003318 abi_long ret;
bellard31e31b82003-02-18 22:55:36 +00003319 struct stat st;
bellard56c8f682005-11-28 22:28:41 +00003320 struct statfs stfs;
pbrook53a59602006-03-25 19:31:22 +00003321 void *p;
ths3b46e622007-09-17 08:09:54 +00003322
bellard72f03902003-02-18 23:33:18 +00003323#ifdef DEBUG
bellardc573ff62004-01-04 15:51:36 +00003324 gemu_log("syscall %d", num);
bellard72f03902003-02-18 23:33:18 +00003325#endif
thsb92c47c2007-11-01 00:07:38 +00003326 if(do_strace)
3327 print_syscall(num, arg1, arg2, arg3, arg4, arg5, arg6);
3328
bellard31e31b82003-02-18 22:55:36 +00003329 switch(num) {
3330 case TARGET_NR_exit:
bellard7d132992003-03-06 23:23:54 +00003331#ifdef HAVE_GPROF
3332 _mcleanup();
3333#endif
bellarde9009672005-04-26 20:42:36 +00003334 gdb_exit(cpu_env, arg1);
bellard1b6b0292003-03-22 17:31:38 +00003335 /* XXX: should free thread stack and CPU env */
bellard31e31b82003-02-18 22:55:36 +00003336 _exit(arg1);
3337 ret = 0; /* avoid warning */
3338 break;
3339 case TARGET_NR_read:
bellard579a97f2007-11-11 14:26:47 +00003340 if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
3341 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003342 ret = get_errno(read(arg1, p, arg3));
3343 unlock_user(p, arg2, ret);
bellard31e31b82003-02-18 22:55:36 +00003344 break;
3345 case TARGET_NR_write:
bellard579a97f2007-11-11 14:26:47 +00003346 if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
3347 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003348 ret = get_errno(write(arg1, p, arg3));
3349 unlock_user(p, arg2, 0);
bellard31e31b82003-02-18 22:55:36 +00003350 break;
3351 case TARGET_NR_open:
bellard2f619692007-11-16 10:46:05 +00003352 if (!(p = lock_user_string(arg1)))
3353 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003354 ret = get_errno(open(path(p),
bellardffa65c32004-01-04 23:57:22 +00003355 target_to_host_bitmask(arg2, fcntl_flags_tbl),
3356 arg3));
pbrook53a59602006-03-25 19:31:22 +00003357 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003358 break;
ths82424832007-09-24 09:21:55 +00003359#if defined(TARGET_NR_openat) && defined(__NR_openat)
3360 case TARGET_NR_openat:
bellard579a97f2007-11-11 14:26:47 +00003361 if (!(p = lock_user_string(arg2)))
3362 goto efault;
3363 ret = get_errno(sys_openat(arg1,
3364 path(p),
3365 target_to_host_bitmask(arg3, fcntl_flags_tbl),
3366 arg4));
3367 unlock_user(p, arg2, 0);
ths82424832007-09-24 09:21:55 +00003368 break;
3369#endif
bellard31e31b82003-02-18 22:55:36 +00003370 case TARGET_NR_close:
3371 ret = get_errno(close(arg1));
3372 break;
3373 case TARGET_NR_brk:
pbrook53a59602006-03-25 19:31:22 +00003374 ret = do_brk(arg1);
bellard31e31b82003-02-18 22:55:36 +00003375 break;
3376 case TARGET_NR_fork:
pbrookd865bab2008-06-07 22:12:17 +00003377 ret = get_errno(do_fork(cpu_env, SIGCHLD, 0, 0, 0, 0));
bellard31e31b82003-02-18 22:55:36 +00003378 break;
thse5febef2007-04-01 18:31:35 +00003379#ifdef TARGET_NR_waitpid
bellard31e31b82003-02-18 22:55:36 +00003380 case TARGET_NR_waitpid:
3381 {
pbrook53a59602006-03-25 19:31:22 +00003382 int status;
3383 ret = get_errno(waitpid(arg1, &status, arg3));
bellard2f619692007-11-16 10:46:05 +00003384 if (!is_error(ret) && arg2
3385 && put_user_s32(status, arg2))
3386 goto efault;
bellard31e31b82003-02-18 22:55:36 +00003387 }
3388 break;
thse5febef2007-04-01 18:31:35 +00003389#endif
pbrookf0cbb612008-05-30 18:20:05 +00003390#ifdef TARGET_NR_waitid
3391 case TARGET_NR_waitid:
3392 {
3393 siginfo_t info;
3394 info.si_pid = 0;
3395 ret = get_errno(waitid(arg1, arg2, &info, arg4));
3396 if (!is_error(ret) && arg3 && info.si_pid != 0) {
3397 if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_siginfo_t), 0)))
3398 goto efault;
3399 host_to_target_siginfo(p, &info);
3400 unlock_user(p, arg3, sizeof(target_siginfo_t));
3401 }
3402 }
3403 break;
3404#endif
j_mayer7a3148a2007-04-05 07:13:51 +00003405#ifdef TARGET_NR_creat /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00003406 case TARGET_NR_creat:
bellard579a97f2007-11-11 14:26:47 +00003407 if (!(p = lock_user_string(arg1)))
3408 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003409 ret = get_errno(creat(p, arg2));
3410 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003411 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003412#endif
bellard31e31b82003-02-18 22:55:36 +00003413 case TARGET_NR_link:
pbrook53a59602006-03-25 19:31:22 +00003414 {
3415 void * p2;
3416 p = lock_user_string(arg1);
3417 p2 = lock_user_string(arg2);
bellard579a97f2007-11-11 14:26:47 +00003418 if (!p || !p2)
3419 ret = -TARGET_EFAULT;
3420 else
3421 ret = get_errno(link(p, p2));
pbrook53a59602006-03-25 19:31:22 +00003422 unlock_user(p2, arg2, 0);
3423 unlock_user(p, arg1, 0);
3424 }
bellard31e31b82003-02-18 22:55:36 +00003425 break;
ths64f0ce42007-09-24 09:25:06 +00003426#if defined(TARGET_NR_linkat) && defined(__NR_linkat)
3427 case TARGET_NR_linkat:
ths64f0ce42007-09-24 09:25:06 +00003428 {
3429 void * p2 = NULL;
bellard579a97f2007-11-11 14:26:47 +00003430 if (!arg2 || !arg4)
3431 goto efault;
ths64f0ce42007-09-24 09:25:06 +00003432 p = lock_user_string(arg2);
3433 p2 = lock_user_string(arg4);
bellard579a97f2007-11-11 14:26:47 +00003434 if (!p || !p2)
ths0da46a62007-10-20 20:23:07 +00003435 ret = -TARGET_EFAULT;
ths64f0ce42007-09-24 09:25:06 +00003436 else
3437 ret = get_errno(sys_linkat(arg1, p, arg3, p2, arg5));
bellard579a97f2007-11-11 14:26:47 +00003438 unlock_user(p, arg2, 0);
3439 unlock_user(p2, arg4, 0);
ths64f0ce42007-09-24 09:25:06 +00003440 }
3441 break;
3442#endif
bellard31e31b82003-02-18 22:55:36 +00003443 case TARGET_NR_unlink:
bellard579a97f2007-11-11 14:26:47 +00003444 if (!(p = lock_user_string(arg1)))
3445 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003446 ret = get_errno(unlink(p));
3447 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003448 break;
ths8170f562007-09-24 09:24:11 +00003449#if defined(TARGET_NR_unlinkat) && defined(__NR_unlinkat)
3450 case TARGET_NR_unlinkat:
bellard579a97f2007-11-11 14:26:47 +00003451 if (!(p = lock_user_string(arg2)))
3452 goto efault;
3453 ret = get_errno(sys_unlinkat(arg1, p, arg3));
3454 unlock_user(p, arg2, 0);
balroged494d82007-12-11 23:23:52 +00003455 break;
balrogb7d35e62007-12-12 00:40:24 +00003456#endif
bellard31e31b82003-02-18 22:55:36 +00003457 case TARGET_NR_execve:
bellard7854b052003-03-29 17:22:23 +00003458 {
3459 char **argp, **envp;
bellardf7341ff2003-03-30 21:00:25 +00003460 int argc, envc;
blueswir1992f48a2007-10-14 16:27:31 +00003461 abi_ulong gp;
3462 abi_ulong guest_argp;
3463 abi_ulong guest_envp;
3464 abi_ulong addr;
bellard7854b052003-03-29 17:22:23 +00003465 char **q;
3466
bellardf7341ff2003-03-30 21:00:25 +00003467 argc = 0;
pbrook53a59602006-03-25 19:31:22 +00003468 guest_argp = arg2;
pbrookda94d262008-05-30 18:24:00 +00003469 for (gp = guest_argp; gp; gp += sizeof(abi_ulong)) {
ths03aa1972007-12-02 06:28:08 +00003470 if (get_user_ual(addr, gp))
bellard2f619692007-11-16 10:46:05 +00003471 goto efault;
ths03aa1972007-12-02 06:28:08 +00003472 if (!addr)
bellard2f619692007-11-16 10:46:05 +00003473 break;
bellard7854b052003-03-29 17:22:23 +00003474 argc++;
bellard2f619692007-11-16 10:46:05 +00003475 }
bellardf7341ff2003-03-30 21:00:25 +00003476 envc = 0;
pbrook53a59602006-03-25 19:31:22 +00003477 guest_envp = arg3;
pbrookda94d262008-05-30 18:24:00 +00003478 for (gp = guest_envp; gp; gp += sizeof(abi_ulong)) {
ths03aa1972007-12-02 06:28:08 +00003479 if (get_user_ual(addr, gp))
bellard2f619692007-11-16 10:46:05 +00003480 goto efault;
ths03aa1972007-12-02 06:28:08 +00003481 if (!addr)
bellard2f619692007-11-16 10:46:05 +00003482 break;
bellard7854b052003-03-29 17:22:23 +00003483 envc++;
bellard2f619692007-11-16 10:46:05 +00003484 }
bellard7854b052003-03-29 17:22:23 +00003485
bellardf7341ff2003-03-30 21:00:25 +00003486 argp = alloca((argc + 1) * sizeof(void *));
3487 envp = alloca((envc + 1) * sizeof(void *));
bellard7854b052003-03-29 17:22:23 +00003488
pbrookda94d262008-05-30 18:24:00 +00003489 for (gp = guest_argp, q = argp; gp;
blueswir1992f48a2007-10-14 16:27:31 +00003490 gp += sizeof(abi_ulong), q++) {
bellard2f619692007-11-16 10:46:05 +00003491 if (get_user_ual(addr, gp))
3492 goto execve_efault;
pbrook53a59602006-03-25 19:31:22 +00003493 if (!addr)
3494 break;
bellard2f619692007-11-16 10:46:05 +00003495 if (!(*q = lock_user_string(addr)))
3496 goto execve_efault;
pbrook53a59602006-03-25 19:31:22 +00003497 }
bellardf7341ff2003-03-30 21:00:25 +00003498 *q = NULL;
3499
pbrookda94d262008-05-30 18:24:00 +00003500 for (gp = guest_envp, q = envp; gp;
blueswir1992f48a2007-10-14 16:27:31 +00003501 gp += sizeof(abi_ulong), q++) {
bellard2f619692007-11-16 10:46:05 +00003502 if (get_user_ual(addr, gp))
3503 goto execve_efault;
pbrook53a59602006-03-25 19:31:22 +00003504 if (!addr)
3505 break;
bellard2f619692007-11-16 10:46:05 +00003506 if (!(*q = lock_user_string(addr)))
3507 goto execve_efault;
pbrook53a59602006-03-25 19:31:22 +00003508 }
bellardf7341ff2003-03-30 21:00:25 +00003509 *q = NULL;
bellard7854b052003-03-29 17:22:23 +00003510
bellard2f619692007-11-16 10:46:05 +00003511 if (!(p = lock_user_string(arg1)))
3512 goto execve_efault;
pbrook53a59602006-03-25 19:31:22 +00003513 ret = get_errno(execve(p, argp, envp));
3514 unlock_user(p, arg1, 0);
3515
bellard2f619692007-11-16 10:46:05 +00003516 goto execve_end;
3517
3518 execve_efault:
3519 ret = -TARGET_EFAULT;
3520
3521 execve_end:
pbrook53a59602006-03-25 19:31:22 +00003522 for (gp = guest_argp, q = argp; *q;
blueswir1992f48a2007-10-14 16:27:31 +00003523 gp += sizeof(abi_ulong), q++) {
bellard2f619692007-11-16 10:46:05 +00003524 if (get_user_ual(addr, gp)
3525 || !addr)
3526 break;
pbrook53a59602006-03-25 19:31:22 +00003527 unlock_user(*q, addr, 0);
3528 }
3529 for (gp = guest_envp, q = envp; *q;
blueswir1992f48a2007-10-14 16:27:31 +00003530 gp += sizeof(abi_ulong), q++) {
bellard2f619692007-11-16 10:46:05 +00003531 if (get_user_ual(addr, gp)
3532 || !addr)
3533 break;
pbrook53a59602006-03-25 19:31:22 +00003534 unlock_user(*q, addr, 0);
3535 }
bellard7854b052003-03-29 17:22:23 +00003536 }
bellard31e31b82003-02-18 22:55:36 +00003537 break;
3538 case TARGET_NR_chdir:
bellard579a97f2007-11-11 14:26:47 +00003539 if (!(p = lock_user_string(arg1)))
3540 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003541 ret = get_errno(chdir(p));
3542 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003543 break;
bellarda315a142005-01-30 22:59:18 +00003544#ifdef TARGET_NR_time
bellard31e31b82003-02-18 22:55:36 +00003545 case TARGET_NR_time:
3546 {
pbrook53a59602006-03-25 19:31:22 +00003547 time_t host_time;
3548 ret = get_errno(time(&host_time));
bellard2f619692007-11-16 10:46:05 +00003549 if (!is_error(ret)
3550 && arg1
3551 && put_user_sal(host_time, arg1))
3552 goto efault;
bellard31e31b82003-02-18 22:55:36 +00003553 }
3554 break;
bellarda315a142005-01-30 22:59:18 +00003555#endif
bellard31e31b82003-02-18 22:55:36 +00003556 case TARGET_NR_mknod:
bellard579a97f2007-11-11 14:26:47 +00003557 if (!(p = lock_user_string(arg1)))
3558 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003559 ret = get_errno(mknod(p, arg2, arg3));
3560 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003561 break;
ths75ac37a2007-09-24 09:23:05 +00003562#if defined(TARGET_NR_mknodat) && defined(__NR_mknodat)
3563 case TARGET_NR_mknodat:
bellard579a97f2007-11-11 14:26:47 +00003564 if (!(p = lock_user_string(arg2)))
3565 goto efault;
3566 ret = get_errno(sys_mknodat(arg1, p, arg3, arg4));
3567 unlock_user(p, arg2, 0);
ths75ac37a2007-09-24 09:23:05 +00003568 break;
3569#endif
bellard31e31b82003-02-18 22:55:36 +00003570 case TARGET_NR_chmod:
bellard579a97f2007-11-11 14:26:47 +00003571 if (!(p = lock_user_string(arg1)))
3572 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003573 ret = get_errno(chmod(p, arg2));
3574 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003575 break;
bellardebc05482003-09-30 21:08:41 +00003576#ifdef TARGET_NR_break
bellard31e31b82003-02-18 22:55:36 +00003577 case TARGET_NR_break:
3578 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00003579#endif
3580#ifdef TARGET_NR_oldstat
bellard31e31b82003-02-18 22:55:36 +00003581 case TARGET_NR_oldstat:
3582 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00003583#endif
bellard31e31b82003-02-18 22:55:36 +00003584 case TARGET_NR_lseek:
3585 ret = get_errno(lseek(arg1, arg2, arg3));
3586 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003587#ifdef TARGET_NR_getxpid
3588 case TARGET_NR_getxpid:
3589#else
bellard31e31b82003-02-18 22:55:36 +00003590 case TARGET_NR_getpid:
j_mayer7a3148a2007-04-05 07:13:51 +00003591#endif
bellard31e31b82003-02-18 22:55:36 +00003592 ret = get_errno(getpid());
3593 break;
3594 case TARGET_NR_mount:
ths80265912007-02-17 22:25:41 +00003595 {
3596 /* need to look at the data field */
3597 void *p2, *p3;
3598 p = lock_user_string(arg1);
3599 p2 = lock_user_string(arg2);
3600 p3 = lock_user_string(arg3);
bellard579a97f2007-11-11 14:26:47 +00003601 if (!p || !p2 || !p3)
3602 ret = -TARGET_EFAULT;
3603 else
3604 /* FIXME - arg5 should be locked, but it isn't clear how to
3605 * do that since it's not guaranteed to be a NULL-terminated
3606 * string.
3607 */
3608 ret = get_errno(mount(p, p2, p3, (unsigned long)arg4, g2h(arg5)));
3609 unlock_user(p, arg1, 0);
3610 unlock_user(p2, arg2, 0);
3611 unlock_user(p3, arg3, 0);
ths80265912007-02-17 22:25:41 +00003612 break;
3613 }
thse5febef2007-04-01 18:31:35 +00003614#ifdef TARGET_NR_umount
bellard31e31b82003-02-18 22:55:36 +00003615 case TARGET_NR_umount:
bellard579a97f2007-11-11 14:26:47 +00003616 if (!(p = lock_user_string(arg1)))
3617 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003618 ret = get_errno(umount(p));
3619 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003620 break;
thse5febef2007-04-01 18:31:35 +00003621#endif
j_mayer7a3148a2007-04-05 07:13:51 +00003622#ifdef TARGET_NR_stime /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00003623 case TARGET_NR_stime:
3624 {
pbrook53a59602006-03-25 19:31:22 +00003625 time_t host_time;
bellard2f619692007-11-16 10:46:05 +00003626 if (get_user_sal(host_time, arg1))
3627 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003628 ret = get_errno(stime(&host_time));
bellard31e31b82003-02-18 22:55:36 +00003629 }
3630 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003631#endif
bellard31e31b82003-02-18 22:55:36 +00003632 case TARGET_NR_ptrace:
3633 goto unimplemented;
j_mayer7a3148a2007-04-05 07:13:51 +00003634#ifdef TARGET_NR_alarm /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00003635 case TARGET_NR_alarm:
3636 ret = alarm(arg1);
3637 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003638#endif
bellardebc05482003-09-30 21:08:41 +00003639#ifdef TARGET_NR_oldfstat
bellard31e31b82003-02-18 22:55:36 +00003640 case TARGET_NR_oldfstat:
3641 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00003642#endif
j_mayer7a3148a2007-04-05 07:13:51 +00003643#ifdef TARGET_NR_pause /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00003644 case TARGET_NR_pause:
3645 ret = get_errno(pause());
3646 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003647#endif
thse5febef2007-04-01 18:31:35 +00003648#ifdef TARGET_NR_utime
bellard31e31b82003-02-18 22:55:36 +00003649 case TARGET_NR_utime:
bellardebc05482003-09-30 21:08:41 +00003650 {
pbrook53a59602006-03-25 19:31:22 +00003651 struct utimbuf tbuf, *host_tbuf;
3652 struct target_utimbuf *target_tbuf;
3653 if (arg2) {
bellard579a97f2007-11-11 14:26:47 +00003654 if (!lock_user_struct(VERIFY_READ, target_tbuf, arg2, 1))
3655 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003656 tbuf.actime = tswapl(target_tbuf->actime);
3657 tbuf.modtime = tswapl(target_tbuf->modtime);
3658 unlock_user_struct(target_tbuf, arg2, 0);
3659 host_tbuf = &tbuf;
bellardf72e8ff2004-05-03 19:23:07 +00003660 } else {
pbrook53a59602006-03-25 19:31:22 +00003661 host_tbuf = NULL;
bellardf72e8ff2004-05-03 19:23:07 +00003662 }
bellard579a97f2007-11-11 14:26:47 +00003663 if (!(p = lock_user_string(arg1)))
3664 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003665 ret = get_errno(utime(p, host_tbuf));
3666 unlock_user(p, arg1, 0);
bellardebc05482003-09-30 21:08:41 +00003667 }
3668 break;
thse5febef2007-04-01 18:31:35 +00003669#endif
bellard978a66f2004-12-06 22:58:05 +00003670 case TARGET_NR_utimes:
3671 {
bellard978a66f2004-12-06 22:58:05 +00003672 struct timeval *tvp, tv[2];
pbrook53a59602006-03-25 19:31:22 +00003673 if (arg2) {
ths788f5ec2007-12-09 02:37:05 +00003674 if (copy_from_user_timeval(&tv[0], arg2)
3675 || copy_from_user_timeval(&tv[1],
3676 arg2 + sizeof(struct target_timeval)))
3677 goto efault;
bellard978a66f2004-12-06 22:58:05 +00003678 tvp = tv;
3679 } else {
3680 tvp = NULL;
3681 }
bellard579a97f2007-11-11 14:26:47 +00003682 if (!(p = lock_user_string(arg1)))
3683 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003684 ret = get_errno(utimes(p, tvp));
3685 unlock_user(p, arg1, 0);
bellard978a66f2004-12-06 22:58:05 +00003686 }
3687 break;
balrogac8a6552008-09-20 02:25:39 +00003688#if defined(TARGET_NR_futimesat) && defined(__NR_futimesat)
3689 case TARGET_NR_futimesat:
3690 {
3691 struct timeval *tvp, tv[2];
3692 if (arg3) {
3693 if (copy_from_user_timeval(&tv[0], arg3)
3694 || copy_from_user_timeval(&tv[1],
3695 arg3 + sizeof(struct target_timeval)))
3696 goto efault;
3697 tvp = tv;
3698 } else {
3699 tvp = NULL;
3700 }
3701 if (!(p = lock_user_string(arg2)))
3702 goto efault;
3703 ret = get_errno(sys_futimesat(arg1, path(p), tvp));
3704 unlock_user(p, arg2, 0);
3705 }
3706 break;
3707#endif
bellardebc05482003-09-30 21:08:41 +00003708#ifdef TARGET_NR_stty
bellard31e31b82003-02-18 22:55:36 +00003709 case TARGET_NR_stty:
3710 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00003711#endif
3712#ifdef TARGET_NR_gtty
bellard31e31b82003-02-18 22:55:36 +00003713 case TARGET_NR_gtty:
3714 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00003715#endif
bellard31e31b82003-02-18 22:55:36 +00003716 case TARGET_NR_access:
bellard579a97f2007-11-11 14:26:47 +00003717 if (!(p = lock_user_string(arg1)))
3718 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003719 ret = get_errno(access(p, arg2));
3720 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003721 break;
ths92a34c12007-09-24 09:27:49 +00003722#if defined(TARGET_NR_faccessat) && defined(__NR_faccessat)
3723 case TARGET_NR_faccessat:
bellard579a97f2007-11-11 14:26:47 +00003724 if (!(p = lock_user_string(arg2)))
3725 goto efault;
3726 ret = get_errno(sys_faccessat(arg1, p, arg3, arg4));
3727 unlock_user(p, arg2, 0);
ths92a34c12007-09-24 09:27:49 +00003728 break;
3729#endif
j_mayer7a3148a2007-04-05 07:13:51 +00003730#ifdef TARGET_NR_nice /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00003731 case TARGET_NR_nice:
3732 ret = get_errno(nice(arg1));
3733 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003734#endif
bellardebc05482003-09-30 21:08:41 +00003735#ifdef TARGET_NR_ftime
bellard31e31b82003-02-18 22:55:36 +00003736 case TARGET_NR_ftime:
3737 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00003738#endif
bellard31e31b82003-02-18 22:55:36 +00003739 case TARGET_NR_sync:
bellard04369ff2003-03-20 22:33:23 +00003740 sync();
3741 ret = 0;
bellard31e31b82003-02-18 22:55:36 +00003742 break;
3743 case TARGET_NR_kill:
pbrook4cb05962008-05-30 18:05:19 +00003744 ret = get_errno(kill(arg1, target_to_host_signal(arg2)));
bellard31e31b82003-02-18 22:55:36 +00003745 break;
3746 case TARGET_NR_rename:
pbrook53a59602006-03-25 19:31:22 +00003747 {
3748 void *p2;
3749 p = lock_user_string(arg1);
3750 p2 = lock_user_string(arg2);
bellard579a97f2007-11-11 14:26:47 +00003751 if (!p || !p2)
3752 ret = -TARGET_EFAULT;
3753 else
3754 ret = get_errno(rename(p, p2));
pbrook53a59602006-03-25 19:31:22 +00003755 unlock_user(p2, arg2, 0);
3756 unlock_user(p, arg1, 0);
3757 }
bellard31e31b82003-02-18 22:55:36 +00003758 break;
ths722183f2007-09-24 09:24:37 +00003759#if defined(TARGET_NR_renameat) && defined(__NR_renameat)
3760 case TARGET_NR_renameat:
ths722183f2007-09-24 09:24:37 +00003761 {
bellard579a97f2007-11-11 14:26:47 +00003762 void *p2;
ths722183f2007-09-24 09:24:37 +00003763 p = lock_user_string(arg2);
3764 p2 = lock_user_string(arg4);
bellard579a97f2007-11-11 14:26:47 +00003765 if (!p || !p2)
ths0da46a62007-10-20 20:23:07 +00003766 ret = -TARGET_EFAULT;
ths722183f2007-09-24 09:24:37 +00003767 else
3768 ret = get_errno(sys_renameat(arg1, p, arg3, p2));
bellard579a97f2007-11-11 14:26:47 +00003769 unlock_user(p2, arg4, 0);
3770 unlock_user(p, arg2, 0);
ths722183f2007-09-24 09:24:37 +00003771 }
3772 break;
3773#endif
bellard31e31b82003-02-18 22:55:36 +00003774 case TARGET_NR_mkdir:
bellard579a97f2007-11-11 14:26:47 +00003775 if (!(p = lock_user_string(arg1)))
3776 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003777 ret = get_errno(mkdir(p, arg2));
3778 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003779 break;
ths4472ad02007-09-24 09:22:32 +00003780#if defined(TARGET_NR_mkdirat) && defined(__NR_mkdirat)
3781 case TARGET_NR_mkdirat:
bellard579a97f2007-11-11 14:26:47 +00003782 if (!(p = lock_user_string(arg2)))
3783 goto efault;
3784 ret = get_errno(sys_mkdirat(arg1, p, arg3));
3785 unlock_user(p, arg2, 0);
ths4472ad02007-09-24 09:22:32 +00003786 break;
3787#endif
bellard31e31b82003-02-18 22:55:36 +00003788 case TARGET_NR_rmdir:
bellard579a97f2007-11-11 14:26:47 +00003789 if (!(p = lock_user_string(arg1)))
3790 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003791 ret = get_errno(rmdir(p));
3792 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003793 break;
3794 case TARGET_NR_dup:
3795 ret = get_errno(dup(arg1));
3796 break;
3797 case TARGET_NR_pipe:
3798 {
pbrook53a59602006-03-25 19:31:22 +00003799 int host_pipe[2];
3800 ret = get_errno(pipe(host_pipe));
bellard31e31b82003-02-18 22:55:36 +00003801 if (!is_error(ret)) {
thsc12ab052007-06-01 11:50:36 +00003802#if defined(TARGET_MIPS)
thsead93602007-09-06 00:18:15 +00003803 CPUMIPSState *env = (CPUMIPSState*)cpu_env;
thsb5dc7732008-06-27 10:02:35 +00003804 env->active_tc.gpr[3] = host_pipe[1];
thsc12ab052007-06-01 11:50:36 +00003805 ret = host_pipe[0];
aurel32b5eff352008-03-11 23:30:22 +00003806#elif defined(TARGET_SH4)
3807 ((CPUSH4State*)cpu_env)->gregs[1] = host_pipe[1];
3808 ret = host_pipe[0];
thsc12ab052007-06-01 11:50:36 +00003809#else
bellard2f619692007-11-16 10:46:05 +00003810 if (put_user_s32(host_pipe[0], arg1)
3811 || put_user_s32(host_pipe[1], arg1 + sizeof(host_pipe[0])))
3812 goto efault;
thsc12ab052007-06-01 11:50:36 +00003813#endif
bellard31e31b82003-02-18 22:55:36 +00003814 }
3815 }
3816 break;
3817 case TARGET_NR_times:
bellard32f36bc2003-03-30 21:29:48 +00003818 {
pbrook53a59602006-03-25 19:31:22 +00003819 struct target_tms *tmsp;
bellard32f36bc2003-03-30 21:29:48 +00003820 struct tms tms;
3821 ret = get_errno(times(&tms));
pbrook53a59602006-03-25 19:31:22 +00003822 if (arg1) {
bellard579a97f2007-11-11 14:26:47 +00003823 tmsp = lock_user(VERIFY_WRITE, arg1, sizeof(struct target_tms), 0);
3824 if (!tmsp)
3825 goto efault;
bellardc596ed12003-07-13 17:32:31 +00003826 tmsp->tms_utime = tswapl(host_to_target_clock_t(tms.tms_utime));
3827 tmsp->tms_stime = tswapl(host_to_target_clock_t(tms.tms_stime));
3828 tmsp->tms_cutime = tswapl(host_to_target_clock_t(tms.tms_cutime));
3829 tmsp->tms_cstime = tswapl(host_to_target_clock_t(tms.tms_cstime));
bellard32f36bc2003-03-30 21:29:48 +00003830 }
bellardc596ed12003-07-13 17:32:31 +00003831 if (!is_error(ret))
3832 ret = host_to_target_clock_t(ret);
bellard32f36bc2003-03-30 21:29:48 +00003833 }
3834 break;
bellardebc05482003-09-30 21:08:41 +00003835#ifdef TARGET_NR_prof
bellard31e31b82003-02-18 22:55:36 +00003836 case TARGET_NR_prof:
3837 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00003838#endif
thse5febef2007-04-01 18:31:35 +00003839#ifdef TARGET_NR_signal
bellard31e31b82003-02-18 22:55:36 +00003840 case TARGET_NR_signal:
3841 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00003842#endif
bellard31e31b82003-02-18 22:55:36 +00003843 case TARGET_NR_acct:
bellard579a97f2007-11-11 14:26:47 +00003844 if (!(p = lock_user_string(arg1)))
3845 goto efault;
pbrook24836682006-04-16 14:14:53 +00003846 ret = get_errno(acct(path(p)));
3847 unlock_user(p, arg1, 0);
3848 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003849#ifdef TARGET_NR_umount2 /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00003850 case TARGET_NR_umount2:
bellard579a97f2007-11-11 14:26:47 +00003851 if (!(p = lock_user_string(arg1)))
3852 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003853 ret = get_errno(umount2(p, arg2));
3854 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003855 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003856#endif
bellardebc05482003-09-30 21:08:41 +00003857#ifdef TARGET_NR_lock
bellard31e31b82003-02-18 22:55:36 +00003858 case TARGET_NR_lock:
3859 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00003860#endif
bellard31e31b82003-02-18 22:55:36 +00003861 case TARGET_NR_ioctl:
3862 ret = do_ioctl(arg1, arg2, arg3);
3863 break;
3864 case TARGET_NR_fcntl:
bellard9ee1fa22007-11-11 15:11:19 +00003865 ret = do_fcntl(arg1, arg2, arg3);
bellard31e31b82003-02-18 22:55:36 +00003866 break;
bellardebc05482003-09-30 21:08:41 +00003867#ifdef TARGET_NR_mpx
bellard31e31b82003-02-18 22:55:36 +00003868 case TARGET_NR_mpx:
3869 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00003870#endif
bellard31e31b82003-02-18 22:55:36 +00003871 case TARGET_NR_setpgid:
3872 ret = get_errno(setpgid(arg1, arg2));
3873 break;
bellardebc05482003-09-30 21:08:41 +00003874#ifdef TARGET_NR_ulimit
bellard31e31b82003-02-18 22:55:36 +00003875 case TARGET_NR_ulimit:
3876 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00003877#endif
3878#ifdef TARGET_NR_oldolduname
bellard31e31b82003-02-18 22:55:36 +00003879 case TARGET_NR_oldolduname:
3880 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00003881#endif
bellard31e31b82003-02-18 22:55:36 +00003882 case TARGET_NR_umask:
3883 ret = get_errno(umask(arg1));
3884 break;
3885 case TARGET_NR_chroot:
bellard579a97f2007-11-11 14:26:47 +00003886 if (!(p = lock_user_string(arg1)))
3887 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003888 ret = get_errno(chroot(p));
3889 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003890 break;
3891 case TARGET_NR_ustat:
3892 goto unimplemented;
3893 case TARGET_NR_dup2:
3894 ret = get_errno(dup2(arg1, arg2));
3895 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003896#ifdef TARGET_NR_getppid /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00003897 case TARGET_NR_getppid:
3898 ret = get_errno(getppid());
3899 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003900#endif
bellard31e31b82003-02-18 22:55:36 +00003901 case TARGET_NR_getpgrp:
3902 ret = get_errno(getpgrp());
3903 break;
3904 case TARGET_NR_setsid:
3905 ret = get_errno(setsid());
3906 break;
thse5febef2007-04-01 18:31:35 +00003907#ifdef TARGET_NR_sigaction
bellard31e31b82003-02-18 22:55:36 +00003908 case TARGET_NR_sigaction:
bellard31e31b82003-02-18 22:55:36 +00003909 {
ths388bb212007-05-13 13:58:00 +00003910#if !defined(TARGET_MIPS)
pbrook53a59602006-03-25 19:31:22 +00003911 struct target_old_sigaction *old_act;
bellard66fb9762003-03-23 01:06:05 +00003912 struct target_sigaction act, oact, *pact;
pbrook53a59602006-03-25 19:31:22 +00003913 if (arg2) {
bellard579a97f2007-11-11 14:26:47 +00003914 if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1))
3915 goto efault;
bellard66fb9762003-03-23 01:06:05 +00003916 act._sa_handler = old_act->_sa_handler;
3917 target_siginitset(&act.sa_mask, old_act->sa_mask);
3918 act.sa_flags = old_act->sa_flags;
3919 act.sa_restorer = old_act->sa_restorer;
pbrook53a59602006-03-25 19:31:22 +00003920 unlock_user_struct(old_act, arg2, 0);
bellard66fb9762003-03-23 01:06:05 +00003921 pact = &act;
3922 } else {
3923 pact = NULL;
3924 }
3925 ret = get_errno(do_sigaction(arg1, pact, &oact));
pbrook53a59602006-03-25 19:31:22 +00003926 if (!is_error(ret) && arg3) {
bellard579a97f2007-11-11 14:26:47 +00003927 if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0))
3928 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003929 old_act->_sa_handler = oact._sa_handler;
3930 old_act->sa_mask = oact.sa_mask.sig[0];
3931 old_act->sa_flags = oact.sa_flags;
3932 old_act->sa_restorer = oact.sa_restorer;
3933 unlock_user_struct(old_act, arg3, 1);
bellard66fb9762003-03-23 01:06:05 +00003934 }
ths388bb212007-05-13 13:58:00 +00003935#else
bellard106ec872006-06-27 21:08:10 +00003936 struct target_sigaction act, oact, *pact, *old_act;
3937
3938 if (arg2) {
bellard579a97f2007-11-11 14:26:47 +00003939 if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1))
3940 goto efault;
bellard106ec872006-06-27 21:08:10 +00003941 act._sa_handler = old_act->_sa_handler;
3942 target_siginitset(&act.sa_mask, old_act->sa_mask.sig[0]);
3943 act.sa_flags = old_act->sa_flags;
3944 unlock_user_struct(old_act, arg2, 0);
3945 pact = &act;
3946 } else {
3947 pact = NULL;
3948 }
3949
3950 ret = get_errno(do_sigaction(arg1, pact, &oact));
3951
3952 if (!is_error(ret) && arg3) {
bellard579a97f2007-11-11 14:26:47 +00003953 if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0))
3954 goto efault;
bellard106ec872006-06-27 21:08:10 +00003955 old_act->_sa_handler = oact._sa_handler;
3956 old_act->sa_flags = oact.sa_flags;
3957 old_act->sa_mask.sig[0] = oact.sa_mask.sig[0];
3958 old_act->sa_mask.sig[1] = 0;
3959 old_act->sa_mask.sig[2] = 0;
3960 old_act->sa_mask.sig[3] = 0;
3961 unlock_user_struct(old_act, arg3, 1);
3962 }
ths388bb212007-05-13 13:58:00 +00003963#endif
bellard31e31b82003-02-18 22:55:36 +00003964 }
3965 break;
thse5febef2007-04-01 18:31:35 +00003966#endif
bellard66fb9762003-03-23 01:06:05 +00003967 case TARGET_NR_rt_sigaction:
pbrook53a59602006-03-25 19:31:22 +00003968 {
3969 struct target_sigaction *act;
3970 struct target_sigaction *oact;
3971
bellard579a97f2007-11-11 14:26:47 +00003972 if (arg2) {
3973 if (!lock_user_struct(VERIFY_READ, act, arg2, 1))
3974 goto efault;
3975 } else
pbrook53a59602006-03-25 19:31:22 +00003976 act = NULL;
bellard579a97f2007-11-11 14:26:47 +00003977 if (arg3) {
3978 if (!lock_user_struct(VERIFY_WRITE, oact, arg3, 0)) {
3979 ret = -TARGET_EFAULT;
3980 goto rt_sigaction_fail;
3981 }
3982 } else
pbrook53a59602006-03-25 19:31:22 +00003983 oact = NULL;
3984 ret = get_errno(do_sigaction(arg1, act, oact));
bellard579a97f2007-11-11 14:26:47 +00003985 rt_sigaction_fail:
3986 if (act)
pbrook53a59602006-03-25 19:31:22 +00003987 unlock_user_struct(act, arg2, 0);
bellard579a97f2007-11-11 14:26:47 +00003988 if (oact)
pbrook53a59602006-03-25 19:31:22 +00003989 unlock_user_struct(oact, arg3, 1);
3990 }
bellard66fb9762003-03-23 01:06:05 +00003991 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003992#ifdef TARGET_NR_sgetmask /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00003993 case TARGET_NR_sgetmask:
bellard66fb9762003-03-23 01:06:05 +00003994 {
3995 sigset_t cur_set;
blueswir1992f48a2007-10-14 16:27:31 +00003996 abi_ulong target_set;
bellard66fb9762003-03-23 01:06:05 +00003997 sigprocmask(0, NULL, &cur_set);
3998 host_to_target_old_sigset(&target_set, &cur_set);
3999 ret = target_set;
4000 }
4001 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004002#endif
4003#ifdef TARGET_NR_ssetmask /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00004004 case TARGET_NR_ssetmask:
bellard66fb9762003-03-23 01:06:05 +00004005 {
4006 sigset_t set, oset, cur_set;
blueswir1992f48a2007-10-14 16:27:31 +00004007 abi_ulong target_set = arg1;
bellard66fb9762003-03-23 01:06:05 +00004008 sigprocmask(0, NULL, &cur_set);
4009 target_to_host_old_sigset(&set, &target_set);
4010 sigorset(&set, &set, &cur_set);
4011 sigprocmask(SIG_SETMASK, &set, &oset);
4012 host_to_target_old_sigset(&target_set, &oset);
4013 ret = target_set;
4014 }
4015 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004016#endif
thse5febef2007-04-01 18:31:35 +00004017#ifdef TARGET_NR_sigprocmask
bellard66fb9762003-03-23 01:06:05 +00004018 case TARGET_NR_sigprocmask:
4019 {
4020 int how = arg1;
4021 sigset_t set, oldset, *set_ptr;
ths3b46e622007-09-17 08:09:54 +00004022
pbrook53a59602006-03-25 19:31:22 +00004023 if (arg2) {
bellard66fb9762003-03-23 01:06:05 +00004024 switch(how) {
4025 case TARGET_SIG_BLOCK:
4026 how = SIG_BLOCK;
4027 break;
4028 case TARGET_SIG_UNBLOCK:
4029 how = SIG_UNBLOCK;
4030 break;
4031 case TARGET_SIG_SETMASK:
4032 how = SIG_SETMASK;
4033 break;
4034 default:
ths0da46a62007-10-20 20:23:07 +00004035 ret = -TARGET_EINVAL;
bellard66fb9762003-03-23 01:06:05 +00004036 goto fail;
4037 }
bellard579a97f2007-11-11 14:26:47 +00004038 if (!(p = lock_user(VERIFY_READ, arg2, sizeof(target_sigset_t), 1)))
4039 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004040 target_to_host_old_sigset(&set, p);
4041 unlock_user(p, arg2, 0);
bellard66fb9762003-03-23 01:06:05 +00004042 set_ptr = &set;
4043 } else {
4044 how = 0;
4045 set_ptr = NULL;
4046 }
4047 ret = get_errno(sigprocmask(arg1, set_ptr, &oldset));
pbrook53a59602006-03-25 19:31:22 +00004048 if (!is_error(ret) && arg3) {
bellard579a97f2007-11-11 14:26:47 +00004049 if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0)))
4050 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004051 host_to_target_old_sigset(p, &oldset);
4052 unlock_user(p, arg3, sizeof(target_sigset_t));
bellard66fb9762003-03-23 01:06:05 +00004053 }
4054 }
4055 break;
thse5febef2007-04-01 18:31:35 +00004056#endif
bellard66fb9762003-03-23 01:06:05 +00004057 case TARGET_NR_rt_sigprocmask:
4058 {
4059 int how = arg1;
4060 sigset_t set, oldset, *set_ptr;
ths3b46e622007-09-17 08:09:54 +00004061
pbrook53a59602006-03-25 19:31:22 +00004062 if (arg2) {
bellard66fb9762003-03-23 01:06:05 +00004063 switch(how) {
4064 case TARGET_SIG_BLOCK:
4065 how = SIG_BLOCK;
4066 break;
4067 case TARGET_SIG_UNBLOCK:
4068 how = SIG_UNBLOCK;
4069 break;
4070 case TARGET_SIG_SETMASK:
4071 how = SIG_SETMASK;
4072 break;
4073 default:
ths0da46a62007-10-20 20:23:07 +00004074 ret = -TARGET_EINVAL;
bellard66fb9762003-03-23 01:06:05 +00004075 goto fail;
4076 }
bellard579a97f2007-11-11 14:26:47 +00004077 if (!(p = lock_user(VERIFY_READ, arg2, sizeof(target_sigset_t), 1)))
4078 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004079 target_to_host_sigset(&set, p);
4080 unlock_user(p, arg2, 0);
bellard66fb9762003-03-23 01:06:05 +00004081 set_ptr = &set;
4082 } else {
4083 how = 0;
4084 set_ptr = NULL;
4085 }
4086 ret = get_errno(sigprocmask(how, set_ptr, &oldset));
pbrook53a59602006-03-25 19:31:22 +00004087 if (!is_error(ret) && arg3) {
bellard579a97f2007-11-11 14:26:47 +00004088 if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0)))
4089 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004090 host_to_target_sigset(p, &oldset);
4091 unlock_user(p, arg3, sizeof(target_sigset_t));
bellard66fb9762003-03-23 01:06:05 +00004092 }
4093 }
4094 break;
thse5febef2007-04-01 18:31:35 +00004095#ifdef TARGET_NR_sigpending
bellard66fb9762003-03-23 01:06:05 +00004096 case TARGET_NR_sigpending:
4097 {
4098 sigset_t set;
4099 ret = get_errno(sigpending(&set));
4100 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00004101 if (!(p = lock_user(VERIFY_WRITE, arg1, sizeof(target_sigset_t), 0)))
4102 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004103 host_to_target_old_sigset(p, &set);
4104 unlock_user(p, arg1, sizeof(target_sigset_t));
bellard66fb9762003-03-23 01:06:05 +00004105 }
4106 }
4107 break;
thse5febef2007-04-01 18:31:35 +00004108#endif
bellard66fb9762003-03-23 01:06:05 +00004109 case TARGET_NR_rt_sigpending:
4110 {
4111 sigset_t set;
4112 ret = get_errno(sigpending(&set));
4113 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00004114 if (!(p = lock_user(VERIFY_WRITE, arg1, sizeof(target_sigset_t), 0)))
4115 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004116 host_to_target_sigset(p, &set);
4117 unlock_user(p, arg1, sizeof(target_sigset_t));
bellard66fb9762003-03-23 01:06:05 +00004118 }
4119 }
4120 break;
thse5febef2007-04-01 18:31:35 +00004121#ifdef TARGET_NR_sigsuspend
bellard66fb9762003-03-23 01:06:05 +00004122 case TARGET_NR_sigsuspend:
4123 {
4124 sigset_t set;
bellard579a97f2007-11-11 14:26:47 +00004125 if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
4126 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004127 target_to_host_old_sigset(&set, p);
4128 unlock_user(p, arg1, 0);
bellard66fb9762003-03-23 01:06:05 +00004129 ret = get_errno(sigsuspend(&set));
4130 }
4131 break;
thse5febef2007-04-01 18:31:35 +00004132#endif
bellard66fb9762003-03-23 01:06:05 +00004133 case TARGET_NR_rt_sigsuspend:
4134 {
4135 sigset_t set;
bellard579a97f2007-11-11 14:26:47 +00004136 if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
4137 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004138 target_to_host_sigset(&set, p);
4139 unlock_user(p, arg1, 0);
bellard66fb9762003-03-23 01:06:05 +00004140 ret = get_errno(sigsuspend(&set));
4141 }
4142 break;
4143 case TARGET_NR_rt_sigtimedwait:
4144 {
bellard66fb9762003-03-23 01:06:05 +00004145 sigset_t set;
4146 struct timespec uts, *puts;
4147 siginfo_t uinfo;
ths3b46e622007-09-17 08:09:54 +00004148
bellard579a97f2007-11-11 14:26:47 +00004149 if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
4150 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004151 target_to_host_sigset(&set, p);
4152 unlock_user(p, arg1, 0);
4153 if (arg3) {
bellard66fb9762003-03-23 01:06:05 +00004154 puts = &uts;
pbrook53a59602006-03-25 19:31:22 +00004155 target_to_host_timespec(puts, arg3);
bellard66fb9762003-03-23 01:06:05 +00004156 } else {
4157 puts = NULL;
4158 }
4159 ret = get_errno(sigtimedwait(&set, &uinfo, puts));
pbrook53a59602006-03-25 19:31:22 +00004160 if (!is_error(ret) && arg2) {
pbrooke1e3f302008-05-30 21:53:38 +00004161 if (!(p = lock_user(VERIFY_WRITE, arg2, sizeof(target_siginfo_t), 0)))
bellard579a97f2007-11-11 14:26:47 +00004162 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004163 host_to_target_siginfo(p, &uinfo);
pbrooke1e3f302008-05-30 21:53:38 +00004164 unlock_user(p, arg2, sizeof(target_siginfo_t));
bellard66fb9762003-03-23 01:06:05 +00004165 }
4166 }
4167 break;
4168 case TARGET_NR_rt_sigqueueinfo:
4169 {
4170 siginfo_t uinfo;
bellard579a97f2007-11-11 14:26:47 +00004171 if (!(p = lock_user(VERIFY_READ, arg3, sizeof(target_sigset_t), 1)))
4172 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004173 target_to_host_siginfo(&uinfo, p);
4174 unlock_user(p, arg1, 0);
bellard66fb9762003-03-23 01:06:05 +00004175 ret = get_errno(sys_rt_sigqueueinfo(arg1, arg2, &uinfo));
4176 }
4177 break;
thse5febef2007-04-01 18:31:35 +00004178#ifdef TARGET_NR_sigreturn
bellard66fb9762003-03-23 01:06:05 +00004179 case TARGET_NR_sigreturn:
4180 /* NOTE: ret is eax, so not transcoding must be done */
4181 ret = do_sigreturn(cpu_env);
4182 break;
thse5febef2007-04-01 18:31:35 +00004183#endif
bellard66fb9762003-03-23 01:06:05 +00004184 case TARGET_NR_rt_sigreturn:
4185 /* NOTE: ret is eax, so not transcoding must be done */
4186 ret = do_rt_sigreturn(cpu_env);
4187 break;
bellard31e31b82003-02-18 22:55:36 +00004188 case TARGET_NR_sethostname:
bellard579a97f2007-11-11 14:26:47 +00004189 if (!(p = lock_user_string(arg1)))
4190 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004191 ret = get_errno(sethostname(p, arg2));
4192 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004193 break;
4194 case TARGET_NR_setrlimit:
bellard9de5e442003-03-23 16:49:39 +00004195 {
4196 /* XXX: convert resource ? */
4197 int resource = arg1;
pbrook53a59602006-03-25 19:31:22 +00004198 struct target_rlimit *target_rlim;
bellard9de5e442003-03-23 16:49:39 +00004199 struct rlimit rlim;
bellard579a97f2007-11-11 14:26:47 +00004200 if (!lock_user_struct(VERIFY_READ, target_rlim, arg2, 1))
4201 goto efault;
bellard9de5e442003-03-23 16:49:39 +00004202 rlim.rlim_cur = tswapl(target_rlim->rlim_cur);
4203 rlim.rlim_max = tswapl(target_rlim->rlim_max);
pbrook53a59602006-03-25 19:31:22 +00004204 unlock_user_struct(target_rlim, arg2, 0);
bellard9de5e442003-03-23 16:49:39 +00004205 ret = get_errno(setrlimit(resource, &rlim));
4206 }
4207 break;
bellard31e31b82003-02-18 22:55:36 +00004208 case TARGET_NR_getrlimit:
bellard9de5e442003-03-23 16:49:39 +00004209 {
4210 /* XXX: convert resource ? */
4211 int resource = arg1;
pbrook53a59602006-03-25 19:31:22 +00004212 struct target_rlimit *target_rlim;
bellard9de5e442003-03-23 16:49:39 +00004213 struct rlimit rlim;
ths3b46e622007-09-17 08:09:54 +00004214
bellard9de5e442003-03-23 16:49:39 +00004215 ret = get_errno(getrlimit(resource, &rlim));
4216 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00004217 if (!lock_user_struct(VERIFY_WRITE, target_rlim, arg2, 0))
4218 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004219 rlim.rlim_cur = tswapl(target_rlim->rlim_cur);
4220 rlim.rlim_max = tswapl(target_rlim->rlim_max);
4221 unlock_user_struct(target_rlim, arg2, 1);
bellard9de5e442003-03-23 16:49:39 +00004222 }
4223 }
4224 break;
bellard31e31b82003-02-18 22:55:36 +00004225 case TARGET_NR_getrusage:
bellardb4091862003-05-16 15:39:34 +00004226 {
4227 struct rusage rusage;
bellardb4091862003-05-16 15:39:34 +00004228 ret = get_errno(getrusage(arg1, &rusage));
4229 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00004230 host_to_target_rusage(arg2, &rusage);
bellardb4091862003-05-16 15:39:34 +00004231 }
4232 }
4233 break;
bellard31e31b82003-02-18 22:55:36 +00004234 case TARGET_NR_gettimeofday:
4235 {
bellard31e31b82003-02-18 22:55:36 +00004236 struct timeval tv;
4237 ret = get_errno(gettimeofday(&tv, NULL));
4238 if (!is_error(ret)) {
ths788f5ec2007-12-09 02:37:05 +00004239 if (copy_to_user_timeval(arg1, &tv))
4240 goto efault;
bellard31e31b82003-02-18 22:55:36 +00004241 }
4242 }
4243 break;
4244 case TARGET_NR_settimeofday:
4245 {
bellard31e31b82003-02-18 22:55:36 +00004246 struct timeval tv;
ths788f5ec2007-12-09 02:37:05 +00004247 if (copy_from_user_timeval(&tv, arg1))
4248 goto efault;
bellard31e31b82003-02-18 22:55:36 +00004249 ret = get_errno(settimeofday(&tv, NULL));
4250 }
4251 break;
bellard048f6b42005-11-26 18:47:20 +00004252#ifdef TARGET_NR_select
bellard31e31b82003-02-18 22:55:36 +00004253 case TARGET_NR_select:
bellardf2674e32003-07-09 12:26:09 +00004254 {
pbrook53a59602006-03-25 19:31:22 +00004255 struct target_sel_arg_struct *sel;
blueswir1992f48a2007-10-14 16:27:31 +00004256 abi_ulong inp, outp, exp, tvp;
pbrook53a59602006-03-25 19:31:22 +00004257 long nsel;
4258
bellard579a97f2007-11-11 14:26:47 +00004259 if (!lock_user_struct(VERIFY_READ, sel, arg1, 1))
4260 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004261 nsel = tswapl(sel->n);
4262 inp = tswapl(sel->inp);
4263 outp = tswapl(sel->outp);
4264 exp = tswapl(sel->exp);
4265 tvp = tswapl(sel->tvp);
4266 unlock_user_struct(sel, arg1, 0);
4267 ret = do_select(nsel, inp, outp, exp, tvp);
bellardf2674e32003-07-09 12:26:09 +00004268 }
4269 break;
bellard048f6b42005-11-26 18:47:20 +00004270#endif
bellard31e31b82003-02-18 22:55:36 +00004271 case TARGET_NR_symlink:
pbrook53a59602006-03-25 19:31:22 +00004272 {
4273 void *p2;
4274 p = lock_user_string(arg1);
4275 p2 = lock_user_string(arg2);
bellard579a97f2007-11-11 14:26:47 +00004276 if (!p || !p2)
4277 ret = -TARGET_EFAULT;
4278 else
4279 ret = get_errno(symlink(p, p2));
pbrook53a59602006-03-25 19:31:22 +00004280 unlock_user(p2, arg2, 0);
4281 unlock_user(p, arg1, 0);
4282 }
bellard31e31b82003-02-18 22:55:36 +00004283 break;
thsf0b62432007-09-24 09:25:40 +00004284#if defined(TARGET_NR_symlinkat) && defined(__NR_symlinkat)
4285 case TARGET_NR_symlinkat:
thsf0b62432007-09-24 09:25:40 +00004286 {
bellard579a97f2007-11-11 14:26:47 +00004287 void *p2;
thsf0b62432007-09-24 09:25:40 +00004288 p = lock_user_string(arg1);
4289 p2 = lock_user_string(arg3);
bellard579a97f2007-11-11 14:26:47 +00004290 if (!p || !p2)
ths0da46a62007-10-20 20:23:07 +00004291 ret = -TARGET_EFAULT;
thsf0b62432007-09-24 09:25:40 +00004292 else
4293 ret = get_errno(sys_symlinkat(p, arg2, p2));
bellard579a97f2007-11-11 14:26:47 +00004294 unlock_user(p2, arg3, 0);
4295 unlock_user(p, arg1, 0);
thsf0b62432007-09-24 09:25:40 +00004296 }
4297 break;
4298#endif
bellardebc05482003-09-30 21:08:41 +00004299#ifdef TARGET_NR_oldlstat
bellard31e31b82003-02-18 22:55:36 +00004300 case TARGET_NR_oldlstat:
4301 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004302#endif
bellard31e31b82003-02-18 22:55:36 +00004303 case TARGET_NR_readlink:
pbrook53a59602006-03-25 19:31:22 +00004304 {
4305 void *p2;
4306 p = lock_user_string(arg1);
bellard579a97f2007-11-11 14:26:47 +00004307 p2 = lock_user(VERIFY_WRITE, arg2, arg3, 0);
4308 if (!p || !p2)
4309 ret = -TARGET_EFAULT;
4310 else
4311 ret = get_errno(readlink(path(p), p2, arg3));
pbrook53a59602006-03-25 19:31:22 +00004312 unlock_user(p2, arg2, ret);
4313 unlock_user(p, arg1, 0);
4314 }
bellard31e31b82003-02-18 22:55:36 +00004315 break;
ths5e0ccb12007-09-24 09:26:10 +00004316#if defined(TARGET_NR_readlinkat) && defined(__NR_readlinkat)
4317 case TARGET_NR_readlinkat:
ths5e0ccb12007-09-24 09:26:10 +00004318 {
bellard579a97f2007-11-11 14:26:47 +00004319 void *p2;
ths5e0ccb12007-09-24 09:26:10 +00004320 p = lock_user_string(arg2);
bellard579a97f2007-11-11 14:26:47 +00004321 p2 = lock_user(VERIFY_WRITE, arg3, arg4, 0);
4322 if (!p || !p2)
ths0da46a62007-10-20 20:23:07 +00004323 ret = -TARGET_EFAULT;
ths5e0ccb12007-09-24 09:26:10 +00004324 else
4325 ret = get_errno(sys_readlinkat(arg1, path(p), p2, arg4));
bellard579a97f2007-11-11 14:26:47 +00004326 unlock_user(p2, arg3, ret);
4327 unlock_user(p, arg2, 0);
ths5e0ccb12007-09-24 09:26:10 +00004328 }
4329 break;
4330#endif
thse5febef2007-04-01 18:31:35 +00004331#ifdef TARGET_NR_uselib
bellard31e31b82003-02-18 22:55:36 +00004332 case TARGET_NR_uselib:
4333 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00004334#endif
4335#ifdef TARGET_NR_swapon
bellard31e31b82003-02-18 22:55:36 +00004336 case TARGET_NR_swapon:
bellard579a97f2007-11-11 14:26:47 +00004337 if (!(p = lock_user_string(arg1)))
4338 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004339 ret = get_errno(swapon(p, arg2));
4340 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004341 break;
thse5febef2007-04-01 18:31:35 +00004342#endif
bellard31e31b82003-02-18 22:55:36 +00004343 case TARGET_NR_reboot:
4344 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00004345#ifdef TARGET_NR_readdir
bellard31e31b82003-02-18 22:55:36 +00004346 case TARGET_NR_readdir:
4347 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00004348#endif
4349#ifdef TARGET_NR_mmap
bellard31e31b82003-02-18 22:55:36 +00004350 case TARGET_NR_mmap:
bellardd2fd1af2007-11-14 18:08:56 +00004351#if (defined(TARGET_I386) && defined(TARGET_ABI32)) || defined(TARGET_ARM) || defined(TARGET_M68K) || defined(TARGET_CRIS)
bellard31e31b82003-02-18 22:55:36 +00004352 {
blueswir1992f48a2007-10-14 16:27:31 +00004353 abi_ulong *v;
4354 abi_ulong v1, v2, v3, v4, v5, v6;
bellard579a97f2007-11-11 14:26:47 +00004355 if (!(v = lock_user(VERIFY_READ, arg1, 6 * sizeof(abi_ulong), 1)))
4356 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004357 v1 = tswapl(v[0]);
4358 v2 = tswapl(v[1]);
4359 v3 = tswapl(v[2]);
4360 v4 = tswapl(v[3]);
4361 v5 = tswapl(v[4]);
4362 v6 = tswapl(v[5]);
4363 unlock_user(v, arg1, 0);
ths5fafdf22007-09-16 21:08:06 +00004364 ret = get_errno(target_mmap(v1, v2, v3,
bellard5286db72003-06-05 00:57:30 +00004365 target_to_host_bitmask(v4, mmap_flags_tbl),
4366 v5, v6));
bellard31e31b82003-02-18 22:55:36 +00004367 }
bellard31e31b82003-02-18 22:55:36 +00004368#else
ths5fafdf22007-09-16 21:08:06 +00004369 ret = get_errno(target_mmap(arg1, arg2, arg3,
4370 target_to_host_bitmask(arg4, mmap_flags_tbl),
bellard6fb883e2003-07-09 17:12:39 +00004371 arg5,
4372 arg6));
bellard31e31b82003-02-18 22:55:36 +00004373#endif
bellard6fb883e2003-07-09 17:12:39 +00004374 break;
thse5febef2007-04-01 18:31:35 +00004375#endif
bellarda315a142005-01-30 22:59:18 +00004376#ifdef TARGET_NR_mmap2
bellard6fb883e2003-07-09 17:12:39 +00004377 case TARGET_NR_mmap2:
pbrookbb7ec042008-03-25 22:28:25 +00004378#ifndef MMAP_SHIFT
bellardc573ff62004-01-04 15:51:36 +00004379#define MMAP_SHIFT 12
bellardc573ff62004-01-04 15:51:36 +00004380#endif
ths5fafdf22007-09-16 21:08:06 +00004381 ret = get_errno(target_mmap(arg1, arg2, arg3,
4382 target_to_host_bitmask(arg4, mmap_flags_tbl),
bellard5286db72003-06-05 00:57:30 +00004383 arg5,
bellardc573ff62004-01-04 15:51:36 +00004384 arg6 << MMAP_SHIFT));
bellard31e31b82003-02-18 22:55:36 +00004385 break;
bellarda315a142005-01-30 22:59:18 +00004386#endif
bellard31e31b82003-02-18 22:55:36 +00004387 case TARGET_NR_munmap:
bellard54936002003-05-13 00:25:15 +00004388 ret = get_errno(target_munmap(arg1, arg2));
bellard31e31b82003-02-18 22:55:36 +00004389 break;
bellard9de5e442003-03-23 16:49:39 +00004390 case TARGET_NR_mprotect:
bellard54936002003-05-13 00:25:15 +00004391 ret = get_errno(target_mprotect(arg1, arg2, arg3));
bellard9de5e442003-03-23 16:49:39 +00004392 break;
thse5febef2007-04-01 18:31:35 +00004393#ifdef TARGET_NR_mremap
bellard9de5e442003-03-23 16:49:39 +00004394 case TARGET_NR_mremap:
bellard54936002003-05-13 00:25:15 +00004395 ret = get_errno(target_mremap(arg1, arg2, arg3, arg4, arg5));
bellard9de5e442003-03-23 16:49:39 +00004396 break;
thse5febef2007-04-01 18:31:35 +00004397#endif
pbrook53a59602006-03-25 19:31:22 +00004398 /* ??? msync/mlock/munlock are broken for softmmu. */
thse5febef2007-04-01 18:31:35 +00004399#ifdef TARGET_NR_msync
bellard9de5e442003-03-23 16:49:39 +00004400 case TARGET_NR_msync:
pbrook53a59602006-03-25 19:31:22 +00004401 ret = get_errno(msync(g2h(arg1), arg2, arg3));
bellard9de5e442003-03-23 16:49:39 +00004402 break;
thse5febef2007-04-01 18:31:35 +00004403#endif
4404#ifdef TARGET_NR_mlock
bellard9de5e442003-03-23 16:49:39 +00004405 case TARGET_NR_mlock:
pbrook53a59602006-03-25 19:31:22 +00004406 ret = get_errno(mlock(g2h(arg1), arg2));
bellard9de5e442003-03-23 16:49:39 +00004407 break;
thse5febef2007-04-01 18:31:35 +00004408#endif
4409#ifdef TARGET_NR_munlock
bellard9de5e442003-03-23 16:49:39 +00004410 case TARGET_NR_munlock:
pbrook53a59602006-03-25 19:31:22 +00004411 ret = get_errno(munlock(g2h(arg1), arg2));
bellard9de5e442003-03-23 16:49:39 +00004412 break;
thse5febef2007-04-01 18:31:35 +00004413#endif
4414#ifdef TARGET_NR_mlockall
bellard9de5e442003-03-23 16:49:39 +00004415 case TARGET_NR_mlockall:
4416 ret = get_errno(mlockall(arg1));
4417 break;
thse5febef2007-04-01 18:31:35 +00004418#endif
4419#ifdef TARGET_NR_munlockall
bellard9de5e442003-03-23 16:49:39 +00004420 case TARGET_NR_munlockall:
4421 ret = get_errno(munlockall());
4422 break;
thse5febef2007-04-01 18:31:35 +00004423#endif
bellard31e31b82003-02-18 22:55:36 +00004424 case TARGET_NR_truncate:
bellard579a97f2007-11-11 14:26:47 +00004425 if (!(p = lock_user_string(arg1)))
4426 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004427 ret = get_errno(truncate(p, arg2));
4428 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004429 break;
4430 case TARGET_NR_ftruncate:
4431 ret = get_errno(ftruncate(arg1, arg2));
4432 break;
4433 case TARGET_NR_fchmod:
4434 ret = get_errno(fchmod(arg1, arg2));
4435 break;
ths814d7972007-09-24 09:26:51 +00004436#if defined(TARGET_NR_fchmodat) && defined(__NR_fchmodat)
4437 case TARGET_NR_fchmodat:
bellard579a97f2007-11-11 14:26:47 +00004438 if (!(p = lock_user_string(arg2)))
4439 goto efault;
4440 ret = get_errno(sys_fchmodat(arg1, p, arg3, arg4));
4441 unlock_user(p, arg2, 0);
ths814d7972007-09-24 09:26:51 +00004442 break;
4443#endif
bellard31e31b82003-02-18 22:55:36 +00004444 case TARGET_NR_getpriority:
thsc6cda172007-10-09 03:42:34 +00004445 /* libc does special remapping of the return value of
4446 * sys_getpriority() so it's just easiest to call
4447 * sys_getpriority() directly rather than through libc. */
4448 ret = sys_getpriority(arg1, arg2);
bellard31e31b82003-02-18 22:55:36 +00004449 break;
4450 case TARGET_NR_setpriority:
4451 ret = get_errno(setpriority(arg1, arg2, arg3));
4452 break;
bellardebc05482003-09-30 21:08:41 +00004453#ifdef TARGET_NR_profil
bellard31e31b82003-02-18 22:55:36 +00004454 case TARGET_NR_profil:
4455 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004456#endif
bellard31e31b82003-02-18 22:55:36 +00004457 case TARGET_NR_statfs:
bellard579a97f2007-11-11 14:26:47 +00004458 if (!(p = lock_user_string(arg1)))
4459 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004460 ret = get_errno(statfs(path(p), &stfs));
4461 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004462 convert_statfs:
4463 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00004464 struct target_statfs *target_stfs;
ths3b46e622007-09-17 08:09:54 +00004465
bellard579a97f2007-11-11 14:26:47 +00004466 if (!lock_user_struct(VERIFY_WRITE, target_stfs, arg2, 0))
4467 goto efault;
4468 __put_user(stfs.f_type, &target_stfs->f_type);
4469 __put_user(stfs.f_bsize, &target_stfs->f_bsize);
4470 __put_user(stfs.f_blocks, &target_stfs->f_blocks);
4471 __put_user(stfs.f_bfree, &target_stfs->f_bfree);
4472 __put_user(stfs.f_bavail, &target_stfs->f_bavail);
4473 __put_user(stfs.f_files, &target_stfs->f_files);
4474 __put_user(stfs.f_ffree, &target_stfs->f_ffree);
4475 __put_user(stfs.f_fsid.__val[0], &target_stfs->f_fsid.val[0]);
4476 __put_user(stfs.f_fsid.__val[1], &target_stfs->f_fsid.val[1]);
4477 __put_user(stfs.f_namelen, &target_stfs->f_namelen);
pbrook53a59602006-03-25 19:31:22 +00004478 unlock_user_struct(target_stfs, arg2, 1);
bellard31e31b82003-02-18 22:55:36 +00004479 }
4480 break;
4481 case TARGET_NR_fstatfs:
bellard56c8f682005-11-28 22:28:41 +00004482 ret = get_errno(fstatfs(arg1, &stfs));
bellard31e31b82003-02-18 22:55:36 +00004483 goto convert_statfs;
bellard56c8f682005-11-28 22:28:41 +00004484#ifdef TARGET_NR_statfs64
4485 case TARGET_NR_statfs64:
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(statfs(path(p), &stfs));
4489 unlock_user(p, arg1, 0);
bellard56c8f682005-11-28 22:28:41 +00004490 convert_statfs64:
4491 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00004492 struct target_statfs64 *target_stfs;
ths3b46e622007-09-17 08:09:54 +00004493
bellard579a97f2007-11-11 14:26:47 +00004494 if (!lock_user_struct(VERIFY_WRITE, target_stfs, arg3, 0))
4495 goto efault;
4496 __put_user(stfs.f_type, &target_stfs->f_type);
4497 __put_user(stfs.f_bsize, &target_stfs->f_bsize);
4498 __put_user(stfs.f_blocks, &target_stfs->f_blocks);
4499 __put_user(stfs.f_bfree, &target_stfs->f_bfree);
4500 __put_user(stfs.f_bavail, &target_stfs->f_bavail);
4501 __put_user(stfs.f_files, &target_stfs->f_files);
4502 __put_user(stfs.f_ffree, &target_stfs->f_ffree);
4503 __put_user(stfs.f_fsid.__val[0], &target_stfs->f_fsid.val[0]);
4504 __put_user(stfs.f_fsid.__val[1], &target_stfs->f_fsid.val[1]);
4505 __put_user(stfs.f_namelen, &target_stfs->f_namelen);
4506 unlock_user_struct(target_stfs, arg3, 1);
bellard56c8f682005-11-28 22:28:41 +00004507 }
4508 break;
4509 case TARGET_NR_fstatfs64:
4510 ret = get_errno(fstatfs(arg1, &stfs));
4511 goto convert_statfs64;
4512#endif
bellardebc05482003-09-30 21:08:41 +00004513#ifdef TARGET_NR_ioperm
bellard31e31b82003-02-18 22:55:36 +00004514 case TARGET_NR_ioperm:
4515 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004516#endif
thse5febef2007-04-01 18:31:35 +00004517#ifdef TARGET_NR_socketcall
bellard31e31b82003-02-18 22:55:36 +00004518 case TARGET_NR_socketcall:
pbrook53a59602006-03-25 19:31:22 +00004519 ret = do_socketcall(arg1, arg2);
bellard31e31b82003-02-18 22:55:36 +00004520 break;
thse5febef2007-04-01 18:31:35 +00004521#endif
bellard3532fa72006-06-24 15:06:03 +00004522#ifdef TARGET_NR_accept
4523 case TARGET_NR_accept:
pbrook1be9e1d2006-11-19 15:26:04 +00004524 ret = do_accept(arg1, arg2, arg3);
bellard3532fa72006-06-24 15:06:03 +00004525 break;
4526#endif
4527#ifdef TARGET_NR_bind
4528 case TARGET_NR_bind:
4529 ret = do_bind(arg1, arg2, arg3);
4530 break;
4531#endif
4532#ifdef TARGET_NR_connect
4533 case TARGET_NR_connect:
4534 ret = do_connect(arg1, arg2, arg3);
4535 break;
4536#endif
4537#ifdef TARGET_NR_getpeername
4538 case TARGET_NR_getpeername:
pbrook1be9e1d2006-11-19 15:26:04 +00004539 ret = do_getpeername(arg1, arg2, arg3);
bellard3532fa72006-06-24 15:06:03 +00004540 break;
4541#endif
4542#ifdef TARGET_NR_getsockname
4543 case TARGET_NR_getsockname:
pbrook1be9e1d2006-11-19 15:26:04 +00004544 ret = do_getsockname(arg1, arg2, arg3);
bellard3532fa72006-06-24 15:06:03 +00004545 break;
4546#endif
4547#ifdef TARGET_NR_getsockopt
4548 case TARGET_NR_getsockopt:
4549 ret = do_getsockopt(arg1, arg2, arg3, arg4, arg5);
4550 break;
4551#endif
4552#ifdef TARGET_NR_listen
4553 case TARGET_NR_listen:
pbrook1be9e1d2006-11-19 15:26:04 +00004554 ret = get_errno(listen(arg1, arg2));
bellard3532fa72006-06-24 15:06:03 +00004555 break;
4556#endif
4557#ifdef TARGET_NR_recv
4558 case TARGET_NR_recv:
pbrook214201b2007-03-17 01:27:24 +00004559 ret = do_recvfrom(arg1, arg2, arg3, arg4, 0, 0);
bellard3532fa72006-06-24 15:06:03 +00004560 break;
4561#endif
4562#ifdef TARGET_NR_recvfrom
4563 case TARGET_NR_recvfrom:
pbrook214201b2007-03-17 01:27:24 +00004564 ret = do_recvfrom(arg1, arg2, arg3, arg4, arg5, arg6);
bellard3532fa72006-06-24 15:06:03 +00004565 break;
4566#endif
4567#ifdef TARGET_NR_recvmsg
4568 case TARGET_NR_recvmsg:
4569 ret = do_sendrecvmsg(arg1, arg2, arg3, 0);
4570 break;
4571#endif
4572#ifdef TARGET_NR_send
4573 case TARGET_NR_send:
pbrook1be9e1d2006-11-19 15:26:04 +00004574 ret = do_sendto(arg1, arg2, arg3, arg4, 0, 0);
bellard3532fa72006-06-24 15:06:03 +00004575 break;
4576#endif
4577#ifdef TARGET_NR_sendmsg
4578 case TARGET_NR_sendmsg:
4579 ret = do_sendrecvmsg(arg1, arg2, arg3, 1);
4580 break;
4581#endif
4582#ifdef TARGET_NR_sendto
4583 case TARGET_NR_sendto:
pbrook1be9e1d2006-11-19 15:26:04 +00004584 ret = do_sendto(arg1, arg2, arg3, arg4, arg5, arg6);
bellard3532fa72006-06-24 15:06:03 +00004585 break;
4586#endif
4587#ifdef TARGET_NR_shutdown
4588 case TARGET_NR_shutdown:
pbrook1be9e1d2006-11-19 15:26:04 +00004589 ret = get_errno(shutdown(arg1, arg2));
bellard3532fa72006-06-24 15:06:03 +00004590 break;
4591#endif
4592#ifdef TARGET_NR_socket
4593 case TARGET_NR_socket:
4594 ret = do_socket(arg1, arg2, arg3);
4595 break;
4596#endif
4597#ifdef TARGET_NR_socketpair
4598 case TARGET_NR_socketpair:
pbrook1be9e1d2006-11-19 15:26:04 +00004599 ret = do_socketpair(arg1, arg2, arg3, arg4);
bellard3532fa72006-06-24 15:06:03 +00004600 break;
4601#endif
4602#ifdef TARGET_NR_setsockopt
4603 case TARGET_NR_setsockopt:
4604 ret = do_setsockopt(arg1, arg2, arg3, arg4, (socklen_t) arg5);
4605 break;
4606#endif
ths7494b0f2007-02-11 18:26:53 +00004607
bellard31e31b82003-02-18 22:55:36 +00004608 case TARGET_NR_syslog:
bellard579a97f2007-11-11 14:26:47 +00004609 if (!(p = lock_user_string(arg2)))
4610 goto efault;
thse5574482007-02-11 20:03:13 +00004611 ret = get_errno(sys_syslog((int)arg1, p, (int)arg3));
4612 unlock_user(p, arg2, 0);
ths7494b0f2007-02-11 18:26:53 +00004613 break;
4614
bellard31e31b82003-02-18 22:55:36 +00004615 case TARGET_NR_setitimer:
bellard66fb9762003-03-23 01:06:05 +00004616 {
bellard66fb9762003-03-23 01:06:05 +00004617 struct itimerval value, ovalue, *pvalue;
4618
pbrook53a59602006-03-25 19:31:22 +00004619 if (arg2) {
bellard66fb9762003-03-23 01:06:05 +00004620 pvalue = &value;
ths788f5ec2007-12-09 02:37:05 +00004621 if (copy_from_user_timeval(&pvalue->it_interval, arg2)
4622 || copy_from_user_timeval(&pvalue->it_value,
4623 arg2 + sizeof(struct target_timeval)))
4624 goto efault;
bellard66fb9762003-03-23 01:06:05 +00004625 } else {
4626 pvalue = NULL;
4627 }
4628 ret = get_errno(setitimer(arg1, pvalue, &ovalue));
pbrook53a59602006-03-25 19:31:22 +00004629 if (!is_error(ret) && arg3) {
ths788f5ec2007-12-09 02:37:05 +00004630 if (copy_to_user_timeval(arg3,
4631 &ovalue.it_interval)
4632 || copy_to_user_timeval(arg3 + sizeof(struct target_timeval),
4633 &ovalue.it_value))
4634 goto efault;
bellard66fb9762003-03-23 01:06:05 +00004635 }
4636 }
4637 break;
bellard31e31b82003-02-18 22:55:36 +00004638 case TARGET_NR_getitimer:
bellard66fb9762003-03-23 01:06:05 +00004639 {
bellard66fb9762003-03-23 01:06:05 +00004640 struct itimerval value;
ths3b46e622007-09-17 08:09:54 +00004641
bellard66fb9762003-03-23 01:06:05 +00004642 ret = get_errno(getitimer(arg1, &value));
pbrook53a59602006-03-25 19:31:22 +00004643 if (!is_error(ret) && arg2) {
ths788f5ec2007-12-09 02:37:05 +00004644 if (copy_to_user_timeval(arg2,
4645 &value.it_interval)
4646 || copy_to_user_timeval(arg2 + sizeof(struct target_timeval),
4647 &value.it_value))
4648 goto efault;
bellard66fb9762003-03-23 01:06:05 +00004649 }
4650 }
4651 break;
bellard31e31b82003-02-18 22:55:36 +00004652 case TARGET_NR_stat:
bellard579a97f2007-11-11 14:26:47 +00004653 if (!(p = lock_user_string(arg1)))
4654 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004655 ret = get_errno(stat(path(p), &st));
4656 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004657 goto do_stat;
4658 case TARGET_NR_lstat:
bellard579a97f2007-11-11 14:26:47 +00004659 if (!(p = lock_user_string(arg1)))
4660 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004661 ret = get_errno(lstat(path(p), &st));
4662 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004663 goto do_stat;
4664 case TARGET_NR_fstat:
4665 {
4666 ret = get_errno(fstat(arg1, &st));
4667 do_stat:
4668 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00004669 struct target_stat *target_st;
thse3584652007-06-01 11:49:38 +00004670
bellard579a97f2007-11-11 14:26:47 +00004671 if (!lock_user_struct(VERIFY_WRITE, target_st, arg2, 0))
4672 goto efault;
bellardd2fd1af2007-11-14 18:08:56 +00004673 __put_user(st.st_dev, &target_st->st_dev);
4674 __put_user(st.st_ino, &target_st->st_ino);
4675 __put_user(st.st_mode, &target_st->st_mode);
4676 __put_user(st.st_uid, &target_st->st_uid);
4677 __put_user(st.st_gid, &target_st->st_gid);
4678 __put_user(st.st_nlink, &target_st->st_nlink);
4679 __put_user(st.st_rdev, &target_st->st_rdev);
4680 __put_user(st.st_size, &target_st->st_size);
4681 __put_user(st.st_blksize, &target_st->st_blksize);
4682 __put_user(st.st_blocks, &target_st->st_blocks);
4683 __put_user(st.st_atime, &target_st->target_st_atime);
4684 __put_user(st.st_mtime, &target_st->target_st_mtime);
4685 __put_user(st.st_ctime, &target_st->target_st_ctime);
pbrook53a59602006-03-25 19:31:22 +00004686 unlock_user_struct(target_st, arg2, 1);
bellard31e31b82003-02-18 22:55:36 +00004687 }
4688 }
4689 break;
bellardebc05482003-09-30 21:08:41 +00004690#ifdef TARGET_NR_olduname
bellard31e31b82003-02-18 22:55:36 +00004691 case TARGET_NR_olduname:
4692 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004693#endif
4694#ifdef TARGET_NR_iopl
bellard31e31b82003-02-18 22:55:36 +00004695 case TARGET_NR_iopl:
4696 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004697#endif
bellard31e31b82003-02-18 22:55:36 +00004698 case TARGET_NR_vhangup:
4699 ret = get_errno(vhangup());
4700 break;
bellardebc05482003-09-30 21:08:41 +00004701#ifdef TARGET_NR_idle
bellard31e31b82003-02-18 22:55:36 +00004702 case TARGET_NR_idle:
4703 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004704#endif
bellard42ad6ae2005-01-03 22:48:11 +00004705#ifdef TARGET_NR_syscall
4706 case TARGET_NR_syscall:
4707 ret = do_syscall(cpu_env,arg1 & 0xffff,arg2,arg3,arg4,arg5,arg6,0);
4708 break;
4709#endif
bellard31e31b82003-02-18 22:55:36 +00004710 case TARGET_NR_wait4:
4711 {
4712 int status;
blueswir1992f48a2007-10-14 16:27:31 +00004713 abi_long status_ptr = arg2;
bellard31e31b82003-02-18 22:55:36 +00004714 struct rusage rusage, *rusage_ptr;
blueswir1992f48a2007-10-14 16:27:31 +00004715 abi_ulong target_rusage = arg4;
bellard31e31b82003-02-18 22:55:36 +00004716 if (target_rusage)
4717 rusage_ptr = &rusage;
4718 else
4719 rusage_ptr = NULL;
4720 ret = get_errno(wait4(arg1, &status, arg3, rusage_ptr));
4721 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +00004722 if (status_ptr) {
4723 if (put_user_s32(status, status_ptr))
4724 goto efault;
bellard31e31b82003-02-18 22:55:36 +00004725 }
bellard2f619692007-11-16 10:46:05 +00004726 if (target_rusage)
4727 host_to_target_rusage(target_rusage, &rusage);
bellard31e31b82003-02-18 22:55:36 +00004728 }
4729 }
4730 break;
thse5febef2007-04-01 18:31:35 +00004731#ifdef TARGET_NR_swapoff
bellard31e31b82003-02-18 22:55:36 +00004732 case TARGET_NR_swapoff:
bellard579a97f2007-11-11 14:26:47 +00004733 if (!(p = lock_user_string(arg1)))
4734 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004735 ret = get_errno(swapoff(p));
4736 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004737 break;
thse5febef2007-04-01 18:31:35 +00004738#endif
bellard31e31b82003-02-18 22:55:36 +00004739 case TARGET_NR_sysinfo:
bellarda5448a72004-06-19 16:59:03 +00004740 {
pbrook53a59602006-03-25 19:31:22 +00004741 struct target_sysinfo *target_value;
bellarda5448a72004-06-19 16:59:03 +00004742 struct sysinfo value;
4743 ret = get_errno(sysinfo(&value));
pbrook53a59602006-03-25 19:31:22 +00004744 if (!is_error(ret) && arg1)
bellarda5448a72004-06-19 16:59:03 +00004745 {
bellard579a97f2007-11-11 14:26:47 +00004746 if (!lock_user_struct(VERIFY_WRITE, target_value, arg1, 0))
4747 goto efault;
bellarda5448a72004-06-19 16:59:03 +00004748 __put_user(value.uptime, &target_value->uptime);
4749 __put_user(value.loads[0], &target_value->loads[0]);
4750 __put_user(value.loads[1], &target_value->loads[1]);
4751 __put_user(value.loads[2], &target_value->loads[2]);
4752 __put_user(value.totalram, &target_value->totalram);
4753 __put_user(value.freeram, &target_value->freeram);
4754 __put_user(value.sharedram, &target_value->sharedram);
4755 __put_user(value.bufferram, &target_value->bufferram);
4756 __put_user(value.totalswap, &target_value->totalswap);
4757 __put_user(value.freeswap, &target_value->freeswap);
4758 __put_user(value.procs, &target_value->procs);
4759 __put_user(value.totalhigh, &target_value->totalhigh);
4760 __put_user(value.freehigh, &target_value->freehigh);
4761 __put_user(value.mem_unit, &target_value->mem_unit);
pbrook53a59602006-03-25 19:31:22 +00004762 unlock_user_struct(target_value, arg1, 1);
bellarda5448a72004-06-19 16:59:03 +00004763 }
4764 }
4765 break;
thse5febef2007-04-01 18:31:35 +00004766#ifdef TARGET_NR_ipc
bellard31e31b82003-02-18 22:55:36 +00004767 case TARGET_NR_ipc:
bellard8853f862004-02-22 14:57:26 +00004768 ret = do_ipc(arg1, arg2, arg3, arg4, arg5, arg6);
4769 break;
thse5febef2007-04-01 18:31:35 +00004770#endif
bellard31e31b82003-02-18 22:55:36 +00004771 case TARGET_NR_fsync:
4772 ret = get_errno(fsync(arg1));
4773 break;
bellard31e31b82003-02-18 22:55:36 +00004774 case TARGET_NR_clone:
aurel320b6d3ae2008-09-15 07:43:43 +00004775#if defined(TARGET_SH4)
4776 ret = get_errno(do_fork(cpu_env, arg1, arg2, arg3, arg5, arg4));
4777#else
pbrookd865bab2008-06-07 22:12:17 +00004778 ret = get_errno(do_fork(cpu_env, arg1, arg2, arg3, arg4, arg5));
aurel320b6d3ae2008-09-15 07:43:43 +00004779#endif
bellard1b6b0292003-03-22 17:31:38 +00004780 break;
bellardec86b0f2003-04-11 00:15:04 +00004781#ifdef __NR_exit_group
4782 /* new thread calls */
4783 case TARGET_NR_exit_group:
bellarde9009672005-04-26 20:42:36 +00004784 gdb_exit(cpu_env, arg1);
bellardec86b0f2003-04-11 00:15:04 +00004785 ret = get_errno(exit_group(arg1));
4786 break;
4787#endif
bellard31e31b82003-02-18 22:55:36 +00004788 case TARGET_NR_setdomainname:
bellard579a97f2007-11-11 14:26:47 +00004789 if (!(p = lock_user_string(arg1)))
4790 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004791 ret = get_errno(setdomainname(p, arg2));
4792 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004793 break;
4794 case TARGET_NR_uname:
4795 /* no need to transcode because we use the linux syscall */
bellard29e619b2004-09-13 21:41:04 +00004796 {
4797 struct new_utsname * buf;
ths3b46e622007-09-17 08:09:54 +00004798
bellard579a97f2007-11-11 14:26:47 +00004799 if (!lock_user_struct(VERIFY_WRITE, buf, arg1, 0))
4800 goto efault;
bellard29e619b2004-09-13 21:41:04 +00004801 ret = get_errno(sys_uname(buf));
4802 if (!is_error(ret)) {
4803 /* Overrite the native machine name with whatever is being
4804 emulated. */
4805 strcpy (buf->machine, UNAME_MACHINE);
pbrookc5937222006-05-14 11:30:38 +00004806 /* Allow the user to override the reported release. */
4807 if (qemu_uname_release && *qemu_uname_release)
4808 strcpy (buf->release, qemu_uname_release);
bellard29e619b2004-09-13 21:41:04 +00004809 }
pbrook53a59602006-03-25 19:31:22 +00004810 unlock_user_struct(buf, arg1, 1);
bellard29e619b2004-09-13 21:41:04 +00004811 }
bellard31e31b82003-02-18 22:55:36 +00004812 break;
bellard6dbad632003-03-16 18:05:05 +00004813#ifdef TARGET_I386
bellard31e31b82003-02-18 22:55:36 +00004814 case TARGET_NR_modify_ldt:
bellard03acab62007-11-11 14:57:14 +00004815 ret = do_modify_ldt(cpu_env, arg1, arg2, arg3);
bellard5cd43932003-03-29 16:54:36 +00004816 break;
j_mayer84409dd2007-04-06 08:56:50 +00004817#if !defined(TARGET_X86_64)
bellard5cd43932003-03-29 16:54:36 +00004818 case TARGET_NR_vm86old:
4819 goto unimplemented;
4820 case TARGET_NR_vm86:
pbrook53a59602006-03-25 19:31:22 +00004821 ret = do_vm86(cpu_env, arg1, arg2);
bellard6dbad632003-03-16 18:05:05 +00004822 break;
4823#endif
j_mayer84409dd2007-04-06 08:56:50 +00004824#endif
bellard31e31b82003-02-18 22:55:36 +00004825 case TARGET_NR_adjtimex:
4826 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00004827#ifdef TARGET_NR_create_module
bellard31e31b82003-02-18 22:55:36 +00004828 case TARGET_NR_create_module:
thse5febef2007-04-01 18:31:35 +00004829#endif
bellard31e31b82003-02-18 22:55:36 +00004830 case TARGET_NR_init_module:
4831 case TARGET_NR_delete_module:
thse5febef2007-04-01 18:31:35 +00004832#ifdef TARGET_NR_get_kernel_syms
bellard31e31b82003-02-18 22:55:36 +00004833 case TARGET_NR_get_kernel_syms:
thse5febef2007-04-01 18:31:35 +00004834#endif
bellard31e31b82003-02-18 22:55:36 +00004835 goto unimplemented;
4836 case TARGET_NR_quotactl:
4837 goto unimplemented;
4838 case TARGET_NR_getpgid:
4839 ret = get_errno(getpgid(arg1));
4840 break;
4841 case TARGET_NR_fchdir:
4842 ret = get_errno(fchdir(arg1));
4843 break;
j_mayer84409dd2007-04-06 08:56:50 +00004844#ifdef TARGET_NR_bdflush /* not on x86_64 */
bellard31e31b82003-02-18 22:55:36 +00004845 case TARGET_NR_bdflush:
4846 goto unimplemented;
j_mayer84409dd2007-04-06 08:56:50 +00004847#endif
thse5febef2007-04-01 18:31:35 +00004848#ifdef TARGET_NR_sysfs
bellard31e31b82003-02-18 22:55:36 +00004849 case TARGET_NR_sysfs:
4850 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00004851#endif
bellard31e31b82003-02-18 22:55:36 +00004852 case TARGET_NR_personality:
bellard1b6b0292003-03-22 17:31:38 +00004853 ret = get_errno(personality(arg1));
bellard31e31b82003-02-18 22:55:36 +00004854 break;
thse5febef2007-04-01 18:31:35 +00004855#ifdef TARGET_NR_afs_syscall
bellard31e31b82003-02-18 22:55:36 +00004856 case TARGET_NR_afs_syscall:
4857 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00004858#endif
j_mayer7a3148a2007-04-05 07:13:51 +00004859#ifdef TARGET_NR__llseek /* Not on alpha */
bellard31e31b82003-02-18 22:55:36 +00004860 case TARGET_NR__llseek:
4861 {
bellard4f2ac232004-04-26 19:44:02 +00004862#if defined (__x86_64__)
4863 ret = get_errno(lseek(arg1, ((uint64_t )arg2 << 32) | arg3, arg5));
bellard2f619692007-11-16 10:46:05 +00004864 if (put_user_s64(ret, arg4))
4865 goto efault;
bellard4f2ac232004-04-26 19:44:02 +00004866#else
bellard31e31b82003-02-18 22:55:36 +00004867 int64_t res;
4868 ret = get_errno(_llseek(arg1, arg2, arg3, &res, arg5));
bellard2f619692007-11-16 10:46:05 +00004869 if (put_user_s64(res, arg4))
4870 goto efault;
bellard4f2ac232004-04-26 19:44:02 +00004871#endif
bellard31e31b82003-02-18 22:55:36 +00004872 }
4873 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004874#endif
bellard31e31b82003-02-18 22:55:36 +00004875 case TARGET_NR_getdents:
blueswir1992f48a2007-10-14 16:27:31 +00004876#if TARGET_ABI_BITS != 32
pbrook53a59602006-03-25 19:31:22 +00004877 goto unimplemented;
blueswir1992f48a2007-10-14 16:27:31 +00004878#elif TARGET_ABI_BITS == 32 && HOST_LONG_BITS == 64
bellard4add45b2003-06-05 01:52:59 +00004879 {
pbrook53a59602006-03-25 19:31:22 +00004880 struct target_dirent *target_dirp;
aurel326556a832008-10-13 21:08:17 +00004881 struct linux_dirent *dirp;
blueswir1992f48a2007-10-14 16:27:31 +00004882 abi_long count = arg3;
bellard4add45b2003-06-05 01:52:59 +00004883
4884 dirp = malloc(count);
ths0da46a62007-10-20 20:23:07 +00004885 if (!dirp) {
bellard579a97f2007-11-11 14:26:47 +00004886 ret = -TARGET_ENOMEM;
ths0da46a62007-10-20 20:23:07 +00004887 goto fail;
4888 }
ths3b46e622007-09-17 08:09:54 +00004889
bellard4add45b2003-06-05 01:52:59 +00004890 ret = get_errno(sys_getdents(arg1, dirp, count));
4891 if (!is_error(ret)) {
aurel326556a832008-10-13 21:08:17 +00004892 struct linux_dirent *de;
bellard4add45b2003-06-05 01:52:59 +00004893 struct target_dirent *tde;
4894 int len = ret;
4895 int reclen, treclen;
4896 int count1, tnamelen;
4897
4898 count1 = 0;
4899 de = dirp;
bellard579a97f2007-11-11 14:26:47 +00004900 if (!(target_dirp = lock_user(VERIFY_WRITE, arg2, count, 0)))
4901 goto efault;
bellard4add45b2003-06-05 01:52:59 +00004902 tde = target_dirp;
4903 while (len > 0) {
4904 reclen = de->d_reclen;
blueswir1992f48a2007-10-14 16:27:31 +00004905 treclen = reclen - (2 * (sizeof(long) - sizeof(abi_long)));
bellard4add45b2003-06-05 01:52:59 +00004906 tde->d_reclen = tswap16(treclen);
4907 tde->d_ino = tswapl(de->d_ino);
4908 tde->d_off = tswapl(de->d_off);
blueswir1992f48a2007-10-14 16:27:31 +00004909 tnamelen = treclen - (2 * sizeof(abi_long) + 2);
bellard4add45b2003-06-05 01:52:59 +00004910 if (tnamelen > 256)
4911 tnamelen = 256;
bellard80a9d032005-01-03 23:31:27 +00004912 /* XXX: may not be correct */
bellard4add45b2003-06-05 01:52:59 +00004913 strncpy(tde->d_name, de->d_name, tnamelen);
aurel326556a832008-10-13 21:08:17 +00004914 de = (struct linux_dirent *)((char *)de + reclen);
bellard4add45b2003-06-05 01:52:59 +00004915 len -= reclen;
j_mayer1c5bf3b2007-04-14 12:17:59 +00004916 tde = (struct target_dirent *)((char *)tde + treclen);
bellard4add45b2003-06-05 01:52:59 +00004917 count1 += treclen;
4918 }
4919 ret = count1;
bellard579a97f2007-11-11 14:26:47 +00004920 unlock_user(target_dirp, arg2, ret);
bellard4add45b2003-06-05 01:52:59 +00004921 }
4922 free(dirp);
4923 }
4924#else
bellard31e31b82003-02-18 22:55:36 +00004925 {
aurel326556a832008-10-13 21:08:17 +00004926 struct linux_dirent *dirp;
blueswir1992f48a2007-10-14 16:27:31 +00004927 abi_long count = arg3;
bellarddab2ed92003-03-22 15:23:14 +00004928
bellard579a97f2007-11-11 14:26:47 +00004929 if (!(dirp = lock_user(VERIFY_WRITE, arg2, count, 0)))
4930 goto efault;
bellard72f03902003-02-18 23:33:18 +00004931 ret = get_errno(sys_getdents(arg1, dirp, count));
bellard31e31b82003-02-18 22:55:36 +00004932 if (!is_error(ret)) {
aurel326556a832008-10-13 21:08:17 +00004933 struct linux_dirent *de;
bellard31e31b82003-02-18 22:55:36 +00004934 int len = ret;
4935 int reclen;
4936 de = dirp;
4937 while (len > 0) {
bellard8083a3e2003-03-24 23:12:16 +00004938 reclen = de->d_reclen;
bellard31e31b82003-02-18 22:55:36 +00004939 if (reclen > len)
4940 break;
bellard8083a3e2003-03-24 23:12:16 +00004941 de->d_reclen = tswap16(reclen);
bellard31e31b82003-02-18 22:55:36 +00004942 tswapls(&de->d_ino);
4943 tswapls(&de->d_off);
aurel326556a832008-10-13 21:08:17 +00004944 de = (struct linux_dirent *)((char *)de + reclen);
bellard31e31b82003-02-18 22:55:36 +00004945 len -= reclen;
4946 }
4947 }
pbrook53a59602006-03-25 19:31:22 +00004948 unlock_user(dirp, arg2, ret);
bellard31e31b82003-02-18 22:55:36 +00004949 }
bellard4add45b2003-06-05 01:52:59 +00004950#endif
bellard31e31b82003-02-18 22:55:36 +00004951 break;
ths3ae43202007-09-16 21:39:48 +00004952#if defined(TARGET_NR_getdents64) && defined(__NR_getdents64)
bellarddab2ed92003-03-22 15:23:14 +00004953 case TARGET_NR_getdents64:
4954 {
aurel326556a832008-10-13 21:08:17 +00004955 struct linux_dirent64 *dirp;
blueswir1992f48a2007-10-14 16:27:31 +00004956 abi_long count = arg3;
bellard579a97f2007-11-11 14:26:47 +00004957 if (!(dirp = lock_user(VERIFY_WRITE, arg2, count, 0)))
4958 goto efault;
bellarddab2ed92003-03-22 15:23:14 +00004959 ret = get_errno(sys_getdents64(arg1, dirp, count));
4960 if (!is_error(ret)) {
aurel326556a832008-10-13 21:08:17 +00004961 struct linux_dirent64 *de;
bellarddab2ed92003-03-22 15:23:14 +00004962 int len = ret;
4963 int reclen;
4964 de = dirp;
4965 while (len > 0) {
bellard8083a3e2003-03-24 23:12:16 +00004966 reclen = de->d_reclen;
bellarddab2ed92003-03-22 15:23:14 +00004967 if (reclen > len)
4968 break;
bellard8083a3e2003-03-24 23:12:16 +00004969 de->d_reclen = tswap16(reclen);
bellard8582a532007-11-11 23:11:36 +00004970 tswap64s((uint64_t *)&de->d_ino);
4971 tswap64s((uint64_t *)&de->d_off);
aurel326556a832008-10-13 21:08:17 +00004972 de = (struct linux_dirent64 *)((char *)de + reclen);
bellarddab2ed92003-03-22 15:23:14 +00004973 len -= reclen;
4974 }
4975 }
pbrook53a59602006-03-25 19:31:22 +00004976 unlock_user(dirp, arg2, ret);
bellarddab2ed92003-03-22 15:23:14 +00004977 }
4978 break;
bellarda541f292004-04-12 20:39:29 +00004979#endif /* TARGET_NR_getdents64 */
thse5febef2007-04-01 18:31:35 +00004980#ifdef TARGET_NR__newselect
bellard31e31b82003-02-18 22:55:36 +00004981 case TARGET_NR__newselect:
pbrook53a59602006-03-25 19:31:22 +00004982 ret = do_select(arg1, arg2, arg3, arg4, arg5);
bellard31e31b82003-02-18 22:55:36 +00004983 break;
thse5febef2007-04-01 18:31:35 +00004984#endif
4985#ifdef TARGET_NR_poll
bellard9de5e442003-03-23 16:49:39 +00004986 case TARGET_NR_poll:
4987 {
pbrook53a59602006-03-25 19:31:22 +00004988 struct target_pollfd *target_pfd;
bellard9de5e442003-03-23 16:49:39 +00004989 unsigned int nfds = arg2;
4990 int timeout = arg3;
4991 struct pollfd *pfd;
bellard7854b052003-03-29 17:22:23 +00004992 unsigned int i;
bellard9de5e442003-03-23 16:49:39 +00004993
bellard579a97f2007-11-11 14:26:47 +00004994 target_pfd = lock_user(VERIFY_WRITE, arg1, sizeof(struct target_pollfd) * nfds, 1);
4995 if (!target_pfd)
4996 goto efault;
bellard9de5e442003-03-23 16:49:39 +00004997 pfd = alloca(sizeof(struct pollfd) * nfds);
4998 for(i = 0; i < nfds; i++) {
bellard5cd43932003-03-29 16:54:36 +00004999 pfd[i].fd = tswap32(target_pfd[i].fd);
5000 pfd[i].events = tswap16(target_pfd[i].events);
bellard9de5e442003-03-23 16:49:39 +00005001 }
5002 ret = get_errno(poll(pfd, nfds, timeout));
5003 if (!is_error(ret)) {
5004 for(i = 0; i < nfds; i++) {
bellard5cd43932003-03-29 16:54:36 +00005005 target_pfd[i].revents = tswap16(pfd[i].revents);
bellard9de5e442003-03-23 16:49:39 +00005006 }
pbrook53a59602006-03-25 19:31:22 +00005007 ret += nfds * (sizeof(struct target_pollfd)
5008 - sizeof(struct pollfd));
bellard9de5e442003-03-23 16:49:39 +00005009 }
pbrook53a59602006-03-25 19:31:22 +00005010 unlock_user(target_pfd, arg1, ret);
bellard9de5e442003-03-23 16:49:39 +00005011 }
5012 break;
thse5febef2007-04-01 18:31:35 +00005013#endif
bellard31e31b82003-02-18 22:55:36 +00005014 case TARGET_NR_flock:
bellard9de5e442003-03-23 16:49:39 +00005015 /* NOTE: the flock constant seems to be the same for every
5016 Linux platform */
5017 ret = get_errno(flock(arg1, arg2));
bellard31e31b82003-02-18 22:55:36 +00005018 break;
5019 case TARGET_NR_readv:
5020 {
5021 int count = arg3;
bellard31e31b82003-02-18 22:55:36 +00005022 struct iovec *vec;
bellard31e31b82003-02-18 22:55:36 +00005023
5024 vec = alloca(count * sizeof(struct iovec));
bellard41df8412008-02-04 22:26:57 +00005025 if (lock_iovec(VERIFY_WRITE, vec, arg2, count, 0) < 0)
5026 goto efault;
bellard31e31b82003-02-18 22:55:36 +00005027 ret = get_errno(readv(arg1, vec, count));
pbrook53a59602006-03-25 19:31:22 +00005028 unlock_iovec(vec, arg2, count, 1);
bellard31e31b82003-02-18 22:55:36 +00005029 }
5030 break;
5031 case TARGET_NR_writev:
5032 {
5033 int count = arg3;
bellard31e31b82003-02-18 22:55:36 +00005034 struct iovec *vec;
bellard31e31b82003-02-18 22:55:36 +00005035
5036 vec = alloca(count * sizeof(struct iovec));
bellard41df8412008-02-04 22:26:57 +00005037 if (lock_iovec(VERIFY_READ, vec, arg2, count, 1) < 0)
5038 goto efault;
bellard31e31b82003-02-18 22:55:36 +00005039 ret = get_errno(writev(arg1, vec, count));
pbrook53a59602006-03-25 19:31:22 +00005040 unlock_iovec(vec, arg2, count, 0);
bellard31e31b82003-02-18 22:55:36 +00005041 }
5042 break;
5043 case TARGET_NR_getsid:
5044 ret = get_errno(getsid(arg1));
5045 break;
j_mayer7a3148a2007-04-05 07:13:51 +00005046#if defined(TARGET_NR_fdatasync) /* Not on alpha (osf_datasync ?) */
bellard31e31b82003-02-18 22:55:36 +00005047 case TARGET_NR_fdatasync:
bellard5cd43932003-03-29 16:54:36 +00005048 ret = get_errno(fdatasync(arg1));
5049 break;
j_mayer7a3148a2007-04-05 07:13:51 +00005050#endif
bellard31e31b82003-02-18 22:55:36 +00005051 case TARGET_NR__sysctl:
ths0da46a62007-10-20 20:23:07 +00005052 /* We don't implement this, but ENOTDIR is always a safe
bellard29e619b2004-09-13 21:41:04 +00005053 return value. */
ths0da46a62007-10-20 20:23:07 +00005054 ret = -TARGET_ENOTDIR;
5055 break;
bellard31e31b82003-02-18 22:55:36 +00005056 case TARGET_NR_sched_setparam:
bellard5cd43932003-03-29 16:54:36 +00005057 {
pbrook53a59602006-03-25 19:31:22 +00005058 struct sched_param *target_schp;
bellard5cd43932003-03-29 16:54:36 +00005059 struct sched_param schp;
pbrook53a59602006-03-25 19:31:22 +00005060
bellard579a97f2007-11-11 14:26:47 +00005061 if (!lock_user_struct(VERIFY_READ, target_schp, arg2, 1))
5062 goto efault;
bellard5cd43932003-03-29 16:54:36 +00005063 schp.sched_priority = tswap32(target_schp->sched_priority);
pbrook53a59602006-03-25 19:31:22 +00005064 unlock_user_struct(target_schp, arg2, 0);
bellard5cd43932003-03-29 16:54:36 +00005065 ret = get_errno(sched_setparam(arg1, &schp));
5066 }
5067 break;
bellard31e31b82003-02-18 22:55:36 +00005068 case TARGET_NR_sched_getparam:
bellard5cd43932003-03-29 16:54:36 +00005069 {
pbrook53a59602006-03-25 19:31:22 +00005070 struct sched_param *target_schp;
bellard5cd43932003-03-29 16:54:36 +00005071 struct sched_param schp;
5072 ret = get_errno(sched_getparam(arg1, &schp));
5073 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00005074 if (!lock_user_struct(VERIFY_WRITE, target_schp, arg2, 0))
5075 goto efault;
bellard5cd43932003-03-29 16:54:36 +00005076 target_schp->sched_priority = tswap32(schp.sched_priority);
pbrook53a59602006-03-25 19:31:22 +00005077 unlock_user_struct(target_schp, arg2, 1);
bellard5cd43932003-03-29 16:54:36 +00005078 }
5079 }
5080 break;
bellard31e31b82003-02-18 22:55:36 +00005081 case TARGET_NR_sched_setscheduler:
bellard5cd43932003-03-29 16:54:36 +00005082 {
pbrook53a59602006-03-25 19:31:22 +00005083 struct sched_param *target_schp;
bellard5cd43932003-03-29 16:54:36 +00005084 struct sched_param schp;
bellard579a97f2007-11-11 14:26:47 +00005085 if (!lock_user_struct(VERIFY_READ, target_schp, arg3, 1))
5086 goto efault;
bellard5cd43932003-03-29 16:54:36 +00005087 schp.sched_priority = tswap32(target_schp->sched_priority);
pbrook53a59602006-03-25 19:31:22 +00005088 unlock_user_struct(target_schp, arg3, 0);
bellard5cd43932003-03-29 16:54:36 +00005089 ret = get_errno(sched_setscheduler(arg1, arg2, &schp));
5090 }
5091 break;
bellard31e31b82003-02-18 22:55:36 +00005092 case TARGET_NR_sched_getscheduler:
bellard5cd43932003-03-29 16:54:36 +00005093 ret = get_errno(sched_getscheduler(arg1));
5094 break;
bellard31e31b82003-02-18 22:55:36 +00005095 case TARGET_NR_sched_yield:
5096 ret = get_errno(sched_yield());
5097 break;
5098 case TARGET_NR_sched_get_priority_max:
bellard5cd43932003-03-29 16:54:36 +00005099 ret = get_errno(sched_get_priority_max(arg1));
5100 break;
bellard31e31b82003-02-18 22:55:36 +00005101 case TARGET_NR_sched_get_priority_min:
bellard5cd43932003-03-29 16:54:36 +00005102 ret = get_errno(sched_get_priority_min(arg1));
5103 break;
bellard31e31b82003-02-18 22:55:36 +00005104 case TARGET_NR_sched_rr_get_interval:
bellard5cd43932003-03-29 16:54:36 +00005105 {
bellard5cd43932003-03-29 16:54:36 +00005106 struct timespec ts;
5107 ret = get_errno(sched_rr_get_interval(arg1, &ts));
5108 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00005109 host_to_target_timespec(arg2, &ts);
bellard5cd43932003-03-29 16:54:36 +00005110 }
5111 }
5112 break;
bellard31e31b82003-02-18 22:55:36 +00005113 case TARGET_NR_nanosleep:
bellard1b6b0292003-03-22 17:31:38 +00005114 {
bellard1b6b0292003-03-22 17:31:38 +00005115 struct timespec req, rem;
pbrook53a59602006-03-25 19:31:22 +00005116 target_to_host_timespec(&req, arg1);
bellard1b6b0292003-03-22 17:31:38 +00005117 ret = get_errno(nanosleep(&req, &rem));
pbrook53a59602006-03-25 19:31:22 +00005118 if (is_error(ret) && arg2) {
5119 host_to_target_timespec(arg2, &rem);
bellard1b6b0292003-03-22 17:31:38 +00005120 }
5121 }
5122 break;
thse5febef2007-04-01 18:31:35 +00005123#ifdef TARGET_NR_query_module
bellard31e31b82003-02-18 22:55:36 +00005124 case TARGET_NR_query_module:
bellard5cd43932003-03-29 16:54:36 +00005125 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00005126#endif
5127#ifdef TARGET_NR_nfsservctl
bellard31e31b82003-02-18 22:55:36 +00005128 case TARGET_NR_nfsservctl:
bellard5cd43932003-03-29 16:54:36 +00005129 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00005130#endif
bellard31e31b82003-02-18 22:55:36 +00005131 case TARGET_NR_prctl:
thse5574482007-02-11 20:03:13 +00005132 switch (arg1)
5133 {
5134 case PR_GET_PDEATHSIG:
5135 {
5136 int deathsig;
5137 ret = get_errno(prctl(arg1, &deathsig, arg3, arg4, arg5));
bellard2f619692007-11-16 10:46:05 +00005138 if (!is_error(ret) && arg2
5139 && put_user_ual(deathsig, arg2))
5140 goto efault;
thse5574482007-02-11 20:03:13 +00005141 }
5142 break;
5143 default:
5144 ret = get_errno(prctl(arg1, arg2, arg3, arg4, arg5));
5145 break;
5146 }
ths39b9aae2007-02-11 18:36:44 +00005147 break;
bellardd2fd1af2007-11-14 18:08:56 +00005148#ifdef TARGET_NR_arch_prctl
5149 case TARGET_NR_arch_prctl:
5150#if defined(TARGET_I386) && !defined(TARGET_ABI32)
5151 ret = do_arch_prctl(cpu_env, arg1, arg2);
5152 break;
5153#else
5154 goto unimplemented;
5155#endif
5156#endif
bellard67867302003-11-23 17:05:30 +00005157#ifdef TARGET_NR_pread
bellard31e31b82003-02-18 22:55:36 +00005158 case TARGET_NR_pread:
balroga4ae00b2008-09-20 03:14:14 +00005159#ifdef TARGET_ARM
5160 if (((CPUARMState *)cpu_env)->eabi)
5161 arg4 = arg5;
5162#endif
bellard579a97f2007-11-11 14:26:47 +00005163 if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
5164 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005165 ret = get_errno(pread(arg1, p, arg3, arg4));
5166 unlock_user(p, arg2, ret);
bellard206f0fa2003-05-14 19:01:56 +00005167 break;
bellard31e31b82003-02-18 22:55:36 +00005168 case TARGET_NR_pwrite:
balroga4ae00b2008-09-20 03:14:14 +00005169#ifdef TARGET_ARM
5170 if (((CPUARMState *)cpu_env)->eabi)
5171 arg4 = arg5;
5172#endif
bellard579a97f2007-11-11 14:26:47 +00005173 if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
5174 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005175 ret = get_errno(pwrite(arg1, p, arg3, arg4));
5176 unlock_user(p, arg2, 0);
bellard206f0fa2003-05-14 19:01:56 +00005177 break;
bellard67867302003-11-23 17:05:30 +00005178#endif
aurel32f2c7ba12008-03-28 22:32:06 +00005179#ifdef TARGET_NR_pread64
5180 case TARGET_NR_pread64:
5181 if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
5182 goto efault;
5183 ret = get_errno(pread64(arg1, p, arg3, target_offset64(arg4, arg5)));
5184 unlock_user(p, arg2, ret);
5185 break;
5186 case TARGET_NR_pwrite64:
5187 if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
5188 goto efault;
5189 ret = get_errno(pwrite64(arg1, p, arg3, target_offset64(arg4, arg5)));
5190 unlock_user(p, arg2, 0);
5191 break;
5192#endif
bellard31e31b82003-02-18 22:55:36 +00005193 case TARGET_NR_getcwd:
bellard579a97f2007-11-11 14:26:47 +00005194 if (!(p = lock_user(VERIFY_WRITE, arg1, arg2, 0)))
5195 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005196 ret = get_errno(sys_getcwd1(p, arg2));
5197 unlock_user(p, arg1, ret);
bellard31e31b82003-02-18 22:55:36 +00005198 break;
5199 case TARGET_NR_capget:
bellard5cd43932003-03-29 16:54:36 +00005200 goto unimplemented;
bellard31e31b82003-02-18 22:55:36 +00005201 case TARGET_NR_capset:
bellard5cd43932003-03-29 16:54:36 +00005202 goto unimplemented;
bellard31e31b82003-02-18 22:55:36 +00005203 case TARGET_NR_sigaltstack:
ths198a74d2007-09-27 16:44:32 +00005204#if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_MIPS) || \
5205 defined(TARGET_SPARC) || defined(TARGET_PPC) || defined(TARGET_ALPHA)
bellard579a97f2007-11-11 14:26:47 +00005206 ret = do_sigaltstack(arg1, arg2, get_sp_from_cpustate((CPUState *)cpu_env));
thsa04e1342007-09-27 13:57:58 +00005207 break;
5208#else
bellard5cd43932003-03-29 16:54:36 +00005209 goto unimplemented;
thsa04e1342007-09-27 13:57:58 +00005210#endif
bellard31e31b82003-02-18 22:55:36 +00005211 case TARGET_NR_sendfile:
bellard5cd43932003-03-29 16:54:36 +00005212 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00005213#ifdef TARGET_NR_getpmsg
bellard31e31b82003-02-18 22:55:36 +00005214 case TARGET_NR_getpmsg:
bellard5cd43932003-03-29 16:54:36 +00005215 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00005216#endif
5217#ifdef TARGET_NR_putpmsg
bellard31e31b82003-02-18 22:55:36 +00005218 case TARGET_NR_putpmsg:
bellard5cd43932003-03-29 16:54:36 +00005219 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00005220#endif
bellard048f6b42005-11-26 18:47:20 +00005221#ifdef TARGET_NR_vfork
bellard31e31b82003-02-18 22:55:36 +00005222 case TARGET_NR_vfork:
pbrookd865bab2008-06-07 22:12:17 +00005223 ret = get_errno(do_fork(cpu_env, CLONE_VFORK | CLONE_VM | SIGCHLD,
5224 0, 0, 0, 0));
bellard31e31b82003-02-18 22:55:36 +00005225 break;
bellard048f6b42005-11-26 18:47:20 +00005226#endif
bellardebc05482003-09-30 21:08:41 +00005227#ifdef TARGET_NR_ugetrlimit
bellard31e31b82003-02-18 22:55:36 +00005228 case TARGET_NR_ugetrlimit:
bellard728584b2003-04-29 20:43:36 +00005229 {
5230 struct rlimit rlim;
5231 ret = get_errno(getrlimit(arg1, &rlim));
5232 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00005233 struct target_rlimit *target_rlim;
bellard579a97f2007-11-11 14:26:47 +00005234 if (!lock_user_struct(VERIFY_WRITE, target_rlim, arg2, 0))
5235 goto efault;
bellard728584b2003-04-29 20:43:36 +00005236 target_rlim->rlim_cur = tswapl(rlim.rlim_cur);
5237 target_rlim->rlim_max = tswapl(rlim.rlim_max);
pbrook53a59602006-03-25 19:31:22 +00005238 unlock_user_struct(target_rlim, arg2, 1);
bellard728584b2003-04-29 20:43:36 +00005239 }
5240 break;
5241 }
bellardebc05482003-09-30 21:08:41 +00005242#endif
bellarda315a142005-01-30 22:59:18 +00005243#ifdef TARGET_NR_truncate64
bellard31e31b82003-02-18 22:55:36 +00005244 case TARGET_NR_truncate64:
bellard579a97f2007-11-11 14:26:47 +00005245 if (!(p = lock_user_string(arg1)))
5246 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005247 ret = target_truncate64(cpu_env, p, arg2, arg3, arg4);
5248 unlock_user(p, arg1, 0);
bellard667f38b2005-07-23 14:46:27 +00005249 break;
bellarda315a142005-01-30 22:59:18 +00005250#endif
5251#ifdef TARGET_NR_ftruncate64
bellard31e31b82003-02-18 22:55:36 +00005252 case TARGET_NR_ftruncate64:
pbrookce4defa2006-02-09 16:49:55 +00005253 ret = target_ftruncate64(cpu_env, arg1, arg2, arg3, arg4);
bellard667f38b2005-07-23 14:46:27 +00005254 break;
bellarda315a142005-01-30 22:59:18 +00005255#endif
5256#ifdef TARGET_NR_stat64
bellard31e31b82003-02-18 22:55:36 +00005257 case TARGET_NR_stat64:
bellard579a97f2007-11-11 14:26:47 +00005258 if (!(p = lock_user_string(arg1)))
5259 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005260 ret = get_errno(stat(path(p), &st));
5261 unlock_user(p, arg1, 0);
balrog6a24a772008-09-20 02:23:36 +00005262 if (!is_error(ret))
5263 ret = host_to_target_stat64(cpu_env, arg2, &st);
5264 break;
bellarda315a142005-01-30 22:59:18 +00005265#endif
5266#ifdef TARGET_NR_lstat64
bellard31e31b82003-02-18 22:55:36 +00005267 case TARGET_NR_lstat64:
bellard579a97f2007-11-11 14:26:47 +00005268 if (!(p = lock_user_string(arg1)))
5269 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005270 ret = get_errno(lstat(path(p), &st));
5271 unlock_user(p, arg1, 0);
balrog6a24a772008-09-20 02:23:36 +00005272 if (!is_error(ret))
5273 ret = host_to_target_stat64(cpu_env, arg2, &st);
5274 break;
bellarda315a142005-01-30 22:59:18 +00005275#endif
5276#ifdef TARGET_NR_fstat64
bellard31e31b82003-02-18 22:55:36 +00005277 case TARGET_NR_fstat64:
balrog6a24a772008-09-20 02:23:36 +00005278 ret = get_errno(fstat(arg1, &st));
5279 if (!is_error(ret))
5280 ret = host_to_target_stat64(cpu_env, arg2, &st);
5281 break;
bellardec86b0f2003-04-11 00:15:04 +00005282#endif
balrog6a24a772008-09-20 02:23:36 +00005283#if defined(TARGET_NR_fstatat64) && defined(__NR_fstatat64)
5284 case TARGET_NR_fstatat64:
5285 if (!(p = lock_user_string(arg2)))
5286 goto efault;
5287 ret = get_errno(sys_fstatat64(arg1, path(p), &st, arg4));
5288 if (!is_error(ret))
5289 ret = host_to_target_stat64(cpu_env, arg3, &st);
bellard60cd49d2003-03-16 22:53:56 +00005290 break;
bellarda315a142005-01-30 22:59:18 +00005291#endif
bellard67867302003-11-23 17:05:30 +00005292#ifdef USE_UID16
5293 case TARGET_NR_lchown:
bellard579a97f2007-11-11 14:26:47 +00005294 if (!(p = lock_user_string(arg1)))
5295 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005296 ret = get_errno(lchown(p, low2highuid(arg2), low2highgid(arg3)));
5297 unlock_user(p, arg1, 0);
bellard67867302003-11-23 17:05:30 +00005298 break;
5299 case TARGET_NR_getuid:
5300 ret = get_errno(high2lowuid(getuid()));
5301 break;
5302 case TARGET_NR_getgid:
5303 ret = get_errno(high2lowgid(getgid()));
5304 break;
5305 case TARGET_NR_geteuid:
5306 ret = get_errno(high2lowuid(geteuid()));
5307 break;
5308 case TARGET_NR_getegid:
5309 ret = get_errno(high2lowgid(getegid()));
5310 break;
5311 case TARGET_NR_setreuid:
5312 ret = get_errno(setreuid(low2highuid(arg1), low2highuid(arg2)));
5313 break;
5314 case TARGET_NR_setregid:
5315 ret = get_errno(setregid(low2highgid(arg1), low2highgid(arg2)));
5316 break;
5317 case TARGET_NR_getgroups:
5318 {
5319 int gidsetsize = arg1;
pbrook53a59602006-03-25 19:31:22 +00005320 uint16_t *target_grouplist;
bellard67867302003-11-23 17:05:30 +00005321 gid_t *grouplist;
5322 int i;
5323
5324 grouplist = alloca(gidsetsize * sizeof(gid_t));
5325 ret = get_errno(getgroups(gidsetsize, grouplist));
balrogcb3bc232008-09-20 02:08:13 +00005326 if (gidsetsize == 0)
5327 break;
bellard67867302003-11-23 17:05:30 +00005328 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00005329 target_grouplist = lock_user(VERIFY_WRITE, arg2, gidsetsize * 2, 0);
5330 if (!target_grouplist)
5331 goto efault;
balroga2155fc2008-09-20 02:12:08 +00005332 for(i = 0;i < ret; i++)
bellard67867302003-11-23 17:05:30 +00005333 target_grouplist[i] = tswap16(grouplist[i]);
pbrook53a59602006-03-25 19:31:22 +00005334 unlock_user(target_grouplist, arg2, gidsetsize * 2);
bellard67867302003-11-23 17:05:30 +00005335 }
5336 }
5337 break;
5338 case TARGET_NR_setgroups:
5339 {
5340 int gidsetsize = arg1;
pbrook53a59602006-03-25 19:31:22 +00005341 uint16_t *target_grouplist;
bellard67867302003-11-23 17:05:30 +00005342 gid_t *grouplist;
5343 int i;
5344
5345 grouplist = alloca(gidsetsize * sizeof(gid_t));
bellard579a97f2007-11-11 14:26:47 +00005346 target_grouplist = lock_user(VERIFY_READ, arg2, gidsetsize * 2, 1);
5347 if (!target_grouplist) {
5348 ret = -TARGET_EFAULT;
5349 goto fail;
5350 }
bellard67867302003-11-23 17:05:30 +00005351 for(i = 0;i < gidsetsize; i++)
5352 grouplist[i] = tswap16(target_grouplist[i]);
pbrook53a59602006-03-25 19:31:22 +00005353 unlock_user(target_grouplist, arg2, 0);
bellard67867302003-11-23 17:05:30 +00005354 ret = get_errno(setgroups(gidsetsize, grouplist));
5355 }
5356 break;
5357 case TARGET_NR_fchown:
5358 ret = get_errno(fchown(arg1, low2highuid(arg2), low2highgid(arg3)));
5359 break;
thsccfa72b2007-09-24 09:23:34 +00005360#if defined(TARGET_NR_fchownat) && defined(__NR_fchownat)
5361 case TARGET_NR_fchownat:
bellard579a97f2007-11-11 14:26:47 +00005362 if (!(p = lock_user_string(arg2)))
5363 goto efault;
5364 ret = get_errno(sys_fchownat(arg1, p, low2highuid(arg3), low2highgid(arg4), arg5));
5365 unlock_user(p, arg2, 0);
thsccfa72b2007-09-24 09:23:34 +00005366 break;
5367#endif
bellard67867302003-11-23 17:05:30 +00005368#ifdef TARGET_NR_setresuid
5369 case TARGET_NR_setresuid:
ths5fafdf22007-09-16 21:08:06 +00005370 ret = get_errno(setresuid(low2highuid(arg1),
5371 low2highuid(arg2),
bellard67867302003-11-23 17:05:30 +00005372 low2highuid(arg3)));
5373 break;
5374#endif
5375#ifdef TARGET_NR_getresuid
5376 case TARGET_NR_getresuid:
5377 {
pbrook53a59602006-03-25 19:31:22 +00005378 uid_t ruid, euid, suid;
bellard67867302003-11-23 17:05:30 +00005379 ret = get_errno(getresuid(&ruid, &euid, &suid));
5380 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +00005381 if (put_user_u16(high2lowuid(ruid), arg1)
5382 || put_user_u16(high2lowuid(euid), arg2)
5383 || put_user_u16(high2lowuid(suid), arg3))
5384 goto efault;
bellard67867302003-11-23 17:05:30 +00005385 }
5386 }
5387 break;
5388#endif
5389#ifdef TARGET_NR_getresgid
5390 case TARGET_NR_setresgid:
ths5fafdf22007-09-16 21:08:06 +00005391 ret = get_errno(setresgid(low2highgid(arg1),
5392 low2highgid(arg2),
bellard67867302003-11-23 17:05:30 +00005393 low2highgid(arg3)));
5394 break;
5395#endif
5396#ifdef TARGET_NR_getresgid
5397 case TARGET_NR_getresgid:
5398 {
pbrook53a59602006-03-25 19:31:22 +00005399 gid_t rgid, egid, sgid;
bellard67867302003-11-23 17:05:30 +00005400 ret = get_errno(getresgid(&rgid, &egid, &sgid));
5401 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +00005402 if (put_user_u16(high2lowgid(rgid), arg1)
5403 || put_user_u16(high2lowgid(egid), arg2)
5404 || put_user_u16(high2lowgid(sgid), arg3))
5405 goto efault;
bellard67867302003-11-23 17:05:30 +00005406 }
5407 }
5408 break;
5409#endif
5410 case TARGET_NR_chown:
bellard579a97f2007-11-11 14:26:47 +00005411 if (!(p = lock_user_string(arg1)))
5412 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005413 ret = get_errno(chown(p, low2highuid(arg2), low2highgid(arg3)));
5414 unlock_user(p, arg1, 0);
bellard67867302003-11-23 17:05:30 +00005415 break;
5416 case TARGET_NR_setuid:
5417 ret = get_errno(setuid(low2highuid(arg1)));
5418 break;
5419 case TARGET_NR_setgid:
5420 ret = get_errno(setgid(low2highgid(arg1)));
5421 break;
5422 case TARGET_NR_setfsuid:
5423 ret = get_errno(setfsuid(arg1));
5424 break;
5425 case TARGET_NR_setfsgid:
5426 ret = get_errno(setfsgid(arg1));
5427 break;
5428#endif /* USE_UID16 */
5429
bellarda315a142005-01-30 22:59:18 +00005430#ifdef TARGET_NR_lchown32
bellard31e31b82003-02-18 22:55:36 +00005431 case TARGET_NR_lchown32:
bellard579a97f2007-11-11 14:26:47 +00005432 if (!(p = lock_user_string(arg1)))
5433 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005434 ret = get_errno(lchown(p, arg2, arg3));
5435 unlock_user(p, arg1, 0);
bellardb03c60f2003-03-23 17:19:56 +00005436 break;
bellarda315a142005-01-30 22:59:18 +00005437#endif
5438#ifdef TARGET_NR_getuid32
bellard31e31b82003-02-18 22:55:36 +00005439 case TARGET_NR_getuid32:
bellardb03c60f2003-03-23 17:19:56 +00005440 ret = get_errno(getuid());
5441 break;
bellarda315a142005-01-30 22:59:18 +00005442#endif
5443#ifdef TARGET_NR_getgid32
bellard31e31b82003-02-18 22:55:36 +00005444 case TARGET_NR_getgid32:
bellardb03c60f2003-03-23 17:19:56 +00005445 ret = get_errno(getgid());
5446 break;
bellarda315a142005-01-30 22:59:18 +00005447#endif
5448#ifdef TARGET_NR_geteuid32
bellard31e31b82003-02-18 22:55:36 +00005449 case TARGET_NR_geteuid32:
bellardb03c60f2003-03-23 17:19:56 +00005450 ret = get_errno(geteuid());
5451 break;
bellarda315a142005-01-30 22:59:18 +00005452#endif
5453#ifdef TARGET_NR_getegid32
bellard31e31b82003-02-18 22:55:36 +00005454 case TARGET_NR_getegid32:
bellardb03c60f2003-03-23 17:19:56 +00005455 ret = get_errno(getegid());
5456 break;
bellarda315a142005-01-30 22:59:18 +00005457#endif
5458#ifdef TARGET_NR_setreuid32
bellard31e31b82003-02-18 22:55:36 +00005459 case TARGET_NR_setreuid32:
bellardb03c60f2003-03-23 17:19:56 +00005460 ret = get_errno(setreuid(arg1, arg2));
5461 break;
bellarda315a142005-01-30 22:59:18 +00005462#endif
5463#ifdef TARGET_NR_setregid32
bellard31e31b82003-02-18 22:55:36 +00005464 case TARGET_NR_setregid32:
bellardb03c60f2003-03-23 17:19:56 +00005465 ret = get_errno(setregid(arg1, arg2));
5466 break;
bellarda315a142005-01-30 22:59:18 +00005467#endif
5468#ifdef TARGET_NR_getgroups32
bellard31e31b82003-02-18 22:55:36 +00005469 case TARGET_NR_getgroups32:
bellard99c475a2005-01-31 20:45:13 +00005470 {
5471 int gidsetsize = arg1;
pbrook53a59602006-03-25 19:31:22 +00005472 uint32_t *target_grouplist;
bellard99c475a2005-01-31 20:45:13 +00005473 gid_t *grouplist;
5474 int i;
5475
5476 grouplist = alloca(gidsetsize * sizeof(gid_t));
5477 ret = get_errno(getgroups(gidsetsize, grouplist));
balrogcb3bc232008-09-20 02:08:13 +00005478 if (gidsetsize == 0)
5479 break;
bellard99c475a2005-01-31 20:45:13 +00005480 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00005481 target_grouplist = lock_user(VERIFY_WRITE, arg2, gidsetsize * 4, 0);
5482 if (!target_grouplist) {
5483 ret = -TARGET_EFAULT;
5484 goto fail;
5485 }
balroga2155fc2008-09-20 02:12:08 +00005486 for(i = 0;i < ret; i++)
pbrook53a59602006-03-25 19:31:22 +00005487 target_grouplist[i] = tswap32(grouplist[i]);
5488 unlock_user(target_grouplist, arg2, gidsetsize * 4);
bellard99c475a2005-01-31 20:45:13 +00005489 }
5490 }
5491 break;
bellarda315a142005-01-30 22:59:18 +00005492#endif
5493#ifdef TARGET_NR_setgroups32
bellard31e31b82003-02-18 22:55:36 +00005494 case TARGET_NR_setgroups32:
bellard99c475a2005-01-31 20:45:13 +00005495 {
5496 int gidsetsize = arg1;
pbrook53a59602006-03-25 19:31:22 +00005497 uint32_t *target_grouplist;
bellard99c475a2005-01-31 20:45:13 +00005498 gid_t *grouplist;
5499 int i;
ths3b46e622007-09-17 08:09:54 +00005500
bellard99c475a2005-01-31 20:45:13 +00005501 grouplist = alloca(gidsetsize * sizeof(gid_t));
bellard579a97f2007-11-11 14:26:47 +00005502 target_grouplist = lock_user(VERIFY_READ, arg2, gidsetsize * 4, 1);
5503 if (!target_grouplist) {
5504 ret = -TARGET_EFAULT;
5505 goto fail;
5506 }
bellard99c475a2005-01-31 20:45:13 +00005507 for(i = 0;i < gidsetsize; i++)
pbrook53a59602006-03-25 19:31:22 +00005508 grouplist[i] = tswap32(target_grouplist[i]);
5509 unlock_user(target_grouplist, arg2, 0);
bellard99c475a2005-01-31 20:45:13 +00005510 ret = get_errno(setgroups(gidsetsize, grouplist));
5511 }
5512 break;
bellarda315a142005-01-30 22:59:18 +00005513#endif
5514#ifdef TARGET_NR_fchown32
bellard31e31b82003-02-18 22:55:36 +00005515 case TARGET_NR_fchown32:
bellardb03c60f2003-03-23 17:19:56 +00005516 ret = get_errno(fchown(arg1, arg2, arg3));
5517 break;
bellarda315a142005-01-30 22:59:18 +00005518#endif
5519#ifdef TARGET_NR_setresuid32
bellard31e31b82003-02-18 22:55:36 +00005520 case TARGET_NR_setresuid32:
bellardb03c60f2003-03-23 17:19:56 +00005521 ret = get_errno(setresuid(arg1, arg2, arg3));
5522 break;
bellarda315a142005-01-30 22:59:18 +00005523#endif
5524#ifdef TARGET_NR_getresuid32
bellard31e31b82003-02-18 22:55:36 +00005525 case TARGET_NR_getresuid32:
bellardb03c60f2003-03-23 17:19:56 +00005526 {
pbrook53a59602006-03-25 19:31:22 +00005527 uid_t ruid, euid, suid;
bellardb03c60f2003-03-23 17:19:56 +00005528 ret = get_errno(getresuid(&ruid, &euid, &suid));
5529 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +00005530 if (put_user_u32(ruid, arg1)
5531 || put_user_u32(euid, arg2)
5532 || put_user_u32(suid, arg3))
5533 goto efault;
bellardb03c60f2003-03-23 17:19:56 +00005534 }
5535 }
5536 break;
bellarda315a142005-01-30 22:59:18 +00005537#endif
5538#ifdef TARGET_NR_setresgid32
bellard31e31b82003-02-18 22:55:36 +00005539 case TARGET_NR_setresgid32:
bellardb03c60f2003-03-23 17:19:56 +00005540 ret = get_errno(setresgid(arg1, arg2, arg3));
5541 break;
bellarda315a142005-01-30 22:59:18 +00005542#endif
5543#ifdef TARGET_NR_getresgid32
bellard31e31b82003-02-18 22:55:36 +00005544 case TARGET_NR_getresgid32:
bellardb03c60f2003-03-23 17:19:56 +00005545 {
pbrook53a59602006-03-25 19:31:22 +00005546 gid_t rgid, egid, sgid;
bellardb03c60f2003-03-23 17:19:56 +00005547 ret = get_errno(getresgid(&rgid, &egid, &sgid));
5548 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +00005549 if (put_user_u32(rgid, arg1)
5550 || put_user_u32(egid, arg2)
5551 || put_user_u32(sgid, arg3))
5552 goto efault;
bellardb03c60f2003-03-23 17:19:56 +00005553 }
5554 }
5555 break;
bellarda315a142005-01-30 22:59:18 +00005556#endif
5557#ifdef TARGET_NR_chown32
bellard31e31b82003-02-18 22:55:36 +00005558 case TARGET_NR_chown32:
bellard579a97f2007-11-11 14:26:47 +00005559 if (!(p = lock_user_string(arg1)))
5560 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005561 ret = get_errno(chown(p, arg2, arg3));
5562 unlock_user(p, arg1, 0);
bellardb03c60f2003-03-23 17:19:56 +00005563 break;
bellarda315a142005-01-30 22:59:18 +00005564#endif
5565#ifdef TARGET_NR_setuid32
bellard31e31b82003-02-18 22:55:36 +00005566 case TARGET_NR_setuid32:
bellardb03c60f2003-03-23 17:19:56 +00005567 ret = get_errno(setuid(arg1));
5568 break;
bellarda315a142005-01-30 22:59:18 +00005569#endif
5570#ifdef TARGET_NR_setgid32
bellard31e31b82003-02-18 22:55:36 +00005571 case TARGET_NR_setgid32:
bellardb03c60f2003-03-23 17:19:56 +00005572 ret = get_errno(setgid(arg1));
5573 break;
bellarda315a142005-01-30 22:59:18 +00005574#endif
5575#ifdef TARGET_NR_setfsuid32
bellard31e31b82003-02-18 22:55:36 +00005576 case TARGET_NR_setfsuid32:
bellardb03c60f2003-03-23 17:19:56 +00005577 ret = get_errno(setfsuid(arg1));
5578 break;
bellarda315a142005-01-30 22:59:18 +00005579#endif
5580#ifdef TARGET_NR_setfsgid32
bellard31e31b82003-02-18 22:55:36 +00005581 case TARGET_NR_setfsgid32:
bellardb03c60f2003-03-23 17:19:56 +00005582 ret = get_errno(setfsgid(arg1));
5583 break;
bellarda315a142005-01-30 22:59:18 +00005584#endif
bellard67867302003-11-23 17:05:30 +00005585
bellard31e31b82003-02-18 22:55:36 +00005586 case TARGET_NR_pivot_root:
bellardb03c60f2003-03-23 17:19:56 +00005587 goto unimplemented;
bellardffa65c32004-01-04 23:57:22 +00005588#ifdef TARGET_NR_mincore
bellard31e31b82003-02-18 22:55:36 +00005589 case TARGET_NR_mincore:
aurel3204bb9ac2008-10-01 21:46:41 +00005590 {
5591 void *a;
5592 ret = -TARGET_EFAULT;
5593 if (!(a = lock_user(VERIFY_READ, arg1,arg2, 0)))
5594 goto efault;
5595 if (!(p = lock_user_string(arg3)))
5596 goto mincore_fail;
5597 ret = get_errno(mincore(a, arg2, p));
5598 unlock_user(p, arg3, ret);
5599 mincore_fail:
5600 unlock_user(a, arg1, 0);
5601 }
5602 break;
bellardffa65c32004-01-04 23:57:22 +00005603#endif
aurel32408321b2008-10-01 21:46:32 +00005604#ifdef TARGET_NR_arm_fadvise64_64
5605 case TARGET_NR_arm_fadvise64_64:
5606 {
5607 /*
5608 * arm_fadvise64_64 looks like fadvise64_64 but
5609 * with different argument order
5610 */
5611 abi_long temp;
5612 temp = arg3;
5613 arg3 = arg4;
5614 arg4 = temp;
5615 }
5616#endif
5617#if defined(TARGET_NR_fadvise64_64) || defined(TARGET_NR_arm_fadvise64_64)
5618#ifdef TARGET_NR_fadvise64_64
5619 case TARGET_NR_fadvise64_64:
5620#endif
5621 /* This is a hint, so ignoring and returning success is ok. */
5622 ret = get_errno(0);
5623 break;
5624#endif
bellardffa65c32004-01-04 23:57:22 +00005625#ifdef TARGET_NR_madvise
bellard31e31b82003-02-18 22:55:36 +00005626 case TARGET_NR_madvise:
pbrook24836682006-04-16 14:14:53 +00005627 /* A straight passthrough may not be safe because qemu sometimes
5628 turns private flie-backed mappings into anonymous mappings.
5629 This will break MADV_DONTNEED.
5630 This is a hint, so ignoring and returning success is ok. */
5631 ret = get_errno(0);
5632 break;
bellardffa65c32004-01-04 23:57:22 +00005633#endif
blueswir1992f48a2007-10-14 16:27:31 +00005634#if TARGET_ABI_BITS == 32
bellard31e31b82003-02-18 22:55:36 +00005635 case TARGET_NR_fcntl64:
bellard77e46722003-04-29 20:39:06 +00005636 {
thsb1e341e2007-03-20 21:50:52 +00005637 int cmd;
bellard77e46722003-04-29 20:39:06 +00005638 struct flock64 fl;
pbrook53a59602006-03-25 19:31:22 +00005639 struct target_flock64 *target_fl;
pbrookce4defa2006-02-09 16:49:55 +00005640#ifdef TARGET_ARM
pbrook53a59602006-03-25 19:31:22 +00005641 struct target_eabi_flock64 *target_efl;
pbrookce4defa2006-02-09 16:49:55 +00005642#endif
bellard77e46722003-04-29 20:39:06 +00005643
thsb1e341e2007-03-20 21:50:52 +00005644 switch(arg2){
5645 case TARGET_F_GETLK64:
5646 cmd = F_GETLK64;
thsa7222582007-03-22 15:08:55 +00005647 break;
thsb1e341e2007-03-20 21:50:52 +00005648 case TARGET_F_SETLK64:
5649 cmd = F_SETLK64;
thsa7222582007-03-22 15:08:55 +00005650 break;
thsb1e341e2007-03-20 21:50:52 +00005651 case TARGET_F_SETLKW64:
5652 cmd = F_SETLK64;
thsa7222582007-03-22 15:08:55 +00005653 break;
thsb1e341e2007-03-20 21:50:52 +00005654 default:
5655 cmd = arg2;
thsa7222582007-03-22 15:08:55 +00005656 break;
thsb1e341e2007-03-20 21:50:52 +00005657 }
5658
bellard60cd49d2003-03-16 22:53:56 +00005659 switch(arg2) {
thsb1e341e2007-03-20 21:50:52 +00005660 case TARGET_F_GETLK64:
ths58134272007-03-31 18:59:32 +00005661#ifdef TARGET_ARM
5662 if (((CPUARMState *)cpu_env)->eabi) {
bellard9ee1fa22007-11-11 15:11:19 +00005663 if (!lock_user_struct(VERIFY_READ, target_efl, arg3, 1))
5664 goto efault;
ths58134272007-03-31 18:59:32 +00005665 fl.l_type = tswap16(target_efl->l_type);
5666 fl.l_whence = tswap16(target_efl->l_whence);
5667 fl.l_start = tswap64(target_efl->l_start);
5668 fl.l_len = tswap64(target_efl->l_len);
5669 fl.l_pid = tswapl(target_efl->l_pid);
5670 unlock_user_struct(target_efl, arg3, 0);
5671 } else
5672#endif
5673 {
bellard9ee1fa22007-11-11 15:11:19 +00005674 if (!lock_user_struct(VERIFY_READ, target_fl, arg3, 1))
5675 goto efault;
ths58134272007-03-31 18:59:32 +00005676 fl.l_type = tswap16(target_fl->l_type);
5677 fl.l_whence = tswap16(target_fl->l_whence);
5678 fl.l_start = tswap64(target_fl->l_start);
5679 fl.l_len = tswap64(target_fl->l_len);
5680 fl.l_pid = tswapl(target_fl->l_pid);
5681 unlock_user_struct(target_fl, arg3, 0);
5682 }
thsb1e341e2007-03-20 21:50:52 +00005683 ret = get_errno(fcntl(arg1, cmd, &fl));
bellard77e46722003-04-29 20:39:06 +00005684 if (ret == 0) {
pbrookce4defa2006-02-09 16:49:55 +00005685#ifdef TARGET_ARM
5686 if (((CPUARMState *)cpu_env)->eabi) {
bellard9ee1fa22007-11-11 15:11:19 +00005687 if (!lock_user_struct(VERIFY_WRITE, target_efl, arg3, 0))
5688 goto efault;
pbrookce4defa2006-02-09 16:49:55 +00005689 target_efl->l_type = tswap16(fl.l_type);
5690 target_efl->l_whence = tswap16(fl.l_whence);
5691 target_efl->l_start = tswap64(fl.l_start);
5692 target_efl->l_len = tswap64(fl.l_len);
5693 target_efl->l_pid = tswapl(fl.l_pid);
pbrook53a59602006-03-25 19:31:22 +00005694 unlock_user_struct(target_efl, arg3, 1);
pbrookce4defa2006-02-09 16:49:55 +00005695 } else
5696#endif
5697 {
bellard9ee1fa22007-11-11 15:11:19 +00005698 if (!lock_user_struct(VERIFY_WRITE, target_fl, arg3, 0))
5699 goto efault;
pbrookce4defa2006-02-09 16:49:55 +00005700 target_fl->l_type = tswap16(fl.l_type);
5701 target_fl->l_whence = tswap16(fl.l_whence);
5702 target_fl->l_start = tswap64(fl.l_start);
5703 target_fl->l_len = tswap64(fl.l_len);
5704 target_fl->l_pid = tswapl(fl.l_pid);
pbrook53a59602006-03-25 19:31:22 +00005705 unlock_user_struct(target_fl, arg3, 1);
pbrookce4defa2006-02-09 16:49:55 +00005706 }
bellard77e46722003-04-29 20:39:06 +00005707 }
5708 break;
5709
thsb1e341e2007-03-20 21:50:52 +00005710 case TARGET_F_SETLK64:
5711 case TARGET_F_SETLKW64:
pbrookce4defa2006-02-09 16:49:55 +00005712#ifdef TARGET_ARM
5713 if (((CPUARMState *)cpu_env)->eabi) {
bellard9ee1fa22007-11-11 15:11:19 +00005714 if (!lock_user_struct(VERIFY_READ, target_efl, arg3, 1))
5715 goto efault;
pbrookce4defa2006-02-09 16:49:55 +00005716 fl.l_type = tswap16(target_efl->l_type);
5717 fl.l_whence = tswap16(target_efl->l_whence);
5718 fl.l_start = tswap64(target_efl->l_start);
5719 fl.l_len = tswap64(target_efl->l_len);
5720 fl.l_pid = tswapl(target_efl->l_pid);
pbrook53a59602006-03-25 19:31:22 +00005721 unlock_user_struct(target_efl, arg3, 0);
pbrookce4defa2006-02-09 16:49:55 +00005722 } else
5723#endif
5724 {
bellard9ee1fa22007-11-11 15:11:19 +00005725 if (!lock_user_struct(VERIFY_READ, target_fl, arg3, 1))
5726 goto efault;
pbrookce4defa2006-02-09 16:49:55 +00005727 fl.l_type = tswap16(target_fl->l_type);
5728 fl.l_whence = tswap16(target_fl->l_whence);
5729 fl.l_start = tswap64(target_fl->l_start);
5730 fl.l_len = tswap64(target_fl->l_len);
5731 fl.l_pid = tswapl(target_fl->l_pid);
pbrook53a59602006-03-25 19:31:22 +00005732 unlock_user_struct(target_fl, arg3, 0);
pbrookce4defa2006-02-09 16:49:55 +00005733 }
thsb1e341e2007-03-20 21:50:52 +00005734 ret = get_errno(fcntl(arg1, cmd, &fl));
bellard77e46722003-04-29 20:39:06 +00005735 break;
bellard60cd49d2003-03-16 22:53:56 +00005736 default:
bellard9ee1fa22007-11-11 15:11:19 +00005737 ret = do_fcntl(arg1, cmd, arg3);
bellard60cd49d2003-03-16 22:53:56 +00005738 break;
5739 }
bellard77e46722003-04-29 20:39:06 +00005740 break;
5741 }
bellard60cd49d2003-03-16 22:53:56 +00005742#endif
ths7d600c82006-12-08 01:32:58 +00005743#ifdef TARGET_NR_cacheflush
5744 case TARGET_NR_cacheflush:
5745 /* self-modifying code is handled automatically, so nothing needed */
5746 ret = 0;
5747 break;
5748#endif
bellardebc05482003-09-30 21:08:41 +00005749#ifdef TARGET_NR_security
bellard31e31b82003-02-18 22:55:36 +00005750 case TARGET_NR_security:
5751 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00005752#endif
bellardc573ff62004-01-04 15:51:36 +00005753#ifdef TARGET_NR_getpagesize
5754 case TARGET_NR_getpagesize:
5755 ret = TARGET_PAGE_SIZE;
5756 break;
5757#endif
bellard31e31b82003-02-18 22:55:36 +00005758 case TARGET_NR_gettid:
5759 ret = get_errno(gettid());
5760 break;
thse5febef2007-04-01 18:31:35 +00005761#ifdef TARGET_NR_readahead
bellard31e31b82003-02-18 22:55:36 +00005762 case TARGET_NR_readahead:
aurel322054ac92008-10-13 21:08:07 +00005763#if TARGET_ABI_BITS == 32
5764#ifdef TARGET_ARM
5765 if (((CPUARMState *)cpu_env)->eabi)
5766 {
5767 arg2 = arg3;
5768 arg3 = arg4;
5769 arg4 = arg5;
5770 }
5771#endif
5772 ret = get_errno(readahead(arg1, ((off64_t)arg3 << 32) | arg2, arg4));
5773#else
5774 ret = get_errno(readahead(arg1, arg2, arg3));
5775#endif
5776 break;
thse5febef2007-04-01 18:31:35 +00005777#endif
bellardebc05482003-09-30 21:08:41 +00005778#ifdef TARGET_NR_setxattr
bellard31e31b82003-02-18 22:55:36 +00005779 case TARGET_NR_setxattr:
5780 case TARGET_NR_lsetxattr:
5781 case TARGET_NR_fsetxattr:
5782 case TARGET_NR_getxattr:
5783 case TARGET_NR_lgetxattr:
5784 case TARGET_NR_fgetxattr:
5785 case TARGET_NR_listxattr:
5786 case TARGET_NR_llistxattr:
5787 case TARGET_NR_flistxattr:
5788 case TARGET_NR_removexattr:
5789 case TARGET_NR_lremovexattr:
5790 case TARGET_NR_fremovexattr:
bellard5cd43932003-03-29 16:54:36 +00005791 goto unimplemented_nowarn;
bellardebc05482003-09-30 21:08:41 +00005792#endif
5793#ifdef TARGET_NR_set_thread_area
bellard5cd43932003-03-29 16:54:36 +00005794 case TARGET_NR_set_thread_area:
bellard8d18e892007-11-14 15:18:40 +00005795#if defined(TARGET_MIPS)
ths6f5b89a2007-03-02 20:48:00 +00005796 ((CPUMIPSState *) cpu_env)->tls_value = arg1;
5797 ret = 0;
5798 break;
bellard8d18e892007-11-14 15:18:40 +00005799#elif defined(TARGET_I386) && defined(TARGET_ABI32)
5800 ret = do_set_thread_area(cpu_env, arg1);
5801 break;
ths6f5b89a2007-03-02 20:48:00 +00005802#else
5803 goto unimplemented_nowarn;
5804#endif
5805#endif
5806#ifdef TARGET_NR_get_thread_area
bellard5cd43932003-03-29 16:54:36 +00005807 case TARGET_NR_get_thread_area:
bellard8d18e892007-11-14 15:18:40 +00005808#if defined(TARGET_I386) && defined(TARGET_ABI32)
5809 ret = do_get_thread_area(cpu_env, arg1);
5810#else
bellard5cd43932003-03-29 16:54:36 +00005811 goto unimplemented_nowarn;
bellardebc05482003-09-30 21:08:41 +00005812#endif
bellard8d18e892007-11-14 15:18:40 +00005813#endif
bellard48dc41e2006-06-21 18:15:50 +00005814#ifdef TARGET_NR_getdomainname
5815 case TARGET_NR_getdomainname:
5816 goto unimplemented_nowarn;
5817#endif
ths6f5b89a2007-03-02 20:48:00 +00005818
thsb5906f92007-03-19 13:32:45 +00005819#ifdef TARGET_NR_clock_gettime
5820 case TARGET_NR_clock_gettime:
5821 {
5822 struct timespec ts;
5823 ret = get_errno(clock_gettime(arg1, &ts));
5824 if (!is_error(ret)) {
5825 host_to_target_timespec(arg2, &ts);
5826 }
5827 break;
5828 }
5829#endif
5830#ifdef TARGET_NR_clock_getres
5831 case TARGET_NR_clock_getres:
5832 {
5833 struct timespec ts;
5834 ret = get_errno(clock_getres(arg1, &ts));
5835 if (!is_error(ret)) {
5836 host_to_target_timespec(arg2, &ts);
5837 }
5838 break;
5839 }
5840#endif
pbrook63d76512008-05-29 13:43:29 +00005841#ifdef TARGET_NR_clock_nanosleep
5842 case TARGET_NR_clock_nanosleep:
5843 {
5844 struct timespec ts;
5845 target_to_host_timespec(&ts, arg3);
5846 ret = get_errno(clock_nanosleep(arg1, arg2, &ts, arg4 ? &ts : NULL));
5847 if (arg4)
5848 host_to_target_timespec(arg4, &ts);
5849 break;
5850 }
5851#endif
thsb5906f92007-03-19 13:32:45 +00005852
ths6f5b89a2007-03-02 20:48:00 +00005853#if defined(TARGET_NR_set_tid_address) && defined(__NR_set_tid_address)
5854 case TARGET_NR_set_tid_address:
bellard579a97f2007-11-11 14:26:47 +00005855 ret = get_errno(set_tid_address((int *)g2h(arg1)));
5856 break;
ths6f5b89a2007-03-02 20:48:00 +00005857#endif
5858
ths3ae43202007-09-16 21:39:48 +00005859#if defined(TARGET_NR_tkill) && defined(__NR_tkill)
ths4cae1d12007-07-12 11:06:53 +00005860 case TARGET_NR_tkill:
pbrook4cb05962008-05-30 18:05:19 +00005861 ret = get_errno(sys_tkill((int)arg1, target_to_host_signal(arg2)));
ths4cae1d12007-07-12 11:06:53 +00005862 break;
5863#endif
5864
ths3ae43202007-09-16 21:39:48 +00005865#if defined(TARGET_NR_tgkill) && defined(__NR_tgkill)
ths71455572007-06-21 21:45:30 +00005866 case TARGET_NR_tgkill:
pbrook4cb05962008-05-30 18:05:19 +00005867 ret = get_errno(sys_tgkill((int)arg1, (int)arg2,
5868 target_to_host_signal(arg3)));
ths71455572007-06-21 21:45:30 +00005869 break;
5870#endif
5871
ths4f2b1fe2007-06-21 21:57:12 +00005872#ifdef TARGET_NR_set_robust_list
5873 case TARGET_NR_set_robust_list:
5874 goto unimplemented_nowarn;
5875#endif
5876
ths9007f0e2007-09-25 17:50:37 +00005877#if defined(TARGET_NR_utimensat) && defined(__NR_utimensat)
5878 case TARGET_NR_utimensat:
5879 {
5880 struct timespec ts[2];
5881 target_to_host_timespec(ts, arg3);
5882 target_to_host_timespec(ts+1, arg3+sizeof(struct target_timespec));
5883 if (!arg2)
5884 ret = get_errno(sys_utimensat(arg1, NULL, ts, arg4));
5885 else {
bellard579a97f2007-11-11 14:26:47 +00005886 if (!(p = lock_user_string(arg2))) {
ths0da46a62007-10-20 20:23:07 +00005887 ret = -TARGET_EFAULT;
bellard579a97f2007-11-11 14:26:47 +00005888 goto fail;
5889 }
5890 ret = get_errno(sys_utimensat(arg1, path(p), ts, arg4));
5891 unlock_user(p, arg2, 0);
ths9007f0e2007-09-25 17:50:37 +00005892 }
5893 }
5894 break;
5895#endif
pbrookbd0c5662008-05-29 14:34:11 +00005896#if defined(USE_NPTL)
5897 case TARGET_NR_futex:
5898 ret = do_futex(arg1, arg2, arg3, arg4, arg5, arg6);
5899 break;
5900#endif
aurel3239b59762008-10-01 21:46:50 +00005901#ifdef TARGET_NR_inotify_init
5902 case TARGET_NR_inotify_init:
5903 ret = get_errno(sys_inotify_init());
5904 break;
5905#endif
5906#ifdef TARGET_NR_inotify_add_watch
5907 case TARGET_NR_inotify_add_watch:
5908 p = lock_user_string(arg2);
5909 ret = get_errno(sys_inotify_add_watch(arg1, path(p), arg3));
5910 unlock_user(p, arg2, 0);
5911 break;
5912#endif
5913#ifdef TARGET_NR_inotify_rm_watch
5914 case TARGET_NR_inotify_rm_watch:
5915 ret = get_errno(sys_inotify_rm_watch(arg1, arg2));
5916 break;
5917#endif
ths9007f0e2007-09-25 17:50:37 +00005918
bellard31e31b82003-02-18 22:55:36 +00005919 default:
5920 unimplemented:
bellard5cd43932003-03-29 16:54:36 +00005921 gemu_log("qemu: Unsupported syscall: %d\n", num);
ths4f2b1fe2007-06-21 21:57:12 +00005922#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 +00005923 unimplemented_nowarn:
bellard80a9d032005-01-03 23:31:27 +00005924#endif
ths0da46a62007-10-20 20:23:07 +00005925 ret = -TARGET_ENOSYS;
bellard31e31b82003-02-18 22:55:36 +00005926 break;
5927 }
bellard579a97f2007-11-11 14:26:47 +00005928fail:
bellardc573ff62004-01-04 15:51:36 +00005929#ifdef DEBUG
5930 gemu_log(" = %ld\n", ret);
5931#endif
thsb92c47c2007-11-01 00:07:38 +00005932 if(do_strace)
5933 print_syscall_ret(num, ret);
bellard31e31b82003-02-18 22:55:36 +00005934 return ret;
bellard579a97f2007-11-11 14:26:47 +00005935efault:
5936 ret = -TARGET_EFAULT;
5937 goto fail;
bellard31e31b82003-02-18 22:55:36 +00005938}