blob: 826511df5204f9f7dd3412e009287c37e8e55e90 [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>
bellarddab2ed92003-03-22 15:23:14 +000071#include <linux/dirent.h>
bellard19b84f32003-05-08 15:41:49 +000072#include <linux/kd.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>
96#define VFAT_IOCTL_READDIR_BOTH _IOR('r', 1, struct dirent [2])
97#define VFAT_IOCTL_READDIR_SHORT _IOR('r', 2, struct dirent [2])
98
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
bellard72f03902003-02-18 23:33:18 +0000160#define __NR_sys_getcwd1 __NR_getcwd
bellard72f03902003-02-18 23:33:18 +0000161#define __NR_sys_getdents __NR_getdents
bellarddab2ed92003-03-22 15:23:14 +0000162#define __NR_sys_getdents64 __NR_getdents64
thsc6cda172007-10-09 03:42:34 +0000163#define __NR_sys_getpriority __NR_getpriority
ths64f0ce42007-09-24 09:25:06 +0000164#define __NR_sys_linkat __NR_linkat
ths4472ad02007-09-24 09:22:32 +0000165#define __NR_sys_mkdirat __NR_mkdirat
ths75ac37a2007-09-24 09:23:05 +0000166#define __NR_sys_mknodat __NR_mknodat
ths82424832007-09-24 09:21:55 +0000167#define __NR_sys_openat __NR_openat
ths5e0ccb12007-09-24 09:26:10 +0000168#define __NR_sys_readlinkat __NR_readlinkat
ths722183f2007-09-24 09:24:37 +0000169#define __NR_sys_renameat __NR_renameat
bellard66fb9762003-03-23 01:06:05 +0000170#define __NR_sys_rt_sigqueueinfo __NR_rt_sigqueueinfo
thsf0b62432007-09-24 09:25:40 +0000171#define __NR_sys_symlinkat __NR_symlinkat
ths7494b0f2007-02-11 18:26:53 +0000172#define __NR_sys_syslog __NR_syslog
ths71455572007-06-21 21:45:30 +0000173#define __NR_sys_tgkill __NR_tgkill
ths4cae1d12007-07-12 11:06:53 +0000174#define __NR_sys_tkill __NR_tkill
ths8170f562007-09-24 09:24:11 +0000175#define __NR_sys_unlinkat __NR_unlinkat
ths9007f0e2007-09-25 17:50:37 +0000176#define __NR_sys_utimensat __NR_utimensat
pbrookbd0c5662008-05-29 14:34:11 +0000177#define __NR_sys_futex __NR_futex
bellard31e31b82003-02-18 22:55:36 +0000178
bellardbc51c5c2004-03-17 23:46:04 +0000179#if defined(__alpha__) || defined (__ia64__) || defined(__x86_64__)
bellard9af9eaa2003-04-07 21:34:41 +0000180#define __NR__llseek __NR_lseek
181#endif
182
bellard72f03902003-02-18 23:33:18 +0000183#ifdef __NR_gettid
bellard31e31b82003-02-18 22:55:36 +0000184_syscall0(int, gettid)
bellard72f03902003-02-18 23:33:18 +0000185#else
ths0da46a62007-10-20 20:23:07 +0000186/* This is a replacement for the host gettid() and must return a host
187 errno. */
bellard72f03902003-02-18 23:33:18 +0000188static int gettid(void) {
189 return -ENOSYS;
190}
191#endif
bellard31e31b82003-02-18 22:55:36 +0000192_syscall1(int,sys_uname,struct new_utsname *,buf)
ths92a34c12007-09-24 09:27:49 +0000193#if defined(TARGET_NR_faccessat) && defined(__NR_faccessat)
194_syscall4(int,sys_faccessat,int,dirfd,const char *,pathname,int,mode,int,flags)
195#endif
ths814d7972007-09-24 09:26:51 +0000196#if defined(TARGET_NR_fchmodat) && defined(__NR_fchmodat)
197_syscall4(int,sys_fchmodat,int,dirfd,const char *,pathname,
198 mode_t,mode,int,flags)
199#endif
blueswir14583f582008-08-24 10:35:55 +0000200#if defined(TARGET_NR_fchownat) && defined(__NR_fchownat) && defined(USE_UID16)
thsccfa72b2007-09-24 09:23:34 +0000201_syscall5(int,sys_fchownat,int,dirfd,const char *,pathname,
202 uid_t,owner,gid_t,group,int,flags)
203#endif
balrog6a24a772008-09-20 02:23:36 +0000204#if defined(TARGET_NR_fstatat64) && defined(__NR_fstatat64)
205_syscall4(int,sys_fstatat64,int,dirfd,const char *,pathname,
206 struct stat *,buf,int,flags)
207#endif
bellard72f03902003-02-18 23:33:18 +0000208_syscall2(int,sys_getcwd1,char *,buf,size_t,size)
blueswir14583f582008-08-24 10:35:55 +0000209#if TARGET_ABI_BITS == 32
bellard72f03902003-02-18 23:33:18 +0000210_syscall3(int, sys_getdents, uint, fd, struct dirent *, dirp, uint, count);
blueswir14583f582008-08-24 10:35:55 +0000211#endif
ths3ae43202007-09-16 21:39:48 +0000212#if defined(TARGET_NR_getdents64) && defined(__NR_getdents64)
bellarddab2ed92003-03-22 15:23:14 +0000213_syscall3(int, sys_getdents64, uint, fd, struct dirent64 *, dirp, uint, count);
ths3ae43202007-09-16 21:39:48 +0000214#endif
thsc6cda172007-10-09 03:42:34 +0000215_syscall2(int, sys_getpriority, int, which, int, who);
blueswir18fcd3692008-08-17 20:26:25 +0000216#if !defined (__x86_64__)
bellard31e31b82003-02-18 22:55:36 +0000217_syscall5(int, _llseek, uint, fd, ulong, hi, ulong, lo,
218 loff_t *, res, uint, wh);
blueswir18fcd3692008-08-17 20:26:25 +0000219#endif
ths64f0ce42007-09-24 09:25:06 +0000220#if defined(TARGET_NR_linkat) && defined(__NR_linkat)
221_syscall5(int,sys_linkat,int,olddirfd,const char *,oldpath,
222 int,newdirfd,const char *,newpath,int,flags)
223#endif
ths4472ad02007-09-24 09:22:32 +0000224#if defined(TARGET_NR_mkdirat) && defined(__NR_mkdirat)
225_syscall3(int,sys_mkdirat,int,dirfd,const char *,pathname,mode_t,mode)
226#endif
ths75ac37a2007-09-24 09:23:05 +0000227#if defined(TARGET_NR_mknodat) && defined(__NR_mknodat)
228_syscall4(int,sys_mknodat,int,dirfd,const char *,pathname,
229 mode_t,mode,dev_t,dev)
230#endif
ths82424832007-09-24 09:21:55 +0000231#if defined(TARGET_NR_openat) && defined(__NR_openat)
232_syscall4(int,sys_openat,int,dirfd,const char *,pathname,int,flags,mode_t,mode)
233#endif
ths5e0ccb12007-09-24 09:26:10 +0000234#if defined(TARGET_NR_readlinkat) && defined(__NR_readlinkat)
235_syscall4(int,sys_readlinkat,int,dirfd,const char *,pathname,
236 char *,buf,size_t,bufsize)
237#endif
ths722183f2007-09-24 09:24:37 +0000238#if defined(TARGET_NR_renameat) && defined(__NR_renameat)
239_syscall4(int,sys_renameat,int,olddirfd,const char *,oldpath,
240 int,newdirfd,const char *,newpath)
241#endif
bellard66fb9762003-03-23 01:06:05 +0000242_syscall3(int,sys_rt_sigqueueinfo,int,pid,int,sig,siginfo_t *,uinfo)
thsb51eaa82007-09-25 16:09:22 +0000243#if defined(TARGET_NR_symlinkat) && defined(__NR_symlinkat)
thsf0b62432007-09-24 09:25:40 +0000244_syscall3(int,sys_symlinkat,const char *,oldpath,
245 int,newdirfd,const char *,newpath)
246#endif
ths7494b0f2007-02-11 18:26:53 +0000247_syscall3(int,sys_syslog,int,type,char*,bufp,int,len)
ths3ae43202007-09-16 21:39:48 +0000248#if defined(TARGET_NR_tgkill) && defined(__NR_tgkill)
ths71455572007-06-21 21:45:30 +0000249_syscall3(int,sys_tgkill,int,tgid,int,pid,int,sig)
ths4cae1d12007-07-12 11:06:53 +0000250#endif
ths3ae43202007-09-16 21:39:48 +0000251#if defined(TARGET_NR_tkill) && defined(__NR_tkill)
ths4cae1d12007-07-12 11:06:53 +0000252_syscall2(int,sys_tkill,int,tid,int,sig)
253#endif
bellardec86b0f2003-04-11 00:15:04 +0000254#ifdef __NR_exit_group
255_syscall1(int,exit_group,int,error_code)
256#endif
ths6f5b89a2007-03-02 20:48:00 +0000257#if defined(TARGET_NR_set_tid_address) && defined(__NR_set_tid_address)
258_syscall1(int,set_tid_address,int *,tidptr)
259#endif
ths8170f562007-09-24 09:24:11 +0000260#if defined(TARGET_NR_unlinkat) && defined(__NR_unlinkat)
261_syscall3(int,sys_unlinkat,int,dirfd,const char *,pathname,int,flags)
262#endif
ths9007f0e2007-09-25 17:50:37 +0000263#if defined(TARGET_NR_utimensat) && defined(__NR_utimensat)
264_syscall4(int,sys_utimensat,int,dirfd,const char *,pathname,
265 const struct timespec *,tsp,int,flags)
266#endif
blueswir18fcd3692008-08-17 20:26:25 +0000267#if defined(USE_NPTL)
pbrookbd0c5662008-05-29 14:34:11 +0000268#if defined(TARGET_NR_futex) && defined(__NR_futex)
269_syscall6(int,sys_futex,int *,uaddr,int,op,int,val,
270 const struct timespec *,timeout,int *,uaddr2,int,val3)
blueswir18fcd3692008-08-17 20:26:25 +0000271#endif
pbrookbd0c5662008-05-29 14:34:11 +0000272#endif
bellard66fb9762003-03-23 01:06:05 +0000273
274extern int personality(int);
bellard9de5e442003-03-23 16:49:39 +0000275extern int flock(int, int);
276extern int setfsuid(int);
277extern int setfsgid(int);
bellard19b84f32003-05-08 15:41:49 +0000278extern int setgroups(int, gid_t *);
bellard31e31b82003-02-18 22:55:36 +0000279
thsb92c47c2007-11-01 00:07:38 +0000280#define ERRNO_TABLE_SIZE 1200
281
282/* target_to_host_errno_table[] is initialized from
283 * host_to_target_errno_table[] in syscall_init(). */
284static uint16_t target_to_host_errno_table[ERRNO_TABLE_SIZE] = {
285};
286
ths637947f2007-06-01 12:09:19 +0000287/*
thsfe8f0962007-07-12 10:59:21 +0000288 * This list is the union of errno values overridden in asm-<arch>/errno.h
ths637947f2007-06-01 12:09:19 +0000289 * minus the errnos that are not actually generic to all archs.
290 */
thsb92c47c2007-11-01 00:07:38 +0000291static uint16_t host_to_target_errno_table[ERRNO_TABLE_SIZE] = {
ths637947f2007-06-01 12:09:19 +0000292 [EIDRM] = TARGET_EIDRM,
293 [ECHRNG] = TARGET_ECHRNG,
294 [EL2NSYNC] = TARGET_EL2NSYNC,
295 [EL3HLT] = TARGET_EL3HLT,
296 [EL3RST] = TARGET_EL3RST,
297 [ELNRNG] = TARGET_ELNRNG,
298 [EUNATCH] = TARGET_EUNATCH,
299 [ENOCSI] = TARGET_ENOCSI,
300 [EL2HLT] = TARGET_EL2HLT,
301 [EDEADLK] = TARGET_EDEADLK,
302 [ENOLCK] = TARGET_ENOLCK,
303 [EBADE] = TARGET_EBADE,
304 [EBADR] = TARGET_EBADR,
305 [EXFULL] = TARGET_EXFULL,
306 [ENOANO] = TARGET_ENOANO,
307 [EBADRQC] = TARGET_EBADRQC,
308 [EBADSLT] = TARGET_EBADSLT,
309 [EBFONT] = TARGET_EBFONT,
310 [ENOSTR] = TARGET_ENOSTR,
311 [ENODATA] = TARGET_ENODATA,
312 [ETIME] = TARGET_ETIME,
313 [ENOSR] = TARGET_ENOSR,
314 [ENONET] = TARGET_ENONET,
315 [ENOPKG] = TARGET_ENOPKG,
316 [EREMOTE] = TARGET_EREMOTE,
317 [ENOLINK] = TARGET_ENOLINK,
318 [EADV] = TARGET_EADV,
319 [ESRMNT] = TARGET_ESRMNT,
320 [ECOMM] = TARGET_ECOMM,
321 [EPROTO] = TARGET_EPROTO,
322 [EDOTDOT] = TARGET_EDOTDOT,
323 [EMULTIHOP] = TARGET_EMULTIHOP,
324 [EBADMSG] = TARGET_EBADMSG,
325 [ENAMETOOLONG] = TARGET_ENAMETOOLONG,
326 [EOVERFLOW] = TARGET_EOVERFLOW,
327 [ENOTUNIQ] = TARGET_ENOTUNIQ,
328 [EBADFD] = TARGET_EBADFD,
329 [EREMCHG] = TARGET_EREMCHG,
330 [ELIBACC] = TARGET_ELIBACC,
331 [ELIBBAD] = TARGET_ELIBBAD,
332 [ELIBSCN] = TARGET_ELIBSCN,
333 [ELIBMAX] = TARGET_ELIBMAX,
334 [ELIBEXEC] = TARGET_ELIBEXEC,
335 [EILSEQ] = TARGET_EILSEQ,
336 [ENOSYS] = TARGET_ENOSYS,
337 [ELOOP] = TARGET_ELOOP,
338 [ERESTART] = TARGET_ERESTART,
339 [ESTRPIPE] = TARGET_ESTRPIPE,
340 [ENOTEMPTY] = TARGET_ENOTEMPTY,
341 [EUSERS] = TARGET_EUSERS,
342 [ENOTSOCK] = TARGET_ENOTSOCK,
343 [EDESTADDRREQ] = TARGET_EDESTADDRREQ,
344 [EMSGSIZE] = TARGET_EMSGSIZE,
345 [EPROTOTYPE] = TARGET_EPROTOTYPE,
346 [ENOPROTOOPT] = TARGET_ENOPROTOOPT,
347 [EPROTONOSUPPORT] = TARGET_EPROTONOSUPPORT,
348 [ESOCKTNOSUPPORT] = TARGET_ESOCKTNOSUPPORT,
349 [EOPNOTSUPP] = TARGET_EOPNOTSUPP,
350 [EPFNOSUPPORT] = TARGET_EPFNOSUPPORT,
351 [EAFNOSUPPORT] = TARGET_EAFNOSUPPORT,
352 [EADDRINUSE] = TARGET_EADDRINUSE,
353 [EADDRNOTAVAIL] = TARGET_EADDRNOTAVAIL,
354 [ENETDOWN] = TARGET_ENETDOWN,
355 [ENETUNREACH] = TARGET_ENETUNREACH,
356 [ENETRESET] = TARGET_ENETRESET,
357 [ECONNABORTED] = TARGET_ECONNABORTED,
358 [ECONNRESET] = TARGET_ECONNRESET,
359 [ENOBUFS] = TARGET_ENOBUFS,
360 [EISCONN] = TARGET_EISCONN,
361 [ENOTCONN] = TARGET_ENOTCONN,
362 [EUCLEAN] = TARGET_EUCLEAN,
363 [ENOTNAM] = TARGET_ENOTNAM,
364 [ENAVAIL] = TARGET_ENAVAIL,
365 [EISNAM] = TARGET_EISNAM,
366 [EREMOTEIO] = TARGET_EREMOTEIO,
367 [ESHUTDOWN] = TARGET_ESHUTDOWN,
368 [ETOOMANYREFS] = TARGET_ETOOMANYREFS,
369 [ETIMEDOUT] = TARGET_ETIMEDOUT,
370 [ECONNREFUSED] = TARGET_ECONNREFUSED,
371 [EHOSTDOWN] = TARGET_EHOSTDOWN,
372 [EHOSTUNREACH] = TARGET_EHOSTUNREACH,
373 [EALREADY] = TARGET_EALREADY,
374 [EINPROGRESS] = TARGET_EINPROGRESS,
375 [ESTALE] = TARGET_ESTALE,
376 [ECANCELED] = TARGET_ECANCELED,
377 [ENOMEDIUM] = TARGET_ENOMEDIUM,
378 [EMEDIUMTYPE] = TARGET_EMEDIUMTYPE,
thsb7fe5db2007-07-23 15:37:46 +0000379#ifdef ENOKEY
ths637947f2007-06-01 12:09:19 +0000380 [ENOKEY] = TARGET_ENOKEY,
thsb7fe5db2007-07-23 15:37:46 +0000381#endif
382#ifdef EKEYEXPIRED
ths637947f2007-06-01 12:09:19 +0000383 [EKEYEXPIRED] = TARGET_EKEYEXPIRED,
thsb7fe5db2007-07-23 15:37:46 +0000384#endif
385#ifdef EKEYREVOKED
ths637947f2007-06-01 12:09:19 +0000386 [EKEYREVOKED] = TARGET_EKEYREVOKED,
thsb7fe5db2007-07-23 15:37:46 +0000387#endif
388#ifdef EKEYREJECTED
ths637947f2007-06-01 12:09:19 +0000389 [EKEYREJECTED] = TARGET_EKEYREJECTED,
thsb7fe5db2007-07-23 15:37:46 +0000390#endif
391#ifdef EOWNERDEAD
ths637947f2007-06-01 12:09:19 +0000392 [EOWNERDEAD] = TARGET_EOWNERDEAD,
thsb7fe5db2007-07-23 15:37:46 +0000393#endif
394#ifdef ENOTRECOVERABLE
ths637947f2007-06-01 12:09:19 +0000395 [ENOTRECOVERABLE] = TARGET_ENOTRECOVERABLE,
thsb7fe5db2007-07-23 15:37:46 +0000396#endif
thsb92c47c2007-11-01 00:07:38 +0000397};
ths637947f2007-06-01 12:09:19 +0000398
399static inline int host_to_target_errno(int err)
400{
401 if(host_to_target_errno_table[err])
402 return host_to_target_errno_table[err];
403 return err;
404}
405
thsb92c47c2007-11-01 00:07:38 +0000406static inline int target_to_host_errno(int err)
407{
408 if (target_to_host_errno_table[err])
409 return target_to_host_errno_table[err];
410 return err;
411}
412
blueswir1992f48a2007-10-14 16:27:31 +0000413static inline abi_long get_errno(abi_long ret)
bellard31e31b82003-02-18 22:55:36 +0000414{
415 if (ret == -1)
ths637947f2007-06-01 12:09:19 +0000416 return -host_to_target_errno(errno);
bellard31e31b82003-02-18 22:55:36 +0000417 else
418 return ret;
419}
420
blueswir1992f48a2007-10-14 16:27:31 +0000421static inline int is_error(abi_long ret)
bellard31e31b82003-02-18 22:55:36 +0000422{
blueswir1992f48a2007-10-14 16:27:31 +0000423 return (abi_ulong)ret >= (abi_ulong)(-4096);
bellard31e31b82003-02-18 22:55:36 +0000424}
425
thsb92c47c2007-11-01 00:07:38 +0000426char *target_strerror(int err)
427{
428 return strerror(target_to_host_errno(err));
429}
430
blueswir1992f48a2007-10-14 16:27:31 +0000431static abi_ulong target_brk;
432static abi_ulong target_original_brk;
bellard31e31b82003-02-18 22:55:36 +0000433
blueswir1992f48a2007-10-14 16:27:31 +0000434void target_set_brk(abi_ulong new_brk)
bellard31e31b82003-02-18 22:55:36 +0000435{
blueswir14c1de732007-07-07 20:45:44 +0000436 target_original_brk = target_brk = HOST_PAGE_ALIGN(new_brk);
bellard31e31b82003-02-18 22:55:36 +0000437}
438
ths0da46a62007-10-20 20:23:07 +0000439/* do_brk() must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +0000440abi_long do_brk(abi_ulong new_brk)
bellard31e31b82003-02-18 22:55:36 +0000441{
blueswir1992f48a2007-10-14 16:27:31 +0000442 abi_ulong brk_page;
443 abi_long mapped_addr;
bellard31e31b82003-02-18 22:55:36 +0000444 int new_alloc_size;
445
446 if (!new_brk)
pbrook53a59602006-03-25 19:31:22 +0000447 return target_brk;
bellard31e31b82003-02-18 22:55:36 +0000448 if (new_brk < target_original_brk)
balrog7ab240a2008-04-26 12:17:34 +0000449 return target_brk;
ths3b46e622007-09-17 08:09:54 +0000450
pbrook53a59602006-03-25 19:31:22 +0000451 brk_page = HOST_PAGE_ALIGN(target_brk);
bellard31e31b82003-02-18 22:55:36 +0000452
453 /* If the new brk is less than this, set it and we're done... */
454 if (new_brk < brk_page) {
455 target_brk = new_brk;
pbrook53a59602006-03-25 19:31:22 +0000456 return target_brk;
bellard31e31b82003-02-18 22:55:36 +0000457 }
458
459 /* We need to allocate more memory after the brk... */
bellard54936002003-05-13 00:25:15 +0000460 new_alloc_size = HOST_PAGE_ALIGN(new_brk - brk_page + 1);
ths5fafdf22007-09-16 21:08:06 +0000461 mapped_addr = get_errno(target_mmap(brk_page, new_alloc_size,
bellard54936002003-05-13 00:25:15 +0000462 PROT_READ|PROT_WRITE,
463 MAP_ANON|MAP_FIXED|MAP_PRIVATE, 0, 0));
balrog7ab240a2008-04-26 12:17:34 +0000464
465 if (!is_error(mapped_addr))
bellard31e31b82003-02-18 22:55:36 +0000466 target_brk = new_brk;
balrog7ab240a2008-04-26 12:17:34 +0000467
468 return target_brk;
bellard31e31b82003-02-18 22:55:36 +0000469}
470
ths26edcf42007-12-09 02:25:24 +0000471static inline abi_long copy_from_user_fdset(fd_set *fds,
472 abi_ulong target_fds_addr,
473 int n)
bellard31e31b82003-02-18 22:55:36 +0000474{
ths26edcf42007-12-09 02:25:24 +0000475 int i, nw, j, k;
476 abi_ulong b, *target_fds;
477
478 nw = (n + TARGET_ABI_BITS - 1) / TARGET_ABI_BITS;
479 if (!(target_fds = lock_user(VERIFY_READ,
480 target_fds_addr,
481 sizeof(abi_ulong) * nw,
482 1)))
483 return -TARGET_EFAULT;
484
485 FD_ZERO(fds);
486 k = 0;
487 for (i = 0; i < nw; i++) {
488 /* grab the abi_ulong */
489 __get_user(b, &target_fds[i]);
490 for (j = 0; j < TARGET_ABI_BITS; j++) {
491 /* check the bit inside the abi_ulong */
492 if ((b >> j) & 1)
493 FD_SET(k, fds);
494 k++;
bellard31e31b82003-02-18 22:55:36 +0000495 }
bellard31e31b82003-02-18 22:55:36 +0000496 }
ths26edcf42007-12-09 02:25:24 +0000497
498 unlock_user(target_fds, target_fds_addr, 0);
499
500 return 0;
bellard31e31b82003-02-18 22:55:36 +0000501}
502
ths26edcf42007-12-09 02:25:24 +0000503static inline abi_long copy_to_user_fdset(abi_ulong target_fds_addr,
504 const fd_set *fds,
505 int n)
bellard31e31b82003-02-18 22:55:36 +0000506{
bellard31e31b82003-02-18 22:55:36 +0000507 int i, nw, j, k;
blueswir1992f48a2007-10-14 16:27:31 +0000508 abi_long v;
ths26edcf42007-12-09 02:25:24 +0000509 abi_ulong *target_fds;
bellard31e31b82003-02-18 22:55:36 +0000510
ths26edcf42007-12-09 02:25:24 +0000511 nw = (n + TARGET_ABI_BITS - 1) / TARGET_ABI_BITS;
512 if (!(target_fds = lock_user(VERIFY_WRITE,
513 target_fds_addr,
514 sizeof(abi_ulong) * nw,
515 0)))
516 return -TARGET_EFAULT;
517
518 k = 0;
519 for (i = 0; i < nw; i++) {
520 v = 0;
521 for (j = 0; j < TARGET_ABI_BITS; j++) {
522 v |= ((FD_ISSET(k, fds) != 0) << j);
523 k++;
bellard31e31b82003-02-18 22:55:36 +0000524 }
ths26edcf42007-12-09 02:25:24 +0000525 __put_user(v, &target_fds[i]);
bellard31e31b82003-02-18 22:55:36 +0000526 }
ths26edcf42007-12-09 02:25:24 +0000527
528 unlock_user(target_fds, target_fds_addr, sizeof(abi_ulong) * nw);
529
530 return 0;
bellard31e31b82003-02-18 22:55:36 +0000531}
532
bellardc596ed12003-07-13 17:32:31 +0000533#if defined(__alpha__)
534#define HOST_HZ 1024
535#else
536#define HOST_HZ 100
537#endif
538
blueswir1992f48a2007-10-14 16:27:31 +0000539static inline abi_long host_to_target_clock_t(long ticks)
bellardc596ed12003-07-13 17:32:31 +0000540{
541#if HOST_HZ == TARGET_HZ
542 return ticks;
543#else
544 return ((int64_t)ticks * TARGET_HZ) / HOST_HZ;
545#endif
546}
547
bellard579a97f2007-11-11 14:26:47 +0000548static inline abi_long host_to_target_rusage(abi_ulong target_addr,
549 const struct rusage *rusage)
bellardb4091862003-05-16 15:39:34 +0000550{
pbrook53a59602006-03-25 19:31:22 +0000551 struct target_rusage *target_rusage;
552
bellard579a97f2007-11-11 14:26:47 +0000553 if (!lock_user_struct(VERIFY_WRITE, target_rusage, target_addr, 0))
554 return -TARGET_EFAULT;
bellardb4091862003-05-16 15:39:34 +0000555 target_rusage->ru_utime.tv_sec = tswapl(rusage->ru_utime.tv_sec);
556 target_rusage->ru_utime.tv_usec = tswapl(rusage->ru_utime.tv_usec);
557 target_rusage->ru_stime.tv_sec = tswapl(rusage->ru_stime.tv_sec);
558 target_rusage->ru_stime.tv_usec = tswapl(rusage->ru_stime.tv_usec);
559 target_rusage->ru_maxrss = tswapl(rusage->ru_maxrss);
560 target_rusage->ru_ixrss = tswapl(rusage->ru_ixrss);
561 target_rusage->ru_idrss = tswapl(rusage->ru_idrss);
562 target_rusage->ru_isrss = tswapl(rusage->ru_isrss);
563 target_rusage->ru_minflt = tswapl(rusage->ru_minflt);
564 target_rusage->ru_majflt = tswapl(rusage->ru_majflt);
565 target_rusage->ru_nswap = tswapl(rusage->ru_nswap);
566 target_rusage->ru_inblock = tswapl(rusage->ru_inblock);
567 target_rusage->ru_oublock = tswapl(rusage->ru_oublock);
568 target_rusage->ru_msgsnd = tswapl(rusage->ru_msgsnd);
569 target_rusage->ru_msgrcv = tswapl(rusage->ru_msgrcv);
570 target_rusage->ru_nsignals = tswapl(rusage->ru_nsignals);
571 target_rusage->ru_nvcsw = tswapl(rusage->ru_nvcsw);
572 target_rusage->ru_nivcsw = tswapl(rusage->ru_nivcsw);
pbrook53a59602006-03-25 19:31:22 +0000573 unlock_user_struct(target_rusage, target_addr, 1);
bellard579a97f2007-11-11 14:26:47 +0000574
575 return 0;
bellardb4091862003-05-16 15:39:34 +0000576}
577
ths788f5ec2007-12-09 02:37:05 +0000578static inline abi_long copy_from_user_timeval(struct timeval *tv,
579 abi_ulong target_tv_addr)
bellard31e31b82003-02-18 22:55:36 +0000580{
pbrook53a59602006-03-25 19:31:22 +0000581 struct target_timeval *target_tv;
582
ths788f5ec2007-12-09 02:37:05 +0000583 if (!lock_user_struct(VERIFY_READ, target_tv, target_tv_addr, 1))
bellard579a97f2007-11-11 14:26:47 +0000584 return -TARGET_EFAULT;
ths788f5ec2007-12-09 02:37:05 +0000585
586 __get_user(tv->tv_sec, &target_tv->tv_sec);
587 __get_user(tv->tv_usec, &target_tv->tv_usec);
588
589 unlock_user_struct(target_tv, target_tv_addr, 0);
bellard579a97f2007-11-11 14:26:47 +0000590
591 return 0;
bellard31e31b82003-02-18 22:55:36 +0000592}
593
ths788f5ec2007-12-09 02:37:05 +0000594static inline abi_long copy_to_user_timeval(abi_ulong target_tv_addr,
595 const struct timeval *tv)
bellard31e31b82003-02-18 22:55:36 +0000596{
pbrook53a59602006-03-25 19:31:22 +0000597 struct target_timeval *target_tv;
598
ths788f5ec2007-12-09 02:37:05 +0000599 if (!lock_user_struct(VERIFY_WRITE, target_tv, target_tv_addr, 0))
bellard579a97f2007-11-11 14:26:47 +0000600 return -TARGET_EFAULT;
ths788f5ec2007-12-09 02:37:05 +0000601
602 __put_user(tv->tv_sec, &target_tv->tv_sec);
603 __put_user(tv->tv_usec, &target_tv->tv_usec);
604
605 unlock_user_struct(target_tv, target_tv_addr, 1);
bellard579a97f2007-11-11 14:26:47 +0000606
607 return 0;
bellard31e31b82003-02-18 22:55:36 +0000608}
609
610
ths0da46a62007-10-20 20:23:07 +0000611/* do_select() must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +0000612static abi_long do_select(int n,
ths26edcf42007-12-09 02:25:24 +0000613 abi_ulong rfd_addr, abi_ulong wfd_addr,
614 abi_ulong efd_addr, abi_ulong target_tv_addr)
bellard31e31b82003-02-18 22:55:36 +0000615{
616 fd_set rfds, wfds, efds;
617 fd_set *rfds_ptr, *wfds_ptr, *efds_ptr;
618 struct timeval tv, *tv_ptr;
blueswir1992f48a2007-10-14 16:27:31 +0000619 abi_long ret;
bellard31e31b82003-02-18 22:55:36 +0000620
ths26edcf42007-12-09 02:25:24 +0000621 if (rfd_addr) {
622 if (copy_from_user_fdset(&rfds, rfd_addr, n))
623 return -TARGET_EFAULT;
624 rfds_ptr = &rfds;
pbrook53a59602006-03-25 19:31:22 +0000625 } else {
pbrook53a59602006-03-25 19:31:22 +0000626 rfds_ptr = NULL;
627 }
ths26edcf42007-12-09 02:25:24 +0000628 if (wfd_addr) {
629 if (copy_from_user_fdset(&wfds, wfd_addr, n))
630 return -TARGET_EFAULT;
631 wfds_ptr = &wfds;
pbrook53a59602006-03-25 19:31:22 +0000632 } else {
pbrook53a59602006-03-25 19:31:22 +0000633 wfds_ptr = NULL;
634 }
ths26edcf42007-12-09 02:25:24 +0000635 if (efd_addr) {
636 if (copy_from_user_fdset(&efds, efd_addr, n))
637 return -TARGET_EFAULT;
638 efds_ptr = &efds;
pbrook53a59602006-03-25 19:31:22 +0000639 } else {
pbrook53a59602006-03-25 19:31:22 +0000640 efds_ptr = NULL;
641 }
ths3b46e622007-09-17 08:09:54 +0000642
ths26edcf42007-12-09 02:25:24 +0000643 if (target_tv_addr) {
ths788f5ec2007-12-09 02:37:05 +0000644 if (copy_from_user_timeval(&tv, target_tv_addr))
645 return -TARGET_EFAULT;
bellard31e31b82003-02-18 22:55:36 +0000646 tv_ptr = &tv;
647 } else {
648 tv_ptr = NULL;
649 }
ths26edcf42007-12-09 02:25:24 +0000650
bellard31e31b82003-02-18 22:55:36 +0000651 ret = get_errno(select(n, rfds_ptr, wfds_ptr, efds_ptr, tv_ptr));
pbrook53a59602006-03-25 19:31:22 +0000652
ths26edcf42007-12-09 02:25:24 +0000653 if (!is_error(ret)) {
654 if (rfd_addr && copy_to_user_fdset(rfd_addr, &rfds, n))
655 return -TARGET_EFAULT;
656 if (wfd_addr && copy_to_user_fdset(wfd_addr, &wfds, n))
657 return -TARGET_EFAULT;
658 if (efd_addr && copy_to_user_fdset(efd_addr, &efds, n))
659 return -TARGET_EFAULT;
bellard31e31b82003-02-18 22:55:36 +0000660
ths788f5ec2007-12-09 02:37:05 +0000661 if (target_tv_addr && copy_to_user_timeval(target_tv_addr, &tv))
662 return -TARGET_EFAULT;
bellard31e31b82003-02-18 22:55:36 +0000663 }
bellard579a97f2007-11-11 14:26:47 +0000664
bellard31e31b82003-02-18 22:55:36 +0000665 return ret;
666}
667
bellard579a97f2007-11-11 14:26:47 +0000668static inline abi_long target_to_host_sockaddr(struct sockaddr *addr,
669 abi_ulong target_addr,
670 socklen_t len)
bellard7854b052003-03-29 17:22:23 +0000671{
pbrook53a59602006-03-25 19:31:22 +0000672 struct target_sockaddr *target_saddr;
673
bellard579a97f2007-11-11 14:26:47 +0000674 target_saddr = lock_user(VERIFY_READ, target_addr, len, 1);
675 if (!target_saddr)
676 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +0000677 memcpy(addr, target_saddr, len);
678 addr->sa_family = tswap16(target_saddr->sa_family);
679 unlock_user(target_saddr, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +0000680
681 return 0;
bellard7854b052003-03-29 17:22:23 +0000682}
683
bellard579a97f2007-11-11 14:26:47 +0000684static inline abi_long host_to_target_sockaddr(abi_ulong target_addr,
685 struct sockaddr *addr,
686 socklen_t len)
bellard7854b052003-03-29 17:22:23 +0000687{
pbrook53a59602006-03-25 19:31:22 +0000688 struct target_sockaddr *target_saddr;
689
bellard579a97f2007-11-11 14:26:47 +0000690 target_saddr = lock_user(VERIFY_WRITE, target_addr, len, 0);
691 if (!target_saddr)
692 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +0000693 memcpy(target_saddr, addr, len);
694 target_saddr->sa_family = tswap16(addr->sa_family);
695 unlock_user(target_saddr, target_addr, len);
bellard579a97f2007-11-11 14:26:47 +0000696
697 return 0;
bellard7854b052003-03-29 17:22:23 +0000698}
699
pbrook53a59602006-03-25 19:31:22 +0000700/* ??? Should this also swap msgh->name? */
bellard5a4a8982007-11-11 17:39:18 +0000701static inline abi_long target_to_host_cmsg(struct msghdr *msgh,
702 struct target_msghdr *target_msgh)
bellard7854b052003-03-29 17:22:23 +0000703{
704 struct cmsghdr *cmsg = CMSG_FIRSTHDR(msgh);
bellard5a4a8982007-11-11 17:39:18 +0000705 abi_long msg_controllen;
706 abi_ulong target_cmsg_addr;
707 struct target_cmsghdr *target_cmsg;
bellard7854b052003-03-29 17:22:23 +0000708 socklen_t space = 0;
bellard5a4a8982007-11-11 17:39:18 +0000709
710 msg_controllen = tswapl(target_msgh->msg_controllen);
711 if (msg_controllen < sizeof (struct target_cmsghdr))
712 goto the_end;
713 target_cmsg_addr = tswapl(target_msgh->msg_control);
714 target_cmsg = lock_user(VERIFY_READ, target_cmsg_addr, msg_controllen, 1);
715 if (!target_cmsg)
716 return -TARGET_EFAULT;
bellard7854b052003-03-29 17:22:23 +0000717
718 while (cmsg && target_cmsg) {
719 void *data = CMSG_DATA(cmsg);
720 void *target_data = TARGET_CMSG_DATA(target_cmsg);
721
ths5fafdf22007-09-16 21:08:06 +0000722 int len = tswapl(target_cmsg->cmsg_len)
bellard7854b052003-03-29 17:22:23 +0000723 - TARGET_CMSG_ALIGN(sizeof (struct target_cmsghdr));
724
725 space += CMSG_SPACE(len);
726 if (space > msgh->msg_controllen) {
727 space -= CMSG_SPACE(len);
bellard31febb72005-12-18 20:03:27 +0000728 gemu_log("Host cmsg overflow\n");
bellard7854b052003-03-29 17:22:23 +0000729 break;
730 }
731
732 cmsg->cmsg_level = tswap32(target_cmsg->cmsg_level);
733 cmsg->cmsg_type = tswap32(target_cmsg->cmsg_type);
734 cmsg->cmsg_len = CMSG_LEN(len);
735
bellard3532fa72006-06-24 15:06:03 +0000736 if (cmsg->cmsg_level != TARGET_SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS) {
bellard7854b052003-03-29 17:22:23 +0000737 gemu_log("Unsupported ancillary data: %d/%d\n", cmsg->cmsg_level, cmsg->cmsg_type);
738 memcpy(data, target_data, len);
739 } else {
740 int *fd = (int *)data;
741 int *target_fd = (int *)target_data;
742 int i, numfds = len / sizeof(int);
743
744 for (i = 0; i < numfds; i++)
745 fd[i] = tswap32(target_fd[i]);
746 }
747
748 cmsg = CMSG_NXTHDR(msgh, cmsg);
749 target_cmsg = TARGET_CMSG_NXTHDR(target_msgh, target_cmsg);
750 }
bellard5a4a8982007-11-11 17:39:18 +0000751 unlock_user(target_cmsg, target_cmsg_addr, 0);
752 the_end:
bellard7854b052003-03-29 17:22:23 +0000753 msgh->msg_controllen = space;
bellard5a4a8982007-11-11 17:39:18 +0000754 return 0;
bellard7854b052003-03-29 17:22:23 +0000755}
756
pbrook53a59602006-03-25 19:31:22 +0000757/* ??? Should this also swap msgh->name? */
bellard5a4a8982007-11-11 17:39:18 +0000758static inline abi_long host_to_target_cmsg(struct target_msghdr *target_msgh,
759 struct msghdr *msgh)
bellard7854b052003-03-29 17:22:23 +0000760{
761 struct cmsghdr *cmsg = CMSG_FIRSTHDR(msgh);
bellard5a4a8982007-11-11 17:39:18 +0000762 abi_long msg_controllen;
763 abi_ulong target_cmsg_addr;
764 struct target_cmsghdr *target_cmsg;
bellard7854b052003-03-29 17:22:23 +0000765 socklen_t space = 0;
766
bellard5a4a8982007-11-11 17:39:18 +0000767 msg_controllen = tswapl(target_msgh->msg_controllen);
768 if (msg_controllen < sizeof (struct target_cmsghdr))
769 goto the_end;
770 target_cmsg_addr = tswapl(target_msgh->msg_control);
771 target_cmsg = lock_user(VERIFY_WRITE, target_cmsg_addr, msg_controllen, 0);
772 if (!target_cmsg)
773 return -TARGET_EFAULT;
774
bellard7854b052003-03-29 17:22:23 +0000775 while (cmsg && target_cmsg) {
776 void *data = CMSG_DATA(cmsg);
777 void *target_data = TARGET_CMSG_DATA(target_cmsg);
778
779 int len = cmsg->cmsg_len - CMSG_ALIGN(sizeof (struct cmsghdr));
780
781 space += TARGET_CMSG_SPACE(len);
bellard5a4a8982007-11-11 17:39:18 +0000782 if (space > msg_controllen) {
bellard7854b052003-03-29 17:22:23 +0000783 space -= TARGET_CMSG_SPACE(len);
bellard31febb72005-12-18 20:03:27 +0000784 gemu_log("Target cmsg overflow\n");
bellard7854b052003-03-29 17:22:23 +0000785 break;
786 }
787
788 target_cmsg->cmsg_level = tswap32(cmsg->cmsg_level);
789 target_cmsg->cmsg_type = tswap32(cmsg->cmsg_type);
790 target_cmsg->cmsg_len = tswapl(TARGET_CMSG_LEN(len));
791
bellard3532fa72006-06-24 15:06:03 +0000792 if (cmsg->cmsg_level != TARGET_SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS) {
bellard7854b052003-03-29 17:22:23 +0000793 gemu_log("Unsupported ancillary data: %d/%d\n", cmsg->cmsg_level, cmsg->cmsg_type);
794 memcpy(target_data, data, len);
795 } else {
796 int *fd = (int *)data;
797 int *target_fd = (int *)target_data;
798 int i, numfds = len / sizeof(int);
799
800 for (i = 0; i < numfds; i++)
801 target_fd[i] = tswap32(fd[i]);
802 }
803
804 cmsg = CMSG_NXTHDR(msgh, cmsg);
805 target_cmsg = TARGET_CMSG_NXTHDR(target_msgh, target_cmsg);
806 }
bellard5a4a8982007-11-11 17:39:18 +0000807 unlock_user(target_cmsg, target_cmsg_addr, space);
808 the_end:
809 target_msgh->msg_controllen = tswapl(space);
810 return 0;
bellard7854b052003-03-29 17:22:23 +0000811}
812
ths0da46a62007-10-20 20:23:07 +0000813/* do_setsockopt() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +0000814static abi_long do_setsockopt(int sockfd, int level, int optname,
bellard2f619692007-11-16 10:46:05 +0000815 abi_ulong optval_addr, socklen_t optlen)
bellard7854b052003-03-29 17:22:23 +0000816{
blueswir1992f48a2007-10-14 16:27:31 +0000817 abi_long ret;
j_mayer32407102007-09-26 23:01:49 +0000818 int val;
ths3b46e622007-09-17 08:09:54 +0000819
bellard8853f862004-02-22 14:57:26 +0000820 switch(level) {
821 case SOL_TCP:
bellard7854b052003-03-29 17:22:23 +0000822 /* TCP options all take an 'int' value. */
bellard7854b052003-03-29 17:22:23 +0000823 if (optlen < sizeof(uint32_t))
ths0da46a62007-10-20 20:23:07 +0000824 return -TARGET_EINVAL;
ths3b46e622007-09-17 08:09:54 +0000825
bellard2f619692007-11-16 10:46:05 +0000826 if (get_user_u32(val, optval_addr))
827 return -TARGET_EFAULT;
bellard8853f862004-02-22 14:57:26 +0000828 ret = get_errno(setsockopt(sockfd, level, optname, &val, sizeof(val)));
829 break;
830 case SOL_IP:
831 switch(optname) {
bellard2efbe912005-07-23 15:10:20 +0000832 case IP_TOS:
833 case IP_TTL:
bellard8853f862004-02-22 14:57:26 +0000834 case IP_HDRINCL:
bellard2efbe912005-07-23 15:10:20 +0000835 case IP_ROUTER_ALERT:
836 case IP_RECVOPTS:
837 case IP_RETOPTS:
838 case IP_PKTINFO:
839 case IP_MTU_DISCOVER:
840 case IP_RECVERR:
841 case IP_RECVTOS:
842#ifdef IP_FREEBIND
843 case IP_FREEBIND:
844#endif
845 case IP_MULTICAST_TTL:
846 case IP_MULTICAST_LOOP:
bellard8853f862004-02-22 14:57:26 +0000847 val = 0;
848 if (optlen >= sizeof(uint32_t)) {
bellard2f619692007-11-16 10:46:05 +0000849 if (get_user_u32(val, optval_addr))
850 return -TARGET_EFAULT;
bellard8853f862004-02-22 14:57:26 +0000851 } else if (optlen >= 1) {
bellard2f619692007-11-16 10:46:05 +0000852 if (get_user_u8(val, optval_addr))
853 return -TARGET_EFAULT;
bellard8853f862004-02-22 14:57:26 +0000854 }
855 ret = get_errno(setsockopt(sockfd, level, optname, &val, sizeof(val)));
856 break;
857 default:
858 goto unimplemented;
859 }
860 break;
bellard3532fa72006-06-24 15:06:03 +0000861 case TARGET_SOL_SOCKET:
bellard8853f862004-02-22 14:57:26 +0000862 switch (optname) {
863 /* Options with 'int' argument. */
bellard3532fa72006-06-24 15:06:03 +0000864 case TARGET_SO_DEBUG:
865 optname = SO_DEBUG;
866 break;
867 case TARGET_SO_REUSEADDR:
868 optname = SO_REUSEADDR;
869 break;
870 case TARGET_SO_TYPE:
871 optname = SO_TYPE;
872 break;
873 case TARGET_SO_ERROR:
874 optname = SO_ERROR;
875 break;
876 case TARGET_SO_DONTROUTE:
877 optname = SO_DONTROUTE;
878 break;
879 case TARGET_SO_BROADCAST:
880 optname = SO_BROADCAST;
881 break;
882 case TARGET_SO_SNDBUF:
883 optname = SO_SNDBUF;
884 break;
885 case TARGET_SO_RCVBUF:
886 optname = SO_RCVBUF;
887 break;
888 case TARGET_SO_KEEPALIVE:
889 optname = SO_KEEPALIVE;
890 break;
891 case TARGET_SO_OOBINLINE:
892 optname = SO_OOBINLINE;
893 break;
894 case TARGET_SO_NO_CHECK:
895 optname = SO_NO_CHECK;
896 break;
897 case TARGET_SO_PRIORITY:
898 optname = SO_PRIORITY;
899 break;
bellard5e83e8e2005-03-01 22:32:06 +0000900#ifdef SO_BSDCOMPAT
bellard3532fa72006-06-24 15:06:03 +0000901 case TARGET_SO_BSDCOMPAT:
902 optname = SO_BSDCOMPAT;
903 break;
bellard5e83e8e2005-03-01 22:32:06 +0000904#endif
bellard3532fa72006-06-24 15:06:03 +0000905 case TARGET_SO_PASSCRED:
906 optname = SO_PASSCRED;
907 break;
908 case TARGET_SO_TIMESTAMP:
909 optname = SO_TIMESTAMP;
910 break;
911 case TARGET_SO_RCVLOWAT:
912 optname = SO_RCVLOWAT;
913 break;
914 case TARGET_SO_RCVTIMEO:
915 optname = SO_RCVTIMEO;
916 break;
917 case TARGET_SO_SNDTIMEO:
918 optname = SO_SNDTIMEO;
919 break;
bellard8853f862004-02-22 14:57:26 +0000920 break;
921 default:
922 goto unimplemented;
923 }
bellard3532fa72006-06-24 15:06:03 +0000924 if (optlen < sizeof(uint32_t))
bellard2f619692007-11-16 10:46:05 +0000925 return -TARGET_EINVAL;
bellard3532fa72006-06-24 15:06:03 +0000926
bellard2f619692007-11-16 10:46:05 +0000927 if (get_user_u32(val, optval_addr))
928 return -TARGET_EFAULT;
bellard3532fa72006-06-24 15:06:03 +0000929 ret = get_errno(setsockopt(sockfd, SOL_SOCKET, optname, &val, sizeof(val)));
bellard8853f862004-02-22 14:57:26 +0000930 break;
bellard7854b052003-03-29 17:22:23 +0000931 default:
bellard8853f862004-02-22 14:57:26 +0000932 unimplemented:
933 gemu_log("Unsupported setsockopt level=%d optname=%d \n", level, optname);
ths6fa13c12007-12-18 02:41:04 +0000934 ret = -TARGET_ENOPROTOOPT;
bellard7854b052003-03-29 17:22:23 +0000935 }
bellard8853f862004-02-22 14:57:26 +0000936 return ret;
bellard7854b052003-03-29 17:22:23 +0000937}
938
ths0da46a62007-10-20 20:23:07 +0000939/* do_getsockopt() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +0000940static abi_long do_getsockopt(int sockfd, int level, int optname,
bellard2f619692007-11-16 10:46:05 +0000941 abi_ulong optval_addr, abi_ulong optlen)
bellard7854b052003-03-29 17:22:23 +0000942{
blueswir1992f48a2007-10-14 16:27:31 +0000943 abi_long ret;
j_mayer32407102007-09-26 23:01:49 +0000944 int len, lv, val;
bellard8853f862004-02-22 14:57:26 +0000945
946 switch(level) {
bellard3532fa72006-06-24 15:06:03 +0000947 case TARGET_SOL_SOCKET:
948 level = SOL_SOCKET;
bellard8853f862004-02-22 14:57:26 +0000949 switch (optname) {
bellard3532fa72006-06-24 15:06:03 +0000950 case TARGET_SO_LINGER:
951 case TARGET_SO_RCVTIMEO:
952 case TARGET_SO_SNDTIMEO:
953 case TARGET_SO_PEERCRED:
954 case TARGET_SO_PEERNAME:
bellard8853f862004-02-22 14:57:26 +0000955 /* These don't just return a single integer */
956 goto unimplemented;
957 default:
bellard2efbe912005-07-23 15:10:20 +0000958 goto int_case;
959 }
960 break;
961 case SOL_TCP:
962 /* TCP options all take an 'int' value. */
963 int_case:
bellard2f619692007-11-16 10:46:05 +0000964 if (get_user_u32(len, optlen))
965 return -TARGET_EFAULT;
bellard2efbe912005-07-23 15:10:20 +0000966 if (len < 0)
ths0da46a62007-10-20 20:23:07 +0000967 return -TARGET_EINVAL;
bellard2efbe912005-07-23 15:10:20 +0000968 lv = sizeof(int);
969 ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
970 if (ret < 0)
971 return ret;
972 val = tswap32(val);
973 if (len > lv)
974 len = lv;
bellard2f619692007-11-16 10:46:05 +0000975 if (len == 4) {
976 if (put_user_u32(val, optval_addr))
977 return -TARGET_EFAULT;
978 } else {
979 if (put_user_u8(val, optval_addr))
980 return -TARGET_EFAULT;
981 }
982 if (put_user_u32(len, optlen))
983 return -TARGET_EFAULT;
bellard2efbe912005-07-23 15:10:20 +0000984 break;
985 case SOL_IP:
986 switch(optname) {
987 case IP_TOS:
988 case IP_TTL:
989 case IP_HDRINCL:
990 case IP_ROUTER_ALERT:
991 case IP_RECVOPTS:
992 case IP_RETOPTS:
993 case IP_PKTINFO:
994 case IP_MTU_DISCOVER:
995 case IP_RECVERR:
996 case IP_RECVTOS:
997#ifdef IP_FREEBIND
998 case IP_FREEBIND:
999#endif
1000 case IP_MULTICAST_TTL:
1001 case IP_MULTICAST_LOOP:
bellard2f619692007-11-16 10:46:05 +00001002 if (get_user_u32(len, optlen))
1003 return -TARGET_EFAULT;
bellard8853f862004-02-22 14:57:26 +00001004 if (len < 0)
ths0da46a62007-10-20 20:23:07 +00001005 return -TARGET_EINVAL;
bellard8853f862004-02-22 14:57:26 +00001006 lv = sizeof(int);
1007 ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
1008 if (ret < 0)
1009 return ret;
bellard2efbe912005-07-23 15:10:20 +00001010 if (len < sizeof(int) && len > 0 && val >= 0 && val < 255) {
bellard2efbe912005-07-23 15:10:20 +00001011 len = 1;
bellard2f619692007-11-16 10:46:05 +00001012 if (put_user_u32(len, optlen)
1013 || put_user_u8(val, optval_addr))
1014 return -TARGET_EFAULT;
bellard2efbe912005-07-23 15:10:20 +00001015 } else {
bellard2efbe912005-07-23 15:10:20 +00001016 if (len > sizeof(int))
1017 len = sizeof(int);
bellard2f619692007-11-16 10:46:05 +00001018 if (put_user_u32(len, optlen)
1019 || put_user_u32(val, optval_addr))
1020 return -TARGET_EFAULT;
bellard2efbe912005-07-23 15:10:20 +00001021 }
bellard8853f862004-02-22 14:57:26 +00001022 break;
bellard2efbe912005-07-23 15:10:20 +00001023 default:
thsc02f4992007-12-18 02:39:59 +00001024 ret = -TARGET_ENOPROTOOPT;
1025 break;
bellard8853f862004-02-22 14:57:26 +00001026 }
1027 break;
1028 default:
1029 unimplemented:
1030 gemu_log("getsockopt level=%d optname=%d not yet supported\n",
1031 level, optname);
thsc02f4992007-12-18 02:39:59 +00001032 ret = -TARGET_EOPNOTSUPP;
bellard8853f862004-02-22 14:57:26 +00001033 break;
1034 }
1035 return ret;
bellard7854b052003-03-29 17:22:23 +00001036}
1037
bellard579a97f2007-11-11 14:26:47 +00001038/* FIXME
1039 * lock_iovec()/unlock_iovec() have a return code of 0 for success where
1040 * other lock functions have a return code of 0 for failure.
1041 */
1042static abi_long lock_iovec(int type, struct iovec *vec, abi_ulong target_addr,
1043 int count, int copy)
pbrook53a59602006-03-25 19:31:22 +00001044{
1045 struct target_iovec *target_vec;
blueswir1992f48a2007-10-14 16:27:31 +00001046 abi_ulong base;
bellard579a97f2007-11-11 14:26:47 +00001047 int i, j;
pbrook53a59602006-03-25 19:31:22 +00001048
bellard579a97f2007-11-11 14:26:47 +00001049 target_vec = lock_user(VERIFY_READ, target_addr, count * sizeof(struct target_iovec), 1);
1050 if (!target_vec)
1051 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00001052 for(i = 0;i < count; i++) {
1053 base = tswapl(target_vec[i].iov_base);
1054 vec[i].iov_len = tswapl(target_vec[i].iov_len);
bellard41df8412008-02-04 22:26:57 +00001055 if (vec[i].iov_len != 0) {
1056 vec[i].iov_base = lock_user(type, base, vec[i].iov_len, copy);
balrog7bedce82008-02-10 13:28:08 +00001057 if (!vec[i].iov_base && vec[i].iov_len)
bellard41df8412008-02-04 22:26:57 +00001058 goto fail;
1059 } else {
1060 /* zero length pointer is ignored */
1061 vec[i].iov_base = NULL;
1062 }
pbrook53a59602006-03-25 19:31:22 +00001063 }
1064 unlock_user (target_vec, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00001065 return 0;
1066 fail:
1067 /* failure - unwind locks */
1068 for (j = 0; j < i; j++) {
1069 base = tswapl(target_vec[j].iov_base);
1070 unlock_user(vec[j].iov_base, base, 0);
1071 }
1072 unlock_user (target_vec, target_addr, 0);
1073 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00001074}
1075
bellard579a97f2007-11-11 14:26:47 +00001076static abi_long unlock_iovec(struct iovec *vec, abi_ulong target_addr,
1077 int count, int copy)
pbrook53a59602006-03-25 19:31:22 +00001078{
1079 struct target_iovec *target_vec;
blueswir1992f48a2007-10-14 16:27:31 +00001080 abi_ulong base;
pbrook53a59602006-03-25 19:31:22 +00001081 int i;
1082
bellard579a97f2007-11-11 14:26:47 +00001083 target_vec = lock_user(VERIFY_READ, target_addr, count * sizeof(struct target_iovec), 1);
1084 if (!target_vec)
1085 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00001086 for(i = 0;i < count; i++) {
1087 base = tswapl(target_vec[i].iov_base);
1088 unlock_user(vec[i].iov_base, base, copy ? vec[i].iov_len : 0);
1089 }
1090 unlock_user (target_vec, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00001091
1092 return 0;
pbrook53a59602006-03-25 19:31:22 +00001093}
1094
ths0da46a62007-10-20 20:23:07 +00001095/* do_socket() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001096static abi_long do_socket(int domain, int type, int protocol)
bellard3532fa72006-06-24 15:06:03 +00001097{
1098#if defined(TARGET_MIPS)
1099 switch(type) {
1100 case TARGET_SOCK_DGRAM:
1101 type = SOCK_DGRAM;
1102 break;
1103 case TARGET_SOCK_STREAM:
1104 type = SOCK_STREAM;
1105 break;
1106 case TARGET_SOCK_RAW:
1107 type = SOCK_RAW;
1108 break;
1109 case TARGET_SOCK_RDM:
1110 type = SOCK_RDM;
1111 break;
1112 case TARGET_SOCK_SEQPACKET:
1113 type = SOCK_SEQPACKET;
1114 break;
1115 case TARGET_SOCK_PACKET:
1116 type = SOCK_PACKET;
1117 break;
1118 }
1119#endif
balrog12bc92a2007-10-30 21:06:14 +00001120 if (domain == PF_NETLINK)
1121 return -EAFNOSUPPORT; /* do not NETLINK socket connections possible */
bellard3532fa72006-06-24 15:06:03 +00001122 return get_errno(socket(domain, type, protocol));
1123}
1124
ths0da46a62007-10-20 20:23:07 +00001125/* do_bind() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001126static abi_long do_bind(int sockfd, abi_ulong target_addr,
1127 socklen_t addrlen)
bellard3532fa72006-06-24 15:06:03 +00001128{
1129 void *addr = alloca(addrlen);
ths3b46e622007-09-17 08:09:54 +00001130
bellard3532fa72006-06-24 15:06:03 +00001131 target_to_host_sockaddr(addr, target_addr, addrlen);
1132 return get_errno(bind(sockfd, addr, addrlen));
1133}
1134
ths0da46a62007-10-20 20:23:07 +00001135/* do_connect() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001136static abi_long do_connect(int sockfd, abi_ulong target_addr,
1137 socklen_t addrlen)
bellard3532fa72006-06-24 15:06:03 +00001138{
1139 void *addr = alloca(addrlen);
ths3b46e622007-09-17 08:09:54 +00001140
bellard3532fa72006-06-24 15:06:03 +00001141 target_to_host_sockaddr(addr, target_addr, addrlen);
1142 return get_errno(connect(sockfd, addr, addrlen));
1143}
1144
ths0da46a62007-10-20 20:23:07 +00001145/* do_sendrecvmsg() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001146static abi_long do_sendrecvmsg(int fd, abi_ulong target_msg,
1147 int flags, int send)
bellard3532fa72006-06-24 15:06:03 +00001148{
blueswir1992f48a2007-10-14 16:27:31 +00001149 abi_long ret;
bellard3532fa72006-06-24 15:06:03 +00001150 struct target_msghdr *msgp;
1151 struct msghdr msg;
1152 int count;
1153 struct iovec *vec;
blueswir1992f48a2007-10-14 16:27:31 +00001154 abi_ulong target_vec;
bellard3532fa72006-06-24 15:06:03 +00001155
bellard579a97f2007-11-11 14:26:47 +00001156 /* FIXME */
1157 if (!lock_user_struct(send ? VERIFY_READ : VERIFY_WRITE,
1158 msgp,
1159 target_msg,
1160 send ? 1 : 0))
1161 return -TARGET_EFAULT;
bellard3532fa72006-06-24 15:06:03 +00001162 if (msgp->msg_name) {
1163 msg.msg_namelen = tswap32(msgp->msg_namelen);
1164 msg.msg_name = alloca(msg.msg_namelen);
1165 target_to_host_sockaddr(msg.msg_name, tswapl(msgp->msg_name),
1166 msg.msg_namelen);
1167 } else {
1168 msg.msg_name = NULL;
1169 msg.msg_namelen = 0;
1170 }
1171 msg.msg_controllen = 2 * tswapl(msgp->msg_controllen);
1172 msg.msg_control = alloca(msg.msg_controllen);
1173 msg.msg_flags = tswap32(msgp->msg_flags);
ths3b46e622007-09-17 08:09:54 +00001174
bellard3532fa72006-06-24 15:06:03 +00001175 count = tswapl(msgp->msg_iovlen);
1176 vec = alloca(count * sizeof(struct iovec));
1177 target_vec = tswapl(msgp->msg_iov);
bellard579a97f2007-11-11 14:26:47 +00001178 lock_iovec(send ? VERIFY_READ : VERIFY_WRITE, vec, target_vec, count, send);
bellard3532fa72006-06-24 15:06:03 +00001179 msg.msg_iovlen = count;
1180 msg.msg_iov = vec;
ths3b46e622007-09-17 08:09:54 +00001181
bellard3532fa72006-06-24 15:06:03 +00001182 if (send) {
bellard5a4a8982007-11-11 17:39:18 +00001183 ret = target_to_host_cmsg(&msg, msgp);
1184 if (ret == 0)
1185 ret = get_errno(sendmsg(fd, &msg, flags));
bellard3532fa72006-06-24 15:06:03 +00001186 } else {
1187 ret = get_errno(recvmsg(fd, &msg, flags));
1188 if (!is_error(ret))
bellard5a4a8982007-11-11 17:39:18 +00001189 ret = host_to_target_cmsg(msgp, &msg);
bellard3532fa72006-06-24 15:06:03 +00001190 }
1191 unlock_iovec(vec, target_vec, count, !send);
bellard579a97f2007-11-11 14:26:47 +00001192 unlock_user_struct(msgp, target_msg, send ? 0 : 1);
bellard3532fa72006-06-24 15:06:03 +00001193 return ret;
1194}
1195
ths0da46a62007-10-20 20:23:07 +00001196/* do_accept() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001197static abi_long do_accept(int fd, abi_ulong target_addr,
bellard2f619692007-11-16 10:46:05 +00001198 abi_ulong target_addrlen_addr)
pbrook1be9e1d2006-11-19 15:26:04 +00001199{
bellard2f619692007-11-16 10:46:05 +00001200 socklen_t addrlen;
1201 void *addr;
blueswir1992f48a2007-10-14 16:27:31 +00001202 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00001203
bellard2f619692007-11-16 10:46:05 +00001204 if (get_user_u32(addrlen, target_addrlen_addr))
1205 return -TARGET_EFAULT;
1206
1207 addr = alloca(addrlen);
1208
pbrook1be9e1d2006-11-19 15:26:04 +00001209 ret = get_errno(accept(fd, addr, &addrlen));
1210 if (!is_error(ret)) {
1211 host_to_target_sockaddr(target_addr, addr, addrlen);
bellard2f619692007-11-16 10:46:05 +00001212 if (put_user_u32(addrlen, target_addrlen_addr))
1213 ret = -TARGET_EFAULT;
pbrook1be9e1d2006-11-19 15:26:04 +00001214 }
1215 return ret;
1216}
1217
ths0da46a62007-10-20 20:23:07 +00001218/* do_getpeername() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001219static abi_long do_getpeername(int fd, abi_ulong target_addr,
bellard2f619692007-11-16 10:46:05 +00001220 abi_ulong target_addrlen_addr)
pbrook1be9e1d2006-11-19 15:26:04 +00001221{
bellard2f619692007-11-16 10:46:05 +00001222 socklen_t addrlen;
1223 void *addr;
blueswir1992f48a2007-10-14 16:27:31 +00001224 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00001225
bellard2f619692007-11-16 10:46:05 +00001226 if (get_user_u32(addrlen, target_addrlen_addr))
1227 return -TARGET_EFAULT;
1228
1229 addr = alloca(addrlen);
1230
pbrook1be9e1d2006-11-19 15:26:04 +00001231 ret = get_errno(getpeername(fd, addr, &addrlen));
1232 if (!is_error(ret)) {
1233 host_to_target_sockaddr(target_addr, addr, addrlen);
bellard2f619692007-11-16 10:46:05 +00001234 if (put_user_u32(addrlen, target_addrlen_addr))
1235 ret = -TARGET_EFAULT;
pbrook1be9e1d2006-11-19 15:26:04 +00001236 }
1237 return ret;
1238}
1239
ths0da46a62007-10-20 20:23:07 +00001240/* do_getsockname() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001241static abi_long do_getsockname(int fd, abi_ulong target_addr,
bellard2f619692007-11-16 10:46:05 +00001242 abi_ulong target_addrlen_addr)
pbrook1be9e1d2006-11-19 15:26:04 +00001243{
bellard2f619692007-11-16 10:46:05 +00001244 socklen_t addrlen;
1245 void *addr;
blueswir1992f48a2007-10-14 16:27:31 +00001246 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00001247
bellard2f619692007-11-16 10:46:05 +00001248 if (get_user_u32(addrlen, target_addrlen_addr))
1249 return -TARGET_EFAULT;
1250
1251 addr = alloca(addrlen);
1252
pbrook1be9e1d2006-11-19 15:26:04 +00001253 ret = get_errno(getsockname(fd, addr, &addrlen));
1254 if (!is_error(ret)) {
1255 host_to_target_sockaddr(target_addr, addr, addrlen);
bellard2f619692007-11-16 10:46:05 +00001256 if (put_user_u32(addrlen, target_addrlen_addr))
1257 ret = -TARGET_EFAULT;
pbrook1be9e1d2006-11-19 15:26:04 +00001258 }
1259 return ret;
1260}
1261
ths0da46a62007-10-20 20:23:07 +00001262/* do_socketpair() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001263static abi_long do_socketpair(int domain, int type, int protocol,
bellard2f619692007-11-16 10:46:05 +00001264 abi_ulong target_tab_addr)
pbrook1be9e1d2006-11-19 15:26:04 +00001265{
1266 int tab[2];
blueswir1992f48a2007-10-14 16:27:31 +00001267 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00001268
1269 ret = get_errno(socketpair(domain, type, protocol, tab));
1270 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +00001271 if (put_user_s32(tab[0], target_tab_addr)
1272 || put_user_s32(tab[1], target_tab_addr + sizeof(tab[0])))
1273 ret = -TARGET_EFAULT;
pbrook1be9e1d2006-11-19 15:26:04 +00001274 }
1275 return ret;
1276}
1277
ths0da46a62007-10-20 20:23:07 +00001278/* do_sendto() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001279static abi_long do_sendto(int fd, abi_ulong msg, size_t len, int flags,
1280 abi_ulong target_addr, socklen_t addrlen)
pbrook1be9e1d2006-11-19 15:26:04 +00001281{
1282 void *addr;
1283 void *host_msg;
blueswir1992f48a2007-10-14 16:27:31 +00001284 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00001285
bellard579a97f2007-11-11 14:26:47 +00001286 host_msg = lock_user(VERIFY_READ, msg, len, 1);
1287 if (!host_msg)
1288 return -TARGET_EFAULT;
pbrook1be9e1d2006-11-19 15:26:04 +00001289 if (target_addr) {
1290 addr = alloca(addrlen);
1291 target_to_host_sockaddr(addr, target_addr, addrlen);
1292 ret = get_errno(sendto(fd, host_msg, len, flags, addr, addrlen));
1293 } else {
1294 ret = get_errno(send(fd, host_msg, len, flags));
1295 }
1296 unlock_user(host_msg, msg, 0);
1297 return ret;
1298}
1299
ths0da46a62007-10-20 20:23:07 +00001300/* do_recvfrom() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001301static abi_long do_recvfrom(int fd, abi_ulong msg, size_t len, int flags,
1302 abi_ulong target_addr,
1303 abi_ulong target_addrlen)
pbrook1be9e1d2006-11-19 15:26:04 +00001304{
1305 socklen_t addrlen;
1306 void *addr;
1307 void *host_msg;
blueswir1992f48a2007-10-14 16:27:31 +00001308 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00001309
bellard579a97f2007-11-11 14:26:47 +00001310 host_msg = lock_user(VERIFY_WRITE, msg, len, 0);
1311 if (!host_msg)
1312 return -TARGET_EFAULT;
pbrook1be9e1d2006-11-19 15:26:04 +00001313 if (target_addr) {
bellard2f619692007-11-16 10:46:05 +00001314 if (get_user_u32(addrlen, target_addrlen)) {
1315 ret = -TARGET_EFAULT;
1316 goto fail;
1317 }
pbrook1be9e1d2006-11-19 15:26:04 +00001318 addr = alloca(addrlen);
1319 ret = get_errno(recvfrom(fd, host_msg, len, flags, addr, &addrlen));
1320 } else {
1321 addr = NULL; /* To keep compiler quiet. */
1322 ret = get_errno(recv(fd, host_msg, len, flags));
1323 }
1324 if (!is_error(ret)) {
1325 if (target_addr) {
1326 host_to_target_sockaddr(target_addr, addr, addrlen);
bellard2f619692007-11-16 10:46:05 +00001327 if (put_user_u32(addrlen, target_addrlen)) {
1328 ret = -TARGET_EFAULT;
1329 goto fail;
1330 }
pbrook1be9e1d2006-11-19 15:26:04 +00001331 }
1332 unlock_user(host_msg, msg, len);
1333 } else {
bellard2f619692007-11-16 10:46:05 +00001334fail:
pbrook1be9e1d2006-11-19 15:26:04 +00001335 unlock_user(host_msg, msg, 0);
1336 }
1337 return ret;
1338}
1339
j_mayer32407102007-09-26 23:01:49 +00001340#ifdef TARGET_NR_socketcall
ths0da46a62007-10-20 20:23:07 +00001341/* do_socketcall() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001342static abi_long do_socketcall(int num, abi_ulong vptr)
bellard31e31b82003-02-18 22:55:36 +00001343{
blueswir1992f48a2007-10-14 16:27:31 +00001344 abi_long ret;
1345 const int n = sizeof(abi_ulong);
bellard31e31b82003-02-18 22:55:36 +00001346
1347 switch(num) {
1348 case SOCKOP_socket:
bellard7854b052003-03-29 17:22:23 +00001349 {
bellard2f619692007-11-16 10:46:05 +00001350 int domain, type, protocol;
1351
1352 if (get_user_s32(domain, vptr)
1353 || get_user_s32(type, vptr + n)
1354 || get_user_s32(protocol, vptr + 2 * n))
1355 return -TARGET_EFAULT;
1356
bellard3532fa72006-06-24 15:06:03 +00001357 ret = do_socket(domain, type, protocol);
bellard7854b052003-03-29 17:22:23 +00001358 }
bellard31e31b82003-02-18 22:55:36 +00001359 break;
1360 case SOCKOP_bind:
bellard7854b052003-03-29 17:22:23 +00001361 {
bellard2f619692007-11-16 10:46:05 +00001362 int sockfd;
1363 abi_ulong target_addr;
1364 socklen_t addrlen;
1365
1366 if (get_user_s32(sockfd, vptr)
1367 || get_user_ual(target_addr, vptr + n)
1368 || get_user_u32(addrlen, vptr + 2 * n))
1369 return -TARGET_EFAULT;
1370
bellard3532fa72006-06-24 15:06:03 +00001371 ret = do_bind(sockfd, target_addr, addrlen);
bellard7854b052003-03-29 17:22:23 +00001372 }
bellard31e31b82003-02-18 22:55:36 +00001373 break;
1374 case SOCKOP_connect:
bellard7854b052003-03-29 17:22:23 +00001375 {
bellard2f619692007-11-16 10:46:05 +00001376 int sockfd;
1377 abi_ulong target_addr;
1378 socklen_t addrlen;
1379
1380 if (get_user_s32(sockfd, vptr)
1381 || get_user_ual(target_addr, vptr + n)
1382 || get_user_u32(addrlen, vptr + 2 * n))
1383 return -TARGET_EFAULT;
1384
bellard3532fa72006-06-24 15:06:03 +00001385 ret = do_connect(sockfd, target_addr, addrlen);
bellard7854b052003-03-29 17:22:23 +00001386 }
bellard31e31b82003-02-18 22:55:36 +00001387 break;
1388 case SOCKOP_listen:
bellard7854b052003-03-29 17:22:23 +00001389 {
bellard2f619692007-11-16 10:46:05 +00001390 int sockfd, backlog;
1391
1392 if (get_user_s32(sockfd, vptr)
1393 || get_user_s32(backlog, vptr + n))
1394 return -TARGET_EFAULT;
1395
bellard7854b052003-03-29 17:22:23 +00001396 ret = get_errno(listen(sockfd, backlog));
1397 }
bellard31e31b82003-02-18 22:55:36 +00001398 break;
1399 case SOCKOP_accept:
1400 {
bellard2f619692007-11-16 10:46:05 +00001401 int sockfd;
1402 abi_ulong target_addr, target_addrlen;
1403
1404 if (get_user_s32(sockfd, vptr)
1405 || get_user_ual(target_addr, vptr + n)
1406 || get_user_u32(target_addrlen, vptr + 2 * n))
1407 return -TARGET_EFAULT;
1408
pbrook1be9e1d2006-11-19 15:26:04 +00001409 ret = do_accept(sockfd, target_addr, target_addrlen);
bellard31e31b82003-02-18 22:55:36 +00001410 }
1411 break;
1412 case SOCKOP_getsockname:
1413 {
bellard2f619692007-11-16 10:46:05 +00001414 int sockfd;
1415 abi_ulong target_addr, target_addrlen;
1416
1417 if (get_user_s32(sockfd, vptr)
1418 || get_user_ual(target_addr, vptr + n)
1419 || get_user_u32(target_addrlen, vptr + 2 * n))
1420 return -TARGET_EFAULT;
1421
pbrook1be9e1d2006-11-19 15:26:04 +00001422 ret = do_getsockname(sockfd, target_addr, target_addrlen);
bellard31e31b82003-02-18 22:55:36 +00001423 }
1424 break;
1425 case SOCKOP_getpeername:
1426 {
bellard2f619692007-11-16 10:46:05 +00001427 int sockfd;
1428 abi_ulong target_addr, target_addrlen;
1429
1430 if (get_user_s32(sockfd, vptr)
1431 || get_user_ual(target_addr, vptr + n)
1432 || get_user_u32(target_addrlen, vptr + 2 * n))
1433 return -TARGET_EFAULT;
1434
pbrook1be9e1d2006-11-19 15:26:04 +00001435 ret = do_getpeername(sockfd, target_addr, target_addrlen);
bellard31e31b82003-02-18 22:55:36 +00001436 }
1437 break;
1438 case SOCKOP_socketpair:
1439 {
bellard2f619692007-11-16 10:46:05 +00001440 int domain, type, protocol;
1441 abi_ulong tab;
1442
1443 if (get_user_s32(domain, vptr)
1444 || get_user_s32(type, vptr + n)
1445 || get_user_s32(protocol, vptr + 2 * n)
1446 || get_user_ual(tab, vptr + 3 * n))
1447 return -TARGET_EFAULT;
1448
pbrook1be9e1d2006-11-19 15:26:04 +00001449 ret = do_socketpair(domain, type, protocol, tab);
bellard31e31b82003-02-18 22:55:36 +00001450 }
1451 break;
1452 case SOCKOP_send:
bellard7854b052003-03-29 17:22:23 +00001453 {
bellard2f619692007-11-16 10:46:05 +00001454 int sockfd;
1455 abi_ulong msg;
1456 size_t len;
1457 int flags;
1458
1459 if (get_user_s32(sockfd, vptr)
1460 || get_user_ual(msg, vptr + n)
1461 || get_user_ual(len, vptr + 2 * n)
1462 || get_user_s32(flags, vptr + 3 * n))
1463 return -TARGET_EFAULT;
1464
pbrook1be9e1d2006-11-19 15:26:04 +00001465 ret = do_sendto(sockfd, msg, len, flags, 0, 0);
bellard7854b052003-03-29 17:22:23 +00001466 }
bellard31e31b82003-02-18 22:55:36 +00001467 break;
1468 case SOCKOP_recv:
bellard7854b052003-03-29 17:22:23 +00001469 {
bellard2f619692007-11-16 10:46:05 +00001470 int sockfd;
1471 abi_ulong msg;
1472 size_t len;
1473 int flags;
1474
1475 if (get_user_s32(sockfd, vptr)
1476 || get_user_ual(msg, vptr + n)
1477 || get_user_ual(len, vptr + 2 * n)
1478 || get_user_s32(flags, vptr + 3 * n))
1479 return -TARGET_EFAULT;
1480
pbrook1be9e1d2006-11-19 15:26:04 +00001481 ret = do_recvfrom(sockfd, msg, len, flags, 0, 0);
bellard7854b052003-03-29 17:22:23 +00001482 }
bellard31e31b82003-02-18 22:55:36 +00001483 break;
1484 case SOCKOP_sendto:
bellard7854b052003-03-29 17:22:23 +00001485 {
bellard2f619692007-11-16 10:46:05 +00001486 int sockfd;
1487 abi_ulong msg;
1488 size_t len;
1489 int flags;
1490 abi_ulong addr;
1491 socklen_t addrlen;
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 || get_user_ual(addr, vptr + 4 * n)
1498 || get_user_u32(addrlen, vptr + 5 * n))
1499 return -TARGET_EFAULT;
1500
pbrook1be9e1d2006-11-19 15:26:04 +00001501 ret = do_sendto(sockfd, msg, len, flags, addr, addrlen);
bellard7854b052003-03-29 17:22:23 +00001502 }
bellard31e31b82003-02-18 22:55:36 +00001503 break;
1504 case SOCKOP_recvfrom:
1505 {
bellard2f619692007-11-16 10:46:05 +00001506 int sockfd;
1507 abi_ulong msg;
1508 size_t len;
1509 int flags;
1510 abi_ulong addr;
1511 socklen_t addrlen;
1512
1513 if (get_user_s32(sockfd, vptr)
1514 || get_user_ual(msg, vptr + n)
1515 || get_user_ual(len, vptr + 2 * n)
1516 || get_user_s32(flags, vptr + 3 * n)
1517 || get_user_ual(addr, vptr + 4 * n)
1518 || get_user_u32(addrlen, vptr + 5 * n))
1519 return -TARGET_EFAULT;
1520
pbrook1be9e1d2006-11-19 15:26:04 +00001521 ret = do_recvfrom(sockfd, msg, len, flags, addr, addrlen);
bellard31e31b82003-02-18 22:55:36 +00001522 }
1523 break;
1524 case SOCKOP_shutdown:
bellard7854b052003-03-29 17:22:23 +00001525 {
bellard2f619692007-11-16 10:46:05 +00001526 int sockfd, how;
1527
1528 if (get_user_s32(sockfd, vptr)
1529 || get_user_s32(how, vptr + n))
1530 return -TARGET_EFAULT;
bellard7854b052003-03-29 17:22:23 +00001531
1532 ret = get_errno(shutdown(sockfd, how));
1533 }
bellard31e31b82003-02-18 22:55:36 +00001534 break;
1535 case SOCKOP_sendmsg:
1536 case SOCKOP_recvmsg:
bellard1a9353d2003-03-16 20:28:50 +00001537 {
1538 int fd;
blueswir1992f48a2007-10-14 16:27:31 +00001539 abi_ulong target_msg;
bellard3532fa72006-06-24 15:06:03 +00001540 int flags;
bellard1a9353d2003-03-16 20:28:50 +00001541
bellard2f619692007-11-16 10:46:05 +00001542 if (get_user_s32(fd, vptr)
1543 || get_user_ual(target_msg, vptr + n)
1544 || get_user_s32(flags, vptr + 2 * n))
1545 return -TARGET_EFAULT;
bellard3532fa72006-06-24 15:06:03 +00001546
ths5fafdf22007-09-16 21:08:06 +00001547 ret = do_sendrecvmsg(fd, target_msg, flags,
bellard3532fa72006-06-24 15:06:03 +00001548 (num == SOCKOP_sendmsg));
bellard1a9353d2003-03-16 20:28:50 +00001549 }
1550 break;
bellard31e31b82003-02-18 22:55:36 +00001551 case SOCKOP_setsockopt:
bellard7854b052003-03-29 17:22:23 +00001552 {
bellard2f619692007-11-16 10:46:05 +00001553 int sockfd;
1554 int level;
1555 int optname;
1556 abi_ulong optval;
1557 socklen_t optlen;
1558
1559 if (get_user_s32(sockfd, vptr)
1560 || get_user_s32(level, vptr + n)
1561 || get_user_s32(optname, vptr + 2 * n)
1562 || get_user_ual(optval, vptr + 3 * n)
1563 || get_user_u32(optlen, vptr + 4 * n))
1564 return -TARGET_EFAULT;
bellard7854b052003-03-29 17:22:23 +00001565
1566 ret = do_setsockopt(sockfd, level, optname, optval, optlen);
1567 }
1568 break;
bellard31e31b82003-02-18 22:55:36 +00001569 case SOCKOP_getsockopt:
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;
bellard7854b052003-03-29 17:22:23 +00001576
bellard2f619692007-11-16 10:46:05 +00001577 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;
1583
1584 ret = do_getsockopt(sockfd, level, optname, optval, optlen);
bellard7854b052003-03-29 17:22:23 +00001585 }
1586 break;
bellard31e31b82003-02-18 22:55:36 +00001587 default:
1588 gemu_log("Unsupported socketcall: %d\n", num);
ths0da46a62007-10-20 20:23:07 +00001589 ret = -TARGET_ENOSYS;
bellard31e31b82003-02-18 22:55:36 +00001590 break;
1591 }
1592 return ret;
1593}
j_mayer32407102007-09-26 23:01:49 +00001594#endif
bellard31e31b82003-02-18 22:55:36 +00001595
j_mayer32407102007-09-26 23:01:49 +00001596#ifdef TARGET_NR_ipc
bellard8853f862004-02-22 14:57:26 +00001597#define N_SHM_REGIONS 32
1598
1599static struct shm_region {
bellard5a4a8982007-11-11 17:39:18 +00001600 abi_ulong start;
1601 abi_ulong size;
bellard8853f862004-02-22 14:57:26 +00001602} shm_regions[N_SHM_REGIONS];
1603
ths3eb6b042007-06-03 14:26:27 +00001604struct target_ipc_perm
1605{
blueswir1992f48a2007-10-14 16:27:31 +00001606 abi_long __key;
1607 abi_ulong uid;
1608 abi_ulong gid;
1609 abi_ulong cuid;
1610 abi_ulong cgid;
ths3eb6b042007-06-03 14:26:27 +00001611 unsigned short int mode;
1612 unsigned short int __pad1;
1613 unsigned short int __seq;
1614 unsigned short int __pad2;
blueswir1992f48a2007-10-14 16:27:31 +00001615 abi_ulong __unused1;
1616 abi_ulong __unused2;
ths3eb6b042007-06-03 14:26:27 +00001617};
1618
1619struct target_semid_ds
1620{
1621 struct target_ipc_perm sem_perm;
blueswir1992f48a2007-10-14 16:27:31 +00001622 abi_ulong sem_otime;
1623 abi_ulong __unused1;
1624 abi_ulong sem_ctime;
1625 abi_ulong __unused2;
1626 abi_ulong sem_nsems;
1627 abi_ulong __unused3;
1628 abi_ulong __unused4;
ths3eb6b042007-06-03 14:26:27 +00001629};
1630
bellard579a97f2007-11-11 14:26:47 +00001631static inline abi_long target_to_host_ipc_perm(struct ipc_perm *host_ip,
1632 abi_ulong target_addr)
ths3eb6b042007-06-03 14:26:27 +00001633{
1634 struct target_ipc_perm *target_ip;
1635 struct target_semid_ds *target_sd;
1636
bellard579a97f2007-11-11 14:26:47 +00001637 if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
1638 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00001639 target_ip=&(target_sd->sem_perm);
1640 host_ip->__key = tswapl(target_ip->__key);
1641 host_ip->uid = tswapl(target_ip->uid);
1642 host_ip->gid = tswapl(target_ip->gid);
1643 host_ip->cuid = tswapl(target_ip->cuid);
1644 host_ip->cgid = tswapl(target_ip->cgid);
1645 host_ip->mode = tswapl(target_ip->mode);
1646 unlock_user_struct(target_sd, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00001647 return 0;
ths3eb6b042007-06-03 14:26:27 +00001648}
1649
bellard579a97f2007-11-11 14:26:47 +00001650static inline abi_long host_to_target_ipc_perm(abi_ulong target_addr,
1651 struct ipc_perm *host_ip)
ths3eb6b042007-06-03 14:26:27 +00001652{
1653 struct target_ipc_perm *target_ip;
1654 struct target_semid_ds *target_sd;
1655
bellard579a97f2007-11-11 14:26:47 +00001656 if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
1657 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00001658 target_ip = &(target_sd->sem_perm);
1659 target_ip->__key = tswapl(host_ip->__key);
1660 target_ip->uid = tswapl(host_ip->uid);
1661 target_ip->gid = tswapl(host_ip->gid);
1662 target_ip->cuid = tswapl(host_ip->cuid);
1663 target_ip->cgid = tswapl(host_ip->cgid);
1664 target_ip->mode = tswapl(host_ip->mode);
1665 unlock_user_struct(target_sd, target_addr, 1);
bellard579a97f2007-11-11 14:26:47 +00001666 return 0;
ths3eb6b042007-06-03 14:26:27 +00001667}
1668
bellard579a97f2007-11-11 14:26:47 +00001669static inline abi_long target_to_host_semid_ds(struct semid_ds *host_sd,
1670 abi_ulong target_addr)
ths3eb6b042007-06-03 14:26:27 +00001671{
1672 struct target_semid_ds *target_sd;
1673
bellard579a97f2007-11-11 14:26:47 +00001674 if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
1675 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00001676 target_to_host_ipc_perm(&(host_sd->sem_perm),target_addr);
1677 host_sd->sem_nsems = tswapl(target_sd->sem_nsems);
1678 host_sd->sem_otime = tswapl(target_sd->sem_otime);
1679 host_sd->sem_ctime = tswapl(target_sd->sem_ctime);
1680 unlock_user_struct(target_sd, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00001681 return 0;
ths3eb6b042007-06-03 14:26:27 +00001682}
1683
bellard579a97f2007-11-11 14:26:47 +00001684static inline abi_long host_to_target_semid_ds(abi_ulong target_addr,
1685 struct semid_ds *host_sd)
ths3eb6b042007-06-03 14:26:27 +00001686{
1687 struct target_semid_ds *target_sd;
1688
bellard579a97f2007-11-11 14:26:47 +00001689 if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
1690 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00001691 host_to_target_ipc_perm(target_addr,&(host_sd->sem_perm));
1692 target_sd->sem_nsems = tswapl(host_sd->sem_nsems);
1693 target_sd->sem_otime = tswapl(host_sd->sem_otime);
1694 target_sd->sem_ctime = tswapl(host_sd->sem_ctime);
1695 unlock_user_struct(target_sd, target_addr, 1);
bellard579a97f2007-11-11 14:26:47 +00001696 return 0;
ths3eb6b042007-06-03 14:26:27 +00001697}
1698
thsfa294812007-02-02 22:05:00 +00001699union semun {
1700 int val;
ths3eb6b042007-06-03 14:26:27 +00001701 struct semid_ds *buf;
thsfa294812007-02-02 22:05:00 +00001702 unsigned short *array;
1703};
1704
ths3eb6b042007-06-03 14:26:27 +00001705union target_semun {
1706 int val;
blueswir1992f48a2007-10-14 16:27:31 +00001707 abi_long buf;
ths3eb6b042007-06-03 14:26:27 +00001708 unsigned short int *array;
1709};
1710
bellard579a97f2007-11-11 14:26:47 +00001711static inline abi_long target_to_host_semun(int cmd,
1712 union semun *host_su,
1713 abi_ulong target_addr,
1714 struct semid_ds *ds)
ths3eb6b042007-06-03 14:26:27 +00001715{
1716 union target_semun *target_su;
1717
1718 switch( cmd ) {
1719 case IPC_STAT:
1720 case IPC_SET:
bellard579a97f2007-11-11 14:26:47 +00001721 if (!lock_user_struct(VERIFY_READ, target_su, target_addr, 1))
1722 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00001723 target_to_host_semid_ds(ds,target_su->buf);
1724 host_su->buf = ds;
1725 unlock_user_struct(target_su, target_addr, 0);
1726 break;
1727 case GETVAL:
1728 case SETVAL:
bellard579a97f2007-11-11 14:26:47 +00001729 if (!lock_user_struct(VERIFY_READ, target_su, target_addr, 1))
1730 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00001731 host_su->val = tswapl(target_su->val);
1732 unlock_user_struct(target_su, target_addr, 0);
1733 break;
1734 case GETALL:
1735 case SETALL:
bellard579a97f2007-11-11 14:26:47 +00001736 if (!lock_user_struct(VERIFY_READ, target_su, target_addr, 1))
1737 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00001738 *host_su->array = tswap16(*target_su->array);
1739 unlock_user_struct(target_su, target_addr, 0);
1740 break;
1741 default:
1742 gemu_log("semun operation not fully supported: %d\n", (int)cmd);
1743 }
bellard579a97f2007-11-11 14:26:47 +00001744 return 0;
ths3eb6b042007-06-03 14:26:27 +00001745}
1746
bellard579a97f2007-11-11 14:26:47 +00001747static inline abi_long host_to_target_semun(int cmd,
1748 abi_ulong target_addr,
1749 union semun *host_su,
1750 struct semid_ds *ds)
ths3eb6b042007-06-03 14:26:27 +00001751{
1752 union target_semun *target_su;
1753
1754 switch( cmd ) {
1755 case IPC_STAT:
1756 case IPC_SET:
bellard579a97f2007-11-11 14:26:47 +00001757 if (lock_user_struct(VERIFY_WRITE, target_su, target_addr, 0))
1758 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00001759 host_to_target_semid_ds(target_su->buf,ds);
1760 unlock_user_struct(target_su, target_addr, 1);
1761 break;
1762 case GETVAL:
1763 case SETVAL:
bellard579a97f2007-11-11 14:26:47 +00001764 if (lock_user_struct(VERIFY_WRITE, target_su, target_addr, 0))
1765 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00001766 target_su->val = tswapl(host_su->val);
1767 unlock_user_struct(target_su, target_addr, 1);
1768 break;
1769 case GETALL:
1770 case SETALL:
bellard579a97f2007-11-11 14:26:47 +00001771 if (lock_user_struct(VERIFY_WRITE, target_su, target_addr, 0))
1772 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00001773 *target_su->array = tswap16(*host_su->array);
1774 unlock_user_struct(target_su, target_addr, 1);
1775 break;
1776 default:
1777 gemu_log("semun operation not fully supported: %d\n", (int)cmd);
1778 }
bellard579a97f2007-11-11 14:26:47 +00001779 return 0;
ths3eb6b042007-06-03 14:26:27 +00001780}
1781
blueswir1992f48a2007-10-14 16:27:31 +00001782static inline abi_long do_semctl(int first, int second, int third,
1783 abi_long ptr)
ths3eb6b042007-06-03 14:26:27 +00001784{
1785 union semun arg;
1786 struct semid_ds dsarg;
1787 int cmd = third&0xff;
blueswir1992f48a2007-10-14 16:27:31 +00001788 abi_long ret = 0;
ths3eb6b042007-06-03 14:26:27 +00001789
1790 switch( cmd ) {
1791 case GETVAL:
1792 target_to_host_semun(cmd,&arg,ptr,&dsarg);
1793 ret = get_errno(semctl(first, second, cmd, arg));
1794 host_to_target_semun(cmd,ptr,&arg,&dsarg);
1795 break;
1796 case SETVAL:
1797 target_to_host_semun(cmd,&arg,ptr,&dsarg);
1798 ret = get_errno(semctl(first, second, cmd, arg));
1799 host_to_target_semun(cmd,ptr,&arg,&dsarg);
1800 break;
1801 case GETALL:
1802 target_to_host_semun(cmd,&arg,ptr,&dsarg);
1803 ret = get_errno(semctl(first, second, cmd, arg));
1804 host_to_target_semun(cmd,ptr,&arg,&dsarg);
1805 break;
1806 case SETALL:
1807 target_to_host_semun(cmd,&arg,ptr,&dsarg);
1808 ret = get_errno(semctl(first, second, cmd, arg));
1809 host_to_target_semun(cmd,ptr,&arg,&dsarg);
1810 break;
1811 case IPC_STAT:
1812 target_to_host_semun(cmd,&arg,ptr,&dsarg);
1813 ret = get_errno(semctl(first, second, cmd, arg));
1814 host_to_target_semun(cmd,ptr,&arg,&dsarg);
1815 break;
1816 case IPC_SET:
1817 target_to_host_semun(cmd,&arg,ptr,&dsarg);
1818 ret = get_errno(semctl(first, second, cmd, arg));
1819 host_to_target_semun(cmd,ptr,&arg,&dsarg);
1820 break;
1821 default:
1822 ret = get_errno(semctl(first, second, cmd, arg));
1823 }
1824
1825 return ret;
1826}
1827
ths1bc012f2007-06-03 14:27:49 +00001828struct target_msqid_ds
1829{
1830 struct target_ipc_perm msg_perm;
blueswir1992f48a2007-10-14 16:27:31 +00001831 abi_ulong msg_stime;
1832 abi_ulong __unused1;
1833 abi_ulong msg_rtime;
1834 abi_ulong __unused2;
1835 abi_ulong msg_ctime;
1836 abi_ulong __unused3;
1837 abi_ulong __msg_cbytes;
1838 abi_ulong msg_qnum;
1839 abi_ulong msg_qbytes;
1840 abi_ulong msg_lspid;
1841 abi_ulong msg_lrpid;
1842 abi_ulong __unused4;
1843 abi_ulong __unused5;
ths1bc012f2007-06-03 14:27:49 +00001844};
1845
bellard579a97f2007-11-11 14:26:47 +00001846static inline abi_long target_to_host_msqid_ds(struct msqid_ds *host_md,
1847 abi_ulong target_addr)
ths1bc012f2007-06-03 14:27:49 +00001848{
1849 struct target_msqid_ds *target_md;
1850
bellard579a97f2007-11-11 14:26:47 +00001851 if (!lock_user_struct(VERIFY_READ, target_md, target_addr, 1))
1852 return -TARGET_EFAULT;
ths1bc012f2007-06-03 14:27:49 +00001853 target_to_host_ipc_perm(&(host_md->msg_perm),target_addr);
1854 host_md->msg_stime = tswapl(target_md->msg_stime);
1855 host_md->msg_rtime = tswapl(target_md->msg_rtime);
1856 host_md->msg_ctime = tswapl(target_md->msg_ctime);
1857 host_md->__msg_cbytes = tswapl(target_md->__msg_cbytes);
1858 host_md->msg_qnum = tswapl(target_md->msg_qnum);
1859 host_md->msg_qbytes = tswapl(target_md->msg_qbytes);
1860 host_md->msg_lspid = tswapl(target_md->msg_lspid);
1861 host_md->msg_lrpid = tswapl(target_md->msg_lrpid);
1862 unlock_user_struct(target_md, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00001863 return 0;
ths1bc012f2007-06-03 14:27:49 +00001864}
1865
bellard579a97f2007-11-11 14:26:47 +00001866static inline abi_long host_to_target_msqid_ds(abi_ulong target_addr,
1867 struct msqid_ds *host_md)
ths1bc012f2007-06-03 14:27:49 +00001868{
1869 struct target_msqid_ds *target_md;
1870
bellard579a97f2007-11-11 14:26:47 +00001871 if (!lock_user_struct(VERIFY_WRITE, target_md, target_addr, 0))
1872 return -TARGET_EFAULT;
ths1bc012f2007-06-03 14:27:49 +00001873 host_to_target_ipc_perm(target_addr,&(host_md->msg_perm));
1874 target_md->msg_stime = tswapl(host_md->msg_stime);
1875 target_md->msg_rtime = tswapl(host_md->msg_rtime);
1876 target_md->msg_ctime = tswapl(host_md->msg_ctime);
1877 target_md->__msg_cbytes = tswapl(host_md->__msg_cbytes);
1878 target_md->msg_qnum = tswapl(host_md->msg_qnum);
1879 target_md->msg_qbytes = tswapl(host_md->msg_qbytes);
1880 target_md->msg_lspid = tswapl(host_md->msg_lspid);
1881 target_md->msg_lrpid = tswapl(host_md->msg_lrpid);
1882 unlock_user_struct(target_md, target_addr, 1);
bellard579a97f2007-11-11 14:26:47 +00001883 return 0;
ths1bc012f2007-06-03 14:27:49 +00001884}
1885
blueswir1992f48a2007-10-14 16:27:31 +00001886static inline abi_long do_msgctl(int first, int second, abi_long ptr)
ths1bc012f2007-06-03 14:27:49 +00001887{
1888 struct msqid_ds dsarg;
1889 int cmd = second&0xff;
blueswir1992f48a2007-10-14 16:27:31 +00001890 abi_long ret = 0;
ths1bc012f2007-06-03 14:27:49 +00001891 switch( cmd ) {
1892 case IPC_STAT:
1893 case IPC_SET:
1894 target_to_host_msqid_ds(&dsarg,ptr);
1895 ret = get_errno(msgctl(first, cmd, &dsarg));
1896 host_to_target_msqid_ds(ptr,&dsarg);
1897 default:
1898 ret = get_errno(msgctl(first, cmd, &dsarg));
1899 }
1900 return ret;
1901}
1902
1903struct target_msgbuf {
blueswir1992f48a2007-10-14 16:27:31 +00001904 abi_ulong mtype;
ths1bc012f2007-06-03 14:27:49 +00001905 char mtext[1];
1906};
1907
blueswir1992f48a2007-10-14 16:27:31 +00001908static inline abi_long do_msgsnd(int msqid, abi_long msgp,
1909 unsigned int msgsz, int msgflg)
ths1bc012f2007-06-03 14:27:49 +00001910{
1911 struct target_msgbuf *target_mb;
1912 struct msgbuf *host_mb;
blueswir1992f48a2007-10-14 16:27:31 +00001913 abi_long ret = 0;
ths1bc012f2007-06-03 14:27:49 +00001914
bellard579a97f2007-11-11 14:26:47 +00001915 if (!lock_user_struct(VERIFY_READ, target_mb, msgp, 0))
1916 return -TARGET_EFAULT;
ths1bc012f2007-06-03 14:27:49 +00001917 host_mb = malloc(msgsz+sizeof(long));
1918 host_mb->mtype = tswapl(target_mb->mtype);
1919 memcpy(host_mb->mtext,target_mb->mtext,msgsz);
1920 ret = get_errno(msgsnd(msqid, host_mb, msgsz, msgflg));
1921 free(host_mb);
1922 unlock_user_struct(target_mb, msgp, 0);
1923
1924 return ret;
1925}
1926
blueswir1992f48a2007-10-14 16:27:31 +00001927static inline abi_long do_msgrcv(int msqid, abi_long msgp,
1928 unsigned int msgsz, int msgtype,
1929 int msgflg)
ths1bc012f2007-06-03 14:27:49 +00001930{
1931 struct target_msgbuf *target_mb;
bellard579a97f2007-11-11 14:26:47 +00001932 char *target_mtext;
ths1bc012f2007-06-03 14:27:49 +00001933 struct msgbuf *host_mb;
blueswir1992f48a2007-10-14 16:27:31 +00001934 abi_long ret = 0;
ths1bc012f2007-06-03 14:27:49 +00001935
bellard579a97f2007-11-11 14:26:47 +00001936 if (!lock_user_struct(VERIFY_WRITE, target_mb, msgp, 0))
1937 return -TARGET_EFAULT;
ths1bc012f2007-06-03 14:27:49 +00001938 host_mb = malloc(msgsz+sizeof(long));
1939 ret = get_errno(msgrcv(msqid, host_mb, msgsz, 1, msgflg));
bellard579a97f2007-11-11 14:26:47 +00001940 if (ret > 0) {
1941 abi_ulong target_mtext_addr = msgp + sizeof(abi_ulong);
1942 target_mtext = lock_user(VERIFY_WRITE, target_mtext_addr, ret, 0);
1943 if (!target_mtext) {
1944 ret = -TARGET_EFAULT;
1945 goto end;
1946 }
ths1bc012f2007-06-03 14:27:49 +00001947 memcpy(target_mb->mtext, host_mb->mtext, ret);
bellard579a97f2007-11-11 14:26:47 +00001948 unlock_user(target_mtext, target_mtext_addr, ret);
1949 }
ths1bc012f2007-06-03 14:27:49 +00001950 target_mb->mtype = tswapl(host_mb->mtype);
1951 free(host_mb);
ths1bc012f2007-06-03 14:27:49 +00001952
bellard579a97f2007-11-11 14:26:47 +00001953end:
1954 if (target_mb)
1955 unlock_user_struct(target_mb, msgp, 1);
ths1bc012f2007-06-03 14:27:49 +00001956 return ret;
1957}
1958
pbrook53a59602006-03-25 19:31:22 +00001959/* ??? This only works with linear mappings. */
ths0da46a62007-10-20 20:23:07 +00001960/* do_ipc() must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001961static abi_long do_ipc(unsigned int call, int first,
1962 int second, int third,
1963 abi_long ptr, abi_long fifth)
bellard8853f862004-02-22 14:57:26 +00001964{
1965 int version;
blueswir1992f48a2007-10-14 16:27:31 +00001966 abi_long ret = 0;
bellard8853f862004-02-22 14:57:26 +00001967 struct shmid_ds shm_info;
1968 int i;
1969
1970 version = call >> 16;
1971 call &= 0xffff;
1972
1973 switch (call) {
thsfa294812007-02-02 22:05:00 +00001974 case IPCOP_semop:
bellard579a97f2007-11-11 14:26:47 +00001975 ret = get_errno(semop(first,(struct sembuf *)g2h(ptr), second));
thsfa294812007-02-02 22:05:00 +00001976 break;
1977
1978 case IPCOP_semget:
1979 ret = get_errno(semget(first, second, third));
1980 break;
1981
1982 case IPCOP_semctl:
ths3eb6b042007-06-03 14:26:27 +00001983 ret = do_semctl(first, second, third, ptr);
thsfa294812007-02-02 22:05:00 +00001984 break;
1985
1986 case IPCOP_semtimedop:
j_mayer32407102007-09-26 23:01:49 +00001987 gemu_log("Unsupported ipc call: %d (version %d)\n", call, version);
ths0da46a62007-10-20 20:23:07 +00001988 ret = -TARGET_ENOSYS;
thsfa294812007-02-02 22:05:00 +00001989 break;
thsd96372e2007-02-02 22:05:44 +00001990
1991 case IPCOP_msgget:
1992 ret = get_errno(msgget(first, second));
1993 break;
1994
1995 case IPCOP_msgsnd:
ths1bc012f2007-06-03 14:27:49 +00001996 ret = do_msgsnd(first, ptr, second, third);
thsd96372e2007-02-02 22:05:44 +00001997 break;
1998
1999 case IPCOP_msgctl:
ths1bc012f2007-06-03 14:27:49 +00002000 ret = do_msgctl(first, second, ptr);
thsd96372e2007-02-02 22:05:44 +00002001 break;
2002
2003 case IPCOP_msgrcv:
ths1bc012f2007-06-03 14:27:49 +00002004 {
bellard579a97f2007-11-11 14:26:47 +00002005 /* XXX: this code is not correct */
ths1bc012f2007-06-03 14:27:49 +00002006 struct ipc_kludge
2007 {
2008 void *__unbounded msgp;
2009 long int msgtyp;
2010 };
thsd96372e2007-02-02 22:05:44 +00002011
bellard579a97f2007-11-11 14:26:47 +00002012 struct ipc_kludge *foo = (struct ipc_kludge *)g2h(ptr);
ths1bc012f2007-06-03 14:27:49 +00002013 struct msgbuf *msgp = (struct msgbuf *) foo->msgp;
thsd96372e2007-02-02 22:05:44 +00002014
ths1bc012f2007-06-03 14:27:49 +00002015 ret = do_msgrcv(first, (long)msgp, second, 0, third);
thsd96372e2007-02-02 22:05:44 +00002016
ths1bc012f2007-06-03 14:27:49 +00002017 }
thsd96372e2007-02-02 22:05:44 +00002018 break;
2019
bellard8853f862004-02-22 14:57:26 +00002020 case IPCOP_shmat:
bellard5a4a8982007-11-11 17:39:18 +00002021 {
2022 abi_ulong raddr;
2023 void *host_addr;
2024 /* SHM_* flags are the same on all linux platforms */
2025 host_addr = shmat(first, (void *)g2h(ptr), second);
2026 if (host_addr == (void *)-1) {
2027 ret = get_errno((long)host_addr);
bellard8853f862004-02-22 14:57:26 +00002028 break;
bellard5a4a8982007-11-11 17:39:18 +00002029 }
2030 raddr = h2g((unsigned long)host_addr);
2031 /* find out the length of the shared memory segment */
2032
2033 ret = get_errno(shmctl(first, IPC_STAT, &shm_info));
2034 if (is_error(ret)) {
2035 /* can't get length, bail out */
2036 shmdt(host_addr);
2037 break;
2038 }
2039 page_set_flags(raddr, raddr + shm_info.shm_segsz,
2040 PAGE_VALID | PAGE_READ |
2041 ((second & SHM_RDONLY)? 0: PAGE_WRITE));
2042 for (i = 0; i < N_SHM_REGIONS; ++i) {
2043 if (shm_regions[i].start == 0) {
2044 shm_regions[i].start = raddr;
2045 shm_regions[i].size = shm_info.shm_segsz;
2046 break;
2047 }
2048 }
bellard2f619692007-11-16 10:46:05 +00002049 if (put_user_ual(raddr, third))
bellard5a4a8982007-11-11 17:39:18 +00002050 return -TARGET_EFAULT;
2051 ret = 0;
2052 }
bellard8853f862004-02-22 14:57:26 +00002053 break;
2054 case IPCOP_shmdt:
2055 for (i = 0; i < N_SHM_REGIONS; ++i) {
2056 if (shm_regions[i].start == ptr) {
2057 shm_regions[i].start = 0;
2058 page_set_flags(ptr, shm_regions[i].size, 0);
2059 break;
2060 }
2061 }
bellard5a4a8982007-11-11 17:39:18 +00002062 ret = get_errno(shmdt((void *)g2h(ptr)));
bellard8853f862004-02-22 14:57:26 +00002063 break;
2064
2065 case IPCOP_shmget:
2066 /* IPC_* flag values are the same on all linux platforms */
2067 ret = get_errno(shmget(first, second, third));
2068 break;
2069
2070 /* IPC_* and SHM_* command values are the same on all linux platforms */
2071 case IPCOP_shmctl:
2072 switch(second) {
2073 case IPC_RMID:
2074 case SHM_LOCK:
2075 case SHM_UNLOCK:
2076 ret = get_errno(shmctl(first, second, NULL));
2077 break;
2078 default:
2079 goto unimplemented;
2080 }
2081 break;
2082 default:
2083 unimplemented:
j_mayer32407102007-09-26 23:01:49 +00002084 gemu_log("Unsupported ipc call: %d (version %d)\n", call, version);
ths0da46a62007-10-20 20:23:07 +00002085 ret = -TARGET_ENOSYS;
bellard8853f862004-02-22 14:57:26 +00002086 break;
2087 }
2088 return ret;
2089}
j_mayer32407102007-09-26 23:01:49 +00002090#endif
bellard8853f862004-02-22 14:57:26 +00002091
bellard31e31b82003-02-18 22:55:36 +00002092/* kernel structure types definitions */
2093#define IFNAMSIZ 16
2094
2095#define STRUCT(name, list...) STRUCT_ ## name,
2096#define STRUCT_SPECIAL(name) STRUCT_ ## name,
2097enum {
2098#include "syscall_types.h"
2099};
2100#undef STRUCT
2101#undef STRUCT_SPECIAL
2102
2103#define STRUCT(name, list...) const argtype struct_ ## name ## _def[] = { list, TYPE_NULL };
2104#define STRUCT_SPECIAL(name)
2105#include "syscall_types.h"
2106#undef STRUCT
2107#undef STRUCT_SPECIAL
2108
2109typedef struct IOCTLEntry {
bellard2ab83ea2003-06-15 19:56:46 +00002110 unsigned int target_cmd;
2111 unsigned int host_cmd;
bellard31e31b82003-02-18 22:55:36 +00002112 const char *name;
2113 int access;
bellard1a9353d2003-03-16 20:28:50 +00002114 const argtype arg_type[5];
bellard31e31b82003-02-18 22:55:36 +00002115} IOCTLEntry;
2116
2117#define IOC_R 0x0001
2118#define IOC_W 0x0002
2119#define IOC_RW (IOC_R | IOC_W)
2120
2121#define MAX_STRUCT_SIZE 4096
2122
bellard2ab83ea2003-06-15 19:56:46 +00002123IOCTLEntry ioctl_entries[] = {
bellard31e31b82003-02-18 22:55:36 +00002124#define IOCTL(cmd, access, types...) \
2125 { TARGET_ ## cmd, cmd, #cmd, access, { types } },
2126#include "ioctls.h"
2127 { 0, 0, },
2128};
2129
pbrook53a59602006-03-25 19:31:22 +00002130/* ??? Implement proper locking for ioctls. */
ths0da46a62007-10-20 20:23:07 +00002131/* do_ioctl() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00002132static abi_long do_ioctl(int fd, abi_long cmd, abi_long arg)
bellard31e31b82003-02-18 22:55:36 +00002133{
2134 const IOCTLEntry *ie;
2135 const argtype *arg_type;
blueswir1992f48a2007-10-14 16:27:31 +00002136 abi_long ret;
bellard31e31b82003-02-18 22:55:36 +00002137 uint8_t buf_temp[MAX_STRUCT_SIZE];
pbrook53a59602006-03-25 19:31:22 +00002138 int target_size;
2139 void *argptr;
bellard31e31b82003-02-18 22:55:36 +00002140
2141 ie = ioctl_entries;
2142 for(;;) {
2143 if (ie->target_cmd == 0) {
j_mayer32407102007-09-26 23:01:49 +00002144 gemu_log("Unsupported ioctl: cmd=0x%04lx\n", (long)cmd);
ths0da46a62007-10-20 20:23:07 +00002145 return -TARGET_ENOSYS;
bellard31e31b82003-02-18 22:55:36 +00002146 }
2147 if (ie->target_cmd == cmd)
2148 break;
2149 ie++;
2150 }
2151 arg_type = ie->arg_type;
bellard9de5e442003-03-23 16:49:39 +00002152#if defined(DEBUG)
j_mayer32407102007-09-26 23:01:49 +00002153 gemu_log("ioctl: cmd=0x%04lx (%s)\n", (long)cmd, ie->name);
bellard72f03902003-02-18 23:33:18 +00002154#endif
bellard31e31b82003-02-18 22:55:36 +00002155 switch(arg_type[0]) {
2156 case TYPE_NULL:
2157 /* no argument */
2158 ret = get_errno(ioctl(fd, ie->host_cmd));
2159 break;
2160 case TYPE_PTRVOID:
2161 case TYPE_INT:
2162 /* int argment */
2163 ret = get_errno(ioctl(fd, ie->host_cmd, arg));
2164 break;
2165 case TYPE_PTR:
2166 arg_type++;
pbrook53a59602006-03-25 19:31:22 +00002167 target_size = thunk_type_size(arg_type, 0);
bellard31e31b82003-02-18 22:55:36 +00002168 switch(ie->access) {
2169 case IOC_R:
2170 ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
2171 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00002172 argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
2173 if (!argptr)
2174 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00002175 thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
2176 unlock_user(argptr, arg, target_size);
bellard31e31b82003-02-18 22:55:36 +00002177 }
2178 break;
2179 case IOC_W:
bellard579a97f2007-11-11 14:26:47 +00002180 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
2181 if (!argptr)
2182 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00002183 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
2184 unlock_user(argptr, arg, 0);
bellard31e31b82003-02-18 22:55:36 +00002185 ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
2186 break;
2187 default:
2188 case IOC_RW:
bellard579a97f2007-11-11 14:26:47 +00002189 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
2190 if (!argptr)
2191 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00002192 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
2193 unlock_user(argptr, arg, 0);
bellard31e31b82003-02-18 22:55:36 +00002194 ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
2195 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00002196 argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
2197 if (!argptr)
2198 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00002199 thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
2200 unlock_user(argptr, arg, target_size);
bellard31e31b82003-02-18 22:55:36 +00002201 }
2202 break;
2203 }
2204 break;
2205 default:
j_mayer32407102007-09-26 23:01:49 +00002206 gemu_log("Unsupported ioctl type: cmd=0x%04lx type=%d\n",
2207 (long)cmd, arg_type[0]);
ths0da46a62007-10-20 20:23:07 +00002208 ret = -TARGET_ENOSYS;
bellard31e31b82003-02-18 22:55:36 +00002209 break;
2210 }
2211 return ret;
2212}
2213
2214bitmask_transtbl iflag_tbl[] = {
2215 { TARGET_IGNBRK, TARGET_IGNBRK, IGNBRK, IGNBRK },
2216 { TARGET_BRKINT, TARGET_BRKINT, BRKINT, BRKINT },
2217 { TARGET_IGNPAR, TARGET_IGNPAR, IGNPAR, IGNPAR },
2218 { TARGET_PARMRK, TARGET_PARMRK, PARMRK, PARMRK },
2219 { TARGET_INPCK, TARGET_INPCK, INPCK, INPCK },
2220 { TARGET_ISTRIP, TARGET_ISTRIP, ISTRIP, ISTRIP },
2221 { TARGET_INLCR, TARGET_INLCR, INLCR, INLCR },
2222 { TARGET_IGNCR, TARGET_IGNCR, IGNCR, IGNCR },
2223 { TARGET_ICRNL, TARGET_ICRNL, ICRNL, ICRNL },
2224 { TARGET_IUCLC, TARGET_IUCLC, IUCLC, IUCLC },
2225 { TARGET_IXON, TARGET_IXON, IXON, IXON },
2226 { TARGET_IXANY, TARGET_IXANY, IXANY, IXANY },
2227 { TARGET_IXOFF, TARGET_IXOFF, IXOFF, IXOFF },
2228 { TARGET_IMAXBEL, TARGET_IMAXBEL, IMAXBEL, IMAXBEL },
2229 { 0, 0, 0, 0 }
2230};
2231
2232bitmask_transtbl oflag_tbl[] = {
2233 { TARGET_OPOST, TARGET_OPOST, OPOST, OPOST },
2234 { TARGET_OLCUC, TARGET_OLCUC, OLCUC, OLCUC },
2235 { TARGET_ONLCR, TARGET_ONLCR, ONLCR, ONLCR },
2236 { TARGET_OCRNL, TARGET_OCRNL, OCRNL, OCRNL },
2237 { TARGET_ONOCR, TARGET_ONOCR, ONOCR, ONOCR },
2238 { TARGET_ONLRET, TARGET_ONLRET, ONLRET, ONLRET },
2239 { TARGET_OFILL, TARGET_OFILL, OFILL, OFILL },
2240 { TARGET_OFDEL, TARGET_OFDEL, OFDEL, OFDEL },
2241 { TARGET_NLDLY, TARGET_NL0, NLDLY, NL0 },
2242 { TARGET_NLDLY, TARGET_NL1, NLDLY, NL1 },
2243 { TARGET_CRDLY, TARGET_CR0, CRDLY, CR0 },
2244 { TARGET_CRDLY, TARGET_CR1, CRDLY, CR1 },
2245 { TARGET_CRDLY, TARGET_CR2, CRDLY, CR2 },
2246 { TARGET_CRDLY, TARGET_CR3, CRDLY, CR3 },
2247 { TARGET_TABDLY, TARGET_TAB0, TABDLY, TAB0 },
2248 { TARGET_TABDLY, TARGET_TAB1, TABDLY, TAB1 },
2249 { TARGET_TABDLY, TARGET_TAB2, TABDLY, TAB2 },
2250 { TARGET_TABDLY, TARGET_TAB3, TABDLY, TAB3 },
2251 { TARGET_BSDLY, TARGET_BS0, BSDLY, BS0 },
2252 { TARGET_BSDLY, TARGET_BS1, BSDLY, BS1 },
2253 { TARGET_VTDLY, TARGET_VT0, VTDLY, VT0 },
2254 { TARGET_VTDLY, TARGET_VT1, VTDLY, VT1 },
2255 { TARGET_FFDLY, TARGET_FF0, FFDLY, FF0 },
2256 { TARGET_FFDLY, TARGET_FF1, FFDLY, FF1 },
2257 { 0, 0, 0, 0 }
2258};
2259
2260bitmask_transtbl cflag_tbl[] = {
2261 { TARGET_CBAUD, TARGET_B0, CBAUD, B0 },
2262 { TARGET_CBAUD, TARGET_B50, CBAUD, B50 },
2263 { TARGET_CBAUD, TARGET_B75, CBAUD, B75 },
2264 { TARGET_CBAUD, TARGET_B110, CBAUD, B110 },
2265 { TARGET_CBAUD, TARGET_B134, CBAUD, B134 },
2266 { TARGET_CBAUD, TARGET_B150, CBAUD, B150 },
2267 { TARGET_CBAUD, TARGET_B200, CBAUD, B200 },
2268 { TARGET_CBAUD, TARGET_B300, CBAUD, B300 },
2269 { TARGET_CBAUD, TARGET_B600, CBAUD, B600 },
2270 { TARGET_CBAUD, TARGET_B1200, CBAUD, B1200 },
2271 { TARGET_CBAUD, TARGET_B1800, CBAUD, B1800 },
2272 { TARGET_CBAUD, TARGET_B2400, CBAUD, B2400 },
2273 { TARGET_CBAUD, TARGET_B4800, CBAUD, B4800 },
2274 { TARGET_CBAUD, TARGET_B9600, CBAUD, B9600 },
2275 { TARGET_CBAUD, TARGET_B19200, CBAUD, B19200 },
2276 { TARGET_CBAUD, TARGET_B38400, CBAUD, B38400 },
2277 { TARGET_CBAUD, TARGET_B57600, CBAUD, B57600 },
2278 { TARGET_CBAUD, TARGET_B115200, CBAUD, B115200 },
2279 { TARGET_CBAUD, TARGET_B230400, CBAUD, B230400 },
2280 { TARGET_CBAUD, TARGET_B460800, CBAUD, B460800 },
2281 { TARGET_CSIZE, TARGET_CS5, CSIZE, CS5 },
2282 { TARGET_CSIZE, TARGET_CS6, CSIZE, CS6 },
2283 { TARGET_CSIZE, TARGET_CS7, CSIZE, CS7 },
2284 { TARGET_CSIZE, TARGET_CS8, CSIZE, CS8 },
2285 { TARGET_CSTOPB, TARGET_CSTOPB, CSTOPB, CSTOPB },
2286 { TARGET_CREAD, TARGET_CREAD, CREAD, CREAD },
2287 { TARGET_PARENB, TARGET_PARENB, PARENB, PARENB },
2288 { TARGET_PARODD, TARGET_PARODD, PARODD, PARODD },
2289 { TARGET_HUPCL, TARGET_HUPCL, HUPCL, HUPCL },
2290 { TARGET_CLOCAL, TARGET_CLOCAL, CLOCAL, CLOCAL },
2291 { TARGET_CRTSCTS, TARGET_CRTSCTS, CRTSCTS, CRTSCTS },
2292 { 0, 0, 0, 0 }
2293};
2294
2295bitmask_transtbl lflag_tbl[] = {
2296 { TARGET_ISIG, TARGET_ISIG, ISIG, ISIG },
2297 { TARGET_ICANON, TARGET_ICANON, ICANON, ICANON },
2298 { TARGET_XCASE, TARGET_XCASE, XCASE, XCASE },
2299 { TARGET_ECHO, TARGET_ECHO, ECHO, ECHO },
2300 { TARGET_ECHOE, TARGET_ECHOE, ECHOE, ECHOE },
2301 { TARGET_ECHOK, TARGET_ECHOK, ECHOK, ECHOK },
2302 { TARGET_ECHONL, TARGET_ECHONL, ECHONL, ECHONL },
2303 { TARGET_NOFLSH, TARGET_NOFLSH, NOFLSH, NOFLSH },
2304 { TARGET_TOSTOP, TARGET_TOSTOP, TOSTOP, TOSTOP },
2305 { TARGET_ECHOCTL, TARGET_ECHOCTL, ECHOCTL, ECHOCTL },
2306 { TARGET_ECHOPRT, TARGET_ECHOPRT, ECHOPRT, ECHOPRT },
2307 { TARGET_ECHOKE, TARGET_ECHOKE, ECHOKE, ECHOKE },
2308 { TARGET_FLUSHO, TARGET_FLUSHO, FLUSHO, FLUSHO },
2309 { TARGET_PENDIN, TARGET_PENDIN, PENDIN, PENDIN },
2310 { TARGET_IEXTEN, TARGET_IEXTEN, IEXTEN, IEXTEN },
2311 { 0, 0, 0, 0 }
2312};
2313
2314static void target_to_host_termios (void *dst, const void *src)
2315{
2316 struct host_termios *host = dst;
2317 const struct target_termios *target = src;
ths3b46e622007-09-17 08:09:54 +00002318
ths5fafdf22007-09-16 21:08:06 +00002319 host->c_iflag =
bellard31e31b82003-02-18 22:55:36 +00002320 target_to_host_bitmask(tswap32(target->c_iflag), iflag_tbl);
ths5fafdf22007-09-16 21:08:06 +00002321 host->c_oflag =
bellard31e31b82003-02-18 22:55:36 +00002322 target_to_host_bitmask(tswap32(target->c_oflag), oflag_tbl);
ths5fafdf22007-09-16 21:08:06 +00002323 host->c_cflag =
bellard31e31b82003-02-18 22:55:36 +00002324 target_to_host_bitmask(tswap32(target->c_cflag), cflag_tbl);
ths5fafdf22007-09-16 21:08:06 +00002325 host->c_lflag =
bellard31e31b82003-02-18 22:55:36 +00002326 target_to_host_bitmask(tswap32(target->c_lflag), lflag_tbl);
2327 host->c_line = target->c_line;
ths3b46e622007-09-17 08:09:54 +00002328
ths5fafdf22007-09-16 21:08:06 +00002329 host->c_cc[VINTR] = target->c_cc[TARGET_VINTR];
2330 host->c_cc[VQUIT] = target->c_cc[TARGET_VQUIT];
ths3b46e622007-09-17 08:09:54 +00002331 host->c_cc[VERASE] = target->c_cc[TARGET_VERASE];
ths5fafdf22007-09-16 21:08:06 +00002332 host->c_cc[VKILL] = target->c_cc[TARGET_VKILL];
ths3b46e622007-09-17 08:09:54 +00002333 host->c_cc[VEOF] = target->c_cc[TARGET_VEOF];
ths5fafdf22007-09-16 21:08:06 +00002334 host->c_cc[VTIME] = target->c_cc[TARGET_VTIME];
ths3b46e622007-09-17 08:09:54 +00002335 host->c_cc[VMIN] = target->c_cc[TARGET_VMIN];
ths5fafdf22007-09-16 21:08:06 +00002336 host->c_cc[VSWTC] = target->c_cc[TARGET_VSWTC];
ths3b46e622007-09-17 08:09:54 +00002337 host->c_cc[VSTART] = target->c_cc[TARGET_VSTART];
ths5fafdf22007-09-16 21:08:06 +00002338 host->c_cc[VSTOP] = target->c_cc[TARGET_VSTOP];
2339 host->c_cc[VSUSP] = target->c_cc[TARGET_VSUSP];
ths3b46e622007-09-17 08:09:54 +00002340 host->c_cc[VEOL] = target->c_cc[TARGET_VEOL];
2341 host->c_cc[VREPRINT] = target->c_cc[TARGET_VREPRINT];
2342 host->c_cc[VDISCARD] = target->c_cc[TARGET_VDISCARD];
2343 host->c_cc[VWERASE] = target->c_cc[TARGET_VWERASE];
2344 host->c_cc[VLNEXT] = target->c_cc[TARGET_VLNEXT];
ths5fafdf22007-09-16 21:08:06 +00002345 host->c_cc[VEOL2] = target->c_cc[TARGET_VEOL2];
bellard31e31b82003-02-18 22:55:36 +00002346}
ths3b46e622007-09-17 08:09:54 +00002347
bellard31e31b82003-02-18 22:55:36 +00002348static void host_to_target_termios (void *dst, const void *src)
2349{
2350 struct target_termios *target = dst;
2351 const struct host_termios *host = src;
2352
ths5fafdf22007-09-16 21:08:06 +00002353 target->c_iflag =
bellard31e31b82003-02-18 22:55:36 +00002354 tswap32(host_to_target_bitmask(host->c_iflag, iflag_tbl));
ths5fafdf22007-09-16 21:08:06 +00002355 target->c_oflag =
bellard31e31b82003-02-18 22:55:36 +00002356 tswap32(host_to_target_bitmask(host->c_oflag, oflag_tbl));
ths5fafdf22007-09-16 21:08:06 +00002357 target->c_cflag =
bellard31e31b82003-02-18 22:55:36 +00002358 tswap32(host_to_target_bitmask(host->c_cflag, cflag_tbl));
ths5fafdf22007-09-16 21:08:06 +00002359 target->c_lflag =
bellard31e31b82003-02-18 22:55:36 +00002360 tswap32(host_to_target_bitmask(host->c_lflag, lflag_tbl));
2361 target->c_line = host->c_line;
ths3b46e622007-09-17 08:09:54 +00002362
bellard31e31b82003-02-18 22:55:36 +00002363 target->c_cc[TARGET_VINTR] = host->c_cc[VINTR];
2364 target->c_cc[TARGET_VQUIT] = host->c_cc[VQUIT];
2365 target->c_cc[TARGET_VERASE] = host->c_cc[VERASE];
2366 target->c_cc[TARGET_VKILL] = host->c_cc[VKILL];
2367 target->c_cc[TARGET_VEOF] = host->c_cc[VEOF];
2368 target->c_cc[TARGET_VTIME] = host->c_cc[VTIME];
2369 target->c_cc[TARGET_VMIN] = host->c_cc[VMIN];
2370 target->c_cc[TARGET_VSWTC] = host->c_cc[VSWTC];
2371 target->c_cc[TARGET_VSTART] = host->c_cc[VSTART];
2372 target->c_cc[TARGET_VSTOP] = host->c_cc[VSTOP];
2373 target->c_cc[TARGET_VSUSP] = host->c_cc[VSUSP];
2374 target->c_cc[TARGET_VEOL] = host->c_cc[VEOL];
2375 target->c_cc[TARGET_VREPRINT] = host->c_cc[VREPRINT];
2376 target->c_cc[TARGET_VDISCARD] = host->c_cc[VDISCARD];
2377 target->c_cc[TARGET_VWERASE] = host->c_cc[VWERASE];
2378 target->c_cc[TARGET_VLNEXT] = host->c_cc[VLNEXT];
2379 target->c_cc[TARGET_VEOL2] = host->c_cc[VEOL2];
2380}
2381
2382StructEntry struct_termios_def = {
2383 .convert = { host_to_target_termios, target_to_host_termios },
2384 .size = { sizeof(struct target_termios), sizeof(struct host_termios) },
2385 .align = { __alignof__(struct target_termios), __alignof__(struct host_termios) },
2386};
2387
bellard5286db72003-06-05 00:57:30 +00002388static bitmask_transtbl mmap_flags_tbl[] = {
2389 { TARGET_MAP_SHARED, TARGET_MAP_SHARED, MAP_SHARED, MAP_SHARED },
2390 { TARGET_MAP_PRIVATE, TARGET_MAP_PRIVATE, MAP_PRIVATE, MAP_PRIVATE },
2391 { TARGET_MAP_FIXED, TARGET_MAP_FIXED, MAP_FIXED, MAP_FIXED },
2392 { TARGET_MAP_ANONYMOUS, TARGET_MAP_ANONYMOUS, MAP_ANONYMOUS, MAP_ANONYMOUS },
2393 { TARGET_MAP_GROWSDOWN, TARGET_MAP_GROWSDOWN, MAP_GROWSDOWN, MAP_GROWSDOWN },
2394 { TARGET_MAP_DENYWRITE, TARGET_MAP_DENYWRITE, MAP_DENYWRITE, MAP_DENYWRITE },
2395 { TARGET_MAP_EXECUTABLE, TARGET_MAP_EXECUTABLE, MAP_EXECUTABLE, MAP_EXECUTABLE },
2396 { TARGET_MAP_LOCKED, TARGET_MAP_LOCKED, MAP_LOCKED, MAP_LOCKED },
2397 { 0, 0, 0, 0 }
2398};
2399
bellardffa65c32004-01-04 23:57:22 +00002400static bitmask_transtbl fcntl_flags_tbl[] = {
2401 { TARGET_O_ACCMODE, TARGET_O_WRONLY, O_ACCMODE, O_WRONLY, },
2402 { TARGET_O_ACCMODE, TARGET_O_RDWR, O_ACCMODE, O_RDWR, },
2403 { TARGET_O_CREAT, TARGET_O_CREAT, O_CREAT, O_CREAT, },
2404 { TARGET_O_EXCL, TARGET_O_EXCL, O_EXCL, O_EXCL, },
2405 { TARGET_O_NOCTTY, TARGET_O_NOCTTY, O_NOCTTY, O_NOCTTY, },
2406 { TARGET_O_TRUNC, TARGET_O_TRUNC, O_TRUNC, O_TRUNC, },
2407 { TARGET_O_APPEND, TARGET_O_APPEND, O_APPEND, O_APPEND, },
2408 { TARGET_O_NONBLOCK, TARGET_O_NONBLOCK, O_NONBLOCK, O_NONBLOCK, },
2409 { TARGET_O_SYNC, TARGET_O_SYNC, O_SYNC, O_SYNC, },
2410 { TARGET_FASYNC, TARGET_FASYNC, FASYNC, FASYNC, },
2411 { TARGET_O_DIRECTORY, TARGET_O_DIRECTORY, O_DIRECTORY, O_DIRECTORY, },
2412 { TARGET_O_NOFOLLOW, TARGET_O_NOFOLLOW, O_NOFOLLOW, O_NOFOLLOW, },
2413 { TARGET_O_LARGEFILE, TARGET_O_LARGEFILE, O_LARGEFILE, O_LARGEFILE, },
bellard121061d2004-02-22 11:56:01 +00002414#if defined(O_DIRECT)
bellardffa65c32004-01-04 23:57:22 +00002415 { TARGET_O_DIRECT, TARGET_O_DIRECT, O_DIRECT, O_DIRECT, },
bellard121061d2004-02-22 11:56:01 +00002416#endif
bellardffa65c32004-01-04 23:57:22 +00002417 { 0, 0, 0, 0 }
2418};
2419
bellard2ab83ea2003-06-15 19:56:46 +00002420#if defined(TARGET_I386)
bellard6dbad632003-03-16 18:05:05 +00002421
2422/* NOTE: there is really one LDT for all the threads */
2423uint8_t *ldt_table;
2424
bellard03acab62007-11-11 14:57:14 +00002425static abi_long read_ldt(abi_ulong ptr, unsigned long bytecount)
bellard6dbad632003-03-16 18:05:05 +00002426{
2427 int size;
pbrook53a59602006-03-25 19:31:22 +00002428 void *p;
bellard6dbad632003-03-16 18:05:05 +00002429
2430 if (!ldt_table)
2431 return 0;
2432 size = TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE;
2433 if (size > bytecount)
2434 size = bytecount;
bellard579a97f2007-11-11 14:26:47 +00002435 p = lock_user(VERIFY_WRITE, ptr, size, 0);
2436 if (!p)
bellard03acab62007-11-11 14:57:14 +00002437 return -TARGET_EFAULT;
bellard579a97f2007-11-11 14:26:47 +00002438 /* ??? Should this by byteswapped? */
pbrook53a59602006-03-25 19:31:22 +00002439 memcpy(p, ldt_table, size);
2440 unlock_user(p, ptr, size);
bellard6dbad632003-03-16 18:05:05 +00002441 return size;
2442}
2443
2444/* XXX: add locking support */
bellard03acab62007-11-11 14:57:14 +00002445static abi_long write_ldt(CPUX86State *env,
2446 abi_ulong ptr, unsigned long bytecount, int oldmode)
bellard6dbad632003-03-16 18:05:05 +00002447{
2448 struct target_modify_ldt_ldt_s ldt_info;
pbrook53a59602006-03-25 19:31:22 +00002449 struct target_modify_ldt_ldt_s *target_ldt_info;
bellard6dbad632003-03-16 18:05:05 +00002450 int seg_32bit, contents, read_exec_only, limit_in_pages;
bellard8d18e892007-11-14 15:18:40 +00002451 int seg_not_present, useable, lm;
bellard6dbad632003-03-16 18:05:05 +00002452 uint32_t *lp, entry_1, entry_2;
2453
2454 if (bytecount != sizeof(ldt_info))
bellard03acab62007-11-11 14:57:14 +00002455 return -TARGET_EINVAL;
bellard579a97f2007-11-11 14:26:47 +00002456 if (!lock_user_struct(VERIFY_READ, target_ldt_info, ptr, 1))
bellard03acab62007-11-11 14:57:14 +00002457 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00002458 ldt_info.entry_number = tswap32(target_ldt_info->entry_number);
2459 ldt_info.base_addr = tswapl(target_ldt_info->base_addr);
2460 ldt_info.limit = tswap32(target_ldt_info->limit);
2461 ldt_info.flags = tswap32(target_ldt_info->flags);
2462 unlock_user_struct(target_ldt_info, ptr, 0);
ths3b46e622007-09-17 08:09:54 +00002463
bellard6dbad632003-03-16 18:05:05 +00002464 if (ldt_info.entry_number >= TARGET_LDT_ENTRIES)
bellard03acab62007-11-11 14:57:14 +00002465 return -TARGET_EINVAL;
bellard6dbad632003-03-16 18:05:05 +00002466 seg_32bit = ldt_info.flags & 1;
2467 contents = (ldt_info.flags >> 1) & 3;
2468 read_exec_only = (ldt_info.flags >> 3) & 1;
2469 limit_in_pages = (ldt_info.flags >> 4) & 1;
2470 seg_not_present = (ldt_info.flags >> 5) & 1;
2471 useable = (ldt_info.flags >> 6) & 1;
bellard8d18e892007-11-14 15:18:40 +00002472#ifdef TARGET_ABI32
2473 lm = 0;
2474#else
2475 lm = (ldt_info.flags >> 7) & 1;
2476#endif
bellard6dbad632003-03-16 18:05:05 +00002477 if (contents == 3) {
2478 if (oldmode)
bellard03acab62007-11-11 14:57:14 +00002479 return -TARGET_EINVAL;
bellard6dbad632003-03-16 18:05:05 +00002480 if (seg_not_present == 0)
bellard03acab62007-11-11 14:57:14 +00002481 return -TARGET_EINVAL;
bellard6dbad632003-03-16 18:05:05 +00002482 }
2483 /* allocate the LDT */
2484 if (!ldt_table) {
2485 ldt_table = malloc(TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE);
2486 if (!ldt_table)
bellard03acab62007-11-11 14:57:14 +00002487 return -TARGET_ENOMEM;
bellard6dbad632003-03-16 18:05:05 +00002488 memset(ldt_table, 0, TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE);
bellardeeeac3f2007-11-11 19:34:32 +00002489 env->ldt.base = h2g((unsigned long)ldt_table);
bellard6dbad632003-03-16 18:05:05 +00002490 env->ldt.limit = 0xffff;
2491 }
2492
2493 /* NOTE: same code as Linux kernel */
2494 /* Allow LDTs to be cleared by the user. */
2495 if (ldt_info.base_addr == 0 && ldt_info.limit == 0) {
2496 if (oldmode ||
2497 (contents == 0 &&
2498 read_exec_only == 1 &&
2499 seg_32bit == 0 &&
2500 limit_in_pages == 0 &&
2501 seg_not_present == 1 &&
2502 useable == 0 )) {
2503 entry_1 = 0;
2504 entry_2 = 0;
2505 goto install;
2506 }
2507 }
ths3b46e622007-09-17 08:09:54 +00002508
bellard6dbad632003-03-16 18:05:05 +00002509 entry_1 = ((ldt_info.base_addr & 0x0000ffff) << 16) |
2510 (ldt_info.limit & 0x0ffff);
2511 entry_2 = (ldt_info.base_addr & 0xff000000) |
2512 ((ldt_info.base_addr & 0x00ff0000) >> 16) |
2513 (ldt_info.limit & 0xf0000) |
2514 ((read_exec_only ^ 1) << 9) |
2515 (contents << 10) |
2516 ((seg_not_present ^ 1) << 15) |
2517 (seg_32bit << 22) |
2518 (limit_in_pages << 23) |
bellard8d18e892007-11-14 15:18:40 +00002519 (lm << 21) |
bellard6dbad632003-03-16 18:05:05 +00002520 0x7000;
2521 if (!oldmode)
2522 entry_2 |= (useable << 20);
bellard14ae3ba2003-05-27 23:25:06 +00002523
bellard6dbad632003-03-16 18:05:05 +00002524 /* Install the new entry ... */
2525install:
2526 lp = (uint32_t *)(ldt_table + (ldt_info.entry_number << 3));
2527 lp[0] = tswap32(entry_1);
2528 lp[1] = tswap32(entry_2);
2529 return 0;
2530}
2531
2532/* specific and weird i386 syscalls */
blueswir18fcd3692008-08-17 20:26:25 +00002533static abi_long do_modify_ldt(CPUX86State *env, int func, abi_ulong ptr,
2534 unsigned long bytecount)
bellard6dbad632003-03-16 18:05:05 +00002535{
bellard03acab62007-11-11 14:57:14 +00002536 abi_long ret;
ths3b46e622007-09-17 08:09:54 +00002537
bellard6dbad632003-03-16 18:05:05 +00002538 switch (func) {
2539 case 0:
2540 ret = read_ldt(ptr, bytecount);
2541 break;
2542 case 1:
2543 ret = write_ldt(env, ptr, bytecount, 1);
2544 break;
2545 case 0x11:
2546 ret = write_ldt(env, ptr, bytecount, 0);
2547 break;
bellard03acab62007-11-11 14:57:14 +00002548 default:
2549 ret = -TARGET_ENOSYS;
2550 break;
bellard6dbad632003-03-16 18:05:05 +00002551 }
2552 return ret;
2553}
bellard1b6b0292003-03-22 17:31:38 +00002554
blueswir14583f582008-08-24 10:35:55 +00002555#if defined(TARGET_I386) && defined(TARGET_ABI32)
blueswir18fcd3692008-08-17 20:26:25 +00002556static abi_long do_set_thread_area(CPUX86State *env, abi_ulong ptr)
bellard8d18e892007-11-14 15:18:40 +00002557{
2558 uint64_t *gdt_table = g2h(env->gdt.base);
2559 struct target_modify_ldt_ldt_s ldt_info;
2560 struct target_modify_ldt_ldt_s *target_ldt_info;
2561 int seg_32bit, contents, read_exec_only, limit_in_pages;
2562 int seg_not_present, useable, lm;
2563 uint32_t *lp, entry_1, entry_2;
2564 int i;
2565
2566 lock_user_struct(VERIFY_WRITE, target_ldt_info, ptr, 1);
2567 if (!target_ldt_info)
2568 return -TARGET_EFAULT;
2569 ldt_info.entry_number = tswap32(target_ldt_info->entry_number);
2570 ldt_info.base_addr = tswapl(target_ldt_info->base_addr);
2571 ldt_info.limit = tswap32(target_ldt_info->limit);
2572 ldt_info.flags = tswap32(target_ldt_info->flags);
2573 if (ldt_info.entry_number == -1) {
2574 for (i=TARGET_GDT_ENTRY_TLS_MIN; i<=TARGET_GDT_ENTRY_TLS_MAX; i++) {
2575 if (gdt_table[i] == 0) {
2576 ldt_info.entry_number = i;
2577 target_ldt_info->entry_number = tswap32(i);
2578 break;
2579 }
2580 }
2581 }
2582 unlock_user_struct(target_ldt_info, ptr, 1);
2583
2584 if (ldt_info.entry_number < TARGET_GDT_ENTRY_TLS_MIN ||
2585 ldt_info.entry_number > TARGET_GDT_ENTRY_TLS_MAX)
2586 return -TARGET_EINVAL;
2587 seg_32bit = ldt_info.flags & 1;
2588 contents = (ldt_info.flags >> 1) & 3;
2589 read_exec_only = (ldt_info.flags >> 3) & 1;
2590 limit_in_pages = (ldt_info.flags >> 4) & 1;
2591 seg_not_present = (ldt_info.flags >> 5) & 1;
2592 useable = (ldt_info.flags >> 6) & 1;
2593#ifdef TARGET_ABI32
2594 lm = 0;
2595#else
2596 lm = (ldt_info.flags >> 7) & 1;
2597#endif
2598
2599 if (contents == 3) {
2600 if (seg_not_present == 0)
2601 return -TARGET_EINVAL;
2602 }
2603
2604 /* NOTE: same code as Linux kernel */
2605 /* Allow LDTs to be cleared by the user. */
2606 if (ldt_info.base_addr == 0 && ldt_info.limit == 0) {
2607 if ((contents == 0 &&
2608 read_exec_only == 1 &&
2609 seg_32bit == 0 &&
2610 limit_in_pages == 0 &&
2611 seg_not_present == 1 &&
2612 useable == 0 )) {
2613 entry_1 = 0;
2614 entry_2 = 0;
2615 goto install;
2616 }
2617 }
2618
2619 entry_1 = ((ldt_info.base_addr & 0x0000ffff) << 16) |
2620 (ldt_info.limit & 0x0ffff);
2621 entry_2 = (ldt_info.base_addr & 0xff000000) |
2622 ((ldt_info.base_addr & 0x00ff0000) >> 16) |
2623 (ldt_info.limit & 0xf0000) |
2624 ((read_exec_only ^ 1) << 9) |
2625 (contents << 10) |
2626 ((seg_not_present ^ 1) << 15) |
2627 (seg_32bit << 22) |
2628 (limit_in_pages << 23) |
2629 (useable << 20) |
2630 (lm << 21) |
2631 0x7000;
2632
2633 /* Install the new entry ... */
2634install:
2635 lp = (uint32_t *)(gdt_table + ldt_info.entry_number);
2636 lp[0] = tswap32(entry_1);
2637 lp[1] = tswap32(entry_2);
2638 return 0;
2639}
2640
blueswir18fcd3692008-08-17 20:26:25 +00002641static abi_long do_get_thread_area(CPUX86State *env, abi_ulong ptr)
bellard8d18e892007-11-14 15:18:40 +00002642{
2643 struct target_modify_ldt_ldt_s *target_ldt_info;
2644 uint64_t *gdt_table = g2h(env->gdt.base);
2645 uint32_t base_addr, limit, flags;
2646 int seg_32bit, contents, read_exec_only, limit_in_pages, idx;
2647 int seg_not_present, useable, lm;
2648 uint32_t *lp, entry_1, entry_2;
2649
2650 lock_user_struct(VERIFY_WRITE, target_ldt_info, ptr, 1);
2651 if (!target_ldt_info)
2652 return -TARGET_EFAULT;
2653 idx = tswap32(target_ldt_info->entry_number);
2654 if (idx < TARGET_GDT_ENTRY_TLS_MIN ||
2655 idx > TARGET_GDT_ENTRY_TLS_MAX) {
2656 unlock_user_struct(target_ldt_info, ptr, 1);
2657 return -TARGET_EINVAL;
2658 }
2659 lp = (uint32_t *)(gdt_table + idx);
2660 entry_1 = tswap32(lp[0]);
2661 entry_2 = tswap32(lp[1]);
2662
2663 read_exec_only = ((entry_2 >> 9) & 1) ^ 1;
2664 contents = (entry_2 >> 10) & 3;
2665 seg_not_present = ((entry_2 >> 15) & 1) ^ 1;
2666 seg_32bit = (entry_2 >> 22) & 1;
2667 limit_in_pages = (entry_2 >> 23) & 1;
2668 useable = (entry_2 >> 20) & 1;
2669#ifdef TARGET_ABI32
2670 lm = 0;
2671#else
2672 lm = (entry_2 >> 21) & 1;
2673#endif
2674 flags = (seg_32bit << 0) | (contents << 1) |
2675 (read_exec_only << 3) | (limit_in_pages << 4) |
2676 (seg_not_present << 5) | (useable << 6) | (lm << 7);
2677 limit = (entry_1 & 0xffff) | (entry_2 & 0xf0000);
2678 base_addr = (entry_1 >> 16) |
2679 (entry_2 & 0xff000000) |
2680 ((entry_2 & 0xff) << 16);
2681 target_ldt_info->base_addr = tswapl(base_addr);
2682 target_ldt_info->limit = tswap32(limit);
2683 target_ldt_info->flags = tswap32(flags);
2684 unlock_user_struct(target_ldt_info, ptr, 1);
2685 return 0;
2686}
blueswir14583f582008-08-24 10:35:55 +00002687#endif /* TARGET_I386 && TARGET_ABI32 */
bellard8d18e892007-11-14 15:18:40 +00002688
bellardd2fd1af2007-11-14 18:08:56 +00002689#ifndef TARGET_ABI32
blueswir18fcd3692008-08-17 20:26:25 +00002690static abi_long do_arch_prctl(CPUX86State *env, int code, abi_ulong addr)
bellardd2fd1af2007-11-14 18:08:56 +00002691{
2692 abi_long ret;
2693 abi_ulong val;
2694 int idx;
2695
2696 switch(code) {
2697 case TARGET_ARCH_SET_GS:
2698 case TARGET_ARCH_SET_FS:
2699 if (code == TARGET_ARCH_SET_GS)
2700 idx = R_GS;
2701 else
2702 idx = R_FS;
2703 cpu_x86_load_seg(env, idx, 0);
2704 env->segs[idx].base = addr;
2705 break;
2706 case TARGET_ARCH_GET_GS:
2707 case TARGET_ARCH_GET_FS:
2708 if (code == TARGET_ARCH_GET_GS)
2709 idx = R_GS;
2710 else
2711 idx = R_FS;
2712 val = env->segs[idx].base;
2713 if (put_user(val, addr, abi_ulong))
2714 return -TARGET_EFAULT;
2715 break;
2716 default:
2717 ret = -TARGET_EINVAL;
2718 break;
2719 }
2720 return 0;
2721}
2722#endif
2723
bellard2ab83ea2003-06-15 19:56:46 +00002724#endif /* defined(TARGET_I386) */
2725
pbrookd865bab2008-06-07 22:12:17 +00002726#if defined(USE_NPTL)
2727
2728#define NEW_STACK_SIZE PTHREAD_STACK_MIN
2729
2730static pthread_mutex_t clone_lock = PTHREAD_MUTEX_INITIALIZER;
2731typedef struct {
2732 CPUState *env;
2733 pthread_mutex_t mutex;
2734 pthread_cond_t cond;
2735 pthread_t thread;
2736 uint32_t tid;
2737 abi_ulong child_tidptr;
2738 abi_ulong parent_tidptr;
2739 sigset_t sigmask;
2740} new_thread_info;
2741
2742static void *clone_func(void *arg)
2743{
2744 new_thread_info *info = arg;
2745 CPUState *env;
2746
2747 env = info->env;
2748 thread_env = env;
2749 info->tid = gettid();
2750 if (info->child_tidptr)
2751 put_user_u32(info->tid, info->child_tidptr);
2752 if (info->parent_tidptr)
2753 put_user_u32(info->tid, info->parent_tidptr);
2754 /* Enable signals. */
2755 sigprocmask(SIG_SETMASK, &info->sigmask, NULL);
2756 /* Signal to the parent that we're ready. */
2757 pthread_mutex_lock(&info->mutex);
2758 pthread_cond_broadcast(&info->cond);
2759 pthread_mutex_unlock(&info->mutex);
2760 /* Wait until the parent has finshed initializing the tls state. */
2761 pthread_mutex_lock(&clone_lock);
2762 pthread_mutex_unlock(&clone_lock);
2763 cpu_loop(env);
2764 /* never exits */
2765 return NULL;
2766}
2767#else
bellard1b6b0292003-03-22 17:31:38 +00002768/* this stack is the equivalent of the kernel stack associated with a
2769 thread/process */
2770#define NEW_STACK_SIZE 8192
2771
2772static int clone_func(void *arg)
2773{
bellard2ab83ea2003-06-15 19:56:46 +00002774 CPUState *env = arg;
bellard1b6b0292003-03-22 17:31:38 +00002775 cpu_loop(env);
2776 /* never exits */
2777 return 0;
2778}
pbrookd865bab2008-06-07 22:12:17 +00002779#endif
bellard1b6b0292003-03-22 17:31:38 +00002780
ths0da46a62007-10-20 20:23:07 +00002781/* do_fork() Must return host values and target errnos (unlike most
2782 do_*() functions). */
pbrookd865bab2008-06-07 22:12:17 +00002783static int do_fork(CPUState *env, unsigned int flags, abi_ulong newsp,
2784 abi_ulong parent_tidptr, target_ulong newtls,
2785 abi_ulong child_tidptr)
bellard1b6b0292003-03-22 17:31:38 +00002786{
2787 int ret;
bellard5cd43932003-03-29 16:54:36 +00002788 TaskState *ts;
bellard1b6b0292003-03-22 17:31:38 +00002789 uint8_t *new_stack;
bellard2ab83ea2003-06-15 19:56:46 +00002790 CPUState *new_env;
pbrookd865bab2008-06-07 22:12:17 +00002791#if defined(USE_NPTL)
2792 unsigned int nptl_flags;
2793 sigset_t sigmask;
2794#endif
ths3b46e622007-09-17 08:09:54 +00002795
bellard1b6b0292003-03-22 17:31:38 +00002796 if (flags & CLONE_VM) {
pbrookbd0c5662008-05-29 14:34:11 +00002797#if defined(USE_NPTL)
pbrookd865bab2008-06-07 22:12:17 +00002798 new_thread_info info;
2799 pthread_attr_t attr;
pbrookbd0c5662008-05-29 14:34:11 +00002800#endif
pbrookc3a92832008-06-09 14:02:50 +00002801 ts = qemu_mallocz(sizeof(TaskState) + NEW_STACK_SIZE);
pbrook624f7972008-05-31 16:11:38 +00002802 init_task_state(ts);
bellard5cd43932003-03-29 16:54:36 +00002803 new_stack = ts->stack;
bellard1b6b0292003-03-22 17:31:38 +00002804 /* we create a new CPU instance. */
thsc5be9f02007-02-28 20:20:53 +00002805 new_env = cpu_copy(env);
pbrook6e68e072008-05-30 17:22:15 +00002806 /* Init regs that differ from the parent. */
2807 cpu_clone_regs(new_env, newsp);
bellard5cd43932003-03-29 16:54:36 +00002808 new_env->opaque = ts;
pbrookd865bab2008-06-07 22:12:17 +00002809#if defined(USE_NPTL)
2810 nptl_flags = flags;
2811 flags &= ~CLONE_NPTL_FLAGS2;
2812
2813 /* TODO: Implement CLONE_CHILD_CLEARTID. */
2814 if (nptl_flags & CLONE_SETTLS)
2815 cpu_set_tls (new_env, newtls);
2816
2817 /* Grab a mutex so that thread setup appears atomic. */
2818 pthread_mutex_lock(&clone_lock);
2819
2820 memset(&info, 0, sizeof(info));
2821 pthread_mutex_init(&info.mutex, NULL);
2822 pthread_mutex_lock(&info.mutex);
2823 pthread_cond_init(&info.cond, NULL);
2824 info.env = new_env;
2825 if (nptl_flags & CLONE_CHILD_SETTID)
2826 info.child_tidptr = child_tidptr;
2827 if (nptl_flags & CLONE_PARENT_SETTID)
2828 info.parent_tidptr = parent_tidptr;
2829
2830 ret = pthread_attr_init(&attr);
2831 ret = pthread_attr_setstack(&attr, new_stack, NEW_STACK_SIZE);
2832 /* It is not safe to deliver signals until the child has finished
2833 initializing, so temporarily block all signals. */
2834 sigfillset(&sigmask);
2835 sigprocmask(SIG_BLOCK, &sigmask, &info.sigmask);
2836
2837 ret = pthread_create(&info.thread, &attr, clone_func, &info);
2838
2839 sigprocmask(SIG_SETMASK, &info.sigmask, NULL);
2840 pthread_attr_destroy(&attr);
2841 if (ret == 0) {
2842 /* Wait for the child to initialize. */
2843 pthread_cond_wait(&info.cond, &info.mutex);
2844 ret = info.tid;
2845 if (flags & CLONE_PARENT_SETTID)
2846 put_user_u32(ret, parent_tidptr);
2847 } else {
2848 ret = -1;
2849 }
2850 pthread_mutex_unlock(&info.mutex);
2851 pthread_cond_destroy(&info.cond);
2852 pthread_mutex_destroy(&info.mutex);
2853 pthread_mutex_unlock(&clone_lock);
2854#else
2855 if (flags & CLONE_NPTL_FLAGS2)
2856 return -EINVAL;
2857 /* This is probably going to die very quickly, but do it anyway. */
bellard27725c12003-04-29 21:08:18 +00002858#ifdef __ia64__
bellardfd4a43e2006-04-24 20:32:17 +00002859 ret = __clone2(clone_func, new_stack + NEW_STACK_SIZE, flags, new_env);
bellard27725c12003-04-29 21:08:18 +00002860#else
2861 ret = clone(clone_func, new_stack + NEW_STACK_SIZE, flags, new_env);
2862#endif
pbrookd865bab2008-06-07 22:12:17 +00002863#endif
bellard1b6b0292003-03-22 17:31:38 +00002864 } else {
2865 /* if no CLONE_VM, we consider it is a fork */
pbrookd865bab2008-06-07 22:12:17 +00002866 if ((flags & ~(CSIGNAL | CLONE_NPTL_FLAGS2)) != 0)
bellard1b6b0292003-03-22 17:31:38 +00002867 return -EINVAL;
pbrookd865bab2008-06-07 22:12:17 +00002868 fork_start();
bellard1b6b0292003-03-22 17:31:38 +00002869 ret = fork();
pbrookd865bab2008-06-07 22:12:17 +00002870#if defined(USE_NPTL)
2871 /* There is a race condition here. The parent process could
2872 theoretically read the TID in the child process before the child
2873 tid is set. This would require using either ptrace
2874 (not implemented) or having *_tidptr to point at a shared memory
2875 mapping. We can't repeat the spinlock hack used above because
2876 the child process gets its own copy of the lock. */
2877 if (ret == 0) {
2878 cpu_clone_regs(env, newsp);
2879 fork_end(1);
2880 /* Child Process. */
2881 if (flags & CLONE_CHILD_SETTID)
2882 put_user_u32(gettid(), child_tidptr);
2883 if (flags & CLONE_PARENT_SETTID)
2884 put_user_u32(gettid(), parent_tidptr);
2885 ts = (TaskState *)env->opaque;
2886 if (flags & CLONE_SETTLS)
2887 cpu_set_tls (env, newtls);
2888 /* TODO: Implement CLONE_CHILD_CLEARTID. */
2889 } else {
2890 fork_end(0);
2891 }
2892#else
pbrook6e68e072008-05-30 17:22:15 +00002893 if (ret == 0) {
2894 cpu_clone_regs(env, newsp);
2895 }
pbrookd865bab2008-06-07 22:12:17 +00002896#endif
bellard1b6b0292003-03-22 17:31:38 +00002897 }
2898 return ret;
2899}
2900
blueswir1992f48a2007-10-14 16:27:31 +00002901static abi_long do_fcntl(int fd, int cmd, abi_ulong arg)
bellard7775e9e2003-05-14 22:46:48 +00002902{
2903 struct flock fl;
pbrook53a59602006-03-25 19:31:22 +00002904 struct target_flock *target_fl;
ths43f238d2007-01-05 20:55:49 +00002905 struct flock64 fl64;
2906 struct target_flock64 *target_fl64;
blueswir1992f48a2007-10-14 16:27:31 +00002907 abi_long ret;
pbrook53a59602006-03-25 19:31:22 +00002908
bellard7775e9e2003-05-14 22:46:48 +00002909 switch(cmd) {
2910 case TARGET_F_GETLK:
bellard579a97f2007-11-11 14:26:47 +00002911 if (!lock_user_struct(VERIFY_READ, target_fl, arg, 1))
2912 return -TARGET_EFAULT;
ths58134272007-03-31 18:59:32 +00002913 fl.l_type = tswap16(target_fl->l_type);
2914 fl.l_whence = tswap16(target_fl->l_whence);
2915 fl.l_start = tswapl(target_fl->l_start);
2916 fl.l_len = tswapl(target_fl->l_len);
2917 fl.l_pid = tswapl(target_fl->l_pid);
2918 unlock_user_struct(target_fl, arg, 0);
bellard9ee1fa22007-11-11 15:11:19 +00002919 ret = get_errno(fcntl(fd, cmd, &fl));
bellard7775e9e2003-05-14 22:46:48 +00002920 if (ret == 0) {
bellard579a97f2007-11-11 14:26:47 +00002921 if (!lock_user_struct(VERIFY_WRITE, target_fl, arg, 0))
2922 return -TARGET_EFAULT;
bellard7775e9e2003-05-14 22:46:48 +00002923 target_fl->l_type = tswap16(fl.l_type);
2924 target_fl->l_whence = tswap16(fl.l_whence);
2925 target_fl->l_start = tswapl(fl.l_start);
2926 target_fl->l_len = tswapl(fl.l_len);
2927 target_fl->l_pid = tswapl(fl.l_pid);
pbrook53a59602006-03-25 19:31:22 +00002928 unlock_user_struct(target_fl, arg, 1);
bellard7775e9e2003-05-14 22:46:48 +00002929 }
2930 break;
ths3b46e622007-09-17 08:09:54 +00002931
bellard7775e9e2003-05-14 22:46:48 +00002932 case TARGET_F_SETLK:
2933 case TARGET_F_SETLKW:
bellard579a97f2007-11-11 14:26:47 +00002934 if (!lock_user_struct(VERIFY_READ, target_fl, arg, 1))
2935 return -TARGET_EFAULT;
bellard7775e9e2003-05-14 22:46:48 +00002936 fl.l_type = tswap16(target_fl->l_type);
2937 fl.l_whence = tswap16(target_fl->l_whence);
2938 fl.l_start = tswapl(target_fl->l_start);
2939 fl.l_len = tswapl(target_fl->l_len);
2940 fl.l_pid = tswapl(target_fl->l_pid);
pbrook53a59602006-03-25 19:31:22 +00002941 unlock_user_struct(target_fl, arg, 0);
bellard9ee1fa22007-11-11 15:11:19 +00002942 ret = get_errno(fcntl(fd, cmd, &fl));
bellard7775e9e2003-05-14 22:46:48 +00002943 break;
ths3b46e622007-09-17 08:09:54 +00002944
bellard7775e9e2003-05-14 22:46:48 +00002945 case TARGET_F_GETLK64:
bellard579a97f2007-11-11 14:26:47 +00002946 if (!lock_user_struct(VERIFY_READ, target_fl64, arg, 1))
2947 return -TARGET_EFAULT;
ths58134272007-03-31 18:59:32 +00002948 fl64.l_type = tswap16(target_fl64->l_type) >> 1;
2949 fl64.l_whence = tswap16(target_fl64->l_whence);
2950 fl64.l_start = tswapl(target_fl64->l_start);
2951 fl64.l_len = tswapl(target_fl64->l_len);
2952 fl64.l_pid = tswap16(target_fl64->l_pid);
2953 unlock_user_struct(target_fl64, arg, 0);
bellard9ee1fa22007-11-11 15:11:19 +00002954 ret = get_errno(fcntl(fd, cmd >> 1, &fl64));
ths43f238d2007-01-05 20:55:49 +00002955 if (ret == 0) {
bellard579a97f2007-11-11 14:26:47 +00002956 if (!lock_user_struct(VERIFY_WRITE, target_fl64, arg, 0))
2957 return -TARGET_EFAULT;
ths43f238d2007-01-05 20:55:49 +00002958 target_fl64->l_type = tswap16(fl64.l_type) >> 1;
2959 target_fl64->l_whence = tswap16(fl64.l_whence);
2960 target_fl64->l_start = tswapl(fl64.l_start);
2961 target_fl64->l_len = tswapl(fl64.l_len);
2962 target_fl64->l_pid = tswapl(fl64.l_pid);
2963 unlock_user_struct(target_fl64, arg, 1);
2964 }
bellard9ee1fa22007-11-11 15:11:19 +00002965 break;
bellard7775e9e2003-05-14 22:46:48 +00002966 case TARGET_F_SETLK64:
2967 case TARGET_F_SETLKW64:
bellard579a97f2007-11-11 14:26:47 +00002968 if (!lock_user_struct(VERIFY_READ, target_fl64, arg, 1))
2969 return -TARGET_EFAULT;
ths43f238d2007-01-05 20:55:49 +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));
bellard7775e9e2003-05-14 22:46:48 +00002977 break;
2978
bellardffa65c32004-01-04 23:57:22 +00002979 case F_GETFL:
bellard9ee1fa22007-11-11 15:11:19 +00002980 ret = get_errno(fcntl(fd, cmd, arg));
2981 if (ret >= 0) {
2982 ret = host_to_target_bitmask(ret, fcntl_flags_tbl);
2983 }
bellardffa65c32004-01-04 23:57:22 +00002984 break;
2985
2986 case F_SETFL:
bellard9ee1fa22007-11-11 15:11:19 +00002987 ret = get_errno(fcntl(fd, cmd, target_to_host_bitmask(arg, fcntl_flags_tbl)));
bellardffa65c32004-01-04 23:57:22 +00002988 break;
2989
bellard7775e9e2003-05-14 22:46:48 +00002990 default:
bellard9ee1fa22007-11-11 15:11:19 +00002991 ret = get_errno(fcntl(fd, cmd, arg));
bellard7775e9e2003-05-14 22:46:48 +00002992 break;
2993 }
2994 return ret;
2995}
2996
bellard67867302003-11-23 17:05:30 +00002997#ifdef USE_UID16
bellard7775e9e2003-05-14 22:46:48 +00002998
bellard67867302003-11-23 17:05:30 +00002999static inline int high2lowuid(int uid)
3000{
3001 if (uid > 65535)
3002 return 65534;
3003 else
3004 return uid;
3005}
3006
3007static inline int high2lowgid(int gid)
3008{
3009 if (gid > 65535)
3010 return 65534;
3011 else
3012 return gid;
3013}
3014
3015static inline int low2highuid(int uid)
3016{
3017 if ((int16_t)uid == -1)
3018 return -1;
3019 else
3020 return uid;
3021}
3022
3023static inline int low2highgid(int gid)
3024{
3025 if ((int16_t)gid == -1)
3026 return -1;
3027 else
3028 return gid;
3029}
3030
3031#endif /* USE_UID16 */
bellard1b6b0292003-03-22 17:31:38 +00003032
bellard31e31b82003-02-18 22:55:36 +00003033void syscall_init(void)
3034{
bellard2ab83ea2003-06-15 19:56:46 +00003035 IOCTLEntry *ie;
3036 const argtype *arg_type;
3037 int size;
thsb92c47c2007-11-01 00:07:38 +00003038 int i;
bellard2ab83ea2003-06-15 19:56:46 +00003039
ths5fafdf22007-09-16 21:08:06 +00003040#define STRUCT(name, list...) thunk_register_struct(STRUCT_ ## name, #name, struct_ ## name ## _def);
3041#define STRUCT_SPECIAL(name) thunk_register_struct_direct(STRUCT_ ## name, #name, &struct_ ## name ## _def);
bellard31e31b82003-02-18 22:55:36 +00003042#include "syscall_types.h"
3043#undef STRUCT
3044#undef STRUCT_SPECIAL
bellard2ab83ea2003-06-15 19:56:46 +00003045
3046 /* we patch the ioctl size if necessary. We rely on the fact that
3047 no ioctl has all the bits at '1' in the size field */
3048 ie = ioctl_entries;
3049 while (ie->target_cmd != 0) {
3050 if (((ie->target_cmd >> TARGET_IOC_SIZESHIFT) & TARGET_IOC_SIZEMASK) ==
3051 TARGET_IOC_SIZEMASK) {
3052 arg_type = ie->arg_type;
3053 if (arg_type[0] != TYPE_PTR) {
ths5fafdf22007-09-16 21:08:06 +00003054 fprintf(stderr, "cannot patch size for ioctl 0x%x\n",
bellard2ab83ea2003-06-15 19:56:46 +00003055 ie->target_cmd);
3056 exit(1);
3057 }
3058 arg_type++;
3059 size = thunk_type_size(arg_type, 0);
ths5fafdf22007-09-16 21:08:06 +00003060 ie->target_cmd = (ie->target_cmd &
bellard2ab83ea2003-06-15 19:56:46 +00003061 ~(TARGET_IOC_SIZEMASK << TARGET_IOC_SIZESHIFT)) |
3062 (size << TARGET_IOC_SIZESHIFT);
3063 }
thsb92c47c2007-11-01 00:07:38 +00003064
3065 /* Build target_to_host_errno_table[] table from
3066 * host_to_target_errno_table[]. */
3067 for (i=0; i < ERRNO_TABLE_SIZE; i++)
3068 target_to_host_errno_table[host_to_target_errno_table[i]] = i;
3069
bellard2ab83ea2003-06-15 19:56:46 +00003070 /* automatic consistency check if same arch */
bellardd2fd1af2007-11-14 18:08:56 +00003071#if defined(__i386__) && defined(TARGET_I386) && defined(TARGET_ABI32)
bellard2ab83ea2003-06-15 19:56:46 +00003072 if (ie->target_cmd != ie->host_cmd) {
ths5fafdf22007-09-16 21:08:06 +00003073 fprintf(stderr, "ERROR: ioctl: target=0x%x host=0x%x\n",
bellard2ab83ea2003-06-15 19:56:46 +00003074 ie->target_cmd, ie->host_cmd);
3075 }
3076#endif
3077 ie++;
3078 }
bellard31e31b82003-02-18 22:55:36 +00003079}
bellardc573ff62004-01-04 15:51:36 +00003080
blueswir1992f48a2007-10-14 16:27:31 +00003081#if TARGET_ABI_BITS == 32
pbrookce4defa2006-02-09 16:49:55 +00003082static inline uint64_t target_offset64(uint32_t word0, uint32_t word1)
3083{
thsaf325d32008-06-10 15:29:15 +00003084#ifdef TARGET_WORDS_BIGENDIAN
pbrookce4defa2006-02-09 16:49:55 +00003085 return ((uint64_t)word0 << 32) | word1;
3086#else
3087 return ((uint64_t)word1 << 32) | word0;
3088#endif
3089}
blueswir1992f48a2007-10-14 16:27:31 +00003090#else /* TARGET_ABI_BITS == 32 */
j_mayer32407102007-09-26 23:01:49 +00003091static inline uint64_t target_offset64(uint64_t word0, uint64_t word1)
3092{
3093 return word0;
3094}
blueswir1992f48a2007-10-14 16:27:31 +00003095#endif /* TARGET_ABI_BITS != 32 */
pbrookce4defa2006-02-09 16:49:55 +00003096
3097#ifdef TARGET_NR_truncate64
blueswir1992f48a2007-10-14 16:27:31 +00003098static inline abi_long target_truncate64(void *cpu_env, const char *arg1,
3099 abi_long arg2,
3100 abi_long arg3,
3101 abi_long arg4)
pbrookce4defa2006-02-09 16:49:55 +00003102{
3103#ifdef TARGET_ARM
3104 if (((CPUARMState *)cpu_env)->eabi)
3105 {
3106 arg2 = arg3;
3107 arg3 = arg4;
3108 }
3109#endif
3110 return get_errno(truncate64(arg1, target_offset64(arg2, arg3)));
3111}
3112#endif
3113
3114#ifdef TARGET_NR_ftruncate64
blueswir1992f48a2007-10-14 16:27:31 +00003115static inline abi_long target_ftruncate64(void *cpu_env, abi_long arg1,
3116 abi_long arg2,
3117 abi_long arg3,
3118 abi_long arg4)
pbrookce4defa2006-02-09 16:49:55 +00003119{
3120#ifdef TARGET_ARM
3121 if (((CPUARMState *)cpu_env)->eabi)
3122 {
3123 arg2 = arg3;
3124 arg3 = arg4;
3125 }
3126#endif
3127 return get_errno(ftruncate64(arg1, target_offset64(arg2, arg3)));
3128}
3129#endif
3130
bellard579a97f2007-11-11 14:26:47 +00003131static inline abi_long target_to_host_timespec(struct timespec *host_ts,
3132 abi_ulong target_addr)
pbrook53a59602006-03-25 19:31:22 +00003133{
3134 struct target_timespec *target_ts;
3135
bellard579a97f2007-11-11 14:26:47 +00003136 if (!lock_user_struct(VERIFY_READ, target_ts, target_addr, 1))
3137 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00003138 host_ts->tv_sec = tswapl(target_ts->tv_sec);
3139 host_ts->tv_nsec = tswapl(target_ts->tv_nsec);
3140 unlock_user_struct(target_ts, target_addr, 0);
bellardb255bfa2008-05-10 21:51:02 +00003141 return 0;
pbrook53a59602006-03-25 19:31:22 +00003142}
3143
bellard579a97f2007-11-11 14:26:47 +00003144static inline abi_long host_to_target_timespec(abi_ulong target_addr,
3145 struct timespec *host_ts)
pbrook53a59602006-03-25 19:31:22 +00003146{
3147 struct target_timespec *target_ts;
3148
bellard579a97f2007-11-11 14:26:47 +00003149 if (!lock_user_struct(VERIFY_WRITE, target_ts, target_addr, 0))
3150 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00003151 target_ts->tv_sec = tswapl(host_ts->tv_sec);
3152 target_ts->tv_nsec = tswapl(host_ts->tv_nsec);
3153 unlock_user_struct(target_ts, target_addr, 1);
bellardb255bfa2008-05-10 21:51:02 +00003154 return 0;
pbrook53a59602006-03-25 19:31:22 +00003155}
3156
balrog6a24a772008-09-20 02:23:36 +00003157#ifdef TARGET_NR_stat64
3158static inline abi_long host_to_target_stat64(void *cpu_env,
3159 abi_ulong target_addr,
3160 struct stat *host_st)
3161{
3162#ifdef TARGET_ARM
3163 if (((CPUARMState *)cpu_env)->eabi) {
3164 struct target_eabi_stat64 *target_st;
3165
3166 if (!lock_user_struct(VERIFY_WRITE, target_st, target_addr, 0))
3167 return -TARGET_EFAULT;
3168 memset(target_st, 0, sizeof(struct target_eabi_stat64));
3169 __put_user(host_st->st_dev, &target_st->st_dev);
3170 __put_user(host_st->st_ino, &target_st->st_ino);
3171#ifdef TARGET_STAT64_HAS_BROKEN_ST_INO
3172 __put_user(host_st->st_ino, &target_st->__st_ino);
3173#endif
3174 __put_user(host_st->st_mode, &target_st->st_mode);
3175 __put_user(host_st->st_nlink, &target_st->st_nlink);
3176 __put_user(host_st->st_uid, &target_st->st_uid);
3177 __put_user(host_st->st_gid, &target_st->st_gid);
3178 __put_user(host_st->st_rdev, &target_st->st_rdev);
3179 __put_user(host_st->st_size, &target_st->st_size);
3180 __put_user(host_st->st_blksize, &target_st->st_blksize);
3181 __put_user(host_st->st_blocks, &target_st->st_blocks);
3182 __put_user(host_st->st_atime, &target_st->target_st_atime);
3183 __put_user(host_st->st_mtime, &target_st->target_st_mtime);
3184 __put_user(host_st->st_ctime, &target_st->target_st_ctime);
3185 unlock_user_struct(target_st, target_addr, 1);
3186 } else
3187#endif
3188 {
3189 struct target_stat64 *target_st;
3190
3191 if (!lock_user_struct(VERIFY_WRITE, target_st, target_addr, 0))
3192 return -TARGET_EFAULT;
3193 memset(target_st, 0, sizeof(struct target_stat64));
3194 __put_user(host_st->st_dev, &target_st->st_dev);
3195 __put_user(host_st->st_ino, &target_st->st_ino);
3196#ifdef TARGET_STAT64_HAS_BROKEN_ST_INO
3197 __put_user(host_st->st_ino, &target_st->__st_ino);
3198#endif
3199 __put_user(host_st->st_mode, &target_st->st_mode);
3200 __put_user(host_st->st_nlink, &target_st->st_nlink);
3201 __put_user(host_st->st_uid, &target_st->st_uid);
3202 __put_user(host_st->st_gid, &target_st->st_gid);
3203 __put_user(host_st->st_rdev, &target_st->st_rdev);
3204 /* XXX: better use of kernel struct */
3205 __put_user(host_st->st_size, &target_st->st_size);
3206 __put_user(host_st->st_blksize, &target_st->st_blksize);
3207 __put_user(host_st->st_blocks, &target_st->st_blocks);
3208 __put_user(host_st->st_atime, &target_st->target_st_atime);
3209 __put_user(host_st->st_mtime, &target_st->target_st_mtime);
3210 __put_user(host_st->st_ctime, &target_st->target_st_ctime);
3211 unlock_user_struct(target_st, target_addr, 1);
3212 }
3213
3214 return 0;
3215}
3216#endif
3217
pbrookbd0c5662008-05-29 14:34:11 +00003218#if defined(USE_NPTL)
3219/* ??? Using host futex calls even when target atomic operations
3220 are not really atomic probably breaks things. However implementing
3221 futexes locally would make futexes shared between multiple processes
3222 tricky. However they're probably useless because guest atomic
3223 operations won't work either. */
blueswir18fcd3692008-08-17 20:26:25 +00003224static int do_futex(target_ulong uaddr, int op, int val, target_ulong timeout,
3225 target_ulong uaddr2, int val3)
pbrookbd0c5662008-05-29 14:34:11 +00003226{
3227 struct timespec ts, *pts;
3228
3229 /* ??? We assume FUTEX_* constants are the same on both host
3230 and target. */
3231 switch (op) {
3232 case FUTEX_WAIT:
3233 if (timeout) {
3234 pts = &ts;
3235 target_to_host_timespec(pts, timeout);
3236 } else {
3237 pts = NULL;
3238 }
3239 return get_errno(sys_futex(g2h(uaddr), FUTEX_WAIT, tswap32(val),
3240 pts, NULL, 0));
3241 case FUTEX_WAKE:
3242 return get_errno(sys_futex(g2h(uaddr), FUTEX_WAKE, val, NULL, NULL, 0));
3243 case FUTEX_FD:
3244 return get_errno(sys_futex(g2h(uaddr), FUTEX_FD, val, NULL, NULL, 0));
3245 case FUTEX_REQUEUE:
3246 return get_errno(sys_futex(g2h(uaddr), FUTEX_REQUEUE, val,
3247 NULL, g2h(uaddr2), 0));
3248 case FUTEX_CMP_REQUEUE:
3249 return get_errno(sys_futex(g2h(uaddr), FUTEX_CMP_REQUEUE, val,
3250 NULL, g2h(uaddr2), tswap32(val3)));
3251 default:
3252 return -TARGET_ENOSYS;
3253 }
3254}
3255#endif
3256
pbrooka745ec62008-05-06 15:36:17 +00003257int get_osversion(void)
3258{
3259 static int osversion;
3260 struct new_utsname buf;
3261 const char *s;
3262 int i, n, tmp;
3263 if (osversion)
3264 return osversion;
3265 if (qemu_uname_release && *qemu_uname_release) {
3266 s = qemu_uname_release;
3267 } else {
3268 if (sys_uname(&buf))
3269 return 0;
3270 s = buf.release;
3271 }
3272 tmp = 0;
3273 for (i = 0; i < 3; i++) {
3274 n = 0;
3275 while (*s >= '0' && *s <= '9') {
3276 n *= 10;
3277 n += *s - '0';
3278 s++;
3279 }
3280 tmp = (tmp << 8) + n;
3281 if (*s == '.')
3282 s++;
3283 }
3284 osversion = tmp;
3285 return osversion;
3286}
3287
ths0da46a62007-10-20 20:23:07 +00003288/* do_syscall() should always have a single exit point at the end so
3289 that actions, such as logging of syscall results, can be performed.
3290 All errnos that do_syscall() returns must be -TARGET_<errcode>. */
blueswir1992f48a2007-10-14 16:27:31 +00003291abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
3292 abi_long arg2, abi_long arg3, abi_long arg4,
3293 abi_long arg5, abi_long arg6)
bellard31e31b82003-02-18 22:55:36 +00003294{
blueswir1992f48a2007-10-14 16:27:31 +00003295 abi_long ret;
bellard31e31b82003-02-18 22:55:36 +00003296 struct stat st;
bellard56c8f682005-11-28 22:28:41 +00003297 struct statfs stfs;
pbrook53a59602006-03-25 19:31:22 +00003298 void *p;
ths3b46e622007-09-17 08:09:54 +00003299
bellard72f03902003-02-18 23:33:18 +00003300#ifdef DEBUG
bellardc573ff62004-01-04 15:51:36 +00003301 gemu_log("syscall %d", num);
bellard72f03902003-02-18 23:33:18 +00003302#endif
thsb92c47c2007-11-01 00:07:38 +00003303 if(do_strace)
3304 print_syscall(num, arg1, arg2, arg3, arg4, arg5, arg6);
3305
bellard31e31b82003-02-18 22:55:36 +00003306 switch(num) {
3307 case TARGET_NR_exit:
bellard7d132992003-03-06 23:23:54 +00003308#ifdef HAVE_GPROF
3309 _mcleanup();
3310#endif
bellarde9009672005-04-26 20:42:36 +00003311 gdb_exit(cpu_env, arg1);
bellard1b6b0292003-03-22 17:31:38 +00003312 /* XXX: should free thread stack and CPU env */
bellard31e31b82003-02-18 22:55:36 +00003313 _exit(arg1);
3314 ret = 0; /* avoid warning */
3315 break;
3316 case TARGET_NR_read:
bellard579a97f2007-11-11 14:26:47 +00003317 if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
3318 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003319 ret = get_errno(read(arg1, p, arg3));
3320 unlock_user(p, arg2, ret);
bellard31e31b82003-02-18 22:55:36 +00003321 break;
3322 case TARGET_NR_write:
bellard579a97f2007-11-11 14:26:47 +00003323 if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
3324 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003325 ret = get_errno(write(arg1, p, arg3));
3326 unlock_user(p, arg2, 0);
bellard31e31b82003-02-18 22:55:36 +00003327 break;
3328 case TARGET_NR_open:
bellard2f619692007-11-16 10:46:05 +00003329 if (!(p = lock_user_string(arg1)))
3330 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003331 ret = get_errno(open(path(p),
bellardffa65c32004-01-04 23:57:22 +00003332 target_to_host_bitmask(arg2, fcntl_flags_tbl),
3333 arg3));
pbrook53a59602006-03-25 19:31:22 +00003334 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003335 break;
ths82424832007-09-24 09:21:55 +00003336#if defined(TARGET_NR_openat) && defined(__NR_openat)
3337 case TARGET_NR_openat:
bellard579a97f2007-11-11 14:26:47 +00003338 if (!(p = lock_user_string(arg2)))
3339 goto efault;
3340 ret = get_errno(sys_openat(arg1,
3341 path(p),
3342 target_to_host_bitmask(arg3, fcntl_flags_tbl),
3343 arg4));
3344 unlock_user(p, arg2, 0);
ths82424832007-09-24 09:21:55 +00003345 break;
3346#endif
bellard31e31b82003-02-18 22:55:36 +00003347 case TARGET_NR_close:
3348 ret = get_errno(close(arg1));
3349 break;
3350 case TARGET_NR_brk:
pbrook53a59602006-03-25 19:31:22 +00003351 ret = do_brk(arg1);
bellard31e31b82003-02-18 22:55:36 +00003352 break;
3353 case TARGET_NR_fork:
pbrookd865bab2008-06-07 22:12:17 +00003354 ret = get_errno(do_fork(cpu_env, SIGCHLD, 0, 0, 0, 0));
bellard31e31b82003-02-18 22:55:36 +00003355 break;
thse5febef2007-04-01 18:31:35 +00003356#ifdef TARGET_NR_waitpid
bellard31e31b82003-02-18 22:55:36 +00003357 case TARGET_NR_waitpid:
3358 {
pbrook53a59602006-03-25 19:31:22 +00003359 int status;
3360 ret = get_errno(waitpid(arg1, &status, arg3));
bellard2f619692007-11-16 10:46:05 +00003361 if (!is_error(ret) && arg2
3362 && put_user_s32(status, arg2))
3363 goto efault;
bellard31e31b82003-02-18 22:55:36 +00003364 }
3365 break;
thse5febef2007-04-01 18:31:35 +00003366#endif
pbrookf0cbb612008-05-30 18:20:05 +00003367#ifdef TARGET_NR_waitid
3368 case TARGET_NR_waitid:
3369 {
3370 siginfo_t info;
3371 info.si_pid = 0;
3372 ret = get_errno(waitid(arg1, arg2, &info, arg4));
3373 if (!is_error(ret) && arg3 && info.si_pid != 0) {
3374 if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_siginfo_t), 0)))
3375 goto efault;
3376 host_to_target_siginfo(p, &info);
3377 unlock_user(p, arg3, sizeof(target_siginfo_t));
3378 }
3379 }
3380 break;
3381#endif
j_mayer7a3148a2007-04-05 07:13:51 +00003382#ifdef TARGET_NR_creat /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00003383 case TARGET_NR_creat:
bellard579a97f2007-11-11 14:26:47 +00003384 if (!(p = lock_user_string(arg1)))
3385 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003386 ret = get_errno(creat(p, arg2));
3387 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003388 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003389#endif
bellard31e31b82003-02-18 22:55:36 +00003390 case TARGET_NR_link:
pbrook53a59602006-03-25 19:31:22 +00003391 {
3392 void * p2;
3393 p = lock_user_string(arg1);
3394 p2 = lock_user_string(arg2);
bellard579a97f2007-11-11 14:26:47 +00003395 if (!p || !p2)
3396 ret = -TARGET_EFAULT;
3397 else
3398 ret = get_errno(link(p, p2));
pbrook53a59602006-03-25 19:31:22 +00003399 unlock_user(p2, arg2, 0);
3400 unlock_user(p, arg1, 0);
3401 }
bellard31e31b82003-02-18 22:55:36 +00003402 break;
ths64f0ce42007-09-24 09:25:06 +00003403#if defined(TARGET_NR_linkat) && defined(__NR_linkat)
3404 case TARGET_NR_linkat:
ths64f0ce42007-09-24 09:25:06 +00003405 {
3406 void * p2 = NULL;
bellard579a97f2007-11-11 14:26:47 +00003407 if (!arg2 || !arg4)
3408 goto efault;
ths64f0ce42007-09-24 09:25:06 +00003409 p = lock_user_string(arg2);
3410 p2 = lock_user_string(arg4);
bellard579a97f2007-11-11 14:26:47 +00003411 if (!p || !p2)
ths0da46a62007-10-20 20:23:07 +00003412 ret = -TARGET_EFAULT;
ths64f0ce42007-09-24 09:25:06 +00003413 else
3414 ret = get_errno(sys_linkat(arg1, p, arg3, p2, arg5));
bellard579a97f2007-11-11 14:26:47 +00003415 unlock_user(p, arg2, 0);
3416 unlock_user(p2, arg4, 0);
ths64f0ce42007-09-24 09:25:06 +00003417 }
3418 break;
3419#endif
bellard31e31b82003-02-18 22:55:36 +00003420 case TARGET_NR_unlink:
bellard579a97f2007-11-11 14:26:47 +00003421 if (!(p = lock_user_string(arg1)))
3422 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003423 ret = get_errno(unlink(p));
3424 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003425 break;
ths8170f562007-09-24 09:24:11 +00003426#if defined(TARGET_NR_unlinkat) && defined(__NR_unlinkat)
3427 case TARGET_NR_unlinkat:
bellard579a97f2007-11-11 14:26:47 +00003428 if (!(p = lock_user_string(arg2)))
3429 goto efault;
3430 ret = get_errno(sys_unlinkat(arg1, p, arg3));
3431 unlock_user(p, arg2, 0);
balroged494d82007-12-11 23:23:52 +00003432 break;
balrogb7d35e62007-12-12 00:40:24 +00003433#endif
bellard31e31b82003-02-18 22:55:36 +00003434 case TARGET_NR_execve:
bellard7854b052003-03-29 17:22:23 +00003435 {
3436 char **argp, **envp;
bellardf7341ff2003-03-30 21:00:25 +00003437 int argc, envc;
blueswir1992f48a2007-10-14 16:27:31 +00003438 abi_ulong gp;
3439 abi_ulong guest_argp;
3440 abi_ulong guest_envp;
3441 abi_ulong addr;
bellard7854b052003-03-29 17:22:23 +00003442 char **q;
3443
bellardf7341ff2003-03-30 21:00:25 +00003444 argc = 0;
pbrook53a59602006-03-25 19:31:22 +00003445 guest_argp = arg2;
pbrookda94d262008-05-30 18:24:00 +00003446 for (gp = guest_argp; gp; gp += sizeof(abi_ulong)) {
ths03aa1972007-12-02 06:28:08 +00003447 if (get_user_ual(addr, gp))
bellard2f619692007-11-16 10:46:05 +00003448 goto efault;
ths03aa1972007-12-02 06:28:08 +00003449 if (!addr)
bellard2f619692007-11-16 10:46:05 +00003450 break;
bellard7854b052003-03-29 17:22:23 +00003451 argc++;
bellard2f619692007-11-16 10:46:05 +00003452 }
bellardf7341ff2003-03-30 21:00:25 +00003453 envc = 0;
pbrook53a59602006-03-25 19:31:22 +00003454 guest_envp = arg3;
pbrookda94d262008-05-30 18:24:00 +00003455 for (gp = guest_envp; gp; gp += sizeof(abi_ulong)) {
ths03aa1972007-12-02 06:28:08 +00003456 if (get_user_ual(addr, gp))
bellard2f619692007-11-16 10:46:05 +00003457 goto efault;
ths03aa1972007-12-02 06:28:08 +00003458 if (!addr)
bellard2f619692007-11-16 10:46:05 +00003459 break;
bellard7854b052003-03-29 17:22:23 +00003460 envc++;
bellard2f619692007-11-16 10:46:05 +00003461 }
bellard7854b052003-03-29 17:22:23 +00003462
bellardf7341ff2003-03-30 21:00:25 +00003463 argp = alloca((argc + 1) * sizeof(void *));
3464 envp = alloca((envc + 1) * sizeof(void *));
bellard7854b052003-03-29 17:22:23 +00003465
pbrookda94d262008-05-30 18:24:00 +00003466 for (gp = guest_argp, q = argp; gp;
blueswir1992f48a2007-10-14 16:27:31 +00003467 gp += sizeof(abi_ulong), q++) {
bellard2f619692007-11-16 10:46:05 +00003468 if (get_user_ual(addr, gp))
3469 goto execve_efault;
pbrook53a59602006-03-25 19:31:22 +00003470 if (!addr)
3471 break;
bellard2f619692007-11-16 10:46:05 +00003472 if (!(*q = lock_user_string(addr)))
3473 goto execve_efault;
pbrook53a59602006-03-25 19:31:22 +00003474 }
bellardf7341ff2003-03-30 21:00:25 +00003475 *q = NULL;
3476
pbrookda94d262008-05-30 18:24:00 +00003477 for (gp = guest_envp, q = envp; gp;
blueswir1992f48a2007-10-14 16:27:31 +00003478 gp += sizeof(abi_ulong), q++) {
bellard2f619692007-11-16 10:46:05 +00003479 if (get_user_ual(addr, gp))
3480 goto execve_efault;
pbrook53a59602006-03-25 19:31:22 +00003481 if (!addr)
3482 break;
bellard2f619692007-11-16 10:46:05 +00003483 if (!(*q = lock_user_string(addr)))
3484 goto execve_efault;
pbrook53a59602006-03-25 19:31:22 +00003485 }
bellardf7341ff2003-03-30 21:00:25 +00003486 *q = NULL;
bellard7854b052003-03-29 17:22:23 +00003487
bellard2f619692007-11-16 10:46:05 +00003488 if (!(p = lock_user_string(arg1)))
3489 goto execve_efault;
pbrook53a59602006-03-25 19:31:22 +00003490 ret = get_errno(execve(p, argp, envp));
3491 unlock_user(p, arg1, 0);
3492
bellard2f619692007-11-16 10:46:05 +00003493 goto execve_end;
3494
3495 execve_efault:
3496 ret = -TARGET_EFAULT;
3497
3498 execve_end:
pbrook53a59602006-03-25 19:31:22 +00003499 for (gp = guest_argp, q = argp; *q;
blueswir1992f48a2007-10-14 16:27:31 +00003500 gp += sizeof(abi_ulong), q++) {
bellard2f619692007-11-16 10:46:05 +00003501 if (get_user_ual(addr, gp)
3502 || !addr)
3503 break;
pbrook53a59602006-03-25 19:31:22 +00003504 unlock_user(*q, addr, 0);
3505 }
3506 for (gp = guest_envp, q = envp; *q;
blueswir1992f48a2007-10-14 16:27:31 +00003507 gp += sizeof(abi_ulong), q++) {
bellard2f619692007-11-16 10:46:05 +00003508 if (get_user_ual(addr, gp)
3509 || !addr)
3510 break;
pbrook53a59602006-03-25 19:31:22 +00003511 unlock_user(*q, addr, 0);
3512 }
bellard7854b052003-03-29 17:22:23 +00003513 }
bellard31e31b82003-02-18 22:55:36 +00003514 break;
3515 case TARGET_NR_chdir:
bellard579a97f2007-11-11 14:26:47 +00003516 if (!(p = lock_user_string(arg1)))
3517 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003518 ret = get_errno(chdir(p));
3519 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003520 break;
bellarda315a142005-01-30 22:59:18 +00003521#ifdef TARGET_NR_time
bellard31e31b82003-02-18 22:55:36 +00003522 case TARGET_NR_time:
3523 {
pbrook53a59602006-03-25 19:31:22 +00003524 time_t host_time;
3525 ret = get_errno(time(&host_time));
bellard2f619692007-11-16 10:46:05 +00003526 if (!is_error(ret)
3527 && arg1
3528 && put_user_sal(host_time, arg1))
3529 goto efault;
bellard31e31b82003-02-18 22:55:36 +00003530 }
3531 break;
bellarda315a142005-01-30 22:59:18 +00003532#endif
bellard31e31b82003-02-18 22:55:36 +00003533 case TARGET_NR_mknod:
bellard579a97f2007-11-11 14:26:47 +00003534 if (!(p = lock_user_string(arg1)))
3535 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003536 ret = get_errno(mknod(p, arg2, arg3));
3537 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003538 break;
ths75ac37a2007-09-24 09:23:05 +00003539#if defined(TARGET_NR_mknodat) && defined(__NR_mknodat)
3540 case TARGET_NR_mknodat:
bellard579a97f2007-11-11 14:26:47 +00003541 if (!(p = lock_user_string(arg2)))
3542 goto efault;
3543 ret = get_errno(sys_mknodat(arg1, p, arg3, arg4));
3544 unlock_user(p, arg2, 0);
ths75ac37a2007-09-24 09:23:05 +00003545 break;
3546#endif
bellard31e31b82003-02-18 22:55:36 +00003547 case TARGET_NR_chmod:
bellard579a97f2007-11-11 14:26:47 +00003548 if (!(p = lock_user_string(arg1)))
3549 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003550 ret = get_errno(chmod(p, arg2));
3551 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003552 break;
bellardebc05482003-09-30 21:08:41 +00003553#ifdef TARGET_NR_break
bellard31e31b82003-02-18 22:55:36 +00003554 case TARGET_NR_break:
3555 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00003556#endif
3557#ifdef TARGET_NR_oldstat
bellard31e31b82003-02-18 22:55:36 +00003558 case TARGET_NR_oldstat:
3559 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00003560#endif
bellard31e31b82003-02-18 22:55:36 +00003561 case TARGET_NR_lseek:
3562 ret = get_errno(lseek(arg1, arg2, arg3));
3563 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003564#ifdef TARGET_NR_getxpid
3565 case TARGET_NR_getxpid:
3566#else
bellard31e31b82003-02-18 22:55:36 +00003567 case TARGET_NR_getpid:
j_mayer7a3148a2007-04-05 07:13:51 +00003568#endif
bellard31e31b82003-02-18 22:55:36 +00003569 ret = get_errno(getpid());
3570 break;
3571 case TARGET_NR_mount:
ths80265912007-02-17 22:25:41 +00003572 {
3573 /* need to look at the data field */
3574 void *p2, *p3;
3575 p = lock_user_string(arg1);
3576 p2 = lock_user_string(arg2);
3577 p3 = lock_user_string(arg3);
bellard579a97f2007-11-11 14:26:47 +00003578 if (!p || !p2 || !p3)
3579 ret = -TARGET_EFAULT;
3580 else
3581 /* FIXME - arg5 should be locked, but it isn't clear how to
3582 * do that since it's not guaranteed to be a NULL-terminated
3583 * string.
3584 */
3585 ret = get_errno(mount(p, p2, p3, (unsigned long)arg4, g2h(arg5)));
3586 unlock_user(p, arg1, 0);
3587 unlock_user(p2, arg2, 0);
3588 unlock_user(p3, arg3, 0);
ths80265912007-02-17 22:25:41 +00003589 break;
3590 }
thse5febef2007-04-01 18:31:35 +00003591#ifdef TARGET_NR_umount
bellard31e31b82003-02-18 22:55:36 +00003592 case TARGET_NR_umount:
bellard579a97f2007-11-11 14:26:47 +00003593 if (!(p = lock_user_string(arg1)))
3594 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003595 ret = get_errno(umount(p));
3596 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003597 break;
thse5febef2007-04-01 18:31:35 +00003598#endif
j_mayer7a3148a2007-04-05 07:13:51 +00003599#ifdef TARGET_NR_stime /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00003600 case TARGET_NR_stime:
3601 {
pbrook53a59602006-03-25 19:31:22 +00003602 time_t host_time;
bellard2f619692007-11-16 10:46:05 +00003603 if (get_user_sal(host_time, arg1))
3604 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003605 ret = get_errno(stime(&host_time));
bellard31e31b82003-02-18 22:55:36 +00003606 }
3607 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003608#endif
bellard31e31b82003-02-18 22:55:36 +00003609 case TARGET_NR_ptrace:
3610 goto unimplemented;
j_mayer7a3148a2007-04-05 07:13:51 +00003611#ifdef TARGET_NR_alarm /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00003612 case TARGET_NR_alarm:
3613 ret = alarm(arg1);
3614 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003615#endif
bellardebc05482003-09-30 21:08:41 +00003616#ifdef TARGET_NR_oldfstat
bellard31e31b82003-02-18 22:55:36 +00003617 case TARGET_NR_oldfstat:
3618 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00003619#endif
j_mayer7a3148a2007-04-05 07:13:51 +00003620#ifdef TARGET_NR_pause /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00003621 case TARGET_NR_pause:
3622 ret = get_errno(pause());
3623 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003624#endif
thse5febef2007-04-01 18:31:35 +00003625#ifdef TARGET_NR_utime
bellard31e31b82003-02-18 22:55:36 +00003626 case TARGET_NR_utime:
bellardebc05482003-09-30 21:08:41 +00003627 {
pbrook53a59602006-03-25 19:31:22 +00003628 struct utimbuf tbuf, *host_tbuf;
3629 struct target_utimbuf *target_tbuf;
3630 if (arg2) {
bellard579a97f2007-11-11 14:26:47 +00003631 if (!lock_user_struct(VERIFY_READ, target_tbuf, arg2, 1))
3632 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003633 tbuf.actime = tswapl(target_tbuf->actime);
3634 tbuf.modtime = tswapl(target_tbuf->modtime);
3635 unlock_user_struct(target_tbuf, arg2, 0);
3636 host_tbuf = &tbuf;
bellardf72e8ff2004-05-03 19:23:07 +00003637 } else {
pbrook53a59602006-03-25 19:31:22 +00003638 host_tbuf = NULL;
bellardf72e8ff2004-05-03 19:23:07 +00003639 }
bellard579a97f2007-11-11 14:26:47 +00003640 if (!(p = lock_user_string(arg1)))
3641 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003642 ret = get_errno(utime(p, host_tbuf));
3643 unlock_user(p, arg1, 0);
bellardebc05482003-09-30 21:08:41 +00003644 }
3645 break;
thse5febef2007-04-01 18:31:35 +00003646#endif
bellard978a66f2004-12-06 22:58:05 +00003647 case TARGET_NR_utimes:
3648 {
bellard978a66f2004-12-06 22:58:05 +00003649 struct timeval *tvp, tv[2];
pbrook53a59602006-03-25 19:31:22 +00003650 if (arg2) {
ths788f5ec2007-12-09 02:37:05 +00003651 if (copy_from_user_timeval(&tv[0], arg2)
3652 || copy_from_user_timeval(&tv[1],
3653 arg2 + sizeof(struct target_timeval)))
3654 goto efault;
bellard978a66f2004-12-06 22:58:05 +00003655 tvp = tv;
3656 } else {
3657 tvp = NULL;
3658 }
bellard579a97f2007-11-11 14:26:47 +00003659 if (!(p = lock_user_string(arg1)))
3660 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003661 ret = get_errno(utimes(p, tvp));
3662 unlock_user(p, arg1, 0);
bellard978a66f2004-12-06 22:58:05 +00003663 }
3664 break;
bellardebc05482003-09-30 21:08:41 +00003665#ifdef TARGET_NR_stty
bellard31e31b82003-02-18 22:55:36 +00003666 case TARGET_NR_stty:
3667 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00003668#endif
3669#ifdef TARGET_NR_gtty
bellard31e31b82003-02-18 22:55:36 +00003670 case TARGET_NR_gtty:
3671 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00003672#endif
bellard31e31b82003-02-18 22:55:36 +00003673 case TARGET_NR_access:
bellard579a97f2007-11-11 14:26:47 +00003674 if (!(p = lock_user_string(arg1)))
3675 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003676 ret = get_errno(access(p, arg2));
3677 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003678 break;
ths92a34c12007-09-24 09:27:49 +00003679#if defined(TARGET_NR_faccessat) && defined(__NR_faccessat)
3680 case TARGET_NR_faccessat:
bellard579a97f2007-11-11 14:26:47 +00003681 if (!(p = lock_user_string(arg2)))
3682 goto efault;
3683 ret = get_errno(sys_faccessat(arg1, p, arg3, arg4));
3684 unlock_user(p, arg2, 0);
ths92a34c12007-09-24 09:27:49 +00003685 break;
3686#endif
j_mayer7a3148a2007-04-05 07:13:51 +00003687#ifdef TARGET_NR_nice /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00003688 case TARGET_NR_nice:
3689 ret = get_errno(nice(arg1));
3690 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003691#endif
bellardebc05482003-09-30 21:08:41 +00003692#ifdef TARGET_NR_ftime
bellard31e31b82003-02-18 22:55:36 +00003693 case TARGET_NR_ftime:
3694 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00003695#endif
bellard31e31b82003-02-18 22:55:36 +00003696 case TARGET_NR_sync:
bellard04369ff2003-03-20 22:33:23 +00003697 sync();
3698 ret = 0;
bellard31e31b82003-02-18 22:55:36 +00003699 break;
3700 case TARGET_NR_kill:
pbrook4cb05962008-05-30 18:05:19 +00003701 ret = get_errno(kill(arg1, target_to_host_signal(arg2)));
bellard31e31b82003-02-18 22:55:36 +00003702 break;
3703 case TARGET_NR_rename:
pbrook53a59602006-03-25 19:31:22 +00003704 {
3705 void *p2;
3706 p = lock_user_string(arg1);
3707 p2 = lock_user_string(arg2);
bellard579a97f2007-11-11 14:26:47 +00003708 if (!p || !p2)
3709 ret = -TARGET_EFAULT;
3710 else
3711 ret = get_errno(rename(p, p2));
pbrook53a59602006-03-25 19:31:22 +00003712 unlock_user(p2, arg2, 0);
3713 unlock_user(p, arg1, 0);
3714 }
bellard31e31b82003-02-18 22:55:36 +00003715 break;
ths722183f2007-09-24 09:24:37 +00003716#if defined(TARGET_NR_renameat) && defined(__NR_renameat)
3717 case TARGET_NR_renameat:
ths722183f2007-09-24 09:24:37 +00003718 {
bellard579a97f2007-11-11 14:26:47 +00003719 void *p2;
ths722183f2007-09-24 09:24:37 +00003720 p = lock_user_string(arg2);
3721 p2 = lock_user_string(arg4);
bellard579a97f2007-11-11 14:26:47 +00003722 if (!p || !p2)
ths0da46a62007-10-20 20:23:07 +00003723 ret = -TARGET_EFAULT;
ths722183f2007-09-24 09:24:37 +00003724 else
3725 ret = get_errno(sys_renameat(arg1, p, arg3, p2));
bellard579a97f2007-11-11 14:26:47 +00003726 unlock_user(p2, arg4, 0);
3727 unlock_user(p, arg2, 0);
ths722183f2007-09-24 09:24:37 +00003728 }
3729 break;
3730#endif
bellard31e31b82003-02-18 22:55:36 +00003731 case TARGET_NR_mkdir:
bellard579a97f2007-11-11 14:26:47 +00003732 if (!(p = lock_user_string(arg1)))
3733 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003734 ret = get_errno(mkdir(p, arg2));
3735 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003736 break;
ths4472ad02007-09-24 09:22:32 +00003737#if defined(TARGET_NR_mkdirat) && defined(__NR_mkdirat)
3738 case TARGET_NR_mkdirat:
bellard579a97f2007-11-11 14:26:47 +00003739 if (!(p = lock_user_string(arg2)))
3740 goto efault;
3741 ret = get_errno(sys_mkdirat(arg1, p, arg3));
3742 unlock_user(p, arg2, 0);
ths4472ad02007-09-24 09:22:32 +00003743 break;
3744#endif
bellard31e31b82003-02-18 22:55:36 +00003745 case TARGET_NR_rmdir:
bellard579a97f2007-11-11 14:26:47 +00003746 if (!(p = lock_user_string(arg1)))
3747 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003748 ret = get_errno(rmdir(p));
3749 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003750 break;
3751 case TARGET_NR_dup:
3752 ret = get_errno(dup(arg1));
3753 break;
3754 case TARGET_NR_pipe:
3755 {
pbrook53a59602006-03-25 19:31:22 +00003756 int host_pipe[2];
3757 ret = get_errno(pipe(host_pipe));
bellard31e31b82003-02-18 22:55:36 +00003758 if (!is_error(ret)) {
thsc12ab052007-06-01 11:50:36 +00003759#if defined(TARGET_MIPS)
thsead93602007-09-06 00:18:15 +00003760 CPUMIPSState *env = (CPUMIPSState*)cpu_env;
thsb5dc7732008-06-27 10:02:35 +00003761 env->active_tc.gpr[3] = host_pipe[1];
thsc12ab052007-06-01 11:50:36 +00003762 ret = host_pipe[0];
aurel32b5eff352008-03-11 23:30:22 +00003763#elif defined(TARGET_SH4)
3764 ((CPUSH4State*)cpu_env)->gregs[1] = host_pipe[1];
3765 ret = host_pipe[0];
thsc12ab052007-06-01 11:50:36 +00003766#else
bellard2f619692007-11-16 10:46:05 +00003767 if (put_user_s32(host_pipe[0], arg1)
3768 || put_user_s32(host_pipe[1], arg1 + sizeof(host_pipe[0])))
3769 goto efault;
thsc12ab052007-06-01 11:50:36 +00003770#endif
bellard31e31b82003-02-18 22:55:36 +00003771 }
3772 }
3773 break;
3774 case TARGET_NR_times:
bellard32f36bc2003-03-30 21:29:48 +00003775 {
pbrook53a59602006-03-25 19:31:22 +00003776 struct target_tms *tmsp;
bellard32f36bc2003-03-30 21:29:48 +00003777 struct tms tms;
3778 ret = get_errno(times(&tms));
pbrook53a59602006-03-25 19:31:22 +00003779 if (arg1) {
bellard579a97f2007-11-11 14:26:47 +00003780 tmsp = lock_user(VERIFY_WRITE, arg1, sizeof(struct target_tms), 0);
3781 if (!tmsp)
3782 goto efault;
bellardc596ed12003-07-13 17:32:31 +00003783 tmsp->tms_utime = tswapl(host_to_target_clock_t(tms.tms_utime));
3784 tmsp->tms_stime = tswapl(host_to_target_clock_t(tms.tms_stime));
3785 tmsp->tms_cutime = tswapl(host_to_target_clock_t(tms.tms_cutime));
3786 tmsp->tms_cstime = tswapl(host_to_target_clock_t(tms.tms_cstime));
bellard32f36bc2003-03-30 21:29:48 +00003787 }
bellardc596ed12003-07-13 17:32:31 +00003788 if (!is_error(ret))
3789 ret = host_to_target_clock_t(ret);
bellard32f36bc2003-03-30 21:29:48 +00003790 }
3791 break;
bellardebc05482003-09-30 21:08:41 +00003792#ifdef TARGET_NR_prof
bellard31e31b82003-02-18 22:55:36 +00003793 case TARGET_NR_prof:
3794 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00003795#endif
thse5febef2007-04-01 18:31:35 +00003796#ifdef TARGET_NR_signal
bellard31e31b82003-02-18 22:55:36 +00003797 case TARGET_NR_signal:
3798 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00003799#endif
bellard31e31b82003-02-18 22:55:36 +00003800 case TARGET_NR_acct:
bellard579a97f2007-11-11 14:26:47 +00003801 if (!(p = lock_user_string(arg1)))
3802 goto efault;
pbrook24836682006-04-16 14:14:53 +00003803 ret = get_errno(acct(path(p)));
3804 unlock_user(p, arg1, 0);
3805 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003806#ifdef TARGET_NR_umount2 /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00003807 case TARGET_NR_umount2:
bellard579a97f2007-11-11 14:26:47 +00003808 if (!(p = lock_user_string(arg1)))
3809 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003810 ret = get_errno(umount2(p, arg2));
3811 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003812 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003813#endif
bellardebc05482003-09-30 21:08:41 +00003814#ifdef TARGET_NR_lock
bellard31e31b82003-02-18 22:55:36 +00003815 case TARGET_NR_lock:
3816 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00003817#endif
bellard31e31b82003-02-18 22:55:36 +00003818 case TARGET_NR_ioctl:
3819 ret = do_ioctl(arg1, arg2, arg3);
3820 break;
3821 case TARGET_NR_fcntl:
bellard9ee1fa22007-11-11 15:11:19 +00003822 ret = do_fcntl(arg1, arg2, arg3);
bellard31e31b82003-02-18 22:55:36 +00003823 break;
bellardebc05482003-09-30 21:08:41 +00003824#ifdef TARGET_NR_mpx
bellard31e31b82003-02-18 22:55:36 +00003825 case TARGET_NR_mpx:
3826 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00003827#endif
bellard31e31b82003-02-18 22:55:36 +00003828 case TARGET_NR_setpgid:
3829 ret = get_errno(setpgid(arg1, arg2));
3830 break;
bellardebc05482003-09-30 21:08:41 +00003831#ifdef TARGET_NR_ulimit
bellard31e31b82003-02-18 22:55:36 +00003832 case TARGET_NR_ulimit:
3833 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00003834#endif
3835#ifdef TARGET_NR_oldolduname
bellard31e31b82003-02-18 22:55:36 +00003836 case TARGET_NR_oldolduname:
3837 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00003838#endif
bellard31e31b82003-02-18 22:55:36 +00003839 case TARGET_NR_umask:
3840 ret = get_errno(umask(arg1));
3841 break;
3842 case TARGET_NR_chroot:
bellard579a97f2007-11-11 14:26:47 +00003843 if (!(p = lock_user_string(arg1)))
3844 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003845 ret = get_errno(chroot(p));
3846 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003847 break;
3848 case TARGET_NR_ustat:
3849 goto unimplemented;
3850 case TARGET_NR_dup2:
3851 ret = get_errno(dup2(arg1, arg2));
3852 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003853#ifdef TARGET_NR_getppid /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00003854 case TARGET_NR_getppid:
3855 ret = get_errno(getppid());
3856 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003857#endif
bellard31e31b82003-02-18 22:55:36 +00003858 case TARGET_NR_getpgrp:
3859 ret = get_errno(getpgrp());
3860 break;
3861 case TARGET_NR_setsid:
3862 ret = get_errno(setsid());
3863 break;
thse5febef2007-04-01 18:31:35 +00003864#ifdef TARGET_NR_sigaction
bellard31e31b82003-02-18 22:55:36 +00003865 case TARGET_NR_sigaction:
bellard31e31b82003-02-18 22:55:36 +00003866 {
ths388bb212007-05-13 13:58:00 +00003867#if !defined(TARGET_MIPS)
pbrook53a59602006-03-25 19:31:22 +00003868 struct target_old_sigaction *old_act;
bellard66fb9762003-03-23 01:06:05 +00003869 struct target_sigaction act, oact, *pact;
pbrook53a59602006-03-25 19:31:22 +00003870 if (arg2) {
bellard579a97f2007-11-11 14:26:47 +00003871 if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1))
3872 goto efault;
bellard66fb9762003-03-23 01:06:05 +00003873 act._sa_handler = old_act->_sa_handler;
3874 target_siginitset(&act.sa_mask, old_act->sa_mask);
3875 act.sa_flags = old_act->sa_flags;
3876 act.sa_restorer = old_act->sa_restorer;
pbrook53a59602006-03-25 19:31:22 +00003877 unlock_user_struct(old_act, arg2, 0);
bellard66fb9762003-03-23 01:06:05 +00003878 pact = &act;
3879 } else {
3880 pact = NULL;
3881 }
3882 ret = get_errno(do_sigaction(arg1, pact, &oact));
pbrook53a59602006-03-25 19:31:22 +00003883 if (!is_error(ret) && arg3) {
bellard579a97f2007-11-11 14:26:47 +00003884 if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0))
3885 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003886 old_act->_sa_handler = oact._sa_handler;
3887 old_act->sa_mask = oact.sa_mask.sig[0];
3888 old_act->sa_flags = oact.sa_flags;
3889 old_act->sa_restorer = oact.sa_restorer;
3890 unlock_user_struct(old_act, arg3, 1);
bellard66fb9762003-03-23 01:06:05 +00003891 }
ths388bb212007-05-13 13:58:00 +00003892#else
bellard106ec872006-06-27 21:08:10 +00003893 struct target_sigaction act, oact, *pact, *old_act;
3894
3895 if (arg2) {
bellard579a97f2007-11-11 14:26:47 +00003896 if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1))
3897 goto efault;
bellard106ec872006-06-27 21:08:10 +00003898 act._sa_handler = old_act->_sa_handler;
3899 target_siginitset(&act.sa_mask, old_act->sa_mask.sig[0]);
3900 act.sa_flags = old_act->sa_flags;
3901 unlock_user_struct(old_act, arg2, 0);
3902 pact = &act;
3903 } else {
3904 pact = NULL;
3905 }
3906
3907 ret = get_errno(do_sigaction(arg1, pact, &oact));
3908
3909 if (!is_error(ret) && arg3) {
bellard579a97f2007-11-11 14:26:47 +00003910 if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0))
3911 goto efault;
bellard106ec872006-06-27 21:08:10 +00003912 old_act->_sa_handler = oact._sa_handler;
3913 old_act->sa_flags = oact.sa_flags;
3914 old_act->sa_mask.sig[0] = oact.sa_mask.sig[0];
3915 old_act->sa_mask.sig[1] = 0;
3916 old_act->sa_mask.sig[2] = 0;
3917 old_act->sa_mask.sig[3] = 0;
3918 unlock_user_struct(old_act, arg3, 1);
3919 }
ths388bb212007-05-13 13:58:00 +00003920#endif
bellard31e31b82003-02-18 22:55:36 +00003921 }
3922 break;
thse5febef2007-04-01 18:31:35 +00003923#endif
bellard66fb9762003-03-23 01:06:05 +00003924 case TARGET_NR_rt_sigaction:
pbrook53a59602006-03-25 19:31:22 +00003925 {
3926 struct target_sigaction *act;
3927 struct target_sigaction *oact;
3928
bellard579a97f2007-11-11 14:26:47 +00003929 if (arg2) {
3930 if (!lock_user_struct(VERIFY_READ, act, arg2, 1))
3931 goto efault;
3932 } else
pbrook53a59602006-03-25 19:31:22 +00003933 act = NULL;
bellard579a97f2007-11-11 14:26:47 +00003934 if (arg3) {
3935 if (!lock_user_struct(VERIFY_WRITE, oact, arg3, 0)) {
3936 ret = -TARGET_EFAULT;
3937 goto rt_sigaction_fail;
3938 }
3939 } else
pbrook53a59602006-03-25 19:31:22 +00003940 oact = NULL;
3941 ret = get_errno(do_sigaction(arg1, act, oact));
bellard579a97f2007-11-11 14:26:47 +00003942 rt_sigaction_fail:
3943 if (act)
pbrook53a59602006-03-25 19:31:22 +00003944 unlock_user_struct(act, arg2, 0);
bellard579a97f2007-11-11 14:26:47 +00003945 if (oact)
pbrook53a59602006-03-25 19:31:22 +00003946 unlock_user_struct(oact, arg3, 1);
3947 }
bellard66fb9762003-03-23 01:06:05 +00003948 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003949#ifdef TARGET_NR_sgetmask /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00003950 case TARGET_NR_sgetmask:
bellard66fb9762003-03-23 01:06:05 +00003951 {
3952 sigset_t cur_set;
blueswir1992f48a2007-10-14 16:27:31 +00003953 abi_ulong target_set;
bellard66fb9762003-03-23 01:06:05 +00003954 sigprocmask(0, NULL, &cur_set);
3955 host_to_target_old_sigset(&target_set, &cur_set);
3956 ret = target_set;
3957 }
3958 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003959#endif
3960#ifdef TARGET_NR_ssetmask /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00003961 case TARGET_NR_ssetmask:
bellard66fb9762003-03-23 01:06:05 +00003962 {
3963 sigset_t set, oset, cur_set;
blueswir1992f48a2007-10-14 16:27:31 +00003964 abi_ulong target_set = arg1;
bellard66fb9762003-03-23 01:06:05 +00003965 sigprocmask(0, NULL, &cur_set);
3966 target_to_host_old_sigset(&set, &target_set);
3967 sigorset(&set, &set, &cur_set);
3968 sigprocmask(SIG_SETMASK, &set, &oset);
3969 host_to_target_old_sigset(&target_set, &oset);
3970 ret = target_set;
3971 }
3972 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003973#endif
thse5febef2007-04-01 18:31:35 +00003974#ifdef TARGET_NR_sigprocmask
bellard66fb9762003-03-23 01:06:05 +00003975 case TARGET_NR_sigprocmask:
3976 {
3977 int how = arg1;
3978 sigset_t set, oldset, *set_ptr;
ths3b46e622007-09-17 08:09:54 +00003979
pbrook53a59602006-03-25 19:31:22 +00003980 if (arg2) {
bellard66fb9762003-03-23 01:06:05 +00003981 switch(how) {
3982 case TARGET_SIG_BLOCK:
3983 how = SIG_BLOCK;
3984 break;
3985 case TARGET_SIG_UNBLOCK:
3986 how = SIG_UNBLOCK;
3987 break;
3988 case TARGET_SIG_SETMASK:
3989 how = SIG_SETMASK;
3990 break;
3991 default:
ths0da46a62007-10-20 20:23:07 +00003992 ret = -TARGET_EINVAL;
bellard66fb9762003-03-23 01:06:05 +00003993 goto fail;
3994 }
bellard579a97f2007-11-11 14:26:47 +00003995 if (!(p = lock_user(VERIFY_READ, arg2, sizeof(target_sigset_t), 1)))
3996 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003997 target_to_host_old_sigset(&set, p);
3998 unlock_user(p, arg2, 0);
bellard66fb9762003-03-23 01:06:05 +00003999 set_ptr = &set;
4000 } else {
4001 how = 0;
4002 set_ptr = NULL;
4003 }
4004 ret = get_errno(sigprocmask(arg1, set_ptr, &oldset));
pbrook53a59602006-03-25 19:31:22 +00004005 if (!is_error(ret) && arg3) {
bellard579a97f2007-11-11 14:26:47 +00004006 if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0)))
4007 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004008 host_to_target_old_sigset(p, &oldset);
4009 unlock_user(p, arg3, sizeof(target_sigset_t));
bellard66fb9762003-03-23 01:06:05 +00004010 }
4011 }
4012 break;
thse5febef2007-04-01 18:31:35 +00004013#endif
bellard66fb9762003-03-23 01:06:05 +00004014 case TARGET_NR_rt_sigprocmask:
4015 {
4016 int how = arg1;
4017 sigset_t set, oldset, *set_ptr;
ths3b46e622007-09-17 08:09:54 +00004018
pbrook53a59602006-03-25 19:31:22 +00004019 if (arg2) {
bellard66fb9762003-03-23 01:06:05 +00004020 switch(how) {
4021 case TARGET_SIG_BLOCK:
4022 how = SIG_BLOCK;
4023 break;
4024 case TARGET_SIG_UNBLOCK:
4025 how = SIG_UNBLOCK;
4026 break;
4027 case TARGET_SIG_SETMASK:
4028 how = SIG_SETMASK;
4029 break;
4030 default:
ths0da46a62007-10-20 20:23:07 +00004031 ret = -TARGET_EINVAL;
bellard66fb9762003-03-23 01:06:05 +00004032 goto fail;
4033 }
bellard579a97f2007-11-11 14:26:47 +00004034 if (!(p = lock_user(VERIFY_READ, arg2, sizeof(target_sigset_t), 1)))
4035 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004036 target_to_host_sigset(&set, p);
4037 unlock_user(p, arg2, 0);
bellard66fb9762003-03-23 01:06:05 +00004038 set_ptr = &set;
4039 } else {
4040 how = 0;
4041 set_ptr = NULL;
4042 }
4043 ret = get_errno(sigprocmask(how, set_ptr, &oldset));
pbrook53a59602006-03-25 19:31:22 +00004044 if (!is_error(ret) && arg3) {
bellard579a97f2007-11-11 14:26:47 +00004045 if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0)))
4046 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004047 host_to_target_sigset(p, &oldset);
4048 unlock_user(p, arg3, sizeof(target_sigset_t));
bellard66fb9762003-03-23 01:06:05 +00004049 }
4050 }
4051 break;
thse5febef2007-04-01 18:31:35 +00004052#ifdef TARGET_NR_sigpending
bellard66fb9762003-03-23 01:06:05 +00004053 case TARGET_NR_sigpending:
4054 {
4055 sigset_t set;
4056 ret = get_errno(sigpending(&set));
4057 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00004058 if (!(p = lock_user(VERIFY_WRITE, arg1, sizeof(target_sigset_t), 0)))
4059 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004060 host_to_target_old_sigset(p, &set);
4061 unlock_user(p, arg1, sizeof(target_sigset_t));
bellard66fb9762003-03-23 01:06:05 +00004062 }
4063 }
4064 break;
thse5febef2007-04-01 18:31:35 +00004065#endif
bellard66fb9762003-03-23 01:06:05 +00004066 case TARGET_NR_rt_sigpending:
4067 {
4068 sigset_t set;
4069 ret = get_errno(sigpending(&set));
4070 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00004071 if (!(p = lock_user(VERIFY_WRITE, arg1, sizeof(target_sigset_t), 0)))
4072 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004073 host_to_target_sigset(p, &set);
4074 unlock_user(p, arg1, sizeof(target_sigset_t));
bellard66fb9762003-03-23 01:06:05 +00004075 }
4076 }
4077 break;
thse5febef2007-04-01 18:31:35 +00004078#ifdef TARGET_NR_sigsuspend
bellard66fb9762003-03-23 01:06:05 +00004079 case TARGET_NR_sigsuspend:
4080 {
4081 sigset_t set;
bellard579a97f2007-11-11 14:26:47 +00004082 if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
4083 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004084 target_to_host_old_sigset(&set, p);
4085 unlock_user(p, arg1, 0);
bellard66fb9762003-03-23 01:06:05 +00004086 ret = get_errno(sigsuspend(&set));
4087 }
4088 break;
thse5febef2007-04-01 18:31:35 +00004089#endif
bellard66fb9762003-03-23 01:06:05 +00004090 case TARGET_NR_rt_sigsuspend:
4091 {
4092 sigset_t set;
bellard579a97f2007-11-11 14:26:47 +00004093 if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
4094 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004095 target_to_host_sigset(&set, p);
4096 unlock_user(p, arg1, 0);
bellard66fb9762003-03-23 01:06:05 +00004097 ret = get_errno(sigsuspend(&set));
4098 }
4099 break;
4100 case TARGET_NR_rt_sigtimedwait:
4101 {
bellard66fb9762003-03-23 01:06:05 +00004102 sigset_t set;
4103 struct timespec uts, *puts;
4104 siginfo_t uinfo;
ths3b46e622007-09-17 08:09:54 +00004105
bellard579a97f2007-11-11 14:26:47 +00004106 if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
4107 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004108 target_to_host_sigset(&set, p);
4109 unlock_user(p, arg1, 0);
4110 if (arg3) {
bellard66fb9762003-03-23 01:06:05 +00004111 puts = &uts;
pbrook53a59602006-03-25 19:31:22 +00004112 target_to_host_timespec(puts, arg3);
bellard66fb9762003-03-23 01:06:05 +00004113 } else {
4114 puts = NULL;
4115 }
4116 ret = get_errno(sigtimedwait(&set, &uinfo, puts));
pbrook53a59602006-03-25 19:31:22 +00004117 if (!is_error(ret) && arg2) {
pbrooke1e3f302008-05-30 21:53:38 +00004118 if (!(p = lock_user(VERIFY_WRITE, arg2, sizeof(target_siginfo_t), 0)))
bellard579a97f2007-11-11 14:26:47 +00004119 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004120 host_to_target_siginfo(p, &uinfo);
pbrooke1e3f302008-05-30 21:53:38 +00004121 unlock_user(p, arg2, sizeof(target_siginfo_t));
bellard66fb9762003-03-23 01:06:05 +00004122 }
4123 }
4124 break;
4125 case TARGET_NR_rt_sigqueueinfo:
4126 {
4127 siginfo_t uinfo;
bellard579a97f2007-11-11 14:26:47 +00004128 if (!(p = lock_user(VERIFY_READ, arg3, sizeof(target_sigset_t), 1)))
4129 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004130 target_to_host_siginfo(&uinfo, p);
4131 unlock_user(p, arg1, 0);
bellard66fb9762003-03-23 01:06:05 +00004132 ret = get_errno(sys_rt_sigqueueinfo(arg1, arg2, &uinfo));
4133 }
4134 break;
thse5febef2007-04-01 18:31:35 +00004135#ifdef TARGET_NR_sigreturn
bellard66fb9762003-03-23 01:06:05 +00004136 case TARGET_NR_sigreturn:
4137 /* NOTE: ret is eax, so not transcoding must be done */
4138 ret = do_sigreturn(cpu_env);
4139 break;
thse5febef2007-04-01 18:31:35 +00004140#endif
bellard66fb9762003-03-23 01:06:05 +00004141 case TARGET_NR_rt_sigreturn:
4142 /* NOTE: ret is eax, so not transcoding must be done */
4143 ret = do_rt_sigreturn(cpu_env);
4144 break;
bellard31e31b82003-02-18 22:55:36 +00004145 case TARGET_NR_sethostname:
bellard579a97f2007-11-11 14:26:47 +00004146 if (!(p = lock_user_string(arg1)))
4147 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004148 ret = get_errno(sethostname(p, arg2));
4149 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004150 break;
4151 case TARGET_NR_setrlimit:
bellard9de5e442003-03-23 16:49:39 +00004152 {
4153 /* XXX: convert resource ? */
4154 int resource = arg1;
pbrook53a59602006-03-25 19:31:22 +00004155 struct target_rlimit *target_rlim;
bellard9de5e442003-03-23 16:49:39 +00004156 struct rlimit rlim;
bellard579a97f2007-11-11 14:26:47 +00004157 if (!lock_user_struct(VERIFY_READ, target_rlim, arg2, 1))
4158 goto efault;
bellard9de5e442003-03-23 16:49:39 +00004159 rlim.rlim_cur = tswapl(target_rlim->rlim_cur);
4160 rlim.rlim_max = tswapl(target_rlim->rlim_max);
pbrook53a59602006-03-25 19:31:22 +00004161 unlock_user_struct(target_rlim, arg2, 0);
bellard9de5e442003-03-23 16:49:39 +00004162 ret = get_errno(setrlimit(resource, &rlim));
4163 }
4164 break;
bellard31e31b82003-02-18 22:55:36 +00004165 case TARGET_NR_getrlimit:
bellard9de5e442003-03-23 16:49:39 +00004166 {
4167 /* XXX: convert resource ? */
4168 int resource = arg1;
pbrook53a59602006-03-25 19:31:22 +00004169 struct target_rlimit *target_rlim;
bellard9de5e442003-03-23 16:49:39 +00004170 struct rlimit rlim;
ths3b46e622007-09-17 08:09:54 +00004171
bellard9de5e442003-03-23 16:49:39 +00004172 ret = get_errno(getrlimit(resource, &rlim));
4173 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00004174 if (!lock_user_struct(VERIFY_WRITE, target_rlim, arg2, 0))
4175 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004176 rlim.rlim_cur = tswapl(target_rlim->rlim_cur);
4177 rlim.rlim_max = tswapl(target_rlim->rlim_max);
4178 unlock_user_struct(target_rlim, arg2, 1);
bellard9de5e442003-03-23 16:49:39 +00004179 }
4180 }
4181 break;
bellard31e31b82003-02-18 22:55:36 +00004182 case TARGET_NR_getrusage:
bellardb4091862003-05-16 15:39:34 +00004183 {
4184 struct rusage rusage;
bellardb4091862003-05-16 15:39:34 +00004185 ret = get_errno(getrusage(arg1, &rusage));
4186 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00004187 host_to_target_rusage(arg2, &rusage);
bellardb4091862003-05-16 15:39:34 +00004188 }
4189 }
4190 break;
bellard31e31b82003-02-18 22:55:36 +00004191 case TARGET_NR_gettimeofday:
4192 {
bellard31e31b82003-02-18 22:55:36 +00004193 struct timeval tv;
4194 ret = get_errno(gettimeofday(&tv, NULL));
4195 if (!is_error(ret)) {
ths788f5ec2007-12-09 02:37:05 +00004196 if (copy_to_user_timeval(arg1, &tv))
4197 goto efault;
bellard31e31b82003-02-18 22:55:36 +00004198 }
4199 }
4200 break;
4201 case TARGET_NR_settimeofday:
4202 {
bellard31e31b82003-02-18 22:55:36 +00004203 struct timeval tv;
ths788f5ec2007-12-09 02:37:05 +00004204 if (copy_from_user_timeval(&tv, arg1))
4205 goto efault;
bellard31e31b82003-02-18 22:55:36 +00004206 ret = get_errno(settimeofday(&tv, NULL));
4207 }
4208 break;
bellard048f6b42005-11-26 18:47:20 +00004209#ifdef TARGET_NR_select
bellard31e31b82003-02-18 22:55:36 +00004210 case TARGET_NR_select:
bellardf2674e32003-07-09 12:26:09 +00004211 {
pbrook53a59602006-03-25 19:31:22 +00004212 struct target_sel_arg_struct *sel;
blueswir1992f48a2007-10-14 16:27:31 +00004213 abi_ulong inp, outp, exp, tvp;
pbrook53a59602006-03-25 19:31:22 +00004214 long nsel;
4215
bellard579a97f2007-11-11 14:26:47 +00004216 if (!lock_user_struct(VERIFY_READ, sel, arg1, 1))
4217 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004218 nsel = tswapl(sel->n);
4219 inp = tswapl(sel->inp);
4220 outp = tswapl(sel->outp);
4221 exp = tswapl(sel->exp);
4222 tvp = tswapl(sel->tvp);
4223 unlock_user_struct(sel, arg1, 0);
4224 ret = do_select(nsel, inp, outp, exp, tvp);
bellardf2674e32003-07-09 12:26:09 +00004225 }
4226 break;
bellard048f6b42005-11-26 18:47:20 +00004227#endif
bellard31e31b82003-02-18 22:55:36 +00004228 case TARGET_NR_symlink:
pbrook53a59602006-03-25 19:31:22 +00004229 {
4230 void *p2;
4231 p = lock_user_string(arg1);
4232 p2 = lock_user_string(arg2);
bellard579a97f2007-11-11 14:26:47 +00004233 if (!p || !p2)
4234 ret = -TARGET_EFAULT;
4235 else
4236 ret = get_errno(symlink(p, p2));
pbrook53a59602006-03-25 19:31:22 +00004237 unlock_user(p2, arg2, 0);
4238 unlock_user(p, arg1, 0);
4239 }
bellard31e31b82003-02-18 22:55:36 +00004240 break;
thsf0b62432007-09-24 09:25:40 +00004241#if defined(TARGET_NR_symlinkat) && defined(__NR_symlinkat)
4242 case TARGET_NR_symlinkat:
thsf0b62432007-09-24 09:25:40 +00004243 {
bellard579a97f2007-11-11 14:26:47 +00004244 void *p2;
thsf0b62432007-09-24 09:25:40 +00004245 p = lock_user_string(arg1);
4246 p2 = lock_user_string(arg3);
bellard579a97f2007-11-11 14:26:47 +00004247 if (!p || !p2)
ths0da46a62007-10-20 20:23:07 +00004248 ret = -TARGET_EFAULT;
thsf0b62432007-09-24 09:25:40 +00004249 else
4250 ret = get_errno(sys_symlinkat(p, arg2, p2));
bellard579a97f2007-11-11 14:26:47 +00004251 unlock_user(p2, arg3, 0);
4252 unlock_user(p, arg1, 0);
thsf0b62432007-09-24 09:25:40 +00004253 }
4254 break;
4255#endif
bellardebc05482003-09-30 21:08:41 +00004256#ifdef TARGET_NR_oldlstat
bellard31e31b82003-02-18 22:55:36 +00004257 case TARGET_NR_oldlstat:
4258 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004259#endif
bellard31e31b82003-02-18 22:55:36 +00004260 case TARGET_NR_readlink:
pbrook53a59602006-03-25 19:31:22 +00004261 {
4262 void *p2;
4263 p = lock_user_string(arg1);
bellard579a97f2007-11-11 14:26:47 +00004264 p2 = lock_user(VERIFY_WRITE, arg2, arg3, 0);
4265 if (!p || !p2)
4266 ret = -TARGET_EFAULT;
4267 else
4268 ret = get_errno(readlink(path(p), p2, arg3));
pbrook53a59602006-03-25 19:31:22 +00004269 unlock_user(p2, arg2, ret);
4270 unlock_user(p, arg1, 0);
4271 }
bellard31e31b82003-02-18 22:55:36 +00004272 break;
ths5e0ccb12007-09-24 09:26:10 +00004273#if defined(TARGET_NR_readlinkat) && defined(__NR_readlinkat)
4274 case TARGET_NR_readlinkat:
ths5e0ccb12007-09-24 09:26:10 +00004275 {
bellard579a97f2007-11-11 14:26:47 +00004276 void *p2;
ths5e0ccb12007-09-24 09:26:10 +00004277 p = lock_user_string(arg2);
bellard579a97f2007-11-11 14:26:47 +00004278 p2 = lock_user(VERIFY_WRITE, arg3, arg4, 0);
4279 if (!p || !p2)
ths0da46a62007-10-20 20:23:07 +00004280 ret = -TARGET_EFAULT;
ths5e0ccb12007-09-24 09:26:10 +00004281 else
4282 ret = get_errno(sys_readlinkat(arg1, path(p), p2, arg4));
bellard579a97f2007-11-11 14:26:47 +00004283 unlock_user(p2, arg3, ret);
4284 unlock_user(p, arg2, 0);
ths5e0ccb12007-09-24 09:26:10 +00004285 }
4286 break;
4287#endif
thse5febef2007-04-01 18:31:35 +00004288#ifdef TARGET_NR_uselib
bellard31e31b82003-02-18 22:55:36 +00004289 case TARGET_NR_uselib:
4290 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00004291#endif
4292#ifdef TARGET_NR_swapon
bellard31e31b82003-02-18 22:55:36 +00004293 case TARGET_NR_swapon:
bellard579a97f2007-11-11 14:26:47 +00004294 if (!(p = lock_user_string(arg1)))
4295 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004296 ret = get_errno(swapon(p, arg2));
4297 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004298 break;
thse5febef2007-04-01 18:31:35 +00004299#endif
bellard31e31b82003-02-18 22:55:36 +00004300 case TARGET_NR_reboot:
4301 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00004302#ifdef TARGET_NR_readdir
bellard31e31b82003-02-18 22:55:36 +00004303 case TARGET_NR_readdir:
4304 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00004305#endif
4306#ifdef TARGET_NR_mmap
bellard31e31b82003-02-18 22:55:36 +00004307 case TARGET_NR_mmap:
bellardd2fd1af2007-11-14 18:08:56 +00004308#if (defined(TARGET_I386) && defined(TARGET_ABI32)) || defined(TARGET_ARM) || defined(TARGET_M68K) || defined(TARGET_CRIS)
bellard31e31b82003-02-18 22:55:36 +00004309 {
blueswir1992f48a2007-10-14 16:27:31 +00004310 abi_ulong *v;
4311 abi_ulong v1, v2, v3, v4, v5, v6;
bellard579a97f2007-11-11 14:26:47 +00004312 if (!(v = lock_user(VERIFY_READ, arg1, 6 * sizeof(abi_ulong), 1)))
4313 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004314 v1 = tswapl(v[0]);
4315 v2 = tswapl(v[1]);
4316 v3 = tswapl(v[2]);
4317 v4 = tswapl(v[3]);
4318 v5 = tswapl(v[4]);
4319 v6 = tswapl(v[5]);
4320 unlock_user(v, arg1, 0);
ths5fafdf22007-09-16 21:08:06 +00004321 ret = get_errno(target_mmap(v1, v2, v3,
bellard5286db72003-06-05 00:57:30 +00004322 target_to_host_bitmask(v4, mmap_flags_tbl),
4323 v5, v6));
bellard31e31b82003-02-18 22:55:36 +00004324 }
bellard31e31b82003-02-18 22:55:36 +00004325#else
ths5fafdf22007-09-16 21:08:06 +00004326 ret = get_errno(target_mmap(arg1, arg2, arg3,
4327 target_to_host_bitmask(arg4, mmap_flags_tbl),
bellard6fb883e2003-07-09 17:12:39 +00004328 arg5,
4329 arg6));
bellard31e31b82003-02-18 22:55:36 +00004330#endif
bellard6fb883e2003-07-09 17:12:39 +00004331 break;
thse5febef2007-04-01 18:31:35 +00004332#endif
bellarda315a142005-01-30 22:59:18 +00004333#ifdef TARGET_NR_mmap2
bellard6fb883e2003-07-09 17:12:39 +00004334 case TARGET_NR_mmap2:
pbrookbb7ec042008-03-25 22:28:25 +00004335#ifndef MMAP_SHIFT
bellardc573ff62004-01-04 15:51:36 +00004336#define MMAP_SHIFT 12
bellardc573ff62004-01-04 15:51:36 +00004337#endif
ths5fafdf22007-09-16 21:08:06 +00004338 ret = get_errno(target_mmap(arg1, arg2, arg3,
4339 target_to_host_bitmask(arg4, mmap_flags_tbl),
bellard5286db72003-06-05 00:57:30 +00004340 arg5,
bellardc573ff62004-01-04 15:51:36 +00004341 arg6 << MMAP_SHIFT));
bellard31e31b82003-02-18 22:55:36 +00004342 break;
bellarda315a142005-01-30 22:59:18 +00004343#endif
bellard31e31b82003-02-18 22:55:36 +00004344 case TARGET_NR_munmap:
bellard54936002003-05-13 00:25:15 +00004345 ret = get_errno(target_munmap(arg1, arg2));
bellard31e31b82003-02-18 22:55:36 +00004346 break;
bellard9de5e442003-03-23 16:49:39 +00004347 case TARGET_NR_mprotect:
bellard54936002003-05-13 00:25:15 +00004348 ret = get_errno(target_mprotect(arg1, arg2, arg3));
bellard9de5e442003-03-23 16:49:39 +00004349 break;
thse5febef2007-04-01 18:31:35 +00004350#ifdef TARGET_NR_mremap
bellard9de5e442003-03-23 16:49:39 +00004351 case TARGET_NR_mremap:
bellard54936002003-05-13 00:25:15 +00004352 ret = get_errno(target_mremap(arg1, arg2, arg3, arg4, arg5));
bellard9de5e442003-03-23 16:49:39 +00004353 break;
thse5febef2007-04-01 18:31:35 +00004354#endif
pbrook53a59602006-03-25 19:31:22 +00004355 /* ??? msync/mlock/munlock are broken for softmmu. */
thse5febef2007-04-01 18:31:35 +00004356#ifdef TARGET_NR_msync
bellard9de5e442003-03-23 16:49:39 +00004357 case TARGET_NR_msync:
pbrook53a59602006-03-25 19:31:22 +00004358 ret = get_errno(msync(g2h(arg1), arg2, arg3));
bellard9de5e442003-03-23 16:49:39 +00004359 break;
thse5febef2007-04-01 18:31:35 +00004360#endif
4361#ifdef TARGET_NR_mlock
bellard9de5e442003-03-23 16:49:39 +00004362 case TARGET_NR_mlock:
pbrook53a59602006-03-25 19:31:22 +00004363 ret = get_errno(mlock(g2h(arg1), arg2));
bellard9de5e442003-03-23 16:49:39 +00004364 break;
thse5febef2007-04-01 18:31:35 +00004365#endif
4366#ifdef TARGET_NR_munlock
bellard9de5e442003-03-23 16:49:39 +00004367 case TARGET_NR_munlock:
pbrook53a59602006-03-25 19:31:22 +00004368 ret = get_errno(munlock(g2h(arg1), arg2));
bellard9de5e442003-03-23 16:49:39 +00004369 break;
thse5febef2007-04-01 18:31:35 +00004370#endif
4371#ifdef TARGET_NR_mlockall
bellard9de5e442003-03-23 16:49:39 +00004372 case TARGET_NR_mlockall:
4373 ret = get_errno(mlockall(arg1));
4374 break;
thse5febef2007-04-01 18:31:35 +00004375#endif
4376#ifdef TARGET_NR_munlockall
bellard9de5e442003-03-23 16:49:39 +00004377 case TARGET_NR_munlockall:
4378 ret = get_errno(munlockall());
4379 break;
thse5febef2007-04-01 18:31:35 +00004380#endif
bellard31e31b82003-02-18 22:55:36 +00004381 case TARGET_NR_truncate:
bellard579a97f2007-11-11 14:26:47 +00004382 if (!(p = lock_user_string(arg1)))
4383 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004384 ret = get_errno(truncate(p, arg2));
4385 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004386 break;
4387 case TARGET_NR_ftruncate:
4388 ret = get_errno(ftruncate(arg1, arg2));
4389 break;
4390 case TARGET_NR_fchmod:
4391 ret = get_errno(fchmod(arg1, arg2));
4392 break;
ths814d7972007-09-24 09:26:51 +00004393#if defined(TARGET_NR_fchmodat) && defined(__NR_fchmodat)
4394 case TARGET_NR_fchmodat:
bellard579a97f2007-11-11 14:26:47 +00004395 if (!(p = lock_user_string(arg2)))
4396 goto efault;
4397 ret = get_errno(sys_fchmodat(arg1, p, arg3, arg4));
4398 unlock_user(p, arg2, 0);
ths814d7972007-09-24 09:26:51 +00004399 break;
4400#endif
bellard31e31b82003-02-18 22:55:36 +00004401 case TARGET_NR_getpriority:
thsc6cda172007-10-09 03:42:34 +00004402 /* libc does special remapping of the return value of
4403 * sys_getpriority() so it's just easiest to call
4404 * sys_getpriority() directly rather than through libc. */
4405 ret = sys_getpriority(arg1, arg2);
bellard31e31b82003-02-18 22:55:36 +00004406 break;
4407 case TARGET_NR_setpriority:
4408 ret = get_errno(setpriority(arg1, arg2, arg3));
4409 break;
bellardebc05482003-09-30 21:08:41 +00004410#ifdef TARGET_NR_profil
bellard31e31b82003-02-18 22:55:36 +00004411 case TARGET_NR_profil:
4412 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004413#endif
bellard31e31b82003-02-18 22:55:36 +00004414 case TARGET_NR_statfs:
bellard579a97f2007-11-11 14:26:47 +00004415 if (!(p = lock_user_string(arg1)))
4416 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004417 ret = get_errno(statfs(path(p), &stfs));
4418 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004419 convert_statfs:
4420 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00004421 struct target_statfs *target_stfs;
ths3b46e622007-09-17 08:09:54 +00004422
bellard579a97f2007-11-11 14:26:47 +00004423 if (!lock_user_struct(VERIFY_WRITE, target_stfs, arg2, 0))
4424 goto efault;
4425 __put_user(stfs.f_type, &target_stfs->f_type);
4426 __put_user(stfs.f_bsize, &target_stfs->f_bsize);
4427 __put_user(stfs.f_blocks, &target_stfs->f_blocks);
4428 __put_user(stfs.f_bfree, &target_stfs->f_bfree);
4429 __put_user(stfs.f_bavail, &target_stfs->f_bavail);
4430 __put_user(stfs.f_files, &target_stfs->f_files);
4431 __put_user(stfs.f_ffree, &target_stfs->f_ffree);
4432 __put_user(stfs.f_fsid.__val[0], &target_stfs->f_fsid.val[0]);
4433 __put_user(stfs.f_fsid.__val[1], &target_stfs->f_fsid.val[1]);
4434 __put_user(stfs.f_namelen, &target_stfs->f_namelen);
pbrook53a59602006-03-25 19:31:22 +00004435 unlock_user_struct(target_stfs, arg2, 1);
bellard31e31b82003-02-18 22:55:36 +00004436 }
4437 break;
4438 case TARGET_NR_fstatfs:
bellard56c8f682005-11-28 22:28:41 +00004439 ret = get_errno(fstatfs(arg1, &stfs));
bellard31e31b82003-02-18 22:55:36 +00004440 goto convert_statfs;
bellard56c8f682005-11-28 22:28:41 +00004441#ifdef TARGET_NR_statfs64
4442 case TARGET_NR_statfs64:
bellard579a97f2007-11-11 14:26:47 +00004443 if (!(p = lock_user_string(arg1)))
4444 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004445 ret = get_errno(statfs(path(p), &stfs));
4446 unlock_user(p, arg1, 0);
bellard56c8f682005-11-28 22:28:41 +00004447 convert_statfs64:
4448 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00004449 struct target_statfs64 *target_stfs;
ths3b46e622007-09-17 08:09:54 +00004450
bellard579a97f2007-11-11 14:26:47 +00004451 if (!lock_user_struct(VERIFY_WRITE, target_stfs, arg3, 0))
4452 goto efault;
4453 __put_user(stfs.f_type, &target_stfs->f_type);
4454 __put_user(stfs.f_bsize, &target_stfs->f_bsize);
4455 __put_user(stfs.f_blocks, &target_stfs->f_blocks);
4456 __put_user(stfs.f_bfree, &target_stfs->f_bfree);
4457 __put_user(stfs.f_bavail, &target_stfs->f_bavail);
4458 __put_user(stfs.f_files, &target_stfs->f_files);
4459 __put_user(stfs.f_ffree, &target_stfs->f_ffree);
4460 __put_user(stfs.f_fsid.__val[0], &target_stfs->f_fsid.val[0]);
4461 __put_user(stfs.f_fsid.__val[1], &target_stfs->f_fsid.val[1]);
4462 __put_user(stfs.f_namelen, &target_stfs->f_namelen);
4463 unlock_user_struct(target_stfs, arg3, 1);
bellard56c8f682005-11-28 22:28:41 +00004464 }
4465 break;
4466 case TARGET_NR_fstatfs64:
4467 ret = get_errno(fstatfs(arg1, &stfs));
4468 goto convert_statfs64;
4469#endif
bellardebc05482003-09-30 21:08:41 +00004470#ifdef TARGET_NR_ioperm
bellard31e31b82003-02-18 22:55:36 +00004471 case TARGET_NR_ioperm:
4472 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004473#endif
thse5febef2007-04-01 18:31:35 +00004474#ifdef TARGET_NR_socketcall
bellard31e31b82003-02-18 22:55:36 +00004475 case TARGET_NR_socketcall:
pbrook53a59602006-03-25 19:31:22 +00004476 ret = do_socketcall(arg1, arg2);
bellard31e31b82003-02-18 22:55:36 +00004477 break;
thse5febef2007-04-01 18:31:35 +00004478#endif
bellard3532fa72006-06-24 15:06:03 +00004479#ifdef TARGET_NR_accept
4480 case TARGET_NR_accept:
pbrook1be9e1d2006-11-19 15:26:04 +00004481 ret = do_accept(arg1, arg2, arg3);
bellard3532fa72006-06-24 15:06:03 +00004482 break;
4483#endif
4484#ifdef TARGET_NR_bind
4485 case TARGET_NR_bind:
4486 ret = do_bind(arg1, arg2, arg3);
4487 break;
4488#endif
4489#ifdef TARGET_NR_connect
4490 case TARGET_NR_connect:
4491 ret = do_connect(arg1, arg2, arg3);
4492 break;
4493#endif
4494#ifdef TARGET_NR_getpeername
4495 case TARGET_NR_getpeername:
pbrook1be9e1d2006-11-19 15:26:04 +00004496 ret = do_getpeername(arg1, arg2, arg3);
bellard3532fa72006-06-24 15:06:03 +00004497 break;
4498#endif
4499#ifdef TARGET_NR_getsockname
4500 case TARGET_NR_getsockname:
pbrook1be9e1d2006-11-19 15:26:04 +00004501 ret = do_getsockname(arg1, arg2, arg3);
bellard3532fa72006-06-24 15:06:03 +00004502 break;
4503#endif
4504#ifdef TARGET_NR_getsockopt
4505 case TARGET_NR_getsockopt:
4506 ret = do_getsockopt(arg1, arg2, arg3, arg4, arg5);
4507 break;
4508#endif
4509#ifdef TARGET_NR_listen
4510 case TARGET_NR_listen:
pbrook1be9e1d2006-11-19 15:26:04 +00004511 ret = get_errno(listen(arg1, arg2));
bellard3532fa72006-06-24 15:06:03 +00004512 break;
4513#endif
4514#ifdef TARGET_NR_recv
4515 case TARGET_NR_recv:
pbrook214201b2007-03-17 01:27:24 +00004516 ret = do_recvfrom(arg1, arg2, arg3, arg4, 0, 0);
bellard3532fa72006-06-24 15:06:03 +00004517 break;
4518#endif
4519#ifdef TARGET_NR_recvfrom
4520 case TARGET_NR_recvfrom:
pbrook214201b2007-03-17 01:27:24 +00004521 ret = do_recvfrom(arg1, arg2, arg3, arg4, arg5, arg6);
bellard3532fa72006-06-24 15:06:03 +00004522 break;
4523#endif
4524#ifdef TARGET_NR_recvmsg
4525 case TARGET_NR_recvmsg:
4526 ret = do_sendrecvmsg(arg1, arg2, arg3, 0);
4527 break;
4528#endif
4529#ifdef TARGET_NR_send
4530 case TARGET_NR_send:
pbrook1be9e1d2006-11-19 15:26:04 +00004531 ret = do_sendto(arg1, arg2, arg3, arg4, 0, 0);
bellard3532fa72006-06-24 15:06:03 +00004532 break;
4533#endif
4534#ifdef TARGET_NR_sendmsg
4535 case TARGET_NR_sendmsg:
4536 ret = do_sendrecvmsg(arg1, arg2, arg3, 1);
4537 break;
4538#endif
4539#ifdef TARGET_NR_sendto
4540 case TARGET_NR_sendto:
pbrook1be9e1d2006-11-19 15:26:04 +00004541 ret = do_sendto(arg1, arg2, arg3, arg4, arg5, arg6);
bellard3532fa72006-06-24 15:06:03 +00004542 break;
4543#endif
4544#ifdef TARGET_NR_shutdown
4545 case TARGET_NR_shutdown:
pbrook1be9e1d2006-11-19 15:26:04 +00004546 ret = get_errno(shutdown(arg1, arg2));
bellard3532fa72006-06-24 15:06:03 +00004547 break;
4548#endif
4549#ifdef TARGET_NR_socket
4550 case TARGET_NR_socket:
4551 ret = do_socket(arg1, arg2, arg3);
4552 break;
4553#endif
4554#ifdef TARGET_NR_socketpair
4555 case TARGET_NR_socketpair:
pbrook1be9e1d2006-11-19 15:26:04 +00004556 ret = do_socketpair(arg1, arg2, arg3, arg4);
bellard3532fa72006-06-24 15:06:03 +00004557 break;
4558#endif
4559#ifdef TARGET_NR_setsockopt
4560 case TARGET_NR_setsockopt:
4561 ret = do_setsockopt(arg1, arg2, arg3, arg4, (socklen_t) arg5);
4562 break;
4563#endif
ths7494b0f2007-02-11 18:26:53 +00004564
bellard31e31b82003-02-18 22:55:36 +00004565 case TARGET_NR_syslog:
bellard579a97f2007-11-11 14:26:47 +00004566 if (!(p = lock_user_string(arg2)))
4567 goto efault;
thse5574482007-02-11 20:03:13 +00004568 ret = get_errno(sys_syslog((int)arg1, p, (int)arg3));
4569 unlock_user(p, arg2, 0);
ths7494b0f2007-02-11 18:26:53 +00004570 break;
4571
bellard31e31b82003-02-18 22:55:36 +00004572 case TARGET_NR_setitimer:
bellard66fb9762003-03-23 01:06:05 +00004573 {
bellard66fb9762003-03-23 01:06:05 +00004574 struct itimerval value, ovalue, *pvalue;
4575
pbrook53a59602006-03-25 19:31:22 +00004576 if (arg2) {
bellard66fb9762003-03-23 01:06:05 +00004577 pvalue = &value;
ths788f5ec2007-12-09 02:37:05 +00004578 if (copy_from_user_timeval(&pvalue->it_interval, arg2)
4579 || copy_from_user_timeval(&pvalue->it_value,
4580 arg2 + sizeof(struct target_timeval)))
4581 goto efault;
bellard66fb9762003-03-23 01:06:05 +00004582 } else {
4583 pvalue = NULL;
4584 }
4585 ret = get_errno(setitimer(arg1, pvalue, &ovalue));
pbrook53a59602006-03-25 19:31:22 +00004586 if (!is_error(ret) && arg3) {
ths788f5ec2007-12-09 02:37:05 +00004587 if (copy_to_user_timeval(arg3,
4588 &ovalue.it_interval)
4589 || copy_to_user_timeval(arg3 + sizeof(struct target_timeval),
4590 &ovalue.it_value))
4591 goto efault;
bellard66fb9762003-03-23 01:06:05 +00004592 }
4593 }
4594 break;
bellard31e31b82003-02-18 22:55:36 +00004595 case TARGET_NR_getitimer:
bellard66fb9762003-03-23 01:06:05 +00004596 {
bellard66fb9762003-03-23 01:06:05 +00004597 struct itimerval value;
ths3b46e622007-09-17 08:09:54 +00004598
bellard66fb9762003-03-23 01:06:05 +00004599 ret = get_errno(getitimer(arg1, &value));
pbrook53a59602006-03-25 19:31:22 +00004600 if (!is_error(ret) && arg2) {
ths788f5ec2007-12-09 02:37:05 +00004601 if (copy_to_user_timeval(arg2,
4602 &value.it_interval)
4603 || copy_to_user_timeval(arg2 + sizeof(struct target_timeval),
4604 &value.it_value))
4605 goto efault;
bellard66fb9762003-03-23 01:06:05 +00004606 }
4607 }
4608 break;
bellard31e31b82003-02-18 22:55:36 +00004609 case TARGET_NR_stat:
bellard579a97f2007-11-11 14:26:47 +00004610 if (!(p = lock_user_string(arg1)))
4611 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004612 ret = get_errno(stat(path(p), &st));
4613 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004614 goto do_stat;
4615 case TARGET_NR_lstat:
bellard579a97f2007-11-11 14:26:47 +00004616 if (!(p = lock_user_string(arg1)))
4617 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004618 ret = get_errno(lstat(path(p), &st));
4619 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004620 goto do_stat;
4621 case TARGET_NR_fstat:
4622 {
4623 ret = get_errno(fstat(arg1, &st));
4624 do_stat:
4625 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00004626 struct target_stat *target_st;
thse3584652007-06-01 11:49:38 +00004627
bellard579a97f2007-11-11 14:26:47 +00004628 if (!lock_user_struct(VERIFY_WRITE, target_st, arg2, 0))
4629 goto efault;
bellardd2fd1af2007-11-14 18:08:56 +00004630 __put_user(st.st_dev, &target_st->st_dev);
4631 __put_user(st.st_ino, &target_st->st_ino);
4632 __put_user(st.st_mode, &target_st->st_mode);
4633 __put_user(st.st_uid, &target_st->st_uid);
4634 __put_user(st.st_gid, &target_st->st_gid);
4635 __put_user(st.st_nlink, &target_st->st_nlink);
4636 __put_user(st.st_rdev, &target_st->st_rdev);
4637 __put_user(st.st_size, &target_st->st_size);
4638 __put_user(st.st_blksize, &target_st->st_blksize);
4639 __put_user(st.st_blocks, &target_st->st_blocks);
4640 __put_user(st.st_atime, &target_st->target_st_atime);
4641 __put_user(st.st_mtime, &target_st->target_st_mtime);
4642 __put_user(st.st_ctime, &target_st->target_st_ctime);
pbrook53a59602006-03-25 19:31:22 +00004643 unlock_user_struct(target_st, arg2, 1);
bellard31e31b82003-02-18 22:55:36 +00004644 }
4645 }
4646 break;
bellardebc05482003-09-30 21:08:41 +00004647#ifdef TARGET_NR_olduname
bellard31e31b82003-02-18 22:55:36 +00004648 case TARGET_NR_olduname:
4649 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004650#endif
4651#ifdef TARGET_NR_iopl
bellard31e31b82003-02-18 22:55:36 +00004652 case TARGET_NR_iopl:
4653 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004654#endif
bellard31e31b82003-02-18 22:55:36 +00004655 case TARGET_NR_vhangup:
4656 ret = get_errno(vhangup());
4657 break;
bellardebc05482003-09-30 21:08:41 +00004658#ifdef TARGET_NR_idle
bellard31e31b82003-02-18 22:55:36 +00004659 case TARGET_NR_idle:
4660 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004661#endif
bellard42ad6ae2005-01-03 22:48:11 +00004662#ifdef TARGET_NR_syscall
4663 case TARGET_NR_syscall:
4664 ret = do_syscall(cpu_env,arg1 & 0xffff,arg2,arg3,arg4,arg5,arg6,0);
4665 break;
4666#endif
bellard31e31b82003-02-18 22:55:36 +00004667 case TARGET_NR_wait4:
4668 {
4669 int status;
blueswir1992f48a2007-10-14 16:27:31 +00004670 abi_long status_ptr = arg2;
bellard31e31b82003-02-18 22:55:36 +00004671 struct rusage rusage, *rusage_ptr;
blueswir1992f48a2007-10-14 16:27:31 +00004672 abi_ulong target_rusage = arg4;
bellard31e31b82003-02-18 22:55:36 +00004673 if (target_rusage)
4674 rusage_ptr = &rusage;
4675 else
4676 rusage_ptr = NULL;
4677 ret = get_errno(wait4(arg1, &status, arg3, rusage_ptr));
4678 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +00004679 if (status_ptr) {
4680 if (put_user_s32(status, status_ptr))
4681 goto efault;
bellard31e31b82003-02-18 22:55:36 +00004682 }
bellard2f619692007-11-16 10:46:05 +00004683 if (target_rusage)
4684 host_to_target_rusage(target_rusage, &rusage);
bellard31e31b82003-02-18 22:55:36 +00004685 }
4686 }
4687 break;
thse5febef2007-04-01 18:31:35 +00004688#ifdef TARGET_NR_swapoff
bellard31e31b82003-02-18 22:55:36 +00004689 case TARGET_NR_swapoff:
bellard579a97f2007-11-11 14:26:47 +00004690 if (!(p = lock_user_string(arg1)))
4691 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004692 ret = get_errno(swapoff(p));
4693 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004694 break;
thse5febef2007-04-01 18:31:35 +00004695#endif
bellard31e31b82003-02-18 22:55:36 +00004696 case TARGET_NR_sysinfo:
bellarda5448a72004-06-19 16:59:03 +00004697 {
pbrook53a59602006-03-25 19:31:22 +00004698 struct target_sysinfo *target_value;
bellarda5448a72004-06-19 16:59:03 +00004699 struct sysinfo value;
4700 ret = get_errno(sysinfo(&value));
pbrook53a59602006-03-25 19:31:22 +00004701 if (!is_error(ret) && arg1)
bellarda5448a72004-06-19 16:59:03 +00004702 {
bellard579a97f2007-11-11 14:26:47 +00004703 if (!lock_user_struct(VERIFY_WRITE, target_value, arg1, 0))
4704 goto efault;
bellarda5448a72004-06-19 16:59:03 +00004705 __put_user(value.uptime, &target_value->uptime);
4706 __put_user(value.loads[0], &target_value->loads[0]);
4707 __put_user(value.loads[1], &target_value->loads[1]);
4708 __put_user(value.loads[2], &target_value->loads[2]);
4709 __put_user(value.totalram, &target_value->totalram);
4710 __put_user(value.freeram, &target_value->freeram);
4711 __put_user(value.sharedram, &target_value->sharedram);
4712 __put_user(value.bufferram, &target_value->bufferram);
4713 __put_user(value.totalswap, &target_value->totalswap);
4714 __put_user(value.freeswap, &target_value->freeswap);
4715 __put_user(value.procs, &target_value->procs);
4716 __put_user(value.totalhigh, &target_value->totalhigh);
4717 __put_user(value.freehigh, &target_value->freehigh);
4718 __put_user(value.mem_unit, &target_value->mem_unit);
pbrook53a59602006-03-25 19:31:22 +00004719 unlock_user_struct(target_value, arg1, 1);
bellarda5448a72004-06-19 16:59:03 +00004720 }
4721 }
4722 break;
thse5febef2007-04-01 18:31:35 +00004723#ifdef TARGET_NR_ipc
bellard31e31b82003-02-18 22:55:36 +00004724 case TARGET_NR_ipc:
bellard8853f862004-02-22 14:57:26 +00004725 ret = do_ipc(arg1, arg2, arg3, arg4, arg5, arg6);
4726 break;
thse5febef2007-04-01 18:31:35 +00004727#endif
bellard31e31b82003-02-18 22:55:36 +00004728 case TARGET_NR_fsync:
4729 ret = get_errno(fsync(arg1));
4730 break;
bellard31e31b82003-02-18 22:55:36 +00004731 case TARGET_NR_clone:
aurel320b6d3ae2008-09-15 07:43:43 +00004732#if defined(TARGET_SH4)
4733 ret = get_errno(do_fork(cpu_env, arg1, arg2, arg3, arg5, arg4));
4734#else
pbrookd865bab2008-06-07 22:12:17 +00004735 ret = get_errno(do_fork(cpu_env, arg1, arg2, arg3, arg4, arg5));
aurel320b6d3ae2008-09-15 07:43:43 +00004736#endif
bellard1b6b0292003-03-22 17:31:38 +00004737 break;
bellardec86b0f2003-04-11 00:15:04 +00004738#ifdef __NR_exit_group
4739 /* new thread calls */
4740 case TARGET_NR_exit_group:
bellarde9009672005-04-26 20:42:36 +00004741 gdb_exit(cpu_env, arg1);
bellardec86b0f2003-04-11 00:15:04 +00004742 ret = get_errno(exit_group(arg1));
4743 break;
4744#endif
bellard31e31b82003-02-18 22:55:36 +00004745 case TARGET_NR_setdomainname:
bellard579a97f2007-11-11 14:26:47 +00004746 if (!(p = lock_user_string(arg1)))
4747 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004748 ret = get_errno(setdomainname(p, arg2));
4749 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004750 break;
4751 case TARGET_NR_uname:
4752 /* no need to transcode because we use the linux syscall */
bellard29e619b2004-09-13 21:41:04 +00004753 {
4754 struct new_utsname * buf;
ths3b46e622007-09-17 08:09:54 +00004755
bellard579a97f2007-11-11 14:26:47 +00004756 if (!lock_user_struct(VERIFY_WRITE, buf, arg1, 0))
4757 goto efault;
bellard29e619b2004-09-13 21:41:04 +00004758 ret = get_errno(sys_uname(buf));
4759 if (!is_error(ret)) {
4760 /* Overrite the native machine name with whatever is being
4761 emulated. */
4762 strcpy (buf->machine, UNAME_MACHINE);
pbrookc5937222006-05-14 11:30:38 +00004763 /* Allow the user to override the reported release. */
4764 if (qemu_uname_release && *qemu_uname_release)
4765 strcpy (buf->release, qemu_uname_release);
bellard29e619b2004-09-13 21:41:04 +00004766 }
pbrook53a59602006-03-25 19:31:22 +00004767 unlock_user_struct(buf, arg1, 1);
bellard29e619b2004-09-13 21:41:04 +00004768 }
bellard31e31b82003-02-18 22:55:36 +00004769 break;
bellard6dbad632003-03-16 18:05:05 +00004770#ifdef TARGET_I386
bellard31e31b82003-02-18 22:55:36 +00004771 case TARGET_NR_modify_ldt:
bellard03acab62007-11-11 14:57:14 +00004772 ret = do_modify_ldt(cpu_env, arg1, arg2, arg3);
bellard5cd43932003-03-29 16:54:36 +00004773 break;
j_mayer84409dd2007-04-06 08:56:50 +00004774#if !defined(TARGET_X86_64)
bellard5cd43932003-03-29 16:54:36 +00004775 case TARGET_NR_vm86old:
4776 goto unimplemented;
4777 case TARGET_NR_vm86:
pbrook53a59602006-03-25 19:31:22 +00004778 ret = do_vm86(cpu_env, arg1, arg2);
bellard6dbad632003-03-16 18:05:05 +00004779 break;
4780#endif
j_mayer84409dd2007-04-06 08:56:50 +00004781#endif
bellard31e31b82003-02-18 22:55:36 +00004782 case TARGET_NR_adjtimex:
4783 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00004784#ifdef TARGET_NR_create_module
bellard31e31b82003-02-18 22:55:36 +00004785 case TARGET_NR_create_module:
thse5febef2007-04-01 18:31:35 +00004786#endif
bellard31e31b82003-02-18 22:55:36 +00004787 case TARGET_NR_init_module:
4788 case TARGET_NR_delete_module:
thse5febef2007-04-01 18:31:35 +00004789#ifdef TARGET_NR_get_kernel_syms
bellard31e31b82003-02-18 22:55:36 +00004790 case TARGET_NR_get_kernel_syms:
thse5febef2007-04-01 18:31:35 +00004791#endif
bellard31e31b82003-02-18 22:55:36 +00004792 goto unimplemented;
4793 case TARGET_NR_quotactl:
4794 goto unimplemented;
4795 case TARGET_NR_getpgid:
4796 ret = get_errno(getpgid(arg1));
4797 break;
4798 case TARGET_NR_fchdir:
4799 ret = get_errno(fchdir(arg1));
4800 break;
j_mayer84409dd2007-04-06 08:56:50 +00004801#ifdef TARGET_NR_bdflush /* not on x86_64 */
bellard31e31b82003-02-18 22:55:36 +00004802 case TARGET_NR_bdflush:
4803 goto unimplemented;
j_mayer84409dd2007-04-06 08:56:50 +00004804#endif
thse5febef2007-04-01 18:31:35 +00004805#ifdef TARGET_NR_sysfs
bellard31e31b82003-02-18 22:55:36 +00004806 case TARGET_NR_sysfs:
4807 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00004808#endif
bellard31e31b82003-02-18 22:55:36 +00004809 case TARGET_NR_personality:
bellard1b6b0292003-03-22 17:31:38 +00004810 ret = get_errno(personality(arg1));
bellard31e31b82003-02-18 22:55:36 +00004811 break;
thse5febef2007-04-01 18:31:35 +00004812#ifdef TARGET_NR_afs_syscall
bellard31e31b82003-02-18 22:55:36 +00004813 case TARGET_NR_afs_syscall:
4814 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00004815#endif
j_mayer7a3148a2007-04-05 07:13:51 +00004816#ifdef TARGET_NR__llseek /* Not on alpha */
bellard31e31b82003-02-18 22:55:36 +00004817 case TARGET_NR__llseek:
4818 {
bellard4f2ac232004-04-26 19:44:02 +00004819#if defined (__x86_64__)
4820 ret = get_errno(lseek(arg1, ((uint64_t )arg2 << 32) | arg3, arg5));
bellard2f619692007-11-16 10:46:05 +00004821 if (put_user_s64(ret, arg4))
4822 goto efault;
bellard4f2ac232004-04-26 19:44:02 +00004823#else
bellard31e31b82003-02-18 22:55:36 +00004824 int64_t res;
4825 ret = get_errno(_llseek(arg1, arg2, arg3, &res, arg5));
bellard2f619692007-11-16 10:46:05 +00004826 if (put_user_s64(res, arg4))
4827 goto efault;
bellard4f2ac232004-04-26 19:44:02 +00004828#endif
bellard31e31b82003-02-18 22:55:36 +00004829 }
4830 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004831#endif
bellard31e31b82003-02-18 22:55:36 +00004832 case TARGET_NR_getdents:
blueswir1992f48a2007-10-14 16:27:31 +00004833#if TARGET_ABI_BITS != 32
pbrook53a59602006-03-25 19:31:22 +00004834 goto unimplemented;
blueswir1992f48a2007-10-14 16:27:31 +00004835#elif TARGET_ABI_BITS == 32 && HOST_LONG_BITS == 64
bellard4add45b2003-06-05 01:52:59 +00004836 {
pbrook53a59602006-03-25 19:31:22 +00004837 struct target_dirent *target_dirp;
bellard4add45b2003-06-05 01:52:59 +00004838 struct dirent *dirp;
blueswir1992f48a2007-10-14 16:27:31 +00004839 abi_long count = arg3;
bellard4add45b2003-06-05 01:52:59 +00004840
4841 dirp = malloc(count);
ths0da46a62007-10-20 20:23:07 +00004842 if (!dirp) {
bellard579a97f2007-11-11 14:26:47 +00004843 ret = -TARGET_ENOMEM;
ths0da46a62007-10-20 20:23:07 +00004844 goto fail;
4845 }
ths3b46e622007-09-17 08:09:54 +00004846
bellard4add45b2003-06-05 01:52:59 +00004847 ret = get_errno(sys_getdents(arg1, dirp, count));
4848 if (!is_error(ret)) {
4849 struct dirent *de;
4850 struct target_dirent *tde;
4851 int len = ret;
4852 int reclen, treclen;
4853 int count1, tnamelen;
4854
4855 count1 = 0;
4856 de = dirp;
bellard579a97f2007-11-11 14:26:47 +00004857 if (!(target_dirp = lock_user(VERIFY_WRITE, arg2, count, 0)))
4858 goto efault;
bellard4add45b2003-06-05 01:52:59 +00004859 tde = target_dirp;
4860 while (len > 0) {
4861 reclen = de->d_reclen;
blueswir1992f48a2007-10-14 16:27:31 +00004862 treclen = reclen - (2 * (sizeof(long) - sizeof(abi_long)));
bellard4add45b2003-06-05 01:52:59 +00004863 tde->d_reclen = tswap16(treclen);
4864 tde->d_ino = tswapl(de->d_ino);
4865 tde->d_off = tswapl(de->d_off);
blueswir1992f48a2007-10-14 16:27:31 +00004866 tnamelen = treclen - (2 * sizeof(abi_long) + 2);
bellard4add45b2003-06-05 01:52:59 +00004867 if (tnamelen > 256)
4868 tnamelen = 256;
bellard80a9d032005-01-03 23:31:27 +00004869 /* XXX: may not be correct */
bellard4add45b2003-06-05 01:52:59 +00004870 strncpy(tde->d_name, de->d_name, tnamelen);
4871 de = (struct dirent *)((char *)de + reclen);
4872 len -= reclen;
j_mayer1c5bf3b2007-04-14 12:17:59 +00004873 tde = (struct target_dirent *)((char *)tde + treclen);
bellard4add45b2003-06-05 01:52:59 +00004874 count1 += treclen;
4875 }
4876 ret = count1;
bellard579a97f2007-11-11 14:26:47 +00004877 unlock_user(target_dirp, arg2, ret);
bellard4add45b2003-06-05 01:52:59 +00004878 }
4879 free(dirp);
4880 }
4881#else
bellard31e31b82003-02-18 22:55:36 +00004882 {
pbrook53a59602006-03-25 19:31:22 +00004883 struct dirent *dirp;
blueswir1992f48a2007-10-14 16:27:31 +00004884 abi_long count = arg3;
bellarddab2ed92003-03-22 15:23:14 +00004885
bellard579a97f2007-11-11 14:26:47 +00004886 if (!(dirp = lock_user(VERIFY_WRITE, arg2, count, 0)))
4887 goto efault;
bellard72f03902003-02-18 23:33:18 +00004888 ret = get_errno(sys_getdents(arg1, dirp, count));
bellard31e31b82003-02-18 22:55:36 +00004889 if (!is_error(ret)) {
4890 struct dirent *de;
4891 int len = ret;
4892 int reclen;
4893 de = dirp;
4894 while (len > 0) {
bellard8083a3e2003-03-24 23:12:16 +00004895 reclen = de->d_reclen;
bellard31e31b82003-02-18 22:55:36 +00004896 if (reclen > len)
4897 break;
bellard8083a3e2003-03-24 23:12:16 +00004898 de->d_reclen = tswap16(reclen);
bellard31e31b82003-02-18 22:55:36 +00004899 tswapls(&de->d_ino);
4900 tswapls(&de->d_off);
4901 de = (struct dirent *)((char *)de + reclen);
4902 len -= reclen;
4903 }
4904 }
pbrook53a59602006-03-25 19:31:22 +00004905 unlock_user(dirp, arg2, ret);
bellard31e31b82003-02-18 22:55:36 +00004906 }
bellard4add45b2003-06-05 01:52:59 +00004907#endif
bellard31e31b82003-02-18 22:55:36 +00004908 break;
ths3ae43202007-09-16 21:39:48 +00004909#if defined(TARGET_NR_getdents64) && defined(__NR_getdents64)
bellarddab2ed92003-03-22 15:23:14 +00004910 case TARGET_NR_getdents64:
4911 {
pbrook53a59602006-03-25 19:31:22 +00004912 struct dirent64 *dirp;
blueswir1992f48a2007-10-14 16:27:31 +00004913 abi_long count = arg3;
bellard579a97f2007-11-11 14:26:47 +00004914 if (!(dirp = lock_user(VERIFY_WRITE, arg2, count, 0)))
4915 goto efault;
bellarddab2ed92003-03-22 15:23:14 +00004916 ret = get_errno(sys_getdents64(arg1, dirp, count));
4917 if (!is_error(ret)) {
4918 struct dirent64 *de;
4919 int len = ret;
4920 int reclen;
4921 de = dirp;
4922 while (len > 0) {
bellard8083a3e2003-03-24 23:12:16 +00004923 reclen = de->d_reclen;
bellarddab2ed92003-03-22 15:23:14 +00004924 if (reclen > len)
4925 break;
bellard8083a3e2003-03-24 23:12:16 +00004926 de->d_reclen = tswap16(reclen);
bellard8582a532007-11-11 23:11:36 +00004927 tswap64s((uint64_t *)&de->d_ino);
4928 tswap64s((uint64_t *)&de->d_off);
bellarddab2ed92003-03-22 15:23:14 +00004929 de = (struct dirent64 *)((char *)de + reclen);
4930 len -= reclen;
4931 }
4932 }
pbrook53a59602006-03-25 19:31:22 +00004933 unlock_user(dirp, arg2, ret);
bellarddab2ed92003-03-22 15:23:14 +00004934 }
4935 break;
bellarda541f292004-04-12 20:39:29 +00004936#endif /* TARGET_NR_getdents64 */
thse5febef2007-04-01 18:31:35 +00004937#ifdef TARGET_NR__newselect
bellard31e31b82003-02-18 22:55:36 +00004938 case TARGET_NR__newselect:
pbrook53a59602006-03-25 19:31:22 +00004939 ret = do_select(arg1, arg2, arg3, arg4, arg5);
bellard31e31b82003-02-18 22:55:36 +00004940 break;
thse5febef2007-04-01 18:31:35 +00004941#endif
4942#ifdef TARGET_NR_poll
bellard9de5e442003-03-23 16:49:39 +00004943 case TARGET_NR_poll:
4944 {
pbrook53a59602006-03-25 19:31:22 +00004945 struct target_pollfd *target_pfd;
bellard9de5e442003-03-23 16:49:39 +00004946 unsigned int nfds = arg2;
4947 int timeout = arg3;
4948 struct pollfd *pfd;
bellard7854b052003-03-29 17:22:23 +00004949 unsigned int i;
bellard9de5e442003-03-23 16:49:39 +00004950
bellard579a97f2007-11-11 14:26:47 +00004951 target_pfd = lock_user(VERIFY_WRITE, arg1, sizeof(struct target_pollfd) * nfds, 1);
4952 if (!target_pfd)
4953 goto efault;
bellard9de5e442003-03-23 16:49:39 +00004954 pfd = alloca(sizeof(struct pollfd) * nfds);
4955 for(i = 0; i < nfds; i++) {
bellard5cd43932003-03-29 16:54:36 +00004956 pfd[i].fd = tswap32(target_pfd[i].fd);
4957 pfd[i].events = tswap16(target_pfd[i].events);
bellard9de5e442003-03-23 16:49:39 +00004958 }
4959 ret = get_errno(poll(pfd, nfds, timeout));
4960 if (!is_error(ret)) {
4961 for(i = 0; i < nfds; i++) {
bellard5cd43932003-03-29 16:54:36 +00004962 target_pfd[i].revents = tswap16(pfd[i].revents);
bellard9de5e442003-03-23 16:49:39 +00004963 }
pbrook53a59602006-03-25 19:31:22 +00004964 ret += nfds * (sizeof(struct target_pollfd)
4965 - sizeof(struct pollfd));
bellard9de5e442003-03-23 16:49:39 +00004966 }
pbrook53a59602006-03-25 19:31:22 +00004967 unlock_user(target_pfd, arg1, ret);
bellard9de5e442003-03-23 16:49:39 +00004968 }
4969 break;
thse5febef2007-04-01 18:31:35 +00004970#endif
bellard31e31b82003-02-18 22:55:36 +00004971 case TARGET_NR_flock:
bellard9de5e442003-03-23 16:49:39 +00004972 /* NOTE: the flock constant seems to be the same for every
4973 Linux platform */
4974 ret = get_errno(flock(arg1, arg2));
bellard31e31b82003-02-18 22:55:36 +00004975 break;
4976 case TARGET_NR_readv:
4977 {
4978 int count = arg3;
bellard31e31b82003-02-18 22:55:36 +00004979 struct iovec *vec;
bellard31e31b82003-02-18 22:55:36 +00004980
4981 vec = alloca(count * sizeof(struct iovec));
bellard41df8412008-02-04 22:26:57 +00004982 if (lock_iovec(VERIFY_WRITE, vec, arg2, count, 0) < 0)
4983 goto efault;
bellard31e31b82003-02-18 22:55:36 +00004984 ret = get_errno(readv(arg1, vec, count));
pbrook53a59602006-03-25 19:31:22 +00004985 unlock_iovec(vec, arg2, count, 1);
bellard31e31b82003-02-18 22:55:36 +00004986 }
4987 break;
4988 case TARGET_NR_writev:
4989 {
4990 int count = arg3;
bellard31e31b82003-02-18 22:55:36 +00004991 struct iovec *vec;
bellard31e31b82003-02-18 22:55:36 +00004992
4993 vec = alloca(count * sizeof(struct iovec));
bellard41df8412008-02-04 22:26:57 +00004994 if (lock_iovec(VERIFY_READ, vec, arg2, count, 1) < 0)
4995 goto efault;
bellard31e31b82003-02-18 22:55:36 +00004996 ret = get_errno(writev(arg1, vec, count));
pbrook53a59602006-03-25 19:31:22 +00004997 unlock_iovec(vec, arg2, count, 0);
bellard31e31b82003-02-18 22:55:36 +00004998 }
4999 break;
5000 case TARGET_NR_getsid:
5001 ret = get_errno(getsid(arg1));
5002 break;
j_mayer7a3148a2007-04-05 07:13:51 +00005003#if defined(TARGET_NR_fdatasync) /* Not on alpha (osf_datasync ?) */
bellard31e31b82003-02-18 22:55:36 +00005004 case TARGET_NR_fdatasync:
bellard5cd43932003-03-29 16:54:36 +00005005 ret = get_errno(fdatasync(arg1));
5006 break;
j_mayer7a3148a2007-04-05 07:13:51 +00005007#endif
bellard31e31b82003-02-18 22:55:36 +00005008 case TARGET_NR__sysctl:
ths0da46a62007-10-20 20:23:07 +00005009 /* We don't implement this, but ENOTDIR is always a safe
bellard29e619b2004-09-13 21:41:04 +00005010 return value. */
ths0da46a62007-10-20 20:23:07 +00005011 ret = -TARGET_ENOTDIR;
5012 break;
bellard31e31b82003-02-18 22:55:36 +00005013 case TARGET_NR_sched_setparam:
bellard5cd43932003-03-29 16:54:36 +00005014 {
pbrook53a59602006-03-25 19:31:22 +00005015 struct sched_param *target_schp;
bellard5cd43932003-03-29 16:54:36 +00005016 struct sched_param schp;
pbrook53a59602006-03-25 19:31:22 +00005017
bellard579a97f2007-11-11 14:26:47 +00005018 if (!lock_user_struct(VERIFY_READ, target_schp, arg2, 1))
5019 goto efault;
bellard5cd43932003-03-29 16:54:36 +00005020 schp.sched_priority = tswap32(target_schp->sched_priority);
pbrook53a59602006-03-25 19:31:22 +00005021 unlock_user_struct(target_schp, arg2, 0);
bellard5cd43932003-03-29 16:54:36 +00005022 ret = get_errno(sched_setparam(arg1, &schp));
5023 }
5024 break;
bellard31e31b82003-02-18 22:55:36 +00005025 case TARGET_NR_sched_getparam:
bellard5cd43932003-03-29 16:54:36 +00005026 {
pbrook53a59602006-03-25 19:31:22 +00005027 struct sched_param *target_schp;
bellard5cd43932003-03-29 16:54:36 +00005028 struct sched_param schp;
5029 ret = get_errno(sched_getparam(arg1, &schp));
5030 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00005031 if (!lock_user_struct(VERIFY_WRITE, target_schp, arg2, 0))
5032 goto efault;
bellard5cd43932003-03-29 16:54:36 +00005033 target_schp->sched_priority = tswap32(schp.sched_priority);
pbrook53a59602006-03-25 19:31:22 +00005034 unlock_user_struct(target_schp, arg2, 1);
bellard5cd43932003-03-29 16:54:36 +00005035 }
5036 }
5037 break;
bellard31e31b82003-02-18 22:55:36 +00005038 case TARGET_NR_sched_setscheduler:
bellard5cd43932003-03-29 16:54:36 +00005039 {
pbrook53a59602006-03-25 19:31:22 +00005040 struct sched_param *target_schp;
bellard5cd43932003-03-29 16:54:36 +00005041 struct sched_param schp;
bellard579a97f2007-11-11 14:26:47 +00005042 if (!lock_user_struct(VERIFY_READ, target_schp, arg3, 1))
5043 goto efault;
bellard5cd43932003-03-29 16:54:36 +00005044 schp.sched_priority = tswap32(target_schp->sched_priority);
pbrook53a59602006-03-25 19:31:22 +00005045 unlock_user_struct(target_schp, arg3, 0);
bellard5cd43932003-03-29 16:54:36 +00005046 ret = get_errno(sched_setscheduler(arg1, arg2, &schp));
5047 }
5048 break;
bellard31e31b82003-02-18 22:55:36 +00005049 case TARGET_NR_sched_getscheduler:
bellard5cd43932003-03-29 16:54:36 +00005050 ret = get_errno(sched_getscheduler(arg1));
5051 break;
bellard31e31b82003-02-18 22:55:36 +00005052 case TARGET_NR_sched_yield:
5053 ret = get_errno(sched_yield());
5054 break;
5055 case TARGET_NR_sched_get_priority_max:
bellard5cd43932003-03-29 16:54:36 +00005056 ret = get_errno(sched_get_priority_max(arg1));
5057 break;
bellard31e31b82003-02-18 22:55:36 +00005058 case TARGET_NR_sched_get_priority_min:
bellard5cd43932003-03-29 16:54:36 +00005059 ret = get_errno(sched_get_priority_min(arg1));
5060 break;
bellard31e31b82003-02-18 22:55:36 +00005061 case TARGET_NR_sched_rr_get_interval:
bellard5cd43932003-03-29 16:54:36 +00005062 {
bellard5cd43932003-03-29 16:54:36 +00005063 struct timespec ts;
5064 ret = get_errno(sched_rr_get_interval(arg1, &ts));
5065 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00005066 host_to_target_timespec(arg2, &ts);
bellard5cd43932003-03-29 16:54:36 +00005067 }
5068 }
5069 break;
bellard31e31b82003-02-18 22:55:36 +00005070 case TARGET_NR_nanosleep:
bellard1b6b0292003-03-22 17:31:38 +00005071 {
bellard1b6b0292003-03-22 17:31:38 +00005072 struct timespec req, rem;
pbrook53a59602006-03-25 19:31:22 +00005073 target_to_host_timespec(&req, arg1);
bellard1b6b0292003-03-22 17:31:38 +00005074 ret = get_errno(nanosleep(&req, &rem));
pbrook53a59602006-03-25 19:31:22 +00005075 if (is_error(ret) && arg2) {
5076 host_to_target_timespec(arg2, &rem);
bellard1b6b0292003-03-22 17:31:38 +00005077 }
5078 }
5079 break;
thse5febef2007-04-01 18:31:35 +00005080#ifdef TARGET_NR_query_module
bellard31e31b82003-02-18 22:55:36 +00005081 case TARGET_NR_query_module:
bellard5cd43932003-03-29 16:54:36 +00005082 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00005083#endif
5084#ifdef TARGET_NR_nfsservctl
bellard31e31b82003-02-18 22:55:36 +00005085 case TARGET_NR_nfsservctl:
bellard5cd43932003-03-29 16:54:36 +00005086 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00005087#endif
bellard31e31b82003-02-18 22:55:36 +00005088 case TARGET_NR_prctl:
thse5574482007-02-11 20:03:13 +00005089 switch (arg1)
5090 {
5091 case PR_GET_PDEATHSIG:
5092 {
5093 int deathsig;
5094 ret = get_errno(prctl(arg1, &deathsig, arg3, arg4, arg5));
bellard2f619692007-11-16 10:46:05 +00005095 if (!is_error(ret) && arg2
5096 && put_user_ual(deathsig, arg2))
5097 goto efault;
thse5574482007-02-11 20:03:13 +00005098 }
5099 break;
5100 default:
5101 ret = get_errno(prctl(arg1, arg2, arg3, arg4, arg5));
5102 break;
5103 }
ths39b9aae2007-02-11 18:36:44 +00005104 break;
bellardd2fd1af2007-11-14 18:08:56 +00005105#ifdef TARGET_NR_arch_prctl
5106 case TARGET_NR_arch_prctl:
5107#if defined(TARGET_I386) && !defined(TARGET_ABI32)
5108 ret = do_arch_prctl(cpu_env, arg1, arg2);
5109 break;
5110#else
5111 goto unimplemented;
5112#endif
5113#endif
bellard67867302003-11-23 17:05:30 +00005114#ifdef TARGET_NR_pread
bellard31e31b82003-02-18 22:55:36 +00005115 case TARGET_NR_pread:
bellard579a97f2007-11-11 14:26:47 +00005116 if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
5117 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005118 ret = get_errno(pread(arg1, p, arg3, arg4));
5119 unlock_user(p, arg2, ret);
bellard206f0fa2003-05-14 19:01:56 +00005120 break;
bellard31e31b82003-02-18 22:55:36 +00005121 case TARGET_NR_pwrite:
bellard579a97f2007-11-11 14:26:47 +00005122 if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
5123 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005124 ret = get_errno(pwrite(arg1, p, arg3, arg4));
5125 unlock_user(p, arg2, 0);
bellard206f0fa2003-05-14 19:01:56 +00005126 break;
bellard67867302003-11-23 17:05:30 +00005127#endif
aurel32f2c7ba12008-03-28 22:32:06 +00005128#ifdef TARGET_NR_pread64
5129 case TARGET_NR_pread64:
5130 if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
5131 goto efault;
5132 ret = get_errno(pread64(arg1, p, arg3, target_offset64(arg4, arg5)));
5133 unlock_user(p, arg2, ret);
5134 break;
5135 case TARGET_NR_pwrite64:
5136 if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
5137 goto efault;
5138 ret = get_errno(pwrite64(arg1, p, arg3, target_offset64(arg4, arg5)));
5139 unlock_user(p, arg2, 0);
5140 break;
5141#endif
bellard31e31b82003-02-18 22:55:36 +00005142 case TARGET_NR_getcwd:
bellard579a97f2007-11-11 14:26:47 +00005143 if (!(p = lock_user(VERIFY_WRITE, arg1, arg2, 0)))
5144 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005145 ret = get_errno(sys_getcwd1(p, arg2));
5146 unlock_user(p, arg1, ret);
bellard31e31b82003-02-18 22:55:36 +00005147 break;
5148 case TARGET_NR_capget:
bellard5cd43932003-03-29 16:54:36 +00005149 goto unimplemented;
bellard31e31b82003-02-18 22:55:36 +00005150 case TARGET_NR_capset:
bellard5cd43932003-03-29 16:54:36 +00005151 goto unimplemented;
bellard31e31b82003-02-18 22:55:36 +00005152 case TARGET_NR_sigaltstack:
ths198a74d2007-09-27 16:44:32 +00005153#if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_MIPS) || \
5154 defined(TARGET_SPARC) || defined(TARGET_PPC) || defined(TARGET_ALPHA)
bellard579a97f2007-11-11 14:26:47 +00005155 ret = do_sigaltstack(arg1, arg2, get_sp_from_cpustate((CPUState *)cpu_env));
thsa04e1342007-09-27 13:57:58 +00005156 break;
5157#else
bellard5cd43932003-03-29 16:54:36 +00005158 goto unimplemented;
thsa04e1342007-09-27 13:57:58 +00005159#endif
bellard31e31b82003-02-18 22:55:36 +00005160 case TARGET_NR_sendfile:
bellard5cd43932003-03-29 16:54:36 +00005161 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00005162#ifdef TARGET_NR_getpmsg
bellard31e31b82003-02-18 22:55:36 +00005163 case TARGET_NR_getpmsg:
bellard5cd43932003-03-29 16:54:36 +00005164 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00005165#endif
5166#ifdef TARGET_NR_putpmsg
bellard31e31b82003-02-18 22:55:36 +00005167 case TARGET_NR_putpmsg:
bellard5cd43932003-03-29 16:54:36 +00005168 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00005169#endif
bellard048f6b42005-11-26 18:47:20 +00005170#ifdef TARGET_NR_vfork
bellard31e31b82003-02-18 22:55:36 +00005171 case TARGET_NR_vfork:
pbrookd865bab2008-06-07 22:12:17 +00005172 ret = get_errno(do_fork(cpu_env, CLONE_VFORK | CLONE_VM | SIGCHLD,
5173 0, 0, 0, 0));
bellard31e31b82003-02-18 22:55:36 +00005174 break;
bellard048f6b42005-11-26 18:47:20 +00005175#endif
bellardebc05482003-09-30 21:08:41 +00005176#ifdef TARGET_NR_ugetrlimit
bellard31e31b82003-02-18 22:55:36 +00005177 case TARGET_NR_ugetrlimit:
bellard728584b2003-04-29 20:43:36 +00005178 {
5179 struct rlimit rlim;
5180 ret = get_errno(getrlimit(arg1, &rlim));
5181 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00005182 struct target_rlimit *target_rlim;
bellard579a97f2007-11-11 14:26:47 +00005183 if (!lock_user_struct(VERIFY_WRITE, target_rlim, arg2, 0))
5184 goto efault;
bellard728584b2003-04-29 20:43:36 +00005185 target_rlim->rlim_cur = tswapl(rlim.rlim_cur);
5186 target_rlim->rlim_max = tswapl(rlim.rlim_max);
pbrook53a59602006-03-25 19:31:22 +00005187 unlock_user_struct(target_rlim, arg2, 1);
bellard728584b2003-04-29 20:43:36 +00005188 }
5189 break;
5190 }
bellardebc05482003-09-30 21:08:41 +00005191#endif
bellarda315a142005-01-30 22:59:18 +00005192#ifdef TARGET_NR_truncate64
bellard31e31b82003-02-18 22:55:36 +00005193 case TARGET_NR_truncate64:
bellard579a97f2007-11-11 14:26:47 +00005194 if (!(p = lock_user_string(arg1)))
5195 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005196 ret = target_truncate64(cpu_env, p, arg2, arg3, arg4);
5197 unlock_user(p, arg1, 0);
bellard667f38b2005-07-23 14:46:27 +00005198 break;
bellarda315a142005-01-30 22:59:18 +00005199#endif
5200#ifdef TARGET_NR_ftruncate64
bellard31e31b82003-02-18 22:55:36 +00005201 case TARGET_NR_ftruncate64:
pbrookce4defa2006-02-09 16:49:55 +00005202 ret = target_ftruncate64(cpu_env, arg1, arg2, arg3, arg4);
bellard667f38b2005-07-23 14:46:27 +00005203 break;
bellarda315a142005-01-30 22:59:18 +00005204#endif
5205#ifdef TARGET_NR_stat64
bellard31e31b82003-02-18 22:55:36 +00005206 case TARGET_NR_stat64:
bellard579a97f2007-11-11 14:26:47 +00005207 if (!(p = lock_user_string(arg1)))
5208 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005209 ret = get_errno(stat(path(p), &st));
5210 unlock_user(p, arg1, 0);
balrog6a24a772008-09-20 02:23:36 +00005211 if (!is_error(ret))
5212 ret = host_to_target_stat64(cpu_env, arg2, &st);
5213 break;
bellarda315a142005-01-30 22:59:18 +00005214#endif
5215#ifdef TARGET_NR_lstat64
bellard31e31b82003-02-18 22:55:36 +00005216 case TARGET_NR_lstat64:
bellard579a97f2007-11-11 14:26:47 +00005217 if (!(p = lock_user_string(arg1)))
5218 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005219 ret = get_errno(lstat(path(p), &st));
5220 unlock_user(p, arg1, 0);
balrog6a24a772008-09-20 02:23:36 +00005221 if (!is_error(ret))
5222 ret = host_to_target_stat64(cpu_env, arg2, &st);
5223 break;
bellarda315a142005-01-30 22:59:18 +00005224#endif
5225#ifdef TARGET_NR_fstat64
bellard31e31b82003-02-18 22:55:36 +00005226 case TARGET_NR_fstat64:
balrog6a24a772008-09-20 02:23:36 +00005227 ret = get_errno(fstat(arg1, &st));
5228 if (!is_error(ret))
5229 ret = host_to_target_stat64(cpu_env, arg2, &st);
5230 break;
bellardec86b0f2003-04-11 00:15:04 +00005231#endif
balrog6a24a772008-09-20 02:23:36 +00005232#if defined(TARGET_NR_fstatat64) && defined(__NR_fstatat64)
5233 case TARGET_NR_fstatat64:
5234 if (!(p = lock_user_string(arg2)))
5235 goto efault;
5236 ret = get_errno(sys_fstatat64(arg1, path(p), &st, arg4));
5237 if (!is_error(ret))
5238 ret = host_to_target_stat64(cpu_env, arg3, &st);
bellard60cd49d2003-03-16 22:53:56 +00005239 break;
bellarda315a142005-01-30 22:59:18 +00005240#endif
bellard67867302003-11-23 17:05:30 +00005241#ifdef USE_UID16
5242 case TARGET_NR_lchown:
bellard579a97f2007-11-11 14:26:47 +00005243 if (!(p = lock_user_string(arg1)))
5244 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005245 ret = get_errno(lchown(p, low2highuid(arg2), low2highgid(arg3)));
5246 unlock_user(p, arg1, 0);
bellard67867302003-11-23 17:05:30 +00005247 break;
5248 case TARGET_NR_getuid:
5249 ret = get_errno(high2lowuid(getuid()));
5250 break;
5251 case TARGET_NR_getgid:
5252 ret = get_errno(high2lowgid(getgid()));
5253 break;
5254 case TARGET_NR_geteuid:
5255 ret = get_errno(high2lowuid(geteuid()));
5256 break;
5257 case TARGET_NR_getegid:
5258 ret = get_errno(high2lowgid(getegid()));
5259 break;
5260 case TARGET_NR_setreuid:
5261 ret = get_errno(setreuid(low2highuid(arg1), low2highuid(arg2)));
5262 break;
5263 case TARGET_NR_setregid:
5264 ret = get_errno(setregid(low2highgid(arg1), low2highgid(arg2)));
5265 break;
5266 case TARGET_NR_getgroups:
5267 {
5268 int gidsetsize = arg1;
pbrook53a59602006-03-25 19:31:22 +00005269 uint16_t *target_grouplist;
bellard67867302003-11-23 17:05:30 +00005270 gid_t *grouplist;
5271 int i;
5272
5273 grouplist = alloca(gidsetsize * sizeof(gid_t));
5274 ret = get_errno(getgroups(gidsetsize, grouplist));
balrogcb3bc232008-09-20 02:08:13 +00005275 if (gidsetsize == 0)
5276 break;
bellard67867302003-11-23 17:05:30 +00005277 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00005278 target_grouplist = lock_user(VERIFY_WRITE, arg2, gidsetsize * 2, 0);
5279 if (!target_grouplist)
5280 goto efault;
balroga2155fc2008-09-20 02:12:08 +00005281 for(i = 0;i < ret; i++)
bellard67867302003-11-23 17:05:30 +00005282 target_grouplist[i] = tswap16(grouplist[i]);
pbrook53a59602006-03-25 19:31:22 +00005283 unlock_user(target_grouplist, arg2, gidsetsize * 2);
bellard67867302003-11-23 17:05:30 +00005284 }
5285 }
5286 break;
5287 case TARGET_NR_setgroups:
5288 {
5289 int gidsetsize = arg1;
pbrook53a59602006-03-25 19:31:22 +00005290 uint16_t *target_grouplist;
bellard67867302003-11-23 17:05:30 +00005291 gid_t *grouplist;
5292 int i;
5293
5294 grouplist = alloca(gidsetsize * sizeof(gid_t));
bellard579a97f2007-11-11 14:26:47 +00005295 target_grouplist = lock_user(VERIFY_READ, arg2, gidsetsize * 2, 1);
5296 if (!target_grouplist) {
5297 ret = -TARGET_EFAULT;
5298 goto fail;
5299 }
bellard67867302003-11-23 17:05:30 +00005300 for(i = 0;i < gidsetsize; i++)
5301 grouplist[i] = tswap16(target_grouplist[i]);
pbrook53a59602006-03-25 19:31:22 +00005302 unlock_user(target_grouplist, arg2, 0);
bellard67867302003-11-23 17:05:30 +00005303 ret = get_errno(setgroups(gidsetsize, grouplist));
5304 }
5305 break;
5306 case TARGET_NR_fchown:
5307 ret = get_errno(fchown(arg1, low2highuid(arg2), low2highgid(arg3)));
5308 break;
thsccfa72b2007-09-24 09:23:34 +00005309#if defined(TARGET_NR_fchownat) && defined(__NR_fchownat)
5310 case TARGET_NR_fchownat:
bellard579a97f2007-11-11 14:26:47 +00005311 if (!(p = lock_user_string(arg2)))
5312 goto efault;
5313 ret = get_errno(sys_fchownat(arg1, p, low2highuid(arg3), low2highgid(arg4), arg5));
5314 unlock_user(p, arg2, 0);
thsccfa72b2007-09-24 09:23:34 +00005315 break;
5316#endif
bellard67867302003-11-23 17:05:30 +00005317#ifdef TARGET_NR_setresuid
5318 case TARGET_NR_setresuid:
ths5fafdf22007-09-16 21:08:06 +00005319 ret = get_errno(setresuid(low2highuid(arg1),
5320 low2highuid(arg2),
bellard67867302003-11-23 17:05:30 +00005321 low2highuid(arg3)));
5322 break;
5323#endif
5324#ifdef TARGET_NR_getresuid
5325 case TARGET_NR_getresuid:
5326 {
pbrook53a59602006-03-25 19:31:22 +00005327 uid_t ruid, euid, suid;
bellard67867302003-11-23 17:05:30 +00005328 ret = get_errno(getresuid(&ruid, &euid, &suid));
5329 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +00005330 if (put_user_u16(high2lowuid(ruid), arg1)
5331 || put_user_u16(high2lowuid(euid), arg2)
5332 || put_user_u16(high2lowuid(suid), arg3))
5333 goto efault;
bellard67867302003-11-23 17:05:30 +00005334 }
5335 }
5336 break;
5337#endif
5338#ifdef TARGET_NR_getresgid
5339 case TARGET_NR_setresgid:
ths5fafdf22007-09-16 21:08:06 +00005340 ret = get_errno(setresgid(low2highgid(arg1),
5341 low2highgid(arg2),
bellard67867302003-11-23 17:05:30 +00005342 low2highgid(arg3)));
5343 break;
5344#endif
5345#ifdef TARGET_NR_getresgid
5346 case TARGET_NR_getresgid:
5347 {
pbrook53a59602006-03-25 19:31:22 +00005348 gid_t rgid, egid, sgid;
bellard67867302003-11-23 17:05:30 +00005349 ret = get_errno(getresgid(&rgid, &egid, &sgid));
5350 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +00005351 if (put_user_u16(high2lowgid(rgid), arg1)
5352 || put_user_u16(high2lowgid(egid), arg2)
5353 || put_user_u16(high2lowgid(sgid), arg3))
5354 goto efault;
bellard67867302003-11-23 17:05:30 +00005355 }
5356 }
5357 break;
5358#endif
5359 case TARGET_NR_chown:
bellard579a97f2007-11-11 14:26:47 +00005360 if (!(p = lock_user_string(arg1)))
5361 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005362 ret = get_errno(chown(p, low2highuid(arg2), low2highgid(arg3)));
5363 unlock_user(p, arg1, 0);
bellard67867302003-11-23 17:05:30 +00005364 break;
5365 case TARGET_NR_setuid:
5366 ret = get_errno(setuid(low2highuid(arg1)));
5367 break;
5368 case TARGET_NR_setgid:
5369 ret = get_errno(setgid(low2highgid(arg1)));
5370 break;
5371 case TARGET_NR_setfsuid:
5372 ret = get_errno(setfsuid(arg1));
5373 break;
5374 case TARGET_NR_setfsgid:
5375 ret = get_errno(setfsgid(arg1));
5376 break;
5377#endif /* USE_UID16 */
5378
bellarda315a142005-01-30 22:59:18 +00005379#ifdef TARGET_NR_lchown32
bellard31e31b82003-02-18 22:55:36 +00005380 case TARGET_NR_lchown32:
bellard579a97f2007-11-11 14:26:47 +00005381 if (!(p = lock_user_string(arg1)))
5382 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005383 ret = get_errno(lchown(p, arg2, arg3));
5384 unlock_user(p, arg1, 0);
bellardb03c60f2003-03-23 17:19:56 +00005385 break;
bellarda315a142005-01-30 22:59:18 +00005386#endif
5387#ifdef TARGET_NR_getuid32
bellard31e31b82003-02-18 22:55:36 +00005388 case TARGET_NR_getuid32:
bellardb03c60f2003-03-23 17:19:56 +00005389 ret = get_errno(getuid());
5390 break;
bellarda315a142005-01-30 22:59:18 +00005391#endif
5392#ifdef TARGET_NR_getgid32
bellard31e31b82003-02-18 22:55:36 +00005393 case TARGET_NR_getgid32:
bellardb03c60f2003-03-23 17:19:56 +00005394 ret = get_errno(getgid());
5395 break;
bellarda315a142005-01-30 22:59:18 +00005396#endif
5397#ifdef TARGET_NR_geteuid32
bellard31e31b82003-02-18 22:55:36 +00005398 case TARGET_NR_geteuid32:
bellardb03c60f2003-03-23 17:19:56 +00005399 ret = get_errno(geteuid());
5400 break;
bellarda315a142005-01-30 22:59:18 +00005401#endif
5402#ifdef TARGET_NR_getegid32
bellard31e31b82003-02-18 22:55:36 +00005403 case TARGET_NR_getegid32:
bellardb03c60f2003-03-23 17:19:56 +00005404 ret = get_errno(getegid());
5405 break;
bellarda315a142005-01-30 22:59:18 +00005406#endif
5407#ifdef TARGET_NR_setreuid32
bellard31e31b82003-02-18 22:55:36 +00005408 case TARGET_NR_setreuid32:
bellardb03c60f2003-03-23 17:19:56 +00005409 ret = get_errno(setreuid(arg1, arg2));
5410 break;
bellarda315a142005-01-30 22:59:18 +00005411#endif
5412#ifdef TARGET_NR_setregid32
bellard31e31b82003-02-18 22:55:36 +00005413 case TARGET_NR_setregid32:
bellardb03c60f2003-03-23 17:19:56 +00005414 ret = get_errno(setregid(arg1, arg2));
5415 break;
bellarda315a142005-01-30 22:59:18 +00005416#endif
5417#ifdef TARGET_NR_getgroups32
bellard31e31b82003-02-18 22:55:36 +00005418 case TARGET_NR_getgroups32:
bellard99c475a2005-01-31 20:45:13 +00005419 {
5420 int gidsetsize = arg1;
pbrook53a59602006-03-25 19:31:22 +00005421 uint32_t *target_grouplist;
bellard99c475a2005-01-31 20:45:13 +00005422 gid_t *grouplist;
5423 int i;
5424
5425 grouplist = alloca(gidsetsize * sizeof(gid_t));
5426 ret = get_errno(getgroups(gidsetsize, grouplist));
balrogcb3bc232008-09-20 02:08:13 +00005427 if (gidsetsize == 0)
5428 break;
bellard99c475a2005-01-31 20:45:13 +00005429 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00005430 target_grouplist = lock_user(VERIFY_WRITE, arg2, gidsetsize * 4, 0);
5431 if (!target_grouplist) {
5432 ret = -TARGET_EFAULT;
5433 goto fail;
5434 }
balroga2155fc2008-09-20 02:12:08 +00005435 for(i = 0;i < ret; i++)
pbrook53a59602006-03-25 19:31:22 +00005436 target_grouplist[i] = tswap32(grouplist[i]);
5437 unlock_user(target_grouplist, arg2, gidsetsize * 4);
bellard99c475a2005-01-31 20:45:13 +00005438 }
5439 }
5440 break;
bellarda315a142005-01-30 22:59:18 +00005441#endif
5442#ifdef TARGET_NR_setgroups32
bellard31e31b82003-02-18 22:55:36 +00005443 case TARGET_NR_setgroups32:
bellard99c475a2005-01-31 20:45:13 +00005444 {
5445 int gidsetsize = arg1;
pbrook53a59602006-03-25 19:31:22 +00005446 uint32_t *target_grouplist;
bellard99c475a2005-01-31 20:45:13 +00005447 gid_t *grouplist;
5448 int i;
ths3b46e622007-09-17 08:09:54 +00005449
bellard99c475a2005-01-31 20:45:13 +00005450 grouplist = alloca(gidsetsize * sizeof(gid_t));
bellard579a97f2007-11-11 14:26:47 +00005451 target_grouplist = lock_user(VERIFY_READ, arg2, gidsetsize * 4, 1);
5452 if (!target_grouplist) {
5453 ret = -TARGET_EFAULT;
5454 goto fail;
5455 }
bellard99c475a2005-01-31 20:45:13 +00005456 for(i = 0;i < gidsetsize; i++)
pbrook53a59602006-03-25 19:31:22 +00005457 grouplist[i] = tswap32(target_grouplist[i]);
5458 unlock_user(target_grouplist, arg2, 0);
bellard99c475a2005-01-31 20:45:13 +00005459 ret = get_errno(setgroups(gidsetsize, grouplist));
5460 }
5461 break;
bellarda315a142005-01-30 22:59:18 +00005462#endif
5463#ifdef TARGET_NR_fchown32
bellard31e31b82003-02-18 22:55:36 +00005464 case TARGET_NR_fchown32:
bellardb03c60f2003-03-23 17:19:56 +00005465 ret = get_errno(fchown(arg1, arg2, arg3));
5466 break;
bellarda315a142005-01-30 22:59:18 +00005467#endif
5468#ifdef TARGET_NR_setresuid32
bellard31e31b82003-02-18 22:55:36 +00005469 case TARGET_NR_setresuid32:
bellardb03c60f2003-03-23 17:19:56 +00005470 ret = get_errno(setresuid(arg1, arg2, arg3));
5471 break;
bellarda315a142005-01-30 22:59:18 +00005472#endif
5473#ifdef TARGET_NR_getresuid32
bellard31e31b82003-02-18 22:55:36 +00005474 case TARGET_NR_getresuid32:
bellardb03c60f2003-03-23 17:19:56 +00005475 {
pbrook53a59602006-03-25 19:31:22 +00005476 uid_t ruid, euid, suid;
bellardb03c60f2003-03-23 17:19:56 +00005477 ret = get_errno(getresuid(&ruid, &euid, &suid));
5478 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +00005479 if (put_user_u32(ruid, arg1)
5480 || put_user_u32(euid, arg2)
5481 || put_user_u32(suid, arg3))
5482 goto efault;
bellardb03c60f2003-03-23 17:19:56 +00005483 }
5484 }
5485 break;
bellarda315a142005-01-30 22:59:18 +00005486#endif
5487#ifdef TARGET_NR_setresgid32
bellard31e31b82003-02-18 22:55:36 +00005488 case TARGET_NR_setresgid32:
bellardb03c60f2003-03-23 17:19:56 +00005489 ret = get_errno(setresgid(arg1, arg2, arg3));
5490 break;
bellarda315a142005-01-30 22:59:18 +00005491#endif
5492#ifdef TARGET_NR_getresgid32
bellard31e31b82003-02-18 22:55:36 +00005493 case TARGET_NR_getresgid32:
bellardb03c60f2003-03-23 17:19:56 +00005494 {
pbrook53a59602006-03-25 19:31:22 +00005495 gid_t rgid, egid, sgid;
bellardb03c60f2003-03-23 17:19:56 +00005496 ret = get_errno(getresgid(&rgid, &egid, &sgid));
5497 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +00005498 if (put_user_u32(rgid, arg1)
5499 || put_user_u32(egid, arg2)
5500 || put_user_u32(sgid, arg3))
5501 goto efault;
bellardb03c60f2003-03-23 17:19:56 +00005502 }
5503 }
5504 break;
bellarda315a142005-01-30 22:59:18 +00005505#endif
5506#ifdef TARGET_NR_chown32
bellard31e31b82003-02-18 22:55:36 +00005507 case TARGET_NR_chown32:
bellard579a97f2007-11-11 14:26:47 +00005508 if (!(p = lock_user_string(arg1)))
5509 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005510 ret = get_errno(chown(p, arg2, arg3));
5511 unlock_user(p, arg1, 0);
bellardb03c60f2003-03-23 17:19:56 +00005512 break;
bellarda315a142005-01-30 22:59:18 +00005513#endif
5514#ifdef TARGET_NR_setuid32
bellard31e31b82003-02-18 22:55:36 +00005515 case TARGET_NR_setuid32:
bellardb03c60f2003-03-23 17:19:56 +00005516 ret = get_errno(setuid(arg1));
5517 break;
bellarda315a142005-01-30 22:59:18 +00005518#endif
5519#ifdef TARGET_NR_setgid32
bellard31e31b82003-02-18 22:55:36 +00005520 case TARGET_NR_setgid32:
bellardb03c60f2003-03-23 17:19:56 +00005521 ret = get_errno(setgid(arg1));
5522 break;
bellarda315a142005-01-30 22:59:18 +00005523#endif
5524#ifdef TARGET_NR_setfsuid32
bellard31e31b82003-02-18 22:55:36 +00005525 case TARGET_NR_setfsuid32:
bellardb03c60f2003-03-23 17:19:56 +00005526 ret = get_errno(setfsuid(arg1));
5527 break;
bellarda315a142005-01-30 22:59:18 +00005528#endif
5529#ifdef TARGET_NR_setfsgid32
bellard31e31b82003-02-18 22:55:36 +00005530 case TARGET_NR_setfsgid32:
bellardb03c60f2003-03-23 17:19:56 +00005531 ret = get_errno(setfsgid(arg1));
5532 break;
bellarda315a142005-01-30 22:59:18 +00005533#endif
bellard67867302003-11-23 17:05:30 +00005534
bellard31e31b82003-02-18 22:55:36 +00005535 case TARGET_NR_pivot_root:
bellardb03c60f2003-03-23 17:19:56 +00005536 goto unimplemented;
bellardffa65c32004-01-04 23:57:22 +00005537#ifdef TARGET_NR_mincore
bellard31e31b82003-02-18 22:55:36 +00005538 case TARGET_NR_mincore:
bellardb03c60f2003-03-23 17:19:56 +00005539 goto unimplemented;
bellardffa65c32004-01-04 23:57:22 +00005540#endif
5541#ifdef TARGET_NR_madvise
bellard31e31b82003-02-18 22:55:36 +00005542 case TARGET_NR_madvise:
pbrook24836682006-04-16 14:14:53 +00005543 /* A straight passthrough may not be safe because qemu sometimes
5544 turns private flie-backed mappings into anonymous mappings.
5545 This will break MADV_DONTNEED.
5546 This is a hint, so ignoring and returning success is ok. */
5547 ret = get_errno(0);
5548 break;
bellardffa65c32004-01-04 23:57:22 +00005549#endif
blueswir1992f48a2007-10-14 16:27:31 +00005550#if TARGET_ABI_BITS == 32
bellard31e31b82003-02-18 22:55:36 +00005551 case TARGET_NR_fcntl64:
bellard77e46722003-04-29 20:39:06 +00005552 {
thsb1e341e2007-03-20 21:50:52 +00005553 int cmd;
bellard77e46722003-04-29 20:39:06 +00005554 struct flock64 fl;
pbrook53a59602006-03-25 19:31:22 +00005555 struct target_flock64 *target_fl;
pbrookce4defa2006-02-09 16:49:55 +00005556#ifdef TARGET_ARM
pbrook53a59602006-03-25 19:31:22 +00005557 struct target_eabi_flock64 *target_efl;
pbrookce4defa2006-02-09 16:49:55 +00005558#endif
bellard77e46722003-04-29 20:39:06 +00005559
thsb1e341e2007-03-20 21:50:52 +00005560 switch(arg2){
5561 case TARGET_F_GETLK64:
5562 cmd = F_GETLK64;
thsa7222582007-03-22 15:08:55 +00005563 break;
thsb1e341e2007-03-20 21:50:52 +00005564 case TARGET_F_SETLK64:
5565 cmd = F_SETLK64;
thsa7222582007-03-22 15:08:55 +00005566 break;
thsb1e341e2007-03-20 21:50:52 +00005567 case TARGET_F_SETLKW64:
5568 cmd = F_SETLK64;
thsa7222582007-03-22 15:08:55 +00005569 break;
thsb1e341e2007-03-20 21:50:52 +00005570 default:
5571 cmd = arg2;
thsa7222582007-03-22 15:08:55 +00005572 break;
thsb1e341e2007-03-20 21:50:52 +00005573 }
5574
bellard60cd49d2003-03-16 22:53:56 +00005575 switch(arg2) {
thsb1e341e2007-03-20 21:50:52 +00005576 case TARGET_F_GETLK64:
ths58134272007-03-31 18:59:32 +00005577#ifdef TARGET_ARM
5578 if (((CPUARMState *)cpu_env)->eabi) {
bellard9ee1fa22007-11-11 15:11:19 +00005579 if (!lock_user_struct(VERIFY_READ, target_efl, arg3, 1))
5580 goto efault;
ths58134272007-03-31 18:59:32 +00005581 fl.l_type = tswap16(target_efl->l_type);
5582 fl.l_whence = tswap16(target_efl->l_whence);
5583 fl.l_start = tswap64(target_efl->l_start);
5584 fl.l_len = tswap64(target_efl->l_len);
5585 fl.l_pid = tswapl(target_efl->l_pid);
5586 unlock_user_struct(target_efl, arg3, 0);
5587 } else
5588#endif
5589 {
bellard9ee1fa22007-11-11 15:11:19 +00005590 if (!lock_user_struct(VERIFY_READ, target_fl, arg3, 1))
5591 goto efault;
ths58134272007-03-31 18:59:32 +00005592 fl.l_type = tswap16(target_fl->l_type);
5593 fl.l_whence = tswap16(target_fl->l_whence);
5594 fl.l_start = tswap64(target_fl->l_start);
5595 fl.l_len = tswap64(target_fl->l_len);
5596 fl.l_pid = tswapl(target_fl->l_pid);
5597 unlock_user_struct(target_fl, arg3, 0);
5598 }
thsb1e341e2007-03-20 21:50:52 +00005599 ret = get_errno(fcntl(arg1, cmd, &fl));
bellard77e46722003-04-29 20:39:06 +00005600 if (ret == 0) {
pbrookce4defa2006-02-09 16:49:55 +00005601#ifdef TARGET_ARM
5602 if (((CPUARMState *)cpu_env)->eabi) {
bellard9ee1fa22007-11-11 15:11:19 +00005603 if (!lock_user_struct(VERIFY_WRITE, target_efl, arg3, 0))
5604 goto efault;
pbrookce4defa2006-02-09 16:49:55 +00005605 target_efl->l_type = tswap16(fl.l_type);
5606 target_efl->l_whence = tswap16(fl.l_whence);
5607 target_efl->l_start = tswap64(fl.l_start);
5608 target_efl->l_len = tswap64(fl.l_len);
5609 target_efl->l_pid = tswapl(fl.l_pid);
pbrook53a59602006-03-25 19:31:22 +00005610 unlock_user_struct(target_efl, arg3, 1);
pbrookce4defa2006-02-09 16:49:55 +00005611 } else
5612#endif
5613 {
bellard9ee1fa22007-11-11 15:11:19 +00005614 if (!lock_user_struct(VERIFY_WRITE, target_fl, arg3, 0))
5615 goto efault;
pbrookce4defa2006-02-09 16:49:55 +00005616 target_fl->l_type = tswap16(fl.l_type);
5617 target_fl->l_whence = tswap16(fl.l_whence);
5618 target_fl->l_start = tswap64(fl.l_start);
5619 target_fl->l_len = tswap64(fl.l_len);
5620 target_fl->l_pid = tswapl(fl.l_pid);
pbrook53a59602006-03-25 19:31:22 +00005621 unlock_user_struct(target_fl, arg3, 1);
pbrookce4defa2006-02-09 16:49:55 +00005622 }
bellard77e46722003-04-29 20:39:06 +00005623 }
5624 break;
5625
thsb1e341e2007-03-20 21:50:52 +00005626 case TARGET_F_SETLK64:
5627 case TARGET_F_SETLKW64:
pbrookce4defa2006-02-09 16:49:55 +00005628#ifdef TARGET_ARM
5629 if (((CPUARMState *)cpu_env)->eabi) {
bellard9ee1fa22007-11-11 15:11:19 +00005630 if (!lock_user_struct(VERIFY_READ, target_efl, arg3, 1))
5631 goto efault;
pbrookce4defa2006-02-09 16:49:55 +00005632 fl.l_type = tswap16(target_efl->l_type);
5633 fl.l_whence = tswap16(target_efl->l_whence);
5634 fl.l_start = tswap64(target_efl->l_start);
5635 fl.l_len = tswap64(target_efl->l_len);
5636 fl.l_pid = tswapl(target_efl->l_pid);
pbrook53a59602006-03-25 19:31:22 +00005637 unlock_user_struct(target_efl, arg3, 0);
pbrookce4defa2006-02-09 16:49:55 +00005638 } else
5639#endif
5640 {
bellard9ee1fa22007-11-11 15:11:19 +00005641 if (!lock_user_struct(VERIFY_READ, target_fl, arg3, 1))
5642 goto efault;
pbrookce4defa2006-02-09 16:49:55 +00005643 fl.l_type = tswap16(target_fl->l_type);
5644 fl.l_whence = tswap16(target_fl->l_whence);
5645 fl.l_start = tswap64(target_fl->l_start);
5646 fl.l_len = tswap64(target_fl->l_len);
5647 fl.l_pid = tswapl(target_fl->l_pid);
pbrook53a59602006-03-25 19:31:22 +00005648 unlock_user_struct(target_fl, arg3, 0);
pbrookce4defa2006-02-09 16:49:55 +00005649 }
thsb1e341e2007-03-20 21:50:52 +00005650 ret = get_errno(fcntl(arg1, cmd, &fl));
bellard77e46722003-04-29 20:39:06 +00005651 break;
bellard60cd49d2003-03-16 22:53:56 +00005652 default:
bellard9ee1fa22007-11-11 15:11:19 +00005653 ret = do_fcntl(arg1, cmd, arg3);
bellard60cd49d2003-03-16 22:53:56 +00005654 break;
5655 }
bellard77e46722003-04-29 20:39:06 +00005656 break;
5657 }
bellard60cd49d2003-03-16 22:53:56 +00005658#endif
ths7d600c82006-12-08 01:32:58 +00005659#ifdef TARGET_NR_cacheflush
5660 case TARGET_NR_cacheflush:
5661 /* self-modifying code is handled automatically, so nothing needed */
5662 ret = 0;
5663 break;
5664#endif
bellardebc05482003-09-30 21:08:41 +00005665#ifdef TARGET_NR_security
bellard31e31b82003-02-18 22:55:36 +00005666 case TARGET_NR_security:
5667 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00005668#endif
bellardc573ff62004-01-04 15:51:36 +00005669#ifdef TARGET_NR_getpagesize
5670 case TARGET_NR_getpagesize:
5671 ret = TARGET_PAGE_SIZE;
5672 break;
5673#endif
bellard31e31b82003-02-18 22:55:36 +00005674 case TARGET_NR_gettid:
5675 ret = get_errno(gettid());
5676 break;
thse5febef2007-04-01 18:31:35 +00005677#ifdef TARGET_NR_readahead
bellard31e31b82003-02-18 22:55:36 +00005678 case TARGET_NR_readahead:
bellard5cd43932003-03-29 16:54:36 +00005679 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00005680#endif
bellardebc05482003-09-30 21:08:41 +00005681#ifdef TARGET_NR_setxattr
bellard31e31b82003-02-18 22:55:36 +00005682 case TARGET_NR_setxattr:
5683 case TARGET_NR_lsetxattr:
5684 case TARGET_NR_fsetxattr:
5685 case TARGET_NR_getxattr:
5686 case TARGET_NR_lgetxattr:
5687 case TARGET_NR_fgetxattr:
5688 case TARGET_NR_listxattr:
5689 case TARGET_NR_llistxattr:
5690 case TARGET_NR_flistxattr:
5691 case TARGET_NR_removexattr:
5692 case TARGET_NR_lremovexattr:
5693 case TARGET_NR_fremovexattr:
bellard5cd43932003-03-29 16:54:36 +00005694 goto unimplemented_nowarn;
bellardebc05482003-09-30 21:08:41 +00005695#endif
5696#ifdef TARGET_NR_set_thread_area
bellard5cd43932003-03-29 16:54:36 +00005697 case TARGET_NR_set_thread_area:
bellard8d18e892007-11-14 15:18:40 +00005698#if defined(TARGET_MIPS)
ths6f5b89a2007-03-02 20:48:00 +00005699 ((CPUMIPSState *) cpu_env)->tls_value = arg1;
5700 ret = 0;
5701 break;
bellard8d18e892007-11-14 15:18:40 +00005702#elif defined(TARGET_I386) && defined(TARGET_ABI32)
5703 ret = do_set_thread_area(cpu_env, arg1);
5704 break;
ths6f5b89a2007-03-02 20:48:00 +00005705#else
5706 goto unimplemented_nowarn;
5707#endif
5708#endif
5709#ifdef TARGET_NR_get_thread_area
bellard5cd43932003-03-29 16:54:36 +00005710 case TARGET_NR_get_thread_area:
bellard8d18e892007-11-14 15:18:40 +00005711#if defined(TARGET_I386) && defined(TARGET_ABI32)
5712 ret = do_get_thread_area(cpu_env, arg1);
5713#else
bellard5cd43932003-03-29 16:54:36 +00005714 goto unimplemented_nowarn;
bellardebc05482003-09-30 21:08:41 +00005715#endif
bellard8d18e892007-11-14 15:18:40 +00005716#endif
bellard48dc41e2006-06-21 18:15:50 +00005717#ifdef TARGET_NR_getdomainname
5718 case TARGET_NR_getdomainname:
5719 goto unimplemented_nowarn;
5720#endif
ths6f5b89a2007-03-02 20:48:00 +00005721
thsb5906f92007-03-19 13:32:45 +00005722#ifdef TARGET_NR_clock_gettime
5723 case TARGET_NR_clock_gettime:
5724 {
5725 struct timespec ts;
5726 ret = get_errno(clock_gettime(arg1, &ts));
5727 if (!is_error(ret)) {
5728 host_to_target_timespec(arg2, &ts);
5729 }
5730 break;
5731 }
5732#endif
5733#ifdef TARGET_NR_clock_getres
5734 case TARGET_NR_clock_getres:
5735 {
5736 struct timespec ts;
5737 ret = get_errno(clock_getres(arg1, &ts));
5738 if (!is_error(ret)) {
5739 host_to_target_timespec(arg2, &ts);
5740 }
5741 break;
5742 }
5743#endif
pbrook63d76512008-05-29 13:43:29 +00005744#ifdef TARGET_NR_clock_nanosleep
5745 case TARGET_NR_clock_nanosleep:
5746 {
5747 struct timespec ts;
5748 target_to_host_timespec(&ts, arg3);
5749 ret = get_errno(clock_nanosleep(arg1, arg2, &ts, arg4 ? &ts : NULL));
5750 if (arg4)
5751 host_to_target_timespec(arg4, &ts);
5752 break;
5753 }
5754#endif
thsb5906f92007-03-19 13:32:45 +00005755
ths6f5b89a2007-03-02 20:48:00 +00005756#if defined(TARGET_NR_set_tid_address) && defined(__NR_set_tid_address)
5757 case TARGET_NR_set_tid_address:
bellard579a97f2007-11-11 14:26:47 +00005758 ret = get_errno(set_tid_address((int *)g2h(arg1)));
5759 break;
ths6f5b89a2007-03-02 20:48:00 +00005760#endif
5761
ths3ae43202007-09-16 21:39:48 +00005762#if defined(TARGET_NR_tkill) && defined(__NR_tkill)
ths4cae1d12007-07-12 11:06:53 +00005763 case TARGET_NR_tkill:
pbrook4cb05962008-05-30 18:05:19 +00005764 ret = get_errno(sys_tkill((int)arg1, target_to_host_signal(arg2)));
ths4cae1d12007-07-12 11:06:53 +00005765 break;
5766#endif
5767
ths3ae43202007-09-16 21:39:48 +00005768#if defined(TARGET_NR_tgkill) && defined(__NR_tgkill)
ths71455572007-06-21 21:45:30 +00005769 case TARGET_NR_tgkill:
pbrook4cb05962008-05-30 18:05:19 +00005770 ret = get_errno(sys_tgkill((int)arg1, (int)arg2,
5771 target_to_host_signal(arg3)));
ths71455572007-06-21 21:45:30 +00005772 break;
5773#endif
5774
ths4f2b1fe2007-06-21 21:57:12 +00005775#ifdef TARGET_NR_set_robust_list
5776 case TARGET_NR_set_robust_list:
5777 goto unimplemented_nowarn;
5778#endif
5779
ths9007f0e2007-09-25 17:50:37 +00005780#if defined(TARGET_NR_utimensat) && defined(__NR_utimensat)
5781 case TARGET_NR_utimensat:
5782 {
5783 struct timespec ts[2];
5784 target_to_host_timespec(ts, arg3);
5785 target_to_host_timespec(ts+1, arg3+sizeof(struct target_timespec));
5786 if (!arg2)
5787 ret = get_errno(sys_utimensat(arg1, NULL, ts, arg4));
5788 else {
bellard579a97f2007-11-11 14:26:47 +00005789 if (!(p = lock_user_string(arg2))) {
ths0da46a62007-10-20 20:23:07 +00005790 ret = -TARGET_EFAULT;
bellard579a97f2007-11-11 14:26:47 +00005791 goto fail;
5792 }
5793 ret = get_errno(sys_utimensat(arg1, path(p), ts, arg4));
5794 unlock_user(p, arg2, 0);
ths9007f0e2007-09-25 17:50:37 +00005795 }
5796 }
5797 break;
5798#endif
pbrookbd0c5662008-05-29 14:34:11 +00005799#if defined(USE_NPTL)
5800 case TARGET_NR_futex:
5801 ret = do_futex(arg1, arg2, arg3, arg4, arg5, arg6);
5802 break;
5803#endif
ths9007f0e2007-09-25 17:50:37 +00005804
bellard31e31b82003-02-18 22:55:36 +00005805 default:
5806 unimplemented:
bellard5cd43932003-03-29 16:54:36 +00005807 gemu_log("qemu: Unsupported syscall: %d\n", num);
ths4f2b1fe2007-06-21 21:57:12 +00005808#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 +00005809 unimplemented_nowarn:
bellard80a9d032005-01-03 23:31:27 +00005810#endif
ths0da46a62007-10-20 20:23:07 +00005811 ret = -TARGET_ENOSYS;
bellard31e31b82003-02-18 22:55:36 +00005812 break;
5813 }
bellard579a97f2007-11-11 14:26:47 +00005814fail:
bellardc573ff62004-01-04 15:51:36 +00005815#ifdef DEBUG
5816 gemu_log(" = %ld\n", ret);
5817#endif
thsb92c47c2007-11-01 00:07:38 +00005818 if(do_strace)
5819 print_syscall_ret(num, ret);
bellard31e31b82003-02-18 22:55:36 +00005820 return ret;
bellard579a97f2007-11-11 14:26:47 +00005821efault:
5822 ret = -TARGET_EFAULT;
5823 goto fail;
bellard31e31b82003-02-18 22:55:36 +00005824}