blob: 1401b2336bb11f0af41368a3686dd0f9ab12d59d [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
balrogac8a6552008-09-20 02:25:39 +0000160#define __NR_sys_futimesat __NR_futimesat
bellard72f03902003-02-18 23:33:18 +0000161#define __NR_sys_getcwd1 __NR_getcwd
bellard72f03902003-02-18 23:33:18 +0000162#define __NR_sys_getdents __NR_getdents
bellarddab2ed92003-03-22 15:23:14 +0000163#define __NR_sys_getdents64 __NR_getdents64
thsc6cda172007-10-09 03:42:34 +0000164#define __NR_sys_getpriority __NR_getpriority
ths64f0ce42007-09-24 09:25:06 +0000165#define __NR_sys_linkat __NR_linkat
ths4472ad02007-09-24 09:22:32 +0000166#define __NR_sys_mkdirat __NR_mkdirat
ths75ac37a2007-09-24 09:23:05 +0000167#define __NR_sys_mknodat __NR_mknodat
ths82424832007-09-24 09:21:55 +0000168#define __NR_sys_openat __NR_openat
ths5e0ccb12007-09-24 09:26:10 +0000169#define __NR_sys_readlinkat __NR_readlinkat
ths722183f2007-09-24 09:24:37 +0000170#define __NR_sys_renameat __NR_renameat
bellard66fb9762003-03-23 01:06:05 +0000171#define __NR_sys_rt_sigqueueinfo __NR_rt_sigqueueinfo
thsf0b62432007-09-24 09:25:40 +0000172#define __NR_sys_symlinkat __NR_symlinkat
ths7494b0f2007-02-11 18:26:53 +0000173#define __NR_sys_syslog __NR_syslog
ths71455572007-06-21 21:45:30 +0000174#define __NR_sys_tgkill __NR_tgkill
ths4cae1d12007-07-12 11:06:53 +0000175#define __NR_sys_tkill __NR_tkill
ths8170f562007-09-24 09:24:11 +0000176#define __NR_sys_unlinkat __NR_unlinkat
ths9007f0e2007-09-25 17:50:37 +0000177#define __NR_sys_utimensat __NR_utimensat
pbrookbd0c5662008-05-29 14:34:11 +0000178#define __NR_sys_futex __NR_futex
bellard31e31b82003-02-18 22:55:36 +0000179
bellardbc51c5c2004-03-17 23:46:04 +0000180#if defined(__alpha__) || defined (__ia64__) || defined(__x86_64__)
bellard9af9eaa2003-04-07 21:34:41 +0000181#define __NR__llseek __NR_lseek
182#endif
183
bellard72f03902003-02-18 23:33:18 +0000184#ifdef __NR_gettid
bellard31e31b82003-02-18 22:55:36 +0000185_syscall0(int, gettid)
bellard72f03902003-02-18 23:33:18 +0000186#else
ths0da46a62007-10-20 20:23:07 +0000187/* This is a replacement for the host gettid() and must return a host
188 errno. */
bellard72f03902003-02-18 23:33:18 +0000189static int gettid(void) {
190 return -ENOSYS;
191}
192#endif
bellard31e31b82003-02-18 22:55:36 +0000193_syscall1(int,sys_uname,struct new_utsname *,buf)
ths92a34c12007-09-24 09:27:49 +0000194#if defined(TARGET_NR_faccessat) && defined(__NR_faccessat)
195_syscall4(int,sys_faccessat,int,dirfd,const char *,pathname,int,mode,int,flags)
196#endif
ths814d7972007-09-24 09:26:51 +0000197#if defined(TARGET_NR_fchmodat) && defined(__NR_fchmodat)
198_syscall4(int,sys_fchmodat,int,dirfd,const char *,pathname,
199 mode_t,mode,int,flags)
200#endif
blueswir14583f582008-08-24 10:35:55 +0000201#if defined(TARGET_NR_fchownat) && defined(__NR_fchownat) && defined(USE_UID16)
thsccfa72b2007-09-24 09:23:34 +0000202_syscall5(int,sys_fchownat,int,dirfd,const char *,pathname,
203 uid_t,owner,gid_t,group,int,flags)
204#endif
balrog6a24a772008-09-20 02:23:36 +0000205#if defined(TARGET_NR_fstatat64) && defined(__NR_fstatat64)
206_syscall4(int,sys_fstatat64,int,dirfd,const char *,pathname,
207 struct stat *,buf,int,flags)
208#endif
balrogac8a6552008-09-20 02:25:39 +0000209#if defined(TARGET_NR_futimesat) && defined(__NR_futimesat)
210_syscall3(int,sys_futimesat,int,dirfd,const char *,pathname,
211 const struct timeval *,times)
212#endif
bellard72f03902003-02-18 23:33:18 +0000213_syscall2(int,sys_getcwd1,char *,buf,size_t,size)
blueswir14583f582008-08-24 10:35:55 +0000214#if TARGET_ABI_BITS == 32
bellard72f03902003-02-18 23:33:18 +0000215_syscall3(int, sys_getdents, uint, fd, struct dirent *, dirp, uint, count);
blueswir14583f582008-08-24 10:35:55 +0000216#endif
ths3ae43202007-09-16 21:39:48 +0000217#if defined(TARGET_NR_getdents64) && defined(__NR_getdents64)
bellarddab2ed92003-03-22 15:23:14 +0000218_syscall3(int, sys_getdents64, uint, fd, struct dirent64 *, dirp, uint, count);
ths3ae43202007-09-16 21:39:48 +0000219#endif
thsc6cda172007-10-09 03:42:34 +0000220_syscall2(int, sys_getpriority, int, which, int, who);
blueswir18fcd3692008-08-17 20:26:25 +0000221#if !defined (__x86_64__)
bellard31e31b82003-02-18 22:55:36 +0000222_syscall5(int, _llseek, uint, fd, ulong, hi, ulong, lo,
223 loff_t *, res, uint, wh);
blueswir18fcd3692008-08-17 20:26:25 +0000224#endif
ths64f0ce42007-09-24 09:25:06 +0000225#if defined(TARGET_NR_linkat) && defined(__NR_linkat)
226_syscall5(int,sys_linkat,int,olddirfd,const char *,oldpath,
227 int,newdirfd,const char *,newpath,int,flags)
228#endif
ths4472ad02007-09-24 09:22:32 +0000229#if defined(TARGET_NR_mkdirat) && defined(__NR_mkdirat)
230_syscall3(int,sys_mkdirat,int,dirfd,const char *,pathname,mode_t,mode)
231#endif
ths75ac37a2007-09-24 09:23:05 +0000232#if defined(TARGET_NR_mknodat) && defined(__NR_mknodat)
233_syscall4(int,sys_mknodat,int,dirfd,const char *,pathname,
234 mode_t,mode,dev_t,dev)
235#endif
ths82424832007-09-24 09:21:55 +0000236#if defined(TARGET_NR_openat) && defined(__NR_openat)
237_syscall4(int,sys_openat,int,dirfd,const char *,pathname,int,flags,mode_t,mode)
238#endif
ths5e0ccb12007-09-24 09:26:10 +0000239#if defined(TARGET_NR_readlinkat) && defined(__NR_readlinkat)
240_syscall4(int,sys_readlinkat,int,dirfd,const char *,pathname,
241 char *,buf,size_t,bufsize)
242#endif
ths722183f2007-09-24 09:24:37 +0000243#if defined(TARGET_NR_renameat) && defined(__NR_renameat)
244_syscall4(int,sys_renameat,int,olddirfd,const char *,oldpath,
245 int,newdirfd,const char *,newpath)
246#endif
bellard66fb9762003-03-23 01:06:05 +0000247_syscall3(int,sys_rt_sigqueueinfo,int,pid,int,sig,siginfo_t *,uinfo)
thsb51eaa82007-09-25 16:09:22 +0000248#if defined(TARGET_NR_symlinkat) && defined(__NR_symlinkat)
thsf0b62432007-09-24 09:25:40 +0000249_syscall3(int,sys_symlinkat,const char *,oldpath,
250 int,newdirfd,const char *,newpath)
251#endif
ths7494b0f2007-02-11 18:26:53 +0000252_syscall3(int,sys_syslog,int,type,char*,bufp,int,len)
ths3ae43202007-09-16 21:39:48 +0000253#if defined(TARGET_NR_tgkill) && defined(__NR_tgkill)
ths71455572007-06-21 21:45:30 +0000254_syscall3(int,sys_tgkill,int,tgid,int,pid,int,sig)
ths4cae1d12007-07-12 11:06:53 +0000255#endif
ths3ae43202007-09-16 21:39:48 +0000256#if defined(TARGET_NR_tkill) && defined(__NR_tkill)
ths4cae1d12007-07-12 11:06:53 +0000257_syscall2(int,sys_tkill,int,tid,int,sig)
258#endif
bellardec86b0f2003-04-11 00:15:04 +0000259#ifdef __NR_exit_group
260_syscall1(int,exit_group,int,error_code)
261#endif
ths6f5b89a2007-03-02 20:48:00 +0000262#if defined(TARGET_NR_set_tid_address) && defined(__NR_set_tid_address)
263_syscall1(int,set_tid_address,int *,tidptr)
264#endif
ths8170f562007-09-24 09:24:11 +0000265#if defined(TARGET_NR_unlinkat) && defined(__NR_unlinkat)
266_syscall3(int,sys_unlinkat,int,dirfd,const char *,pathname,int,flags)
267#endif
ths9007f0e2007-09-25 17:50:37 +0000268#if defined(TARGET_NR_utimensat) && defined(__NR_utimensat)
269_syscall4(int,sys_utimensat,int,dirfd,const char *,pathname,
270 const struct timespec *,tsp,int,flags)
271#endif
blueswir18fcd3692008-08-17 20:26:25 +0000272#if defined(USE_NPTL)
pbrookbd0c5662008-05-29 14:34:11 +0000273#if defined(TARGET_NR_futex) && defined(__NR_futex)
274_syscall6(int,sys_futex,int *,uaddr,int,op,int,val,
275 const struct timespec *,timeout,int *,uaddr2,int,val3)
blueswir18fcd3692008-08-17 20:26:25 +0000276#endif
pbrookbd0c5662008-05-29 14:34:11 +0000277#endif
bellard66fb9762003-03-23 01:06:05 +0000278
279extern int personality(int);
bellard9de5e442003-03-23 16:49:39 +0000280extern int flock(int, int);
281extern int setfsuid(int);
282extern int setfsgid(int);
bellard19b84f32003-05-08 15:41:49 +0000283extern int setgroups(int, gid_t *);
bellard31e31b82003-02-18 22:55:36 +0000284
thsb92c47c2007-11-01 00:07:38 +0000285#define ERRNO_TABLE_SIZE 1200
286
287/* target_to_host_errno_table[] is initialized from
288 * host_to_target_errno_table[] in syscall_init(). */
289static uint16_t target_to_host_errno_table[ERRNO_TABLE_SIZE] = {
290};
291
ths637947f2007-06-01 12:09:19 +0000292/*
thsfe8f0962007-07-12 10:59:21 +0000293 * This list is the union of errno values overridden in asm-<arch>/errno.h
ths637947f2007-06-01 12:09:19 +0000294 * minus the errnos that are not actually generic to all archs.
295 */
thsb92c47c2007-11-01 00:07:38 +0000296static uint16_t host_to_target_errno_table[ERRNO_TABLE_SIZE] = {
ths637947f2007-06-01 12:09:19 +0000297 [EIDRM] = TARGET_EIDRM,
298 [ECHRNG] = TARGET_ECHRNG,
299 [EL2NSYNC] = TARGET_EL2NSYNC,
300 [EL3HLT] = TARGET_EL3HLT,
301 [EL3RST] = TARGET_EL3RST,
302 [ELNRNG] = TARGET_ELNRNG,
303 [EUNATCH] = TARGET_EUNATCH,
304 [ENOCSI] = TARGET_ENOCSI,
305 [EL2HLT] = TARGET_EL2HLT,
306 [EDEADLK] = TARGET_EDEADLK,
307 [ENOLCK] = TARGET_ENOLCK,
308 [EBADE] = TARGET_EBADE,
309 [EBADR] = TARGET_EBADR,
310 [EXFULL] = TARGET_EXFULL,
311 [ENOANO] = TARGET_ENOANO,
312 [EBADRQC] = TARGET_EBADRQC,
313 [EBADSLT] = TARGET_EBADSLT,
314 [EBFONT] = TARGET_EBFONT,
315 [ENOSTR] = TARGET_ENOSTR,
316 [ENODATA] = TARGET_ENODATA,
317 [ETIME] = TARGET_ETIME,
318 [ENOSR] = TARGET_ENOSR,
319 [ENONET] = TARGET_ENONET,
320 [ENOPKG] = TARGET_ENOPKG,
321 [EREMOTE] = TARGET_EREMOTE,
322 [ENOLINK] = TARGET_ENOLINK,
323 [EADV] = TARGET_EADV,
324 [ESRMNT] = TARGET_ESRMNT,
325 [ECOMM] = TARGET_ECOMM,
326 [EPROTO] = TARGET_EPROTO,
327 [EDOTDOT] = TARGET_EDOTDOT,
328 [EMULTIHOP] = TARGET_EMULTIHOP,
329 [EBADMSG] = TARGET_EBADMSG,
330 [ENAMETOOLONG] = TARGET_ENAMETOOLONG,
331 [EOVERFLOW] = TARGET_EOVERFLOW,
332 [ENOTUNIQ] = TARGET_ENOTUNIQ,
333 [EBADFD] = TARGET_EBADFD,
334 [EREMCHG] = TARGET_EREMCHG,
335 [ELIBACC] = TARGET_ELIBACC,
336 [ELIBBAD] = TARGET_ELIBBAD,
337 [ELIBSCN] = TARGET_ELIBSCN,
338 [ELIBMAX] = TARGET_ELIBMAX,
339 [ELIBEXEC] = TARGET_ELIBEXEC,
340 [EILSEQ] = TARGET_EILSEQ,
341 [ENOSYS] = TARGET_ENOSYS,
342 [ELOOP] = TARGET_ELOOP,
343 [ERESTART] = TARGET_ERESTART,
344 [ESTRPIPE] = TARGET_ESTRPIPE,
345 [ENOTEMPTY] = TARGET_ENOTEMPTY,
346 [EUSERS] = TARGET_EUSERS,
347 [ENOTSOCK] = TARGET_ENOTSOCK,
348 [EDESTADDRREQ] = TARGET_EDESTADDRREQ,
349 [EMSGSIZE] = TARGET_EMSGSIZE,
350 [EPROTOTYPE] = TARGET_EPROTOTYPE,
351 [ENOPROTOOPT] = TARGET_ENOPROTOOPT,
352 [EPROTONOSUPPORT] = TARGET_EPROTONOSUPPORT,
353 [ESOCKTNOSUPPORT] = TARGET_ESOCKTNOSUPPORT,
354 [EOPNOTSUPP] = TARGET_EOPNOTSUPP,
355 [EPFNOSUPPORT] = TARGET_EPFNOSUPPORT,
356 [EAFNOSUPPORT] = TARGET_EAFNOSUPPORT,
357 [EADDRINUSE] = TARGET_EADDRINUSE,
358 [EADDRNOTAVAIL] = TARGET_EADDRNOTAVAIL,
359 [ENETDOWN] = TARGET_ENETDOWN,
360 [ENETUNREACH] = TARGET_ENETUNREACH,
361 [ENETRESET] = TARGET_ENETRESET,
362 [ECONNABORTED] = TARGET_ECONNABORTED,
363 [ECONNRESET] = TARGET_ECONNRESET,
364 [ENOBUFS] = TARGET_ENOBUFS,
365 [EISCONN] = TARGET_EISCONN,
366 [ENOTCONN] = TARGET_ENOTCONN,
367 [EUCLEAN] = TARGET_EUCLEAN,
368 [ENOTNAM] = TARGET_ENOTNAM,
369 [ENAVAIL] = TARGET_ENAVAIL,
370 [EISNAM] = TARGET_EISNAM,
371 [EREMOTEIO] = TARGET_EREMOTEIO,
372 [ESHUTDOWN] = TARGET_ESHUTDOWN,
373 [ETOOMANYREFS] = TARGET_ETOOMANYREFS,
374 [ETIMEDOUT] = TARGET_ETIMEDOUT,
375 [ECONNREFUSED] = TARGET_ECONNREFUSED,
376 [EHOSTDOWN] = TARGET_EHOSTDOWN,
377 [EHOSTUNREACH] = TARGET_EHOSTUNREACH,
378 [EALREADY] = TARGET_EALREADY,
379 [EINPROGRESS] = TARGET_EINPROGRESS,
380 [ESTALE] = TARGET_ESTALE,
381 [ECANCELED] = TARGET_ECANCELED,
382 [ENOMEDIUM] = TARGET_ENOMEDIUM,
383 [EMEDIUMTYPE] = TARGET_EMEDIUMTYPE,
thsb7fe5db2007-07-23 15:37:46 +0000384#ifdef ENOKEY
ths637947f2007-06-01 12:09:19 +0000385 [ENOKEY] = TARGET_ENOKEY,
thsb7fe5db2007-07-23 15:37:46 +0000386#endif
387#ifdef EKEYEXPIRED
ths637947f2007-06-01 12:09:19 +0000388 [EKEYEXPIRED] = TARGET_EKEYEXPIRED,
thsb7fe5db2007-07-23 15:37:46 +0000389#endif
390#ifdef EKEYREVOKED
ths637947f2007-06-01 12:09:19 +0000391 [EKEYREVOKED] = TARGET_EKEYREVOKED,
thsb7fe5db2007-07-23 15:37:46 +0000392#endif
393#ifdef EKEYREJECTED
ths637947f2007-06-01 12:09:19 +0000394 [EKEYREJECTED] = TARGET_EKEYREJECTED,
thsb7fe5db2007-07-23 15:37:46 +0000395#endif
396#ifdef EOWNERDEAD
ths637947f2007-06-01 12:09:19 +0000397 [EOWNERDEAD] = TARGET_EOWNERDEAD,
thsb7fe5db2007-07-23 15:37:46 +0000398#endif
399#ifdef ENOTRECOVERABLE
ths637947f2007-06-01 12:09:19 +0000400 [ENOTRECOVERABLE] = TARGET_ENOTRECOVERABLE,
thsb7fe5db2007-07-23 15:37:46 +0000401#endif
thsb92c47c2007-11-01 00:07:38 +0000402};
ths637947f2007-06-01 12:09:19 +0000403
404static inline int host_to_target_errno(int err)
405{
406 if(host_to_target_errno_table[err])
407 return host_to_target_errno_table[err];
408 return err;
409}
410
thsb92c47c2007-11-01 00:07:38 +0000411static inline int target_to_host_errno(int err)
412{
413 if (target_to_host_errno_table[err])
414 return target_to_host_errno_table[err];
415 return err;
416}
417
blueswir1992f48a2007-10-14 16:27:31 +0000418static inline abi_long get_errno(abi_long ret)
bellard31e31b82003-02-18 22:55:36 +0000419{
420 if (ret == -1)
ths637947f2007-06-01 12:09:19 +0000421 return -host_to_target_errno(errno);
bellard31e31b82003-02-18 22:55:36 +0000422 else
423 return ret;
424}
425
blueswir1992f48a2007-10-14 16:27:31 +0000426static inline int is_error(abi_long ret)
bellard31e31b82003-02-18 22:55:36 +0000427{
blueswir1992f48a2007-10-14 16:27:31 +0000428 return (abi_ulong)ret >= (abi_ulong)(-4096);
bellard31e31b82003-02-18 22:55:36 +0000429}
430
thsb92c47c2007-11-01 00:07:38 +0000431char *target_strerror(int err)
432{
433 return strerror(target_to_host_errno(err));
434}
435
blueswir1992f48a2007-10-14 16:27:31 +0000436static abi_ulong target_brk;
437static abi_ulong target_original_brk;
bellard31e31b82003-02-18 22:55:36 +0000438
blueswir1992f48a2007-10-14 16:27:31 +0000439void target_set_brk(abi_ulong new_brk)
bellard31e31b82003-02-18 22:55:36 +0000440{
blueswir14c1de732007-07-07 20:45:44 +0000441 target_original_brk = target_brk = HOST_PAGE_ALIGN(new_brk);
bellard31e31b82003-02-18 22:55:36 +0000442}
443
ths0da46a62007-10-20 20:23:07 +0000444/* do_brk() must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +0000445abi_long do_brk(abi_ulong new_brk)
bellard31e31b82003-02-18 22:55:36 +0000446{
blueswir1992f48a2007-10-14 16:27:31 +0000447 abi_ulong brk_page;
448 abi_long mapped_addr;
bellard31e31b82003-02-18 22:55:36 +0000449 int new_alloc_size;
450
451 if (!new_brk)
pbrook53a59602006-03-25 19:31:22 +0000452 return target_brk;
bellard31e31b82003-02-18 22:55:36 +0000453 if (new_brk < target_original_brk)
balrog7ab240a2008-04-26 12:17:34 +0000454 return target_brk;
ths3b46e622007-09-17 08:09:54 +0000455
pbrook53a59602006-03-25 19:31:22 +0000456 brk_page = HOST_PAGE_ALIGN(target_brk);
bellard31e31b82003-02-18 22:55:36 +0000457
458 /* If the new brk is less than this, set it and we're done... */
459 if (new_brk < brk_page) {
460 target_brk = new_brk;
pbrook53a59602006-03-25 19:31:22 +0000461 return target_brk;
bellard31e31b82003-02-18 22:55:36 +0000462 }
463
464 /* We need to allocate more memory after the brk... */
bellard54936002003-05-13 00:25:15 +0000465 new_alloc_size = HOST_PAGE_ALIGN(new_brk - brk_page + 1);
ths5fafdf22007-09-16 21:08:06 +0000466 mapped_addr = get_errno(target_mmap(brk_page, new_alloc_size,
bellard54936002003-05-13 00:25:15 +0000467 PROT_READ|PROT_WRITE,
468 MAP_ANON|MAP_FIXED|MAP_PRIVATE, 0, 0));
balrog7ab240a2008-04-26 12:17:34 +0000469
470 if (!is_error(mapped_addr))
bellard31e31b82003-02-18 22:55:36 +0000471 target_brk = new_brk;
balrog7ab240a2008-04-26 12:17:34 +0000472
473 return target_brk;
bellard31e31b82003-02-18 22:55:36 +0000474}
475
ths26edcf42007-12-09 02:25:24 +0000476static inline abi_long copy_from_user_fdset(fd_set *fds,
477 abi_ulong target_fds_addr,
478 int n)
bellard31e31b82003-02-18 22:55:36 +0000479{
ths26edcf42007-12-09 02:25:24 +0000480 int i, nw, j, k;
481 abi_ulong b, *target_fds;
482
483 nw = (n + TARGET_ABI_BITS - 1) / TARGET_ABI_BITS;
484 if (!(target_fds = lock_user(VERIFY_READ,
485 target_fds_addr,
486 sizeof(abi_ulong) * nw,
487 1)))
488 return -TARGET_EFAULT;
489
490 FD_ZERO(fds);
491 k = 0;
492 for (i = 0; i < nw; i++) {
493 /* grab the abi_ulong */
494 __get_user(b, &target_fds[i]);
495 for (j = 0; j < TARGET_ABI_BITS; j++) {
496 /* check the bit inside the abi_ulong */
497 if ((b >> j) & 1)
498 FD_SET(k, fds);
499 k++;
bellard31e31b82003-02-18 22:55:36 +0000500 }
bellard31e31b82003-02-18 22:55:36 +0000501 }
ths26edcf42007-12-09 02:25:24 +0000502
503 unlock_user(target_fds, target_fds_addr, 0);
504
505 return 0;
bellard31e31b82003-02-18 22:55:36 +0000506}
507
ths26edcf42007-12-09 02:25:24 +0000508static inline abi_long copy_to_user_fdset(abi_ulong target_fds_addr,
509 const fd_set *fds,
510 int n)
bellard31e31b82003-02-18 22:55:36 +0000511{
bellard31e31b82003-02-18 22:55:36 +0000512 int i, nw, j, k;
blueswir1992f48a2007-10-14 16:27:31 +0000513 abi_long v;
ths26edcf42007-12-09 02:25:24 +0000514 abi_ulong *target_fds;
bellard31e31b82003-02-18 22:55:36 +0000515
ths26edcf42007-12-09 02:25:24 +0000516 nw = (n + TARGET_ABI_BITS - 1) / TARGET_ABI_BITS;
517 if (!(target_fds = lock_user(VERIFY_WRITE,
518 target_fds_addr,
519 sizeof(abi_ulong) * nw,
520 0)))
521 return -TARGET_EFAULT;
522
523 k = 0;
524 for (i = 0; i < nw; i++) {
525 v = 0;
526 for (j = 0; j < TARGET_ABI_BITS; j++) {
527 v |= ((FD_ISSET(k, fds) != 0) << j);
528 k++;
bellard31e31b82003-02-18 22:55:36 +0000529 }
ths26edcf42007-12-09 02:25:24 +0000530 __put_user(v, &target_fds[i]);
bellard31e31b82003-02-18 22:55:36 +0000531 }
ths26edcf42007-12-09 02:25:24 +0000532
533 unlock_user(target_fds, target_fds_addr, sizeof(abi_ulong) * nw);
534
535 return 0;
bellard31e31b82003-02-18 22:55:36 +0000536}
537
bellardc596ed12003-07-13 17:32:31 +0000538#if defined(__alpha__)
539#define HOST_HZ 1024
540#else
541#define HOST_HZ 100
542#endif
543
blueswir1992f48a2007-10-14 16:27:31 +0000544static inline abi_long host_to_target_clock_t(long ticks)
bellardc596ed12003-07-13 17:32:31 +0000545{
546#if HOST_HZ == TARGET_HZ
547 return ticks;
548#else
549 return ((int64_t)ticks * TARGET_HZ) / HOST_HZ;
550#endif
551}
552
bellard579a97f2007-11-11 14:26:47 +0000553static inline abi_long host_to_target_rusage(abi_ulong target_addr,
554 const struct rusage *rusage)
bellardb4091862003-05-16 15:39:34 +0000555{
pbrook53a59602006-03-25 19:31:22 +0000556 struct target_rusage *target_rusage;
557
bellard579a97f2007-11-11 14:26:47 +0000558 if (!lock_user_struct(VERIFY_WRITE, target_rusage, target_addr, 0))
559 return -TARGET_EFAULT;
bellardb4091862003-05-16 15:39:34 +0000560 target_rusage->ru_utime.tv_sec = tswapl(rusage->ru_utime.tv_sec);
561 target_rusage->ru_utime.tv_usec = tswapl(rusage->ru_utime.tv_usec);
562 target_rusage->ru_stime.tv_sec = tswapl(rusage->ru_stime.tv_sec);
563 target_rusage->ru_stime.tv_usec = tswapl(rusage->ru_stime.tv_usec);
564 target_rusage->ru_maxrss = tswapl(rusage->ru_maxrss);
565 target_rusage->ru_ixrss = tswapl(rusage->ru_ixrss);
566 target_rusage->ru_idrss = tswapl(rusage->ru_idrss);
567 target_rusage->ru_isrss = tswapl(rusage->ru_isrss);
568 target_rusage->ru_minflt = tswapl(rusage->ru_minflt);
569 target_rusage->ru_majflt = tswapl(rusage->ru_majflt);
570 target_rusage->ru_nswap = tswapl(rusage->ru_nswap);
571 target_rusage->ru_inblock = tswapl(rusage->ru_inblock);
572 target_rusage->ru_oublock = tswapl(rusage->ru_oublock);
573 target_rusage->ru_msgsnd = tswapl(rusage->ru_msgsnd);
574 target_rusage->ru_msgrcv = tswapl(rusage->ru_msgrcv);
575 target_rusage->ru_nsignals = tswapl(rusage->ru_nsignals);
576 target_rusage->ru_nvcsw = tswapl(rusage->ru_nvcsw);
577 target_rusage->ru_nivcsw = tswapl(rusage->ru_nivcsw);
pbrook53a59602006-03-25 19:31:22 +0000578 unlock_user_struct(target_rusage, target_addr, 1);
bellard579a97f2007-11-11 14:26:47 +0000579
580 return 0;
bellardb4091862003-05-16 15:39:34 +0000581}
582
ths788f5ec2007-12-09 02:37:05 +0000583static inline abi_long copy_from_user_timeval(struct timeval *tv,
584 abi_ulong target_tv_addr)
bellard31e31b82003-02-18 22:55:36 +0000585{
pbrook53a59602006-03-25 19:31:22 +0000586 struct target_timeval *target_tv;
587
ths788f5ec2007-12-09 02:37:05 +0000588 if (!lock_user_struct(VERIFY_READ, target_tv, target_tv_addr, 1))
bellard579a97f2007-11-11 14:26:47 +0000589 return -TARGET_EFAULT;
ths788f5ec2007-12-09 02:37:05 +0000590
591 __get_user(tv->tv_sec, &target_tv->tv_sec);
592 __get_user(tv->tv_usec, &target_tv->tv_usec);
593
594 unlock_user_struct(target_tv, target_tv_addr, 0);
bellard579a97f2007-11-11 14:26:47 +0000595
596 return 0;
bellard31e31b82003-02-18 22:55:36 +0000597}
598
ths788f5ec2007-12-09 02:37:05 +0000599static inline abi_long copy_to_user_timeval(abi_ulong target_tv_addr,
600 const struct timeval *tv)
bellard31e31b82003-02-18 22:55:36 +0000601{
pbrook53a59602006-03-25 19:31:22 +0000602 struct target_timeval *target_tv;
603
ths788f5ec2007-12-09 02:37:05 +0000604 if (!lock_user_struct(VERIFY_WRITE, target_tv, target_tv_addr, 0))
bellard579a97f2007-11-11 14:26:47 +0000605 return -TARGET_EFAULT;
ths788f5ec2007-12-09 02:37:05 +0000606
607 __put_user(tv->tv_sec, &target_tv->tv_sec);
608 __put_user(tv->tv_usec, &target_tv->tv_usec);
609
610 unlock_user_struct(target_tv, target_tv_addr, 1);
bellard579a97f2007-11-11 14:26:47 +0000611
612 return 0;
bellard31e31b82003-02-18 22:55:36 +0000613}
614
615
ths0da46a62007-10-20 20:23:07 +0000616/* do_select() must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +0000617static abi_long do_select(int n,
ths26edcf42007-12-09 02:25:24 +0000618 abi_ulong rfd_addr, abi_ulong wfd_addr,
619 abi_ulong efd_addr, abi_ulong target_tv_addr)
bellard31e31b82003-02-18 22:55:36 +0000620{
621 fd_set rfds, wfds, efds;
622 fd_set *rfds_ptr, *wfds_ptr, *efds_ptr;
623 struct timeval tv, *tv_ptr;
blueswir1992f48a2007-10-14 16:27:31 +0000624 abi_long ret;
bellard31e31b82003-02-18 22:55:36 +0000625
ths26edcf42007-12-09 02:25:24 +0000626 if (rfd_addr) {
627 if (copy_from_user_fdset(&rfds, rfd_addr, n))
628 return -TARGET_EFAULT;
629 rfds_ptr = &rfds;
pbrook53a59602006-03-25 19:31:22 +0000630 } else {
pbrook53a59602006-03-25 19:31:22 +0000631 rfds_ptr = NULL;
632 }
ths26edcf42007-12-09 02:25:24 +0000633 if (wfd_addr) {
634 if (copy_from_user_fdset(&wfds, wfd_addr, n))
635 return -TARGET_EFAULT;
636 wfds_ptr = &wfds;
pbrook53a59602006-03-25 19:31:22 +0000637 } else {
pbrook53a59602006-03-25 19:31:22 +0000638 wfds_ptr = NULL;
639 }
ths26edcf42007-12-09 02:25:24 +0000640 if (efd_addr) {
641 if (copy_from_user_fdset(&efds, efd_addr, n))
642 return -TARGET_EFAULT;
643 efds_ptr = &efds;
pbrook53a59602006-03-25 19:31:22 +0000644 } else {
pbrook53a59602006-03-25 19:31:22 +0000645 efds_ptr = NULL;
646 }
ths3b46e622007-09-17 08:09:54 +0000647
ths26edcf42007-12-09 02:25:24 +0000648 if (target_tv_addr) {
ths788f5ec2007-12-09 02:37:05 +0000649 if (copy_from_user_timeval(&tv, target_tv_addr))
650 return -TARGET_EFAULT;
bellard31e31b82003-02-18 22:55:36 +0000651 tv_ptr = &tv;
652 } else {
653 tv_ptr = NULL;
654 }
ths26edcf42007-12-09 02:25:24 +0000655
bellard31e31b82003-02-18 22:55:36 +0000656 ret = get_errno(select(n, rfds_ptr, wfds_ptr, efds_ptr, tv_ptr));
pbrook53a59602006-03-25 19:31:22 +0000657
ths26edcf42007-12-09 02:25:24 +0000658 if (!is_error(ret)) {
659 if (rfd_addr && copy_to_user_fdset(rfd_addr, &rfds, n))
660 return -TARGET_EFAULT;
661 if (wfd_addr && copy_to_user_fdset(wfd_addr, &wfds, n))
662 return -TARGET_EFAULT;
663 if (efd_addr && copy_to_user_fdset(efd_addr, &efds, n))
664 return -TARGET_EFAULT;
bellard31e31b82003-02-18 22:55:36 +0000665
ths788f5ec2007-12-09 02:37:05 +0000666 if (target_tv_addr && copy_to_user_timeval(target_tv_addr, &tv))
667 return -TARGET_EFAULT;
bellard31e31b82003-02-18 22:55:36 +0000668 }
bellard579a97f2007-11-11 14:26:47 +0000669
bellard31e31b82003-02-18 22:55:36 +0000670 return ret;
671}
672
bellard579a97f2007-11-11 14:26:47 +0000673static inline abi_long target_to_host_sockaddr(struct sockaddr *addr,
674 abi_ulong target_addr,
675 socklen_t len)
bellard7854b052003-03-29 17:22:23 +0000676{
pbrook53a59602006-03-25 19:31:22 +0000677 struct target_sockaddr *target_saddr;
678
bellard579a97f2007-11-11 14:26:47 +0000679 target_saddr = lock_user(VERIFY_READ, target_addr, len, 1);
680 if (!target_saddr)
681 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +0000682 memcpy(addr, target_saddr, len);
683 addr->sa_family = tswap16(target_saddr->sa_family);
684 unlock_user(target_saddr, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +0000685
686 return 0;
bellard7854b052003-03-29 17:22:23 +0000687}
688
bellard579a97f2007-11-11 14:26:47 +0000689static inline abi_long host_to_target_sockaddr(abi_ulong target_addr,
690 struct sockaddr *addr,
691 socklen_t len)
bellard7854b052003-03-29 17:22:23 +0000692{
pbrook53a59602006-03-25 19:31:22 +0000693 struct target_sockaddr *target_saddr;
694
bellard579a97f2007-11-11 14:26:47 +0000695 target_saddr = lock_user(VERIFY_WRITE, target_addr, len, 0);
696 if (!target_saddr)
697 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +0000698 memcpy(target_saddr, addr, len);
699 target_saddr->sa_family = tswap16(addr->sa_family);
700 unlock_user(target_saddr, target_addr, len);
bellard579a97f2007-11-11 14:26:47 +0000701
702 return 0;
bellard7854b052003-03-29 17:22:23 +0000703}
704
pbrook53a59602006-03-25 19:31:22 +0000705/* ??? Should this also swap msgh->name? */
bellard5a4a8982007-11-11 17:39:18 +0000706static inline abi_long target_to_host_cmsg(struct msghdr *msgh,
707 struct target_msghdr *target_msgh)
bellard7854b052003-03-29 17:22:23 +0000708{
709 struct cmsghdr *cmsg = CMSG_FIRSTHDR(msgh);
bellard5a4a8982007-11-11 17:39:18 +0000710 abi_long msg_controllen;
711 abi_ulong target_cmsg_addr;
712 struct target_cmsghdr *target_cmsg;
bellard7854b052003-03-29 17:22:23 +0000713 socklen_t space = 0;
bellard5a4a8982007-11-11 17:39:18 +0000714
715 msg_controllen = tswapl(target_msgh->msg_controllen);
716 if (msg_controllen < sizeof (struct target_cmsghdr))
717 goto the_end;
718 target_cmsg_addr = tswapl(target_msgh->msg_control);
719 target_cmsg = lock_user(VERIFY_READ, target_cmsg_addr, msg_controllen, 1);
720 if (!target_cmsg)
721 return -TARGET_EFAULT;
bellard7854b052003-03-29 17:22:23 +0000722
723 while (cmsg && target_cmsg) {
724 void *data = CMSG_DATA(cmsg);
725 void *target_data = TARGET_CMSG_DATA(target_cmsg);
726
ths5fafdf22007-09-16 21:08:06 +0000727 int len = tswapl(target_cmsg->cmsg_len)
bellard7854b052003-03-29 17:22:23 +0000728 - TARGET_CMSG_ALIGN(sizeof (struct target_cmsghdr));
729
730 space += CMSG_SPACE(len);
731 if (space > msgh->msg_controllen) {
732 space -= CMSG_SPACE(len);
bellard31febb72005-12-18 20:03:27 +0000733 gemu_log("Host cmsg overflow\n");
bellard7854b052003-03-29 17:22:23 +0000734 break;
735 }
736
737 cmsg->cmsg_level = tswap32(target_cmsg->cmsg_level);
738 cmsg->cmsg_type = tswap32(target_cmsg->cmsg_type);
739 cmsg->cmsg_len = CMSG_LEN(len);
740
bellard3532fa72006-06-24 15:06:03 +0000741 if (cmsg->cmsg_level != TARGET_SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS) {
bellard7854b052003-03-29 17:22:23 +0000742 gemu_log("Unsupported ancillary data: %d/%d\n", cmsg->cmsg_level, cmsg->cmsg_type);
743 memcpy(data, target_data, len);
744 } else {
745 int *fd = (int *)data;
746 int *target_fd = (int *)target_data;
747 int i, numfds = len / sizeof(int);
748
749 for (i = 0; i < numfds; i++)
750 fd[i] = tswap32(target_fd[i]);
751 }
752
753 cmsg = CMSG_NXTHDR(msgh, cmsg);
754 target_cmsg = TARGET_CMSG_NXTHDR(target_msgh, target_cmsg);
755 }
bellard5a4a8982007-11-11 17:39:18 +0000756 unlock_user(target_cmsg, target_cmsg_addr, 0);
757 the_end:
bellard7854b052003-03-29 17:22:23 +0000758 msgh->msg_controllen = space;
bellard5a4a8982007-11-11 17:39:18 +0000759 return 0;
bellard7854b052003-03-29 17:22:23 +0000760}
761
pbrook53a59602006-03-25 19:31:22 +0000762/* ??? Should this also swap msgh->name? */
bellard5a4a8982007-11-11 17:39:18 +0000763static inline abi_long host_to_target_cmsg(struct target_msghdr *target_msgh,
764 struct msghdr *msgh)
bellard7854b052003-03-29 17:22:23 +0000765{
766 struct cmsghdr *cmsg = CMSG_FIRSTHDR(msgh);
bellard5a4a8982007-11-11 17:39:18 +0000767 abi_long msg_controllen;
768 abi_ulong target_cmsg_addr;
769 struct target_cmsghdr *target_cmsg;
bellard7854b052003-03-29 17:22:23 +0000770 socklen_t space = 0;
771
bellard5a4a8982007-11-11 17:39:18 +0000772 msg_controllen = tswapl(target_msgh->msg_controllen);
773 if (msg_controllen < sizeof (struct target_cmsghdr))
774 goto the_end;
775 target_cmsg_addr = tswapl(target_msgh->msg_control);
776 target_cmsg = lock_user(VERIFY_WRITE, target_cmsg_addr, msg_controllen, 0);
777 if (!target_cmsg)
778 return -TARGET_EFAULT;
779
bellard7854b052003-03-29 17:22:23 +0000780 while (cmsg && target_cmsg) {
781 void *data = CMSG_DATA(cmsg);
782 void *target_data = TARGET_CMSG_DATA(target_cmsg);
783
784 int len = cmsg->cmsg_len - CMSG_ALIGN(sizeof (struct cmsghdr));
785
786 space += TARGET_CMSG_SPACE(len);
bellard5a4a8982007-11-11 17:39:18 +0000787 if (space > msg_controllen) {
bellard7854b052003-03-29 17:22:23 +0000788 space -= TARGET_CMSG_SPACE(len);
bellard31febb72005-12-18 20:03:27 +0000789 gemu_log("Target cmsg overflow\n");
bellard7854b052003-03-29 17:22:23 +0000790 break;
791 }
792
793 target_cmsg->cmsg_level = tswap32(cmsg->cmsg_level);
794 target_cmsg->cmsg_type = tswap32(cmsg->cmsg_type);
795 target_cmsg->cmsg_len = tswapl(TARGET_CMSG_LEN(len));
796
bellard3532fa72006-06-24 15:06:03 +0000797 if (cmsg->cmsg_level != TARGET_SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS) {
bellard7854b052003-03-29 17:22:23 +0000798 gemu_log("Unsupported ancillary data: %d/%d\n", cmsg->cmsg_level, cmsg->cmsg_type);
799 memcpy(target_data, data, len);
800 } else {
801 int *fd = (int *)data;
802 int *target_fd = (int *)target_data;
803 int i, numfds = len / sizeof(int);
804
805 for (i = 0; i < numfds; i++)
806 target_fd[i] = tswap32(fd[i]);
807 }
808
809 cmsg = CMSG_NXTHDR(msgh, cmsg);
810 target_cmsg = TARGET_CMSG_NXTHDR(target_msgh, target_cmsg);
811 }
bellard5a4a8982007-11-11 17:39:18 +0000812 unlock_user(target_cmsg, target_cmsg_addr, space);
813 the_end:
814 target_msgh->msg_controllen = tswapl(space);
815 return 0;
bellard7854b052003-03-29 17:22:23 +0000816}
817
ths0da46a62007-10-20 20:23:07 +0000818/* do_setsockopt() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +0000819static abi_long do_setsockopt(int sockfd, int level, int optname,
bellard2f619692007-11-16 10:46:05 +0000820 abi_ulong optval_addr, socklen_t optlen)
bellard7854b052003-03-29 17:22:23 +0000821{
blueswir1992f48a2007-10-14 16:27:31 +0000822 abi_long ret;
j_mayer32407102007-09-26 23:01:49 +0000823 int val;
ths3b46e622007-09-17 08:09:54 +0000824
bellard8853f862004-02-22 14:57:26 +0000825 switch(level) {
826 case SOL_TCP:
bellard7854b052003-03-29 17:22:23 +0000827 /* TCP options all take an 'int' value. */
bellard7854b052003-03-29 17:22:23 +0000828 if (optlen < sizeof(uint32_t))
ths0da46a62007-10-20 20:23:07 +0000829 return -TARGET_EINVAL;
ths3b46e622007-09-17 08:09:54 +0000830
bellard2f619692007-11-16 10:46:05 +0000831 if (get_user_u32(val, optval_addr))
832 return -TARGET_EFAULT;
bellard8853f862004-02-22 14:57:26 +0000833 ret = get_errno(setsockopt(sockfd, level, optname, &val, sizeof(val)));
834 break;
835 case SOL_IP:
836 switch(optname) {
bellard2efbe912005-07-23 15:10:20 +0000837 case IP_TOS:
838 case IP_TTL:
bellard8853f862004-02-22 14:57:26 +0000839 case IP_HDRINCL:
bellard2efbe912005-07-23 15:10:20 +0000840 case IP_ROUTER_ALERT:
841 case IP_RECVOPTS:
842 case IP_RETOPTS:
843 case IP_PKTINFO:
844 case IP_MTU_DISCOVER:
845 case IP_RECVERR:
846 case IP_RECVTOS:
847#ifdef IP_FREEBIND
848 case IP_FREEBIND:
849#endif
850 case IP_MULTICAST_TTL:
851 case IP_MULTICAST_LOOP:
bellard8853f862004-02-22 14:57:26 +0000852 val = 0;
853 if (optlen >= sizeof(uint32_t)) {
bellard2f619692007-11-16 10:46:05 +0000854 if (get_user_u32(val, optval_addr))
855 return -TARGET_EFAULT;
bellard8853f862004-02-22 14:57:26 +0000856 } else if (optlen >= 1) {
bellard2f619692007-11-16 10:46:05 +0000857 if (get_user_u8(val, optval_addr))
858 return -TARGET_EFAULT;
bellard8853f862004-02-22 14:57:26 +0000859 }
860 ret = get_errno(setsockopt(sockfd, level, optname, &val, sizeof(val)));
861 break;
862 default:
863 goto unimplemented;
864 }
865 break;
bellard3532fa72006-06-24 15:06:03 +0000866 case TARGET_SOL_SOCKET:
bellard8853f862004-02-22 14:57:26 +0000867 switch (optname) {
868 /* Options with 'int' argument. */
bellard3532fa72006-06-24 15:06:03 +0000869 case TARGET_SO_DEBUG:
870 optname = SO_DEBUG;
871 break;
872 case TARGET_SO_REUSEADDR:
873 optname = SO_REUSEADDR;
874 break;
875 case TARGET_SO_TYPE:
876 optname = SO_TYPE;
877 break;
878 case TARGET_SO_ERROR:
879 optname = SO_ERROR;
880 break;
881 case TARGET_SO_DONTROUTE:
882 optname = SO_DONTROUTE;
883 break;
884 case TARGET_SO_BROADCAST:
885 optname = SO_BROADCAST;
886 break;
887 case TARGET_SO_SNDBUF:
888 optname = SO_SNDBUF;
889 break;
890 case TARGET_SO_RCVBUF:
891 optname = SO_RCVBUF;
892 break;
893 case TARGET_SO_KEEPALIVE:
894 optname = SO_KEEPALIVE;
895 break;
896 case TARGET_SO_OOBINLINE:
897 optname = SO_OOBINLINE;
898 break;
899 case TARGET_SO_NO_CHECK:
900 optname = SO_NO_CHECK;
901 break;
902 case TARGET_SO_PRIORITY:
903 optname = SO_PRIORITY;
904 break;
bellard5e83e8e2005-03-01 22:32:06 +0000905#ifdef SO_BSDCOMPAT
bellard3532fa72006-06-24 15:06:03 +0000906 case TARGET_SO_BSDCOMPAT:
907 optname = SO_BSDCOMPAT;
908 break;
bellard5e83e8e2005-03-01 22:32:06 +0000909#endif
bellard3532fa72006-06-24 15:06:03 +0000910 case TARGET_SO_PASSCRED:
911 optname = SO_PASSCRED;
912 break;
913 case TARGET_SO_TIMESTAMP:
914 optname = SO_TIMESTAMP;
915 break;
916 case TARGET_SO_RCVLOWAT:
917 optname = SO_RCVLOWAT;
918 break;
919 case TARGET_SO_RCVTIMEO:
920 optname = SO_RCVTIMEO;
921 break;
922 case TARGET_SO_SNDTIMEO:
923 optname = SO_SNDTIMEO;
924 break;
bellard8853f862004-02-22 14:57:26 +0000925 break;
926 default:
927 goto unimplemented;
928 }
bellard3532fa72006-06-24 15:06:03 +0000929 if (optlen < sizeof(uint32_t))
bellard2f619692007-11-16 10:46:05 +0000930 return -TARGET_EINVAL;
bellard3532fa72006-06-24 15:06:03 +0000931
bellard2f619692007-11-16 10:46:05 +0000932 if (get_user_u32(val, optval_addr))
933 return -TARGET_EFAULT;
bellard3532fa72006-06-24 15:06:03 +0000934 ret = get_errno(setsockopt(sockfd, SOL_SOCKET, optname, &val, sizeof(val)));
bellard8853f862004-02-22 14:57:26 +0000935 break;
bellard7854b052003-03-29 17:22:23 +0000936 default:
bellard8853f862004-02-22 14:57:26 +0000937 unimplemented:
938 gemu_log("Unsupported setsockopt level=%d optname=%d \n", level, optname);
ths6fa13c12007-12-18 02:41:04 +0000939 ret = -TARGET_ENOPROTOOPT;
bellard7854b052003-03-29 17:22:23 +0000940 }
bellard8853f862004-02-22 14:57:26 +0000941 return ret;
bellard7854b052003-03-29 17:22:23 +0000942}
943
ths0da46a62007-10-20 20:23:07 +0000944/* do_getsockopt() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +0000945static abi_long do_getsockopt(int sockfd, int level, int optname,
bellard2f619692007-11-16 10:46:05 +0000946 abi_ulong optval_addr, abi_ulong optlen)
bellard7854b052003-03-29 17:22:23 +0000947{
blueswir1992f48a2007-10-14 16:27:31 +0000948 abi_long ret;
j_mayer32407102007-09-26 23:01:49 +0000949 int len, lv, val;
bellard8853f862004-02-22 14:57:26 +0000950
951 switch(level) {
bellard3532fa72006-06-24 15:06:03 +0000952 case TARGET_SOL_SOCKET:
953 level = SOL_SOCKET;
bellard8853f862004-02-22 14:57:26 +0000954 switch (optname) {
bellard3532fa72006-06-24 15:06:03 +0000955 case TARGET_SO_LINGER:
956 case TARGET_SO_RCVTIMEO:
957 case TARGET_SO_SNDTIMEO:
958 case TARGET_SO_PEERCRED:
959 case TARGET_SO_PEERNAME:
bellard8853f862004-02-22 14:57:26 +0000960 /* These don't just return a single integer */
961 goto unimplemented;
962 default:
bellard2efbe912005-07-23 15:10:20 +0000963 goto int_case;
964 }
965 break;
966 case SOL_TCP:
967 /* TCP options all take an 'int' value. */
968 int_case:
bellard2f619692007-11-16 10:46:05 +0000969 if (get_user_u32(len, optlen))
970 return -TARGET_EFAULT;
bellard2efbe912005-07-23 15:10:20 +0000971 if (len < 0)
ths0da46a62007-10-20 20:23:07 +0000972 return -TARGET_EINVAL;
bellard2efbe912005-07-23 15:10:20 +0000973 lv = sizeof(int);
974 ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
975 if (ret < 0)
976 return ret;
977 val = tswap32(val);
978 if (len > lv)
979 len = lv;
bellard2f619692007-11-16 10:46:05 +0000980 if (len == 4) {
981 if (put_user_u32(val, optval_addr))
982 return -TARGET_EFAULT;
983 } else {
984 if (put_user_u8(val, optval_addr))
985 return -TARGET_EFAULT;
986 }
987 if (put_user_u32(len, optlen))
988 return -TARGET_EFAULT;
bellard2efbe912005-07-23 15:10:20 +0000989 break;
990 case SOL_IP:
991 switch(optname) {
992 case IP_TOS:
993 case IP_TTL:
994 case IP_HDRINCL:
995 case IP_ROUTER_ALERT:
996 case IP_RECVOPTS:
997 case IP_RETOPTS:
998 case IP_PKTINFO:
999 case IP_MTU_DISCOVER:
1000 case IP_RECVERR:
1001 case IP_RECVTOS:
1002#ifdef IP_FREEBIND
1003 case IP_FREEBIND:
1004#endif
1005 case IP_MULTICAST_TTL:
1006 case IP_MULTICAST_LOOP:
bellard2f619692007-11-16 10:46:05 +00001007 if (get_user_u32(len, optlen))
1008 return -TARGET_EFAULT;
bellard8853f862004-02-22 14:57:26 +00001009 if (len < 0)
ths0da46a62007-10-20 20:23:07 +00001010 return -TARGET_EINVAL;
bellard8853f862004-02-22 14:57:26 +00001011 lv = sizeof(int);
1012 ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
1013 if (ret < 0)
1014 return ret;
bellard2efbe912005-07-23 15:10:20 +00001015 if (len < sizeof(int) && len > 0 && val >= 0 && val < 255) {
bellard2efbe912005-07-23 15:10:20 +00001016 len = 1;
bellard2f619692007-11-16 10:46:05 +00001017 if (put_user_u32(len, optlen)
1018 || put_user_u8(val, optval_addr))
1019 return -TARGET_EFAULT;
bellard2efbe912005-07-23 15:10:20 +00001020 } else {
bellard2efbe912005-07-23 15:10:20 +00001021 if (len > sizeof(int))
1022 len = sizeof(int);
bellard2f619692007-11-16 10:46:05 +00001023 if (put_user_u32(len, optlen)
1024 || put_user_u32(val, optval_addr))
1025 return -TARGET_EFAULT;
bellard2efbe912005-07-23 15:10:20 +00001026 }
bellard8853f862004-02-22 14:57:26 +00001027 break;
bellard2efbe912005-07-23 15:10:20 +00001028 default:
thsc02f4992007-12-18 02:39:59 +00001029 ret = -TARGET_ENOPROTOOPT;
1030 break;
bellard8853f862004-02-22 14:57:26 +00001031 }
1032 break;
1033 default:
1034 unimplemented:
1035 gemu_log("getsockopt level=%d optname=%d not yet supported\n",
1036 level, optname);
thsc02f4992007-12-18 02:39:59 +00001037 ret = -TARGET_EOPNOTSUPP;
bellard8853f862004-02-22 14:57:26 +00001038 break;
1039 }
1040 return ret;
bellard7854b052003-03-29 17:22:23 +00001041}
1042
bellard579a97f2007-11-11 14:26:47 +00001043/* FIXME
1044 * lock_iovec()/unlock_iovec() have a return code of 0 for success where
1045 * other lock functions have a return code of 0 for failure.
1046 */
1047static abi_long lock_iovec(int type, struct iovec *vec, abi_ulong target_addr,
1048 int count, int copy)
pbrook53a59602006-03-25 19:31:22 +00001049{
1050 struct target_iovec *target_vec;
blueswir1992f48a2007-10-14 16:27:31 +00001051 abi_ulong base;
bellard579a97f2007-11-11 14:26:47 +00001052 int i, j;
pbrook53a59602006-03-25 19:31:22 +00001053
bellard579a97f2007-11-11 14:26:47 +00001054 target_vec = lock_user(VERIFY_READ, target_addr, count * sizeof(struct target_iovec), 1);
1055 if (!target_vec)
1056 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00001057 for(i = 0;i < count; i++) {
1058 base = tswapl(target_vec[i].iov_base);
1059 vec[i].iov_len = tswapl(target_vec[i].iov_len);
bellard41df8412008-02-04 22:26:57 +00001060 if (vec[i].iov_len != 0) {
1061 vec[i].iov_base = lock_user(type, base, vec[i].iov_len, copy);
balrog7bedce82008-02-10 13:28:08 +00001062 if (!vec[i].iov_base && vec[i].iov_len)
bellard41df8412008-02-04 22:26:57 +00001063 goto fail;
1064 } else {
1065 /* zero length pointer is ignored */
1066 vec[i].iov_base = NULL;
1067 }
pbrook53a59602006-03-25 19:31:22 +00001068 }
1069 unlock_user (target_vec, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00001070 return 0;
1071 fail:
1072 /* failure - unwind locks */
1073 for (j = 0; j < i; j++) {
1074 base = tswapl(target_vec[j].iov_base);
1075 unlock_user(vec[j].iov_base, base, 0);
1076 }
1077 unlock_user (target_vec, target_addr, 0);
1078 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00001079}
1080
bellard579a97f2007-11-11 14:26:47 +00001081static abi_long unlock_iovec(struct iovec *vec, abi_ulong target_addr,
1082 int count, int copy)
pbrook53a59602006-03-25 19:31:22 +00001083{
1084 struct target_iovec *target_vec;
blueswir1992f48a2007-10-14 16:27:31 +00001085 abi_ulong base;
pbrook53a59602006-03-25 19:31:22 +00001086 int i;
1087
bellard579a97f2007-11-11 14:26:47 +00001088 target_vec = lock_user(VERIFY_READ, target_addr, count * sizeof(struct target_iovec), 1);
1089 if (!target_vec)
1090 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00001091 for(i = 0;i < count; i++) {
1092 base = tswapl(target_vec[i].iov_base);
1093 unlock_user(vec[i].iov_base, base, copy ? vec[i].iov_len : 0);
1094 }
1095 unlock_user (target_vec, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00001096
1097 return 0;
pbrook53a59602006-03-25 19:31:22 +00001098}
1099
ths0da46a62007-10-20 20:23:07 +00001100/* do_socket() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001101static abi_long do_socket(int domain, int type, int protocol)
bellard3532fa72006-06-24 15:06:03 +00001102{
1103#if defined(TARGET_MIPS)
1104 switch(type) {
1105 case TARGET_SOCK_DGRAM:
1106 type = SOCK_DGRAM;
1107 break;
1108 case TARGET_SOCK_STREAM:
1109 type = SOCK_STREAM;
1110 break;
1111 case TARGET_SOCK_RAW:
1112 type = SOCK_RAW;
1113 break;
1114 case TARGET_SOCK_RDM:
1115 type = SOCK_RDM;
1116 break;
1117 case TARGET_SOCK_SEQPACKET:
1118 type = SOCK_SEQPACKET;
1119 break;
1120 case TARGET_SOCK_PACKET:
1121 type = SOCK_PACKET;
1122 break;
1123 }
1124#endif
balrog12bc92a2007-10-30 21:06:14 +00001125 if (domain == PF_NETLINK)
1126 return -EAFNOSUPPORT; /* do not NETLINK socket connections possible */
bellard3532fa72006-06-24 15:06:03 +00001127 return get_errno(socket(domain, type, protocol));
1128}
1129
ths0da46a62007-10-20 20:23:07 +00001130/* do_bind() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001131static abi_long do_bind(int sockfd, abi_ulong target_addr,
1132 socklen_t addrlen)
bellard3532fa72006-06-24 15:06:03 +00001133{
1134 void *addr = alloca(addrlen);
ths3b46e622007-09-17 08:09:54 +00001135
bellard3532fa72006-06-24 15:06:03 +00001136 target_to_host_sockaddr(addr, target_addr, addrlen);
1137 return get_errno(bind(sockfd, addr, addrlen));
1138}
1139
ths0da46a62007-10-20 20:23:07 +00001140/* do_connect() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001141static abi_long do_connect(int sockfd, abi_ulong target_addr,
1142 socklen_t addrlen)
bellard3532fa72006-06-24 15:06:03 +00001143{
1144 void *addr = alloca(addrlen);
ths3b46e622007-09-17 08:09:54 +00001145
bellard3532fa72006-06-24 15:06:03 +00001146 target_to_host_sockaddr(addr, target_addr, addrlen);
1147 return get_errno(connect(sockfd, addr, addrlen));
1148}
1149
ths0da46a62007-10-20 20:23:07 +00001150/* do_sendrecvmsg() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001151static abi_long do_sendrecvmsg(int fd, abi_ulong target_msg,
1152 int flags, int send)
bellard3532fa72006-06-24 15:06:03 +00001153{
blueswir1992f48a2007-10-14 16:27:31 +00001154 abi_long ret;
bellard3532fa72006-06-24 15:06:03 +00001155 struct target_msghdr *msgp;
1156 struct msghdr msg;
1157 int count;
1158 struct iovec *vec;
blueswir1992f48a2007-10-14 16:27:31 +00001159 abi_ulong target_vec;
bellard3532fa72006-06-24 15:06:03 +00001160
bellard579a97f2007-11-11 14:26:47 +00001161 /* FIXME */
1162 if (!lock_user_struct(send ? VERIFY_READ : VERIFY_WRITE,
1163 msgp,
1164 target_msg,
1165 send ? 1 : 0))
1166 return -TARGET_EFAULT;
bellard3532fa72006-06-24 15:06:03 +00001167 if (msgp->msg_name) {
1168 msg.msg_namelen = tswap32(msgp->msg_namelen);
1169 msg.msg_name = alloca(msg.msg_namelen);
1170 target_to_host_sockaddr(msg.msg_name, tswapl(msgp->msg_name),
1171 msg.msg_namelen);
1172 } else {
1173 msg.msg_name = NULL;
1174 msg.msg_namelen = 0;
1175 }
1176 msg.msg_controllen = 2 * tswapl(msgp->msg_controllen);
1177 msg.msg_control = alloca(msg.msg_controllen);
1178 msg.msg_flags = tswap32(msgp->msg_flags);
ths3b46e622007-09-17 08:09:54 +00001179
bellard3532fa72006-06-24 15:06:03 +00001180 count = tswapl(msgp->msg_iovlen);
1181 vec = alloca(count * sizeof(struct iovec));
1182 target_vec = tswapl(msgp->msg_iov);
bellard579a97f2007-11-11 14:26:47 +00001183 lock_iovec(send ? VERIFY_READ : VERIFY_WRITE, vec, target_vec, count, send);
bellard3532fa72006-06-24 15:06:03 +00001184 msg.msg_iovlen = count;
1185 msg.msg_iov = vec;
ths3b46e622007-09-17 08:09:54 +00001186
bellard3532fa72006-06-24 15:06:03 +00001187 if (send) {
bellard5a4a8982007-11-11 17:39:18 +00001188 ret = target_to_host_cmsg(&msg, msgp);
1189 if (ret == 0)
1190 ret = get_errno(sendmsg(fd, &msg, flags));
bellard3532fa72006-06-24 15:06:03 +00001191 } else {
1192 ret = get_errno(recvmsg(fd, &msg, flags));
1193 if (!is_error(ret))
bellard5a4a8982007-11-11 17:39:18 +00001194 ret = host_to_target_cmsg(msgp, &msg);
bellard3532fa72006-06-24 15:06:03 +00001195 }
1196 unlock_iovec(vec, target_vec, count, !send);
bellard579a97f2007-11-11 14:26:47 +00001197 unlock_user_struct(msgp, target_msg, send ? 0 : 1);
bellard3532fa72006-06-24 15:06:03 +00001198 return ret;
1199}
1200
ths0da46a62007-10-20 20:23:07 +00001201/* do_accept() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001202static abi_long do_accept(int fd, abi_ulong target_addr,
bellard2f619692007-11-16 10:46:05 +00001203 abi_ulong target_addrlen_addr)
pbrook1be9e1d2006-11-19 15:26:04 +00001204{
bellard2f619692007-11-16 10:46:05 +00001205 socklen_t addrlen;
1206 void *addr;
blueswir1992f48a2007-10-14 16:27:31 +00001207 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00001208
bellard2f619692007-11-16 10:46:05 +00001209 if (get_user_u32(addrlen, target_addrlen_addr))
1210 return -TARGET_EFAULT;
1211
1212 addr = alloca(addrlen);
1213
pbrook1be9e1d2006-11-19 15:26:04 +00001214 ret = get_errno(accept(fd, addr, &addrlen));
1215 if (!is_error(ret)) {
1216 host_to_target_sockaddr(target_addr, addr, addrlen);
bellard2f619692007-11-16 10:46:05 +00001217 if (put_user_u32(addrlen, target_addrlen_addr))
1218 ret = -TARGET_EFAULT;
pbrook1be9e1d2006-11-19 15:26:04 +00001219 }
1220 return ret;
1221}
1222
ths0da46a62007-10-20 20:23:07 +00001223/* do_getpeername() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001224static abi_long do_getpeername(int fd, abi_ulong target_addr,
bellard2f619692007-11-16 10:46:05 +00001225 abi_ulong target_addrlen_addr)
pbrook1be9e1d2006-11-19 15:26:04 +00001226{
bellard2f619692007-11-16 10:46:05 +00001227 socklen_t addrlen;
1228 void *addr;
blueswir1992f48a2007-10-14 16:27:31 +00001229 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00001230
bellard2f619692007-11-16 10:46:05 +00001231 if (get_user_u32(addrlen, target_addrlen_addr))
1232 return -TARGET_EFAULT;
1233
1234 addr = alloca(addrlen);
1235
pbrook1be9e1d2006-11-19 15:26:04 +00001236 ret = get_errno(getpeername(fd, addr, &addrlen));
1237 if (!is_error(ret)) {
1238 host_to_target_sockaddr(target_addr, addr, addrlen);
bellard2f619692007-11-16 10:46:05 +00001239 if (put_user_u32(addrlen, target_addrlen_addr))
1240 ret = -TARGET_EFAULT;
pbrook1be9e1d2006-11-19 15:26:04 +00001241 }
1242 return ret;
1243}
1244
ths0da46a62007-10-20 20:23:07 +00001245/* do_getsockname() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001246static abi_long do_getsockname(int fd, abi_ulong target_addr,
bellard2f619692007-11-16 10:46:05 +00001247 abi_ulong target_addrlen_addr)
pbrook1be9e1d2006-11-19 15:26:04 +00001248{
bellard2f619692007-11-16 10:46:05 +00001249 socklen_t addrlen;
1250 void *addr;
blueswir1992f48a2007-10-14 16:27:31 +00001251 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00001252
bellard2f619692007-11-16 10:46:05 +00001253 if (get_user_u32(addrlen, target_addrlen_addr))
1254 return -TARGET_EFAULT;
1255
1256 addr = alloca(addrlen);
1257
pbrook1be9e1d2006-11-19 15:26:04 +00001258 ret = get_errno(getsockname(fd, addr, &addrlen));
1259 if (!is_error(ret)) {
1260 host_to_target_sockaddr(target_addr, addr, addrlen);
bellard2f619692007-11-16 10:46:05 +00001261 if (put_user_u32(addrlen, target_addrlen_addr))
1262 ret = -TARGET_EFAULT;
pbrook1be9e1d2006-11-19 15:26:04 +00001263 }
1264 return ret;
1265}
1266
ths0da46a62007-10-20 20:23:07 +00001267/* do_socketpair() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001268static abi_long do_socketpair(int domain, int type, int protocol,
bellard2f619692007-11-16 10:46:05 +00001269 abi_ulong target_tab_addr)
pbrook1be9e1d2006-11-19 15:26:04 +00001270{
1271 int tab[2];
blueswir1992f48a2007-10-14 16:27:31 +00001272 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00001273
1274 ret = get_errno(socketpair(domain, type, protocol, tab));
1275 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +00001276 if (put_user_s32(tab[0], target_tab_addr)
1277 || put_user_s32(tab[1], target_tab_addr + sizeof(tab[0])))
1278 ret = -TARGET_EFAULT;
pbrook1be9e1d2006-11-19 15:26:04 +00001279 }
1280 return ret;
1281}
1282
ths0da46a62007-10-20 20:23:07 +00001283/* do_sendto() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001284static abi_long do_sendto(int fd, abi_ulong msg, size_t len, int flags,
1285 abi_ulong target_addr, socklen_t addrlen)
pbrook1be9e1d2006-11-19 15:26:04 +00001286{
1287 void *addr;
1288 void *host_msg;
blueswir1992f48a2007-10-14 16:27:31 +00001289 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00001290
bellard579a97f2007-11-11 14:26:47 +00001291 host_msg = lock_user(VERIFY_READ, msg, len, 1);
1292 if (!host_msg)
1293 return -TARGET_EFAULT;
pbrook1be9e1d2006-11-19 15:26:04 +00001294 if (target_addr) {
1295 addr = alloca(addrlen);
1296 target_to_host_sockaddr(addr, target_addr, addrlen);
1297 ret = get_errno(sendto(fd, host_msg, len, flags, addr, addrlen));
1298 } else {
1299 ret = get_errno(send(fd, host_msg, len, flags));
1300 }
1301 unlock_user(host_msg, msg, 0);
1302 return ret;
1303}
1304
ths0da46a62007-10-20 20:23:07 +00001305/* do_recvfrom() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001306static abi_long do_recvfrom(int fd, abi_ulong msg, size_t len, int flags,
1307 abi_ulong target_addr,
1308 abi_ulong target_addrlen)
pbrook1be9e1d2006-11-19 15:26:04 +00001309{
1310 socklen_t addrlen;
1311 void *addr;
1312 void *host_msg;
blueswir1992f48a2007-10-14 16:27:31 +00001313 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00001314
bellard579a97f2007-11-11 14:26:47 +00001315 host_msg = lock_user(VERIFY_WRITE, msg, len, 0);
1316 if (!host_msg)
1317 return -TARGET_EFAULT;
pbrook1be9e1d2006-11-19 15:26:04 +00001318 if (target_addr) {
bellard2f619692007-11-16 10:46:05 +00001319 if (get_user_u32(addrlen, target_addrlen)) {
1320 ret = -TARGET_EFAULT;
1321 goto fail;
1322 }
pbrook1be9e1d2006-11-19 15:26:04 +00001323 addr = alloca(addrlen);
1324 ret = get_errno(recvfrom(fd, host_msg, len, flags, addr, &addrlen));
1325 } else {
1326 addr = NULL; /* To keep compiler quiet. */
1327 ret = get_errno(recv(fd, host_msg, len, flags));
1328 }
1329 if (!is_error(ret)) {
1330 if (target_addr) {
1331 host_to_target_sockaddr(target_addr, addr, addrlen);
bellard2f619692007-11-16 10:46:05 +00001332 if (put_user_u32(addrlen, target_addrlen)) {
1333 ret = -TARGET_EFAULT;
1334 goto fail;
1335 }
pbrook1be9e1d2006-11-19 15:26:04 +00001336 }
1337 unlock_user(host_msg, msg, len);
1338 } else {
bellard2f619692007-11-16 10:46:05 +00001339fail:
pbrook1be9e1d2006-11-19 15:26:04 +00001340 unlock_user(host_msg, msg, 0);
1341 }
1342 return ret;
1343}
1344
j_mayer32407102007-09-26 23:01:49 +00001345#ifdef TARGET_NR_socketcall
ths0da46a62007-10-20 20:23:07 +00001346/* do_socketcall() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001347static abi_long do_socketcall(int num, abi_ulong vptr)
bellard31e31b82003-02-18 22:55:36 +00001348{
blueswir1992f48a2007-10-14 16:27:31 +00001349 abi_long ret;
1350 const int n = sizeof(abi_ulong);
bellard31e31b82003-02-18 22:55:36 +00001351
1352 switch(num) {
1353 case SOCKOP_socket:
bellard7854b052003-03-29 17:22:23 +00001354 {
bellard2f619692007-11-16 10:46:05 +00001355 int domain, type, protocol;
1356
1357 if (get_user_s32(domain, vptr)
1358 || get_user_s32(type, vptr + n)
1359 || get_user_s32(protocol, vptr + 2 * n))
1360 return -TARGET_EFAULT;
1361
bellard3532fa72006-06-24 15:06:03 +00001362 ret = do_socket(domain, type, protocol);
bellard7854b052003-03-29 17:22:23 +00001363 }
bellard31e31b82003-02-18 22:55:36 +00001364 break;
1365 case SOCKOP_bind:
bellard7854b052003-03-29 17:22:23 +00001366 {
bellard2f619692007-11-16 10:46:05 +00001367 int sockfd;
1368 abi_ulong target_addr;
1369 socklen_t addrlen;
1370
1371 if (get_user_s32(sockfd, vptr)
1372 || get_user_ual(target_addr, vptr + n)
1373 || get_user_u32(addrlen, vptr + 2 * n))
1374 return -TARGET_EFAULT;
1375
bellard3532fa72006-06-24 15:06:03 +00001376 ret = do_bind(sockfd, target_addr, addrlen);
bellard7854b052003-03-29 17:22:23 +00001377 }
bellard31e31b82003-02-18 22:55:36 +00001378 break;
1379 case SOCKOP_connect:
bellard7854b052003-03-29 17:22:23 +00001380 {
bellard2f619692007-11-16 10:46:05 +00001381 int sockfd;
1382 abi_ulong target_addr;
1383 socklen_t addrlen;
1384
1385 if (get_user_s32(sockfd, vptr)
1386 || get_user_ual(target_addr, vptr + n)
1387 || get_user_u32(addrlen, vptr + 2 * n))
1388 return -TARGET_EFAULT;
1389
bellard3532fa72006-06-24 15:06:03 +00001390 ret = do_connect(sockfd, target_addr, addrlen);
bellard7854b052003-03-29 17:22:23 +00001391 }
bellard31e31b82003-02-18 22:55:36 +00001392 break;
1393 case SOCKOP_listen:
bellard7854b052003-03-29 17:22:23 +00001394 {
bellard2f619692007-11-16 10:46:05 +00001395 int sockfd, backlog;
1396
1397 if (get_user_s32(sockfd, vptr)
1398 || get_user_s32(backlog, vptr + n))
1399 return -TARGET_EFAULT;
1400
bellard7854b052003-03-29 17:22:23 +00001401 ret = get_errno(listen(sockfd, backlog));
1402 }
bellard31e31b82003-02-18 22:55:36 +00001403 break;
1404 case SOCKOP_accept:
1405 {
bellard2f619692007-11-16 10:46:05 +00001406 int sockfd;
1407 abi_ulong target_addr, target_addrlen;
1408
1409 if (get_user_s32(sockfd, vptr)
1410 || get_user_ual(target_addr, vptr + n)
1411 || get_user_u32(target_addrlen, vptr + 2 * n))
1412 return -TARGET_EFAULT;
1413
pbrook1be9e1d2006-11-19 15:26:04 +00001414 ret = do_accept(sockfd, target_addr, target_addrlen);
bellard31e31b82003-02-18 22:55:36 +00001415 }
1416 break;
1417 case SOCKOP_getsockname:
1418 {
bellard2f619692007-11-16 10:46:05 +00001419 int sockfd;
1420 abi_ulong target_addr, target_addrlen;
1421
1422 if (get_user_s32(sockfd, vptr)
1423 || get_user_ual(target_addr, vptr + n)
1424 || get_user_u32(target_addrlen, vptr + 2 * n))
1425 return -TARGET_EFAULT;
1426
pbrook1be9e1d2006-11-19 15:26:04 +00001427 ret = do_getsockname(sockfd, target_addr, target_addrlen);
bellard31e31b82003-02-18 22:55:36 +00001428 }
1429 break;
1430 case SOCKOP_getpeername:
1431 {
bellard2f619692007-11-16 10:46:05 +00001432 int sockfd;
1433 abi_ulong target_addr, target_addrlen;
1434
1435 if (get_user_s32(sockfd, vptr)
1436 || get_user_ual(target_addr, vptr + n)
1437 || get_user_u32(target_addrlen, vptr + 2 * n))
1438 return -TARGET_EFAULT;
1439
pbrook1be9e1d2006-11-19 15:26:04 +00001440 ret = do_getpeername(sockfd, target_addr, target_addrlen);
bellard31e31b82003-02-18 22:55:36 +00001441 }
1442 break;
1443 case SOCKOP_socketpair:
1444 {
bellard2f619692007-11-16 10:46:05 +00001445 int domain, type, protocol;
1446 abi_ulong tab;
1447
1448 if (get_user_s32(domain, vptr)
1449 || get_user_s32(type, vptr + n)
1450 || get_user_s32(protocol, vptr + 2 * n)
1451 || get_user_ual(tab, vptr + 3 * n))
1452 return -TARGET_EFAULT;
1453
pbrook1be9e1d2006-11-19 15:26:04 +00001454 ret = do_socketpair(domain, type, protocol, tab);
bellard31e31b82003-02-18 22:55:36 +00001455 }
1456 break;
1457 case SOCKOP_send:
bellard7854b052003-03-29 17:22:23 +00001458 {
bellard2f619692007-11-16 10:46:05 +00001459 int sockfd;
1460 abi_ulong msg;
1461 size_t len;
1462 int flags;
1463
1464 if (get_user_s32(sockfd, vptr)
1465 || get_user_ual(msg, vptr + n)
1466 || get_user_ual(len, vptr + 2 * n)
1467 || get_user_s32(flags, vptr + 3 * n))
1468 return -TARGET_EFAULT;
1469
pbrook1be9e1d2006-11-19 15:26:04 +00001470 ret = do_sendto(sockfd, msg, len, flags, 0, 0);
bellard7854b052003-03-29 17:22:23 +00001471 }
bellard31e31b82003-02-18 22:55:36 +00001472 break;
1473 case SOCKOP_recv:
bellard7854b052003-03-29 17:22:23 +00001474 {
bellard2f619692007-11-16 10:46:05 +00001475 int sockfd;
1476 abi_ulong msg;
1477 size_t len;
1478 int flags;
1479
1480 if (get_user_s32(sockfd, vptr)
1481 || get_user_ual(msg, vptr + n)
1482 || get_user_ual(len, vptr + 2 * n)
1483 || get_user_s32(flags, vptr + 3 * n))
1484 return -TARGET_EFAULT;
1485
pbrook1be9e1d2006-11-19 15:26:04 +00001486 ret = do_recvfrom(sockfd, msg, len, flags, 0, 0);
bellard7854b052003-03-29 17:22:23 +00001487 }
bellard31e31b82003-02-18 22:55:36 +00001488 break;
1489 case SOCKOP_sendto:
bellard7854b052003-03-29 17:22:23 +00001490 {
bellard2f619692007-11-16 10:46:05 +00001491 int sockfd;
1492 abi_ulong msg;
1493 size_t len;
1494 int flags;
1495 abi_ulong addr;
1496 socklen_t addrlen;
1497
1498 if (get_user_s32(sockfd, vptr)
1499 || get_user_ual(msg, vptr + n)
1500 || get_user_ual(len, vptr + 2 * n)
1501 || get_user_s32(flags, vptr + 3 * n)
1502 || get_user_ual(addr, vptr + 4 * n)
1503 || get_user_u32(addrlen, vptr + 5 * n))
1504 return -TARGET_EFAULT;
1505
pbrook1be9e1d2006-11-19 15:26:04 +00001506 ret = do_sendto(sockfd, msg, len, flags, addr, addrlen);
bellard7854b052003-03-29 17:22:23 +00001507 }
bellard31e31b82003-02-18 22:55:36 +00001508 break;
1509 case SOCKOP_recvfrom:
1510 {
bellard2f619692007-11-16 10:46:05 +00001511 int sockfd;
1512 abi_ulong msg;
1513 size_t len;
1514 int flags;
1515 abi_ulong addr;
1516 socklen_t addrlen;
1517
1518 if (get_user_s32(sockfd, vptr)
1519 || get_user_ual(msg, vptr + n)
1520 || get_user_ual(len, vptr + 2 * n)
1521 || get_user_s32(flags, vptr + 3 * n)
1522 || get_user_ual(addr, vptr + 4 * n)
1523 || get_user_u32(addrlen, vptr + 5 * n))
1524 return -TARGET_EFAULT;
1525
pbrook1be9e1d2006-11-19 15:26:04 +00001526 ret = do_recvfrom(sockfd, msg, len, flags, addr, addrlen);
bellard31e31b82003-02-18 22:55:36 +00001527 }
1528 break;
1529 case SOCKOP_shutdown:
bellard7854b052003-03-29 17:22:23 +00001530 {
bellard2f619692007-11-16 10:46:05 +00001531 int sockfd, how;
1532
1533 if (get_user_s32(sockfd, vptr)
1534 || get_user_s32(how, vptr + n))
1535 return -TARGET_EFAULT;
bellard7854b052003-03-29 17:22:23 +00001536
1537 ret = get_errno(shutdown(sockfd, how));
1538 }
bellard31e31b82003-02-18 22:55:36 +00001539 break;
1540 case SOCKOP_sendmsg:
1541 case SOCKOP_recvmsg:
bellard1a9353d2003-03-16 20:28:50 +00001542 {
1543 int fd;
blueswir1992f48a2007-10-14 16:27:31 +00001544 abi_ulong target_msg;
bellard3532fa72006-06-24 15:06:03 +00001545 int flags;
bellard1a9353d2003-03-16 20:28:50 +00001546
bellard2f619692007-11-16 10:46:05 +00001547 if (get_user_s32(fd, vptr)
1548 || get_user_ual(target_msg, vptr + n)
1549 || get_user_s32(flags, vptr + 2 * n))
1550 return -TARGET_EFAULT;
bellard3532fa72006-06-24 15:06:03 +00001551
ths5fafdf22007-09-16 21:08:06 +00001552 ret = do_sendrecvmsg(fd, target_msg, flags,
bellard3532fa72006-06-24 15:06:03 +00001553 (num == SOCKOP_sendmsg));
bellard1a9353d2003-03-16 20:28:50 +00001554 }
1555 break;
bellard31e31b82003-02-18 22:55:36 +00001556 case SOCKOP_setsockopt:
bellard7854b052003-03-29 17:22:23 +00001557 {
bellard2f619692007-11-16 10:46:05 +00001558 int sockfd;
1559 int level;
1560 int optname;
1561 abi_ulong optval;
1562 socklen_t optlen;
1563
1564 if (get_user_s32(sockfd, vptr)
1565 || get_user_s32(level, vptr + n)
1566 || get_user_s32(optname, vptr + 2 * n)
1567 || get_user_ual(optval, vptr + 3 * n)
1568 || get_user_u32(optlen, vptr + 4 * n))
1569 return -TARGET_EFAULT;
bellard7854b052003-03-29 17:22:23 +00001570
1571 ret = do_setsockopt(sockfd, level, optname, optval, optlen);
1572 }
1573 break;
bellard31e31b82003-02-18 22:55:36 +00001574 case SOCKOP_getsockopt:
bellard7854b052003-03-29 17:22:23 +00001575 {
bellard2f619692007-11-16 10:46:05 +00001576 int sockfd;
1577 int level;
1578 int optname;
1579 abi_ulong optval;
1580 socklen_t optlen;
bellard7854b052003-03-29 17:22:23 +00001581
bellard2f619692007-11-16 10:46:05 +00001582 if (get_user_s32(sockfd, vptr)
1583 || get_user_s32(level, vptr + n)
1584 || get_user_s32(optname, vptr + 2 * n)
1585 || get_user_ual(optval, vptr + 3 * n)
1586 || get_user_u32(optlen, vptr + 4 * n))
1587 return -TARGET_EFAULT;
1588
1589 ret = do_getsockopt(sockfd, level, optname, optval, optlen);
bellard7854b052003-03-29 17:22:23 +00001590 }
1591 break;
bellard31e31b82003-02-18 22:55:36 +00001592 default:
1593 gemu_log("Unsupported socketcall: %d\n", num);
ths0da46a62007-10-20 20:23:07 +00001594 ret = -TARGET_ENOSYS;
bellard31e31b82003-02-18 22:55:36 +00001595 break;
1596 }
1597 return ret;
1598}
j_mayer32407102007-09-26 23:01:49 +00001599#endif
bellard31e31b82003-02-18 22:55:36 +00001600
j_mayer32407102007-09-26 23:01:49 +00001601#ifdef TARGET_NR_ipc
bellard8853f862004-02-22 14:57:26 +00001602#define N_SHM_REGIONS 32
1603
1604static struct shm_region {
bellard5a4a8982007-11-11 17:39:18 +00001605 abi_ulong start;
1606 abi_ulong size;
bellard8853f862004-02-22 14:57:26 +00001607} shm_regions[N_SHM_REGIONS];
1608
ths3eb6b042007-06-03 14:26:27 +00001609struct target_ipc_perm
1610{
blueswir1992f48a2007-10-14 16:27:31 +00001611 abi_long __key;
1612 abi_ulong uid;
1613 abi_ulong gid;
1614 abi_ulong cuid;
1615 abi_ulong cgid;
ths3eb6b042007-06-03 14:26:27 +00001616 unsigned short int mode;
1617 unsigned short int __pad1;
1618 unsigned short int __seq;
1619 unsigned short int __pad2;
blueswir1992f48a2007-10-14 16:27:31 +00001620 abi_ulong __unused1;
1621 abi_ulong __unused2;
ths3eb6b042007-06-03 14:26:27 +00001622};
1623
1624struct target_semid_ds
1625{
1626 struct target_ipc_perm sem_perm;
blueswir1992f48a2007-10-14 16:27:31 +00001627 abi_ulong sem_otime;
1628 abi_ulong __unused1;
1629 abi_ulong sem_ctime;
1630 abi_ulong __unused2;
1631 abi_ulong sem_nsems;
1632 abi_ulong __unused3;
1633 abi_ulong __unused4;
ths3eb6b042007-06-03 14:26:27 +00001634};
1635
bellard579a97f2007-11-11 14:26:47 +00001636static inline abi_long target_to_host_ipc_perm(struct ipc_perm *host_ip,
1637 abi_ulong target_addr)
ths3eb6b042007-06-03 14:26:27 +00001638{
1639 struct target_ipc_perm *target_ip;
1640 struct target_semid_ds *target_sd;
1641
bellard579a97f2007-11-11 14:26:47 +00001642 if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
1643 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00001644 target_ip=&(target_sd->sem_perm);
1645 host_ip->__key = tswapl(target_ip->__key);
1646 host_ip->uid = tswapl(target_ip->uid);
1647 host_ip->gid = tswapl(target_ip->gid);
1648 host_ip->cuid = tswapl(target_ip->cuid);
1649 host_ip->cgid = tswapl(target_ip->cgid);
1650 host_ip->mode = tswapl(target_ip->mode);
1651 unlock_user_struct(target_sd, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00001652 return 0;
ths3eb6b042007-06-03 14:26:27 +00001653}
1654
bellard579a97f2007-11-11 14:26:47 +00001655static inline abi_long host_to_target_ipc_perm(abi_ulong target_addr,
1656 struct ipc_perm *host_ip)
ths3eb6b042007-06-03 14:26:27 +00001657{
1658 struct target_ipc_perm *target_ip;
1659 struct target_semid_ds *target_sd;
1660
bellard579a97f2007-11-11 14:26:47 +00001661 if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
1662 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00001663 target_ip = &(target_sd->sem_perm);
1664 target_ip->__key = tswapl(host_ip->__key);
1665 target_ip->uid = tswapl(host_ip->uid);
1666 target_ip->gid = tswapl(host_ip->gid);
1667 target_ip->cuid = tswapl(host_ip->cuid);
1668 target_ip->cgid = tswapl(host_ip->cgid);
1669 target_ip->mode = tswapl(host_ip->mode);
1670 unlock_user_struct(target_sd, target_addr, 1);
bellard579a97f2007-11-11 14:26:47 +00001671 return 0;
ths3eb6b042007-06-03 14:26:27 +00001672}
1673
bellard579a97f2007-11-11 14:26:47 +00001674static inline abi_long target_to_host_semid_ds(struct semid_ds *host_sd,
1675 abi_ulong target_addr)
ths3eb6b042007-06-03 14:26:27 +00001676{
1677 struct target_semid_ds *target_sd;
1678
bellard579a97f2007-11-11 14:26:47 +00001679 if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
1680 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00001681 target_to_host_ipc_perm(&(host_sd->sem_perm),target_addr);
1682 host_sd->sem_nsems = tswapl(target_sd->sem_nsems);
1683 host_sd->sem_otime = tswapl(target_sd->sem_otime);
1684 host_sd->sem_ctime = tswapl(target_sd->sem_ctime);
1685 unlock_user_struct(target_sd, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00001686 return 0;
ths3eb6b042007-06-03 14:26:27 +00001687}
1688
bellard579a97f2007-11-11 14:26:47 +00001689static inline abi_long host_to_target_semid_ds(abi_ulong target_addr,
1690 struct semid_ds *host_sd)
ths3eb6b042007-06-03 14:26:27 +00001691{
1692 struct target_semid_ds *target_sd;
1693
bellard579a97f2007-11-11 14:26:47 +00001694 if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
1695 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00001696 host_to_target_ipc_perm(target_addr,&(host_sd->sem_perm));
1697 target_sd->sem_nsems = tswapl(host_sd->sem_nsems);
1698 target_sd->sem_otime = tswapl(host_sd->sem_otime);
1699 target_sd->sem_ctime = tswapl(host_sd->sem_ctime);
1700 unlock_user_struct(target_sd, target_addr, 1);
bellard579a97f2007-11-11 14:26:47 +00001701 return 0;
ths3eb6b042007-06-03 14:26:27 +00001702}
1703
thsfa294812007-02-02 22:05:00 +00001704union semun {
1705 int val;
ths3eb6b042007-06-03 14:26:27 +00001706 struct semid_ds *buf;
thsfa294812007-02-02 22:05:00 +00001707 unsigned short *array;
1708};
1709
ths3eb6b042007-06-03 14:26:27 +00001710union target_semun {
1711 int val;
blueswir1992f48a2007-10-14 16:27:31 +00001712 abi_long buf;
ths3eb6b042007-06-03 14:26:27 +00001713 unsigned short int *array;
1714};
1715
bellard579a97f2007-11-11 14:26:47 +00001716static inline abi_long target_to_host_semun(int cmd,
1717 union semun *host_su,
1718 abi_ulong target_addr,
1719 struct semid_ds *ds)
ths3eb6b042007-06-03 14:26:27 +00001720{
1721 union target_semun *target_su;
1722
1723 switch( cmd ) {
1724 case IPC_STAT:
1725 case IPC_SET:
bellard579a97f2007-11-11 14:26:47 +00001726 if (!lock_user_struct(VERIFY_READ, target_su, target_addr, 1))
1727 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00001728 target_to_host_semid_ds(ds,target_su->buf);
1729 host_su->buf = ds;
1730 unlock_user_struct(target_su, target_addr, 0);
1731 break;
1732 case GETVAL:
1733 case SETVAL:
bellard579a97f2007-11-11 14:26:47 +00001734 if (!lock_user_struct(VERIFY_READ, target_su, target_addr, 1))
1735 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00001736 host_su->val = tswapl(target_su->val);
1737 unlock_user_struct(target_su, target_addr, 0);
1738 break;
1739 case GETALL:
1740 case SETALL:
bellard579a97f2007-11-11 14:26:47 +00001741 if (!lock_user_struct(VERIFY_READ, target_su, target_addr, 1))
1742 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00001743 *host_su->array = tswap16(*target_su->array);
1744 unlock_user_struct(target_su, target_addr, 0);
1745 break;
1746 default:
1747 gemu_log("semun operation not fully supported: %d\n", (int)cmd);
1748 }
bellard579a97f2007-11-11 14:26:47 +00001749 return 0;
ths3eb6b042007-06-03 14:26:27 +00001750}
1751
bellard579a97f2007-11-11 14:26:47 +00001752static inline abi_long host_to_target_semun(int cmd,
1753 abi_ulong target_addr,
1754 union semun *host_su,
1755 struct semid_ds *ds)
ths3eb6b042007-06-03 14:26:27 +00001756{
1757 union target_semun *target_su;
1758
1759 switch( cmd ) {
1760 case IPC_STAT:
1761 case IPC_SET:
bellard579a97f2007-11-11 14:26:47 +00001762 if (lock_user_struct(VERIFY_WRITE, target_su, target_addr, 0))
1763 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00001764 host_to_target_semid_ds(target_su->buf,ds);
1765 unlock_user_struct(target_su, target_addr, 1);
1766 break;
1767 case GETVAL:
1768 case SETVAL:
bellard579a97f2007-11-11 14:26:47 +00001769 if (lock_user_struct(VERIFY_WRITE, target_su, target_addr, 0))
1770 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00001771 target_su->val = tswapl(host_su->val);
1772 unlock_user_struct(target_su, target_addr, 1);
1773 break;
1774 case GETALL:
1775 case SETALL:
bellard579a97f2007-11-11 14:26:47 +00001776 if (lock_user_struct(VERIFY_WRITE, target_su, target_addr, 0))
1777 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00001778 *target_su->array = tswap16(*host_su->array);
1779 unlock_user_struct(target_su, target_addr, 1);
1780 break;
1781 default:
1782 gemu_log("semun operation not fully supported: %d\n", (int)cmd);
1783 }
bellard579a97f2007-11-11 14:26:47 +00001784 return 0;
ths3eb6b042007-06-03 14:26:27 +00001785}
1786
blueswir1992f48a2007-10-14 16:27:31 +00001787static inline abi_long do_semctl(int first, int second, int third,
1788 abi_long ptr)
ths3eb6b042007-06-03 14:26:27 +00001789{
1790 union semun arg;
1791 struct semid_ds dsarg;
1792 int cmd = third&0xff;
blueswir1992f48a2007-10-14 16:27:31 +00001793 abi_long ret = 0;
ths3eb6b042007-06-03 14:26:27 +00001794
1795 switch( cmd ) {
1796 case GETVAL:
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 SETVAL:
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 GETALL:
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 SETALL:
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_STAT:
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 case IPC_SET:
1822 target_to_host_semun(cmd,&arg,ptr,&dsarg);
1823 ret = get_errno(semctl(first, second, cmd, arg));
1824 host_to_target_semun(cmd,ptr,&arg,&dsarg);
1825 break;
1826 default:
1827 ret = get_errno(semctl(first, second, cmd, arg));
1828 }
1829
1830 return ret;
1831}
1832
ths1bc012f2007-06-03 14:27:49 +00001833struct target_msqid_ds
1834{
1835 struct target_ipc_perm msg_perm;
blueswir1992f48a2007-10-14 16:27:31 +00001836 abi_ulong msg_stime;
1837 abi_ulong __unused1;
1838 abi_ulong msg_rtime;
1839 abi_ulong __unused2;
1840 abi_ulong msg_ctime;
1841 abi_ulong __unused3;
1842 abi_ulong __msg_cbytes;
1843 abi_ulong msg_qnum;
1844 abi_ulong msg_qbytes;
1845 abi_ulong msg_lspid;
1846 abi_ulong msg_lrpid;
1847 abi_ulong __unused4;
1848 abi_ulong __unused5;
ths1bc012f2007-06-03 14:27:49 +00001849};
1850
bellard579a97f2007-11-11 14:26:47 +00001851static inline abi_long target_to_host_msqid_ds(struct msqid_ds *host_md,
1852 abi_ulong target_addr)
ths1bc012f2007-06-03 14:27:49 +00001853{
1854 struct target_msqid_ds *target_md;
1855
bellard579a97f2007-11-11 14:26:47 +00001856 if (!lock_user_struct(VERIFY_READ, target_md, target_addr, 1))
1857 return -TARGET_EFAULT;
ths1bc012f2007-06-03 14:27:49 +00001858 target_to_host_ipc_perm(&(host_md->msg_perm),target_addr);
1859 host_md->msg_stime = tswapl(target_md->msg_stime);
1860 host_md->msg_rtime = tswapl(target_md->msg_rtime);
1861 host_md->msg_ctime = tswapl(target_md->msg_ctime);
1862 host_md->__msg_cbytes = tswapl(target_md->__msg_cbytes);
1863 host_md->msg_qnum = tswapl(target_md->msg_qnum);
1864 host_md->msg_qbytes = tswapl(target_md->msg_qbytes);
1865 host_md->msg_lspid = tswapl(target_md->msg_lspid);
1866 host_md->msg_lrpid = tswapl(target_md->msg_lrpid);
1867 unlock_user_struct(target_md, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00001868 return 0;
ths1bc012f2007-06-03 14:27:49 +00001869}
1870
bellard579a97f2007-11-11 14:26:47 +00001871static inline abi_long host_to_target_msqid_ds(abi_ulong target_addr,
1872 struct msqid_ds *host_md)
ths1bc012f2007-06-03 14:27:49 +00001873{
1874 struct target_msqid_ds *target_md;
1875
bellard579a97f2007-11-11 14:26:47 +00001876 if (!lock_user_struct(VERIFY_WRITE, target_md, target_addr, 0))
1877 return -TARGET_EFAULT;
ths1bc012f2007-06-03 14:27:49 +00001878 host_to_target_ipc_perm(target_addr,&(host_md->msg_perm));
1879 target_md->msg_stime = tswapl(host_md->msg_stime);
1880 target_md->msg_rtime = tswapl(host_md->msg_rtime);
1881 target_md->msg_ctime = tswapl(host_md->msg_ctime);
1882 target_md->__msg_cbytes = tswapl(host_md->__msg_cbytes);
1883 target_md->msg_qnum = tswapl(host_md->msg_qnum);
1884 target_md->msg_qbytes = tswapl(host_md->msg_qbytes);
1885 target_md->msg_lspid = tswapl(host_md->msg_lspid);
1886 target_md->msg_lrpid = tswapl(host_md->msg_lrpid);
1887 unlock_user_struct(target_md, target_addr, 1);
bellard579a97f2007-11-11 14:26:47 +00001888 return 0;
ths1bc012f2007-06-03 14:27:49 +00001889}
1890
blueswir1992f48a2007-10-14 16:27:31 +00001891static inline abi_long do_msgctl(int first, int second, abi_long ptr)
ths1bc012f2007-06-03 14:27:49 +00001892{
1893 struct msqid_ds dsarg;
1894 int cmd = second&0xff;
blueswir1992f48a2007-10-14 16:27:31 +00001895 abi_long ret = 0;
ths1bc012f2007-06-03 14:27:49 +00001896 switch( cmd ) {
1897 case IPC_STAT:
1898 case IPC_SET:
1899 target_to_host_msqid_ds(&dsarg,ptr);
1900 ret = get_errno(msgctl(first, cmd, &dsarg));
1901 host_to_target_msqid_ds(ptr,&dsarg);
1902 default:
1903 ret = get_errno(msgctl(first, cmd, &dsarg));
1904 }
1905 return ret;
1906}
1907
1908struct target_msgbuf {
blueswir1992f48a2007-10-14 16:27:31 +00001909 abi_ulong mtype;
ths1bc012f2007-06-03 14:27:49 +00001910 char mtext[1];
1911};
1912
blueswir1992f48a2007-10-14 16:27:31 +00001913static inline abi_long do_msgsnd(int msqid, abi_long msgp,
1914 unsigned int msgsz, int msgflg)
ths1bc012f2007-06-03 14:27:49 +00001915{
1916 struct target_msgbuf *target_mb;
1917 struct msgbuf *host_mb;
blueswir1992f48a2007-10-14 16:27:31 +00001918 abi_long ret = 0;
ths1bc012f2007-06-03 14:27:49 +00001919
bellard579a97f2007-11-11 14:26:47 +00001920 if (!lock_user_struct(VERIFY_READ, target_mb, msgp, 0))
1921 return -TARGET_EFAULT;
ths1bc012f2007-06-03 14:27:49 +00001922 host_mb = malloc(msgsz+sizeof(long));
1923 host_mb->mtype = tswapl(target_mb->mtype);
1924 memcpy(host_mb->mtext,target_mb->mtext,msgsz);
1925 ret = get_errno(msgsnd(msqid, host_mb, msgsz, msgflg));
1926 free(host_mb);
1927 unlock_user_struct(target_mb, msgp, 0);
1928
1929 return ret;
1930}
1931
blueswir1992f48a2007-10-14 16:27:31 +00001932static inline abi_long do_msgrcv(int msqid, abi_long msgp,
1933 unsigned int msgsz, int msgtype,
1934 int msgflg)
ths1bc012f2007-06-03 14:27:49 +00001935{
1936 struct target_msgbuf *target_mb;
bellard579a97f2007-11-11 14:26:47 +00001937 char *target_mtext;
ths1bc012f2007-06-03 14:27:49 +00001938 struct msgbuf *host_mb;
blueswir1992f48a2007-10-14 16:27:31 +00001939 abi_long ret = 0;
ths1bc012f2007-06-03 14:27:49 +00001940
bellard579a97f2007-11-11 14:26:47 +00001941 if (!lock_user_struct(VERIFY_WRITE, target_mb, msgp, 0))
1942 return -TARGET_EFAULT;
ths1bc012f2007-06-03 14:27:49 +00001943 host_mb = malloc(msgsz+sizeof(long));
1944 ret = get_errno(msgrcv(msqid, host_mb, msgsz, 1, msgflg));
bellard579a97f2007-11-11 14:26:47 +00001945 if (ret > 0) {
1946 abi_ulong target_mtext_addr = msgp + sizeof(abi_ulong);
1947 target_mtext = lock_user(VERIFY_WRITE, target_mtext_addr, ret, 0);
1948 if (!target_mtext) {
1949 ret = -TARGET_EFAULT;
1950 goto end;
1951 }
ths1bc012f2007-06-03 14:27:49 +00001952 memcpy(target_mb->mtext, host_mb->mtext, ret);
bellard579a97f2007-11-11 14:26:47 +00001953 unlock_user(target_mtext, target_mtext_addr, ret);
1954 }
ths1bc012f2007-06-03 14:27:49 +00001955 target_mb->mtype = tswapl(host_mb->mtype);
1956 free(host_mb);
ths1bc012f2007-06-03 14:27:49 +00001957
bellard579a97f2007-11-11 14:26:47 +00001958end:
1959 if (target_mb)
1960 unlock_user_struct(target_mb, msgp, 1);
ths1bc012f2007-06-03 14:27:49 +00001961 return ret;
1962}
1963
pbrook53a59602006-03-25 19:31:22 +00001964/* ??? This only works with linear mappings. */
ths0da46a62007-10-20 20:23:07 +00001965/* do_ipc() must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001966static abi_long do_ipc(unsigned int call, int first,
1967 int second, int third,
1968 abi_long ptr, abi_long fifth)
bellard8853f862004-02-22 14:57:26 +00001969{
1970 int version;
blueswir1992f48a2007-10-14 16:27:31 +00001971 abi_long ret = 0;
bellard8853f862004-02-22 14:57:26 +00001972 struct shmid_ds shm_info;
1973 int i;
1974
1975 version = call >> 16;
1976 call &= 0xffff;
1977
1978 switch (call) {
thsfa294812007-02-02 22:05:00 +00001979 case IPCOP_semop:
bellard579a97f2007-11-11 14:26:47 +00001980 ret = get_errno(semop(first,(struct sembuf *)g2h(ptr), second));
thsfa294812007-02-02 22:05:00 +00001981 break;
1982
1983 case IPCOP_semget:
1984 ret = get_errno(semget(first, second, third));
1985 break;
1986
1987 case IPCOP_semctl:
ths3eb6b042007-06-03 14:26:27 +00001988 ret = do_semctl(first, second, third, ptr);
thsfa294812007-02-02 22:05:00 +00001989 break;
1990
1991 case IPCOP_semtimedop:
j_mayer32407102007-09-26 23:01:49 +00001992 gemu_log("Unsupported ipc call: %d (version %d)\n", call, version);
ths0da46a62007-10-20 20:23:07 +00001993 ret = -TARGET_ENOSYS;
thsfa294812007-02-02 22:05:00 +00001994 break;
thsd96372e2007-02-02 22:05:44 +00001995
1996 case IPCOP_msgget:
1997 ret = get_errno(msgget(first, second));
1998 break;
1999
2000 case IPCOP_msgsnd:
ths1bc012f2007-06-03 14:27:49 +00002001 ret = do_msgsnd(first, ptr, second, third);
thsd96372e2007-02-02 22:05:44 +00002002 break;
2003
2004 case IPCOP_msgctl:
ths1bc012f2007-06-03 14:27:49 +00002005 ret = do_msgctl(first, second, ptr);
thsd96372e2007-02-02 22:05:44 +00002006 break;
2007
2008 case IPCOP_msgrcv:
ths1bc012f2007-06-03 14:27:49 +00002009 {
bellard579a97f2007-11-11 14:26:47 +00002010 /* XXX: this code is not correct */
ths1bc012f2007-06-03 14:27:49 +00002011 struct ipc_kludge
2012 {
2013 void *__unbounded msgp;
2014 long int msgtyp;
2015 };
thsd96372e2007-02-02 22:05:44 +00002016
bellard579a97f2007-11-11 14:26:47 +00002017 struct ipc_kludge *foo = (struct ipc_kludge *)g2h(ptr);
ths1bc012f2007-06-03 14:27:49 +00002018 struct msgbuf *msgp = (struct msgbuf *) foo->msgp;
thsd96372e2007-02-02 22:05:44 +00002019
ths1bc012f2007-06-03 14:27:49 +00002020 ret = do_msgrcv(first, (long)msgp, second, 0, third);
thsd96372e2007-02-02 22:05:44 +00002021
ths1bc012f2007-06-03 14:27:49 +00002022 }
thsd96372e2007-02-02 22:05:44 +00002023 break;
2024
bellard8853f862004-02-22 14:57:26 +00002025 case IPCOP_shmat:
bellard5a4a8982007-11-11 17:39:18 +00002026 {
2027 abi_ulong raddr;
2028 void *host_addr;
2029 /* SHM_* flags are the same on all linux platforms */
2030 host_addr = shmat(first, (void *)g2h(ptr), second);
2031 if (host_addr == (void *)-1) {
2032 ret = get_errno((long)host_addr);
bellard8853f862004-02-22 14:57:26 +00002033 break;
bellard5a4a8982007-11-11 17:39:18 +00002034 }
2035 raddr = h2g((unsigned long)host_addr);
2036 /* find out the length of the shared memory segment */
2037
2038 ret = get_errno(shmctl(first, IPC_STAT, &shm_info));
2039 if (is_error(ret)) {
2040 /* can't get length, bail out */
2041 shmdt(host_addr);
2042 break;
2043 }
2044 page_set_flags(raddr, raddr + shm_info.shm_segsz,
2045 PAGE_VALID | PAGE_READ |
2046 ((second & SHM_RDONLY)? 0: PAGE_WRITE));
2047 for (i = 0; i < N_SHM_REGIONS; ++i) {
2048 if (shm_regions[i].start == 0) {
2049 shm_regions[i].start = raddr;
2050 shm_regions[i].size = shm_info.shm_segsz;
2051 break;
2052 }
2053 }
bellard2f619692007-11-16 10:46:05 +00002054 if (put_user_ual(raddr, third))
bellard5a4a8982007-11-11 17:39:18 +00002055 return -TARGET_EFAULT;
2056 ret = 0;
2057 }
bellard8853f862004-02-22 14:57:26 +00002058 break;
2059 case IPCOP_shmdt:
2060 for (i = 0; i < N_SHM_REGIONS; ++i) {
2061 if (shm_regions[i].start == ptr) {
2062 shm_regions[i].start = 0;
2063 page_set_flags(ptr, shm_regions[i].size, 0);
2064 break;
2065 }
2066 }
bellard5a4a8982007-11-11 17:39:18 +00002067 ret = get_errno(shmdt((void *)g2h(ptr)));
bellard8853f862004-02-22 14:57:26 +00002068 break;
2069
2070 case IPCOP_shmget:
2071 /* IPC_* flag values are the same on all linux platforms */
2072 ret = get_errno(shmget(first, second, third));
2073 break;
2074
2075 /* IPC_* and SHM_* command values are the same on all linux platforms */
2076 case IPCOP_shmctl:
2077 switch(second) {
2078 case IPC_RMID:
2079 case SHM_LOCK:
2080 case SHM_UNLOCK:
2081 ret = get_errno(shmctl(first, second, NULL));
2082 break;
2083 default:
2084 goto unimplemented;
2085 }
2086 break;
2087 default:
2088 unimplemented:
j_mayer32407102007-09-26 23:01:49 +00002089 gemu_log("Unsupported ipc call: %d (version %d)\n", call, version);
ths0da46a62007-10-20 20:23:07 +00002090 ret = -TARGET_ENOSYS;
bellard8853f862004-02-22 14:57:26 +00002091 break;
2092 }
2093 return ret;
2094}
j_mayer32407102007-09-26 23:01:49 +00002095#endif
bellard8853f862004-02-22 14:57:26 +00002096
bellard31e31b82003-02-18 22:55:36 +00002097/* kernel structure types definitions */
2098#define IFNAMSIZ 16
2099
2100#define STRUCT(name, list...) STRUCT_ ## name,
2101#define STRUCT_SPECIAL(name) STRUCT_ ## name,
2102enum {
2103#include "syscall_types.h"
2104};
2105#undef STRUCT
2106#undef STRUCT_SPECIAL
2107
2108#define STRUCT(name, list...) const argtype struct_ ## name ## _def[] = { list, TYPE_NULL };
2109#define STRUCT_SPECIAL(name)
2110#include "syscall_types.h"
2111#undef STRUCT
2112#undef STRUCT_SPECIAL
2113
2114typedef struct IOCTLEntry {
bellard2ab83ea2003-06-15 19:56:46 +00002115 unsigned int target_cmd;
2116 unsigned int host_cmd;
bellard31e31b82003-02-18 22:55:36 +00002117 const char *name;
2118 int access;
bellard1a9353d2003-03-16 20:28:50 +00002119 const argtype arg_type[5];
bellard31e31b82003-02-18 22:55:36 +00002120} IOCTLEntry;
2121
2122#define IOC_R 0x0001
2123#define IOC_W 0x0002
2124#define IOC_RW (IOC_R | IOC_W)
2125
2126#define MAX_STRUCT_SIZE 4096
2127
bellard2ab83ea2003-06-15 19:56:46 +00002128IOCTLEntry ioctl_entries[] = {
bellard31e31b82003-02-18 22:55:36 +00002129#define IOCTL(cmd, access, types...) \
2130 { TARGET_ ## cmd, cmd, #cmd, access, { types } },
2131#include "ioctls.h"
2132 { 0, 0, },
2133};
2134
pbrook53a59602006-03-25 19:31:22 +00002135/* ??? Implement proper locking for ioctls. */
ths0da46a62007-10-20 20:23:07 +00002136/* do_ioctl() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00002137static abi_long do_ioctl(int fd, abi_long cmd, abi_long arg)
bellard31e31b82003-02-18 22:55:36 +00002138{
2139 const IOCTLEntry *ie;
2140 const argtype *arg_type;
blueswir1992f48a2007-10-14 16:27:31 +00002141 abi_long ret;
bellard31e31b82003-02-18 22:55:36 +00002142 uint8_t buf_temp[MAX_STRUCT_SIZE];
pbrook53a59602006-03-25 19:31:22 +00002143 int target_size;
2144 void *argptr;
bellard31e31b82003-02-18 22:55:36 +00002145
2146 ie = ioctl_entries;
2147 for(;;) {
2148 if (ie->target_cmd == 0) {
j_mayer32407102007-09-26 23:01:49 +00002149 gemu_log("Unsupported ioctl: cmd=0x%04lx\n", (long)cmd);
ths0da46a62007-10-20 20:23:07 +00002150 return -TARGET_ENOSYS;
bellard31e31b82003-02-18 22:55:36 +00002151 }
2152 if (ie->target_cmd == cmd)
2153 break;
2154 ie++;
2155 }
2156 arg_type = ie->arg_type;
bellard9de5e442003-03-23 16:49:39 +00002157#if defined(DEBUG)
j_mayer32407102007-09-26 23:01:49 +00002158 gemu_log("ioctl: cmd=0x%04lx (%s)\n", (long)cmd, ie->name);
bellard72f03902003-02-18 23:33:18 +00002159#endif
bellard31e31b82003-02-18 22:55:36 +00002160 switch(arg_type[0]) {
2161 case TYPE_NULL:
2162 /* no argument */
2163 ret = get_errno(ioctl(fd, ie->host_cmd));
2164 break;
2165 case TYPE_PTRVOID:
2166 case TYPE_INT:
2167 /* int argment */
2168 ret = get_errno(ioctl(fd, ie->host_cmd, arg));
2169 break;
2170 case TYPE_PTR:
2171 arg_type++;
pbrook53a59602006-03-25 19:31:22 +00002172 target_size = thunk_type_size(arg_type, 0);
bellard31e31b82003-02-18 22:55:36 +00002173 switch(ie->access) {
2174 case IOC_R:
2175 ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
2176 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00002177 argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
2178 if (!argptr)
2179 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00002180 thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
2181 unlock_user(argptr, arg, target_size);
bellard31e31b82003-02-18 22:55:36 +00002182 }
2183 break;
2184 case IOC_W:
bellard579a97f2007-11-11 14:26:47 +00002185 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
2186 if (!argptr)
2187 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00002188 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
2189 unlock_user(argptr, arg, 0);
bellard31e31b82003-02-18 22:55:36 +00002190 ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
2191 break;
2192 default:
2193 case IOC_RW:
bellard579a97f2007-11-11 14:26:47 +00002194 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
2195 if (!argptr)
2196 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00002197 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
2198 unlock_user(argptr, arg, 0);
bellard31e31b82003-02-18 22:55:36 +00002199 ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
2200 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00002201 argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
2202 if (!argptr)
2203 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00002204 thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
2205 unlock_user(argptr, arg, target_size);
bellard31e31b82003-02-18 22:55:36 +00002206 }
2207 break;
2208 }
2209 break;
2210 default:
j_mayer32407102007-09-26 23:01:49 +00002211 gemu_log("Unsupported ioctl type: cmd=0x%04lx type=%d\n",
2212 (long)cmd, arg_type[0]);
ths0da46a62007-10-20 20:23:07 +00002213 ret = -TARGET_ENOSYS;
bellard31e31b82003-02-18 22:55:36 +00002214 break;
2215 }
2216 return ret;
2217}
2218
2219bitmask_transtbl iflag_tbl[] = {
2220 { TARGET_IGNBRK, TARGET_IGNBRK, IGNBRK, IGNBRK },
2221 { TARGET_BRKINT, TARGET_BRKINT, BRKINT, BRKINT },
2222 { TARGET_IGNPAR, TARGET_IGNPAR, IGNPAR, IGNPAR },
2223 { TARGET_PARMRK, TARGET_PARMRK, PARMRK, PARMRK },
2224 { TARGET_INPCK, TARGET_INPCK, INPCK, INPCK },
2225 { TARGET_ISTRIP, TARGET_ISTRIP, ISTRIP, ISTRIP },
2226 { TARGET_INLCR, TARGET_INLCR, INLCR, INLCR },
2227 { TARGET_IGNCR, TARGET_IGNCR, IGNCR, IGNCR },
2228 { TARGET_ICRNL, TARGET_ICRNL, ICRNL, ICRNL },
2229 { TARGET_IUCLC, TARGET_IUCLC, IUCLC, IUCLC },
2230 { TARGET_IXON, TARGET_IXON, IXON, IXON },
2231 { TARGET_IXANY, TARGET_IXANY, IXANY, IXANY },
2232 { TARGET_IXOFF, TARGET_IXOFF, IXOFF, IXOFF },
2233 { TARGET_IMAXBEL, TARGET_IMAXBEL, IMAXBEL, IMAXBEL },
2234 { 0, 0, 0, 0 }
2235};
2236
2237bitmask_transtbl oflag_tbl[] = {
2238 { TARGET_OPOST, TARGET_OPOST, OPOST, OPOST },
2239 { TARGET_OLCUC, TARGET_OLCUC, OLCUC, OLCUC },
2240 { TARGET_ONLCR, TARGET_ONLCR, ONLCR, ONLCR },
2241 { TARGET_OCRNL, TARGET_OCRNL, OCRNL, OCRNL },
2242 { TARGET_ONOCR, TARGET_ONOCR, ONOCR, ONOCR },
2243 { TARGET_ONLRET, TARGET_ONLRET, ONLRET, ONLRET },
2244 { TARGET_OFILL, TARGET_OFILL, OFILL, OFILL },
2245 { TARGET_OFDEL, TARGET_OFDEL, OFDEL, OFDEL },
2246 { TARGET_NLDLY, TARGET_NL0, NLDLY, NL0 },
2247 { TARGET_NLDLY, TARGET_NL1, NLDLY, NL1 },
2248 { TARGET_CRDLY, TARGET_CR0, CRDLY, CR0 },
2249 { TARGET_CRDLY, TARGET_CR1, CRDLY, CR1 },
2250 { TARGET_CRDLY, TARGET_CR2, CRDLY, CR2 },
2251 { TARGET_CRDLY, TARGET_CR3, CRDLY, CR3 },
2252 { TARGET_TABDLY, TARGET_TAB0, TABDLY, TAB0 },
2253 { TARGET_TABDLY, TARGET_TAB1, TABDLY, TAB1 },
2254 { TARGET_TABDLY, TARGET_TAB2, TABDLY, TAB2 },
2255 { TARGET_TABDLY, TARGET_TAB3, TABDLY, TAB3 },
2256 { TARGET_BSDLY, TARGET_BS0, BSDLY, BS0 },
2257 { TARGET_BSDLY, TARGET_BS1, BSDLY, BS1 },
2258 { TARGET_VTDLY, TARGET_VT0, VTDLY, VT0 },
2259 { TARGET_VTDLY, TARGET_VT1, VTDLY, VT1 },
2260 { TARGET_FFDLY, TARGET_FF0, FFDLY, FF0 },
2261 { TARGET_FFDLY, TARGET_FF1, FFDLY, FF1 },
2262 { 0, 0, 0, 0 }
2263};
2264
2265bitmask_transtbl cflag_tbl[] = {
2266 { TARGET_CBAUD, TARGET_B0, CBAUD, B0 },
2267 { TARGET_CBAUD, TARGET_B50, CBAUD, B50 },
2268 { TARGET_CBAUD, TARGET_B75, CBAUD, B75 },
2269 { TARGET_CBAUD, TARGET_B110, CBAUD, B110 },
2270 { TARGET_CBAUD, TARGET_B134, CBAUD, B134 },
2271 { TARGET_CBAUD, TARGET_B150, CBAUD, B150 },
2272 { TARGET_CBAUD, TARGET_B200, CBAUD, B200 },
2273 { TARGET_CBAUD, TARGET_B300, CBAUD, B300 },
2274 { TARGET_CBAUD, TARGET_B600, CBAUD, B600 },
2275 { TARGET_CBAUD, TARGET_B1200, CBAUD, B1200 },
2276 { TARGET_CBAUD, TARGET_B1800, CBAUD, B1800 },
2277 { TARGET_CBAUD, TARGET_B2400, CBAUD, B2400 },
2278 { TARGET_CBAUD, TARGET_B4800, CBAUD, B4800 },
2279 { TARGET_CBAUD, TARGET_B9600, CBAUD, B9600 },
2280 { TARGET_CBAUD, TARGET_B19200, CBAUD, B19200 },
2281 { TARGET_CBAUD, TARGET_B38400, CBAUD, B38400 },
2282 { TARGET_CBAUD, TARGET_B57600, CBAUD, B57600 },
2283 { TARGET_CBAUD, TARGET_B115200, CBAUD, B115200 },
2284 { TARGET_CBAUD, TARGET_B230400, CBAUD, B230400 },
2285 { TARGET_CBAUD, TARGET_B460800, CBAUD, B460800 },
2286 { TARGET_CSIZE, TARGET_CS5, CSIZE, CS5 },
2287 { TARGET_CSIZE, TARGET_CS6, CSIZE, CS6 },
2288 { TARGET_CSIZE, TARGET_CS7, CSIZE, CS7 },
2289 { TARGET_CSIZE, TARGET_CS8, CSIZE, CS8 },
2290 { TARGET_CSTOPB, TARGET_CSTOPB, CSTOPB, CSTOPB },
2291 { TARGET_CREAD, TARGET_CREAD, CREAD, CREAD },
2292 { TARGET_PARENB, TARGET_PARENB, PARENB, PARENB },
2293 { TARGET_PARODD, TARGET_PARODD, PARODD, PARODD },
2294 { TARGET_HUPCL, TARGET_HUPCL, HUPCL, HUPCL },
2295 { TARGET_CLOCAL, TARGET_CLOCAL, CLOCAL, CLOCAL },
2296 { TARGET_CRTSCTS, TARGET_CRTSCTS, CRTSCTS, CRTSCTS },
2297 { 0, 0, 0, 0 }
2298};
2299
2300bitmask_transtbl lflag_tbl[] = {
2301 { TARGET_ISIG, TARGET_ISIG, ISIG, ISIG },
2302 { TARGET_ICANON, TARGET_ICANON, ICANON, ICANON },
2303 { TARGET_XCASE, TARGET_XCASE, XCASE, XCASE },
2304 { TARGET_ECHO, TARGET_ECHO, ECHO, ECHO },
2305 { TARGET_ECHOE, TARGET_ECHOE, ECHOE, ECHOE },
2306 { TARGET_ECHOK, TARGET_ECHOK, ECHOK, ECHOK },
2307 { TARGET_ECHONL, TARGET_ECHONL, ECHONL, ECHONL },
2308 { TARGET_NOFLSH, TARGET_NOFLSH, NOFLSH, NOFLSH },
2309 { TARGET_TOSTOP, TARGET_TOSTOP, TOSTOP, TOSTOP },
2310 { TARGET_ECHOCTL, TARGET_ECHOCTL, ECHOCTL, ECHOCTL },
2311 { TARGET_ECHOPRT, TARGET_ECHOPRT, ECHOPRT, ECHOPRT },
2312 { TARGET_ECHOKE, TARGET_ECHOKE, ECHOKE, ECHOKE },
2313 { TARGET_FLUSHO, TARGET_FLUSHO, FLUSHO, FLUSHO },
2314 { TARGET_PENDIN, TARGET_PENDIN, PENDIN, PENDIN },
2315 { TARGET_IEXTEN, TARGET_IEXTEN, IEXTEN, IEXTEN },
2316 { 0, 0, 0, 0 }
2317};
2318
2319static void target_to_host_termios (void *dst, const void *src)
2320{
2321 struct host_termios *host = dst;
2322 const struct target_termios *target = src;
ths3b46e622007-09-17 08:09:54 +00002323
ths5fafdf22007-09-16 21:08:06 +00002324 host->c_iflag =
bellard31e31b82003-02-18 22:55:36 +00002325 target_to_host_bitmask(tswap32(target->c_iflag), iflag_tbl);
ths5fafdf22007-09-16 21:08:06 +00002326 host->c_oflag =
bellard31e31b82003-02-18 22:55:36 +00002327 target_to_host_bitmask(tswap32(target->c_oflag), oflag_tbl);
ths5fafdf22007-09-16 21:08:06 +00002328 host->c_cflag =
bellard31e31b82003-02-18 22:55:36 +00002329 target_to_host_bitmask(tswap32(target->c_cflag), cflag_tbl);
ths5fafdf22007-09-16 21:08:06 +00002330 host->c_lflag =
bellard31e31b82003-02-18 22:55:36 +00002331 target_to_host_bitmask(tswap32(target->c_lflag), lflag_tbl);
2332 host->c_line = target->c_line;
ths3b46e622007-09-17 08:09:54 +00002333
ths5fafdf22007-09-16 21:08:06 +00002334 host->c_cc[VINTR] = target->c_cc[TARGET_VINTR];
2335 host->c_cc[VQUIT] = target->c_cc[TARGET_VQUIT];
ths3b46e622007-09-17 08:09:54 +00002336 host->c_cc[VERASE] = target->c_cc[TARGET_VERASE];
ths5fafdf22007-09-16 21:08:06 +00002337 host->c_cc[VKILL] = target->c_cc[TARGET_VKILL];
ths3b46e622007-09-17 08:09:54 +00002338 host->c_cc[VEOF] = target->c_cc[TARGET_VEOF];
ths5fafdf22007-09-16 21:08:06 +00002339 host->c_cc[VTIME] = target->c_cc[TARGET_VTIME];
ths3b46e622007-09-17 08:09:54 +00002340 host->c_cc[VMIN] = target->c_cc[TARGET_VMIN];
ths5fafdf22007-09-16 21:08:06 +00002341 host->c_cc[VSWTC] = target->c_cc[TARGET_VSWTC];
ths3b46e622007-09-17 08:09:54 +00002342 host->c_cc[VSTART] = target->c_cc[TARGET_VSTART];
ths5fafdf22007-09-16 21:08:06 +00002343 host->c_cc[VSTOP] = target->c_cc[TARGET_VSTOP];
2344 host->c_cc[VSUSP] = target->c_cc[TARGET_VSUSP];
ths3b46e622007-09-17 08:09:54 +00002345 host->c_cc[VEOL] = target->c_cc[TARGET_VEOL];
2346 host->c_cc[VREPRINT] = target->c_cc[TARGET_VREPRINT];
2347 host->c_cc[VDISCARD] = target->c_cc[TARGET_VDISCARD];
2348 host->c_cc[VWERASE] = target->c_cc[TARGET_VWERASE];
2349 host->c_cc[VLNEXT] = target->c_cc[TARGET_VLNEXT];
ths5fafdf22007-09-16 21:08:06 +00002350 host->c_cc[VEOL2] = target->c_cc[TARGET_VEOL2];
bellard31e31b82003-02-18 22:55:36 +00002351}
ths3b46e622007-09-17 08:09:54 +00002352
bellard31e31b82003-02-18 22:55:36 +00002353static void host_to_target_termios (void *dst, const void *src)
2354{
2355 struct target_termios *target = dst;
2356 const struct host_termios *host = src;
2357
ths5fafdf22007-09-16 21:08:06 +00002358 target->c_iflag =
bellard31e31b82003-02-18 22:55:36 +00002359 tswap32(host_to_target_bitmask(host->c_iflag, iflag_tbl));
ths5fafdf22007-09-16 21:08:06 +00002360 target->c_oflag =
bellard31e31b82003-02-18 22:55:36 +00002361 tswap32(host_to_target_bitmask(host->c_oflag, oflag_tbl));
ths5fafdf22007-09-16 21:08:06 +00002362 target->c_cflag =
bellard31e31b82003-02-18 22:55:36 +00002363 tswap32(host_to_target_bitmask(host->c_cflag, cflag_tbl));
ths5fafdf22007-09-16 21:08:06 +00002364 target->c_lflag =
bellard31e31b82003-02-18 22:55:36 +00002365 tswap32(host_to_target_bitmask(host->c_lflag, lflag_tbl));
2366 target->c_line = host->c_line;
ths3b46e622007-09-17 08:09:54 +00002367
bellard31e31b82003-02-18 22:55:36 +00002368 target->c_cc[TARGET_VINTR] = host->c_cc[VINTR];
2369 target->c_cc[TARGET_VQUIT] = host->c_cc[VQUIT];
2370 target->c_cc[TARGET_VERASE] = host->c_cc[VERASE];
2371 target->c_cc[TARGET_VKILL] = host->c_cc[VKILL];
2372 target->c_cc[TARGET_VEOF] = host->c_cc[VEOF];
2373 target->c_cc[TARGET_VTIME] = host->c_cc[VTIME];
2374 target->c_cc[TARGET_VMIN] = host->c_cc[VMIN];
2375 target->c_cc[TARGET_VSWTC] = host->c_cc[VSWTC];
2376 target->c_cc[TARGET_VSTART] = host->c_cc[VSTART];
2377 target->c_cc[TARGET_VSTOP] = host->c_cc[VSTOP];
2378 target->c_cc[TARGET_VSUSP] = host->c_cc[VSUSP];
2379 target->c_cc[TARGET_VEOL] = host->c_cc[VEOL];
2380 target->c_cc[TARGET_VREPRINT] = host->c_cc[VREPRINT];
2381 target->c_cc[TARGET_VDISCARD] = host->c_cc[VDISCARD];
2382 target->c_cc[TARGET_VWERASE] = host->c_cc[VWERASE];
2383 target->c_cc[TARGET_VLNEXT] = host->c_cc[VLNEXT];
2384 target->c_cc[TARGET_VEOL2] = host->c_cc[VEOL2];
2385}
2386
2387StructEntry struct_termios_def = {
2388 .convert = { host_to_target_termios, target_to_host_termios },
2389 .size = { sizeof(struct target_termios), sizeof(struct host_termios) },
2390 .align = { __alignof__(struct target_termios), __alignof__(struct host_termios) },
2391};
2392
bellard5286db72003-06-05 00:57:30 +00002393static bitmask_transtbl mmap_flags_tbl[] = {
2394 { TARGET_MAP_SHARED, TARGET_MAP_SHARED, MAP_SHARED, MAP_SHARED },
2395 { TARGET_MAP_PRIVATE, TARGET_MAP_PRIVATE, MAP_PRIVATE, MAP_PRIVATE },
2396 { TARGET_MAP_FIXED, TARGET_MAP_FIXED, MAP_FIXED, MAP_FIXED },
2397 { TARGET_MAP_ANONYMOUS, TARGET_MAP_ANONYMOUS, MAP_ANONYMOUS, MAP_ANONYMOUS },
2398 { TARGET_MAP_GROWSDOWN, TARGET_MAP_GROWSDOWN, MAP_GROWSDOWN, MAP_GROWSDOWN },
2399 { TARGET_MAP_DENYWRITE, TARGET_MAP_DENYWRITE, MAP_DENYWRITE, MAP_DENYWRITE },
2400 { TARGET_MAP_EXECUTABLE, TARGET_MAP_EXECUTABLE, MAP_EXECUTABLE, MAP_EXECUTABLE },
2401 { TARGET_MAP_LOCKED, TARGET_MAP_LOCKED, MAP_LOCKED, MAP_LOCKED },
2402 { 0, 0, 0, 0 }
2403};
2404
bellardffa65c32004-01-04 23:57:22 +00002405static bitmask_transtbl fcntl_flags_tbl[] = {
2406 { TARGET_O_ACCMODE, TARGET_O_WRONLY, O_ACCMODE, O_WRONLY, },
2407 { TARGET_O_ACCMODE, TARGET_O_RDWR, O_ACCMODE, O_RDWR, },
2408 { TARGET_O_CREAT, TARGET_O_CREAT, O_CREAT, O_CREAT, },
2409 { TARGET_O_EXCL, TARGET_O_EXCL, O_EXCL, O_EXCL, },
2410 { TARGET_O_NOCTTY, TARGET_O_NOCTTY, O_NOCTTY, O_NOCTTY, },
2411 { TARGET_O_TRUNC, TARGET_O_TRUNC, O_TRUNC, O_TRUNC, },
2412 { TARGET_O_APPEND, TARGET_O_APPEND, O_APPEND, O_APPEND, },
2413 { TARGET_O_NONBLOCK, TARGET_O_NONBLOCK, O_NONBLOCK, O_NONBLOCK, },
2414 { TARGET_O_SYNC, TARGET_O_SYNC, O_SYNC, O_SYNC, },
2415 { TARGET_FASYNC, TARGET_FASYNC, FASYNC, FASYNC, },
2416 { TARGET_O_DIRECTORY, TARGET_O_DIRECTORY, O_DIRECTORY, O_DIRECTORY, },
2417 { TARGET_O_NOFOLLOW, TARGET_O_NOFOLLOW, O_NOFOLLOW, O_NOFOLLOW, },
2418 { TARGET_O_LARGEFILE, TARGET_O_LARGEFILE, O_LARGEFILE, O_LARGEFILE, },
bellard121061d2004-02-22 11:56:01 +00002419#if defined(O_DIRECT)
bellardffa65c32004-01-04 23:57:22 +00002420 { TARGET_O_DIRECT, TARGET_O_DIRECT, O_DIRECT, O_DIRECT, },
bellard121061d2004-02-22 11:56:01 +00002421#endif
bellardffa65c32004-01-04 23:57:22 +00002422 { 0, 0, 0, 0 }
2423};
2424
bellard2ab83ea2003-06-15 19:56:46 +00002425#if defined(TARGET_I386)
bellard6dbad632003-03-16 18:05:05 +00002426
2427/* NOTE: there is really one LDT for all the threads */
2428uint8_t *ldt_table;
2429
bellard03acab62007-11-11 14:57:14 +00002430static abi_long read_ldt(abi_ulong ptr, unsigned long bytecount)
bellard6dbad632003-03-16 18:05:05 +00002431{
2432 int size;
pbrook53a59602006-03-25 19:31:22 +00002433 void *p;
bellard6dbad632003-03-16 18:05:05 +00002434
2435 if (!ldt_table)
2436 return 0;
2437 size = TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE;
2438 if (size > bytecount)
2439 size = bytecount;
bellard579a97f2007-11-11 14:26:47 +00002440 p = lock_user(VERIFY_WRITE, ptr, size, 0);
2441 if (!p)
bellard03acab62007-11-11 14:57:14 +00002442 return -TARGET_EFAULT;
bellard579a97f2007-11-11 14:26:47 +00002443 /* ??? Should this by byteswapped? */
pbrook53a59602006-03-25 19:31:22 +00002444 memcpy(p, ldt_table, size);
2445 unlock_user(p, ptr, size);
bellard6dbad632003-03-16 18:05:05 +00002446 return size;
2447}
2448
2449/* XXX: add locking support */
bellard03acab62007-11-11 14:57:14 +00002450static abi_long write_ldt(CPUX86State *env,
2451 abi_ulong ptr, unsigned long bytecount, int oldmode)
bellard6dbad632003-03-16 18:05:05 +00002452{
2453 struct target_modify_ldt_ldt_s ldt_info;
pbrook53a59602006-03-25 19:31:22 +00002454 struct target_modify_ldt_ldt_s *target_ldt_info;
bellard6dbad632003-03-16 18:05:05 +00002455 int seg_32bit, contents, read_exec_only, limit_in_pages;
bellard8d18e892007-11-14 15:18:40 +00002456 int seg_not_present, useable, lm;
bellard6dbad632003-03-16 18:05:05 +00002457 uint32_t *lp, entry_1, entry_2;
2458
2459 if (bytecount != sizeof(ldt_info))
bellard03acab62007-11-11 14:57:14 +00002460 return -TARGET_EINVAL;
bellard579a97f2007-11-11 14:26:47 +00002461 if (!lock_user_struct(VERIFY_READ, target_ldt_info, ptr, 1))
bellard03acab62007-11-11 14:57:14 +00002462 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00002463 ldt_info.entry_number = tswap32(target_ldt_info->entry_number);
2464 ldt_info.base_addr = tswapl(target_ldt_info->base_addr);
2465 ldt_info.limit = tswap32(target_ldt_info->limit);
2466 ldt_info.flags = tswap32(target_ldt_info->flags);
2467 unlock_user_struct(target_ldt_info, ptr, 0);
ths3b46e622007-09-17 08:09:54 +00002468
bellard6dbad632003-03-16 18:05:05 +00002469 if (ldt_info.entry_number >= TARGET_LDT_ENTRIES)
bellard03acab62007-11-11 14:57:14 +00002470 return -TARGET_EINVAL;
bellard6dbad632003-03-16 18:05:05 +00002471 seg_32bit = ldt_info.flags & 1;
2472 contents = (ldt_info.flags >> 1) & 3;
2473 read_exec_only = (ldt_info.flags >> 3) & 1;
2474 limit_in_pages = (ldt_info.flags >> 4) & 1;
2475 seg_not_present = (ldt_info.flags >> 5) & 1;
2476 useable = (ldt_info.flags >> 6) & 1;
bellard8d18e892007-11-14 15:18:40 +00002477#ifdef TARGET_ABI32
2478 lm = 0;
2479#else
2480 lm = (ldt_info.flags >> 7) & 1;
2481#endif
bellard6dbad632003-03-16 18:05:05 +00002482 if (contents == 3) {
2483 if (oldmode)
bellard03acab62007-11-11 14:57:14 +00002484 return -TARGET_EINVAL;
bellard6dbad632003-03-16 18:05:05 +00002485 if (seg_not_present == 0)
bellard03acab62007-11-11 14:57:14 +00002486 return -TARGET_EINVAL;
bellard6dbad632003-03-16 18:05:05 +00002487 }
2488 /* allocate the LDT */
2489 if (!ldt_table) {
2490 ldt_table = malloc(TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE);
2491 if (!ldt_table)
bellard03acab62007-11-11 14:57:14 +00002492 return -TARGET_ENOMEM;
bellard6dbad632003-03-16 18:05:05 +00002493 memset(ldt_table, 0, TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE);
bellardeeeac3f2007-11-11 19:34:32 +00002494 env->ldt.base = h2g((unsigned long)ldt_table);
bellard6dbad632003-03-16 18:05:05 +00002495 env->ldt.limit = 0xffff;
2496 }
2497
2498 /* NOTE: same code as Linux kernel */
2499 /* Allow LDTs to be cleared by the user. */
2500 if (ldt_info.base_addr == 0 && ldt_info.limit == 0) {
2501 if (oldmode ||
2502 (contents == 0 &&
2503 read_exec_only == 1 &&
2504 seg_32bit == 0 &&
2505 limit_in_pages == 0 &&
2506 seg_not_present == 1 &&
2507 useable == 0 )) {
2508 entry_1 = 0;
2509 entry_2 = 0;
2510 goto install;
2511 }
2512 }
ths3b46e622007-09-17 08:09:54 +00002513
bellard6dbad632003-03-16 18:05:05 +00002514 entry_1 = ((ldt_info.base_addr & 0x0000ffff) << 16) |
2515 (ldt_info.limit & 0x0ffff);
2516 entry_2 = (ldt_info.base_addr & 0xff000000) |
2517 ((ldt_info.base_addr & 0x00ff0000) >> 16) |
2518 (ldt_info.limit & 0xf0000) |
2519 ((read_exec_only ^ 1) << 9) |
2520 (contents << 10) |
2521 ((seg_not_present ^ 1) << 15) |
2522 (seg_32bit << 22) |
2523 (limit_in_pages << 23) |
bellard8d18e892007-11-14 15:18:40 +00002524 (lm << 21) |
bellard6dbad632003-03-16 18:05:05 +00002525 0x7000;
2526 if (!oldmode)
2527 entry_2 |= (useable << 20);
bellard14ae3ba2003-05-27 23:25:06 +00002528
bellard6dbad632003-03-16 18:05:05 +00002529 /* Install the new entry ... */
2530install:
2531 lp = (uint32_t *)(ldt_table + (ldt_info.entry_number << 3));
2532 lp[0] = tswap32(entry_1);
2533 lp[1] = tswap32(entry_2);
2534 return 0;
2535}
2536
2537/* specific and weird i386 syscalls */
blueswir18fcd3692008-08-17 20:26:25 +00002538static abi_long do_modify_ldt(CPUX86State *env, int func, abi_ulong ptr,
2539 unsigned long bytecount)
bellard6dbad632003-03-16 18:05:05 +00002540{
bellard03acab62007-11-11 14:57:14 +00002541 abi_long ret;
ths3b46e622007-09-17 08:09:54 +00002542
bellard6dbad632003-03-16 18:05:05 +00002543 switch (func) {
2544 case 0:
2545 ret = read_ldt(ptr, bytecount);
2546 break;
2547 case 1:
2548 ret = write_ldt(env, ptr, bytecount, 1);
2549 break;
2550 case 0x11:
2551 ret = write_ldt(env, ptr, bytecount, 0);
2552 break;
bellard03acab62007-11-11 14:57:14 +00002553 default:
2554 ret = -TARGET_ENOSYS;
2555 break;
bellard6dbad632003-03-16 18:05:05 +00002556 }
2557 return ret;
2558}
bellard1b6b0292003-03-22 17:31:38 +00002559
blueswir14583f582008-08-24 10:35:55 +00002560#if defined(TARGET_I386) && defined(TARGET_ABI32)
blueswir18fcd3692008-08-17 20:26:25 +00002561static abi_long do_set_thread_area(CPUX86State *env, abi_ulong ptr)
bellard8d18e892007-11-14 15:18:40 +00002562{
2563 uint64_t *gdt_table = g2h(env->gdt.base);
2564 struct target_modify_ldt_ldt_s ldt_info;
2565 struct target_modify_ldt_ldt_s *target_ldt_info;
2566 int seg_32bit, contents, read_exec_only, limit_in_pages;
2567 int seg_not_present, useable, lm;
2568 uint32_t *lp, entry_1, entry_2;
2569 int i;
2570
2571 lock_user_struct(VERIFY_WRITE, target_ldt_info, ptr, 1);
2572 if (!target_ldt_info)
2573 return -TARGET_EFAULT;
2574 ldt_info.entry_number = tswap32(target_ldt_info->entry_number);
2575 ldt_info.base_addr = tswapl(target_ldt_info->base_addr);
2576 ldt_info.limit = tswap32(target_ldt_info->limit);
2577 ldt_info.flags = tswap32(target_ldt_info->flags);
2578 if (ldt_info.entry_number == -1) {
2579 for (i=TARGET_GDT_ENTRY_TLS_MIN; i<=TARGET_GDT_ENTRY_TLS_MAX; i++) {
2580 if (gdt_table[i] == 0) {
2581 ldt_info.entry_number = i;
2582 target_ldt_info->entry_number = tswap32(i);
2583 break;
2584 }
2585 }
2586 }
2587 unlock_user_struct(target_ldt_info, ptr, 1);
2588
2589 if (ldt_info.entry_number < TARGET_GDT_ENTRY_TLS_MIN ||
2590 ldt_info.entry_number > TARGET_GDT_ENTRY_TLS_MAX)
2591 return -TARGET_EINVAL;
2592 seg_32bit = ldt_info.flags & 1;
2593 contents = (ldt_info.flags >> 1) & 3;
2594 read_exec_only = (ldt_info.flags >> 3) & 1;
2595 limit_in_pages = (ldt_info.flags >> 4) & 1;
2596 seg_not_present = (ldt_info.flags >> 5) & 1;
2597 useable = (ldt_info.flags >> 6) & 1;
2598#ifdef TARGET_ABI32
2599 lm = 0;
2600#else
2601 lm = (ldt_info.flags >> 7) & 1;
2602#endif
2603
2604 if (contents == 3) {
2605 if (seg_not_present == 0)
2606 return -TARGET_EINVAL;
2607 }
2608
2609 /* NOTE: same code as Linux kernel */
2610 /* Allow LDTs to be cleared by the user. */
2611 if (ldt_info.base_addr == 0 && ldt_info.limit == 0) {
2612 if ((contents == 0 &&
2613 read_exec_only == 1 &&
2614 seg_32bit == 0 &&
2615 limit_in_pages == 0 &&
2616 seg_not_present == 1 &&
2617 useable == 0 )) {
2618 entry_1 = 0;
2619 entry_2 = 0;
2620 goto install;
2621 }
2622 }
2623
2624 entry_1 = ((ldt_info.base_addr & 0x0000ffff) << 16) |
2625 (ldt_info.limit & 0x0ffff);
2626 entry_2 = (ldt_info.base_addr & 0xff000000) |
2627 ((ldt_info.base_addr & 0x00ff0000) >> 16) |
2628 (ldt_info.limit & 0xf0000) |
2629 ((read_exec_only ^ 1) << 9) |
2630 (contents << 10) |
2631 ((seg_not_present ^ 1) << 15) |
2632 (seg_32bit << 22) |
2633 (limit_in_pages << 23) |
2634 (useable << 20) |
2635 (lm << 21) |
2636 0x7000;
2637
2638 /* Install the new entry ... */
2639install:
2640 lp = (uint32_t *)(gdt_table + ldt_info.entry_number);
2641 lp[0] = tswap32(entry_1);
2642 lp[1] = tswap32(entry_2);
2643 return 0;
2644}
2645
blueswir18fcd3692008-08-17 20:26:25 +00002646static abi_long do_get_thread_area(CPUX86State *env, abi_ulong ptr)
bellard8d18e892007-11-14 15:18:40 +00002647{
2648 struct target_modify_ldt_ldt_s *target_ldt_info;
2649 uint64_t *gdt_table = g2h(env->gdt.base);
2650 uint32_t base_addr, limit, flags;
2651 int seg_32bit, contents, read_exec_only, limit_in_pages, idx;
2652 int seg_not_present, useable, lm;
2653 uint32_t *lp, entry_1, entry_2;
2654
2655 lock_user_struct(VERIFY_WRITE, target_ldt_info, ptr, 1);
2656 if (!target_ldt_info)
2657 return -TARGET_EFAULT;
2658 idx = tswap32(target_ldt_info->entry_number);
2659 if (idx < TARGET_GDT_ENTRY_TLS_MIN ||
2660 idx > TARGET_GDT_ENTRY_TLS_MAX) {
2661 unlock_user_struct(target_ldt_info, ptr, 1);
2662 return -TARGET_EINVAL;
2663 }
2664 lp = (uint32_t *)(gdt_table + idx);
2665 entry_1 = tswap32(lp[0]);
2666 entry_2 = tswap32(lp[1]);
2667
2668 read_exec_only = ((entry_2 >> 9) & 1) ^ 1;
2669 contents = (entry_2 >> 10) & 3;
2670 seg_not_present = ((entry_2 >> 15) & 1) ^ 1;
2671 seg_32bit = (entry_2 >> 22) & 1;
2672 limit_in_pages = (entry_2 >> 23) & 1;
2673 useable = (entry_2 >> 20) & 1;
2674#ifdef TARGET_ABI32
2675 lm = 0;
2676#else
2677 lm = (entry_2 >> 21) & 1;
2678#endif
2679 flags = (seg_32bit << 0) | (contents << 1) |
2680 (read_exec_only << 3) | (limit_in_pages << 4) |
2681 (seg_not_present << 5) | (useable << 6) | (lm << 7);
2682 limit = (entry_1 & 0xffff) | (entry_2 & 0xf0000);
2683 base_addr = (entry_1 >> 16) |
2684 (entry_2 & 0xff000000) |
2685 ((entry_2 & 0xff) << 16);
2686 target_ldt_info->base_addr = tswapl(base_addr);
2687 target_ldt_info->limit = tswap32(limit);
2688 target_ldt_info->flags = tswap32(flags);
2689 unlock_user_struct(target_ldt_info, ptr, 1);
2690 return 0;
2691}
blueswir14583f582008-08-24 10:35:55 +00002692#endif /* TARGET_I386 && TARGET_ABI32 */
bellard8d18e892007-11-14 15:18:40 +00002693
bellardd2fd1af2007-11-14 18:08:56 +00002694#ifndef TARGET_ABI32
blueswir18fcd3692008-08-17 20:26:25 +00002695static abi_long do_arch_prctl(CPUX86State *env, int code, abi_ulong addr)
bellardd2fd1af2007-11-14 18:08:56 +00002696{
2697 abi_long ret;
2698 abi_ulong val;
2699 int idx;
2700
2701 switch(code) {
2702 case TARGET_ARCH_SET_GS:
2703 case TARGET_ARCH_SET_FS:
2704 if (code == TARGET_ARCH_SET_GS)
2705 idx = R_GS;
2706 else
2707 idx = R_FS;
2708 cpu_x86_load_seg(env, idx, 0);
2709 env->segs[idx].base = addr;
2710 break;
2711 case TARGET_ARCH_GET_GS:
2712 case TARGET_ARCH_GET_FS:
2713 if (code == TARGET_ARCH_GET_GS)
2714 idx = R_GS;
2715 else
2716 idx = R_FS;
2717 val = env->segs[idx].base;
2718 if (put_user(val, addr, abi_ulong))
2719 return -TARGET_EFAULT;
2720 break;
2721 default:
2722 ret = -TARGET_EINVAL;
2723 break;
2724 }
2725 return 0;
2726}
2727#endif
2728
bellard2ab83ea2003-06-15 19:56:46 +00002729#endif /* defined(TARGET_I386) */
2730
pbrookd865bab2008-06-07 22:12:17 +00002731#if defined(USE_NPTL)
2732
2733#define NEW_STACK_SIZE PTHREAD_STACK_MIN
2734
2735static pthread_mutex_t clone_lock = PTHREAD_MUTEX_INITIALIZER;
2736typedef struct {
2737 CPUState *env;
2738 pthread_mutex_t mutex;
2739 pthread_cond_t cond;
2740 pthread_t thread;
2741 uint32_t tid;
2742 abi_ulong child_tidptr;
2743 abi_ulong parent_tidptr;
2744 sigset_t sigmask;
2745} new_thread_info;
2746
2747static void *clone_func(void *arg)
2748{
2749 new_thread_info *info = arg;
2750 CPUState *env;
2751
2752 env = info->env;
2753 thread_env = env;
2754 info->tid = gettid();
2755 if (info->child_tidptr)
2756 put_user_u32(info->tid, info->child_tidptr);
2757 if (info->parent_tidptr)
2758 put_user_u32(info->tid, info->parent_tidptr);
2759 /* Enable signals. */
2760 sigprocmask(SIG_SETMASK, &info->sigmask, NULL);
2761 /* Signal to the parent that we're ready. */
2762 pthread_mutex_lock(&info->mutex);
2763 pthread_cond_broadcast(&info->cond);
2764 pthread_mutex_unlock(&info->mutex);
2765 /* Wait until the parent has finshed initializing the tls state. */
2766 pthread_mutex_lock(&clone_lock);
2767 pthread_mutex_unlock(&clone_lock);
2768 cpu_loop(env);
2769 /* never exits */
2770 return NULL;
2771}
2772#else
bellard1b6b0292003-03-22 17:31:38 +00002773/* this stack is the equivalent of the kernel stack associated with a
2774 thread/process */
2775#define NEW_STACK_SIZE 8192
2776
2777static int clone_func(void *arg)
2778{
bellard2ab83ea2003-06-15 19:56:46 +00002779 CPUState *env = arg;
bellard1b6b0292003-03-22 17:31:38 +00002780 cpu_loop(env);
2781 /* never exits */
2782 return 0;
2783}
pbrookd865bab2008-06-07 22:12:17 +00002784#endif
bellard1b6b0292003-03-22 17:31:38 +00002785
ths0da46a62007-10-20 20:23:07 +00002786/* do_fork() Must return host values and target errnos (unlike most
2787 do_*() functions). */
pbrookd865bab2008-06-07 22:12:17 +00002788static int do_fork(CPUState *env, unsigned int flags, abi_ulong newsp,
2789 abi_ulong parent_tidptr, target_ulong newtls,
2790 abi_ulong child_tidptr)
bellard1b6b0292003-03-22 17:31:38 +00002791{
2792 int ret;
bellard5cd43932003-03-29 16:54:36 +00002793 TaskState *ts;
bellard1b6b0292003-03-22 17:31:38 +00002794 uint8_t *new_stack;
bellard2ab83ea2003-06-15 19:56:46 +00002795 CPUState *new_env;
pbrookd865bab2008-06-07 22:12:17 +00002796#if defined(USE_NPTL)
2797 unsigned int nptl_flags;
2798 sigset_t sigmask;
2799#endif
ths3b46e622007-09-17 08:09:54 +00002800
bellard1b6b0292003-03-22 17:31:38 +00002801 if (flags & CLONE_VM) {
pbrookbd0c5662008-05-29 14:34:11 +00002802#if defined(USE_NPTL)
pbrookd865bab2008-06-07 22:12:17 +00002803 new_thread_info info;
2804 pthread_attr_t attr;
pbrookbd0c5662008-05-29 14:34:11 +00002805#endif
pbrookc3a92832008-06-09 14:02:50 +00002806 ts = qemu_mallocz(sizeof(TaskState) + NEW_STACK_SIZE);
pbrook624f7972008-05-31 16:11:38 +00002807 init_task_state(ts);
bellard5cd43932003-03-29 16:54:36 +00002808 new_stack = ts->stack;
bellard1b6b0292003-03-22 17:31:38 +00002809 /* we create a new CPU instance. */
thsc5be9f02007-02-28 20:20:53 +00002810 new_env = cpu_copy(env);
pbrook6e68e072008-05-30 17:22:15 +00002811 /* Init regs that differ from the parent. */
2812 cpu_clone_regs(new_env, newsp);
bellard5cd43932003-03-29 16:54:36 +00002813 new_env->opaque = ts;
pbrookd865bab2008-06-07 22:12:17 +00002814#if defined(USE_NPTL)
2815 nptl_flags = flags;
2816 flags &= ~CLONE_NPTL_FLAGS2;
2817
2818 /* TODO: Implement CLONE_CHILD_CLEARTID. */
2819 if (nptl_flags & CLONE_SETTLS)
2820 cpu_set_tls (new_env, newtls);
2821
2822 /* Grab a mutex so that thread setup appears atomic. */
2823 pthread_mutex_lock(&clone_lock);
2824
2825 memset(&info, 0, sizeof(info));
2826 pthread_mutex_init(&info.mutex, NULL);
2827 pthread_mutex_lock(&info.mutex);
2828 pthread_cond_init(&info.cond, NULL);
2829 info.env = new_env;
2830 if (nptl_flags & CLONE_CHILD_SETTID)
2831 info.child_tidptr = child_tidptr;
2832 if (nptl_flags & CLONE_PARENT_SETTID)
2833 info.parent_tidptr = parent_tidptr;
2834
2835 ret = pthread_attr_init(&attr);
2836 ret = pthread_attr_setstack(&attr, new_stack, NEW_STACK_SIZE);
2837 /* It is not safe to deliver signals until the child has finished
2838 initializing, so temporarily block all signals. */
2839 sigfillset(&sigmask);
2840 sigprocmask(SIG_BLOCK, &sigmask, &info.sigmask);
2841
2842 ret = pthread_create(&info.thread, &attr, clone_func, &info);
2843
2844 sigprocmask(SIG_SETMASK, &info.sigmask, NULL);
2845 pthread_attr_destroy(&attr);
2846 if (ret == 0) {
2847 /* Wait for the child to initialize. */
2848 pthread_cond_wait(&info.cond, &info.mutex);
2849 ret = info.tid;
2850 if (flags & CLONE_PARENT_SETTID)
2851 put_user_u32(ret, parent_tidptr);
2852 } else {
2853 ret = -1;
2854 }
2855 pthread_mutex_unlock(&info.mutex);
2856 pthread_cond_destroy(&info.cond);
2857 pthread_mutex_destroy(&info.mutex);
2858 pthread_mutex_unlock(&clone_lock);
2859#else
2860 if (flags & CLONE_NPTL_FLAGS2)
2861 return -EINVAL;
2862 /* This is probably going to die very quickly, but do it anyway. */
bellard27725c12003-04-29 21:08:18 +00002863#ifdef __ia64__
bellardfd4a43e2006-04-24 20:32:17 +00002864 ret = __clone2(clone_func, new_stack + NEW_STACK_SIZE, flags, new_env);
bellard27725c12003-04-29 21:08:18 +00002865#else
2866 ret = clone(clone_func, new_stack + NEW_STACK_SIZE, flags, new_env);
2867#endif
pbrookd865bab2008-06-07 22:12:17 +00002868#endif
bellard1b6b0292003-03-22 17:31:38 +00002869 } else {
2870 /* if no CLONE_VM, we consider it is a fork */
pbrookd865bab2008-06-07 22:12:17 +00002871 if ((flags & ~(CSIGNAL | CLONE_NPTL_FLAGS2)) != 0)
bellard1b6b0292003-03-22 17:31:38 +00002872 return -EINVAL;
pbrookd865bab2008-06-07 22:12:17 +00002873 fork_start();
bellard1b6b0292003-03-22 17:31:38 +00002874 ret = fork();
pbrookd865bab2008-06-07 22:12:17 +00002875#if defined(USE_NPTL)
2876 /* There is a race condition here. The parent process could
2877 theoretically read the TID in the child process before the child
2878 tid is set. This would require using either ptrace
2879 (not implemented) or having *_tidptr to point at a shared memory
2880 mapping. We can't repeat the spinlock hack used above because
2881 the child process gets its own copy of the lock. */
2882 if (ret == 0) {
2883 cpu_clone_regs(env, newsp);
2884 fork_end(1);
2885 /* Child Process. */
2886 if (flags & CLONE_CHILD_SETTID)
2887 put_user_u32(gettid(), child_tidptr);
2888 if (flags & CLONE_PARENT_SETTID)
2889 put_user_u32(gettid(), parent_tidptr);
2890 ts = (TaskState *)env->opaque;
2891 if (flags & CLONE_SETTLS)
2892 cpu_set_tls (env, newtls);
2893 /* TODO: Implement CLONE_CHILD_CLEARTID. */
2894 } else {
2895 fork_end(0);
2896 }
2897#else
pbrook6e68e072008-05-30 17:22:15 +00002898 if (ret == 0) {
2899 cpu_clone_regs(env, newsp);
2900 }
pbrookd865bab2008-06-07 22:12:17 +00002901#endif
bellard1b6b0292003-03-22 17:31:38 +00002902 }
2903 return ret;
2904}
2905
blueswir1992f48a2007-10-14 16:27:31 +00002906static abi_long do_fcntl(int fd, int cmd, abi_ulong arg)
bellard7775e9e2003-05-14 22:46:48 +00002907{
2908 struct flock fl;
pbrook53a59602006-03-25 19:31:22 +00002909 struct target_flock *target_fl;
ths43f238d2007-01-05 20:55:49 +00002910 struct flock64 fl64;
2911 struct target_flock64 *target_fl64;
blueswir1992f48a2007-10-14 16:27:31 +00002912 abi_long ret;
pbrook53a59602006-03-25 19:31:22 +00002913
bellard7775e9e2003-05-14 22:46:48 +00002914 switch(cmd) {
2915 case TARGET_F_GETLK:
bellard579a97f2007-11-11 14:26:47 +00002916 if (!lock_user_struct(VERIFY_READ, target_fl, arg, 1))
2917 return -TARGET_EFAULT;
ths58134272007-03-31 18:59:32 +00002918 fl.l_type = tswap16(target_fl->l_type);
2919 fl.l_whence = tswap16(target_fl->l_whence);
2920 fl.l_start = tswapl(target_fl->l_start);
2921 fl.l_len = tswapl(target_fl->l_len);
2922 fl.l_pid = tswapl(target_fl->l_pid);
2923 unlock_user_struct(target_fl, arg, 0);
bellard9ee1fa22007-11-11 15:11:19 +00002924 ret = get_errno(fcntl(fd, cmd, &fl));
bellard7775e9e2003-05-14 22:46:48 +00002925 if (ret == 0) {
bellard579a97f2007-11-11 14:26:47 +00002926 if (!lock_user_struct(VERIFY_WRITE, target_fl, arg, 0))
2927 return -TARGET_EFAULT;
bellard7775e9e2003-05-14 22:46:48 +00002928 target_fl->l_type = tswap16(fl.l_type);
2929 target_fl->l_whence = tswap16(fl.l_whence);
2930 target_fl->l_start = tswapl(fl.l_start);
2931 target_fl->l_len = tswapl(fl.l_len);
2932 target_fl->l_pid = tswapl(fl.l_pid);
pbrook53a59602006-03-25 19:31:22 +00002933 unlock_user_struct(target_fl, arg, 1);
bellard7775e9e2003-05-14 22:46:48 +00002934 }
2935 break;
ths3b46e622007-09-17 08:09:54 +00002936
bellard7775e9e2003-05-14 22:46:48 +00002937 case TARGET_F_SETLK:
2938 case TARGET_F_SETLKW:
bellard579a97f2007-11-11 14:26:47 +00002939 if (!lock_user_struct(VERIFY_READ, target_fl, arg, 1))
2940 return -TARGET_EFAULT;
bellard7775e9e2003-05-14 22:46:48 +00002941 fl.l_type = tswap16(target_fl->l_type);
2942 fl.l_whence = tswap16(target_fl->l_whence);
2943 fl.l_start = tswapl(target_fl->l_start);
2944 fl.l_len = tswapl(target_fl->l_len);
2945 fl.l_pid = tswapl(target_fl->l_pid);
pbrook53a59602006-03-25 19:31:22 +00002946 unlock_user_struct(target_fl, arg, 0);
bellard9ee1fa22007-11-11 15:11:19 +00002947 ret = get_errno(fcntl(fd, cmd, &fl));
bellard7775e9e2003-05-14 22:46:48 +00002948 break;
ths3b46e622007-09-17 08:09:54 +00002949
bellard7775e9e2003-05-14 22:46:48 +00002950 case TARGET_F_GETLK64:
bellard579a97f2007-11-11 14:26:47 +00002951 if (!lock_user_struct(VERIFY_READ, target_fl64, arg, 1))
2952 return -TARGET_EFAULT;
ths58134272007-03-31 18:59:32 +00002953 fl64.l_type = tswap16(target_fl64->l_type) >> 1;
2954 fl64.l_whence = tswap16(target_fl64->l_whence);
2955 fl64.l_start = tswapl(target_fl64->l_start);
2956 fl64.l_len = tswapl(target_fl64->l_len);
2957 fl64.l_pid = tswap16(target_fl64->l_pid);
2958 unlock_user_struct(target_fl64, arg, 0);
bellard9ee1fa22007-11-11 15:11:19 +00002959 ret = get_errno(fcntl(fd, cmd >> 1, &fl64));
ths43f238d2007-01-05 20:55:49 +00002960 if (ret == 0) {
bellard579a97f2007-11-11 14:26:47 +00002961 if (!lock_user_struct(VERIFY_WRITE, target_fl64, arg, 0))
2962 return -TARGET_EFAULT;
ths43f238d2007-01-05 20:55:49 +00002963 target_fl64->l_type = tswap16(fl64.l_type) >> 1;
2964 target_fl64->l_whence = tswap16(fl64.l_whence);
2965 target_fl64->l_start = tswapl(fl64.l_start);
2966 target_fl64->l_len = tswapl(fl64.l_len);
2967 target_fl64->l_pid = tswapl(fl64.l_pid);
2968 unlock_user_struct(target_fl64, arg, 1);
2969 }
bellard9ee1fa22007-11-11 15:11:19 +00002970 break;
bellard7775e9e2003-05-14 22:46:48 +00002971 case TARGET_F_SETLK64:
2972 case TARGET_F_SETLKW64:
bellard579a97f2007-11-11 14:26:47 +00002973 if (!lock_user_struct(VERIFY_READ, target_fl64, arg, 1))
2974 return -TARGET_EFAULT;
ths43f238d2007-01-05 20:55:49 +00002975 fl64.l_type = tswap16(target_fl64->l_type) >> 1;
2976 fl64.l_whence = tswap16(target_fl64->l_whence);
2977 fl64.l_start = tswapl(target_fl64->l_start);
2978 fl64.l_len = tswapl(target_fl64->l_len);
2979 fl64.l_pid = tswap16(target_fl64->l_pid);
2980 unlock_user_struct(target_fl64, arg, 0);
bellard9ee1fa22007-11-11 15:11:19 +00002981 ret = get_errno(fcntl(fd, cmd >> 1, &fl64));
bellard7775e9e2003-05-14 22:46:48 +00002982 break;
2983
bellardffa65c32004-01-04 23:57:22 +00002984 case F_GETFL:
bellard9ee1fa22007-11-11 15:11:19 +00002985 ret = get_errno(fcntl(fd, cmd, arg));
2986 if (ret >= 0) {
2987 ret = host_to_target_bitmask(ret, fcntl_flags_tbl);
2988 }
bellardffa65c32004-01-04 23:57:22 +00002989 break;
2990
2991 case F_SETFL:
bellard9ee1fa22007-11-11 15:11:19 +00002992 ret = get_errno(fcntl(fd, cmd, target_to_host_bitmask(arg, fcntl_flags_tbl)));
bellardffa65c32004-01-04 23:57:22 +00002993 break;
2994
bellard7775e9e2003-05-14 22:46:48 +00002995 default:
bellard9ee1fa22007-11-11 15:11:19 +00002996 ret = get_errno(fcntl(fd, cmd, arg));
bellard7775e9e2003-05-14 22:46:48 +00002997 break;
2998 }
2999 return ret;
3000}
3001
bellard67867302003-11-23 17:05:30 +00003002#ifdef USE_UID16
bellard7775e9e2003-05-14 22:46:48 +00003003
bellard67867302003-11-23 17:05:30 +00003004static inline int high2lowuid(int uid)
3005{
3006 if (uid > 65535)
3007 return 65534;
3008 else
3009 return uid;
3010}
3011
3012static inline int high2lowgid(int gid)
3013{
3014 if (gid > 65535)
3015 return 65534;
3016 else
3017 return gid;
3018}
3019
3020static inline int low2highuid(int uid)
3021{
3022 if ((int16_t)uid == -1)
3023 return -1;
3024 else
3025 return uid;
3026}
3027
3028static inline int low2highgid(int gid)
3029{
3030 if ((int16_t)gid == -1)
3031 return -1;
3032 else
3033 return gid;
3034}
3035
3036#endif /* USE_UID16 */
bellard1b6b0292003-03-22 17:31:38 +00003037
bellard31e31b82003-02-18 22:55:36 +00003038void syscall_init(void)
3039{
bellard2ab83ea2003-06-15 19:56:46 +00003040 IOCTLEntry *ie;
3041 const argtype *arg_type;
3042 int size;
thsb92c47c2007-11-01 00:07:38 +00003043 int i;
bellard2ab83ea2003-06-15 19:56:46 +00003044
ths5fafdf22007-09-16 21:08:06 +00003045#define STRUCT(name, list...) thunk_register_struct(STRUCT_ ## name, #name, struct_ ## name ## _def);
3046#define STRUCT_SPECIAL(name) thunk_register_struct_direct(STRUCT_ ## name, #name, &struct_ ## name ## _def);
bellard31e31b82003-02-18 22:55:36 +00003047#include "syscall_types.h"
3048#undef STRUCT
3049#undef STRUCT_SPECIAL
bellard2ab83ea2003-06-15 19:56:46 +00003050
3051 /* we patch the ioctl size if necessary. We rely on the fact that
3052 no ioctl has all the bits at '1' in the size field */
3053 ie = ioctl_entries;
3054 while (ie->target_cmd != 0) {
3055 if (((ie->target_cmd >> TARGET_IOC_SIZESHIFT) & TARGET_IOC_SIZEMASK) ==
3056 TARGET_IOC_SIZEMASK) {
3057 arg_type = ie->arg_type;
3058 if (arg_type[0] != TYPE_PTR) {
ths5fafdf22007-09-16 21:08:06 +00003059 fprintf(stderr, "cannot patch size for ioctl 0x%x\n",
bellard2ab83ea2003-06-15 19:56:46 +00003060 ie->target_cmd);
3061 exit(1);
3062 }
3063 arg_type++;
3064 size = thunk_type_size(arg_type, 0);
ths5fafdf22007-09-16 21:08:06 +00003065 ie->target_cmd = (ie->target_cmd &
bellard2ab83ea2003-06-15 19:56:46 +00003066 ~(TARGET_IOC_SIZEMASK << TARGET_IOC_SIZESHIFT)) |
3067 (size << TARGET_IOC_SIZESHIFT);
3068 }
thsb92c47c2007-11-01 00:07:38 +00003069
3070 /* Build target_to_host_errno_table[] table from
3071 * host_to_target_errno_table[]. */
3072 for (i=0; i < ERRNO_TABLE_SIZE; i++)
3073 target_to_host_errno_table[host_to_target_errno_table[i]] = i;
3074
bellard2ab83ea2003-06-15 19:56:46 +00003075 /* automatic consistency check if same arch */
bellardd2fd1af2007-11-14 18:08:56 +00003076#if defined(__i386__) && defined(TARGET_I386) && defined(TARGET_ABI32)
bellard2ab83ea2003-06-15 19:56:46 +00003077 if (ie->target_cmd != ie->host_cmd) {
ths5fafdf22007-09-16 21:08:06 +00003078 fprintf(stderr, "ERROR: ioctl: target=0x%x host=0x%x\n",
bellard2ab83ea2003-06-15 19:56:46 +00003079 ie->target_cmd, ie->host_cmd);
3080 }
3081#endif
3082 ie++;
3083 }
bellard31e31b82003-02-18 22:55:36 +00003084}
bellardc573ff62004-01-04 15:51:36 +00003085
blueswir1992f48a2007-10-14 16:27:31 +00003086#if TARGET_ABI_BITS == 32
pbrookce4defa2006-02-09 16:49:55 +00003087static inline uint64_t target_offset64(uint32_t word0, uint32_t word1)
3088{
thsaf325d32008-06-10 15:29:15 +00003089#ifdef TARGET_WORDS_BIGENDIAN
pbrookce4defa2006-02-09 16:49:55 +00003090 return ((uint64_t)word0 << 32) | word1;
3091#else
3092 return ((uint64_t)word1 << 32) | word0;
3093#endif
3094}
blueswir1992f48a2007-10-14 16:27:31 +00003095#else /* TARGET_ABI_BITS == 32 */
j_mayer32407102007-09-26 23:01:49 +00003096static inline uint64_t target_offset64(uint64_t word0, uint64_t word1)
3097{
3098 return word0;
3099}
blueswir1992f48a2007-10-14 16:27:31 +00003100#endif /* TARGET_ABI_BITS != 32 */
pbrookce4defa2006-02-09 16:49:55 +00003101
3102#ifdef TARGET_NR_truncate64
blueswir1992f48a2007-10-14 16:27:31 +00003103static inline abi_long target_truncate64(void *cpu_env, const char *arg1,
3104 abi_long arg2,
3105 abi_long arg3,
3106 abi_long arg4)
pbrookce4defa2006-02-09 16:49:55 +00003107{
3108#ifdef TARGET_ARM
3109 if (((CPUARMState *)cpu_env)->eabi)
3110 {
3111 arg2 = arg3;
3112 arg3 = arg4;
3113 }
3114#endif
3115 return get_errno(truncate64(arg1, target_offset64(arg2, arg3)));
3116}
3117#endif
3118
3119#ifdef TARGET_NR_ftruncate64
blueswir1992f48a2007-10-14 16:27:31 +00003120static inline abi_long target_ftruncate64(void *cpu_env, abi_long arg1,
3121 abi_long arg2,
3122 abi_long arg3,
3123 abi_long arg4)
pbrookce4defa2006-02-09 16:49:55 +00003124{
3125#ifdef TARGET_ARM
3126 if (((CPUARMState *)cpu_env)->eabi)
3127 {
3128 arg2 = arg3;
3129 arg3 = arg4;
3130 }
3131#endif
3132 return get_errno(ftruncate64(arg1, target_offset64(arg2, arg3)));
3133}
3134#endif
3135
bellard579a97f2007-11-11 14:26:47 +00003136static inline abi_long target_to_host_timespec(struct timespec *host_ts,
3137 abi_ulong target_addr)
pbrook53a59602006-03-25 19:31:22 +00003138{
3139 struct target_timespec *target_ts;
3140
bellard579a97f2007-11-11 14:26:47 +00003141 if (!lock_user_struct(VERIFY_READ, target_ts, target_addr, 1))
3142 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00003143 host_ts->tv_sec = tswapl(target_ts->tv_sec);
3144 host_ts->tv_nsec = tswapl(target_ts->tv_nsec);
3145 unlock_user_struct(target_ts, target_addr, 0);
bellardb255bfa2008-05-10 21:51:02 +00003146 return 0;
pbrook53a59602006-03-25 19:31:22 +00003147}
3148
bellard579a97f2007-11-11 14:26:47 +00003149static inline abi_long host_to_target_timespec(abi_ulong target_addr,
3150 struct timespec *host_ts)
pbrook53a59602006-03-25 19:31:22 +00003151{
3152 struct target_timespec *target_ts;
3153
bellard579a97f2007-11-11 14:26:47 +00003154 if (!lock_user_struct(VERIFY_WRITE, target_ts, target_addr, 0))
3155 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00003156 target_ts->tv_sec = tswapl(host_ts->tv_sec);
3157 target_ts->tv_nsec = tswapl(host_ts->tv_nsec);
3158 unlock_user_struct(target_ts, target_addr, 1);
bellardb255bfa2008-05-10 21:51:02 +00003159 return 0;
pbrook53a59602006-03-25 19:31:22 +00003160}
3161
balrog6a24a772008-09-20 02:23:36 +00003162#ifdef TARGET_NR_stat64
3163static inline abi_long host_to_target_stat64(void *cpu_env,
3164 abi_ulong target_addr,
3165 struct stat *host_st)
3166{
3167#ifdef TARGET_ARM
3168 if (((CPUARMState *)cpu_env)->eabi) {
3169 struct target_eabi_stat64 *target_st;
3170
3171 if (!lock_user_struct(VERIFY_WRITE, target_st, target_addr, 0))
3172 return -TARGET_EFAULT;
3173 memset(target_st, 0, sizeof(struct target_eabi_stat64));
3174 __put_user(host_st->st_dev, &target_st->st_dev);
3175 __put_user(host_st->st_ino, &target_st->st_ino);
3176#ifdef TARGET_STAT64_HAS_BROKEN_ST_INO
3177 __put_user(host_st->st_ino, &target_st->__st_ino);
3178#endif
3179 __put_user(host_st->st_mode, &target_st->st_mode);
3180 __put_user(host_st->st_nlink, &target_st->st_nlink);
3181 __put_user(host_st->st_uid, &target_st->st_uid);
3182 __put_user(host_st->st_gid, &target_st->st_gid);
3183 __put_user(host_st->st_rdev, &target_st->st_rdev);
3184 __put_user(host_st->st_size, &target_st->st_size);
3185 __put_user(host_st->st_blksize, &target_st->st_blksize);
3186 __put_user(host_st->st_blocks, &target_st->st_blocks);
3187 __put_user(host_st->st_atime, &target_st->target_st_atime);
3188 __put_user(host_st->st_mtime, &target_st->target_st_mtime);
3189 __put_user(host_st->st_ctime, &target_st->target_st_ctime);
3190 unlock_user_struct(target_st, target_addr, 1);
3191 } else
3192#endif
3193 {
3194 struct target_stat64 *target_st;
3195
3196 if (!lock_user_struct(VERIFY_WRITE, target_st, target_addr, 0))
3197 return -TARGET_EFAULT;
3198 memset(target_st, 0, sizeof(struct target_stat64));
3199 __put_user(host_st->st_dev, &target_st->st_dev);
3200 __put_user(host_st->st_ino, &target_st->st_ino);
3201#ifdef TARGET_STAT64_HAS_BROKEN_ST_INO
3202 __put_user(host_st->st_ino, &target_st->__st_ino);
3203#endif
3204 __put_user(host_st->st_mode, &target_st->st_mode);
3205 __put_user(host_st->st_nlink, &target_st->st_nlink);
3206 __put_user(host_st->st_uid, &target_st->st_uid);
3207 __put_user(host_st->st_gid, &target_st->st_gid);
3208 __put_user(host_st->st_rdev, &target_st->st_rdev);
3209 /* XXX: better use of kernel struct */
3210 __put_user(host_st->st_size, &target_st->st_size);
3211 __put_user(host_st->st_blksize, &target_st->st_blksize);
3212 __put_user(host_st->st_blocks, &target_st->st_blocks);
3213 __put_user(host_st->st_atime, &target_st->target_st_atime);
3214 __put_user(host_st->st_mtime, &target_st->target_st_mtime);
3215 __put_user(host_st->st_ctime, &target_st->target_st_ctime);
3216 unlock_user_struct(target_st, target_addr, 1);
3217 }
3218
3219 return 0;
3220}
3221#endif
3222
pbrookbd0c5662008-05-29 14:34:11 +00003223#if defined(USE_NPTL)
3224/* ??? Using host futex calls even when target atomic operations
3225 are not really atomic probably breaks things. However implementing
3226 futexes locally would make futexes shared between multiple processes
3227 tricky. However they're probably useless because guest atomic
3228 operations won't work either. */
blueswir18fcd3692008-08-17 20:26:25 +00003229static int do_futex(target_ulong uaddr, int op, int val, target_ulong timeout,
3230 target_ulong uaddr2, int val3)
pbrookbd0c5662008-05-29 14:34:11 +00003231{
3232 struct timespec ts, *pts;
3233
3234 /* ??? We assume FUTEX_* constants are the same on both host
3235 and target. */
3236 switch (op) {
3237 case FUTEX_WAIT:
3238 if (timeout) {
3239 pts = &ts;
3240 target_to_host_timespec(pts, timeout);
3241 } else {
3242 pts = NULL;
3243 }
3244 return get_errno(sys_futex(g2h(uaddr), FUTEX_WAIT, tswap32(val),
3245 pts, NULL, 0));
3246 case FUTEX_WAKE:
3247 return get_errno(sys_futex(g2h(uaddr), FUTEX_WAKE, val, NULL, NULL, 0));
3248 case FUTEX_FD:
3249 return get_errno(sys_futex(g2h(uaddr), FUTEX_FD, val, NULL, NULL, 0));
3250 case FUTEX_REQUEUE:
3251 return get_errno(sys_futex(g2h(uaddr), FUTEX_REQUEUE, val,
3252 NULL, g2h(uaddr2), 0));
3253 case FUTEX_CMP_REQUEUE:
3254 return get_errno(sys_futex(g2h(uaddr), FUTEX_CMP_REQUEUE, val,
3255 NULL, g2h(uaddr2), tswap32(val3)));
3256 default:
3257 return -TARGET_ENOSYS;
3258 }
3259}
3260#endif
3261
pbrooka745ec62008-05-06 15:36:17 +00003262int get_osversion(void)
3263{
3264 static int osversion;
3265 struct new_utsname buf;
3266 const char *s;
3267 int i, n, tmp;
3268 if (osversion)
3269 return osversion;
3270 if (qemu_uname_release && *qemu_uname_release) {
3271 s = qemu_uname_release;
3272 } else {
3273 if (sys_uname(&buf))
3274 return 0;
3275 s = buf.release;
3276 }
3277 tmp = 0;
3278 for (i = 0; i < 3; i++) {
3279 n = 0;
3280 while (*s >= '0' && *s <= '9') {
3281 n *= 10;
3282 n += *s - '0';
3283 s++;
3284 }
3285 tmp = (tmp << 8) + n;
3286 if (*s == '.')
3287 s++;
3288 }
3289 osversion = tmp;
3290 return osversion;
3291}
3292
ths0da46a62007-10-20 20:23:07 +00003293/* do_syscall() should always have a single exit point at the end so
3294 that actions, such as logging of syscall results, can be performed.
3295 All errnos that do_syscall() returns must be -TARGET_<errcode>. */
blueswir1992f48a2007-10-14 16:27:31 +00003296abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
3297 abi_long arg2, abi_long arg3, abi_long arg4,
3298 abi_long arg5, abi_long arg6)
bellard31e31b82003-02-18 22:55:36 +00003299{
blueswir1992f48a2007-10-14 16:27:31 +00003300 abi_long ret;
bellard31e31b82003-02-18 22:55:36 +00003301 struct stat st;
bellard56c8f682005-11-28 22:28:41 +00003302 struct statfs stfs;
pbrook53a59602006-03-25 19:31:22 +00003303 void *p;
ths3b46e622007-09-17 08:09:54 +00003304
bellard72f03902003-02-18 23:33:18 +00003305#ifdef DEBUG
bellardc573ff62004-01-04 15:51:36 +00003306 gemu_log("syscall %d", num);
bellard72f03902003-02-18 23:33:18 +00003307#endif
thsb92c47c2007-11-01 00:07:38 +00003308 if(do_strace)
3309 print_syscall(num, arg1, arg2, arg3, arg4, arg5, arg6);
3310
bellard31e31b82003-02-18 22:55:36 +00003311 switch(num) {
3312 case TARGET_NR_exit:
bellard7d132992003-03-06 23:23:54 +00003313#ifdef HAVE_GPROF
3314 _mcleanup();
3315#endif
bellarde9009672005-04-26 20:42:36 +00003316 gdb_exit(cpu_env, arg1);
bellard1b6b0292003-03-22 17:31:38 +00003317 /* XXX: should free thread stack and CPU env */
bellard31e31b82003-02-18 22:55:36 +00003318 _exit(arg1);
3319 ret = 0; /* avoid warning */
3320 break;
3321 case TARGET_NR_read:
bellard579a97f2007-11-11 14:26:47 +00003322 if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
3323 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003324 ret = get_errno(read(arg1, p, arg3));
3325 unlock_user(p, arg2, ret);
bellard31e31b82003-02-18 22:55:36 +00003326 break;
3327 case TARGET_NR_write:
bellard579a97f2007-11-11 14:26:47 +00003328 if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
3329 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003330 ret = get_errno(write(arg1, p, arg3));
3331 unlock_user(p, arg2, 0);
bellard31e31b82003-02-18 22:55:36 +00003332 break;
3333 case TARGET_NR_open:
bellard2f619692007-11-16 10:46:05 +00003334 if (!(p = lock_user_string(arg1)))
3335 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003336 ret = get_errno(open(path(p),
bellardffa65c32004-01-04 23:57:22 +00003337 target_to_host_bitmask(arg2, fcntl_flags_tbl),
3338 arg3));
pbrook53a59602006-03-25 19:31:22 +00003339 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003340 break;
ths82424832007-09-24 09:21:55 +00003341#if defined(TARGET_NR_openat) && defined(__NR_openat)
3342 case TARGET_NR_openat:
bellard579a97f2007-11-11 14:26:47 +00003343 if (!(p = lock_user_string(arg2)))
3344 goto efault;
3345 ret = get_errno(sys_openat(arg1,
3346 path(p),
3347 target_to_host_bitmask(arg3, fcntl_flags_tbl),
3348 arg4));
3349 unlock_user(p, arg2, 0);
ths82424832007-09-24 09:21:55 +00003350 break;
3351#endif
bellard31e31b82003-02-18 22:55:36 +00003352 case TARGET_NR_close:
3353 ret = get_errno(close(arg1));
3354 break;
3355 case TARGET_NR_brk:
pbrook53a59602006-03-25 19:31:22 +00003356 ret = do_brk(arg1);
bellard31e31b82003-02-18 22:55:36 +00003357 break;
3358 case TARGET_NR_fork:
pbrookd865bab2008-06-07 22:12:17 +00003359 ret = get_errno(do_fork(cpu_env, SIGCHLD, 0, 0, 0, 0));
bellard31e31b82003-02-18 22:55:36 +00003360 break;
thse5febef2007-04-01 18:31:35 +00003361#ifdef TARGET_NR_waitpid
bellard31e31b82003-02-18 22:55:36 +00003362 case TARGET_NR_waitpid:
3363 {
pbrook53a59602006-03-25 19:31:22 +00003364 int status;
3365 ret = get_errno(waitpid(arg1, &status, arg3));
bellard2f619692007-11-16 10:46:05 +00003366 if (!is_error(ret) && arg2
3367 && put_user_s32(status, arg2))
3368 goto efault;
bellard31e31b82003-02-18 22:55:36 +00003369 }
3370 break;
thse5febef2007-04-01 18:31:35 +00003371#endif
pbrookf0cbb612008-05-30 18:20:05 +00003372#ifdef TARGET_NR_waitid
3373 case TARGET_NR_waitid:
3374 {
3375 siginfo_t info;
3376 info.si_pid = 0;
3377 ret = get_errno(waitid(arg1, arg2, &info, arg4));
3378 if (!is_error(ret) && arg3 && info.si_pid != 0) {
3379 if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_siginfo_t), 0)))
3380 goto efault;
3381 host_to_target_siginfo(p, &info);
3382 unlock_user(p, arg3, sizeof(target_siginfo_t));
3383 }
3384 }
3385 break;
3386#endif
j_mayer7a3148a2007-04-05 07:13:51 +00003387#ifdef TARGET_NR_creat /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00003388 case TARGET_NR_creat:
bellard579a97f2007-11-11 14:26:47 +00003389 if (!(p = lock_user_string(arg1)))
3390 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003391 ret = get_errno(creat(p, arg2));
3392 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003393 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003394#endif
bellard31e31b82003-02-18 22:55:36 +00003395 case TARGET_NR_link:
pbrook53a59602006-03-25 19:31:22 +00003396 {
3397 void * p2;
3398 p = lock_user_string(arg1);
3399 p2 = lock_user_string(arg2);
bellard579a97f2007-11-11 14:26:47 +00003400 if (!p || !p2)
3401 ret = -TARGET_EFAULT;
3402 else
3403 ret = get_errno(link(p, p2));
pbrook53a59602006-03-25 19:31:22 +00003404 unlock_user(p2, arg2, 0);
3405 unlock_user(p, arg1, 0);
3406 }
bellard31e31b82003-02-18 22:55:36 +00003407 break;
ths64f0ce42007-09-24 09:25:06 +00003408#if defined(TARGET_NR_linkat) && defined(__NR_linkat)
3409 case TARGET_NR_linkat:
ths64f0ce42007-09-24 09:25:06 +00003410 {
3411 void * p2 = NULL;
bellard579a97f2007-11-11 14:26:47 +00003412 if (!arg2 || !arg4)
3413 goto efault;
ths64f0ce42007-09-24 09:25:06 +00003414 p = lock_user_string(arg2);
3415 p2 = lock_user_string(arg4);
bellard579a97f2007-11-11 14:26:47 +00003416 if (!p || !p2)
ths0da46a62007-10-20 20:23:07 +00003417 ret = -TARGET_EFAULT;
ths64f0ce42007-09-24 09:25:06 +00003418 else
3419 ret = get_errno(sys_linkat(arg1, p, arg3, p2, arg5));
bellard579a97f2007-11-11 14:26:47 +00003420 unlock_user(p, arg2, 0);
3421 unlock_user(p2, arg4, 0);
ths64f0ce42007-09-24 09:25:06 +00003422 }
3423 break;
3424#endif
bellard31e31b82003-02-18 22:55:36 +00003425 case TARGET_NR_unlink:
bellard579a97f2007-11-11 14:26:47 +00003426 if (!(p = lock_user_string(arg1)))
3427 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003428 ret = get_errno(unlink(p));
3429 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003430 break;
ths8170f562007-09-24 09:24:11 +00003431#if defined(TARGET_NR_unlinkat) && defined(__NR_unlinkat)
3432 case TARGET_NR_unlinkat:
bellard579a97f2007-11-11 14:26:47 +00003433 if (!(p = lock_user_string(arg2)))
3434 goto efault;
3435 ret = get_errno(sys_unlinkat(arg1, p, arg3));
3436 unlock_user(p, arg2, 0);
balroged494d82007-12-11 23:23:52 +00003437 break;
balrogb7d35e62007-12-12 00:40:24 +00003438#endif
bellard31e31b82003-02-18 22:55:36 +00003439 case TARGET_NR_execve:
bellard7854b052003-03-29 17:22:23 +00003440 {
3441 char **argp, **envp;
bellardf7341ff2003-03-30 21:00:25 +00003442 int argc, envc;
blueswir1992f48a2007-10-14 16:27:31 +00003443 abi_ulong gp;
3444 abi_ulong guest_argp;
3445 abi_ulong guest_envp;
3446 abi_ulong addr;
bellard7854b052003-03-29 17:22:23 +00003447 char **q;
3448
bellardf7341ff2003-03-30 21:00:25 +00003449 argc = 0;
pbrook53a59602006-03-25 19:31:22 +00003450 guest_argp = arg2;
pbrookda94d262008-05-30 18:24:00 +00003451 for (gp = guest_argp; gp; gp += sizeof(abi_ulong)) {
ths03aa1972007-12-02 06:28:08 +00003452 if (get_user_ual(addr, gp))
bellard2f619692007-11-16 10:46:05 +00003453 goto efault;
ths03aa1972007-12-02 06:28:08 +00003454 if (!addr)
bellard2f619692007-11-16 10:46:05 +00003455 break;
bellard7854b052003-03-29 17:22:23 +00003456 argc++;
bellard2f619692007-11-16 10:46:05 +00003457 }
bellardf7341ff2003-03-30 21:00:25 +00003458 envc = 0;
pbrook53a59602006-03-25 19:31:22 +00003459 guest_envp = arg3;
pbrookda94d262008-05-30 18:24:00 +00003460 for (gp = guest_envp; gp; gp += sizeof(abi_ulong)) {
ths03aa1972007-12-02 06:28:08 +00003461 if (get_user_ual(addr, gp))
bellard2f619692007-11-16 10:46:05 +00003462 goto efault;
ths03aa1972007-12-02 06:28:08 +00003463 if (!addr)
bellard2f619692007-11-16 10:46:05 +00003464 break;
bellard7854b052003-03-29 17:22:23 +00003465 envc++;
bellard2f619692007-11-16 10:46:05 +00003466 }
bellard7854b052003-03-29 17:22:23 +00003467
bellardf7341ff2003-03-30 21:00:25 +00003468 argp = alloca((argc + 1) * sizeof(void *));
3469 envp = alloca((envc + 1) * sizeof(void *));
bellard7854b052003-03-29 17:22:23 +00003470
pbrookda94d262008-05-30 18:24:00 +00003471 for (gp = guest_argp, q = argp; gp;
blueswir1992f48a2007-10-14 16:27:31 +00003472 gp += sizeof(abi_ulong), q++) {
bellard2f619692007-11-16 10:46:05 +00003473 if (get_user_ual(addr, gp))
3474 goto execve_efault;
pbrook53a59602006-03-25 19:31:22 +00003475 if (!addr)
3476 break;
bellard2f619692007-11-16 10:46:05 +00003477 if (!(*q = lock_user_string(addr)))
3478 goto execve_efault;
pbrook53a59602006-03-25 19:31:22 +00003479 }
bellardf7341ff2003-03-30 21:00:25 +00003480 *q = NULL;
3481
pbrookda94d262008-05-30 18:24:00 +00003482 for (gp = guest_envp, q = envp; gp;
blueswir1992f48a2007-10-14 16:27:31 +00003483 gp += sizeof(abi_ulong), q++) {
bellard2f619692007-11-16 10:46:05 +00003484 if (get_user_ual(addr, gp))
3485 goto execve_efault;
pbrook53a59602006-03-25 19:31:22 +00003486 if (!addr)
3487 break;
bellard2f619692007-11-16 10:46:05 +00003488 if (!(*q = lock_user_string(addr)))
3489 goto execve_efault;
pbrook53a59602006-03-25 19:31:22 +00003490 }
bellardf7341ff2003-03-30 21:00:25 +00003491 *q = NULL;
bellard7854b052003-03-29 17:22:23 +00003492
bellard2f619692007-11-16 10:46:05 +00003493 if (!(p = lock_user_string(arg1)))
3494 goto execve_efault;
pbrook53a59602006-03-25 19:31:22 +00003495 ret = get_errno(execve(p, argp, envp));
3496 unlock_user(p, arg1, 0);
3497
bellard2f619692007-11-16 10:46:05 +00003498 goto execve_end;
3499
3500 execve_efault:
3501 ret = -TARGET_EFAULT;
3502
3503 execve_end:
pbrook53a59602006-03-25 19:31:22 +00003504 for (gp = guest_argp, q = argp; *q;
blueswir1992f48a2007-10-14 16:27:31 +00003505 gp += sizeof(abi_ulong), q++) {
bellard2f619692007-11-16 10:46:05 +00003506 if (get_user_ual(addr, gp)
3507 || !addr)
3508 break;
pbrook53a59602006-03-25 19:31:22 +00003509 unlock_user(*q, addr, 0);
3510 }
3511 for (gp = guest_envp, q = envp; *q;
blueswir1992f48a2007-10-14 16:27:31 +00003512 gp += sizeof(abi_ulong), q++) {
bellard2f619692007-11-16 10:46:05 +00003513 if (get_user_ual(addr, gp)
3514 || !addr)
3515 break;
pbrook53a59602006-03-25 19:31:22 +00003516 unlock_user(*q, addr, 0);
3517 }
bellard7854b052003-03-29 17:22:23 +00003518 }
bellard31e31b82003-02-18 22:55:36 +00003519 break;
3520 case TARGET_NR_chdir:
bellard579a97f2007-11-11 14:26:47 +00003521 if (!(p = lock_user_string(arg1)))
3522 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003523 ret = get_errno(chdir(p));
3524 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003525 break;
bellarda315a142005-01-30 22:59:18 +00003526#ifdef TARGET_NR_time
bellard31e31b82003-02-18 22:55:36 +00003527 case TARGET_NR_time:
3528 {
pbrook53a59602006-03-25 19:31:22 +00003529 time_t host_time;
3530 ret = get_errno(time(&host_time));
bellard2f619692007-11-16 10:46:05 +00003531 if (!is_error(ret)
3532 && arg1
3533 && put_user_sal(host_time, arg1))
3534 goto efault;
bellard31e31b82003-02-18 22:55:36 +00003535 }
3536 break;
bellarda315a142005-01-30 22:59:18 +00003537#endif
bellard31e31b82003-02-18 22:55:36 +00003538 case TARGET_NR_mknod:
bellard579a97f2007-11-11 14:26:47 +00003539 if (!(p = lock_user_string(arg1)))
3540 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003541 ret = get_errno(mknod(p, arg2, arg3));
3542 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003543 break;
ths75ac37a2007-09-24 09:23:05 +00003544#if defined(TARGET_NR_mknodat) && defined(__NR_mknodat)
3545 case TARGET_NR_mknodat:
bellard579a97f2007-11-11 14:26:47 +00003546 if (!(p = lock_user_string(arg2)))
3547 goto efault;
3548 ret = get_errno(sys_mknodat(arg1, p, arg3, arg4));
3549 unlock_user(p, arg2, 0);
ths75ac37a2007-09-24 09:23:05 +00003550 break;
3551#endif
bellard31e31b82003-02-18 22:55:36 +00003552 case TARGET_NR_chmod:
bellard579a97f2007-11-11 14:26:47 +00003553 if (!(p = lock_user_string(arg1)))
3554 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003555 ret = get_errno(chmod(p, arg2));
3556 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003557 break;
bellardebc05482003-09-30 21:08:41 +00003558#ifdef TARGET_NR_break
bellard31e31b82003-02-18 22:55:36 +00003559 case TARGET_NR_break:
3560 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00003561#endif
3562#ifdef TARGET_NR_oldstat
bellard31e31b82003-02-18 22:55:36 +00003563 case TARGET_NR_oldstat:
3564 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00003565#endif
bellard31e31b82003-02-18 22:55:36 +00003566 case TARGET_NR_lseek:
3567 ret = get_errno(lseek(arg1, arg2, arg3));
3568 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003569#ifdef TARGET_NR_getxpid
3570 case TARGET_NR_getxpid:
3571#else
bellard31e31b82003-02-18 22:55:36 +00003572 case TARGET_NR_getpid:
j_mayer7a3148a2007-04-05 07:13:51 +00003573#endif
bellard31e31b82003-02-18 22:55:36 +00003574 ret = get_errno(getpid());
3575 break;
3576 case TARGET_NR_mount:
ths80265912007-02-17 22:25:41 +00003577 {
3578 /* need to look at the data field */
3579 void *p2, *p3;
3580 p = lock_user_string(arg1);
3581 p2 = lock_user_string(arg2);
3582 p3 = lock_user_string(arg3);
bellard579a97f2007-11-11 14:26:47 +00003583 if (!p || !p2 || !p3)
3584 ret = -TARGET_EFAULT;
3585 else
3586 /* FIXME - arg5 should be locked, but it isn't clear how to
3587 * do that since it's not guaranteed to be a NULL-terminated
3588 * string.
3589 */
3590 ret = get_errno(mount(p, p2, p3, (unsigned long)arg4, g2h(arg5)));
3591 unlock_user(p, arg1, 0);
3592 unlock_user(p2, arg2, 0);
3593 unlock_user(p3, arg3, 0);
ths80265912007-02-17 22:25:41 +00003594 break;
3595 }
thse5febef2007-04-01 18:31:35 +00003596#ifdef TARGET_NR_umount
bellard31e31b82003-02-18 22:55:36 +00003597 case TARGET_NR_umount:
bellard579a97f2007-11-11 14:26:47 +00003598 if (!(p = lock_user_string(arg1)))
3599 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003600 ret = get_errno(umount(p));
3601 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003602 break;
thse5febef2007-04-01 18:31:35 +00003603#endif
j_mayer7a3148a2007-04-05 07:13:51 +00003604#ifdef TARGET_NR_stime /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00003605 case TARGET_NR_stime:
3606 {
pbrook53a59602006-03-25 19:31:22 +00003607 time_t host_time;
bellard2f619692007-11-16 10:46:05 +00003608 if (get_user_sal(host_time, arg1))
3609 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003610 ret = get_errno(stime(&host_time));
bellard31e31b82003-02-18 22:55:36 +00003611 }
3612 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003613#endif
bellard31e31b82003-02-18 22:55:36 +00003614 case TARGET_NR_ptrace:
3615 goto unimplemented;
j_mayer7a3148a2007-04-05 07:13:51 +00003616#ifdef TARGET_NR_alarm /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00003617 case TARGET_NR_alarm:
3618 ret = alarm(arg1);
3619 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003620#endif
bellardebc05482003-09-30 21:08:41 +00003621#ifdef TARGET_NR_oldfstat
bellard31e31b82003-02-18 22:55:36 +00003622 case TARGET_NR_oldfstat:
3623 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00003624#endif
j_mayer7a3148a2007-04-05 07:13:51 +00003625#ifdef TARGET_NR_pause /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00003626 case TARGET_NR_pause:
3627 ret = get_errno(pause());
3628 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003629#endif
thse5febef2007-04-01 18:31:35 +00003630#ifdef TARGET_NR_utime
bellard31e31b82003-02-18 22:55:36 +00003631 case TARGET_NR_utime:
bellardebc05482003-09-30 21:08:41 +00003632 {
pbrook53a59602006-03-25 19:31:22 +00003633 struct utimbuf tbuf, *host_tbuf;
3634 struct target_utimbuf *target_tbuf;
3635 if (arg2) {
bellard579a97f2007-11-11 14:26:47 +00003636 if (!lock_user_struct(VERIFY_READ, target_tbuf, arg2, 1))
3637 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003638 tbuf.actime = tswapl(target_tbuf->actime);
3639 tbuf.modtime = tswapl(target_tbuf->modtime);
3640 unlock_user_struct(target_tbuf, arg2, 0);
3641 host_tbuf = &tbuf;
bellardf72e8ff2004-05-03 19:23:07 +00003642 } else {
pbrook53a59602006-03-25 19:31:22 +00003643 host_tbuf = NULL;
bellardf72e8ff2004-05-03 19:23:07 +00003644 }
bellard579a97f2007-11-11 14:26:47 +00003645 if (!(p = lock_user_string(arg1)))
3646 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003647 ret = get_errno(utime(p, host_tbuf));
3648 unlock_user(p, arg1, 0);
bellardebc05482003-09-30 21:08:41 +00003649 }
3650 break;
thse5febef2007-04-01 18:31:35 +00003651#endif
bellard978a66f2004-12-06 22:58:05 +00003652 case TARGET_NR_utimes:
3653 {
bellard978a66f2004-12-06 22:58:05 +00003654 struct timeval *tvp, tv[2];
pbrook53a59602006-03-25 19:31:22 +00003655 if (arg2) {
ths788f5ec2007-12-09 02:37:05 +00003656 if (copy_from_user_timeval(&tv[0], arg2)
3657 || copy_from_user_timeval(&tv[1],
3658 arg2 + sizeof(struct target_timeval)))
3659 goto efault;
bellard978a66f2004-12-06 22:58:05 +00003660 tvp = tv;
3661 } else {
3662 tvp = NULL;
3663 }
bellard579a97f2007-11-11 14:26:47 +00003664 if (!(p = lock_user_string(arg1)))
3665 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003666 ret = get_errno(utimes(p, tvp));
3667 unlock_user(p, arg1, 0);
bellard978a66f2004-12-06 22:58:05 +00003668 }
3669 break;
balrogac8a6552008-09-20 02:25:39 +00003670#if defined(TARGET_NR_futimesat) && defined(__NR_futimesat)
3671 case TARGET_NR_futimesat:
3672 {
3673 struct timeval *tvp, tv[2];
3674 if (arg3) {
3675 if (copy_from_user_timeval(&tv[0], arg3)
3676 || copy_from_user_timeval(&tv[1],
3677 arg3 + sizeof(struct target_timeval)))
3678 goto efault;
3679 tvp = tv;
3680 } else {
3681 tvp = NULL;
3682 }
3683 if (!(p = lock_user_string(arg2)))
3684 goto efault;
3685 ret = get_errno(sys_futimesat(arg1, path(p), tvp));
3686 unlock_user(p, arg2, 0);
3687 }
3688 break;
3689#endif
bellardebc05482003-09-30 21:08:41 +00003690#ifdef TARGET_NR_stty
bellard31e31b82003-02-18 22:55:36 +00003691 case TARGET_NR_stty:
3692 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00003693#endif
3694#ifdef TARGET_NR_gtty
bellard31e31b82003-02-18 22:55:36 +00003695 case TARGET_NR_gtty:
3696 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00003697#endif
bellard31e31b82003-02-18 22:55:36 +00003698 case TARGET_NR_access:
bellard579a97f2007-11-11 14:26:47 +00003699 if (!(p = lock_user_string(arg1)))
3700 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003701 ret = get_errno(access(p, arg2));
3702 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003703 break;
ths92a34c12007-09-24 09:27:49 +00003704#if defined(TARGET_NR_faccessat) && defined(__NR_faccessat)
3705 case TARGET_NR_faccessat:
bellard579a97f2007-11-11 14:26:47 +00003706 if (!(p = lock_user_string(arg2)))
3707 goto efault;
3708 ret = get_errno(sys_faccessat(arg1, p, arg3, arg4));
3709 unlock_user(p, arg2, 0);
ths92a34c12007-09-24 09:27:49 +00003710 break;
3711#endif
j_mayer7a3148a2007-04-05 07:13:51 +00003712#ifdef TARGET_NR_nice /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00003713 case TARGET_NR_nice:
3714 ret = get_errno(nice(arg1));
3715 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003716#endif
bellardebc05482003-09-30 21:08:41 +00003717#ifdef TARGET_NR_ftime
bellard31e31b82003-02-18 22:55:36 +00003718 case TARGET_NR_ftime:
3719 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00003720#endif
bellard31e31b82003-02-18 22:55:36 +00003721 case TARGET_NR_sync:
bellard04369ff2003-03-20 22:33:23 +00003722 sync();
3723 ret = 0;
bellard31e31b82003-02-18 22:55:36 +00003724 break;
3725 case TARGET_NR_kill:
pbrook4cb05962008-05-30 18:05:19 +00003726 ret = get_errno(kill(arg1, target_to_host_signal(arg2)));
bellard31e31b82003-02-18 22:55:36 +00003727 break;
3728 case TARGET_NR_rename:
pbrook53a59602006-03-25 19:31:22 +00003729 {
3730 void *p2;
3731 p = lock_user_string(arg1);
3732 p2 = lock_user_string(arg2);
bellard579a97f2007-11-11 14:26:47 +00003733 if (!p || !p2)
3734 ret = -TARGET_EFAULT;
3735 else
3736 ret = get_errno(rename(p, p2));
pbrook53a59602006-03-25 19:31:22 +00003737 unlock_user(p2, arg2, 0);
3738 unlock_user(p, arg1, 0);
3739 }
bellard31e31b82003-02-18 22:55:36 +00003740 break;
ths722183f2007-09-24 09:24:37 +00003741#if defined(TARGET_NR_renameat) && defined(__NR_renameat)
3742 case TARGET_NR_renameat:
ths722183f2007-09-24 09:24:37 +00003743 {
bellard579a97f2007-11-11 14:26:47 +00003744 void *p2;
ths722183f2007-09-24 09:24:37 +00003745 p = lock_user_string(arg2);
3746 p2 = lock_user_string(arg4);
bellard579a97f2007-11-11 14:26:47 +00003747 if (!p || !p2)
ths0da46a62007-10-20 20:23:07 +00003748 ret = -TARGET_EFAULT;
ths722183f2007-09-24 09:24:37 +00003749 else
3750 ret = get_errno(sys_renameat(arg1, p, arg3, p2));
bellard579a97f2007-11-11 14:26:47 +00003751 unlock_user(p2, arg4, 0);
3752 unlock_user(p, arg2, 0);
ths722183f2007-09-24 09:24:37 +00003753 }
3754 break;
3755#endif
bellard31e31b82003-02-18 22:55:36 +00003756 case TARGET_NR_mkdir:
bellard579a97f2007-11-11 14:26:47 +00003757 if (!(p = lock_user_string(arg1)))
3758 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003759 ret = get_errno(mkdir(p, arg2));
3760 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003761 break;
ths4472ad02007-09-24 09:22:32 +00003762#if defined(TARGET_NR_mkdirat) && defined(__NR_mkdirat)
3763 case TARGET_NR_mkdirat:
bellard579a97f2007-11-11 14:26:47 +00003764 if (!(p = lock_user_string(arg2)))
3765 goto efault;
3766 ret = get_errno(sys_mkdirat(arg1, p, arg3));
3767 unlock_user(p, arg2, 0);
ths4472ad02007-09-24 09:22:32 +00003768 break;
3769#endif
bellard31e31b82003-02-18 22:55:36 +00003770 case TARGET_NR_rmdir:
bellard579a97f2007-11-11 14:26:47 +00003771 if (!(p = lock_user_string(arg1)))
3772 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003773 ret = get_errno(rmdir(p));
3774 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003775 break;
3776 case TARGET_NR_dup:
3777 ret = get_errno(dup(arg1));
3778 break;
3779 case TARGET_NR_pipe:
3780 {
pbrook53a59602006-03-25 19:31:22 +00003781 int host_pipe[2];
3782 ret = get_errno(pipe(host_pipe));
bellard31e31b82003-02-18 22:55:36 +00003783 if (!is_error(ret)) {
thsc12ab052007-06-01 11:50:36 +00003784#if defined(TARGET_MIPS)
thsead93602007-09-06 00:18:15 +00003785 CPUMIPSState *env = (CPUMIPSState*)cpu_env;
thsb5dc7732008-06-27 10:02:35 +00003786 env->active_tc.gpr[3] = host_pipe[1];
thsc12ab052007-06-01 11:50:36 +00003787 ret = host_pipe[0];
aurel32b5eff352008-03-11 23:30:22 +00003788#elif defined(TARGET_SH4)
3789 ((CPUSH4State*)cpu_env)->gregs[1] = host_pipe[1];
3790 ret = host_pipe[0];
thsc12ab052007-06-01 11:50:36 +00003791#else
bellard2f619692007-11-16 10:46:05 +00003792 if (put_user_s32(host_pipe[0], arg1)
3793 || put_user_s32(host_pipe[1], arg1 + sizeof(host_pipe[0])))
3794 goto efault;
thsc12ab052007-06-01 11:50:36 +00003795#endif
bellard31e31b82003-02-18 22:55:36 +00003796 }
3797 }
3798 break;
3799 case TARGET_NR_times:
bellard32f36bc2003-03-30 21:29:48 +00003800 {
pbrook53a59602006-03-25 19:31:22 +00003801 struct target_tms *tmsp;
bellard32f36bc2003-03-30 21:29:48 +00003802 struct tms tms;
3803 ret = get_errno(times(&tms));
pbrook53a59602006-03-25 19:31:22 +00003804 if (arg1) {
bellard579a97f2007-11-11 14:26:47 +00003805 tmsp = lock_user(VERIFY_WRITE, arg1, sizeof(struct target_tms), 0);
3806 if (!tmsp)
3807 goto efault;
bellardc596ed12003-07-13 17:32:31 +00003808 tmsp->tms_utime = tswapl(host_to_target_clock_t(tms.tms_utime));
3809 tmsp->tms_stime = tswapl(host_to_target_clock_t(tms.tms_stime));
3810 tmsp->tms_cutime = tswapl(host_to_target_clock_t(tms.tms_cutime));
3811 tmsp->tms_cstime = tswapl(host_to_target_clock_t(tms.tms_cstime));
bellard32f36bc2003-03-30 21:29:48 +00003812 }
bellardc596ed12003-07-13 17:32:31 +00003813 if (!is_error(ret))
3814 ret = host_to_target_clock_t(ret);
bellard32f36bc2003-03-30 21:29:48 +00003815 }
3816 break;
bellardebc05482003-09-30 21:08:41 +00003817#ifdef TARGET_NR_prof
bellard31e31b82003-02-18 22:55:36 +00003818 case TARGET_NR_prof:
3819 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00003820#endif
thse5febef2007-04-01 18:31:35 +00003821#ifdef TARGET_NR_signal
bellard31e31b82003-02-18 22:55:36 +00003822 case TARGET_NR_signal:
3823 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00003824#endif
bellard31e31b82003-02-18 22:55:36 +00003825 case TARGET_NR_acct:
bellard579a97f2007-11-11 14:26:47 +00003826 if (!(p = lock_user_string(arg1)))
3827 goto efault;
pbrook24836682006-04-16 14:14:53 +00003828 ret = get_errno(acct(path(p)));
3829 unlock_user(p, arg1, 0);
3830 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003831#ifdef TARGET_NR_umount2 /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00003832 case TARGET_NR_umount2:
bellard579a97f2007-11-11 14:26:47 +00003833 if (!(p = lock_user_string(arg1)))
3834 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003835 ret = get_errno(umount2(p, arg2));
3836 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003837 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003838#endif
bellardebc05482003-09-30 21:08:41 +00003839#ifdef TARGET_NR_lock
bellard31e31b82003-02-18 22:55:36 +00003840 case TARGET_NR_lock:
3841 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00003842#endif
bellard31e31b82003-02-18 22:55:36 +00003843 case TARGET_NR_ioctl:
3844 ret = do_ioctl(arg1, arg2, arg3);
3845 break;
3846 case TARGET_NR_fcntl:
bellard9ee1fa22007-11-11 15:11:19 +00003847 ret = do_fcntl(arg1, arg2, arg3);
bellard31e31b82003-02-18 22:55:36 +00003848 break;
bellardebc05482003-09-30 21:08:41 +00003849#ifdef TARGET_NR_mpx
bellard31e31b82003-02-18 22:55:36 +00003850 case TARGET_NR_mpx:
3851 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00003852#endif
bellard31e31b82003-02-18 22:55:36 +00003853 case TARGET_NR_setpgid:
3854 ret = get_errno(setpgid(arg1, arg2));
3855 break;
bellardebc05482003-09-30 21:08:41 +00003856#ifdef TARGET_NR_ulimit
bellard31e31b82003-02-18 22:55:36 +00003857 case TARGET_NR_ulimit:
3858 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00003859#endif
3860#ifdef TARGET_NR_oldolduname
bellard31e31b82003-02-18 22:55:36 +00003861 case TARGET_NR_oldolduname:
3862 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00003863#endif
bellard31e31b82003-02-18 22:55:36 +00003864 case TARGET_NR_umask:
3865 ret = get_errno(umask(arg1));
3866 break;
3867 case TARGET_NR_chroot:
bellard579a97f2007-11-11 14:26:47 +00003868 if (!(p = lock_user_string(arg1)))
3869 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003870 ret = get_errno(chroot(p));
3871 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003872 break;
3873 case TARGET_NR_ustat:
3874 goto unimplemented;
3875 case TARGET_NR_dup2:
3876 ret = get_errno(dup2(arg1, arg2));
3877 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003878#ifdef TARGET_NR_getppid /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00003879 case TARGET_NR_getppid:
3880 ret = get_errno(getppid());
3881 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003882#endif
bellard31e31b82003-02-18 22:55:36 +00003883 case TARGET_NR_getpgrp:
3884 ret = get_errno(getpgrp());
3885 break;
3886 case TARGET_NR_setsid:
3887 ret = get_errno(setsid());
3888 break;
thse5febef2007-04-01 18:31:35 +00003889#ifdef TARGET_NR_sigaction
bellard31e31b82003-02-18 22:55:36 +00003890 case TARGET_NR_sigaction:
bellard31e31b82003-02-18 22:55:36 +00003891 {
ths388bb212007-05-13 13:58:00 +00003892#if !defined(TARGET_MIPS)
pbrook53a59602006-03-25 19:31:22 +00003893 struct target_old_sigaction *old_act;
bellard66fb9762003-03-23 01:06:05 +00003894 struct target_sigaction act, oact, *pact;
pbrook53a59602006-03-25 19:31:22 +00003895 if (arg2) {
bellard579a97f2007-11-11 14:26:47 +00003896 if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1))
3897 goto efault;
bellard66fb9762003-03-23 01:06:05 +00003898 act._sa_handler = old_act->_sa_handler;
3899 target_siginitset(&act.sa_mask, old_act->sa_mask);
3900 act.sa_flags = old_act->sa_flags;
3901 act.sa_restorer = old_act->sa_restorer;
pbrook53a59602006-03-25 19:31:22 +00003902 unlock_user_struct(old_act, arg2, 0);
bellard66fb9762003-03-23 01:06:05 +00003903 pact = &act;
3904 } else {
3905 pact = NULL;
3906 }
3907 ret = get_errno(do_sigaction(arg1, pact, &oact));
pbrook53a59602006-03-25 19:31:22 +00003908 if (!is_error(ret) && arg3) {
bellard579a97f2007-11-11 14:26:47 +00003909 if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0))
3910 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003911 old_act->_sa_handler = oact._sa_handler;
3912 old_act->sa_mask = oact.sa_mask.sig[0];
3913 old_act->sa_flags = oact.sa_flags;
3914 old_act->sa_restorer = oact.sa_restorer;
3915 unlock_user_struct(old_act, arg3, 1);
bellard66fb9762003-03-23 01:06:05 +00003916 }
ths388bb212007-05-13 13:58:00 +00003917#else
bellard106ec872006-06-27 21:08:10 +00003918 struct target_sigaction act, oact, *pact, *old_act;
3919
3920 if (arg2) {
bellard579a97f2007-11-11 14:26:47 +00003921 if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1))
3922 goto efault;
bellard106ec872006-06-27 21:08:10 +00003923 act._sa_handler = old_act->_sa_handler;
3924 target_siginitset(&act.sa_mask, old_act->sa_mask.sig[0]);
3925 act.sa_flags = old_act->sa_flags;
3926 unlock_user_struct(old_act, arg2, 0);
3927 pact = &act;
3928 } else {
3929 pact = NULL;
3930 }
3931
3932 ret = get_errno(do_sigaction(arg1, pact, &oact));
3933
3934 if (!is_error(ret) && arg3) {
bellard579a97f2007-11-11 14:26:47 +00003935 if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0))
3936 goto efault;
bellard106ec872006-06-27 21:08:10 +00003937 old_act->_sa_handler = oact._sa_handler;
3938 old_act->sa_flags = oact.sa_flags;
3939 old_act->sa_mask.sig[0] = oact.sa_mask.sig[0];
3940 old_act->sa_mask.sig[1] = 0;
3941 old_act->sa_mask.sig[2] = 0;
3942 old_act->sa_mask.sig[3] = 0;
3943 unlock_user_struct(old_act, arg3, 1);
3944 }
ths388bb212007-05-13 13:58:00 +00003945#endif
bellard31e31b82003-02-18 22:55:36 +00003946 }
3947 break;
thse5febef2007-04-01 18:31:35 +00003948#endif
bellard66fb9762003-03-23 01:06:05 +00003949 case TARGET_NR_rt_sigaction:
pbrook53a59602006-03-25 19:31:22 +00003950 {
3951 struct target_sigaction *act;
3952 struct target_sigaction *oact;
3953
bellard579a97f2007-11-11 14:26:47 +00003954 if (arg2) {
3955 if (!lock_user_struct(VERIFY_READ, act, arg2, 1))
3956 goto efault;
3957 } else
pbrook53a59602006-03-25 19:31:22 +00003958 act = NULL;
bellard579a97f2007-11-11 14:26:47 +00003959 if (arg3) {
3960 if (!lock_user_struct(VERIFY_WRITE, oact, arg3, 0)) {
3961 ret = -TARGET_EFAULT;
3962 goto rt_sigaction_fail;
3963 }
3964 } else
pbrook53a59602006-03-25 19:31:22 +00003965 oact = NULL;
3966 ret = get_errno(do_sigaction(arg1, act, oact));
bellard579a97f2007-11-11 14:26:47 +00003967 rt_sigaction_fail:
3968 if (act)
pbrook53a59602006-03-25 19:31:22 +00003969 unlock_user_struct(act, arg2, 0);
bellard579a97f2007-11-11 14:26:47 +00003970 if (oact)
pbrook53a59602006-03-25 19:31:22 +00003971 unlock_user_struct(oact, arg3, 1);
3972 }
bellard66fb9762003-03-23 01:06:05 +00003973 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003974#ifdef TARGET_NR_sgetmask /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00003975 case TARGET_NR_sgetmask:
bellard66fb9762003-03-23 01:06:05 +00003976 {
3977 sigset_t cur_set;
blueswir1992f48a2007-10-14 16:27:31 +00003978 abi_ulong target_set;
bellard66fb9762003-03-23 01:06:05 +00003979 sigprocmask(0, NULL, &cur_set);
3980 host_to_target_old_sigset(&target_set, &cur_set);
3981 ret = target_set;
3982 }
3983 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003984#endif
3985#ifdef TARGET_NR_ssetmask /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00003986 case TARGET_NR_ssetmask:
bellard66fb9762003-03-23 01:06:05 +00003987 {
3988 sigset_t set, oset, cur_set;
blueswir1992f48a2007-10-14 16:27:31 +00003989 abi_ulong target_set = arg1;
bellard66fb9762003-03-23 01:06:05 +00003990 sigprocmask(0, NULL, &cur_set);
3991 target_to_host_old_sigset(&set, &target_set);
3992 sigorset(&set, &set, &cur_set);
3993 sigprocmask(SIG_SETMASK, &set, &oset);
3994 host_to_target_old_sigset(&target_set, &oset);
3995 ret = target_set;
3996 }
3997 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003998#endif
thse5febef2007-04-01 18:31:35 +00003999#ifdef TARGET_NR_sigprocmask
bellard66fb9762003-03-23 01:06:05 +00004000 case TARGET_NR_sigprocmask:
4001 {
4002 int how = arg1;
4003 sigset_t set, oldset, *set_ptr;
ths3b46e622007-09-17 08:09:54 +00004004
pbrook53a59602006-03-25 19:31:22 +00004005 if (arg2) {
bellard66fb9762003-03-23 01:06:05 +00004006 switch(how) {
4007 case TARGET_SIG_BLOCK:
4008 how = SIG_BLOCK;
4009 break;
4010 case TARGET_SIG_UNBLOCK:
4011 how = SIG_UNBLOCK;
4012 break;
4013 case TARGET_SIG_SETMASK:
4014 how = SIG_SETMASK;
4015 break;
4016 default:
ths0da46a62007-10-20 20:23:07 +00004017 ret = -TARGET_EINVAL;
bellard66fb9762003-03-23 01:06:05 +00004018 goto fail;
4019 }
bellard579a97f2007-11-11 14:26:47 +00004020 if (!(p = lock_user(VERIFY_READ, arg2, sizeof(target_sigset_t), 1)))
4021 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004022 target_to_host_old_sigset(&set, p);
4023 unlock_user(p, arg2, 0);
bellard66fb9762003-03-23 01:06:05 +00004024 set_ptr = &set;
4025 } else {
4026 how = 0;
4027 set_ptr = NULL;
4028 }
4029 ret = get_errno(sigprocmask(arg1, set_ptr, &oldset));
pbrook53a59602006-03-25 19:31:22 +00004030 if (!is_error(ret) && arg3) {
bellard579a97f2007-11-11 14:26:47 +00004031 if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0)))
4032 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004033 host_to_target_old_sigset(p, &oldset);
4034 unlock_user(p, arg3, sizeof(target_sigset_t));
bellard66fb9762003-03-23 01:06:05 +00004035 }
4036 }
4037 break;
thse5febef2007-04-01 18:31:35 +00004038#endif
bellard66fb9762003-03-23 01:06:05 +00004039 case TARGET_NR_rt_sigprocmask:
4040 {
4041 int how = arg1;
4042 sigset_t set, oldset, *set_ptr;
ths3b46e622007-09-17 08:09:54 +00004043
pbrook53a59602006-03-25 19:31:22 +00004044 if (arg2) {
bellard66fb9762003-03-23 01:06:05 +00004045 switch(how) {
4046 case TARGET_SIG_BLOCK:
4047 how = SIG_BLOCK;
4048 break;
4049 case TARGET_SIG_UNBLOCK:
4050 how = SIG_UNBLOCK;
4051 break;
4052 case TARGET_SIG_SETMASK:
4053 how = SIG_SETMASK;
4054 break;
4055 default:
ths0da46a62007-10-20 20:23:07 +00004056 ret = -TARGET_EINVAL;
bellard66fb9762003-03-23 01:06:05 +00004057 goto fail;
4058 }
bellard579a97f2007-11-11 14:26:47 +00004059 if (!(p = lock_user(VERIFY_READ, arg2, sizeof(target_sigset_t), 1)))
4060 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004061 target_to_host_sigset(&set, p);
4062 unlock_user(p, arg2, 0);
bellard66fb9762003-03-23 01:06:05 +00004063 set_ptr = &set;
4064 } else {
4065 how = 0;
4066 set_ptr = NULL;
4067 }
4068 ret = get_errno(sigprocmask(how, set_ptr, &oldset));
pbrook53a59602006-03-25 19:31:22 +00004069 if (!is_error(ret) && arg3) {
bellard579a97f2007-11-11 14:26:47 +00004070 if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0)))
4071 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004072 host_to_target_sigset(p, &oldset);
4073 unlock_user(p, arg3, sizeof(target_sigset_t));
bellard66fb9762003-03-23 01:06:05 +00004074 }
4075 }
4076 break;
thse5febef2007-04-01 18:31:35 +00004077#ifdef TARGET_NR_sigpending
bellard66fb9762003-03-23 01:06:05 +00004078 case TARGET_NR_sigpending:
4079 {
4080 sigset_t set;
4081 ret = get_errno(sigpending(&set));
4082 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00004083 if (!(p = lock_user(VERIFY_WRITE, arg1, sizeof(target_sigset_t), 0)))
4084 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004085 host_to_target_old_sigset(p, &set);
4086 unlock_user(p, arg1, sizeof(target_sigset_t));
bellard66fb9762003-03-23 01:06:05 +00004087 }
4088 }
4089 break;
thse5febef2007-04-01 18:31:35 +00004090#endif
bellard66fb9762003-03-23 01:06:05 +00004091 case TARGET_NR_rt_sigpending:
4092 {
4093 sigset_t set;
4094 ret = get_errno(sigpending(&set));
4095 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00004096 if (!(p = lock_user(VERIFY_WRITE, arg1, sizeof(target_sigset_t), 0)))
4097 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004098 host_to_target_sigset(p, &set);
4099 unlock_user(p, arg1, sizeof(target_sigset_t));
bellard66fb9762003-03-23 01:06:05 +00004100 }
4101 }
4102 break;
thse5febef2007-04-01 18:31:35 +00004103#ifdef TARGET_NR_sigsuspend
bellard66fb9762003-03-23 01:06:05 +00004104 case TARGET_NR_sigsuspend:
4105 {
4106 sigset_t set;
bellard579a97f2007-11-11 14:26:47 +00004107 if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
4108 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004109 target_to_host_old_sigset(&set, p);
4110 unlock_user(p, arg1, 0);
bellard66fb9762003-03-23 01:06:05 +00004111 ret = get_errno(sigsuspend(&set));
4112 }
4113 break;
thse5febef2007-04-01 18:31:35 +00004114#endif
bellard66fb9762003-03-23 01:06:05 +00004115 case TARGET_NR_rt_sigsuspend:
4116 {
4117 sigset_t set;
bellard579a97f2007-11-11 14:26:47 +00004118 if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
4119 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004120 target_to_host_sigset(&set, p);
4121 unlock_user(p, arg1, 0);
bellard66fb9762003-03-23 01:06:05 +00004122 ret = get_errno(sigsuspend(&set));
4123 }
4124 break;
4125 case TARGET_NR_rt_sigtimedwait:
4126 {
bellard66fb9762003-03-23 01:06:05 +00004127 sigset_t set;
4128 struct timespec uts, *puts;
4129 siginfo_t uinfo;
ths3b46e622007-09-17 08:09:54 +00004130
bellard579a97f2007-11-11 14:26:47 +00004131 if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
4132 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004133 target_to_host_sigset(&set, p);
4134 unlock_user(p, arg1, 0);
4135 if (arg3) {
bellard66fb9762003-03-23 01:06:05 +00004136 puts = &uts;
pbrook53a59602006-03-25 19:31:22 +00004137 target_to_host_timespec(puts, arg3);
bellard66fb9762003-03-23 01:06:05 +00004138 } else {
4139 puts = NULL;
4140 }
4141 ret = get_errno(sigtimedwait(&set, &uinfo, puts));
pbrook53a59602006-03-25 19:31:22 +00004142 if (!is_error(ret) && arg2) {
pbrooke1e3f302008-05-30 21:53:38 +00004143 if (!(p = lock_user(VERIFY_WRITE, arg2, sizeof(target_siginfo_t), 0)))
bellard579a97f2007-11-11 14:26:47 +00004144 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004145 host_to_target_siginfo(p, &uinfo);
pbrooke1e3f302008-05-30 21:53:38 +00004146 unlock_user(p, arg2, sizeof(target_siginfo_t));
bellard66fb9762003-03-23 01:06:05 +00004147 }
4148 }
4149 break;
4150 case TARGET_NR_rt_sigqueueinfo:
4151 {
4152 siginfo_t uinfo;
bellard579a97f2007-11-11 14:26:47 +00004153 if (!(p = lock_user(VERIFY_READ, arg3, sizeof(target_sigset_t), 1)))
4154 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004155 target_to_host_siginfo(&uinfo, p);
4156 unlock_user(p, arg1, 0);
bellard66fb9762003-03-23 01:06:05 +00004157 ret = get_errno(sys_rt_sigqueueinfo(arg1, arg2, &uinfo));
4158 }
4159 break;
thse5febef2007-04-01 18:31:35 +00004160#ifdef TARGET_NR_sigreturn
bellard66fb9762003-03-23 01:06:05 +00004161 case TARGET_NR_sigreturn:
4162 /* NOTE: ret is eax, so not transcoding must be done */
4163 ret = do_sigreturn(cpu_env);
4164 break;
thse5febef2007-04-01 18:31:35 +00004165#endif
bellard66fb9762003-03-23 01:06:05 +00004166 case TARGET_NR_rt_sigreturn:
4167 /* NOTE: ret is eax, so not transcoding must be done */
4168 ret = do_rt_sigreturn(cpu_env);
4169 break;
bellard31e31b82003-02-18 22:55:36 +00004170 case TARGET_NR_sethostname:
bellard579a97f2007-11-11 14:26:47 +00004171 if (!(p = lock_user_string(arg1)))
4172 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004173 ret = get_errno(sethostname(p, arg2));
4174 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004175 break;
4176 case TARGET_NR_setrlimit:
bellard9de5e442003-03-23 16:49:39 +00004177 {
4178 /* XXX: convert resource ? */
4179 int resource = arg1;
pbrook53a59602006-03-25 19:31:22 +00004180 struct target_rlimit *target_rlim;
bellard9de5e442003-03-23 16:49:39 +00004181 struct rlimit rlim;
bellard579a97f2007-11-11 14:26:47 +00004182 if (!lock_user_struct(VERIFY_READ, target_rlim, arg2, 1))
4183 goto efault;
bellard9de5e442003-03-23 16:49:39 +00004184 rlim.rlim_cur = tswapl(target_rlim->rlim_cur);
4185 rlim.rlim_max = tswapl(target_rlim->rlim_max);
pbrook53a59602006-03-25 19:31:22 +00004186 unlock_user_struct(target_rlim, arg2, 0);
bellard9de5e442003-03-23 16:49:39 +00004187 ret = get_errno(setrlimit(resource, &rlim));
4188 }
4189 break;
bellard31e31b82003-02-18 22:55:36 +00004190 case TARGET_NR_getrlimit:
bellard9de5e442003-03-23 16:49:39 +00004191 {
4192 /* XXX: convert resource ? */
4193 int resource = arg1;
pbrook53a59602006-03-25 19:31:22 +00004194 struct target_rlimit *target_rlim;
bellard9de5e442003-03-23 16:49:39 +00004195 struct rlimit rlim;
ths3b46e622007-09-17 08:09:54 +00004196
bellard9de5e442003-03-23 16:49:39 +00004197 ret = get_errno(getrlimit(resource, &rlim));
4198 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00004199 if (!lock_user_struct(VERIFY_WRITE, target_rlim, arg2, 0))
4200 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004201 rlim.rlim_cur = tswapl(target_rlim->rlim_cur);
4202 rlim.rlim_max = tswapl(target_rlim->rlim_max);
4203 unlock_user_struct(target_rlim, arg2, 1);
bellard9de5e442003-03-23 16:49:39 +00004204 }
4205 }
4206 break;
bellard31e31b82003-02-18 22:55:36 +00004207 case TARGET_NR_getrusage:
bellardb4091862003-05-16 15:39:34 +00004208 {
4209 struct rusage rusage;
bellardb4091862003-05-16 15:39:34 +00004210 ret = get_errno(getrusage(arg1, &rusage));
4211 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00004212 host_to_target_rusage(arg2, &rusage);
bellardb4091862003-05-16 15:39:34 +00004213 }
4214 }
4215 break;
bellard31e31b82003-02-18 22:55:36 +00004216 case TARGET_NR_gettimeofday:
4217 {
bellard31e31b82003-02-18 22:55:36 +00004218 struct timeval tv;
4219 ret = get_errno(gettimeofday(&tv, NULL));
4220 if (!is_error(ret)) {
ths788f5ec2007-12-09 02:37:05 +00004221 if (copy_to_user_timeval(arg1, &tv))
4222 goto efault;
bellard31e31b82003-02-18 22:55:36 +00004223 }
4224 }
4225 break;
4226 case TARGET_NR_settimeofday:
4227 {
bellard31e31b82003-02-18 22:55:36 +00004228 struct timeval tv;
ths788f5ec2007-12-09 02:37:05 +00004229 if (copy_from_user_timeval(&tv, arg1))
4230 goto efault;
bellard31e31b82003-02-18 22:55:36 +00004231 ret = get_errno(settimeofday(&tv, NULL));
4232 }
4233 break;
bellard048f6b42005-11-26 18:47:20 +00004234#ifdef TARGET_NR_select
bellard31e31b82003-02-18 22:55:36 +00004235 case TARGET_NR_select:
bellardf2674e32003-07-09 12:26:09 +00004236 {
pbrook53a59602006-03-25 19:31:22 +00004237 struct target_sel_arg_struct *sel;
blueswir1992f48a2007-10-14 16:27:31 +00004238 abi_ulong inp, outp, exp, tvp;
pbrook53a59602006-03-25 19:31:22 +00004239 long nsel;
4240
bellard579a97f2007-11-11 14:26:47 +00004241 if (!lock_user_struct(VERIFY_READ, sel, arg1, 1))
4242 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004243 nsel = tswapl(sel->n);
4244 inp = tswapl(sel->inp);
4245 outp = tswapl(sel->outp);
4246 exp = tswapl(sel->exp);
4247 tvp = tswapl(sel->tvp);
4248 unlock_user_struct(sel, arg1, 0);
4249 ret = do_select(nsel, inp, outp, exp, tvp);
bellardf2674e32003-07-09 12:26:09 +00004250 }
4251 break;
bellard048f6b42005-11-26 18:47:20 +00004252#endif
bellard31e31b82003-02-18 22:55:36 +00004253 case TARGET_NR_symlink:
pbrook53a59602006-03-25 19:31:22 +00004254 {
4255 void *p2;
4256 p = lock_user_string(arg1);
4257 p2 = lock_user_string(arg2);
bellard579a97f2007-11-11 14:26:47 +00004258 if (!p || !p2)
4259 ret = -TARGET_EFAULT;
4260 else
4261 ret = get_errno(symlink(p, p2));
pbrook53a59602006-03-25 19:31:22 +00004262 unlock_user(p2, arg2, 0);
4263 unlock_user(p, arg1, 0);
4264 }
bellard31e31b82003-02-18 22:55:36 +00004265 break;
thsf0b62432007-09-24 09:25:40 +00004266#if defined(TARGET_NR_symlinkat) && defined(__NR_symlinkat)
4267 case TARGET_NR_symlinkat:
thsf0b62432007-09-24 09:25:40 +00004268 {
bellard579a97f2007-11-11 14:26:47 +00004269 void *p2;
thsf0b62432007-09-24 09:25:40 +00004270 p = lock_user_string(arg1);
4271 p2 = lock_user_string(arg3);
bellard579a97f2007-11-11 14:26:47 +00004272 if (!p || !p2)
ths0da46a62007-10-20 20:23:07 +00004273 ret = -TARGET_EFAULT;
thsf0b62432007-09-24 09:25:40 +00004274 else
4275 ret = get_errno(sys_symlinkat(p, arg2, p2));
bellard579a97f2007-11-11 14:26:47 +00004276 unlock_user(p2, arg3, 0);
4277 unlock_user(p, arg1, 0);
thsf0b62432007-09-24 09:25:40 +00004278 }
4279 break;
4280#endif
bellardebc05482003-09-30 21:08:41 +00004281#ifdef TARGET_NR_oldlstat
bellard31e31b82003-02-18 22:55:36 +00004282 case TARGET_NR_oldlstat:
4283 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004284#endif
bellard31e31b82003-02-18 22:55:36 +00004285 case TARGET_NR_readlink:
pbrook53a59602006-03-25 19:31:22 +00004286 {
4287 void *p2;
4288 p = lock_user_string(arg1);
bellard579a97f2007-11-11 14:26:47 +00004289 p2 = lock_user(VERIFY_WRITE, arg2, arg3, 0);
4290 if (!p || !p2)
4291 ret = -TARGET_EFAULT;
4292 else
4293 ret = get_errno(readlink(path(p), p2, arg3));
pbrook53a59602006-03-25 19:31:22 +00004294 unlock_user(p2, arg2, ret);
4295 unlock_user(p, arg1, 0);
4296 }
bellard31e31b82003-02-18 22:55:36 +00004297 break;
ths5e0ccb12007-09-24 09:26:10 +00004298#if defined(TARGET_NR_readlinkat) && defined(__NR_readlinkat)
4299 case TARGET_NR_readlinkat:
ths5e0ccb12007-09-24 09:26:10 +00004300 {
bellard579a97f2007-11-11 14:26:47 +00004301 void *p2;
ths5e0ccb12007-09-24 09:26:10 +00004302 p = lock_user_string(arg2);
bellard579a97f2007-11-11 14:26:47 +00004303 p2 = lock_user(VERIFY_WRITE, arg3, arg4, 0);
4304 if (!p || !p2)
ths0da46a62007-10-20 20:23:07 +00004305 ret = -TARGET_EFAULT;
ths5e0ccb12007-09-24 09:26:10 +00004306 else
4307 ret = get_errno(sys_readlinkat(arg1, path(p), p2, arg4));
bellard579a97f2007-11-11 14:26:47 +00004308 unlock_user(p2, arg3, ret);
4309 unlock_user(p, arg2, 0);
ths5e0ccb12007-09-24 09:26:10 +00004310 }
4311 break;
4312#endif
thse5febef2007-04-01 18:31:35 +00004313#ifdef TARGET_NR_uselib
bellard31e31b82003-02-18 22:55:36 +00004314 case TARGET_NR_uselib:
4315 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00004316#endif
4317#ifdef TARGET_NR_swapon
bellard31e31b82003-02-18 22:55:36 +00004318 case TARGET_NR_swapon:
bellard579a97f2007-11-11 14:26:47 +00004319 if (!(p = lock_user_string(arg1)))
4320 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004321 ret = get_errno(swapon(p, arg2));
4322 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004323 break;
thse5febef2007-04-01 18:31:35 +00004324#endif
bellard31e31b82003-02-18 22:55:36 +00004325 case TARGET_NR_reboot:
4326 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00004327#ifdef TARGET_NR_readdir
bellard31e31b82003-02-18 22:55:36 +00004328 case TARGET_NR_readdir:
4329 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00004330#endif
4331#ifdef TARGET_NR_mmap
bellard31e31b82003-02-18 22:55:36 +00004332 case TARGET_NR_mmap:
bellardd2fd1af2007-11-14 18:08:56 +00004333#if (defined(TARGET_I386) && defined(TARGET_ABI32)) || defined(TARGET_ARM) || defined(TARGET_M68K) || defined(TARGET_CRIS)
bellard31e31b82003-02-18 22:55:36 +00004334 {
blueswir1992f48a2007-10-14 16:27:31 +00004335 abi_ulong *v;
4336 abi_ulong v1, v2, v3, v4, v5, v6;
bellard579a97f2007-11-11 14:26:47 +00004337 if (!(v = lock_user(VERIFY_READ, arg1, 6 * sizeof(abi_ulong), 1)))
4338 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004339 v1 = tswapl(v[0]);
4340 v2 = tswapl(v[1]);
4341 v3 = tswapl(v[2]);
4342 v4 = tswapl(v[3]);
4343 v5 = tswapl(v[4]);
4344 v6 = tswapl(v[5]);
4345 unlock_user(v, arg1, 0);
ths5fafdf22007-09-16 21:08:06 +00004346 ret = get_errno(target_mmap(v1, v2, v3,
bellard5286db72003-06-05 00:57:30 +00004347 target_to_host_bitmask(v4, mmap_flags_tbl),
4348 v5, v6));
bellard31e31b82003-02-18 22:55:36 +00004349 }
bellard31e31b82003-02-18 22:55:36 +00004350#else
ths5fafdf22007-09-16 21:08:06 +00004351 ret = get_errno(target_mmap(arg1, arg2, arg3,
4352 target_to_host_bitmask(arg4, mmap_flags_tbl),
bellard6fb883e2003-07-09 17:12:39 +00004353 arg5,
4354 arg6));
bellard31e31b82003-02-18 22:55:36 +00004355#endif
bellard6fb883e2003-07-09 17:12:39 +00004356 break;
thse5febef2007-04-01 18:31:35 +00004357#endif
bellarda315a142005-01-30 22:59:18 +00004358#ifdef TARGET_NR_mmap2
bellard6fb883e2003-07-09 17:12:39 +00004359 case TARGET_NR_mmap2:
pbrookbb7ec042008-03-25 22:28:25 +00004360#ifndef MMAP_SHIFT
bellardc573ff62004-01-04 15:51:36 +00004361#define MMAP_SHIFT 12
bellardc573ff62004-01-04 15:51:36 +00004362#endif
ths5fafdf22007-09-16 21:08:06 +00004363 ret = get_errno(target_mmap(arg1, arg2, arg3,
4364 target_to_host_bitmask(arg4, mmap_flags_tbl),
bellard5286db72003-06-05 00:57:30 +00004365 arg5,
bellardc573ff62004-01-04 15:51:36 +00004366 arg6 << MMAP_SHIFT));
bellard31e31b82003-02-18 22:55:36 +00004367 break;
bellarda315a142005-01-30 22:59:18 +00004368#endif
bellard31e31b82003-02-18 22:55:36 +00004369 case TARGET_NR_munmap:
bellard54936002003-05-13 00:25:15 +00004370 ret = get_errno(target_munmap(arg1, arg2));
bellard31e31b82003-02-18 22:55:36 +00004371 break;
bellard9de5e442003-03-23 16:49:39 +00004372 case TARGET_NR_mprotect:
bellard54936002003-05-13 00:25:15 +00004373 ret = get_errno(target_mprotect(arg1, arg2, arg3));
bellard9de5e442003-03-23 16:49:39 +00004374 break;
thse5febef2007-04-01 18:31:35 +00004375#ifdef TARGET_NR_mremap
bellard9de5e442003-03-23 16:49:39 +00004376 case TARGET_NR_mremap:
bellard54936002003-05-13 00:25:15 +00004377 ret = get_errno(target_mremap(arg1, arg2, arg3, arg4, arg5));
bellard9de5e442003-03-23 16:49:39 +00004378 break;
thse5febef2007-04-01 18:31:35 +00004379#endif
pbrook53a59602006-03-25 19:31:22 +00004380 /* ??? msync/mlock/munlock are broken for softmmu. */
thse5febef2007-04-01 18:31:35 +00004381#ifdef TARGET_NR_msync
bellard9de5e442003-03-23 16:49:39 +00004382 case TARGET_NR_msync:
pbrook53a59602006-03-25 19:31:22 +00004383 ret = get_errno(msync(g2h(arg1), arg2, arg3));
bellard9de5e442003-03-23 16:49:39 +00004384 break;
thse5febef2007-04-01 18:31:35 +00004385#endif
4386#ifdef TARGET_NR_mlock
bellard9de5e442003-03-23 16:49:39 +00004387 case TARGET_NR_mlock:
pbrook53a59602006-03-25 19:31:22 +00004388 ret = get_errno(mlock(g2h(arg1), arg2));
bellard9de5e442003-03-23 16:49:39 +00004389 break;
thse5febef2007-04-01 18:31:35 +00004390#endif
4391#ifdef TARGET_NR_munlock
bellard9de5e442003-03-23 16:49:39 +00004392 case TARGET_NR_munlock:
pbrook53a59602006-03-25 19:31:22 +00004393 ret = get_errno(munlock(g2h(arg1), arg2));
bellard9de5e442003-03-23 16:49:39 +00004394 break;
thse5febef2007-04-01 18:31:35 +00004395#endif
4396#ifdef TARGET_NR_mlockall
bellard9de5e442003-03-23 16:49:39 +00004397 case TARGET_NR_mlockall:
4398 ret = get_errno(mlockall(arg1));
4399 break;
thse5febef2007-04-01 18:31:35 +00004400#endif
4401#ifdef TARGET_NR_munlockall
bellard9de5e442003-03-23 16:49:39 +00004402 case TARGET_NR_munlockall:
4403 ret = get_errno(munlockall());
4404 break;
thse5febef2007-04-01 18:31:35 +00004405#endif
bellard31e31b82003-02-18 22:55:36 +00004406 case TARGET_NR_truncate:
bellard579a97f2007-11-11 14:26:47 +00004407 if (!(p = lock_user_string(arg1)))
4408 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004409 ret = get_errno(truncate(p, arg2));
4410 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004411 break;
4412 case TARGET_NR_ftruncate:
4413 ret = get_errno(ftruncate(arg1, arg2));
4414 break;
4415 case TARGET_NR_fchmod:
4416 ret = get_errno(fchmod(arg1, arg2));
4417 break;
ths814d7972007-09-24 09:26:51 +00004418#if defined(TARGET_NR_fchmodat) && defined(__NR_fchmodat)
4419 case TARGET_NR_fchmodat:
bellard579a97f2007-11-11 14:26:47 +00004420 if (!(p = lock_user_string(arg2)))
4421 goto efault;
4422 ret = get_errno(sys_fchmodat(arg1, p, arg3, arg4));
4423 unlock_user(p, arg2, 0);
ths814d7972007-09-24 09:26:51 +00004424 break;
4425#endif
bellard31e31b82003-02-18 22:55:36 +00004426 case TARGET_NR_getpriority:
thsc6cda172007-10-09 03:42:34 +00004427 /* libc does special remapping of the return value of
4428 * sys_getpriority() so it's just easiest to call
4429 * sys_getpriority() directly rather than through libc. */
4430 ret = sys_getpriority(arg1, arg2);
bellard31e31b82003-02-18 22:55:36 +00004431 break;
4432 case TARGET_NR_setpriority:
4433 ret = get_errno(setpriority(arg1, arg2, arg3));
4434 break;
bellardebc05482003-09-30 21:08:41 +00004435#ifdef TARGET_NR_profil
bellard31e31b82003-02-18 22:55:36 +00004436 case TARGET_NR_profil:
4437 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004438#endif
bellard31e31b82003-02-18 22:55:36 +00004439 case TARGET_NR_statfs:
bellard579a97f2007-11-11 14:26:47 +00004440 if (!(p = lock_user_string(arg1)))
4441 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004442 ret = get_errno(statfs(path(p), &stfs));
4443 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004444 convert_statfs:
4445 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00004446 struct target_statfs *target_stfs;
ths3b46e622007-09-17 08:09:54 +00004447
bellard579a97f2007-11-11 14:26:47 +00004448 if (!lock_user_struct(VERIFY_WRITE, target_stfs, arg2, 0))
4449 goto efault;
4450 __put_user(stfs.f_type, &target_stfs->f_type);
4451 __put_user(stfs.f_bsize, &target_stfs->f_bsize);
4452 __put_user(stfs.f_blocks, &target_stfs->f_blocks);
4453 __put_user(stfs.f_bfree, &target_stfs->f_bfree);
4454 __put_user(stfs.f_bavail, &target_stfs->f_bavail);
4455 __put_user(stfs.f_files, &target_stfs->f_files);
4456 __put_user(stfs.f_ffree, &target_stfs->f_ffree);
4457 __put_user(stfs.f_fsid.__val[0], &target_stfs->f_fsid.val[0]);
4458 __put_user(stfs.f_fsid.__val[1], &target_stfs->f_fsid.val[1]);
4459 __put_user(stfs.f_namelen, &target_stfs->f_namelen);
pbrook53a59602006-03-25 19:31:22 +00004460 unlock_user_struct(target_stfs, arg2, 1);
bellard31e31b82003-02-18 22:55:36 +00004461 }
4462 break;
4463 case TARGET_NR_fstatfs:
bellard56c8f682005-11-28 22:28:41 +00004464 ret = get_errno(fstatfs(arg1, &stfs));
bellard31e31b82003-02-18 22:55:36 +00004465 goto convert_statfs;
bellard56c8f682005-11-28 22:28:41 +00004466#ifdef TARGET_NR_statfs64
4467 case TARGET_NR_statfs64:
bellard579a97f2007-11-11 14:26:47 +00004468 if (!(p = lock_user_string(arg1)))
4469 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004470 ret = get_errno(statfs(path(p), &stfs));
4471 unlock_user(p, arg1, 0);
bellard56c8f682005-11-28 22:28:41 +00004472 convert_statfs64:
4473 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00004474 struct target_statfs64 *target_stfs;
ths3b46e622007-09-17 08:09:54 +00004475
bellard579a97f2007-11-11 14:26:47 +00004476 if (!lock_user_struct(VERIFY_WRITE, target_stfs, arg3, 0))
4477 goto efault;
4478 __put_user(stfs.f_type, &target_stfs->f_type);
4479 __put_user(stfs.f_bsize, &target_stfs->f_bsize);
4480 __put_user(stfs.f_blocks, &target_stfs->f_blocks);
4481 __put_user(stfs.f_bfree, &target_stfs->f_bfree);
4482 __put_user(stfs.f_bavail, &target_stfs->f_bavail);
4483 __put_user(stfs.f_files, &target_stfs->f_files);
4484 __put_user(stfs.f_ffree, &target_stfs->f_ffree);
4485 __put_user(stfs.f_fsid.__val[0], &target_stfs->f_fsid.val[0]);
4486 __put_user(stfs.f_fsid.__val[1], &target_stfs->f_fsid.val[1]);
4487 __put_user(stfs.f_namelen, &target_stfs->f_namelen);
4488 unlock_user_struct(target_stfs, arg3, 1);
bellard56c8f682005-11-28 22:28:41 +00004489 }
4490 break;
4491 case TARGET_NR_fstatfs64:
4492 ret = get_errno(fstatfs(arg1, &stfs));
4493 goto convert_statfs64;
4494#endif
bellardebc05482003-09-30 21:08:41 +00004495#ifdef TARGET_NR_ioperm
bellard31e31b82003-02-18 22:55:36 +00004496 case TARGET_NR_ioperm:
4497 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004498#endif
thse5febef2007-04-01 18:31:35 +00004499#ifdef TARGET_NR_socketcall
bellard31e31b82003-02-18 22:55:36 +00004500 case TARGET_NR_socketcall:
pbrook53a59602006-03-25 19:31:22 +00004501 ret = do_socketcall(arg1, arg2);
bellard31e31b82003-02-18 22:55:36 +00004502 break;
thse5febef2007-04-01 18:31:35 +00004503#endif
bellard3532fa72006-06-24 15:06:03 +00004504#ifdef TARGET_NR_accept
4505 case TARGET_NR_accept:
pbrook1be9e1d2006-11-19 15:26:04 +00004506 ret = do_accept(arg1, arg2, arg3);
bellard3532fa72006-06-24 15:06:03 +00004507 break;
4508#endif
4509#ifdef TARGET_NR_bind
4510 case TARGET_NR_bind:
4511 ret = do_bind(arg1, arg2, arg3);
4512 break;
4513#endif
4514#ifdef TARGET_NR_connect
4515 case TARGET_NR_connect:
4516 ret = do_connect(arg1, arg2, arg3);
4517 break;
4518#endif
4519#ifdef TARGET_NR_getpeername
4520 case TARGET_NR_getpeername:
pbrook1be9e1d2006-11-19 15:26:04 +00004521 ret = do_getpeername(arg1, arg2, arg3);
bellard3532fa72006-06-24 15:06:03 +00004522 break;
4523#endif
4524#ifdef TARGET_NR_getsockname
4525 case TARGET_NR_getsockname:
pbrook1be9e1d2006-11-19 15:26:04 +00004526 ret = do_getsockname(arg1, arg2, arg3);
bellard3532fa72006-06-24 15:06:03 +00004527 break;
4528#endif
4529#ifdef TARGET_NR_getsockopt
4530 case TARGET_NR_getsockopt:
4531 ret = do_getsockopt(arg1, arg2, arg3, arg4, arg5);
4532 break;
4533#endif
4534#ifdef TARGET_NR_listen
4535 case TARGET_NR_listen:
pbrook1be9e1d2006-11-19 15:26:04 +00004536 ret = get_errno(listen(arg1, arg2));
bellard3532fa72006-06-24 15:06:03 +00004537 break;
4538#endif
4539#ifdef TARGET_NR_recv
4540 case TARGET_NR_recv:
pbrook214201b2007-03-17 01:27:24 +00004541 ret = do_recvfrom(arg1, arg2, arg3, arg4, 0, 0);
bellard3532fa72006-06-24 15:06:03 +00004542 break;
4543#endif
4544#ifdef TARGET_NR_recvfrom
4545 case TARGET_NR_recvfrom:
pbrook214201b2007-03-17 01:27:24 +00004546 ret = do_recvfrom(arg1, arg2, arg3, arg4, arg5, arg6);
bellard3532fa72006-06-24 15:06:03 +00004547 break;
4548#endif
4549#ifdef TARGET_NR_recvmsg
4550 case TARGET_NR_recvmsg:
4551 ret = do_sendrecvmsg(arg1, arg2, arg3, 0);
4552 break;
4553#endif
4554#ifdef TARGET_NR_send
4555 case TARGET_NR_send:
pbrook1be9e1d2006-11-19 15:26:04 +00004556 ret = do_sendto(arg1, arg2, arg3, arg4, 0, 0);
bellard3532fa72006-06-24 15:06:03 +00004557 break;
4558#endif
4559#ifdef TARGET_NR_sendmsg
4560 case TARGET_NR_sendmsg:
4561 ret = do_sendrecvmsg(arg1, arg2, arg3, 1);
4562 break;
4563#endif
4564#ifdef TARGET_NR_sendto
4565 case TARGET_NR_sendto:
pbrook1be9e1d2006-11-19 15:26:04 +00004566 ret = do_sendto(arg1, arg2, arg3, arg4, arg5, arg6);
bellard3532fa72006-06-24 15:06:03 +00004567 break;
4568#endif
4569#ifdef TARGET_NR_shutdown
4570 case TARGET_NR_shutdown:
pbrook1be9e1d2006-11-19 15:26:04 +00004571 ret = get_errno(shutdown(arg1, arg2));
bellard3532fa72006-06-24 15:06:03 +00004572 break;
4573#endif
4574#ifdef TARGET_NR_socket
4575 case TARGET_NR_socket:
4576 ret = do_socket(arg1, arg2, arg3);
4577 break;
4578#endif
4579#ifdef TARGET_NR_socketpair
4580 case TARGET_NR_socketpair:
pbrook1be9e1d2006-11-19 15:26:04 +00004581 ret = do_socketpair(arg1, arg2, arg3, arg4);
bellard3532fa72006-06-24 15:06:03 +00004582 break;
4583#endif
4584#ifdef TARGET_NR_setsockopt
4585 case TARGET_NR_setsockopt:
4586 ret = do_setsockopt(arg1, arg2, arg3, arg4, (socklen_t) arg5);
4587 break;
4588#endif
ths7494b0f2007-02-11 18:26:53 +00004589
bellard31e31b82003-02-18 22:55:36 +00004590 case TARGET_NR_syslog:
bellard579a97f2007-11-11 14:26:47 +00004591 if (!(p = lock_user_string(arg2)))
4592 goto efault;
thse5574482007-02-11 20:03:13 +00004593 ret = get_errno(sys_syslog((int)arg1, p, (int)arg3));
4594 unlock_user(p, arg2, 0);
ths7494b0f2007-02-11 18:26:53 +00004595 break;
4596
bellard31e31b82003-02-18 22:55:36 +00004597 case TARGET_NR_setitimer:
bellard66fb9762003-03-23 01:06:05 +00004598 {
bellard66fb9762003-03-23 01:06:05 +00004599 struct itimerval value, ovalue, *pvalue;
4600
pbrook53a59602006-03-25 19:31:22 +00004601 if (arg2) {
bellard66fb9762003-03-23 01:06:05 +00004602 pvalue = &value;
ths788f5ec2007-12-09 02:37:05 +00004603 if (copy_from_user_timeval(&pvalue->it_interval, arg2)
4604 || copy_from_user_timeval(&pvalue->it_value,
4605 arg2 + sizeof(struct target_timeval)))
4606 goto efault;
bellard66fb9762003-03-23 01:06:05 +00004607 } else {
4608 pvalue = NULL;
4609 }
4610 ret = get_errno(setitimer(arg1, pvalue, &ovalue));
pbrook53a59602006-03-25 19:31:22 +00004611 if (!is_error(ret) && arg3) {
ths788f5ec2007-12-09 02:37:05 +00004612 if (copy_to_user_timeval(arg3,
4613 &ovalue.it_interval)
4614 || copy_to_user_timeval(arg3 + sizeof(struct target_timeval),
4615 &ovalue.it_value))
4616 goto efault;
bellard66fb9762003-03-23 01:06:05 +00004617 }
4618 }
4619 break;
bellard31e31b82003-02-18 22:55:36 +00004620 case TARGET_NR_getitimer:
bellard66fb9762003-03-23 01:06:05 +00004621 {
bellard66fb9762003-03-23 01:06:05 +00004622 struct itimerval value;
ths3b46e622007-09-17 08:09:54 +00004623
bellard66fb9762003-03-23 01:06:05 +00004624 ret = get_errno(getitimer(arg1, &value));
pbrook53a59602006-03-25 19:31:22 +00004625 if (!is_error(ret) && arg2) {
ths788f5ec2007-12-09 02:37:05 +00004626 if (copy_to_user_timeval(arg2,
4627 &value.it_interval)
4628 || copy_to_user_timeval(arg2 + sizeof(struct target_timeval),
4629 &value.it_value))
4630 goto efault;
bellard66fb9762003-03-23 01:06:05 +00004631 }
4632 }
4633 break;
bellard31e31b82003-02-18 22:55:36 +00004634 case TARGET_NR_stat:
bellard579a97f2007-11-11 14:26:47 +00004635 if (!(p = lock_user_string(arg1)))
4636 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004637 ret = get_errno(stat(path(p), &st));
4638 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004639 goto do_stat;
4640 case TARGET_NR_lstat:
bellard579a97f2007-11-11 14:26:47 +00004641 if (!(p = lock_user_string(arg1)))
4642 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004643 ret = get_errno(lstat(path(p), &st));
4644 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004645 goto do_stat;
4646 case TARGET_NR_fstat:
4647 {
4648 ret = get_errno(fstat(arg1, &st));
4649 do_stat:
4650 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00004651 struct target_stat *target_st;
thse3584652007-06-01 11:49:38 +00004652
bellard579a97f2007-11-11 14:26:47 +00004653 if (!lock_user_struct(VERIFY_WRITE, target_st, arg2, 0))
4654 goto efault;
bellardd2fd1af2007-11-14 18:08:56 +00004655 __put_user(st.st_dev, &target_st->st_dev);
4656 __put_user(st.st_ino, &target_st->st_ino);
4657 __put_user(st.st_mode, &target_st->st_mode);
4658 __put_user(st.st_uid, &target_st->st_uid);
4659 __put_user(st.st_gid, &target_st->st_gid);
4660 __put_user(st.st_nlink, &target_st->st_nlink);
4661 __put_user(st.st_rdev, &target_st->st_rdev);
4662 __put_user(st.st_size, &target_st->st_size);
4663 __put_user(st.st_blksize, &target_st->st_blksize);
4664 __put_user(st.st_blocks, &target_st->st_blocks);
4665 __put_user(st.st_atime, &target_st->target_st_atime);
4666 __put_user(st.st_mtime, &target_st->target_st_mtime);
4667 __put_user(st.st_ctime, &target_st->target_st_ctime);
pbrook53a59602006-03-25 19:31:22 +00004668 unlock_user_struct(target_st, arg2, 1);
bellard31e31b82003-02-18 22:55:36 +00004669 }
4670 }
4671 break;
bellardebc05482003-09-30 21:08:41 +00004672#ifdef TARGET_NR_olduname
bellard31e31b82003-02-18 22:55:36 +00004673 case TARGET_NR_olduname:
4674 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004675#endif
4676#ifdef TARGET_NR_iopl
bellard31e31b82003-02-18 22:55:36 +00004677 case TARGET_NR_iopl:
4678 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004679#endif
bellard31e31b82003-02-18 22:55:36 +00004680 case TARGET_NR_vhangup:
4681 ret = get_errno(vhangup());
4682 break;
bellardebc05482003-09-30 21:08:41 +00004683#ifdef TARGET_NR_idle
bellard31e31b82003-02-18 22:55:36 +00004684 case TARGET_NR_idle:
4685 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004686#endif
bellard42ad6ae2005-01-03 22:48:11 +00004687#ifdef TARGET_NR_syscall
4688 case TARGET_NR_syscall:
4689 ret = do_syscall(cpu_env,arg1 & 0xffff,arg2,arg3,arg4,arg5,arg6,0);
4690 break;
4691#endif
bellard31e31b82003-02-18 22:55:36 +00004692 case TARGET_NR_wait4:
4693 {
4694 int status;
blueswir1992f48a2007-10-14 16:27:31 +00004695 abi_long status_ptr = arg2;
bellard31e31b82003-02-18 22:55:36 +00004696 struct rusage rusage, *rusage_ptr;
blueswir1992f48a2007-10-14 16:27:31 +00004697 abi_ulong target_rusage = arg4;
bellard31e31b82003-02-18 22:55:36 +00004698 if (target_rusage)
4699 rusage_ptr = &rusage;
4700 else
4701 rusage_ptr = NULL;
4702 ret = get_errno(wait4(arg1, &status, arg3, rusage_ptr));
4703 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +00004704 if (status_ptr) {
4705 if (put_user_s32(status, status_ptr))
4706 goto efault;
bellard31e31b82003-02-18 22:55:36 +00004707 }
bellard2f619692007-11-16 10:46:05 +00004708 if (target_rusage)
4709 host_to_target_rusage(target_rusage, &rusage);
bellard31e31b82003-02-18 22:55:36 +00004710 }
4711 }
4712 break;
thse5febef2007-04-01 18:31:35 +00004713#ifdef TARGET_NR_swapoff
bellard31e31b82003-02-18 22:55:36 +00004714 case TARGET_NR_swapoff:
bellard579a97f2007-11-11 14:26:47 +00004715 if (!(p = lock_user_string(arg1)))
4716 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004717 ret = get_errno(swapoff(p));
4718 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004719 break;
thse5febef2007-04-01 18:31:35 +00004720#endif
bellard31e31b82003-02-18 22:55:36 +00004721 case TARGET_NR_sysinfo:
bellarda5448a72004-06-19 16:59:03 +00004722 {
pbrook53a59602006-03-25 19:31:22 +00004723 struct target_sysinfo *target_value;
bellarda5448a72004-06-19 16:59:03 +00004724 struct sysinfo value;
4725 ret = get_errno(sysinfo(&value));
pbrook53a59602006-03-25 19:31:22 +00004726 if (!is_error(ret) && arg1)
bellarda5448a72004-06-19 16:59:03 +00004727 {
bellard579a97f2007-11-11 14:26:47 +00004728 if (!lock_user_struct(VERIFY_WRITE, target_value, arg1, 0))
4729 goto efault;
bellarda5448a72004-06-19 16:59:03 +00004730 __put_user(value.uptime, &target_value->uptime);
4731 __put_user(value.loads[0], &target_value->loads[0]);
4732 __put_user(value.loads[1], &target_value->loads[1]);
4733 __put_user(value.loads[2], &target_value->loads[2]);
4734 __put_user(value.totalram, &target_value->totalram);
4735 __put_user(value.freeram, &target_value->freeram);
4736 __put_user(value.sharedram, &target_value->sharedram);
4737 __put_user(value.bufferram, &target_value->bufferram);
4738 __put_user(value.totalswap, &target_value->totalswap);
4739 __put_user(value.freeswap, &target_value->freeswap);
4740 __put_user(value.procs, &target_value->procs);
4741 __put_user(value.totalhigh, &target_value->totalhigh);
4742 __put_user(value.freehigh, &target_value->freehigh);
4743 __put_user(value.mem_unit, &target_value->mem_unit);
pbrook53a59602006-03-25 19:31:22 +00004744 unlock_user_struct(target_value, arg1, 1);
bellarda5448a72004-06-19 16:59:03 +00004745 }
4746 }
4747 break;
thse5febef2007-04-01 18:31:35 +00004748#ifdef TARGET_NR_ipc
bellard31e31b82003-02-18 22:55:36 +00004749 case TARGET_NR_ipc:
bellard8853f862004-02-22 14:57:26 +00004750 ret = do_ipc(arg1, arg2, arg3, arg4, arg5, arg6);
4751 break;
thse5febef2007-04-01 18:31:35 +00004752#endif
bellard31e31b82003-02-18 22:55:36 +00004753 case TARGET_NR_fsync:
4754 ret = get_errno(fsync(arg1));
4755 break;
bellard31e31b82003-02-18 22:55:36 +00004756 case TARGET_NR_clone:
aurel320b6d3ae2008-09-15 07:43:43 +00004757#if defined(TARGET_SH4)
4758 ret = get_errno(do_fork(cpu_env, arg1, arg2, arg3, arg5, arg4));
4759#else
pbrookd865bab2008-06-07 22:12:17 +00004760 ret = get_errno(do_fork(cpu_env, arg1, arg2, arg3, arg4, arg5));
aurel320b6d3ae2008-09-15 07:43:43 +00004761#endif
bellard1b6b0292003-03-22 17:31:38 +00004762 break;
bellardec86b0f2003-04-11 00:15:04 +00004763#ifdef __NR_exit_group
4764 /* new thread calls */
4765 case TARGET_NR_exit_group:
bellarde9009672005-04-26 20:42:36 +00004766 gdb_exit(cpu_env, arg1);
bellardec86b0f2003-04-11 00:15:04 +00004767 ret = get_errno(exit_group(arg1));
4768 break;
4769#endif
bellard31e31b82003-02-18 22:55:36 +00004770 case TARGET_NR_setdomainname:
bellard579a97f2007-11-11 14:26:47 +00004771 if (!(p = lock_user_string(arg1)))
4772 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004773 ret = get_errno(setdomainname(p, arg2));
4774 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004775 break;
4776 case TARGET_NR_uname:
4777 /* no need to transcode because we use the linux syscall */
bellard29e619b2004-09-13 21:41:04 +00004778 {
4779 struct new_utsname * buf;
ths3b46e622007-09-17 08:09:54 +00004780
bellard579a97f2007-11-11 14:26:47 +00004781 if (!lock_user_struct(VERIFY_WRITE, buf, arg1, 0))
4782 goto efault;
bellard29e619b2004-09-13 21:41:04 +00004783 ret = get_errno(sys_uname(buf));
4784 if (!is_error(ret)) {
4785 /* Overrite the native machine name with whatever is being
4786 emulated. */
4787 strcpy (buf->machine, UNAME_MACHINE);
pbrookc5937222006-05-14 11:30:38 +00004788 /* Allow the user to override the reported release. */
4789 if (qemu_uname_release && *qemu_uname_release)
4790 strcpy (buf->release, qemu_uname_release);
bellard29e619b2004-09-13 21:41:04 +00004791 }
pbrook53a59602006-03-25 19:31:22 +00004792 unlock_user_struct(buf, arg1, 1);
bellard29e619b2004-09-13 21:41:04 +00004793 }
bellard31e31b82003-02-18 22:55:36 +00004794 break;
bellard6dbad632003-03-16 18:05:05 +00004795#ifdef TARGET_I386
bellard31e31b82003-02-18 22:55:36 +00004796 case TARGET_NR_modify_ldt:
bellard03acab62007-11-11 14:57:14 +00004797 ret = do_modify_ldt(cpu_env, arg1, arg2, arg3);
bellard5cd43932003-03-29 16:54:36 +00004798 break;
j_mayer84409dd2007-04-06 08:56:50 +00004799#if !defined(TARGET_X86_64)
bellard5cd43932003-03-29 16:54:36 +00004800 case TARGET_NR_vm86old:
4801 goto unimplemented;
4802 case TARGET_NR_vm86:
pbrook53a59602006-03-25 19:31:22 +00004803 ret = do_vm86(cpu_env, arg1, arg2);
bellard6dbad632003-03-16 18:05:05 +00004804 break;
4805#endif
j_mayer84409dd2007-04-06 08:56:50 +00004806#endif
bellard31e31b82003-02-18 22:55:36 +00004807 case TARGET_NR_adjtimex:
4808 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00004809#ifdef TARGET_NR_create_module
bellard31e31b82003-02-18 22:55:36 +00004810 case TARGET_NR_create_module:
thse5febef2007-04-01 18:31:35 +00004811#endif
bellard31e31b82003-02-18 22:55:36 +00004812 case TARGET_NR_init_module:
4813 case TARGET_NR_delete_module:
thse5febef2007-04-01 18:31:35 +00004814#ifdef TARGET_NR_get_kernel_syms
bellard31e31b82003-02-18 22:55:36 +00004815 case TARGET_NR_get_kernel_syms:
thse5febef2007-04-01 18:31:35 +00004816#endif
bellard31e31b82003-02-18 22:55:36 +00004817 goto unimplemented;
4818 case TARGET_NR_quotactl:
4819 goto unimplemented;
4820 case TARGET_NR_getpgid:
4821 ret = get_errno(getpgid(arg1));
4822 break;
4823 case TARGET_NR_fchdir:
4824 ret = get_errno(fchdir(arg1));
4825 break;
j_mayer84409dd2007-04-06 08:56:50 +00004826#ifdef TARGET_NR_bdflush /* not on x86_64 */
bellard31e31b82003-02-18 22:55:36 +00004827 case TARGET_NR_bdflush:
4828 goto unimplemented;
j_mayer84409dd2007-04-06 08:56:50 +00004829#endif
thse5febef2007-04-01 18:31:35 +00004830#ifdef TARGET_NR_sysfs
bellard31e31b82003-02-18 22:55:36 +00004831 case TARGET_NR_sysfs:
4832 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00004833#endif
bellard31e31b82003-02-18 22:55:36 +00004834 case TARGET_NR_personality:
bellard1b6b0292003-03-22 17:31:38 +00004835 ret = get_errno(personality(arg1));
bellard31e31b82003-02-18 22:55:36 +00004836 break;
thse5febef2007-04-01 18:31:35 +00004837#ifdef TARGET_NR_afs_syscall
bellard31e31b82003-02-18 22:55:36 +00004838 case TARGET_NR_afs_syscall:
4839 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00004840#endif
j_mayer7a3148a2007-04-05 07:13:51 +00004841#ifdef TARGET_NR__llseek /* Not on alpha */
bellard31e31b82003-02-18 22:55:36 +00004842 case TARGET_NR__llseek:
4843 {
bellard4f2ac232004-04-26 19:44:02 +00004844#if defined (__x86_64__)
4845 ret = get_errno(lseek(arg1, ((uint64_t )arg2 << 32) | arg3, arg5));
bellard2f619692007-11-16 10:46:05 +00004846 if (put_user_s64(ret, arg4))
4847 goto efault;
bellard4f2ac232004-04-26 19:44:02 +00004848#else
bellard31e31b82003-02-18 22:55:36 +00004849 int64_t res;
4850 ret = get_errno(_llseek(arg1, arg2, arg3, &res, arg5));
bellard2f619692007-11-16 10:46:05 +00004851 if (put_user_s64(res, arg4))
4852 goto efault;
bellard4f2ac232004-04-26 19:44:02 +00004853#endif
bellard31e31b82003-02-18 22:55:36 +00004854 }
4855 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004856#endif
bellard31e31b82003-02-18 22:55:36 +00004857 case TARGET_NR_getdents:
blueswir1992f48a2007-10-14 16:27:31 +00004858#if TARGET_ABI_BITS != 32
pbrook53a59602006-03-25 19:31:22 +00004859 goto unimplemented;
blueswir1992f48a2007-10-14 16:27:31 +00004860#elif TARGET_ABI_BITS == 32 && HOST_LONG_BITS == 64
bellard4add45b2003-06-05 01:52:59 +00004861 {
pbrook53a59602006-03-25 19:31:22 +00004862 struct target_dirent *target_dirp;
bellard4add45b2003-06-05 01:52:59 +00004863 struct dirent *dirp;
blueswir1992f48a2007-10-14 16:27:31 +00004864 abi_long count = arg3;
bellard4add45b2003-06-05 01:52:59 +00004865
4866 dirp = malloc(count);
ths0da46a62007-10-20 20:23:07 +00004867 if (!dirp) {
bellard579a97f2007-11-11 14:26:47 +00004868 ret = -TARGET_ENOMEM;
ths0da46a62007-10-20 20:23:07 +00004869 goto fail;
4870 }
ths3b46e622007-09-17 08:09:54 +00004871
bellard4add45b2003-06-05 01:52:59 +00004872 ret = get_errno(sys_getdents(arg1, dirp, count));
4873 if (!is_error(ret)) {
4874 struct dirent *de;
4875 struct target_dirent *tde;
4876 int len = ret;
4877 int reclen, treclen;
4878 int count1, tnamelen;
4879
4880 count1 = 0;
4881 de = dirp;
bellard579a97f2007-11-11 14:26:47 +00004882 if (!(target_dirp = lock_user(VERIFY_WRITE, arg2, count, 0)))
4883 goto efault;
bellard4add45b2003-06-05 01:52:59 +00004884 tde = target_dirp;
4885 while (len > 0) {
4886 reclen = de->d_reclen;
blueswir1992f48a2007-10-14 16:27:31 +00004887 treclen = reclen - (2 * (sizeof(long) - sizeof(abi_long)));
bellard4add45b2003-06-05 01:52:59 +00004888 tde->d_reclen = tswap16(treclen);
4889 tde->d_ino = tswapl(de->d_ino);
4890 tde->d_off = tswapl(de->d_off);
blueswir1992f48a2007-10-14 16:27:31 +00004891 tnamelen = treclen - (2 * sizeof(abi_long) + 2);
bellard4add45b2003-06-05 01:52:59 +00004892 if (tnamelen > 256)
4893 tnamelen = 256;
bellard80a9d032005-01-03 23:31:27 +00004894 /* XXX: may not be correct */
bellard4add45b2003-06-05 01:52:59 +00004895 strncpy(tde->d_name, de->d_name, tnamelen);
4896 de = (struct dirent *)((char *)de + reclen);
4897 len -= reclen;
j_mayer1c5bf3b2007-04-14 12:17:59 +00004898 tde = (struct target_dirent *)((char *)tde + treclen);
bellard4add45b2003-06-05 01:52:59 +00004899 count1 += treclen;
4900 }
4901 ret = count1;
bellard579a97f2007-11-11 14:26:47 +00004902 unlock_user(target_dirp, arg2, ret);
bellard4add45b2003-06-05 01:52:59 +00004903 }
4904 free(dirp);
4905 }
4906#else
bellard31e31b82003-02-18 22:55:36 +00004907 {
pbrook53a59602006-03-25 19:31:22 +00004908 struct dirent *dirp;
blueswir1992f48a2007-10-14 16:27:31 +00004909 abi_long count = arg3;
bellarddab2ed92003-03-22 15:23:14 +00004910
bellard579a97f2007-11-11 14:26:47 +00004911 if (!(dirp = lock_user(VERIFY_WRITE, arg2, count, 0)))
4912 goto efault;
bellard72f03902003-02-18 23:33:18 +00004913 ret = get_errno(sys_getdents(arg1, dirp, count));
bellard31e31b82003-02-18 22:55:36 +00004914 if (!is_error(ret)) {
4915 struct dirent *de;
4916 int len = ret;
4917 int reclen;
4918 de = dirp;
4919 while (len > 0) {
bellard8083a3e2003-03-24 23:12:16 +00004920 reclen = de->d_reclen;
bellard31e31b82003-02-18 22:55:36 +00004921 if (reclen > len)
4922 break;
bellard8083a3e2003-03-24 23:12:16 +00004923 de->d_reclen = tswap16(reclen);
bellard31e31b82003-02-18 22:55:36 +00004924 tswapls(&de->d_ino);
4925 tswapls(&de->d_off);
4926 de = (struct dirent *)((char *)de + reclen);
4927 len -= reclen;
4928 }
4929 }
pbrook53a59602006-03-25 19:31:22 +00004930 unlock_user(dirp, arg2, ret);
bellard31e31b82003-02-18 22:55:36 +00004931 }
bellard4add45b2003-06-05 01:52:59 +00004932#endif
bellard31e31b82003-02-18 22:55:36 +00004933 break;
ths3ae43202007-09-16 21:39:48 +00004934#if defined(TARGET_NR_getdents64) && defined(__NR_getdents64)
bellarddab2ed92003-03-22 15:23:14 +00004935 case TARGET_NR_getdents64:
4936 {
pbrook53a59602006-03-25 19:31:22 +00004937 struct dirent64 *dirp;
blueswir1992f48a2007-10-14 16:27:31 +00004938 abi_long count = arg3;
bellard579a97f2007-11-11 14:26:47 +00004939 if (!(dirp = lock_user(VERIFY_WRITE, arg2, count, 0)))
4940 goto efault;
bellarddab2ed92003-03-22 15:23:14 +00004941 ret = get_errno(sys_getdents64(arg1, dirp, count));
4942 if (!is_error(ret)) {
4943 struct dirent64 *de;
4944 int len = ret;
4945 int reclen;
4946 de = dirp;
4947 while (len > 0) {
bellard8083a3e2003-03-24 23:12:16 +00004948 reclen = de->d_reclen;
bellarddab2ed92003-03-22 15:23:14 +00004949 if (reclen > len)
4950 break;
bellard8083a3e2003-03-24 23:12:16 +00004951 de->d_reclen = tswap16(reclen);
bellard8582a532007-11-11 23:11:36 +00004952 tswap64s((uint64_t *)&de->d_ino);
4953 tswap64s((uint64_t *)&de->d_off);
bellarddab2ed92003-03-22 15:23:14 +00004954 de = (struct dirent64 *)((char *)de + reclen);
4955 len -= reclen;
4956 }
4957 }
pbrook53a59602006-03-25 19:31:22 +00004958 unlock_user(dirp, arg2, ret);
bellarddab2ed92003-03-22 15:23:14 +00004959 }
4960 break;
bellarda541f292004-04-12 20:39:29 +00004961#endif /* TARGET_NR_getdents64 */
thse5febef2007-04-01 18:31:35 +00004962#ifdef TARGET_NR__newselect
bellard31e31b82003-02-18 22:55:36 +00004963 case TARGET_NR__newselect:
pbrook53a59602006-03-25 19:31:22 +00004964 ret = do_select(arg1, arg2, arg3, arg4, arg5);
bellard31e31b82003-02-18 22:55:36 +00004965 break;
thse5febef2007-04-01 18:31:35 +00004966#endif
4967#ifdef TARGET_NR_poll
bellard9de5e442003-03-23 16:49:39 +00004968 case TARGET_NR_poll:
4969 {
pbrook53a59602006-03-25 19:31:22 +00004970 struct target_pollfd *target_pfd;
bellard9de5e442003-03-23 16:49:39 +00004971 unsigned int nfds = arg2;
4972 int timeout = arg3;
4973 struct pollfd *pfd;
bellard7854b052003-03-29 17:22:23 +00004974 unsigned int i;
bellard9de5e442003-03-23 16:49:39 +00004975
bellard579a97f2007-11-11 14:26:47 +00004976 target_pfd = lock_user(VERIFY_WRITE, arg1, sizeof(struct target_pollfd) * nfds, 1);
4977 if (!target_pfd)
4978 goto efault;
bellard9de5e442003-03-23 16:49:39 +00004979 pfd = alloca(sizeof(struct pollfd) * nfds);
4980 for(i = 0; i < nfds; i++) {
bellard5cd43932003-03-29 16:54:36 +00004981 pfd[i].fd = tswap32(target_pfd[i].fd);
4982 pfd[i].events = tswap16(target_pfd[i].events);
bellard9de5e442003-03-23 16:49:39 +00004983 }
4984 ret = get_errno(poll(pfd, nfds, timeout));
4985 if (!is_error(ret)) {
4986 for(i = 0; i < nfds; i++) {
bellard5cd43932003-03-29 16:54:36 +00004987 target_pfd[i].revents = tswap16(pfd[i].revents);
bellard9de5e442003-03-23 16:49:39 +00004988 }
pbrook53a59602006-03-25 19:31:22 +00004989 ret += nfds * (sizeof(struct target_pollfd)
4990 - sizeof(struct pollfd));
bellard9de5e442003-03-23 16:49:39 +00004991 }
pbrook53a59602006-03-25 19:31:22 +00004992 unlock_user(target_pfd, arg1, ret);
bellard9de5e442003-03-23 16:49:39 +00004993 }
4994 break;
thse5febef2007-04-01 18:31:35 +00004995#endif
bellard31e31b82003-02-18 22:55:36 +00004996 case TARGET_NR_flock:
bellard9de5e442003-03-23 16:49:39 +00004997 /* NOTE: the flock constant seems to be the same for every
4998 Linux platform */
4999 ret = get_errno(flock(arg1, arg2));
bellard31e31b82003-02-18 22:55:36 +00005000 break;
5001 case TARGET_NR_readv:
5002 {
5003 int count = arg3;
bellard31e31b82003-02-18 22:55:36 +00005004 struct iovec *vec;
bellard31e31b82003-02-18 22:55:36 +00005005
5006 vec = alloca(count * sizeof(struct iovec));
bellard41df8412008-02-04 22:26:57 +00005007 if (lock_iovec(VERIFY_WRITE, vec, arg2, count, 0) < 0)
5008 goto efault;
bellard31e31b82003-02-18 22:55:36 +00005009 ret = get_errno(readv(arg1, vec, count));
pbrook53a59602006-03-25 19:31:22 +00005010 unlock_iovec(vec, arg2, count, 1);
bellard31e31b82003-02-18 22:55:36 +00005011 }
5012 break;
5013 case TARGET_NR_writev:
5014 {
5015 int count = arg3;
bellard31e31b82003-02-18 22:55:36 +00005016 struct iovec *vec;
bellard31e31b82003-02-18 22:55:36 +00005017
5018 vec = alloca(count * sizeof(struct iovec));
bellard41df8412008-02-04 22:26:57 +00005019 if (lock_iovec(VERIFY_READ, vec, arg2, count, 1) < 0)
5020 goto efault;
bellard31e31b82003-02-18 22:55:36 +00005021 ret = get_errno(writev(arg1, vec, count));
pbrook53a59602006-03-25 19:31:22 +00005022 unlock_iovec(vec, arg2, count, 0);
bellard31e31b82003-02-18 22:55:36 +00005023 }
5024 break;
5025 case TARGET_NR_getsid:
5026 ret = get_errno(getsid(arg1));
5027 break;
j_mayer7a3148a2007-04-05 07:13:51 +00005028#if defined(TARGET_NR_fdatasync) /* Not on alpha (osf_datasync ?) */
bellard31e31b82003-02-18 22:55:36 +00005029 case TARGET_NR_fdatasync:
bellard5cd43932003-03-29 16:54:36 +00005030 ret = get_errno(fdatasync(arg1));
5031 break;
j_mayer7a3148a2007-04-05 07:13:51 +00005032#endif
bellard31e31b82003-02-18 22:55:36 +00005033 case TARGET_NR__sysctl:
ths0da46a62007-10-20 20:23:07 +00005034 /* We don't implement this, but ENOTDIR is always a safe
bellard29e619b2004-09-13 21:41:04 +00005035 return value. */
ths0da46a62007-10-20 20:23:07 +00005036 ret = -TARGET_ENOTDIR;
5037 break;
bellard31e31b82003-02-18 22:55:36 +00005038 case TARGET_NR_sched_setparam:
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;
pbrook53a59602006-03-25 19:31:22 +00005042
bellard579a97f2007-11-11 14:26:47 +00005043 if (!lock_user_struct(VERIFY_READ, target_schp, arg2, 1))
5044 goto efault;
bellard5cd43932003-03-29 16:54:36 +00005045 schp.sched_priority = tswap32(target_schp->sched_priority);
pbrook53a59602006-03-25 19:31:22 +00005046 unlock_user_struct(target_schp, arg2, 0);
bellard5cd43932003-03-29 16:54:36 +00005047 ret = get_errno(sched_setparam(arg1, &schp));
5048 }
5049 break;
bellard31e31b82003-02-18 22:55:36 +00005050 case TARGET_NR_sched_getparam:
bellard5cd43932003-03-29 16:54:36 +00005051 {
pbrook53a59602006-03-25 19:31:22 +00005052 struct sched_param *target_schp;
bellard5cd43932003-03-29 16:54:36 +00005053 struct sched_param schp;
5054 ret = get_errno(sched_getparam(arg1, &schp));
5055 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00005056 if (!lock_user_struct(VERIFY_WRITE, target_schp, arg2, 0))
5057 goto efault;
bellard5cd43932003-03-29 16:54:36 +00005058 target_schp->sched_priority = tswap32(schp.sched_priority);
pbrook53a59602006-03-25 19:31:22 +00005059 unlock_user_struct(target_schp, arg2, 1);
bellard5cd43932003-03-29 16:54:36 +00005060 }
5061 }
5062 break;
bellard31e31b82003-02-18 22:55:36 +00005063 case TARGET_NR_sched_setscheduler:
bellard5cd43932003-03-29 16:54:36 +00005064 {
pbrook53a59602006-03-25 19:31:22 +00005065 struct sched_param *target_schp;
bellard5cd43932003-03-29 16:54:36 +00005066 struct sched_param schp;
bellard579a97f2007-11-11 14:26:47 +00005067 if (!lock_user_struct(VERIFY_READ, target_schp, arg3, 1))
5068 goto efault;
bellard5cd43932003-03-29 16:54:36 +00005069 schp.sched_priority = tswap32(target_schp->sched_priority);
pbrook53a59602006-03-25 19:31:22 +00005070 unlock_user_struct(target_schp, arg3, 0);
bellard5cd43932003-03-29 16:54:36 +00005071 ret = get_errno(sched_setscheduler(arg1, arg2, &schp));
5072 }
5073 break;
bellard31e31b82003-02-18 22:55:36 +00005074 case TARGET_NR_sched_getscheduler:
bellard5cd43932003-03-29 16:54:36 +00005075 ret = get_errno(sched_getscheduler(arg1));
5076 break;
bellard31e31b82003-02-18 22:55:36 +00005077 case TARGET_NR_sched_yield:
5078 ret = get_errno(sched_yield());
5079 break;
5080 case TARGET_NR_sched_get_priority_max:
bellard5cd43932003-03-29 16:54:36 +00005081 ret = get_errno(sched_get_priority_max(arg1));
5082 break;
bellard31e31b82003-02-18 22:55:36 +00005083 case TARGET_NR_sched_get_priority_min:
bellard5cd43932003-03-29 16:54:36 +00005084 ret = get_errno(sched_get_priority_min(arg1));
5085 break;
bellard31e31b82003-02-18 22:55:36 +00005086 case TARGET_NR_sched_rr_get_interval:
bellard5cd43932003-03-29 16:54:36 +00005087 {
bellard5cd43932003-03-29 16:54:36 +00005088 struct timespec ts;
5089 ret = get_errno(sched_rr_get_interval(arg1, &ts));
5090 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00005091 host_to_target_timespec(arg2, &ts);
bellard5cd43932003-03-29 16:54:36 +00005092 }
5093 }
5094 break;
bellard31e31b82003-02-18 22:55:36 +00005095 case TARGET_NR_nanosleep:
bellard1b6b0292003-03-22 17:31:38 +00005096 {
bellard1b6b0292003-03-22 17:31:38 +00005097 struct timespec req, rem;
pbrook53a59602006-03-25 19:31:22 +00005098 target_to_host_timespec(&req, arg1);
bellard1b6b0292003-03-22 17:31:38 +00005099 ret = get_errno(nanosleep(&req, &rem));
pbrook53a59602006-03-25 19:31:22 +00005100 if (is_error(ret) && arg2) {
5101 host_to_target_timespec(arg2, &rem);
bellard1b6b0292003-03-22 17:31:38 +00005102 }
5103 }
5104 break;
thse5febef2007-04-01 18:31:35 +00005105#ifdef TARGET_NR_query_module
bellard31e31b82003-02-18 22:55:36 +00005106 case TARGET_NR_query_module:
bellard5cd43932003-03-29 16:54:36 +00005107 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00005108#endif
5109#ifdef TARGET_NR_nfsservctl
bellard31e31b82003-02-18 22:55:36 +00005110 case TARGET_NR_nfsservctl:
bellard5cd43932003-03-29 16:54:36 +00005111 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00005112#endif
bellard31e31b82003-02-18 22:55:36 +00005113 case TARGET_NR_prctl:
thse5574482007-02-11 20:03:13 +00005114 switch (arg1)
5115 {
5116 case PR_GET_PDEATHSIG:
5117 {
5118 int deathsig;
5119 ret = get_errno(prctl(arg1, &deathsig, arg3, arg4, arg5));
bellard2f619692007-11-16 10:46:05 +00005120 if (!is_error(ret) && arg2
5121 && put_user_ual(deathsig, arg2))
5122 goto efault;
thse5574482007-02-11 20:03:13 +00005123 }
5124 break;
5125 default:
5126 ret = get_errno(prctl(arg1, arg2, arg3, arg4, arg5));
5127 break;
5128 }
ths39b9aae2007-02-11 18:36:44 +00005129 break;
bellardd2fd1af2007-11-14 18:08:56 +00005130#ifdef TARGET_NR_arch_prctl
5131 case TARGET_NR_arch_prctl:
5132#if defined(TARGET_I386) && !defined(TARGET_ABI32)
5133 ret = do_arch_prctl(cpu_env, arg1, arg2);
5134 break;
5135#else
5136 goto unimplemented;
5137#endif
5138#endif
bellard67867302003-11-23 17:05:30 +00005139#ifdef TARGET_NR_pread
bellard31e31b82003-02-18 22:55:36 +00005140 case TARGET_NR_pread:
bellard579a97f2007-11-11 14:26:47 +00005141 if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
5142 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005143 ret = get_errno(pread(arg1, p, arg3, arg4));
5144 unlock_user(p, arg2, ret);
bellard206f0fa2003-05-14 19:01:56 +00005145 break;
bellard31e31b82003-02-18 22:55:36 +00005146 case TARGET_NR_pwrite:
bellard579a97f2007-11-11 14:26:47 +00005147 if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
5148 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005149 ret = get_errno(pwrite(arg1, p, arg3, arg4));
5150 unlock_user(p, arg2, 0);
bellard206f0fa2003-05-14 19:01:56 +00005151 break;
bellard67867302003-11-23 17:05:30 +00005152#endif
aurel32f2c7ba12008-03-28 22:32:06 +00005153#ifdef TARGET_NR_pread64
5154 case TARGET_NR_pread64:
5155 if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
5156 goto efault;
5157 ret = get_errno(pread64(arg1, p, arg3, target_offset64(arg4, arg5)));
5158 unlock_user(p, arg2, ret);
5159 break;
5160 case TARGET_NR_pwrite64:
5161 if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
5162 goto efault;
5163 ret = get_errno(pwrite64(arg1, p, arg3, target_offset64(arg4, arg5)));
5164 unlock_user(p, arg2, 0);
5165 break;
5166#endif
bellard31e31b82003-02-18 22:55:36 +00005167 case TARGET_NR_getcwd:
bellard579a97f2007-11-11 14:26:47 +00005168 if (!(p = lock_user(VERIFY_WRITE, arg1, arg2, 0)))
5169 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005170 ret = get_errno(sys_getcwd1(p, arg2));
5171 unlock_user(p, arg1, ret);
bellard31e31b82003-02-18 22:55:36 +00005172 break;
5173 case TARGET_NR_capget:
bellard5cd43932003-03-29 16:54:36 +00005174 goto unimplemented;
bellard31e31b82003-02-18 22:55:36 +00005175 case TARGET_NR_capset:
bellard5cd43932003-03-29 16:54:36 +00005176 goto unimplemented;
bellard31e31b82003-02-18 22:55:36 +00005177 case TARGET_NR_sigaltstack:
ths198a74d2007-09-27 16:44:32 +00005178#if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_MIPS) || \
5179 defined(TARGET_SPARC) || defined(TARGET_PPC) || defined(TARGET_ALPHA)
bellard579a97f2007-11-11 14:26:47 +00005180 ret = do_sigaltstack(arg1, arg2, get_sp_from_cpustate((CPUState *)cpu_env));
thsa04e1342007-09-27 13:57:58 +00005181 break;
5182#else
bellard5cd43932003-03-29 16:54:36 +00005183 goto unimplemented;
thsa04e1342007-09-27 13:57:58 +00005184#endif
bellard31e31b82003-02-18 22:55:36 +00005185 case TARGET_NR_sendfile:
bellard5cd43932003-03-29 16:54:36 +00005186 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00005187#ifdef TARGET_NR_getpmsg
bellard31e31b82003-02-18 22:55:36 +00005188 case TARGET_NR_getpmsg:
bellard5cd43932003-03-29 16:54:36 +00005189 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00005190#endif
5191#ifdef TARGET_NR_putpmsg
bellard31e31b82003-02-18 22:55:36 +00005192 case TARGET_NR_putpmsg:
bellard5cd43932003-03-29 16:54:36 +00005193 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00005194#endif
bellard048f6b42005-11-26 18:47:20 +00005195#ifdef TARGET_NR_vfork
bellard31e31b82003-02-18 22:55:36 +00005196 case TARGET_NR_vfork:
pbrookd865bab2008-06-07 22:12:17 +00005197 ret = get_errno(do_fork(cpu_env, CLONE_VFORK | CLONE_VM | SIGCHLD,
5198 0, 0, 0, 0));
bellard31e31b82003-02-18 22:55:36 +00005199 break;
bellard048f6b42005-11-26 18:47:20 +00005200#endif
bellardebc05482003-09-30 21:08:41 +00005201#ifdef TARGET_NR_ugetrlimit
bellard31e31b82003-02-18 22:55:36 +00005202 case TARGET_NR_ugetrlimit:
bellard728584b2003-04-29 20:43:36 +00005203 {
5204 struct rlimit rlim;
5205 ret = get_errno(getrlimit(arg1, &rlim));
5206 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00005207 struct target_rlimit *target_rlim;
bellard579a97f2007-11-11 14:26:47 +00005208 if (!lock_user_struct(VERIFY_WRITE, target_rlim, arg2, 0))
5209 goto efault;
bellard728584b2003-04-29 20:43:36 +00005210 target_rlim->rlim_cur = tswapl(rlim.rlim_cur);
5211 target_rlim->rlim_max = tswapl(rlim.rlim_max);
pbrook53a59602006-03-25 19:31:22 +00005212 unlock_user_struct(target_rlim, arg2, 1);
bellard728584b2003-04-29 20:43:36 +00005213 }
5214 break;
5215 }
bellardebc05482003-09-30 21:08:41 +00005216#endif
bellarda315a142005-01-30 22:59:18 +00005217#ifdef TARGET_NR_truncate64
bellard31e31b82003-02-18 22:55:36 +00005218 case TARGET_NR_truncate64:
bellard579a97f2007-11-11 14:26:47 +00005219 if (!(p = lock_user_string(arg1)))
5220 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005221 ret = target_truncate64(cpu_env, p, arg2, arg3, arg4);
5222 unlock_user(p, arg1, 0);
bellard667f38b2005-07-23 14:46:27 +00005223 break;
bellarda315a142005-01-30 22:59:18 +00005224#endif
5225#ifdef TARGET_NR_ftruncate64
bellard31e31b82003-02-18 22:55:36 +00005226 case TARGET_NR_ftruncate64:
pbrookce4defa2006-02-09 16:49:55 +00005227 ret = target_ftruncate64(cpu_env, arg1, arg2, arg3, arg4);
bellard667f38b2005-07-23 14:46:27 +00005228 break;
bellarda315a142005-01-30 22:59:18 +00005229#endif
5230#ifdef TARGET_NR_stat64
bellard31e31b82003-02-18 22:55:36 +00005231 case TARGET_NR_stat64:
bellard579a97f2007-11-11 14:26:47 +00005232 if (!(p = lock_user_string(arg1)))
5233 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005234 ret = get_errno(stat(path(p), &st));
5235 unlock_user(p, arg1, 0);
balrog6a24a772008-09-20 02:23:36 +00005236 if (!is_error(ret))
5237 ret = host_to_target_stat64(cpu_env, arg2, &st);
5238 break;
bellarda315a142005-01-30 22:59:18 +00005239#endif
5240#ifdef TARGET_NR_lstat64
bellard31e31b82003-02-18 22:55:36 +00005241 case TARGET_NR_lstat64:
bellard579a97f2007-11-11 14:26:47 +00005242 if (!(p = lock_user_string(arg1)))
5243 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005244 ret = get_errno(lstat(path(p), &st));
5245 unlock_user(p, arg1, 0);
balrog6a24a772008-09-20 02:23:36 +00005246 if (!is_error(ret))
5247 ret = host_to_target_stat64(cpu_env, arg2, &st);
5248 break;
bellarda315a142005-01-30 22:59:18 +00005249#endif
5250#ifdef TARGET_NR_fstat64
bellard31e31b82003-02-18 22:55:36 +00005251 case TARGET_NR_fstat64:
balrog6a24a772008-09-20 02:23:36 +00005252 ret = get_errno(fstat(arg1, &st));
5253 if (!is_error(ret))
5254 ret = host_to_target_stat64(cpu_env, arg2, &st);
5255 break;
bellardec86b0f2003-04-11 00:15:04 +00005256#endif
balrog6a24a772008-09-20 02:23:36 +00005257#if defined(TARGET_NR_fstatat64) && defined(__NR_fstatat64)
5258 case TARGET_NR_fstatat64:
5259 if (!(p = lock_user_string(arg2)))
5260 goto efault;
5261 ret = get_errno(sys_fstatat64(arg1, path(p), &st, arg4));
5262 if (!is_error(ret))
5263 ret = host_to_target_stat64(cpu_env, arg3, &st);
bellard60cd49d2003-03-16 22:53:56 +00005264 break;
bellarda315a142005-01-30 22:59:18 +00005265#endif
bellard67867302003-11-23 17:05:30 +00005266#ifdef USE_UID16
5267 case TARGET_NR_lchown:
bellard579a97f2007-11-11 14:26:47 +00005268 if (!(p = lock_user_string(arg1)))
5269 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005270 ret = get_errno(lchown(p, low2highuid(arg2), low2highgid(arg3)));
5271 unlock_user(p, arg1, 0);
bellard67867302003-11-23 17:05:30 +00005272 break;
5273 case TARGET_NR_getuid:
5274 ret = get_errno(high2lowuid(getuid()));
5275 break;
5276 case TARGET_NR_getgid:
5277 ret = get_errno(high2lowgid(getgid()));
5278 break;
5279 case TARGET_NR_geteuid:
5280 ret = get_errno(high2lowuid(geteuid()));
5281 break;
5282 case TARGET_NR_getegid:
5283 ret = get_errno(high2lowgid(getegid()));
5284 break;
5285 case TARGET_NR_setreuid:
5286 ret = get_errno(setreuid(low2highuid(arg1), low2highuid(arg2)));
5287 break;
5288 case TARGET_NR_setregid:
5289 ret = get_errno(setregid(low2highgid(arg1), low2highgid(arg2)));
5290 break;
5291 case TARGET_NR_getgroups:
5292 {
5293 int gidsetsize = arg1;
pbrook53a59602006-03-25 19:31:22 +00005294 uint16_t *target_grouplist;
bellard67867302003-11-23 17:05:30 +00005295 gid_t *grouplist;
5296 int i;
5297
5298 grouplist = alloca(gidsetsize * sizeof(gid_t));
5299 ret = get_errno(getgroups(gidsetsize, grouplist));
balrogcb3bc232008-09-20 02:08:13 +00005300 if (gidsetsize == 0)
5301 break;
bellard67867302003-11-23 17:05:30 +00005302 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00005303 target_grouplist = lock_user(VERIFY_WRITE, arg2, gidsetsize * 2, 0);
5304 if (!target_grouplist)
5305 goto efault;
balroga2155fc2008-09-20 02:12:08 +00005306 for(i = 0;i < ret; i++)
bellard67867302003-11-23 17:05:30 +00005307 target_grouplist[i] = tswap16(grouplist[i]);
pbrook53a59602006-03-25 19:31:22 +00005308 unlock_user(target_grouplist, arg2, gidsetsize * 2);
bellard67867302003-11-23 17:05:30 +00005309 }
5310 }
5311 break;
5312 case TARGET_NR_setgroups:
5313 {
5314 int gidsetsize = arg1;
pbrook53a59602006-03-25 19:31:22 +00005315 uint16_t *target_grouplist;
bellard67867302003-11-23 17:05:30 +00005316 gid_t *grouplist;
5317 int i;
5318
5319 grouplist = alloca(gidsetsize * sizeof(gid_t));
bellard579a97f2007-11-11 14:26:47 +00005320 target_grouplist = lock_user(VERIFY_READ, arg2, gidsetsize * 2, 1);
5321 if (!target_grouplist) {
5322 ret = -TARGET_EFAULT;
5323 goto fail;
5324 }
bellard67867302003-11-23 17:05:30 +00005325 for(i = 0;i < gidsetsize; i++)
5326 grouplist[i] = tswap16(target_grouplist[i]);
pbrook53a59602006-03-25 19:31:22 +00005327 unlock_user(target_grouplist, arg2, 0);
bellard67867302003-11-23 17:05:30 +00005328 ret = get_errno(setgroups(gidsetsize, grouplist));
5329 }
5330 break;
5331 case TARGET_NR_fchown:
5332 ret = get_errno(fchown(arg1, low2highuid(arg2), low2highgid(arg3)));
5333 break;
thsccfa72b2007-09-24 09:23:34 +00005334#if defined(TARGET_NR_fchownat) && defined(__NR_fchownat)
5335 case TARGET_NR_fchownat:
bellard579a97f2007-11-11 14:26:47 +00005336 if (!(p = lock_user_string(arg2)))
5337 goto efault;
5338 ret = get_errno(sys_fchownat(arg1, p, low2highuid(arg3), low2highgid(arg4), arg5));
5339 unlock_user(p, arg2, 0);
thsccfa72b2007-09-24 09:23:34 +00005340 break;
5341#endif
bellard67867302003-11-23 17:05:30 +00005342#ifdef TARGET_NR_setresuid
5343 case TARGET_NR_setresuid:
ths5fafdf22007-09-16 21:08:06 +00005344 ret = get_errno(setresuid(low2highuid(arg1),
5345 low2highuid(arg2),
bellard67867302003-11-23 17:05:30 +00005346 low2highuid(arg3)));
5347 break;
5348#endif
5349#ifdef TARGET_NR_getresuid
5350 case TARGET_NR_getresuid:
5351 {
pbrook53a59602006-03-25 19:31:22 +00005352 uid_t ruid, euid, suid;
bellard67867302003-11-23 17:05:30 +00005353 ret = get_errno(getresuid(&ruid, &euid, &suid));
5354 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +00005355 if (put_user_u16(high2lowuid(ruid), arg1)
5356 || put_user_u16(high2lowuid(euid), arg2)
5357 || put_user_u16(high2lowuid(suid), arg3))
5358 goto efault;
bellard67867302003-11-23 17:05:30 +00005359 }
5360 }
5361 break;
5362#endif
5363#ifdef TARGET_NR_getresgid
5364 case TARGET_NR_setresgid:
ths5fafdf22007-09-16 21:08:06 +00005365 ret = get_errno(setresgid(low2highgid(arg1),
5366 low2highgid(arg2),
bellard67867302003-11-23 17:05:30 +00005367 low2highgid(arg3)));
5368 break;
5369#endif
5370#ifdef TARGET_NR_getresgid
5371 case TARGET_NR_getresgid:
5372 {
pbrook53a59602006-03-25 19:31:22 +00005373 gid_t rgid, egid, sgid;
bellard67867302003-11-23 17:05:30 +00005374 ret = get_errno(getresgid(&rgid, &egid, &sgid));
5375 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +00005376 if (put_user_u16(high2lowgid(rgid), arg1)
5377 || put_user_u16(high2lowgid(egid), arg2)
5378 || put_user_u16(high2lowgid(sgid), arg3))
5379 goto efault;
bellard67867302003-11-23 17:05:30 +00005380 }
5381 }
5382 break;
5383#endif
5384 case TARGET_NR_chown:
bellard579a97f2007-11-11 14:26:47 +00005385 if (!(p = lock_user_string(arg1)))
5386 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005387 ret = get_errno(chown(p, low2highuid(arg2), low2highgid(arg3)));
5388 unlock_user(p, arg1, 0);
bellard67867302003-11-23 17:05:30 +00005389 break;
5390 case TARGET_NR_setuid:
5391 ret = get_errno(setuid(low2highuid(arg1)));
5392 break;
5393 case TARGET_NR_setgid:
5394 ret = get_errno(setgid(low2highgid(arg1)));
5395 break;
5396 case TARGET_NR_setfsuid:
5397 ret = get_errno(setfsuid(arg1));
5398 break;
5399 case TARGET_NR_setfsgid:
5400 ret = get_errno(setfsgid(arg1));
5401 break;
5402#endif /* USE_UID16 */
5403
bellarda315a142005-01-30 22:59:18 +00005404#ifdef TARGET_NR_lchown32
bellard31e31b82003-02-18 22:55:36 +00005405 case TARGET_NR_lchown32:
bellard579a97f2007-11-11 14:26:47 +00005406 if (!(p = lock_user_string(arg1)))
5407 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005408 ret = get_errno(lchown(p, arg2, arg3));
5409 unlock_user(p, arg1, 0);
bellardb03c60f2003-03-23 17:19:56 +00005410 break;
bellarda315a142005-01-30 22:59:18 +00005411#endif
5412#ifdef TARGET_NR_getuid32
bellard31e31b82003-02-18 22:55:36 +00005413 case TARGET_NR_getuid32:
bellardb03c60f2003-03-23 17:19:56 +00005414 ret = get_errno(getuid());
5415 break;
bellarda315a142005-01-30 22:59:18 +00005416#endif
5417#ifdef TARGET_NR_getgid32
bellard31e31b82003-02-18 22:55:36 +00005418 case TARGET_NR_getgid32:
bellardb03c60f2003-03-23 17:19:56 +00005419 ret = get_errno(getgid());
5420 break;
bellarda315a142005-01-30 22:59:18 +00005421#endif
5422#ifdef TARGET_NR_geteuid32
bellard31e31b82003-02-18 22:55:36 +00005423 case TARGET_NR_geteuid32:
bellardb03c60f2003-03-23 17:19:56 +00005424 ret = get_errno(geteuid());
5425 break;
bellarda315a142005-01-30 22:59:18 +00005426#endif
5427#ifdef TARGET_NR_getegid32
bellard31e31b82003-02-18 22:55:36 +00005428 case TARGET_NR_getegid32:
bellardb03c60f2003-03-23 17:19:56 +00005429 ret = get_errno(getegid());
5430 break;
bellarda315a142005-01-30 22:59:18 +00005431#endif
5432#ifdef TARGET_NR_setreuid32
bellard31e31b82003-02-18 22:55:36 +00005433 case TARGET_NR_setreuid32:
bellardb03c60f2003-03-23 17:19:56 +00005434 ret = get_errno(setreuid(arg1, arg2));
5435 break;
bellarda315a142005-01-30 22:59:18 +00005436#endif
5437#ifdef TARGET_NR_setregid32
bellard31e31b82003-02-18 22:55:36 +00005438 case TARGET_NR_setregid32:
bellardb03c60f2003-03-23 17:19:56 +00005439 ret = get_errno(setregid(arg1, arg2));
5440 break;
bellarda315a142005-01-30 22:59:18 +00005441#endif
5442#ifdef TARGET_NR_getgroups32
bellard31e31b82003-02-18 22:55:36 +00005443 case TARGET_NR_getgroups32:
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;
5449
5450 grouplist = alloca(gidsetsize * sizeof(gid_t));
5451 ret = get_errno(getgroups(gidsetsize, grouplist));
balrogcb3bc232008-09-20 02:08:13 +00005452 if (gidsetsize == 0)
5453 break;
bellard99c475a2005-01-31 20:45:13 +00005454 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00005455 target_grouplist = lock_user(VERIFY_WRITE, arg2, gidsetsize * 4, 0);
5456 if (!target_grouplist) {
5457 ret = -TARGET_EFAULT;
5458 goto fail;
5459 }
balroga2155fc2008-09-20 02:12:08 +00005460 for(i = 0;i < ret; i++)
pbrook53a59602006-03-25 19:31:22 +00005461 target_grouplist[i] = tswap32(grouplist[i]);
5462 unlock_user(target_grouplist, arg2, gidsetsize * 4);
bellard99c475a2005-01-31 20:45:13 +00005463 }
5464 }
5465 break;
bellarda315a142005-01-30 22:59:18 +00005466#endif
5467#ifdef TARGET_NR_setgroups32
bellard31e31b82003-02-18 22:55:36 +00005468 case TARGET_NR_setgroups32:
bellard99c475a2005-01-31 20:45:13 +00005469 {
5470 int gidsetsize = arg1;
pbrook53a59602006-03-25 19:31:22 +00005471 uint32_t *target_grouplist;
bellard99c475a2005-01-31 20:45:13 +00005472 gid_t *grouplist;
5473 int i;
ths3b46e622007-09-17 08:09:54 +00005474
bellard99c475a2005-01-31 20:45:13 +00005475 grouplist = alloca(gidsetsize * sizeof(gid_t));
bellard579a97f2007-11-11 14:26:47 +00005476 target_grouplist = lock_user(VERIFY_READ, arg2, gidsetsize * 4, 1);
5477 if (!target_grouplist) {
5478 ret = -TARGET_EFAULT;
5479 goto fail;
5480 }
bellard99c475a2005-01-31 20:45:13 +00005481 for(i = 0;i < gidsetsize; i++)
pbrook53a59602006-03-25 19:31:22 +00005482 grouplist[i] = tswap32(target_grouplist[i]);
5483 unlock_user(target_grouplist, arg2, 0);
bellard99c475a2005-01-31 20:45:13 +00005484 ret = get_errno(setgroups(gidsetsize, grouplist));
5485 }
5486 break;
bellarda315a142005-01-30 22:59:18 +00005487#endif
5488#ifdef TARGET_NR_fchown32
bellard31e31b82003-02-18 22:55:36 +00005489 case TARGET_NR_fchown32:
bellardb03c60f2003-03-23 17:19:56 +00005490 ret = get_errno(fchown(arg1, arg2, arg3));
5491 break;
bellarda315a142005-01-30 22:59:18 +00005492#endif
5493#ifdef TARGET_NR_setresuid32
bellard31e31b82003-02-18 22:55:36 +00005494 case TARGET_NR_setresuid32:
bellardb03c60f2003-03-23 17:19:56 +00005495 ret = get_errno(setresuid(arg1, arg2, arg3));
5496 break;
bellarda315a142005-01-30 22:59:18 +00005497#endif
5498#ifdef TARGET_NR_getresuid32
bellard31e31b82003-02-18 22:55:36 +00005499 case TARGET_NR_getresuid32:
bellardb03c60f2003-03-23 17:19:56 +00005500 {
pbrook53a59602006-03-25 19:31:22 +00005501 uid_t ruid, euid, suid;
bellardb03c60f2003-03-23 17:19:56 +00005502 ret = get_errno(getresuid(&ruid, &euid, &suid));
5503 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +00005504 if (put_user_u32(ruid, arg1)
5505 || put_user_u32(euid, arg2)
5506 || put_user_u32(suid, arg3))
5507 goto efault;
bellardb03c60f2003-03-23 17:19:56 +00005508 }
5509 }
5510 break;
bellarda315a142005-01-30 22:59:18 +00005511#endif
5512#ifdef TARGET_NR_setresgid32
bellard31e31b82003-02-18 22:55:36 +00005513 case TARGET_NR_setresgid32:
bellardb03c60f2003-03-23 17:19:56 +00005514 ret = get_errno(setresgid(arg1, arg2, arg3));
5515 break;
bellarda315a142005-01-30 22:59:18 +00005516#endif
5517#ifdef TARGET_NR_getresgid32
bellard31e31b82003-02-18 22:55:36 +00005518 case TARGET_NR_getresgid32:
bellardb03c60f2003-03-23 17:19:56 +00005519 {
pbrook53a59602006-03-25 19:31:22 +00005520 gid_t rgid, egid, sgid;
bellardb03c60f2003-03-23 17:19:56 +00005521 ret = get_errno(getresgid(&rgid, &egid, &sgid));
5522 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +00005523 if (put_user_u32(rgid, arg1)
5524 || put_user_u32(egid, arg2)
5525 || put_user_u32(sgid, arg3))
5526 goto efault;
bellardb03c60f2003-03-23 17:19:56 +00005527 }
5528 }
5529 break;
bellarda315a142005-01-30 22:59:18 +00005530#endif
5531#ifdef TARGET_NR_chown32
bellard31e31b82003-02-18 22:55:36 +00005532 case TARGET_NR_chown32:
bellard579a97f2007-11-11 14:26:47 +00005533 if (!(p = lock_user_string(arg1)))
5534 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005535 ret = get_errno(chown(p, arg2, arg3));
5536 unlock_user(p, arg1, 0);
bellardb03c60f2003-03-23 17:19:56 +00005537 break;
bellarda315a142005-01-30 22:59:18 +00005538#endif
5539#ifdef TARGET_NR_setuid32
bellard31e31b82003-02-18 22:55:36 +00005540 case TARGET_NR_setuid32:
bellardb03c60f2003-03-23 17:19:56 +00005541 ret = get_errno(setuid(arg1));
5542 break;
bellarda315a142005-01-30 22:59:18 +00005543#endif
5544#ifdef TARGET_NR_setgid32
bellard31e31b82003-02-18 22:55:36 +00005545 case TARGET_NR_setgid32:
bellardb03c60f2003-03-23 17:19:56 +00005546 ret = get_errno(setgid(arg1));
5547 break;
bellarda315a142005-01-30 22:59:18 +00005548#endif
5549#ifdef TARGET_NR_setfsuid32
bellard31e31b82003-02-18 22:55:36 +00005550 case TARGET_NR_setfsuid32:
bellardb03c60f2003-03-23 17:19:56 +00005551 ret = get_errno(setfsuid(arg1));
5552 break;
bellarda315a142005-01-30 22:59:18 +00005553#endif
5554#ifdef TARGET_NR_setfsgid32
bellard31e31b82003-02-18 22:55:36 +00005555 case TARGET_NR_setfsgid32:
bellardb03c60f2003-03-23 17:19:56 +00005556 ret = get_errno(setfsgid(arg1));
5557 break;
bellarda315a142005-01-30 22:59:18 +00005558#endif
bellard67867302003-11-23 17:05:30 +00005559
bellard31e31b82003-02-18 22:55:36 +00005560 case TARGET_NR_pivot_root:
bellardb03c60f2003-03-23 17:19:56 +00005561 goto unimplemented;
bellardffa65c32004-01-04 23:57:22 +00005562#ifdef TARGET_NR_mincore
bellard31e31b82003-02-18 22:55:36 +00005563 case TARGET_NR_mincore:
bellardb03c60f2003-03-23 17:19:56 +00005564 goto unimplemented;
bellardffa65c32004-01-04 23:57:22 +00005565#endif
5566#ifdef TARGET_NR_madvise
bellard31e31b82003-02-18 22:55:36 +00005567 case TARGET_NR_madvise:
pbrook24836682006-04-16 14:14:53 +00005568 /* A straight passthrough may not be safe because qemu sometimes
5569 turns private flie-backed mappings into anonymous mappings.
5570 This will break MADV_DONTNEED.
5571 This is a hint, so ignoring and returning success is ok. */
5572 ret = get_errno(0);
5573 break;
bellardffa65c32004-01-04 23:57:22 +00005574#endif
blueswir1992f48a2007-10-14 16:27:31 +00005575#if TARGET_ABI_BITS == 32
bellard31e31b82003-02-18 22:55:36 +00005576 case TARGET_NR_fcntl64:
bellard77e46722003-04-29 20:39:06 +00005577 {
thsb1e341e2007-03-20 21:50:52 +00005578 int cmd;
bellard77e46722003-04-29 20:39:06 +00005579 struct flock64 fl;
pbrook53a59602006-03-25 19:31:22 +00005580 struct target_flock64 *target_fl;
pbrookce4defa2006-02-09 16:49:55 +00005581#ifdef TARGET_ARM
pbrook53a59602006-03-25 19:31:22 +00005582 struct target_eabi_flock64 *target_efl;
pbrookce4defa2006-02-09 16:49:55 +00005583#endif
bellard77e46722003-04-29 20:39:06 +00005584
thsb1e341e2007-03-20 21:50:52 +00005585 switch(arg2){
5586 case TARGET_F_GETLK64:
5587 cmd = F_GETLK64;
thsa7222582007-03-22 15:08:55 +00005588 break;
thsb1e341e2007-03-20 21:50:52 +00005589 case TARGET_F_SETLK64:
5590 cmd = F_SETLK64;
thsa7222582007-03-22 15:08:55 +00005591 break;
thsb1e341e2007-03-20 21:50:52 +00005592 case TARGET_F_SETLKW64:
5593 cmd = F_SETLK64;
thsa7222582007-03-22 15:08:55 +00005594 break;
thsb1e341e2007-03-20 21:50:52 +00005595 default:
5596 cmd = arg2;
thsa7222582007-03-22 15:08:55 +00005597 break;
thsb1e341e2007-03-20 21:50:52 +00005598 }
5599
bellard60cd49d2003-03-16 22:53:56 +00005600 switch(arg2) {
thsb1e341e2007-03-20 21:50:52 +00005601 case TARGET_F_GETLK64:
ths58134272007-03-31 18:59:32 +00005602#ifdef TARGET_ARM
5603 if (((CPUARMState *)cpu_env)->eabi) {
bellard9ee1fa22007-11-11 15:11:19 +00005604 if (!lock_user_struct(VERIFY_READ, target_efl, arg3, 1))
5605 goto efault;
ths58134272007-03-31 18:59:32 +00005606 fl.l_type = tswap16(target_efl->l_type);
5607 fl.l_whence = tswap16(target_efl->l_whence);
5608 fl.l_start = tswap64(target_efl->l_start);
5609 fl.l_len = tswap64(target_efl->l_len);
5610 fl.l_pid = tswapl(target_efl->l_pid);
5611 unlock_user_struct(target_efl, arg3, 0);
5612 } else
5613#endif
5614 {
bellard9ee1fa22007-11-11 15:11:19 +00005615 if (!lock_user_struct(VERIFY_READ, target_fl, arg3, 1))
5616 goto efault;
ths58134272007-03-31 18:59:32 +00005617 fl.l_type = tswap16(target_fl->l_type);
5618 fl.l_whence = tswap16(target_fl->l_whence);
5619 fl.l_start = tswap64(target_fl->l_start);
5620 fl.l_len = tswap64(target_fl->l_len);
5621 fl.l_pid = tswapl(target_fl->l_pid);
5622 unlock_user_struct(target_fl, arg3, 0);
5623 }
thsb1e341e2007-03-20 21:50:52 +00005624 ret = get_errno(fcntl(arg1, cmd, &fl));
bellard77e46722003-04-29 20:39:06 +00005625 if (ret == 0) {
pbrookce4defa2006-02-09 16:49:55 +00005626#ifdef TARGET_ARM
5627 if (((CPUARMState *)cpu_env)->eabi) {
bellard9ee1fa22007-11-11 15:11:19 +00005628 if (!lock_user_struct(VERIFY_WRITE, target_efl, arg3, 0))
5629 goto efault;
pbrookce4defa2006-02-09 16:49:55 +00005630 target_efl->l_type = tswap16(fl.l_type);
5631 target_efl->l_whence = tswap16(fl.l_whence);
5632 target_efl->l_start = tswap64(fl.l_start);
5633 target_efl->l_len = tswap64(fl.l_len);
5634 target_efl->l_pid = tswapl(fl.l_pid);
pbrook53a59602006-03-25 19:31:22 +00005635 unlock_user_struct(target_efl, arg3, 1);
pbrookce4defa2006-02-09 16:49:55 +00005636 } else
5637#endif
5638 {
bellard9ee1fa22007-11-11 15:11:19 +00005639 if (!lock_user_struct(VERIFY_WRITE, target_fl, arg3, 0))
5640 goto efault;
pbrookce4defa2006-02-09 16:49:55 +00005641 target_fl->l_type = tswap16(fl.l_type);
5642 target_fl->l_whence = tswap16(fl.l_whence);
5643 target_fl->l_start = tswap64(fl.l_start);
5644 target_fl->l_len = tswap64(fl.l_len);
5645 target_fl->l_pid = tswapl(fl.l_pid);
pbrook53a59602006-03-25 19:31:22 +00005646 unlock_user_struct(target_fl, arg3, 1);
pbrookce4defa2006-02-09 16:49:55 +00005647 }
bellard77e46722003-04-29 20:39:06 +00005648 }
5649 break;
5650
thsb1e341e2007-03-20 21:50:52 +00005651 case TARGET_F_SETLK64:
5652 case TARGET_F_SETLKW64:
pbrookce4defa2006-02-09 16:49:55 +00005653#ifdef TARGET_ARM
5654 if (((CPUARMState *)cpu_env)->eabi) {
bellard9ee1fa22007-11-11 15:11:19 +00005655 if (!lock_user_struct(VERIFY_READ, target_efl, arg3, 1))
5656 goto efault;
pbrookce4defa2006-02-09 16:49:55 +00005657 fl.l_type = tswap16(target_efl->l_type);
5658 fl.l_whence = tswap16(target_efl->l_whence);
5659 fl.l_start = tswap64(target_efl->l_start);
5660 fl.l_len = tswap64(target_efl->l_len);
5661 fl.l_pid = tswapl(target_efl->l_pid);
pbrook53a59602006-03-25 19:31:22 +00005662 unlock_user_struct(target_efl, arg3, 0);
pbrookce4defa2006-02-09 16:49:55 +00005663 } else
5664#endif
5665 {
bellard9ee1fa22007-11-11 15:11:19 +00005666 if (!lock_user_struct(VERIFY_READ, target_fl, arg3, 1))
5667 goto efault;
pbrookce4defa2006-02-09 16:49:55 +00005668 fl.l_type = tswap16(target_fl->l_type);
5669 fl.l_whence = tswap16(target_fl->l_whence);
5670 fl.l_start = tswap64(target_fl->l_start);
5671 fl.l_len = tswap64(target_fl->l_len);
5672 fl.l_pid = tswapl(target_fl->l_pid);
pbrook53a59602006-03-25 19:31:22 +00005673 unlock_user_struct(target_fl, arg3, 0);
pbrookce4defa2006-02-09 16:49:55 +00005674 }
thsb1e341e2007-03-20 21:50:52 +00005675 ret = get_errno(fcntl(arg1, cmd, &fl));
bellard77e46722003-04-29 20:39:06 +00005676 break;
bellard60cd49d2003-03-16 22:53:56 +00005677 default:
bellard9ee1fa22007-11-11 15:11:19 +00005678 ret = do_fcntl(arg1, cmd, arg3);
bellard60cd49d2003-03-16 22:53:56 +00005679 break;
5680 }
bellard77e46722003-04-29 20:39:06 +00005681 break;
5682 }
bellard60cd49d2003-03-16 22:53:56 +00005683#endif
ths7d600c82006-12-08 01:32:58 +00005684#ifdef TARGET_NR_cacheflush
5685 case TARGET_NR_cacheflush:
5686 /* self-modifying code is handled automatically, so nothing needed */
5687 ret = 0;
5688 break;
5689#endif
bellardebc05482003-09-30 21:08:41 +00005690#ifdef TARGET_NR_security
bellard31e31b82003-02-18 22:55:36 +00005691 case TARGET_NR_security:
5692 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00005693#endif
bellardc573ff62004-01-04 15:51:36 +00005694#ifdef TARGET_NR_getpagesize
5695 case TARGET_NR_getpagesize:
5696 ret = TARGET_PAGE_SIZE;
5697 break;
5698#endif
bellard31e31b82003-02-18 22:55:36 +00005699 case TARGET_NR_gettid:
5700 ret = get_errno(gettid());
5701 break;
thse5febef2007-04-01 18:31:35 +00005702#ifdef TARGET_NR_readahead
bellard31e31b82003-02-18 22:55:36 +00005703 case TARGET_NR_readahead:
bellard5cd43932003-03-29 16:54:36 +00005704 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00005705#endif
bellardebc05482003-09-30 21:08:41 +00005706#ifdef TARGET_NR_setxattr
bellard31e31b82003-02-18 22:55:36 +00005707 case TARGET_NR_setxattr:
5708 case TARGET_NR_lsetxattr:
5709 case TARGET_NR_fsetxattr:
5710 case TARGET_NR_getxattr:
5711 case TARGET_NR_lgetxattr:
5712 case TARGET_NR_fgetxattr:
5713 case TARGET_NR_listxattr:
5714 case TARGET_NR_llistxattr:
5715 case TARGET_NR_flistxattr:
5716 case TARGET_NR_removexattr:
5717 case TARGET_NR_lremovexattr:
5718 case TARGET_NR_fremovexattr:
bellard5cd43932003-03-29 16:54:36 +00005719 goto unimplemented_nowarn;
bellardebc05482003-09-30 21:08:41 +00005720#endif
5721#ifdef TARGET_NR_set_thread_area
bellard5cd43932003-03-29 16:54:36 +00005722 case TARGET_NR_set_thread_area:
bellard8d18e892007-11-14 15:18:40 +00005723#if defined(TARGET_MIPS)
ths6f5b89a2007-03-02 20:48:00 +00005724 ((CPUMIPSState *) cpu_env)->tls_value = arg1;
5725 ret = 0;
5726 break;
bellard8d18e892007-11-14 15:18:40 +00005727#elif defined(TARGET_I386) && defined(TARGET_ABI32)
5728 ret = do_set_thread_area(cpu_env, arg1);
5729 break;
ths6f5b89a2007-03-02 20:48:00 +00005730#else
5731 goto unimplemented_nowarn;
5732#endif
5733#endif
5734#ifdef TARGET_NR_get_thread_area
bellard5cd43932003-03-29 16:54:36 +00005735 case TARGET_NR_get_thread_area:
bellard8d18e892007-11-14 15:18:40 +00005736#if defined(TARGET_I386) && defined(TARGET_ABI32)
5737 ret = do_get_thread_area(cpu_env, arg1);
5738#else
bellard5cd43932003-03-29 16:54:36 +00005739 goto unimplemented_nowarn;
bellardebc05482003-09-30 21:08:41 +00005740#endif
bellard8d18e892007-11-14 15:18:40 +00005741#endif
bellard48dc41e2006-06-21 18:15:50 +00005742#ifdef TARGET_NR_getdomainname
5743 case TARGET_NR_getdomainname:
5744 goto unimplemented_nowarn;
5745#endif
ths6f5b89a2007-03-02 20:48:00 +00005746
thsb5906f92007-03-19 13:32:45 +00005747#ifdef TARGET_NR_clock_gettime
5748 case TARGET_NR_clock_gettime:
5749 {
5750 struct timespec ts;
5751 ret = get_errno(clock_gettime(arg1, &ts));
5752 if (!is_error(ret)) {
5753 host_to_target_timespec(arg2, &ts);
5754 }
5755 break;
5756 }
5757#endif
5758#ifdef TARGET_NR_clock_getres
5759 case TARGET_NR_clock_getres:
5760 {
5761 struct timespec ts;
5762 ret = get_errno(clock_getres(arg1, &ts));
5763 if (!is_error(ret)) {
5764 host_to_target_timespec(arg2, &ts);
5765 }
5766 break;
5767 }
5768#endif
pbrook63d76512008-05-29 13:43:29 +00005769#ifdef TARGET_NR_clock_nanosleep
5770 case TARGET_NR_clock_nanosleep:
5771 {
5772 struct timespec ts;
5773 target_to_host_timespec(&ts, arg3);
5774 ret = get_errno(clock_nanosleep(arg1, arg2, &ts, arg4 ? &ts : NULL));
5775 if (arg4)
5776 host_to_target_timespec(arg4, &ts);
5777 break;
5778 }
5779#endif
thsb5906f92007-03-19 13:32:45 +00005780
ths6f5b89a2007-03-02 20:48:00 +00005781#if defined(TARGET_NR_set_tid_address) && defined(__NR_set_tid_address)
5782 case TARGET_NR_set_tid_address:
bellard579a97f2007-11-11 14:26:47 +00005783 ret = get_errno(set_tid_address((int *)g2h(arg1)));
5784 break;
ths6f5b89a2007-03-02 20:48:00 +00005785#endif
5786
ths3ae43202007-09-16 21:39:48 +00005787#if defined(TARGET_NR_tkill) && defined(__NR_tkill)
ths4cae1d12007-07-12 11:06:53 +00005788 case TARGET_NR_tkill:
pbrook4cb05962008-05-30 18:05:19 +00005789 ret = get_errno(sys_tkill((int)arg1, target_to_host_signal(arg2)));
ths4cae1d12007-07-12 11:06:53 +00005790 break;
5791#endif
5792
ths3ae43202007-09-16 21:39:48 +00005793#if defined(TARGET_NR_tgkill) && defined(__NR_tgkill)
ths71455572007-06-21 21:45:30 +00005794 case TARGET_NR_tgkill:
pbrook4cb05962008-05-30 18:05:19 +00005795 ret = get_errno(sys_tgkill((int)arg1, (int)arg2,
5796 target_to_host_signal(arg3)));
ths71455572007-06-21 21:45:30 +00005797 break;
5798#endif
5799
ths4f2b1fe2007-06-21 21:57:12 +00005800#ifdef TARGET_NR_set_robust_list
5801 case TARGET_NR_set_robust_list:
5802 goto unimplemented_nowarn;
5803#endif
5804
ths9007f0e2007-09-25 17:50:37 +00005805#if defined(TARGET_NR_utimensat) && defined(__NR_utimensat)
5806 case TARGET_NR_utimensat:
5807 {
5808 struct timespec ts[2];
5809 target_to_host_timespec(ts, arg3);
5810 target_to_host_timespec(ts+1, arg3+sizeof(struct target_timespec));
5811 if (!arg2)
5812 ret = get_errno(sys_utimensat(arg1, NULL, ts, arg4));
5813 else {
bellard579a97f2007-11-11 14:26:47 +00005814 if (!(p = lock_user_string(arg2))) {
ths0da46a62007-10-20 20:23:07 +00005815 ret = -TARGET_EFAULT;
bellard579a97f2007-11-11 14:26:47 +00005816 goto fail;
5817 }
5818 ret = get_errno(sys_utimensat(arg1, path(p), ts, arg4));
5819 unlock_user(p, arg2, 0);
ths9007f0e2007-09-25 17:50:37 +00005820 }
5821 }
5822 break;
5823#endif
pbrookbd0c5662008-05-29 14:34:11 +00005824#if defined(USE_NPTL)
5825 case TARGET_NR_futex:
5826 ret = do_futex(arg1, arg2, arg3, arg4, arg5, arg6);
5827 break;
5828#endif
ths9007f0e2007-09-25 17:50:37 +00005829
bellard31e31b82003-02-18 22:55:36 +00005830 default:
5831 unimplemented:
bellard5cd43932003-03-29 16:54:36 +00005832 gemu_log("qemu: Unsupported syscall: %d\n", num);
ths4f2b1fe2007-06-21 21:57:12 +00005833#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 +00005834 unimplemented_nowarn:
bellard80a9d032005-01-03 23:31:27 +00005835#endif
ths0da46a62007-10-20 20:23:07 +00005836 ret = -TARGET_ENOSYS;
bellard31e31b82003-02-18 22:55:36 +00005837 break;
5838 }
bellard579a97f2007-11-11 14:26:47 +00005839fail:
bellardc573ff62004-01-04 15:51:36 +00005840#ifdef DEBUG
5841 gemu_log(" = %ld\n", ret);
5842#endif
thsb92c47c2007-11-01 00:07:38 +00005843 if(do_strace)
5844 print_syscall_ret(num, ret);
bellard31e31b82003-02-18 22:55:36 +00005845 return ret;
bellard579a97f2007-11-11 14:26:47 +00005846efault:
5847 ret = -TARGET_EFAULT;
5848 goto fail;
bellard31e31b82003-02-18 22:55:36 +00005849}