blob: 4ba8880261c16fe6ee3178972c6c027f0138df2f [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
bellard72f03902003-02-18 23:33:18 +0000159#define __NR_sys_getcwd1 __NR_getcwd
bellard72f03902003-02-18 23:33:18 +0000160#define __NR_sys_getdents __NR_getdents
bellarddab2ed92003-03-22 15:23:14 +0000161#define __NR_sys_getdents64 __NR_getdents64
thsc6cda172007-10-09 03:42:34 +0000162#define __NR_sys_getpriority __NR_getpriority
ths64f0ce42007-09-24 09:25:06 +0000163#define __NR_sys_linkat __NR_linkat
ths4472ad02007-09-24 09:22:32 +0000164#define __NR_sys_mkdirat __NR_mkdirat
ths75ac37a2007-09-24 09:23:05 +0000165#define __NR_sys_mknodat __NR_mknodat
ths82424832007-09-24 09:21:55 +0000166#define __NR_sys_openat __NR_openat
ths5e0ccb12007-09-24 09:26:10 +0000167#define __NR_sys_readlinkat __NR_readlinkat
ths722183f2007-09-24 09:24:37 +0000168#define __NR_sys_renameat __NR_renameat
bellard66fb9762003-03-23 01:06:05 +0000169#define __NR_sys_rt_sigqueueinfo __NR_rt_sigqueueinfo
thsf0b62432007-09-24 09:25:40 +0000170#define __NR_sys_symlinkat __NR_symlinkat
ths7494b0f2007-02-11 18:26:53 +0000171#define __NR_sys_syslog __NR_syslog
ths71455572007-06-21 21:45:30 +0000172#define __NR_sys_tgkill __NR_tgkill
ths4cae1d12007-07-12 11:06:53 +0000173#define __NR_sys_tkill __NR_tkill
ths8170f562007-09-24 09:24:11 +0000174#define __NR_sys_unlinkat __NR_unlinkat
ths9007f0e2007-09-25 17:50:37 +0000175#define __NR_sys_utimensat __NR_utimensat
pbrookbd0c5662008-05-29 14:34:11 +0000176#define __NR_sys_futex __NR_futex
bellard31e31b82003-02-18 22:55:36 +0000177
bellardbc51c5c2004-03-17 23:46:04 +0000178#if defined(__alpha__) || defined (__ia64__) || defined(__x86_64__)
bellard9af9eaa2003-04-07 21:34:41 +0000179#define __NR__llseek __NR_lseek
180#endif
181
bellard72f03902003-02-18 23:33:18 +0000182#ifdef __NR_gettid
bellard31e31b82003-02-18 22:55:36 +0000183_syscall0(int, gettid)
bellard72f03902003-02-18 23:33:18 +0000184#else
ths0da46a62007-10-20 20:23:07 +0000185/* This is a replacement for the host gettid() and must return a host
186 errno. */
bellard72f03902003-02-18 23:33:18 +0000187static int gettid(void) {
188 return -ENOSYS;
189}
190#endif
bellard31e31b82003-02-18 22:55:36 +0000191_syscall1(int,sys_uname,struct new_utsname *,buf)
ths92a34c12007-09-24 09:27:49 +0000192#if defined(TARGET_NR_faccessat) && defined(__NR_faccessat)
193_syscall4(int,sys_faccessat,int,dirfd,const char *,pathname,int,mode,int,flags)
194#endif
ths814d7972007-09-24 09:26:51 +0000195#if defined(TARGET_NR_fchmodat) && defined(__NR_fchmodat)
196_syscall4(int,sys_fchmodat,int,dirfd,const char *,pathname,
197 mode_t,mode,int,flags)
198#endif
blueswir14583f582008-08-24 10:35:55 +0000199#if defined(TARGET_NR_fchownat) && defined(__NR_fchownat) && defined(USE_UID16)
thsccfa72b2007-09-24 09:23:34 +0000200_syscall5(int,sys_fchownat,int,dirfd,const char *,pathname,
201 uid_t,owner,gid_t,group,int,flags)
202#endif
bellard72f03902003-02-18 23:33:18 +0000203_syscall2(int,sys_getcwd1,char *,buf,size_t,size)
blueswir14583f582008-08-24 10:35:55 +0000204#if TARGET_ABI_BITS == 32
bellard72f03902003-02-18 23:33:18 +0000205_syscall3(int, sys_getdents, uint, fd, struct dirent *, dirp, uint, count);
blueswir14583f582008-08-24 10:35:55 +0000206#endif
ths3ae43202007-09-16 21:39:48 +0000207#if defined(TARGET_NR_getdents64) && defined(__NR_getdents64)
bellarddab2ed92003-03-22 15:23:14 +0000208_syscall3(int, sys_getdents64, uint, fd, struct dirent64 *, dirp, uint, count);
ths3ae43202007-09-16 21:39:48 +0000209#endif
thsc6cda172007-10-09 03:42:34 +0000210_syscall2(int, sys_getpriority, int, which, int, who);
blueswir18fcd3692008-08-17 20:26:25 +0000211#if !defined (__x86_64__)
bellard31e31b82003-02-18 22:55:36 +0000212_syscall5(int, _llseek, uint, fd, ulong, hi, ulong, lo,
213 loff_t *, res, uint, wh);
blueswir18fcd3692008-08-17 20:26:25 +0000214#endif
ths64f0ce42007-09-24 09:25:06 +0000215#if defined(TARGET_NR_linkat) && defined(__NR_linkat)
216_syscall5(int,sys_linkat,int,olddirfd,const char *,oldpath,
217 int,newdirfd,const char *,newpath,int,flags)
218#endif
ths4472ad02007-09-24 09:22:32 +0000219#if defined(TARGET_NR_mkdirat) && defined(__NR_mkdirat)
220_syscall3(int,sys_mkdirat,int,dirfd,const char *,pathname,mode_t,mode)
221#endif
ths75ac37a2007-09-24 09:23:05 +0000222#if defined(TARGET_NR_mknodat) && defined(__NR_mknodat)
223_syscall4(int,sys_mknodat,int,dirfd,const char *,pathname,
224 mode_t,mode,dev_t,dev)
225#endif
ths82424832007-09-24 09:21:55 +0000226#if defined(TARGET_NR_openat) && defined(__NR_openat)
227_syscall4(int,sys_openat,int,dirfd,const char *,pathname,int,flags,mode_t,mode)
228#endif
ths5e0ccb12007-09-24 09:26:10 +0000229#if defined(TARGET_NR_readlinkat) && defined(__NR_readlinkat)
230_syscall4(int,sys_readlinkat,int,dirfd,const char *,pathname,
231 char *,buf,size_t,bufsize)
232#endif
ths722183f2007-09-24 09:24:37 +0000233#if defined(TARGET_NR_renameat) && defined(__NR_renameat)
234_syscall4(int,sys_renameat,int,olddirfd,const char *,oldpath,
235 int,newdirfd,const char *,newpath)
236#endif
bellard66fb9762003-03-23 01:06:05 +0000237_syscall3(int,sys_rt_sigqueueinfo,int,pid,int,sig,siginfo_t *,uinfo)
thsb51eaa82007-09-25 16:09:22 +0000238#if defined(TARGET_NR_symlinkat) && defined(__NR_symlinkat)
thsf0b62432007-09-24 09:25:40 +0000239_syscall3(int,sys_symlinkat,const char *,oldpath,
240 int,newdirfd,const char *,newpath)
241#endif
ths7494b0f2007-02-11 18:26:53 +0000242_syscall3(int,sys_syslog,int,type,char*,bufp,int,len)
ths3ae43202007-09-16 21:39:48 +0000243#if defined(TARGET_NR_tgkill) && defined(__NR_tgkill)
ths71455572007-06-21 21:45:30 +0000244_syscall3(int,sys_tgkill,int,tgid,int,pid,int,sig)
ths4cae1d12007-07-12 11:06:53 +0000245#endif
ths3ae43202007-09-16 21:39:48 +0000246#if defined(TARGET_NR_tkill) && defined(__NR_tkill)
ths4cae1d12007-07-12 11:06:53 +0000247_syscall2(int,sys_tkill,int,tid,int,sig)
248#endif
bellardec86b0f2003-04-11 00:15:04 +0000249#ifdef __NR_exit_group
250_syscall1(int,exit_group,int,error_code)
251#endif
ths6f5b89a2007-03-02 20:48:00 +0000252#if defined(TARGET_NR_set_tid_address) && defined(__NR_set_tid_address)
253_syscall1(int,set_tid_address,int *,tidptr)
254#endif
ths8170f562007-09-24 09:24:11 +0000255#if defined(TARGET_NR_unlinkat) && defined(__NR_unlinkat)
256_syscall3(int,sys_unlinkat,int,dirfd,const char *,pathname,int,flags)
257#endif
ths9007f0e2007-09-25 17:50:37 +0000258#if defined(TARGET_NR_utimensat) && defined(__NR_utimensat)
259_syscall4(int,sys_utimensat,int,dirfd,const char *,pathname,
260 const struct timespec *,tsp,int,flags)
261#endif
blueswir18fcd3692008-08-17 20:26:25 +0000262#if defined(USE_NPTL)
pbrookbd0c5662008-05-29 14:34:11 +0000263#if defined(TARGET_NR_futex) && defined(__NR_futex)
264_syscall6(int,sys_futex,int *,uaddr,int,op,int,val,
265 const struct timespec *,timeout,int *,uaddr2,int,val3)
blueswir18fcd3692008-08-17 20:26:25 +0000266#endif
pbrookbd0c5662008-05-29 14:34:11 +0000267#endif
bellard66fb9762003-03-23 01:06:05 +0000268
269extern int personality(int);
bellard9de5e442003-03-23 16:49:39 +0000270extern int flock(int, int);
271extern int setfsuid(int);
272extern int setfsgid(int);
bellard19b84f32003-05-08 15:41:49 +0000273extern int setgroups(int, gid_t *);
bellard31e31b82003-02-18 22:55:36 +0000274
thsb92c47c2007-11-01 00:07:38 +0000275#define ERRNO_TABLE_SIZE 1200
276
277/* target_to_host_errno_table[] is initialized from
278 * host_to_target_errno_table[] in syscall_init(). */
279static uint16_t target_to_host_errno_table[ERRNO_TABLE_SIZE] = {
280};
281
ths637947f2007-06-01 12:09:19 +0000282/*
thsfe8f0962007-07-12 10:59:21 +0000283 * This list is the union of errno values overridden in asm-<arch>/errno.h
ths637947f2007-06-01 12:09:19 +0000284 * minus the errnos that are not actually generic to all archs.
285 */
thsb92c47c2007-11-01 00:07:38 +0000286static uint16_t host_to_target_errno_table[ERRNO_TABLE_SIZE] = {
ths637947f2007-06-01 12:09:19 +0000287 [EIDRM] = TARGET_EIDRM,
288 [ECHRNG] = TARGET_ECHRNG,
289 [EL2NSYNC] = TARGET_EL2NSYNC,
290 [EL3HLT] = TARGET_EL3HLT,
291 [EL3RST] = TARGET_EL3RST,
292 [ELNRNG] = TARGET_ELNRNG,
293 [EUNATCH] = TARGET_EUNATCH,
294 [ENOCSI] = TARGET_ENOCSI,
295 [EL2HLT] = TARGET_EL2HLT,
296 [EDEADLK] = TARGET_EDEADLK,
297 [ENOLCK] = TARGET_ENOLCK,
298 [EBADE] = TARGET_EBADE,
299 [EBADR] = TARGET_EBADR,
300 [EXFULL] = TARGET_EXFULL,
301 [ENOANO] = TARGET_ENOANO,
302 [EBADRQC] = TARGET_EBADRQC,
303 [EBADSLT] = TARGET_EBADSLT,
304 [EBFONT] = TARGET_EBFONT,
305 [ENOSTR] = TARGET_ENOSTR,
306 [ENODATA] = TARGET_ENODATA,
307 [ETIME] = TARGET_ETIME,
308 [ENOSR] = TARGET_ENOSR,
309 [ENONET] = TARGET_ENONET,
310 [ENOPKG] = TARGET_ENOPKG,
311 [EREMOTE] = TARGET_EREMOTE,
312 [ENOLINK] = TARGET_ENOLINK,
313 [EADV] = TARGET_EADV,
314 [ESRMNT] = TARGET_ESRMNT,
315 [ECOMM] = TARGET_ECOMM,
316 [EPROTO] = TARGET_EPROTO,
317 [EDOTDOT] = TARGET_EDOTDOT,
318 [EMULTIHOP] = TARGET_EMULTIHOP,
319 [EBADMSG] = TARGET_EBADMSG,
320 [ENAMETOOLONG] = TARGET_ENAMETOOLONG,
321 [EOVERFLOW] = TARGET_EOVERFLOW,
322 [ENOTUNIQ] = TARGET_ENOTUNIQ,
323 [EBADFD] = TARGET_EBADFD,
324 [EREMCHG] = TARGET_EREMCHG,
325 [ELIBACC] = TARGET_ELIBACC,
326 [ELIBBAD] = TARGET_ELIBBAD,
327 [ELIBSCN] = TARGET_ELIBSCN,
328 [ELIBMAX] = TARGET_ELIBMAX,
329 [ELIBEXEC] = TARGET_ELIBEXEC,
330 [EILSEQ] = TARGET_EILSEQ,
331 [ENOSYS] = TARGET_ENOSYS,
332 [ELOOP] = TARGET_ELOOP,
333 [ERESTART] = TARGET_ERESTART,
334 [ESTRPIPE] = TARGET_ESTRPIPE,
335 [ENOTEMPTY] = TARGET_ENOTEMPTY,
336 [EUSERS] = TARGET_EUSERS,
337 [ENOTSOCK] = TARGET_ENOTSOCK,
338 [EDESTADDRREQ] = TARGET_EDESTADDRREQ,
339 [EMSGSIZE] = TARGET_EMSGSIZE,
340 [EPROTOTYPE] = TARGET_EPROTOTYPE,
341 [ENOPROTOOPT] = TARGET_ENOPROTOOPT,
342 [EPROTONOSUPPORT] = TARGET_EPROTONOSUPPORT,
343 [ESOCKTNOSUPPORT] = TARGET_ESOCKTNOSUPPORT,
344 [EOPNOTSUPP] = TARGET_EOPNOTSUPP,
345 [EPFNOSUPPORT] = TARGET_EPFNOSUPPORT,
346 [EAFNOSUPPORT] = TARGET_EAFNOSUPPORT,
347 [EADDRINUSE] = TARGET_EADDRINUSE,
348 [EADDRNOTAVAIL] = TARGET_EADDRNOTAVAIL,
349 [ENETDOWN] = TARGET_ENETDOWN,
350 [ENETUNREACH] = TARGET_ENETUNREACH,
351 [ENETRESET] = TARGET_ENETRESET,
352 [ECONNABORTED] = TARGET_ECONNABORTED,
353 [ECONNRESET] = TARGET_ECONNRESET,
354 [ENOBUFS] = TARGET_ENOBUFS,
355 [EISCONN] = TARGET_EISCONN,
356 [ENOTCONN] = TARGET_ENOTCONN,
357 [EUCLEAN] = TARGET_EUCLEAN,
358 [ENOTNAM] = TARGET_ENOTNAM,
359 [ENAVAIL] = TARGET_ENAVAIL,
360 [EISNAM] = TARGET_EISNAM,
361 [EREMOTEIO] = TARGET_EREMOTEIO,
362 [ESHUTDOWN] = TARGET_ESHUTDOWN,
363 [ETOOMANYREFS] = TARGET_ETOOMANYREFS,
364 [ETIMEDOUT] = TARGET_ETIMEDOUT,
365 [ECONNREFUSED] = TARGET_ECONNREFUSED,
366 [EHOSTDOWN] = TARGET_EHOSTDOWN,
367 [EHOSTUNREACH] = TARGET_EHOSTUNREACH,
368 [EALREADY] = TARGET_EALREADY,
369 [EINPROGRESS] = TARGET_EINPROGRESS,
370 [ESTALE] = TARGET_ESTALE,
371 [ECANCELED] = TARGET_ECANCELED,
372 [ENOMEDIUM] = TARGET_ENOMEDIUM,
373 [EMEDIUMTYPE] = TARGET_EMEDIUMTYPE,
thsb7fe5db2007-07-23 15:37:46 +0000374#ifdef ENOKEY
ths637947f2007-06-01 12:09:19 +0000375 [ENOKEY] = TARGET_ENOKEY,
thsb7fe5db2007-07-23 15:37:46 +0000376#endif
377#ifdef EKEYEXPIRED
ths637947f2007-06-01 12:09:19 +0000378 [EKEYEXPIRED] = TARGET_EKEYEXPIRED,
thsb7fe5db2007-07-23 15:37:46 +0000379#endif
380#ifdef EKEYREVOKED
ths637947f2007-06-01 12:09:19 +0000381 [EKEYREVOKED] = TARGET_EKEYREVOKED,
thsb7fe5db2007-07-23 15:37:46 +0000382#endif
383#ifdef EKEYREJECTED
ths637947f2007-06-01 12:09:19 +0000384 [EKEYREJECTED] = TARGET_EKEYREJECTED,
thsb7fe5db2007-07-23 15:37:46 +0000385#endif
386#ifdef EOWNERDEAD
ths637947f2007-06-01 12:09:19 +0000387 [EOWNERDEAD] = TARGET_EOWNERDEAD,
thsb7fe5db2007-07-23 15:37:46 +0000388#endif
389#ifdef ENOTRECOVERABLE
ths637947f2007-06-01 12:09:19 +0000390 [ENOTRECOVERABLE] = TARGET_ENOTRECOVERABLE,
thsb7fe5db2007-07-23 15:37:46 +0000391#endif
thsb92c47c2007-11-01 00:07:38 +0000392};
ths637947f2007-06-01 12:09:19 +0000393
394static inline int host_to_target_errno(int err)
395{
396 if(host_to_target_errno_table[err])
397 return host_to_target_errno_table[err];
398 return err;
399}
400
thsb92c47c2007-11-01 00:07:38 +0000401static inline int target_to_host_errno(int err)
402{
403 if (target_to_host_errno_table[err])
404 return target_to_host_errno_table[err];
405 return err;
406}
407
blueswir1992f48a2007-10-14 16:27:31 +0000408static inline abi_long get_errno(abi_long ret)
bellard31e31b82003-02-18 22:55:36 +0000409{
410 if (ret == -1)
ths637947f2007-06-01 12:09:19 +0000411 return -host_to_target_errno(errno);
bellard31e31b82003-02-18 22:55:36 +0000412 else
413 return ret;
414}
415
blueswir1992f48a2007-10-14 16:27:31 +0000416static inline int is_error(abi_long ret)
bellard31e31b82003-02-18 22:55:36 +0000417{
blueswir1992f48a2007-10-14 16:27:31 +0000418 return (abi_ulong)ret >= (abi_ulong)(-4096);
bellard31e31b82003-02-18 22:55:36 +0000419}
420
thsb92c47c2007-11-01 00:07:38 +0000421char *target_strerror(int err)
422{
423 return strerror(target_to_host_errno(err));
424}
425
blueswir1992f48a2007-10-14 16:27:31 +0000426static abi_ulong target_brk;
427static abi_ulong target_original_brk;
bellard31e31b82003-02-18 22:55:36 +0000428
blueswir1992f48a2007-10-14 16:27:31 +0000429void target_set_brk(abi_ulong new_brk)
bellard31e31b82003-02-18 22:55:36 +0000430{
blueswir14c1de732007-07-07 20:45:44 +0000431 target_original_brk = target_brk = HOST_PAGE_ALIGN(new_brk);
bellard31e31b82003-02-18 22:55:36 +0000432}
433
ths0da46a62007-10-20 20:23:07 +0000434/* do_brk() must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +0000435abi_long do_brk(abi_ulong new_brk)
bellard31e31b82003-02-18 22:55:36 +0000436{
blueswir1992f48a2007-10-14 16:27:31 +0000437 abi_ulong brk_page;
438 abi_long mapped_addr;
bellard31e31b82003-02-18 22:55:36 +0000439 int new_alloc_size;
440
441 if (!new_brk)
pbrook53a59602006-03-25 19:31:22 +0000442 return target_brk;
bellard31e31b82003-02-18 22:55:36 +0000443 if (new_brk < target_original_brk)
balrog7ab240a2008-04-26 12:17:34 +0000444 return target_brk;
ths3b46e622007-09-17 08:09:54 +0000445
pbrook53a59602006-03-25 19:31:22 +0000446 brk_page = HOST_PAGE_ALIGN(target_brk);
bellard31e31b82003-02-18 22:55:36 +0000447
448 /* If the new brk is less than this, set it and we're done... */
449 if (new_brk < brk_page) {
450 target_brk = new_brk;
pbrook53a59602006-03-25 19:31:22 +0000451 return target_brk;
bellard31e31b82003-02-18 22:55:36 +0000452 }
453
454 /* We need to allocate more memory after the brk... */
bellard54936002003-05-13 00:25:15 +0000455 new_alloc_size = HOST_PAGE_ALIGN(new_brk - brk_page + 1);
ths5fafdf22007-09-16 21:08:06 +0000456 mapped_addr = get_errno(target_mmap(brk_page, new_alloc_size,
bellard54936002003-05-13 00:25:15 +0000457 PROT_READ|PROT_WRITE,
458 MAP_ANON|MAP_FIXED|MAP_PRIVATE, 0, 0));
balrog7ab240a2008-04-26 12:17:34 +0000459
460 if (!is_error(mapped_addr))
bellard31e31b82003-02-18 22:55:36 +0000461 target_brk = new_brk;
balrog7ab240a2008-04-26 12:17:34 +0000462
463 return target_brk;
bellard31e31b82003-02-18 22:55:36 +0000464}
465
ths26edcf42007-12-09 02:25:24 +0000466static inline abi_long copy_from_user_fdset(fd_set *fds,
467 abi_ulong target_fds_addr,
468 int n)
bellard31e31b82003-02-18 22:55:36 +0000469{
ths26edcf42007-12-09 02:25:24 +0000470 int i, nw, j, k;
471 abi_ulong b, *target_fds;
472
473 nw = (n + TARGET_ABI_BITS - 1) / TARGET_ABI_BITS;
474 if (!(target_fds = lock_user(VERIFY_READ,
475 target_fds_addr,
476 sizeof(abi_ulong) * nw,
477 1)))
478 return -TARGET_EFAULT;
479
480 FD_ZERO(fds);
481 k = 0;
482 for (i = 0; i < nw; i++) {
483 /* grab the abi_ulong */
484 __get_user(b, &target_fds[i]);
485 for (j = 0; j < TARGET_ABI_BITS; j++) {
486 /* check the bit inside the abi_ulong */
487 if ((b >> j) & 1)
488 FD_SET(k, fds);
489 k++;
bellard31e31b82003-02-18 22:55:36 +0000490 }
bellard31e31b82003-02-18 22:55:36 +0000491 }
ths26edcf42007-12-09 02:25:24 +0000492
493 unlock_user(target_fds, target_fds_addr, 0);
494
495 return 0;
bellard31e31b82003-02-18 22:55:36 +0000496}
497
ths26edcf42007-12-09 02:25:24 +0000498static inline abi_long copy_to_user_fdset(abi_ulong target_fds_addr,
499 const fd_set *fds,
500 int n)
bellard31e31b82003-02-18 22:55:36 +0000501{
bellard31e31b82003-02-18 22:55:36 +0000502 int i, nw, j, k;
blueswir1992f48a2007-10-14 16:27:31 +0000503 abi_long v;
ths26edcf42007-12-09 02:25:24 +0000504 abi_ulong *target_fds;
bellard31e31b82003-02-18 22:55:36 +0000505
ths26edcf42007-12-09 02:25:24 +0000506 nw = (n + TARGET_ABI_BITS - 1) / TARGET_ABI_BITS;
507 if (!(target_fds = lock_user(VERIFY_WRITE,
508 target_fds_addr,
509 sizeof(abi_ulong) * nw,
510 0)))
511 return -TARGET_EFAULT;
512
513 k = 0;
514 for (i = 0; i < nw; i++) {
515 v = 0;
516 for (j = 0; j < TARGET_ABI_BITS; j++) {
517 v |= ((FD_ISSET(k, fds) != 0) << j);
518 k++;
bellard31e31b82003-02-18 22:55:36 +0000519 }
ths26edcf42007-12-09 02:25:24 +0000520 __put_user(v, &target_fds[i]);
bellard31e31b82003-02-18 22:55:36 +0000521 }
ths26edcf42007-12-09 02:25:24 +0000522
523 unlock_user(target_fds, target_fds_addr, sizeof(abi_ulong) * nw);
524
525 return 0;
bellard31e31b82003-02-18 22:55:36 +0000526}
527
bellardc596ed12003-07-13 17:32:31 +0000528#if defined(__alpha__)
529#define HOST_HZ 1024
530#else
531#define HOST_HZ 100
532#endif
533
blueswir1992f48a2007-10-14 16:27:31 +0000534static inline abi_long host_to_target_clock_t(long ticks)
bellardc596ed12003-07-13 17:32:31 +0000535{
536#if HOST_HZ == TARGET_HZ
537 return ticks;
538#else
539 return ((int64_t)ticks * TARGET_HZ) / HOST_HZ;
540#endif
541}
542
bellard579a97f2007-11-11 14:26:47 +0000543static inline abi_long host_to_target_rusage(abi_ulong target_addr,
544 const struct rusage *rusage)
bellardb4091862003-05-16 15:39:34 +0000545{
pbrook53a59602006-03-25 19:31:22 +0000546 struct target_rusage *target_rusage;
547
bellard579a97f2007-11-11 14:26:47 +0000548 if (!lock_user_struct(VERIFY_WRITE, target_rusage, target_addr, 0))
549 return -TARGET_EFAULT;
bellardb4091862003-05-16 15:39:34 +0000550 target_rusage->ru_utime.tv_sec = tswapl(rusage->ru_utime.tv_sec);
551 target_rusage->ru_utime.tv_usec = tswapl(rusage->ru_utime.tv_usec);
552 target_rusage->ru_stime.tv_sec = tswapl(rusage->ru_stime.tv_sec);
553 target_rusage->ru_stime.tv_usec = tswapl(rusage->ru_stime.tv_usec);
554 target_rusage->ru_maxrss = tswapl(rusage->ru_maxrss);
555 target_rusage->ru_ixrss = tswapl(rusage->ru_ixrss);
556 target_rusage->ru_idrss = tswapl(rusage->ru_idrss);
557 target_rusage->ru_isrss = tswapl(rusage->ru_isrss);
558 target_rusage->ru_minflt = tswapl(rusage->ru_minflt);
559 target_rusage->ru_majflt = tswapl(rusage->ru_majflt);
560 target_rusage->ru_nswap = tswapl(rusage->ru_nswap);
561 target_rusage->ru_inblock = tswapl(rusage->ru_inblock);
562 target_rusage->ru_oublock = tswapl(rusage->ru_oublock);
563 target_rusage->ru_msgsnd = tswapl(rusage->ru_msgsnd);
564 target_rusage->ru_msgrcv = tswapl(rusage->ru_msgrcv);
565 target_rusage->ru_nsignals = tswapl(rusage->ru_nsignals);
566 target_rusage->ru_nvcsw = tswapl(rusage->ru_nvcsw);
567 target_rusage->ru_nivcsw = tswapl(rusage->ru_nivcsw);
pbrook53a59602006-03-25 19:31:22 +0000568 unlock_user_struct(target_rusage, target_addr, 1);
bellard579a97f2007-11-11 14:26:47 +0000569
570 return 0;
bellardb4091862003-05-16 15:39:34 +0000571}
572
ths788f5ec2007-12-09 02:37:05 +0000573static inline abi_long copy_from_user_timeval(struct timeval *tv,
574 abi_ulong target_tv_addr)
bellard31e31b82003-02-18 22:55:36 +0000575{
pbrook53a59602006-03-25 19:31:22 +0000576 struct target_timeval *target_tv;
577
ths788f5ec2007-12-09 02:37:05 +0000578 if (!lock_user_struct(VERIFY_READ, target_tv, target_tv_addr, 1))
bellard579a97f2007-11-11 14:26:47 +0000579 return -TARGET_EFAULT;
ths788f5ec2007-12-09 02:37:05 +0000580
581 __get_user(tv->tv_sec, &target_tv->tv_sec);
582 __get_user(tv->tv_usec, &target_tv->tv_usec);
583
584 unlock_user_struct(target_tv, target_tv_addr, 0);
bellard579a97f2007-11-11 14:26:47 +0000585
586 return 0;
bellard31e31b82003-02-18 22:55:36 +0000587}
588
ths788f5ec2007-12-09 02:37:05 +0000589static inline abi_long copy_to_user_timeval(abi_ulong target_tv_addr,
590 const struct timeval *tv)
bellard31e31b82003-02-18 22:55:36 +0000591{
pbrook53a59602006-03-25 19:31:22 +0000592 struct target_timeval *target_tv;
593
ths788f5ec2007-12-09 02:37:05 +0000594 if (!lock_user_struct(VERIFY_WRITE, target_tv, target_tv_addr, 0))
bellard579a97f2007-11-11 14:26:47 +0000595 return -TARGET_EFAULT;
ths788f5ec2007-12-09 02:37:05 +0000596
597 __put_user(tv->tv_sec, &target_tv->tv_sec);
598 __put_user(tv->tv_usec, &target_tv->tv_usec);
599
600 unlock_user_struct(target_tv, target_tv_addr, 1);
bellard579a97f2007-11-11 14:26:47 +0000601
602 return 0;
bellard31e31b82003-02-18 22:55:36 +0000603}
604
605
ths0da46a62007-10-20 20:23:07 +0000606/* do_select() must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +0000607static abi_long do_select(int n,
ths26edcf42007-12-09 02:25:24 +0000608 abi_ulong rfd_addr, abi_ulong wfd_addr,
609 abi_ulong efd_addr, abi_ulong target_tv_addr)
bellard31e31b82003-02-18 22:55:36 +0000610{
611 fd_set rfds, wfds, efds;
612 fd_set *rfds_ptr, *wfds_ptr, *efds_ptr;
613 struct timeval tv, *tv_ptr;
blueswir1992f48a2007-10-14 16:27:31 +0000614 abi_long ret;
bellard31e31b82003-02-18 22:55:36 +0000615
ths26edcf42007-12-09 02:25:24 +0000616 if (rfd_addr) {
617 if (copy_from_user_fdset(&rfds, rfd_addr, n))
618 return -TARGET_EFAULT;
619 rfds_ptr = &rfds;
pbrook53a59602006-03-25 19:31:22 +0000620 } else {
pbrook53a59602006-03-25 19:31:22 +0000621 rfds_ptr = NULL;
622 }
ths26edcf42007-12-09 02:25:24 +0000623 if (wfd_addr) {
624 if (copy_from_user_fdset(&wfds, wfd_addr, n))
625 return -TARGET_EFAULT;
626 wfds_ptr = &wfds;
pbrook53a59602006-03-25 19:31:22 +0000627 } else {
pbrook53a59602006-03-25 19:31:22 +0000628 wfds_ptr = NULL;
629 }
ths26edcf42007-12-09 02:25:24 +0000630 if (efd_addr) {
631 if (copy_from_user_fdset(&efds, efd_addr, n))
632 return -TARGET_EFAULT;
633 efds_ptr = &efds;
pbrook53a59602006-03-25 19:31:22 +0000634 } else {
pbrook53a59602006-03-25 19:31:22 +0000635 efds_ptr = NULL;
636 }
ths3b46e622007-09-17 08:09:54 +0000637
ths26edcf42007-12-09 02:25:24 +0000638 if (target_tv_addr) {
ths788f5ec2007-12-09 02:37:05 +0000639 if (copy_from_user_timeval(&tv, target_tv_addr))
640 return -TARGET_EFAULT;
bellard31e31b82003-02-18 22:55:36 +0000641 tv_ptr = &tv;
642 } else {
643 tv_ptr = NULL;
644 }
ths26edcf42007-12-09 02:25:24 +0000645
bellard31e31b82003-02-18 22:55:36 +0000646 ret = get_errno(select(n, rfds_ptr, wfds_ptr, efds_ptr, tv_ptr));
pbrook53a59602006-03-25 19:31:22 +0000647
ths26edcf42007-12-09 02:25:24 +0000648 if (!is_error(ret)) {
649 if (rfd_addr && copy_to_user_fdset(rfd_addr, &rfds, n))
650 return -TARGET_EFAULT;
651 if (wfd_addr && copy_to_user_fdset(wfd_addr, &wfds, n))
652 return -TARGET_EFAULT;
653 if (efd_addr && copy_to_user_fdset(efd_addr, &efds, n))
654 return -TARGET_EFAULT;
bellard31e31b82003-02-18 22:55:36 +0000655
ths788f5ec2007-12-09 02:37:05 +0000656 if (target_tv_addr && copy_to_user_timeval(target_tv_addr, &tv))
657 return -TARGET_EFAULT;
bellard31e31b82003-02-18 22:55:36 +0000658 }
bellard579a97f2007-11-11 14:26:47 +0000659
bellard31e31b82003-02-18 22:55:36 +0000660 return ret;
661}
662
bellard579a97f2007-11-11 14:26:47 +0000663static inline abi_long target_to_host_sockaddr(struct sockaddr *addr,
664 abi_ulong target_addr,
665 socklen_t len)
bellard7854b052003-03-29 17:22:23 +0000666{
pbrook53a59602006-03-25 19:31:22 +0000667 struct target_sockaddr *target_saddr;
668
bellard579a97f2007-11-11 14:26:47 +0000669 target_saddr = lock_user(VERIFY_READ, target_addr, len, 1);
670 if (!target_saddr)
671 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +0000672 memcpy(addr, target_saddr, len);
673 addr->sa_family = tswap16(target_saddr->sa_family);
674 unlock_user(target_saddr, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +0000675
676 return 0;
bellard7854b052003-03-29 17:22:23 +0000677}
678
bellard579a97f2007-11-11 14:26:47 +0000679static inline abi_long host_to_target_sockaddr(abi_ulong target_addr,
680 struct sockaddr *addr,
681 socklen_t len)
bellard7854b052003-03-29 17:22:23 +0000682{
pbrook53a59602006-03-25 19:31:22 +0000683 struct target_sockaddr *target_saddr;
684
bellard579a97f2007-11-11 14:26:47 +0000685 target_saddr = lock_user(VERIFY_WRITE, target_addr, len, 0);
686 if (!target_saddr)
687 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +0000688 memcpy(target_saddr, addr, len);
689 target_saddr->sa_family = tswap16(addr->sa_family);
690 unlock_user(target_saddr, target_addr, len);
bellard579a97f2007-11-11 14:26:47 +0000691
692 return 0;
bellard7854b052003-03-29 17:22:23 +0000693}
694
pbrook53a59602006-03-25 19:31:22 +0000695/* ??? Should this also swap msgh->name? */
bellard5a4a8982007-11-11 17:39:18 +0000696static inline abi_long target_to_host_cmsg(struct msghdr *msgh,
697 struct target_msghdr *target_msgh)
bellard7854b052003-03-29 17:22:23 +0000698{
699 struct cmsghdr *cmsg = CMSG_FIRSTHDR(msgh);
bellard5a4a8982007-11-11 17:39:18 +0000700 abi_long msg_controllen;
701 abi_ulong target_cmsg_addr;
702 struct target_cmsghdr *target_cmsg;
bellard7854b052003-03-29 17:22:23 +0000703 socklen_t space = 0;
bellard5a4a8982007-11-11 17:39:18 +0000704
705 msg_controllen = tswapl(target_msgh->msg_controllen);
706 if (msg_controllen < sizeof (struct target_cmsghdr))
707 goto the_end;
708 target_cmsg_addr = tswapl(target_msgh->msg_control);
709 target_cmsg = lock_user(VERIFY_READ, target_cmsg_addr, msg_controllen, 1);
710 if (!target_cmsg)
711 return -TARGET_EFAULT;
bellard7854b052003-03-29 17:22:23 +0000712
713 while (cmsg && target_cmsg) {
714 void *data = CMSG_DATA(cmsg);
715 void *target_data = TARGET_CMSG_DATA(target_cmsg);
716
ths5fafdf22007-09-16 21:08:06 +0000717 int len = tswapl(target_cmsg->cmsg_len)
bellard7854b052003-03-29 17:22:23 +0000718 - TARGET_CMSG_ALIGN(sizeof (struct target_cmsghdr));
719
720 space += CMSG_SPACE(len);
721 if (space > msgh->msg_controllen) {
722 space -= CMSG_SPACE(len);
bellard31febb72005-12-18 20:03:27 +0000723 gemu_log("Host cmsg overflow\n");
bellard7854b052003-03-29 17:22:23 +0000724 break;
725 }
726
727 cmsg->cmsg_level = tswap32(target_cmsg->cmsg_level);
728 cmsg->cmsg_type = tswap32(target_cmsg->cmsg_type);
729 cmsg->cmsg_len = CMSG_LEN(len);
730
bellard3532fa72006-06-24 15:06:03 +0000731 if (cmsg->cmsg_level != TARGET_SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS) {
bellard7854b052003-03-29 17:22:23 +0000732 gemu_log("Unsupported ancillary data: %d/%d\n", cmsg->cmsg_level, cmsg->cmsg_type);
733 memcpy(data, target_data, len);
734 } else {
735 int *fd = (int *)data;
736 int *target_fd = (int *)target_data;
737 int i, numfds = len / sizeof(int);
738
739 for (i = 0; i < numfds; i++)
740 fd[i] = tswap32(target_fd[i]);
741 }
742
743 cmsg = CMSG_NXTHDR(msgh, cmsg);
744 target_cmsg = TARGET_CMSG_NXTHDR(target_msgh, target_cmsg);
745 }
bellard5a4a8982007-11-11 17:39:18 +0000746 unlock_user(target_cmsg, target_cmsg_addr, 0);
747 the_end:
bellard7854b052003-03-29 17:22:23 +0000748 msgh->msg_controllen = space;
bellard5a4a8982007-11-11 17:39:18 +0000749 return 0;
bellard7854b052003-03-29 17:22:23 +0000750}
751
pbrook53a59602006-03-25 19:31:22 +0000752/* ??? Should this also swap msgh->name? */
bellard5a4a8982007-11-11 17:39:18 +0000753static inline abi_long host_to_target_cmsg(struct target_msghdr *target_msgh,
754 struct msghdr *msgh)
bellard7854b052003-03-29 17:22:23 +0000755{
756 struct cmsghdr *cmsg = CMSG_FIRSTHDR(msgh);
bellard5a4a8982007-11-11 17:39:18 +0000757 abi_long msg_controllen;
758 abi_ulong target_cmsg_addr;
759 struct target_cmsghdr *target_cmsg;
bellard7854b052003-03-29 17:22:23 +0000760 socklen_t space = 0;
761
bellard5a4a8982007-11-11 17:39:18 +0000762 msg_controllen = tswapl(target_msgh->msg_controllen);
763 if (msg_controllen < sizeof (struct target_cmsghdr))
764 goto the_end;
765 target_cmsg_addr = tswapl(target_msgh->msg_control);
766 target_cmsg = lock_user(VERIFY_WRITE, target_cmsg_addr, msg_controllen, 0);
767 if (!target_cmsg)
768 return -TARGET_EFAULT;
769
bellard7854b052003-03-29 17:22:23 +0000770 while (cmsg && target_cmsg) {
771 void *data = CMSG_DATA(cmsg);
772 void *target_data = TARGET_CMSG_DATA(target_cmsg);
773
774 int len = cmsg->cmsg_len - CMSG_ALIGN(sizeof (struct cmsghdr));
775
776 space += TARGET_CMSG_SPACE(len);
bellard5a4a8982007-11-11 17:39:18 +0000777 if (space > msg_controllen) {
bellard7854b052003-03-29 17:22:23 +0000778 space -= TARGET_CMSG_SPACE(len);
bellard31febb72005-12-18 20:03:27 +0000779 gemu_log("Target cmsg overflow\n");
bellard7854b052003-03-29 17:22:23 +0000780 break;
781 }
782
783 target_cmsg->cmsg_level = tswap32(cmsg->cmsg_level);
784 target_cmsg->cmsg_type = tswap32(cmsg->cmsg_type);
785 target_cmsg->cmsg_len = tswapl(TARGET_CMSG_LEN(len));
786
bellard3532fa72006-06-24 15:06:03 +0000787 if (cmsg->cmsg_level != TARGET_SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS) {
bellard7854b052003-03-29 17:22:23 +0000788 gemu_log("Unsupported ancillary data: %d/%d\n", cmsg->cmsg_level, cmsg->cmsg_type);
789 memcpy(target_data, data, len);
790 } else {
791 int *fd = (int *)data;
792 int *target_fd = (int *)target_data;
793 int i, numfds = len / sizeof(int);
794
795 for (i = 0; i < numfds; i++)
796 target_fd[i] = tswap32(fd[i]);
797 }
798
799 cmsg = CMSG_NXTHDR(msgh, cmsg);
800 target_cmsg = TARGET_CMSG_NXTHDR(target_msgh, target_cmsg);
801 }
bellard5a4a8982007-11-11 17:39:18 +0000802 unlock_user(target_cmsg, target_cmsg_addr, space);
803 the_end:
804 target_msgh->msg_controllen = tswapl(space);
805 return 0;
bellard7854b052003-03-29 17:22:23 +0000806}
807
ths0da46a62007-10-20 20:23:07 +0000808/* do_setsockopt() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +0000809static abi_long do_setsockopt(int sockfd, int level, int optname,
bellard2f619692007-11-16 10:46:05 +0000810 abi_ulong optval_addr, socklen_t optlen)
bellard7854b052003-03-29 17:22:23 +0000811{
blueswir1992f48a2007-10-14 16:27:31 +0000812 abi_long ret;
j_mayer32407102007-09-26 23:01:49 +0000813 int val;
ths3b46e622007-09-17 08:09:54 +0000814
bellard8853f862004-02-22 14:57:26 +0000815 switch(level) {
816 case SOL_TCP:
bellard7854b052003-03-29 17:22:23 +0000817 /* TCP options all take an 'int' value. */
bellard7854b052003-03-29 17:22:23 +0000818 if (optlen < sizeof(uint32_t))
ths0da46a62007-10-20 20:23:07 +0000819 return -TARGET_EINVAL;
ths3b46e622007-09-17 08:09:54 +0000820
bellard2f619692007-11-16 10:46:05 +0000821 if (get_user_u32(val, optval_addr))
822 return -TARGET_EFAULT;
bellard8853f862004-02-22 14:57:26 +0000823 ret = get_errno(setsockopt(sockfd, level, optname, &val, sizeof(val)));
824 break;
825 case SOL_IP:
826 switch(optname) {
bellard2efbe912005-07-23 15:10:20 +0000827 case IP_TOS:
828 case IP_TTL:
bellard8853f862004-02-22 14:57:26 +0000829 case IP_HDRINCL:
bellard2efbe912005-07-23 15:10:20 +0000830 case IP_ROUTER_ALERT:
831 case IP_RECVOPTS:
832 case IP_RETOPTS:
833 case IP_PKTINFO:
834 case IP_MTU_DISCOVER:
835 case IP_RECVERR:
836 case IP_RECVTOS:
837#ifdef IP_FREEBIND
838 case IP_FREEBIND:
839#endif
840 case IP_MULTICAST_TTL:
841 case IP_MULTICAST_LOOP:
bellard8853f862004-02-22 14:57:26 +0000842 val = 0;
843 if (optlen >= sizeof(uint32_t)) {
bellard2f619692007-11-16 10:46:05 +0000844 if (get_user_u32(val, optval_addr))
845 return -TARGET_EFAULT;
bellard8853f862004-02-22 14:57:26 +0000846 } else if (optlen >= 1) {
bellard2f619692007-11-16 10:46:05 +0000847 if (get_user_u8(val, optval_addr))
848 return -TARGET_EFAULT;
bellard8853f862004-02-22 14:57:26 +0000849 }
850 ret = get_errno(setsockopt(sockfd, level, optname, &val, sizeof(val)));
851 break;
852 default:
853 goto unimplemented;
854 }
855 break;
bellard3532fa72006-06-24 15:06:03 +0000856 case TARGET_SOL_SOCKET:
bellard8853f862004-02-22 14:57:26 +0000857 switch (optname) {
858 /* Options with 'int' argument. */
bellard3532fa72006-06-24 15:06:03 +0000859 case TARGET_SO_DEBUG:
860 optname = SO_DEBUG;
861 break;
862 case TARGET_SO_REUSEADDR:
863 optname = SO_REUSEADDR;
864 break;
865 case TARGET_SO_TYPE:
866 optname = SO_TYPE;
867 break;
868 case TARGET_SO_ERROR:
869 optname = SO_ERROR;
870 break;
871 case TARGET_SO_DONTROUTE:
872 optname = SO_DONTROUTE;
873 break;
874 case TARGET_SO_BROADCAST:
875 optname = SO_BROADCAST;
876 break;
877 case TARGET_SO_SNDBUF:
878 optname = SO_SNDBUF;
879 break;
880 case TARGET_SO_RCVBUF:
881 optname = SO_RCVBUF;
882 break;
883 case TARGET_SO_KEEPALIVE:
884 optname = SO_KEEPALIVE;
885 break;
886 case TARGET_SO_OOBINLINE:
887 optname = SO_OOBINLINE;
888 break;
889 case TARGET_SO_NO_CHECK:
890 optname = SO_NO_CHECK;
891 break;
892 case TARGET_SO_PRIORITY:
893 optname = SO_PRIORITY;
894 break;
bellard5e83e8e2005-03-01 22:32:06 +0000895#ifdef SO_BSDCOMPAT
bellard3532fa72006-06-24 15:06:03 +0000896 case TARGET_SO_BSDCOMPAT:
897 optname = SO_BSDCOMPAT;
898 break;
bellard5e83e8e2005-03-01 22:32:06 +0000899#endif
bellard3532fa72006-06-24 15:06:03 +0000900 case TARGET_SO_PASSCRED:
901 optname = SO_PASSCRED;
902 break;
903 case TARGET_SO_TIMESTAMP:
904 optname = SO_TIMESTAMP;
905 break;
906 case TARGET_SO_RCVLOWAT:
907 optname = SO_RCVLOWAT;
908 break;
909 case TARGET_SO_RCVTIMEO:
910 optname = SO_RCVTIMEO;
911 break;
912 case TARGET_SO_SNDTIMEO:
913 optname = SO_SNDTIMEO;
914 break;
bellard8853f862004-02-22 14:57:26 +0000915 break;
916 default:
917 goto unimplemented;
918 }
bellard3532fa72006-06-24 15:06:03 +0000919 if (optlen < sizeof(uint32_t))
bellard2f619692007-11-16 10:46:05 +0000920 return -TARGET_EINVAL;
bellard3532fa72006-06-24 15:06:03 +0000921
bellard2f619692007-11-16 10:46:05 +0000922 if (get_user_u32(val, optval_addr))
923 return -TARGET_EFAULT;
bellard3532fa72006-06-24 15:06:03 +0000924 ret = get_errno(setsockopt(sockfd, SOL_SOCKET, optname, &val, sizeof(val)));
bellard8853f862004-02-22 14:57:26 +0000925 break;
bellard7854b052003-03-29 17:22:23 +0000926 default:
bellard8853f862004-02-22 14:57:26 +0000927 unimplemented:
928 gemu_log("Unsupported setsockopt level=%d optname=%d \n", level, optname);
ths6fa13c12007-12-18 02:41:04 +0000929 ret = -TARGET_ENOPROTOOPT;
bellard7854b052003-03-29 17:22:23 +0000930 }
bellard8853f862004-02-22 14:57:26 +0000931 return ret;
bellard7854b052003-03-29 17:22:23 +0000932}
933
ths0da46a62007-10-20 20:23:07 +0000934/* do_getsockopt() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +0000935static abi_long do_getsockopt(int sockfd, int level, int optname,
bellard2f619692007-11-16 10:46:05 +0000936 abi_ulong optval_addr, abi_ulong optlen)
bellard7854b052003-03-29 17:22:23 +0000937{
blueswir1992f48a2007-10-14 16:27:31 +0000938 abi_long ret;
j_mayer32407102007-09-26 23:01:49 +0000939 int len, lv, val;
bellard8853f862004-02-22 14:57:26 +0000940
941 switch(level) {
bellard3532fa72006-06-24 15:06:03 +0000942 case TARGET_SOL_SOCKET:
943 level = SOL_SOCKET;
bellard8853f862004-02-22 14:57:26 +0000944 switch (optname) {
bellard3532fa72006-06-24 15:06:03 +0000945 case TARGET_SO_LINGER:
946 case TARGET_SO_RCVTIMEO:
947 case TARGET_SO_SNDTIMEO:
948 case TARGET_SO_PEERCRED:
949 case TARGET_SO_PEERNAME:
bellard8853f862004-02-22 14:57:26 +0000950 /* These don't just return a single integer */
951 goto unimplemented;
952 default:
bellard2efbe912005-07-23 15:10:20 +0000953 goto int_case;
954 }
955 break;
956 case SOL_TCP:
957 /* TCP options all take an 'int' value. */
958 int_case:
bellard2f619692007-11-16 10:46:05 +0000959 if (get_user_u32(len, optlen))
960 return -TARGET_EFAULT;
bellard2efbe912005-07-23 15:10:20 +0000961 if (len < 0)
ths0da46a62007-10-20 20:23:07 +0000962 return -TARGET_EINVAL;
bellard2efbe912005-07-23 15:10:20 +0000963 lv = sizeof(int);
964 ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
965 if (ret < 0)
966 return ret;
967 val = tswap32(val);
968 if (len > lv)
969 len = lv;
bellard2f619692007-11-16 10:46:05 +0000970 if (len == 4) {
971 if (put_user_u32(val, optval_addr))
972 return -TARGET_EFAULT;
973 } else {
974 if (put_user_u8(val, optval_addr))
975 return -TARGET_EFAULT;
976 }
977 if (put_user_u32(len, optlen))
978 return -TARGET_EFAULT;
bellard2efbe912005-07-23 15:10:20 +0000979 break;
980 case SOL_IP:
981 switch(optname) {
982 case IP_TOS:
983 case IP_TTL:
984 case IP_HDRINCL:
985 case IP_ROUTER_ALERT:
986 case IP_RECVOPTS:
987 case IP_RETOPTS:
988 case IP_PKTINFO:
989 case IP_MTU_DISCOVER:
990 case IP_RECVERR:
991 case IP_RECVTOS:
992#ifdef IP_FREEBIND
993 case IP_FREEBIND:
994#endif
995 case IP_MULTICAST_TTL:
996 case IP_MULTICAST_LOOP:
bellard2f619692007-11-16 10:46:05 +0000997 if (get_user_u32(len, optlen))
998 return -TARGET_EFAULT;
bellard8853f862004-02-22 14:57:26 +0000999 if (len < 0)
ths0da46a62007-10-20 20:23:07 +00001000 return -TARGET_EINVAL;
bellard8853f862004-02-22 14:57:26 +00001001 lv = sizeof(int);
1002 ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
1003 if (ret < 0)
1004 return ret;
bellard2efbe912005-07-23 15:10:20 +00001005 if (len < sizeof(int) && len > 0 && val >= 0 && val < 255) {
bellard2efbe912005-07-23 15:10:20 +00001006 len = 1;
bellard2f619692007-11-16 10:46:05 +00001007 if (put_user_u32(len, optlen)
1008 || put_user_u8(val, optval_addr))
1009 return -TARGET_EFAULT;
bellard2efbe912005-07-23 15:10:20 +00001010 } else {
bellard2efbe912005-07-23 15:10:20 +00001011 if (len > sizeof(int))
1012 len = sizeof(int);
bellard2f619692007-11-16 10:46:05 +00001013 if (put_user_u32(len, optlen)
1014 || put_user_u32(val, optval_addr))
1015 return -TARGET_EFAULT;
bellard2efbe912005-07-23 15:10:20 +00001016 }
bellard8853f862004-02-22 14:57:26 +00001017 break;
bellard2efbe912005-07-23 15:10:20 +00001018 default:
thsc02f4992007-12-18 02:39:59 +00001019 ret = -TARGET_ENOPROTOOPT;
1020 break;
bellard8853f862004-02-22 14:57:26 +00001021 }
1022 break;
1023 default:
1024 unimplemented:
1025 gemu_log("getsockopt level=%d optname=%d not yet supported\n",
1026 level, optname);
thsc02f4992007-12-18 02:39:59 +00001027 ret = -TARGET_EOPNOTSUPP;
bellard8853f862004-02-22 14:57:26 +00001028 break;
1029 }
1030 return ret;
bellard7854b052003-03-29 17:22:23 +00001031}
1032
bellard579a97f2007-11-11 14:26:47 +00001033/* FIXME
1034 * lock_iovec()/unlock_iovec() have a return code of 0 for success where
1035 * other lock functions have a return code of 0 for failure.
1036 */
1037static abi_long lock_iovec(int type, struct iovec *vec, abi_ulong target_addr,
1038 int count, int copy)
pbrook53a59602006-03-25 19:31:22 +00001039{
1040 struct target_iovec *target_vec;
blueswir1992f48a2007-10-14 16:27:31 +00001041 abi_ulong base;
bellard579a97f2007-11-11 14:26:47 +00001042 int i, j;
pbrook53a59602006-03-25 19:31:22 +00001043
bellard579a97f2007-11-11 14:26:47 +00001044 target_vec = lock_user(VERIFY_READ, target_addr, count * sizeof(struct target_iovec), 1);
1045 if (!target_vec)
1046 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00001047 for(i = 0;i < count; i++) {
1048 base = tswapl(target_vec[i].iov_base);
1049 vec[i].iov_len = tswapl(target_vec[i].iov_len);
bellard41df8412008-02-04 22:26:57 +00001050 if (vec[i].iov_len != 0) {
1051 vec[i].iov_base = lock_user(type, base, vec[i].iov_len, copy);
balrog7bedce82008-02-10 13:28:08 +00001052 if (!vec[i].iov_base && vec[i].iov_len)
bellard41df8412008-02-04 22:26:57 +00001053 goto fail;
1054 } else {
1055 /* zero length pointer is ignored */
1056 vec[i].iov_base = NULL;
1057 }
pbrook53a59602006-03-25 19:31:22 +00001058 }
1059 unlock_user (target_vec, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00001060 return 0;
1061 fail:
1062 /* failure - unwind locks */
1063 for (j = 0; j < i; j++) {
1064 base = tswapl(target_vec[j].iov_base);
1065 unlock_user(vec[j].iov_base, base, 0);
1066 }
1067 unlock_user (target_vec, target_addr, 0);
1068 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00001069}
1070
bellard579a97f2007-11-11 14:26:47 +00001071static abi_long unlock_iovec(struct iovec *vec, abi_ulong target_addr,
1072 int count, int copy)
pbrook53a59602006-03-25 19:31:22 +00001073{
1074 struct target_iovec *target_vec;
blueswir1992f48a2007-10-14 16:27:31 +00001075 abi_ulong base;
pbrook53a59602006-03-25 19:31:22 +00001076 int i;
1077
bellard579a97f2007-11-11 14:26:47 +00001078 target_vec = lock_user(VERIFY_READ, target_addr, count * sizeof(struct target_iovec), 1);
1079 if (!target_vec)
1080 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00001081 for(i = 0;i < count; i++) {
1082 base = tswapl(target_vec[i].iov_base);
1083 unlock_user(vec[i].iov_base, base, copy ? vec[i].iov_len : 0);
1084 }
1085 unlock_user (target_vec, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00001086
1087 return 0;
pbrook53a59602006-03-25 19:31:22 +00001088}
1089
ths0da46a62007-10-20 20:23:07 +00001090/* do_socket() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001091static abi_long do_socket(int domain, int type, int protocol)
bellard3532fa72006-06-24 15:06:03 +00001092{
1093#if defined(TARGET_MIPS)
1094 switch(type) {
1095 case TARGET_SOCK_DGRAM:
1096 type = SOCK_DGRAM;
1097 break;
1098 case TARGET_SOCK_STREAM:
1099 type = SOCK_STREAM;
1100 break;
1101 case TARGET_SOCK_RAW:
1102 type = SOCK_RAW;
1103 break;
1104 case TARGET_SOCK_RDM:
1105 type = SOCK_RDM;
1106 break;
1107 case TARGET_SOCK_SEQPACKET:
1108 type = SOCK_SEQPACKET;
1109 break;
1110 case TARGET_SOCK_PACKET:
1111 type = SOCK_PACKET;
1112 break;
1113 }
1114#endif
balrog12bc92a2007-10-30 21:06:14 +00001115 if (domain == PF_NETLINK)
1116 return -EAFNOSUPPORT; /* do not NETLINK socket connections possible */
bellard3532fa72006-06-24 15:06:03 +00001117 return get_errno(socket(domain, type, protocol));
1118}
1119
ths0da46a62007-10-20 20:23:07 +00001120/* do_bind() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001121static abi_long do_bind(int sockfd, abi_ulong target_addr,
1122 socklen_t addrlen)
bellard3532fa72006-06-24 15:06:03 +00001123{
1124 void *addr = alloca(addrlen);
ths3b46e622007-09-17 08:09:54 +00001125
bellard3532fa72006-06-24 15:06:03 +00001126 target_to_host_sockaddr(addr, target_addr, addrlen);
1127 return get_errno(bind(sockfd, addr, addrlen));
1128}
1129
ths0da46a62007-10-20 20:23:07 +00001130/* do_connect() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001131static abi_long do_connect(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(connect(sockfd, addr, addrlen));
1138}
1139
ths0da46a62007-10-20 20:23:07 +00001140/* do_sendrecvmsg() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001141static abi_long do_sendrecvmsg(int fd, abi_ulong target_msg,
1142 int flags, int send)
bellard3532fa72006-06-24 15:06:03 +00001143{
blueswir1992f48a2007-10-14 16:27:31 +00001144 abi_long ret;
bellard3532fa72006-06-24 15:06:03 +00001145 struct target_msghdr *msgp;
1146 struct msghdr msg;
1147 int count;
1148 struct iovec *vec;
blueswir1992f48a2007-10-14 16:27:31 +00001149 abi_ulong target_vec;
bellard3532fa72006-06-24 15:06:03 +00001150
bellard579a97f2007-11-11 14:26:47 +00001151 /* FIXME */
1152 if (!lock_user_struct(send ? VERIFY_READ : VERIFY_WRITE,
1153 msgp,
1154 target_msg,
1155 send ? 1 : 0))
1156 return -TARGET_EFAULT;
bellard3532fa72006-06-24 15:06:03 +00001157 if (msgp->msg_name) {
1158 msg.msg_namelen = tswap32(msgp->msg_namelen);
1159 msg.msg_name = alloca(msg.msg_namelen);
1160 target_to_host_sockaddr(msg.msg_name, tswapl(msgp->msg_name),
1161 msg.msg_namelen);
1162 } else {
1163 msg.msg_name = NULL;
1164 msg.msg_namelen = 0;
1165 }
1166 msg.msg_controllen = 2 * tswapl(msgp->msg_controllen);
1167 msg.msg_control = alloca(msg.msg_controllen);
1168 msg.msg_flags = tswap32(msgp->msg_flags);
ths3b46e622007-09-17 08:09:54 +00001169
bellard3532fa72006-06-24 15:06:03 +00001170 count = tswapl(msgp->msg_iovlen);
1171 vec = alloca(count * sizeof(struct iovec));
1172 target_vec = tswapl(msgp->msg_iov);
bellard579a97f2007-11-11 14:26:47 +00001173 lock_iovec(send ? VERIFY_READ : VERIFY_WRITE, vec, target_vec, count, send);
bellard3532fa72006-06-24 15:06:03 +00001174 msg.msg_iovlen = count;
1175 msg.msg_iov = vec;
ths3b46e622007-09-17 08:09:54 +00001176
bellard3532fa72006-06-24 15:06:03 +00001177 if (send) {
bellard5a4a8982007-11-11 17:39:18 +00001178 ret = target_to_host_cmsg(&msg, msgp);
1179 if (ret == 0)
1180 ret = get_errno(sendmsg(fd, &msg, flags));
bellard3532fa72006-06-24 15:06:03 +00001181 } else {
1182 ret = get_errno(recvmsg(fd, &msg, flags));
1183 if (!is_error(ret))
bellard5a4a8982007-11-11 17:39:18 +00001184 ret = host_to_target_cmsg(msgp, &msg);
bellard3532fa72006-06-24 15:06:03 +00001185 }
1186 unlock_iovec(vec, target_vec, count, !send);
bellard579a97f2007-11-11 14:26:47 +00001187 unlock_user_struct(msgp, target_msg, send ? 0 : 1);
bellard3532fa72006-06-24 15:06:03 +00001188 return ret;
1189}
1190
ths0da46a62007-10-20 20:23:07 +00001191/* do_accept() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001192static abi_long do_accept(int fd, abi_ulong target_addr,
bellard2f619692007-11-16 10:46:05 +00001193 abi_ulong target_addrlen_addr)
pbrook1be9e1d2006-11-19 15:26:04 +00001194{
bellard2f619692007-11-16 10:46:05 +00001195 socklen_t addrlen;
1196 void *addr;
blueswir1992f48a2007-10-14 16:27:31 +00001197 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00001198
bellard2f619692007-11-16 10:46:05 +00001199 if (get_user_u32(addrlen, target_addrlen_addr))
1200 return -TARGET_EFAULT;
1201
1202 addr = alloca(addrlen);
1203
pbrook1be9e1d2006-11-19 15:26:04 +00001204 ret = get_errno(accept(fd, addr, &addrlen));
1205 if (!is_error(ret)) {
1206 host_to_target_sockaddr(target_addr, addr, addrlen);
bellard2f619692007-11-16 10:46:05 +00001207 if (put_user_u32(addrlen, target_addrlen_addr))
1208 ret = -TARGET_EFAULT;
pbrook1be9e1d2006-11-19 15:26:04 +00001209 }
1210 return ret;
1211}
1212
ths0da46a62007-10-20 20:23:07 +00001213/* do_getpeername() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001214static abi_long do_getpeername(int fd, abi_ulong target_addr,
bellard2f619692007-11-16 10:46:05 +00001215 abi_ulong target_addrlen_addr)
pbrook1be9e1d2006-11-19 15:26:04 +00001216{
bellard2f619692007-11-16 10:46:05 +00001217 socklen_t addrlen;
1218 void *addr;
blueswir1992f48a2007-10-14 16:27:31 +00001219 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00001220
bellard2f619692007-11-16 10:46:05 +00001221 if (get_user_u32(addrlen, target_addrlen_addr))
1222 return -TARGET_EFAULT;
1223
1224 addr = alloca(addrlen);
1225
pbrook1be9e1d2006-11-19 15:26:04 +00001226 ret = get_errno(getpeername(fd, addr, &addrlen));
1227 if (!is_error(ret)) {
1228 host_to_target_sockaddr(target_addr, addr, addrlen);
bellard2f619692007-11-16 10:46:05 +00001229 if (put_user_u32(addrlen, target_addrlen_addr))
1230 ret = -TARGET_EFAULT;
pbrook1be9e1d2006-11-19 15:26:04 +00001231 }
1232 return ret;
1233}
1234
ths0da46a62007-10-20 20:23:07 +00001235/* do_getsockname() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001236static abi_long do_getsockname(int fd, abi_ulong target_addr,
bellard2f619692007-11-16 10:46:05 +00001237 abi_ulong target_addrlen_addr)
pbrook1be9e1d2006-11-19 15:26:04 +00001238{
bellard2f619692007-11-16 10:46:05 +00001239 socklen_t addrlen;
1240 void *addr;
blueswir1992f48a2007-10-14 16:27:31 +00001241 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00001242
bellard2f619692007-11-16 10:46:05 +00001243 if (get_user_u32(addrlen, target_addrlen_addr))
1244 return -TARGET_EFAULT;
1245
1246 addr = alloca(addrlen);
1247
pbrook1be9e1d2006-11-19 15:26:04 +00001248 ret = get_errno(getsockname(fd, addr, &addrlen));
1249 if (!is_error(ret)) {
1250 host_to_target_sockaddr(target_addr, addr, addrlen);
bellard2f619692007-11-16 10:46:05 +00001251 if (put_user_u32(addrlen, target_addrlen_addr))
1252 ret = -TARGET_EFAULT;
pbrook1be9e1d2006-11-19 15:26:04 +00001253 }
1254 return ret;
1255}
1256
ths0da46a62007-10-20 20:23:07 +00001257/* do_socketpair() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001258static abi_long do_socketpair(int domain, int type, int protocol,
bellard2f619692007-11-16 10:46:05 +00001259 abi_ulong target_tab_addr)
pbrook1be9e1d2006-11-19 15:26:04 +00001260{
1261 int tab[2];
blueswir1992f48a2007-10-14 16:27:31 +00001262 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00001263
1264 ret = get_errno(socketpair(domain, type, protocol, tab));
1265 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +00001266 if (put_user_s32(tab[0], target_tab_addr)
1267 || put_user_s32(tab[1], target_tab_addr + sizeof(tab[0])))
1268 ret = -TARGET_EFAULT;
pbrook1be9e1d2006-11-19 15:26:04 +00001269 }
1270 return ret;
1271}
1272
ths0da46a62007-10-20 20:23:07 +00001273/* do_sendto() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001274static abi_long do_sendto(int fd, abi_ulong msg, size_t len, int flags,
1275 abi_ulong target_addr, socklen_t addrlen)
pbrook1be9e1d2006-11-19 15:26:04 +00001276{
1277 void *addr;
1278 void *host_msg;
blueswir1992f48a2007-10-14 16:27:31 +00001279 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00001280
bellard579a97f2007-11-11 14:26:47 +00001281 host_msg = lock_user(VERIFY_READ, msg, len, 1);
1282 if (!host_msg)
1283 return -TARGET_EFAULT;
pbrook1be9e1d2006-11-19 15:26:04 +00001284 if (target_addr) {
1285 addr = alloca(addrlen);
1286 target_to_host_sockaddr(addr, target_addr, addrlen);
1287 ret = get_errno(sendto(fd, host_msg, len, flags, addr, addrlen));
1288 } else {
1289 ret = get_errno(send(fd, host_msg, len, flags));
1290 }
1291 unlock_user(host_msg, msg, 0);
1292 return ret;
1293}
1294
ths0da46a62007-10-20 20:23:07 +00001295/* do_recvfrom() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001296static abi_long do_recvfrom(int fd, abi_ulong msg, size_t len, int flags,
1297 abi_ulong target_addr,
1298 abi_ulong target_addrlen)
pbrook1be9e1d2006-11-19 15:26:04 +00001299{
1300 socklen_t addrlen;
1301 void *addr;
1302 void *host_msg;
blueswir1992f48a2007-10-14 16:27:31 +00001303 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00001304
bellard579a97f2007-11-11 14:26:47 +00001305 host_msg = lock_user(VERIFY_WRITE, msg, len, 0);
1306 if (!host_msg)
1307 return -TARGET_EFAULT;
pbrook1be9e1d2006-11-19 15:26:04 +00001308 if (target_addr) {
bellard2f619692007-11-16 10:46:05 +00001309 if (get_user_u32(addrlen, target_addrlen)) {
1310 ret = -TARGET_EFAULT;
1311 goto fail;
1312 }
pbrook1be9e1d2006-11-19 15:26:04 +00001313 addr = alloca(addrlen);
1314 ret = get_errno(recvfrom(fd, host_msg, len, flags, addr, &addrlen));
1315 } else {
1316 addr = NULL; /* To keep compiler quiet. */
1317 ret = get_errno(recv(fd, host_msg, len, flags));
1318 }
1319 if (!is_error(ret)) {
1320 if (target_addr) {
1321 host_to_target_sockaddr(target_addr, addr, addrlen);
bellard2f619692007-11-16 10:46:05 +00001322 if (put_user_u32(addrlen, target_addrlen)) {
1323 ret = -TARGET_EFAULT;
1324 goto fail;
1325 }
pbrook1be9e1d2006-11-19 15:26:04 +00001326 }
1327 unlock_user(host_msg, msg, len);
1328 } else {
bellard2f619692007-11-16 10:46:05 +00001329fail:
pbrook1be9e1d2006-11-19 15:26:04 +00001330 unlock_user(host_msg, msg, 0);
1331 }
1332 return ret;
1333}
1334
j_mayer32407102007-09-26 23:01:49 +00001335#ifdef TARGET_NR_socketcall
ths0da46a62007-10-20 20:23:07 +00001336/* do_socketcall() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001337static abi_long do_socketcall(int num, abi_ulong vptr)
bellard31e31b82003-02-18 22:55:36 +00001338{
blueswir1992f48a2007-10-14 16:27:31 +00001339 abi_long ret;
1340 const int n = sizeof(abi_ulong);
bellard31e31b82003-02-18 22:55:36 +00001341
1342 switch(num) {
1343 case SOCKOP_socket:
bellard7854b052003-03-29 17:22:23 +00001344 {
bellard2f619692007-11-16 10:46:05 +00001345 int domain, type, protocol;
1346
1347 if (get_user_s32(domain, vptr)
1348 || get_user_s32(type, vptr + n)
1349 || get_user_s32(protocol, vptr + 2 * n))
1350 return -TARGET_EFAULT;
1351
bellard3532fa72006-06-24 15:06:03 +00001352 ret = do_socket(domain, type, protocol);
bellard7854b052003-03-29 17:22:23 +00001353 }
bellard31e31b82003-02-18 22:55:36 +00001354 break;
1355 case SOCKOP_bind:
bellard7854b052003-03-29 17:22:23 +00001356 {
bellard2f619692007-11-16 10:46:05 +00001357 int sockfd;
1358 abi_ulong target_addr;
1359 socklen_t addrlen;
1360
1361 if (get_user_s32(sockfd, vptr)
1362 || get_user_ual(target_addr, vptr + n)
1363 || get_user_u32(addrlen, vptr + 2 * n))
1364 return -TARGET_EFAULT;
1365
bellard3532fa72006-06-24 15:06:03 +00001366 ret = do_bind(sockfd, target_addr, addrlen);
bellard7854b052003-03-29 17:22:23 +00001367 }
bellard31e31b82003-02-18 22:55:36 +00001368 break;
1369 case SOCKOP_connect:
bellard7854b052003-03-29 17:22:23 +00001370 {
bellard2f619692007-11-16 10:46:05 +00001371 int sockfd;
1372 abi_ulong target_addr;
1373 socklen_t addrlen;
1374
1375 if (get_user_s32(sockfd, vptr)
1376 || get_user_ual(target_addr, vptr + n)
1377 || get_user_u32(addrlen, vptr + 2 * n))
1378 return -TARGET_EFAULT;
1379
bellard3532fa72006-06-24 15:06:03 +00001380 ret = do_connect(sockfd, target_addr, addrlen);
bellard7854b052003-03-29 17:22:23 +00001381 }
bellard31e31b82003-02-18 22:55:36 +00001382 break;
1383 case SOCKOP_listen:
bellard7854b052003-03-29 17:22:23 +00001384 {
bellard2f619692007-11-16 10:46:05 +00001385 int sockfd, backlog;
1386
1387 if (get_user_s32(sockfd, vptr)
1388 || get_user_s32(backlog, vptr + n))
1389 return -TARGET_EFAULT;
1390
bellard7854b052003-03-29 17:22:23 +00001391 ret = get_errno(listen(sockfd, backlog));
1392 }
bellard31e31b82003-02-18 22:55:36 +00001393 break;
1394 case SOCKOP_accept:
1395 {
bellard2f619692007-11-16 10:46:05 +00001396 int sockfd;
1397 abi_ulong target_addr, target_addrlen;
1398
1399 if (get_user_s32(sockfd, vptr)
1400 || get_user_ual(target_addr, vptr + n)
1401 || get_user_u32(target_addrlen, vptr + 2 * n))
1402 return -TARGET_EFAULT;
1403
pbrook1be9e1d2006-11-19 15:26:04 +00001404 ret = do_accept(sockfd, target_addr, target_addrlen);
bellard31e31b82003-02-18 22:55:36 +00001405 }
1406 break;
1407 case SOCKOP_getsockname:
1408 {
bellard2f619692007-11-16 10:46:05 +00001409 int sockfd;
1410 abi_ulong target_addr, target_addrlen;
1411
1412 if (get_user_s32(sockfd, vptr)
1413 || get_user_ual(target_addr, vptr + n)
1414 || get_user_u32(target_addrlen, vptr + 2 * n))
1415 return -TARGET_EFAULT;
1416
pbrook1be9e1d2006-11-19 15:26:04 +00001417 ret = do_getsockname(sockfd, target_addr, target_addrlen);
bellard31e31b82003-02-18 22:55:36 +00001418 }
1419 break;
1420 case SOCKOP_getpeername:
1421 {
bellard2f619692007-11-16 10:46:05 +00001422 int sockfd;
1423 abi_ulong target_addr, target_addrlen;
1424
1425 if (get_user_s32(sockfd, vptr)
1426 || get_user_ual(target_addr, vptr + n)
1427 || get_user_u32(target_addrlen, vptr + 2 * n))
1428 return -TARGET_EFAULT;
1429
pbrook1be9e1d2006-11-19 15:26:04 +00001430 ret = do_getpeername(sockfd, target_addr, target_addrlen);
bellard31e31b82003-02-18 22:55:36 +00001431 }
1432 break;
1433 case SOCKOP_socketpair:
1434 {
bellard2f619692007-11-16 10:46:05 +00001435 int domain, type, protocol;
1436 abi_ulong tab;
1437
1438 if (get_user_s32(domain, vptr)
1439 || get_user_s32(type, vptr + n)
1440 || get_user_s32(protocol, vptr + 2 * n)
1441 || get_user_ual(tab, vptr + 3 * n))
1442 return -TARGET_EFAULT;
1443
pbrook1be9e1d2006-11-19 15:26:04 +00001444 ret = do_socketpair(domain, type, protocol, tab);
bellard31e31b82003-02-18 22:55:36 +00001445 }
1446 break;
1447 case SOCKOP_send:
bellard7854b052003-03-29 17:22:23 +00001448 {
bellard2f619692007-11-16 10:46:05 +00001449 int sockfd;
1450 abi_ulong msg;
1451 size_t len;
1452 int flags;
1453
1454 if (get_user_s32(sockfd, vptr)
1455 || get_user_ual(msg, vptr + n)
1456 || get_user_ual(len, vptr + 2 * n)
1457 || get_user_s32(flags, vptr + 3 * n))
1458 return -TARGET_EFAULT;
1459
pbrook1be9e1d2006-11-19 15:26:04 +00001460 ret = do_sendto(sockfd, msg, len, flags, 0, 0);
bellard7854b052003-03-29 17:22:23 +00001461 }
bellard31e31b82003-02-18 22:55:36 +00001462 break;
1463 case SOCKOP_recv:
bellard7854b052003-03-29 17:22:23 +00001464 {
bellard2f619692007-11-16 10:46:05 +00001465 int sockfd;
1466 abi_ulong msg;
1467 size_t len;
1468 int flags;
1469
1470 if (get_user_s32(sockfd, vptr)
1471 || get_user_ual(msg, vptr + n)
1472 || get_user_ual(len, vptr + 2 * n)
1473 || get_user_s32(flags, vptr + 3 * n))
1474 return -TARGET_EFAULT;
1475
pbrook1be9e1d2006-11-19 15:26:04 +00001476 ret = do_recvfrom(sockfd, msg, len, flags, 0, 0);
bellard7854b052003-03-29 17:22:23 +00001477 }
bellard31e31b82003-02-18 22:55:36 +00001478 break;
1479 case SOCKOP_sendto:
bellard7854b052003-03-29 17:22:23 +00001480 {
bellard2f619692007-11-16 10:46:05 +00001481 int sockfd;
1482 abi_ulong msg;
1483 size_t len;
1484 int flags;
1485 abi_ulong addr;
1486 socklen_t addrlen;
1487
1488 if (get_user_s32(sockfd, vptr)
1489 || get_user_ual(msg, vptr + n)
1490 || get_user_ual(len, vptr + 2 * n)
1491 || get_user_s32(flags, vptr + 3 * n)
1492 || get_user_ual(addr, vptr + 4 * n)
1493 || get_user_u32(addrlen, vptr + 5 * n))
1494 return -TARGET_EFAULT;
1495
pbrook1be9e1d2006-11-19 15:26:04 +00001496 ret = do_sendto(sockfd, msg, len, flags, addr, addrlen);
bellard7854b052003-03-29 17:22:23 +00001497 }
bellard31e31b82003-02-18 22:55:36 +00001498 break;
1499 case SOCKOP_recvfrom:
1500 {
bellard2f619692007-11-16 10:46:05 +00001501 int sockfd;
1502 abi_ulong msg;
1503 size_t len;
1504 int flags;
1505 abi_ulong addr;
1506 socklen_t addrlen;
1507
1508 if (get_user_s32(sockfd, vptr)
1509 || get_user_ual(msg, vptr + n)
1510 || get_user_ual(len, vptr + 2 * n)
1511 || get_user_s32(flags, vptr + 3 * n)
1512 || get_user_ual(addr, vptr + 4 * n)
1513 || get_user_u32(addrlen, vptr + 5 * n))
1514 return -TARGET_EFAULT;
1515
pbrook1be9e1d2006-11-19 15:26:04 +00001516 ret = do_recvfrom(sockfd, msg, len, flags, addr, addrlen);
bellard31e31b82003-02-18 22:55:36 +00001517 }
1518 break;
1519 case SOCKOP_shutdown:
bellard7854b052003-03-29 17:22:23 +00001520 {
bellard2f619692007-11-16 10:46:05 +00001521 int sockfd, how;
1522
1523 if (get_user_s32(sockfd, vptr)
1524 || get_user_s32(how, vptr + n))
1525 return -TARGET_EFAULT;
bellard7854b052003-03-29 17:22:23 +00001526
1527 ret = get_errno(shutdown(sockfd, how));
1528 }
bellard31e31b82003-02-18 22:55:36 +00001529 break;
1530 case SOCKOP_sendmsg:
1531 case SOCKOP_recvmsg:
bellard1a9353d2003-03-16 20:28:50 +00001532 {
1533 int fd;
blueswir1992f48a2007-10-14 16:27:31 +00001534 abi_ulong target_msg;
bellard3532fa72006-06-24 15:06:03 +00001535 int flags;
bellard1a9353d2003-03-16 20:28:50 +00001536
bellard2f619692007-11-16 10:46:05 +00001537 if (get_user_s32(fd, vptr)
1538 || get_user_ual(target_msg, vptr + n)
1539 || get_user_s32(flags, vptr + 2 * n))
1540 return -TARGET_EFAULT;
bellard3532fa72006-06-24 15:06:03 +00001541
ths5fafdf22007-09-16 21:08:06 +00001542 ret = do_sendrecvmsg(fd, target_msg, flags,
bellard3532fa72006-06-24 15:06:03 +00001543 (num == SOCKOP_sendmsg));
bellard1a9353d2003-03-16 20:28:50 +00001544 }
1545 break;
bellard31e31b82003-02-18 22:55:36 +00001546 case SOCKOP_setsockopt:
bellard7854b052003-03-29 17:22:23 +00001547 {
bellard2f619692007-11-16 10:46:05 +00001548 int sockfd;
1549 int level;
1550 int optname;
1551 abi_ulong optval;
1552 socklen_t optlen;
1553
1554 if (get_user_s32(sockfd, vptr)
1555 || get_user_s32(level, vptr + n)
1556 || get_user_s32(optname, vptr + 2 * n)
1557 || get_user_ual(optval, vptr + 3 * n)
1558 || get_user_u32(optlen, vptr + 4 * n))
1559 return -TARGET_EFAULT;
bellard7854b052003-03-29 17:22:23 +00001560
1561 ret = do_setsockopt(sockfd, level, optname, optval, optlen);
1562 }
1563 break;
bellard31e31b82003-02-18 22:55:36 +00001564 case SOCKOP_getsockopt:
bellard7854b052003-03-29 17:22:23 +00001565 {
bellard2f619692007-11-16 10:46:05 +00001566 int sockfd;
1567 int level;
1568 int optname;
1569 abi_ulong optval;
1570 socklen_t optlen;
bellard7854b052003-03-29 17:22:23 +00001571
bellard2f619692007-11-16 10:46:05 +00001572 if (get_user_s32(sockfd, vptr)
1573 || get_user_s32(level, vptr + n)
1574 || get_user_s32(optname, vptr + 2 * n)
1575 || get_user_ual(optval, vptr + 3 * n)
1576 || get_user_u32(optlen, vptr + 4 * n))
1577 return -TARGET_EFAULT;
1578
1579 ret = do_getsockopt(sockfd, level, optname, optval, optlen);
bellard7854b052003-03-29 17:22:23 +00001580 }
1581 break;
bellard31e31b82003-02-18 22:55:36 +00001582 default:
1583 gemu_log("Unsupported socketcall: %d\n", num);
ths0da46a62007-10-20 20:23:07 +00001584 ret = -TARGET_ENOSYS;
bellard31e31b82003-02-18 22:55:36 +00001585 break;
1586 }
1587 return ret;
1588}
j_mayer32407102007-09-26 23:01:49 +00001589#endif
bellard31e31b82003-02-18 22:55:36 +00001590
j_mayer32407102007-09-26 23:01:49 +00001591#ifdef TARGET_NR_ipc
bellard8853f862004-02-22 14:57:26 +00001592#define N_SHM_REGIONS 32
1593
1594static struct shm_region {
bellard5a4a8982007-11-11 17:39:18 +00001595 abi_ulong start;
1596 abi_ulong size;
bellard8853f862004-02-22 14:57:26 +00001597} shm_regions[N_SHM_REGIONS];
1598
ths3eb6b042007-06-03 14:26:27 +00001599struct target_ipc_perm
1600{
blueswir1992f48a2007-10-14 16:27:31 +00001601 abi_long __key;
1602 abi_ulong uid;
1603 abi_ulong gid;
1604 abi_ulong cuid;
1605 abi_ulong cgid;
ths3eb6b042007-06-03 14:26:27 +00001606 unsigned short int mode;
1607 unsigned short int __pad1;
1608 unsigned short int __seq;
1609 unsigned short int __pad2;
blueswir1992f48a2007-10-14 16:27:31 +00001610 abi_ulong __unused1;
1611 abi_ulong __unused2;
ths3eb6b042007-06-03 14:26:27 +00001612};
1613
1614struct target_semid_ds
1615{
1616 struct target_ipc_perm sem_perm;
blueswir1992f48a2007-10-14 16:27:31 +00001617 abi_ulong sem_otime;
1618 abi_ulong __unused1;
1619 abi_ulong sem_ctime;
1620 abi_ulong __unused2;
1621 abi_ulong sem_nsems;
1622 abi_ulong __unused3;
1623 abi_ulong __unused4;
ths3eb6b042007-06-03 14:26:27 +00001624};
1625
bellard579a97f2007-11-11 14:26:47 +00001626static inline abi_long target_to_host_ipc_perm(struct ipc_perm *host_ip,
1627 abi_ulong target_addr)
ths3eb6b042007-06-03 14:26:27 +00001628{
1629 struct target_ipc_perm *target_ip;
1630 struct target_semid_ds *target_sd;
1631
bellard579a97f2007-11-11 14:26:47 +00001632 if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
1633 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00001634 target_ip=&(target_sd->sem_perm);
1635 host_ip->__key = tswapl(target_ip->__key);
1636 host_ip->uid = tswapl(target_ip->uid);
1637 host_ip->gid = tswapl(target_ip->gid);
1638 host_ip->cuid = tswapl(target_ip->cuid);
1639 host_ip->cgid = tswapl(target_ip->cgid);
1640 host_ip->mode = tswapl(target_ip->mode);
1641 unlock_user_struct(target_sd, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00001642 return 0;
ths3eb6b042007-06-03 14:26:27 +00001643}
1644
bellard579a97f2007-11-11 14:26:47 +00001645static inline abi_long host_to_target_ipc_perm(abi_ulong target_addr,
1646 struct ipc_perm *host_ip)
ths3eb6b042007-06-03 14:26:27 +00001647{
1648 struct target_ipc_perm *target_ip;
1649 struct target_semid_ds *target_sd;
1650
bellard579a97f2007-11-11 14:26:47 +00001651 if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
1652 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00001653 target_ip = &(target_sd->sem_perm);
1654 target_ip->__key = tswapl(host_ip->__key);
1655 target_ip->uid = tswapl(host_ip->uid);
1656 target_ip->gid = tswapl(host_ip->gid);
1657 target_ip->cuid = tswapl(host_ip->cuid);
1658 target_ip->cgid = tswapl(host_ip->cgid);
1659 target_ip->mode = tswapl(host_ip->mode);
1660 unlock_user_struct(target_sd, target_addr, 1);
bellard579a97f2007-11-11 14:26:47 +00001661 return 0;
ths3eb6b042007-06-03 14:26:27 +00001662}
1663
bellard579a97f2007-11-11 14:26:47 +00001664static inline abi_long target_to_host_semid_ds(struct semid_ds *host_sd,
1665 abi_ulong target_addr)
ths3eb6b042007-06-03 14:26:27 +00001666{
1667 struct target_semid_ds *target_sd;
1668
bellard579a97f2007-11-11 14:26:47 +00001669 if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
1670 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00001671 target_to_host_ipc_perm(&(host_sd->sem_perm),target_addr);
1672 host_sd->sem_nsems = tswapl(target_sd->sem_nsems);
1673 host_sd->sem_otime = tswapl(target_sd->sem_otime);
1674 host_sd->sem_ctime = tswapl(target_sd->sem_ctime);
1675 unlock_user_struct(target_sd, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00001676 return 0;
ths3eb6b042007-06-03 14:26:27 +00001677}
1678
bellard579a97f2007-11-11 14:26:47 +00001679static inline abi_long host_to_target_semid_ds(abi_ulong target_addr,
1680 struct semid_ds *host_sd)
ths3eb6b042007-06-03 14:26:27 +00001681{
1682 struct target_semid_ds *target_sd;
1683
bellard579a97f2007-11-11 14:26:47 +00001684 if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
1685 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00001686 host_to_target_ipc_perm(target_addr,&(host_sd->sem_perm));
1687 target_sd->sem_nsems = tswapl(host_sd->sem_nsems);
1688 target_sd->sem_otime = tswapl(host_sd->sem_otime);
1689 target_sd->sem_ctime = tswapl(host_sd->sem_ctime);
1690 unlock_user_struct(target_sd, target_addr, 1);
bellard579a97f2007-11-11 14:26:47 +00001691 return 0;
ths3eb6b042007-06-03 14:26:27 +00001692}
1693
thsfa294812007-02-02 22:05:00 +00001694union semun {
1695 int val;
ths3eb6b042007-06-03 14:26:27 +00001696 struct semid_ds *buf;
thsfa294812007-02-02 22:05:00 +00001697 unsigned short *array;
1698};
1699
ths3eb6b042007-06-03 14:26:27 +00001700union target_semun {
1701 int val;
blueswir1992f48a2007-10-14 16:27:31 +00001702 abi_long buf;
ths3eb6b042007-06-03 14:26:27 +00001703 unsigned short int *array;
1704};
1705
bellard579a97f2007-11-11 14:26:47 +00001706static inline abi_long target_to_host_semun(int cmd,
1707 union semun *host_su,
1708 abi_ulong target_addr,
1709 struct semid_ds *ds)
ths3eb6b042007-06-03 14:26:27 +00001710{
1711 union target_semun *target_su;
1712
1713 switch( cmd ) {
1714 case IPC_STAT:
1715 case IPC_SET:
bellard579a97f2007-11-11 14:26:47 +00001716 if (!lock_user_struct(VERIFY_READ, target_su, target_addr, 1))
1717 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00001718 target_to_host_semid_ds(ds,target_su->buf);
1719 host_su->buf = ds;
1720 unlock_user_struct(target_su, target_addr, 0);
1721 break;
1722 case GETVAL:
1723 case SETVAL:
bellard579a97f2007-11-11 14:26:47 +00001724 if (!lock_user_struct(VERIFY_READ, target_su, target_addr, 1))
1725 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00001726 host_su->val = tswapl(target_su->val);
1727 unlock_user_struct(target_su, target_addr, 0);
1728 break;
1729 case GETALL:
1730 case SETALL:
bellard579a97f2007-11-11 14:26:47 +00001731 if (!lock_user_struct(VERIFY_READ, target_su, target_addr, 1))
1732 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00001733 *host_su->array = tswap16(*target_su->array);
1734 unlock_user_struct(target_su, target_addr, 0);
1735 break;
1736 default:
1737 gemu_log("semun operation not fully supported: %d\n", (int)cmd);
1738 }
bellard579a97f2007-11-11 14:26:47 +00001739 return 0;
ths3eb6b042007-06-03 14:26:27 +00001740}
1741
bellard579a97f2007-11-11 14:26:47 +00001742static inline abi_long host_to_target_semun(int cmd,
1743 abi_ulong target_addr,
1744 union semun *host_su,
1745 struct semid_ds *ds)
ths3eb6b042007-06-03 14:26:27 +00001746{
1747 union target_semun *target_su;
1748
1749 switch( cmd ) {
1750 case IPC_STAT:
1751 case IPC_SET:
bellard579a97f2007-11-11 14:26:47 +00001752 if (lock_user_struct(VERIFY_WRITE, target_su, target_addr, 0))
1753 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00001754 host_to_target_semid_ds(target_su->buf,ds);
1755 unlock_user_struct(target_su, target_addr, 1);
1756 break;
1757 case GETVAL:
1758 case SETVAL:
bellard579a97f2007-11-11 14:26:47 +00001759 if (lock_user_struct(VERIFY_WRITE, target_su, target_addr, 0))
1760 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00001761 target_su->val = tswapl(host_su->val);
1762 unlock_user_struct(target_su, target_addr, 1);
1763 break;
1764 case GETALL:
1765 case SETALL:
bellard579a97f2007-11-11 14:26:47 +00001766 if (lock_user_struct(VERIFY_WRITE, target_su, target_addr, 0))
1767 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00001768 *target_su->array = tswap16(*host_su->array);
1769 unlock_user_struct(target_su, target_addr, 1);
1770 break;
1771 default:
1772 gemu_log("semun operation not fully supported: %d\n", (int)cmd);
1773 }
bellard579a97f2007-11-11 14:26:47 +00001774 return 0;
ths3eb6b042007-06-03 14:26:27 +00001775}
1776
blueswir1992f48a2007-10-14 16:27:31 +00001777static inline abi_long do_semctl(int first, int second, int third,
1778 abi_long ptr)
ths3eb6b042007-06-03 14:26:27 +00001779{
1780 union semun arg;
1781 struct semid_ds dsarg;
1782 int cmd = third&0xff;
blueswir1992f48a2007-10-14 16:27:31 +00001783 abi_long ret = 0;
ths3eb6b042007-06-03 14:26:27 +00001784
1785 switch( cmd ) {
1786 case GETVAL:
1787 target_to_host_semun(cmd,&arg,ptr,&dsarg);
1788 ret = get_errno(semctl(first, second, cmd, arg));
1789 host_to_target_semun(cmd,ptr,&arg,&dsarg);
1790 break;
1791 case SETVAL:
1792 target_to_host_semun(cmd,&arg,ptr,&dsarg);
1793 ret = get_errno(semctl(first, second, cmd, arg));
1794 host_to_target_semun(cmd,ptr,&arg,&dsarg);
1795 break;
1796 case GETALL:
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 SETALL:
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 IPC_STAT:
1807 target_to_host_semun(cmd,&arg,ptr,&dsarg);
1808 ret = get_errno(semctl(first, second, cmd, arg));
1809 host_to_target_semun(cmd,ptr,&arg,&dsarg);
1810 break;
1811 case IPC_SET:
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 default:
1817 ret = get_errno(semctl(first, second, cmd, arg));
1818 }
1819
1820 return ret;
1821}
1822
ths1bc012f2007-06-03 14:27:49 +00001823struct target_msqid_ds
1824{
1825 struct target_ipc_perm msg_perm;
blueswir1992f48a2007-10-14 16:27:31 +00001826 abi_ulong msg_stime;
1827 abi_ulong __unused1;
1828 abi_ulong msg_rtime;
1829 abi_ulong __unused2;
1830 abi_ulong msg_ctime;
1831 abi_ulong __unused3;
1832 abi_ulong __msg_cbytes;
1833 abi_ulong msg_qnum;
1834 abi_ulong msg_qbytes;
1835 abi_ulong msg_lspid;
1836 abi_ulong msg_lrpid;
1837 abi_ulong __unused4;
1838 abi_ulong __unused5;
ths1bc012f2007-06-03 14:27:49 +00001839};
1840
bellard579a97f2007-11-11 14:26:47 +00001841static inline abi_long target_to_host_msqid_ds(struct msqid_ds *host_md,
1842 abi_ulong target_addr)
ths1bc012f2007-06-03 14:27:49 +00001843{
1844 struct target_msqid_ds *target_md;
1845
bellard579a97f2007-11-11 14:26:47 +00001846 if (!lock_user_struct(VERIFY_READ, target_md, target_addr, 1))
1847 return -TARGET_EFAULT;
ths1bc012f2007-06-03 14:27:49 +00001848 target_to_host_ipc_perm(&(host_md->msg_perm),target_addr);
1849 host_md->msg_stime = tswapl(target_md->msg_stime);
1850 host_md->msg_rtime = tswapl(target_md->msg_rtime);
1851 host_md->msg_ctime = tswapl(target_md->msg_ctime);
1852 host_md->__msg_cbytes = tswapl(target_md->__msg_cbytes);
1853 host_md->msg_qnum = tswapl(target_md->msg_qnum);
1854 host_md->msg_qbytes = tswapl(target_md->msg_qbytes);
1855 host_md->msg_lspid = tswapl(target_md->msg_lspid);
1856 host_md->msg_lrpid = tswapl(target_md->msg_lrpid);
1857 unlock_user_struct(target_md, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00001858 return 0;
ths1bc012f2007-06-03 14:27:49 +00001859}
1860
bellard579a97f2007-11-11 14:26:47 +00001861static inline abi_long host_to_target_msqid_ds(abi_ulong target_addr,
1862 struct msqid_ds *host_md)
ths1bc012f2007-06-03 14:27:49 +00001863{
1864 struct target_msqid_ds *target_md;
1865
bellard579a97f2007-11-11 14:26:47 +00001866 if (!lock_user_struct(VERIFY_WRITE, target_md, target_addr, 0))
1867 return -TARGET_EFAULT;
ths1bc012f2007-06-03 14:27:49 +00001868 host_to_target_ipc_perm(target_addr,&(host_md->msg_perm));
1869 target_md->msg_stime = tswapl(host_md->msg_stime);
1870 target_md->msg_rtime = tswapl(host_md->msg_rtime);
1871 target_md->msg_ctime = tswapl(host_md->msg_ctime);
1872 target_md->__msg_cbytes = tswapl(host_md->__msg_cbytes);
1873 target_md->msg_qnum = tswapl(host_md->msg_qnum);
1874 target_md->msg_qbytes = tswapl(host_md->msg_qbytes);
1875 target_md->msg_lspid = tswapl(host_md->msg_lspid);
1876 target_md->msg_lrpid = tswapl(host_md->msg_lrpid);
1877 unlock_user_struct(target_md, target_addr, 1);
bellard579a97f2007-11-11 14:26:47 +00001878 return 0;
ths1bc012f2007-06-03 14:27:49 +00001879}
1880
blueswir1992f48a2007-10-14 16:27:31 +00001881static inline abi_long do_msgctl(int first, int second, abi_long ptr)
ths1bc012f2007-06-03 14:27:49 +00001882{
1883 struct msqid_ds dsarg;
1884 int cmd = second&0xff;
blueswir1992f48a2007-10-14 16:27:31 +00001885 abi_long ret = 0;
ths1bc012f2007-06-03 14:27:49 +00001886 switch( cmd ) {
1887 case IPC_STAT:
1888 case IPC_SET:
1889 target_to_host_msqid_ds(&dsarg,ptr);
1890 ret = get_errno(msgctl(first, cmd, &dsarg));
1891 host_to_target_msqid_ds(ptr,&dsarg);
1892 default:
1893 ret = get_errno(msgctl(first, cmd, &dsarg));
1894 }
1895 return ret;
1896}
1897
1898struct target_msgbuf {
blueswir1992f48a2007-10-14 16:27:31 +00001899 abi_ulong mtype;
ths1bc012f2007-06-03 14:27:49 +00001900 char mtext[1];
1901};
1902
blueswir1992f48a2007-10-14 16:27:31 +00001903static inline abi_long do_msgsnd(int msqid, abi_long msgp,
1904 unsigned int msgsz, int msgflg)
ths1bc012f2007-06-03 14:27:49 +00001905{
1906 struct target_msgbuf *target_mb;
1907 struct msgbuf *host_mb;
blueswir1992f48a2007-10-14 16:27:31 +00001908 abi_long ret = 0;
ths1bc012f2007-06-03 14:27:49 +00001909
bellard579a97f2007-11-11 14:26:47 +00001910 if (!lock_user_struct(VERIFY_READ, target_mb, msgp, 0))
1911 return -TARGET_EFAULT;
ths1bc012f2007-06-03 14:27:49 +00001912 host_mb = malloc(msgsz+sizeof(long));
1913 host_mb->mtype = tswapl(target_mb->mtype);
1914 memcpy(host_mb->mtext,target_mb->mtext,msgsz);
1915 ret = get_errno(msgsnd(msqid, host_mb, msgsz, msgflg));
1916 free(host_mb);
1917 unlock_user_struct(target_mb, msgp, 0);
1918
1919 return ret;
1920}
1921
blueswir1992f48a2007-10-14 16:27:31 +00001922static inline abi_long do_msgrcv(int msqid, abi_long msgp,
1923 unsigned int msgsz, int msgtype,
1924 int msgflg)
ths1bc012f2007-06-03 14:27:49 +00001925{
1926 struct target_msgbuf *target_mb;
bellard579a97f2007-11-11 14:26:47 +00001927 char *target_mtext;
ths1bc012f2007-06-03 14:27:49 +00001928 struct msgbuf *host_mb;
blueswir1992f48a2007-10-14 16:27:31 +00001929 abi_long ret = 0;
ths1bc012f2007-06-03 14:27:49 +00001930
bellard579a97f2007-11-11 14:26:47 +00001931 if (!lock_user_struct(VERIFY_WRITE, target_mb, msgp, 0))
1932 return -TARGET_EFAULT;
ths1bc012f2007-06-03 14:27:49 +00001933 host_mb = malloc(msgsz+sizeof(long));
1934 ret = get_errno(msgrcv(msqid, host_mb, msgsz, 1, msgflg));
bellard579a97f2007-11-11 14:26:47 +00001935 if (ret > 0) {
1936 abi_ulong target_mtext_addr = msgp + sizeof(abi_ulong);
1937 target_mtext = lock_user(VERIFY_WRITE, target_mtext_addr, ret, 0);
1938 if (!target_mtext) {
1939 ret = -TARGET_EFAULT;
1940 goto end;
1941 }
ths1bc012f2007-06-03 14:27:49 +00001942 memcpy(target_mb->mtext, host_mb->mtext, ret);
bellard579a97f2007-11-11 14:26:47 +00001943 unlock_user(target_mtext, target_mtext_addr, ret);
1944 }
ths1bc012f2007-06-03 14:27:49 +00001945 target_mb->mtype = tswapl(host_mb->mtype);
1946 free(host_mb);
ths1bc012f2007-06-03 14:27:49 +00001947
bellard579a97f2007-11-11 14:26:47 +00001948end:
1949 if (target_mb)
1950 unlock_user_struct(target_mb, msgp, 1);
ths1bc012f2007-06-03 14:27:49 +00001951 return ret;
1952}
1953
pbrook53a59602006-03-25 19:31:22 +00001954/* ??? This only works with linear mappings. */
ths0da46a62007-10-20 20:23:07 +00001955/* do_ipc() must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001956static abi_long do_ipc(unsigned int call, int first,
1957 int second, int third,
1958 abi_long ptr, abi_long fifth)
bellard8853f862004-02-22 14:57:26 +00001959{
1960 int version;
blueswir1992f48a2007-10-14 16:27:31 +00001961 abi_long ret = 0;
bellard8853f862004-02-22 14:57:26 +00001962 struct shmid_ds shm_info;
1963 int i;
1964
1965 version = call >> 16;
1966 call &= 0xffff;
1967
1968 switch (call) {
thsfa294812007-02-02 22:05:00 +00001969 case IPCOP_semop:
bellard579a97f2007-11-11 14:26:47 +00001970 ret = get_errno(semop(first,(struct sembuf *)g2h(ptr), second));
thsfa294812007-02-02 22:05:00 +00001971 break;
1972
1973 case IPCOP_semget:
1974 ret = get_errno(semget(first, second, third));
1975 break;
1976
1977 case IPCOP_semctl:
ths3eb6b042007-06-03 14:26:27 +00001978 ret = do_semctl(first, second, third, ptr);
thsfa294812007-02-02 22:05:00 +00001979 break;
1980
1981 case IPCOP_semtimedop:
j_mayer32407102007-09-26 23:01:49 +00001982 gemu_log("Unsupported ipc call: %d (version %d)\n", call, version);
ths0da46a62007-10-20 20:23:07 +00001983 ret = -TARGET_ENOSYS;
thsfa294812007-02-02 22:05:00 +00001984 break;
thsd96372e2007-02-02 22:05:44 +00001985
1986 case IPCOP_msgget:
1987 ret = get_errno(msgget(first, second));
1988 break;
1989
1990 case IPCOP_msgsnd:
ths1bc012f2007-06-03 14:27:49 +00001991 ret = do_msgsnd(first, ptr, second, third);
thsd96372e2007-02-02 22:05:44 +00001992 break;
1993
1994 case IPCOP_msgctl:
ths1bc012f2007-06-03 14:27:49 +00001995 ret = do_msgctl(first, second, ptr);
thsd96372e2007-02-02 22:05:44 +00001996 break;
1997
1998 case IPCOP_msgrcv:
ths1bc012f2007-06-03 14:27:49 +00001999 {
bellard579a97f2007-11-11 14:26:47 +00002000 /* XXX: this code is not correct */
ths1bc012f2007-06-03 14:27:49 +00002001 struct ipc_kludge
2002 {
2003 void *__unbounded msgp;
2004 long int msgtyp;
2005 };
thsd96372e2007-02-02 22:05:44 +00002006
bellard579a97f2007-11-11 14:26:47 +00002007 struct ipc_kludge *foo = (struct ipc_kludge *)g2h(ptr);
ths1bc012f2007-06-03 14:27:49 +00002008 struct msgbuf *msgp = (struct msgbuf *) foo->msgp;
thsd96372e2007-02-02 22:05:44 +00002009
ths1bc012f2007-06-03 14:27:49 +00002010 ret = do_msgrcv(first, (long)msgp, second, 0, third);
thsd96372e2007-02-02 22:05:44 +00002011
ths1bc012f2007-06-03 14:27:49 +00002012 }
thsd96372e2007-02-02 22:05:44 +00002013 break;
2014
bellard8853f862004-02-22 14:57:26 +00002015 case IPCOP_shmat:
bellard5a4a8982007-11-11 17:39:18 +00002016 {
2017 abi_ulong raddr;
2018 void *host_addr;
2019 /* SHM_* flags are the same on all linux platforms */
2020 host_addr = shmat(first, (void *)g2h(ptr), second);
2021 if (host_addr == (void *)-1) {
2022 ret = get_errno((long)host_addr);
bellard8853f862004-02-22 14:57:26 +00002023 break;
bellard5a4a8982007-11-11 17:39:18 +00002024 }
2025 raddr = h2g((unsigned long)host_addr);
2026 /* find out the length of the shared memory segment */
2027
2028 ret = get_errno(shmctl(first, IPC_STAT, &shm_info));
2029 if (is_error(ret)) {
2030 /* can't get length, bail out */
2031 shmdt(host_addr);
2032 break;
2033 }
2034 page_set_flags(raddr, raddr + shm_info.shm_segsz,
2035 PAGE_VALID | PAGE_READ |
2036 ((second & SHM_RDONLY)? 0: PAGE_WRITE));
2037 for (i = 0; i < N_SHM_REGIONS; ++i) {
2038 if (shm_regions[i].start == 0) {
2039 shm_regions[i].start = raddr;
2040 shm_regions[i].size = shm_info.shm_segsz;
2041 break;
2042 }
2043 }
bellard2f619692007-11-16 10:46:05 +00002044 if (put_user_ual(raddr, third))
bellard5a4a8982007-11-11 17:39:18 +00002045 return -TARGET_EFAULT;
2046 ret = 0;
2047 }
bellard8853f862004-02-22 14:57:26 +00002048 break;
2049 case IPCOP_shmdt:
2050 for (i = 0; i < N_SHM_REGIONS; ++i) {
2051 if (shm_regions[i].start == ptr) {
2052 shm_regions[i].start = 0;
2053 page_set_flags(ptr, shm_regions[i].size, 0);
2054 break;
2055 }
2056 }
bellard5a4a8982007-11-11 17:39:18 +00002057 ret = get_errno(shmdt((void *)g2h(ptr)));
bellard8853f862004-02-22 14:57:26 +00002058 break;
2059
2060 case IPCOP_shmget:
2061 /* IPC_* flag values are the same on all linux platforms */
2062 ret = get_errno(shmget(first, second, third));
2063 break;
2064
2065 /* IPC_* and SHM_* command values are the same on all linux platforms */
2066 case IPCOP_shmctl:
2067 switch(second) {
2068 case IPC_RMID:
2069 case SHM_LOCK:
2070 case SHM_UNLOCK:
2071 ret = get_errno(shmctl(first, second, NULL));
2072 break;
2073 default:
2074 goto unimplemented;
2075 }
2076 break;
2077 default:
2078 unimplemented:
j_mayer32407102007-09-26 23:01:49 +00002079 gemu_log("Unsupported ipc call: %d (version %d)\n", call, version);
ths0da46a62007-10-20 20:23:07 +00002080 ret = -TARGET_ENOSYS;
bellard8853f862004-02-22 14:57:26 +00002081 break;
2082 }
2083 return ret;
2084}
j_mayer32407102007-09-26 23:01:49 +00002085#endif
bellard8853f862004-02-22 14:57:26 +00002086
bellard31e31b82003-02-18 22:55:36 +00002087/* kernel structure types definitions */
2088#define IFNAMSIZ 16
2089
2090#define STRUCT(name, list...) STRUCT_ ## name,
2091#define STRUCT_SPECIAL(name) STRUCT_ ## name,
2092enum {
2093#include "syscall_types.h"
2094};
2095#undef STRUCT
2096#undef STRUCT_SPECIAL
2097
2098#define STRUCT(name, list...) const argtype struct_ ## name ## _def[] = { list, TYPE_NULL };
2099#define STRUCT_SPECIAL(name)
2100#include "syscall_types.h"
2101#undef STRUCT
2102#undef STRUCT_SPECIAL
2103
2104typedef struct IOCTLEntry {
bellard2ab83ea2003-06-15 19:56:46 +00002105 unsigned int target_cmd;
2106 unsigned int host_cmd;
bellard31e31b82003-02-18 22:55:36 +00002107 const char *name;
2108 int access;
bellard1a9353d2003-03-16 20:28:50 +00002109 const argtype arg_type[5];
bellard31e31b82003-02-18 22:55:36 +00002110} IOCTLEntry;
2111
2112#define IOC_R 0x0001
2113#define IOC_W 0x0002
2114#define IOC_RW (IOC_R | IOC_W)
2115
2116#define MAX_STRUCT_SIZE 4096
2117
bellard2ab83ea2003-06-15 19:56:46 +00002118IOCTLEntry ioctl_entries[] = {
bellard31e31b82003-02-18 22:55:36 +00002119#define IOCTL(cmd, access, types...) \
2120 { TARGET_ ## cmd, cmd, #cmd, access, { types } },
2121#include "ioctls.h"
2122 { 0, 0, },
2123};
2124
pbrook53a59602006-03-25 19:31:22 +00002125/* ??? Implement proper locking for ioctls. */
ths0da46a62007-10-20 20:23:07 +00002126/* do_ioctl() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00002127static abi_long do_ioctl(int fd, abi_long cmd, abi_long arg)
bellard31e31b82003-02-18 22:55:36 +00002128{
2129 const IOCTLEntry *ie;
2130 const argtype *arg_type;
blueswir1992f48a2007-10-14 16:27:31 +00002131 abi_long ret;
bellard31e31b82003-02-18 22:55:36 +00002132 uint8_t buf_temp[MAX_STRUCT_SIZE];
pbrook53a59602006-03-25 19:31:22 +00002133 int target_size;
2134 void *argptr;
bellard31e31b82003-02-18 22:55:36 +00002135
2136 ie = ioctl_entries;
2137 for(;;) {
2138 if (ie->target_cmd == 0) {
j_mayer32407102007-09-26 23:01:49 +00002139 gemu_log("Unsupported ioctl: cmd=0x%04lx\n", (long)cmd);
ths0da46a62007-10-20 20:23:07 +00002140 return -TARGET_ENOSYS;
bellard31e31b82003-02-18 22:55:36 +00002141 }
2142 if (ie->target_cmd == cmd)
2143 break;
2144 ie++;
2145 }
2146 arg_type = ie->arg_type;
bellard9de5e442003-03-23 16:49:39 +00002147#if defined(DEBUG)
j_mayer32407102007-09-26 23:01:49 +00002148 gemu_log("ioctl: cmd=0x%04lx (%s)\n", (long)cmd, ie->name);
bellard72f03902003-02-18 23:33:18 +00002149#endif
bellard31e31b82003-02-18 22:55:36 +00002150 switch(arg_type[0]) {
2151 case TYPE_NULL:
2152 /* no argument */
2153 ret = get_errno(ioctl(fd, ie->host_cmd));
2154 break;
2155 case TYPE_PTRVOID:
2156 case TYPE_INT:
2157 /* int argment */
2158 ret = get_errno(ioctl(fd, ie->host_cmd, arg));
2159 break;
2160 case TYPE_PTR:
2161 arg_type++;
pbrook53a59602006-03-25 19:31:22 +00002162 target_size = thunk_type_size(arg_type, 0);
bellard31e31b82003-02-18 22:55:36 +00002163 switch(ie->access) {
2164 case IOC_R:
2165 ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
2166 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00002167 argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
2168 if (!argptr)
2169 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00002170 thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
2171 unlock_user(argptr, arg, target_size);
bellard31e31b82003-02-18 22:55:36 +00002172 }
2173 break;
2174 case IOC_W:
bellard579a97f2007-11-11 14:26:47 +00002175 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
2176 if (!argptr)
2177 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00002178 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
2179 unlock_user(argptr, arg, 0);
bellard31e31b82003-02-18 22:55:36 +00002180 ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
2181 break;
2182 default:
2183 case IOC_RW:
bellard579a97f2007-11-11 14:26:47 +00002184 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
2185 if (!argptr)
2186 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00002187 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
2188 unlock_user(argptr, arg, 0);
bellard31e31b82003-02-18 22:55:36 +00002189 ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
2190 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00002191 argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
2192 if (!argptr)
2193 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00002194 thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
2195 unlock_user(argptr, arg, target_size);
bellard31e31b82003-02-18 22:55:36 +00002196 }
2197 break;
2198 }
2199 break;
2200 default:
j_mayer32407102007-09-26 23:01:49 +00002201 gemu_log("Unsupported ioctl type: cmd=0x%04lx type=%d\n",
2202 (long)cmd, arg_type[0]);
ths0da46a62007-10-20 20:23:07 +00002203 ret = -TARGET_ENOSYS;
bellard31e31b82003-02-18 22:55:36 +00002204 break;
2205 }
2206 return ret;
2207}
2208
2209bitmask_transtbl iflag_tbl[] = {
2210 { TARGET_IGNBRK, TARGET_IGNBRK, IGNBRK, IGNBRK },
2211 { TARGET_BRKINT, TARGET_BRKINT, BRKINT, BRKINT },
2212 { TARGET_IGNPAR, TARGET_IGNPAR, IGNPAR, IGNPAR },
2213 { TARGET_PARMRK, TARGET_PARMRK, PARMRK, PARMRK },
2214 { TARGET_INPCK, TARGET_INPCK, INPCK, INPCK },
2215 { TARGET_ISTRIP, TARGET_ISTRIP, ISTRIP, ISTRIP },
2216 { TARGET_INLCR, TARGET_INLCR, INLCR, INLCR },
2217 { TARGET_IGNCR, TARGET_IGNCR, IGNCR, IGNCR },
2218 { TARGET_ICRNL, TARGET_ICRNL, ICRNL, ICRNL },
2219 { TARGET_IUCLC, TARGET_IUCLC, IUCLC, IUCLC },
2220 { TARGET_IXON, TARGET_IXON, IXON, IXON },
2221 { TARGET_IXANY, TARGET_IXANY, IXANY, IXANY },
2222 { TARGET_IXOFF, TARGET_IXOFF, IXOFF, IXOFF },
2223 { TARGET_IMAXBEL, TARGET_IMAXBEL, IMAXBEL, IMAXBEL },
2224 { 0, 0, 0, 0 }
2225};
2226
2227bitmask_transtbl oflag_tbl[] = {
2228 { TARGET_OPOST, TARGET_OPOST, OPOST, OPOST },
2229 { TARGET_OLCUC, TARGET_OLCUC, OLCUC, OLCUC },
2230 { TARGET_ONLCR, TARGET_ONLCR, ONLCR, ONLCR },
2231 { TARGET_OCRNL, TARGET_OCRNL, OCRNL, OCRNL },
2232 { TARGET_ONOCR, TARGET_ONOCR, ONOCR, ONOCR },
2233 { TARGET_ONLRET, TARGET_ONLRET, ONLRET, ONLRET },
2234 { TARGET_OFILL, TARGET_OFILL, OFILL, OFILL },
2235 { TARGET_OFDEL, TARGET_OFDEL, OFDEL, OFDEL },
2236 { TARGET_NLDLY, TARGET_NL0, NLDLY, NL0 },
2237 { TARGET_NLDLY, TARGET_NL1, NLDLY, NL1 },
2238 { TARGET_CRDLY, TARGET_CR0, CRDLY, CR0 },
2239 { TARGET_CRDLY, TARGET_CR1, CRDLY, CR1 },
2240 { TARGET_CRDLY, TARGET_CR2, CRDLY, CR2 },
2241 { TARGET_CRDLY, TARGET_CR3, CRDLY, CR3 },
2242 { TARGET_TABDLY, TARGET_TAB0, TABDLY, TAB0 },
2243 { TARGET_TABDLY, TARGET_TAB1, TABDLY, TAB1 },
2244 { TARGET_TABDLY, TARGET_TAB2, TABDLY, TAB2 },
2245 { TARGET_TABDLY, TARGET_TAB3, TABDLY, TAB3 },
2246 { TARGET_BSDLY, TARGET_BS0, BSDLY, BS0 },
2247 { TARGET_BSDLY, TARGET_BS1, BSDLY, BS1 },
2248 { TARGET_VTDLY, TARGET_VT0, VTDLY, VT0 },
2249 { TARGET_VTDLY, TARGET_VT1, VTDLY, VT1 },
2250 { TARGET_FFDLY, TARGET_FF0, FFDLY, FF0 },
2251 { TARGET_FFDLY, TARGET_FF1, FFDLY, FF1 },
2252 { 0, 0, 0, 0 }
2253};
2254
2255bitmask_transtbl cflag_tbl[] = {
2256 { TARGET_CBAUD, TARGET_B0, CBAUD, B0 },
2257 { TARGET_CBAUD, TARGET_B50, CBAUD, B50 },
2258 { TARGET_CBAUD, TARGET_B75, CBAUD, B75 },
2259 { TARGET_CBAUD, TARGET_B110, CBAUD, B110 },
2260 { TARGET_CBAUD, TARGET_B134, CBAUD, B134 },
2261 { TARGET_CBAUD, TARGET_B150, CBAUD, B150 },
2262 { TARGET_CBAUD, TARGET_B200, CBAUD, B200 },
2263 { TARGET_CBAUD, TARGET_B300, CBAUD, B300 },
2264 { TARGET_CBAUD, TARGET_B600, CBAUD, B600 },
2265 { TARGET_CBAUD, TARGET_B1200, CBAUD, B1200 },
2266 { TARGET_CBAUD, TARGET_B1800, CBAUD, B1800 },
2267 { TARGET_CBAUD, TARGET_B2400, CBAUD, B2400 },
2268 { TARGET_CBAUD, TARGET_B4800, CBAUD, B4800 },
2269 { TARGET_CBAUD, TARGET_B9600, CBAUD, B9600 },
2270 { TARGET_CBAUD, TARGET_B19200, CBAUD, B19200 },
2271 { TARGET_CBAUD, TARGET_B38400, CBAUD, B38400 },
2272 { TARGET_CBAUD, TARGET_B57600, CBAUD, B57600 },
2273 { TARGET_CBAUD, TARGET_B115200, CBAUD, B115200 },
2274 { TARGET_CBAUD, TARGET_B230400, CBAUD, B230400 },
2275 { TARGET_CBAUD, TARGET_B460800, CBAUD, B460800 },
2276 { TARGET_CSIZE, TARGET_CS5, CSIZE, CS5 },
2277 { TARGET_CSIZE, TARGET_CS6, CSIZE, CS6 },
2278 { TARGET_CSIZE, TARGET_CS7, CSIZE, CS7 },
2279 { TARGET_CSIZE, TARGET_CS8, CSIZE, CS8 },
2280 { TARGET_CSTOPB, TARGET_CSTOPB, CSTOPB, CSTOPB },
2281 { TARGET_CREAD, TARGET_CREAD, CREAD, CREAD },
2282 { TARGET_PARENB, TARGET_PARENB, PARENB, PARENB },
2283 { TARGET_PARODD, TARGET_PARODD, PARODD, PARODD },
2284 { TARGET_HUPCL, TARGET_HUPCL, HUPCL, HUPCL },
2285 { TARGET_CLOCAL, TARGET_CLOCAL, CLOCAL, CLOCAL },
2286 { TARGET_CRTSCTS, TARGET_CRTSCTS, CRTSCTS, CRTSCTS },
2287 { 0, 0, 0, 0 }
2288};
2289
2290bitmask_transtbl lflag_tbl[] = {
2291 { TARGET_ISIG, TARGET_ISIG, ISIG, ISIG },
2292 { TARGET_ICANON, TARGET_ICANON, ICANON, ICANON },
2293 { TARGET_XCASE, TARGET_XCASE, XCASE, XCASE },
2294 { TARGET_ECHO, TARGET_ECHO, ECHO, ECHO },
2295 { TARGET_ECHOE, TARGET_ECHOE, ECHOE, ECHOE },
2296 { TARGET_ECHOK, TARGET_ECHOK, ECHOK, ECHOK },
2297 { TARGET_ECHONL, TARGET_ECHONL, ECHONL, ECHONL },
2298 { TARGET_NOFLSH, TARGET_NOFLSH, NOFLSH, NOFLSH },
2299 { TARGET_TOSTOP, TARGET_TOSTOP, TOSTOP, TOSTOP },
2300 { TARGET_ECHOCTL, TARGET_ECHOCTL, ECHOCTL, ECHOCTL },
2301 { TARGET_ECHOPRT, TARGET_ECHOPRT, ECHOPRT, ECHOPRT },
2302 { TARGET_ECHOKE, TARGET_ECHOKE, ECHOKE, ECHOKE },
2303 { TARGET_FLUSHO, TARGET_FLUSHO, FLUSHO, FLUSHO },
2304 { TARGET_PENDIN, TARGET_PENDIN, PENDIN, PENDIN },
2305 { TARGET_IEXTEN, TARGET_IEXTEN, IEXTEN, IEXTEN },
2306 { 0, 0, 0, 0 }
2307};
2308
2309static void target_to_host_termios (void *dst, const void *src)
2310{
2311 struct host_termios *host = dst;
2312 const struct target_termios *target = src;
ths3b46e622007-09-17 08:09:54 +00002313
ths5fafdf22007-09-16 21:08:06 +00002314 host->c_iflag =
bellard31e31b82003-02-18 22:55:36 +00002315 target_to_host_bitmask(tswap32(target->c_iflag), iflag_tbl);
ths5fafdf22007-09-16 21:08:06 +00002316 host->c_oflag =
bellard31e31b82003-02-18 22:55:36 +00002317 target_to_host_bitmask(tswap32(target->c_oflag), oflag_tbl);
ths5fafdf22007-09-16 21:08:06 +00002318 host->c_cflag =
bellard31e31b82003-02-18 22:55:36 +00002319 target_to_host_bitmask(tswap32(target->c_cflag), cflag_tbl);
ths5fafdf22007-09-16 21:08:06 +00002320 host->c_lflag =
bellard31e31b82003-02-18 22:55:36 +00002321 target_to_host_bitmask(tswap32(target->c_lflag), lflag_tbl);
2322 host->c_line = target->c_line;
ths3b46e622007-09-17 08:09:54 +00002323
ths5fafdf22007-09-16 21:08:06 +00002324 host->c_cc[VINTR] = target->c_cc[TARGET_VINTR];
2325 host->c_cc[VQUIT] = target->c_cc[TARGET_VQUIT];
ths3b46e622007-09-17 08:09:54 +00002326 host->c_cc[VERASE] = target->c_cc[TARGET_VERASE];
ths5fafdf22007-09-16 21:08:06 +00002327 host->c_cc[VKILL] = target->c_cc[TARGET_VKILL];
ths3b46e622007-09-17 08:09:54 +00002328 host->c_cc[VEOF] = target->c_cc[TARGET_VEOF];
ths5fafdf22007-09-16 21:08:06 +00002329 host->c_cc[VTIME] = target->c_cc[TARGET_VTIME];
ths3b46e622007-09-17 08:09:54 +00002330 host->c_cc[VMIN] = target->c_cc[TARGET_VMIN];
ths5fafdf22007-09-16 21:08:06 +00002331 host->c_cc[VSWTC] = target->c_cc[TARGET_VSWTC];
ths3b46e622007-09-17 08:09:54 +00002332 host->c_cc[VSTART] = target->c_cc[TARGET_VSTART];
ths5fafdf22007-09-16 21:08:06 +00002333 host->c_cc[VSTOP] = target->c_cc[TARGET_VSTOP];
2334 host->c_cc[VSUSP] = target->c_cc[TARGET_VSUSP];
ths3b46e622007-09-17 08:09:54 +00002335 host->c_cc[VEOL] = target->c_cc[TARGET_VEOL];
2336 host->c_cc[VREPRINT] = target->c_cc[TARGET_VREPRINT];
2337 host->c_cc[VDISCARD] = target->c_cc[TARGET_VDISCARD];
2338 host->c_cc[VWERASE] = target->c_cc[TARGET_VWERASE];
2339 host->c_cc[VLNEXT] = target->c_cc[TARGET_VLNEXT];
ths5fafdf22007-09-16 21:08:06 +00002340 host->c_cc[VEOL2] = target->c_cc[TARGET_VEOL2];
bellard31e31b82003-02-18 22:55:36 +00002341}
ths3b46e622007-09-17 08:09:54 +00002342
bellard31e31b82003-02-18 22:55:36 +00002343static void host_to_target_termios (void *dst, const void *src)
2344{
2345 struct target_termios *target = dst;
2346 const struct host_termios *host = src;
2347
ths5fafdf22007-09-16 21:08:06 +00002348 target->c_iflag =
bellard31e31b82003-02-18 22:55:36 +00002349 tswap32(host_to_target_bitmask(host->c_iflag, iflag_tbl));
ths5fafdf22007-09-16 21:08:06 +00002350 target->c_oflag =
bellard31e31b82003-02-18 22:55:36 +00002351 tswap32(host_to_target_bitmask(host->c_oflag, oflag_tbl));
ths5fafdf22007-09-16 21:08:06 +00002352 target->c_cflag =
bellard31e31b82003-02-18 22:55:36 +00002353 tswap32(host_to_target_bitmask(host->c_cflag, cflag_tbl));
ths5fafdf22007-09-16 21:08:06 +00002354 target->c_lflag =
bellard31e31b82003-02-18 22:55:36 +00002355 tswap32(host_to_target_bitmask(host->c_lflag, lflag_tbl));
2356 target->c_line = host->c_line;
ths3b46e622007-09-17 08:09:54 +00002357
bellard31e31b82003-02-18 22:55:36 +00002358 target->c_cc[TARGET_VINTR] = host->c_cc[VINTR];
2359 target->c_cc[TARGET_VQUIT] = host->c_cc[VQUIT];
2360 target->c_cc[TARGET_VERASE] = host->c_cc[VERASE];
2361 target->c_cc[TARGET_VKILL] = host->c_cc[VKILL];
2362 target->c_cc[TARGET_VEOF] = host->c_cc[VEOF];
2363 target->c_cc[TARGET_VTIME] = host->c_cc[VTIME];
2364 target->c_cc[TARGET_VMIN] = host->c_cc[VMIN];
2365 target->c_cc[TARGET_VSWTC] = host->c_cc[VSWTC];
2366 target->c_cc[TARGET_VSTART] = host->c_cc[VSTART];
2367 target->c_cc[TARGET_VSTOP] = host->c_cc[VSTOP];
2368 target->c_cc[TARGET_VSUSP] = host->c_cc[VSUSP];
2369 target->c_cc[TARGET_VEOL] = host->c_cc[VEOL];
2370 target->c_cc[TARGET_VREPRINT] = host->c_cc[VREPRINT];
2371 target->c_cc[TARGET_VDISCARD] = host->c_cc[VDISCARD];
2372 target->c_cc[TARGET_VWERASE] = host->c_cc[VWERASE];
2373 target->c_cc[TARGET_VLNEXT] = host->c_cc[VLNEXT];
2374 target->c_cc[TARGET_VEOL2] = host->c_cc[VEOL2];
2375}
2376
2377StructEntry struct_termios_def = {
2378 .convert = { host_to_target_termios, target_to_host_termios },
2379 .size = { sizeof(struct target_termios), sizeof(struct host_termios) },
2380 .align = { __alignof__(struct target_termios), __alignof__(struct host_termios) },
2381};
2382
bellard5286db72003-06-05 00:57:30 +00002383static bitmask_transtbl mmap_flags_tbl[] = {
2384 { TARGET_MAP_SHARED, TARGET_MAP_SHARED, MAP_SHARED, MAP_SHARED },
2385 { TARGET_MAP_PRIVATE, TARGET_MAP_PRIVATE, MAP_PRIVATE, MAP_PRIVATE },
2386 { TARGET_MAP_FIXED, TARGET_MAP_FIXED, MAP_FIXED, MAP_FIXED },
2387 { TARGET_MAP_ANONYMOUS, TARGET_MAP_ANONYMOUS, MAP_ANONYMOUS, MAP_ANONYMOUS },
2388 { TARGET_MAP_GROWSDOWN, TARGET_MAP_GROWSDOWN, MAP_GROWSDOWN, MAP_GROWSDOWN },
2389 { TARGET_MAP_DENYWRITE, TARGET_MAP_DENYWRITE, MAP_DENYWRITE, MAP_DENYWRITE },
2390 { TARGET_MAP_EXECUTABLE, TARGET_MAP_EXECUTABLE, MAP_EXECUTABLE, MAP_EXECUTABLE },
2391 { TARGET_MAP_LOCKED, TARGET_MAP_LOCKED, MAP_LOCKED, MAP_LOCKED },
2392 { 0, 0, 0, 0 }
2393};
2394
bellardffa65c32004-01-04 23:57:22 +00002395static bitmask_transtbl fcntl_flags_tbl[] = {
2396 { TARGET_O_ACCMODE, TARGET_O_WRONLY, O_ACCMODE, O_WRONLY, },
2397 { TARGET_O_ACCMODE, TARGET_O_RDWR, O_ACCMODE, O_RDWR, },
2398 { TARGET_O_CREAT, TARGET_O_CREAT, O_CREAT, O_CREAT, },
2399 { TARGET_O_EXCL, TARGET_O_EXCL, O_EXCL, O_EXCL, },
2400 { TARGET_O_NOCTTY, TARGET_O_NOCTTY, O_NOCTTY, O_NOCTTY, },
2401 { TARGET_O_TRUNC, TARGET_O_TRUNC, O_TRUNC, O_TRUNC, },
2402 { TARGET_O_APPEND, TARGET_O_APPEND, O_APPEND, O_APPEND, },
2403 { TARGET_O_NONBLOCK, TARGET_O_NONBLOCK, O_NONBLOCK, O_NONBLOCK, },
2404 { TARGET_O_SYNC, TARGET_O_SYNC, O_SYNC, O_SYNC, },
2405 { TARGET_FASYNC, TARGET_FASYNC, FASYNC, FASYNC, },
2406 { TARGET_O_DIRECTORY, TARGET_O_DIRECTORY, O_DIRECTORY, O_DIRECTORY, },
2407 { TARGET_O_NOFOLLOW, TARGET_O_NOFOLLOW, O_NOFOLLOW, O_NOFOLLOW, },
2408 { TARGET_O_LARGEFILE, TARGET_O_LARGEFILE, O_LARGEFILE, O_LARGEFILE, },
bellard121061d2004-02-22 11:56:01 +00002409#if defined(O_DIRECT)
bellardffa65c32004-01-04 23:57:22 +00002410 { TARGET_O_DIRECT, TARGET_O_DIRECT, O_DIRECT, O_DIRECT, },
bellard121061d2004-02-22 11:56:01 +00002411#endif
bellardffa65c32004-01-04 23:57:22 +00002412 { 0, 0, 0, 0 }
2413};
2414
bellard2ab83ea2003-06-15 19:56:46 +00002415#if defined(TARGET_I386)
bellard6dbad632003-03-16 18:05:05 +00002416
2417/* NOTE: there is really one LDT for all the threads */
2418uint8_t *ldt_table;
2419
bellard03acab62007-11-11 14:57:14 +00002420static abi_long read_ldt(abi_ulong ptr, unsigned long bytecount)
bellard6dbad632003-03-16 18:05:05 +00002421{
2422 int size;
pbrook53a59602006-03-25 19:31:22 +00002423 void *p;
bellard6dbad632003-03-16 18:05:05 +00002424
2425 if (!ldt_table)
2426 return 0;
2427 size = TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE;
2428 if (size > bytecount)
2429 size = bytecount;
bellard579a97f2007-11-11 14:26:47 +00002430 p = lock_user(VERIFY_WRITE, ptr, size, 0);
2431 if (!p)
bellard03acab62007-11-11 14:57:14 +00002432 return -TARGET_EFAULT;
bellard579a97f2007-11-11 14:26:47 +00002433 /* ??? Should this by byteswapped? */
pbrook53a59602006-03-25 19:31:22 +00002434 memcpy(p, ldt_table, size);
2435 unlock_user(p, ptr, size);
bellard6dbad632003-03-16 18:05:05 +00002436 return size;
2437}
2438
2439/* XXX: add locking support */
bellard03acab62007-11-11 14:57:14 +00002440static abi_long write_ldt(CPUX86State *env,
2441 abi_ulong ptr, unsigned long bytecount, int oldmode)
bellard6dbad632003-03-16 18:05:05 +00002442{
2443 struct target_modify_ldt_ldt_s ldt_info;
pbrook53a59602006-03-25 19:31:22 +00002444 struct target_modify_ldt_ldt_s *target_ldt_info;
bellard6dbad632003-03-16 18:05:05 +00002445 int seg_32bit, contents, read_exec_only, limit_in_pages;
bellard8d18e892007-11-14 15:18:40 +00002446 int seg_not_present, useable, lm;
bellard6dbad632003-03-16 18:05:05 +00002447 uint32_t *lp, entry_1, entry_2;
2448
2449 if (bytecount != sizeof(ldt_info))
bellard03acab62007-11-11 14:57:14 +00002450 return -TARGET_EINVAL;
bellard579a97f2007-11-11 14:26:47 +00002451 if (!lock_user_struct(VERIFY_READ, target_ldt_info, ptr, 1))
bellard03acab62007-11-11 14:57:14 +00002452 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00002453 ldt_info.entry_number = tswap32(target_ldt_info->entry_number);
2454 ldt_info.base_addr = tswapl(target_ldt_info->base_addr);
2455 ldt_info.limit = tswap32(target_ldt_info->limit);
2456 ldt_info.flags = tswap32(target_ldt_info->flags);
2457 unlock_user_struct(target_ldt_info, ptr, 0);
ths3b46e622007-09-17 08:09:54 +00002458
bellard6dbad632003-03-16 18:05:05 +00002459 if (ldt_info.entry_number >= TARGET_LDT_ENTRIES)
bellard03acab62007-11-11 14:57:14 +00002460 return -TARGET_EINVAL;
bellard6dbad632003-03-16 18:05:05 +00002461 seg_32bit = ldt_info.flags & 1;
2462 contents = (ldt_info.flags >> 1) & 3;
2463 read_exec_only = (ldt_info.flags >> 3) & 1;
2464 limit_in_pages = (ldt_info.flags >> 4) & 1;
2465 seg_not_present = (ldt_info.flags >> 5) & 1;
2466 useable = (ldt_info.flags >> 6) & 1;
bellard8d18e892007-11-14 15:18:40 +00002467#ifdef TARGET_ABI32
2468 lm = 0;
2469#else
2470 lm = (ldt_info.flags >> 7) & 1;
2471#endif
bellard6dbad632003-03-16 18:05:05 +00002472 if (contents == 3) {
2473 if (oldmode)
bellard03acab62007-11-11 14:57:14 +00002474 return -TARGET_EINVAL;
bellard6dbad632003-03-16 18:05:05 +00002475 if (seg_not_present == 0)
bellard03acab62007-11-11 14:57:14 +00002476 return -TARGET_EINVAL;
bellard6dbad632003-03-16 18:05:05 +00002477 }
2478 /* allocate the LDT */
2479 if (!ldt_table) {
2480 ldt_table = malloc(TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE);
2481 if (!ldt_table)
bellard03acab62007-11-11 14:57:14 +00002482 return -TARGET_ENOMEM;
bellard6dbad632003-03-16 18:05:05 +00002483 memset(ldt_table, 0, TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE);
bellardeeeac3f2007-11-11 19:34:32 +00002484 env->ldt.base = h2g((unsigned long)ldt_table);
bellard6dbad632003-03-16 18:05:05 +00002485 env->ldt.limit = 0xffff;
2486 }
2487
2488 /* NOTE: same code as Linux kernel */
2489 /* Allow LDTs to be cleared by the user. */
2490 if (ldt_info.base_addr == 0 && ldt_info.limit == 0) {
2491 if (oldmode ||
2492 (contents == 0 &&
2493 read_exec_only == 1 &&
2494 seg_32bit == 0 &&
2495 limit_in_pages == 0 &&
2496 seg_not_present == 1 &&
2497 useable == 0 )) {
2498 entry_1 = 0;
2499 entry_2 = 0;
2500 goto install;
2501 }
2502 }
ths3b46e622007-09-17 08:09:54 +00002503
bellard6dbad632003-03-16 18:05:05 +00002504 entry_1 = ((ldt_info.base_addr & 0x0000ffff) << 16) |
2505 (ldt_info.limit & 0x0ffff);
2506 entry_2 = (ldt_info.base_addr & 0xff000000) |
2507 ((ldt_info.base_addr & 0x00ff0000) >> 16) |
2508 (ldt_info.limit & 0xf0000) |
2509 ((read_exec_only ^ 1) << 9) |
2510 (contents << 10) |
2511 ((seg_not_present ^ 1) << 15) |
2512 (seg_32bit << 22) |
2513 (limit_in_pages << 23) |
bellard8d18e892007-11-14 15:18:40 +00002514 (lm << 21) |
bellard6dbad632003-03-16 18:05:05 +00002515 0x7000;
2516 if (!oldmode)
2517 entry_2 |= (useable << 20);
bellard14ae3ba2003-05-27 23:25:06 +00002518
bellard6dbad632003-03-16 18:05:05 +00002519 /* Install the new entry ... */
2520install:
2521 lp = (uint32_t *)(ldt_table + (ldt_info.entry_number << 3));
2522 lp[0] = tswap32(entry_1);
2523 lp[1] = tswap32(entry_2);
2524 return 0;
2525}
2526
2527/* specific and weird i386 syscalls */
blueswir18fcd3692008-08-17 20:26:25 +00002528static abi_long do_modify_ldt(CPUX86State *env, int func, abi_ulong ptr,
2529 unsigned long bytecount)
bellard6dbad632003-03-16 18:05:05 +00002530{
bellard03acab62007-11-11 14:57:14 +00002531 abi_long ret;
ths3b46e622007-09-17 08:09:54 +00002532
bellard6dbad632003-03-16 18:05:05 +00002533 switch (func) {
2534 case 0:
2535 ret = read_ldt(ptr, bytecount);
2536 break;
2537 case 1:
2538 ret = write_ldt(env, ptr, bytecount, 1);
2539 break;
2540 case 0x11:
2541 ret = write_ldt(env, ptr, bytecount, 0);
2542 break;
bellard03acab62007-11-11 14:57:14 +00002543 default:
2544 ret = -TARGET_ENOSYS;
2545 break;
bellard6dbad632003-03-16 18:05:05 +00002546 }
2547 return ret;
2548}
bellard1b6b0292003-03-22 17:31:38 +00002549
blueswir14583f582008-08-24 10:35:55 +00002550#if defined(TARGET_I386) && defined(TARGET_ABI32)
blueswir18fcd3692008-08-17 20:26:25 +00002551static abi_long do_set_thread_area(CPUX86State *env, abi_ulong ptr)
bellard8d18e892007-11-14 15:18:40 +00002552{
2553 uint64_t *gdt_table = g2h(env->gdt.base);
2554 struct target_modify_ldt_ldt_s ldt_info;
2555 struct target_modify_ldt_ldt_s *target_ldt_info;
2556 int seg_32bit, contents, read_exec_only, limit_in_pages;
2557 int seg_not_present, useable, lm;
2558 uint32_t *lp, entry_1, entry_2;
2559 int i;
2560
2561 lock_user_struct(VERIFY_WRITE, target_ldt_info, ptr, 1);
2562 if (!target_ldt_info)
2563 return -TARGET_EFAULT;
2564 ldt_info.entry_number = tswap32(target_ldt_info->entry_number);
2565 ldt_info.base_addr = tswapl(target_ldt_info->base_addr);
2566 ldt_info.limit = tswap32(target_ldt_info->limit);
2567 ldt_info.flags = tswap32(target_ldt_info->flags);
2568 if (ldt_info.entry_number == -1) {
2569 for (i=TARGET_GDT_ENTRY_TLS_MIN; i<=TARGET_GDT_ENTRY_TLS_MAX; i++) {
2570 if (gdt_table[i] == 0) {
2571 ldt_info.entry_number = i;
2572 target_ldt_info->entry_number = tswap32(i);
2573 break;
2574 }
2575 }
2576 }
2577 unlock_user_struct(target_ldt_info, ptr, 1);
2578
2579 if (ldt_info.entry_number < TARGET_GDT_ENTRY_TLS_MIN ||
2580 ldt_info.entry_number > TARGET_GDT_ENTRY_TLS_MAX)
2581 return -TARGET_EINVAL;
2582 seg_32bit = ldt_info.flags & 1;
2583 contents = (ldt_info.flags >> 1) & 3;
2584 read_exec_only = (ldt_info.flags >> 3) & 1;
2585 limit_in_pages = (ldt_info.flags >> 4) & 1;
2586 seg_not_present = (ldt_info.flags >> 5) & 1;
2587 useable = (ldt_info.flags >> 6) & 1;
2588#ifdef TARGET_ABI32
2589 lm = 0;
2590#else
2591 lm = (ldt_info.flags >> 7) & 1;
2592#endif
2593
2594 if (contents == 3) {
2595 if (seg_not_present == 0)
2596 return -TARGET_EINVAL;
2597 }
2598
2599 /* NOTE: same code as Linux kernel */
2600 /* Allow LDTs to be cleared by the user. */
2601 if (ldt_info.base_addr == 0 && ldt_info.limit == 0) {
2602 if ((contents == 0 &&
2603 read_exec_only == 1 &&
2604 seg_32bit == 0 &&
2605 limit_in_pages == 0 &&
2606 seg_not_present == 1 &&
2607 useable == 0 )) {
2608 entry_1 = 0;
2609 entry_2 = 0;
2610 goto install;
2611 }
2612 }
2613
2614 entry_1 = ((ldt_info.base_addr & 0x0000ffff) << 16) |
2615 (ldt_info.limit & 0x0ffff);
2616 entry_2 = (ldt_info.base_addr & 0xff000000) |
2617 ((ldt_info.base_addr & 0x00ff0000) >> 16) |
2618 (ldt_info.limit & 0xf0000) |
2619 ((read_exec_only ^ 1) << 9) |
2620 (contents << 10) |
2621 ((seg_not_present ^ 1) << 15) |
2622 (seg_32bit << 22) |
2623 (limit_in_pages << 23) |
2624 (useable << 20) |
2625 (lm << 21) |
2626 0x7000;
2627
2628 /* Install the new entry ... */
2629install:
2630 lp = (uint32_t *)(gdt_table + ldt_info.entry_number);
2631 lp[0] = tswap32(entry_1);
2632 lp[1] = tswap32(entry_2);
2633 return 0;
2634}
2635
blueswir18fcd3692008-08-17 20:26:25 +00002636static abi_long do_get_thread_area(CPUX86State *env, abi_ulong ptr)
bellard8d18e892007-11-14 15:18:40 +00002637{
2638 struct target_modify_ldt_ldt_s *target_ldt_info;
2639 uint64_t *gdt_table = g2h(env->gdt.base);
2640 uint32_t base_addr, limit, flags;
2641 int seg_32bit, contents, read_exec_only, limit_in_pages, idx;
2642 int seg_not_present, useable, lm;
2643 uint32_t *lp, entry_1, entry_2;
2644
2645 lock_user_struct(VERIFY_WRITE, target_ldt_info, ptr, 1);
2646 if (!target_ldt_info)
2647 return -TARGET_EFAULT;
2648 idx = tswap32(target_ldt_info->entry_number);
2649 if (idx < TARGET_GDT_ENTRY_TLS_MIN ||
2650 idx > TARGET_GDT_ENTRY_TLS_MAX) {
2651 unlock_user_struct(target_ldt_info, ptr, 1);
2652 return -TARGET_EINVAL;
2653 }
2654 lp = (uint32_t *)(gdt_table + idx);
2655 entry_1 = tswap32(lp[0]);
2656 entry_2 = tswap32(lp[1]);
2657
2658 read_exec_only = ((entry_2 >> 9) & 1) ^ 1;
2659 contents = (entry_2 >> 10) & 3;
2660 seg_not_present = ((entry_2 >> 15) & 1) ^ 1;
2661 seg_32bit = (entry_2 >> 22) & 1;
2662 limit_in_pages = (entry_2 >> 23) & 1;
2663 useable = (entry_2 >> 20) & 1;
2664#ifdef TARGET_ABI32
2665 lm = 0;
2666#else
2667 lm = (entry_2 >> 21) & 1;
2668#endif
2669 flags = (seg_32bit << 0) | (contents << 1) |
2670 (read_exec_only << 3) | (limit_in_pages << 4) |
2671 (seg_not_present << 5) | (useable << 6) | (lm << 7);
2672 limit = (entry_1 & 0xffff) | (entry_2 & 0xf0000);
2673 base_addr = (entry_1 >> 16) |
2674 (entry_2 & 0xff000000) |
2675 ((entry_2 & 0xff) << 16);
2676 target_ldt_info->base_addr = tswapl(base_addr);
2677 target_ldt_info->limit = tswap32(limit);
2678 target_ldt_info->flags = tswap32(flags);
2679 unlock_user_struct(target_ldt_info, ptr, 1);
2680 return 0;
2681}
blueswir14583f582008-08-24 10:35:55 +00002682#endif /* TARGET_I386 && TARGET_ABI32 */
bellard8d18e892007-11-14 15:18:40 +00002683
bellardd2fd1af2007-11-14 18:08:56 +00002684#ifndef TARGET_ABI32
blueswir18fcd3692008-08-17 20:26:25 +00002685static abi_long do_arch_prctl(CPUX86State *env, int code, abi_ulong addr)
bellardd2fd1af2007-11-14 18:08:56 +00002686{
2687 abi_long ret;
2688 abi_ulong val;
2689 int idx;
2690
2691 switch(code) {
2692 case TARGET_ARCH_SET_GS:
2693 case TARGET_ARCH_SET_FS:
2694 if (code == TARGET_ARCH_SET_GS)
2695 idx = R_GS;
2696 else
2697 idx = R_FS;
2698 cpu_x86_load_seg(env, idx, 0);
2699 env->segs[idx].base = addr;
2700 break;
2701 case TARGET_ARCH_GET_GS:
2702 case TARGET_ARCH_GET_FS:
2703 if (code == TARGET_ARCH_GET_GS)
2704 idx = R_GS;
2705 else
2706 idx = R_FS;
2707 val = env->segs[idx].base;
2708 if (put_user(val, addr, abi_ulong))
2709 return -TARGET_EFAULT;
2710 break;
2711 default:
2712 ret = -TARGET_EINVAL;
2713 break;
2714 }
2715 return 0;
2716}
2717#endif
2718
bellard2ab83ea2003-06-15 19:56:46 +00002719#endif /* defined(TARGET_I386) */
2720
pbrookd865bab2008-06-07 22:12:17 +00002721#if defined(USE_NPTL)
2722
2723#define NEW_STACK_SIZE PTHREAD_STACK_MIN
2724
2725static pthread_mutex_t clone_lock = PTHREAD_MUTEX_INITIALIZER;
2726typedef struct {
2727 CPUState *env;
2728 pthread_mutex_t mutex;
2729 pthread_cond_t cond;
2730 pthread_t thread;
2731 uint32_t tid;
2732 abi_ulong child_tidptr;
2733 abi_ulong parent_tidptr;
2734 sigset_t sigmask;
2735} new_thread_info;
2736
2737static void *clone_func(void *arg)
2738{
2739 new_thread_info *info = arg;
2740 CPUState *env;
2741
2742 env = info->env;
2743 thread_env = env;
2744 info->tid = gettid();
2745 if (info->child_tidptr)
2746 put_user_u32(info->tid, info->child_tidptr);
2747 if (info->parent_tidptr)
2748 put_user_u32(info->tid, info->parent_tidptr);
2749 /* Enable signals. */
2750 sigprocmask(SIG_SETMASK, &info->sigmask, NULL);
2751 /* Signal to the parent that we're ready. */
2752 pthread_mutex_lock(&info->mutex);
2753 pthread_cond_broadcast(&info->cond);
2754 pthread_mutex_unlock(&info->mutex);
2755 /* Wait until the parent has finshed initializing the tls state. */
2756 pthread_mutex_lock(&clone_lock);
2757 pthread_mutex_unlock(&clone_lock);
2758 cpu_loop(env);
2759 /* never exits */
2760 return NULL;
2761}
2762#else
bellard1b6b0292003-03-22 17:31:38 +00002763/* this stack is the equivalent of the kernel stack associated with a
2764 thread/process */
2765#define NEW_STACK_SIZE 8192
2766
2767static int clone_func(void *arg)
2768{
bellard2ab83ea2003-06-15 19:56:46 +00002769 CPUState *env = arg;
bellard1b6b0292003-03-22 17:31:38 +00002770 cpu_loop(env);
2771 /* never exits */
2772 return 0;
2773}
pbrookd865bab2008-06-07 22:12:17 +00002774#endif
bellard1b6b0292003-03-22 17:31:38 +00002775
ths0da46a62007-10-20 20:23:07 +00002776/* do_fork() Must return host values and target errnos (unlike most
2777 do_*() functions). */
pbrookd865bab2008-06-07 22:12:17 +00002778static int do_fork(CPUState *env, unsigned int flags, abi_ulong newsp,
2779 abi_ulong parent_tidptr, target_ulong newtls,
2780 abi_ulong child_tidptr)
bellard1b6b0292003-03-22 17:31:38 +00002781{
2782 int ret;
bellard5cd43932003-03-29 16:54:36 +00002783 TaskState *ts;
bellard1b6b0292003-03-22 17:31:38 +00002784 uint8_t *new_stack;
bellard2ab83ea2003-06-15 19:56:46 +00002785 CPUState *new_env;
pbrookd865bab2008-06-07 22:12:17 +00002786#if defined(USE_NPTL)
2787 unsigned int nptl_flags;
2788 sigset_t sigmask;
2789#endif
ths3b46e622007-09-17 08:09:54 +00002790
bellard1b6b0292003-03-22 17:31:38 +00002791 if (flags & CLONE_VM) {
pbrookbd0c5662008-05-29 14:34:11 +00002792#if defined(USE_NPTL)
pbrookd865bab2008-06-07 22:12:17 +00002793 new_thread_info info;
2794 pthread_attr_t attr;
pbrookbd0c5662008-05-29 14:34:11 +00002795#endif
pbrookc3a92832008-06-09 14:02:50 +00002796 ts = qemu_mallocz(sizeof(TaskState) + NEW_STACK_SIZE);
pbrook624f7972008-05-31 16:11:38 +00002797 init_task_state(ts);
bellard5cd43932003-03-29 16:54:36 +00002798 new_stack = ts->stack;
bellard1b6b0292003-03-22 17:31:38 +00002799 /* we create a new CPU instance. */
thsc5be9f02007-02-28 20:20:53 +00002800 new_env = cpu_copy(env);
pbrook6e68e072008-05-30 17:22:15 +00002801 /* Init regs that differ from the parent. */
2802 cpu_clone_regs(new_env, newsp);
bellard5cd43932003-03-29 16:54:36 +00002803 new_env->opaque = ts;
pbrookd865bab2008-06-07 22:12:17 +00002804#if defined(USE_NPTL)
2805 nptl_flags = flags;
2806 flags &= ~CLONE_NPTL_FLAGS2;
2807
2808 /* TODO: Implement CLONE_CHILD_CLEARTID. */
2809 if (nptl_flags & CLONE_SETTLS)
2810 cpu_set_tls (new_env, newtls);
2811
2812 /* Grab a mutex so that thread setup appears atomic. */
2813 pthread_mutex_lock(&clone_lock);
2814
2815 memset(&info, 0, sizeof(info));
2816 pthread_mutex_init(&info.mutex, NULL);
2817 pthread_mutex_lock(&info.mutex);
2818 pthread_cond_init(&info.cond, NULL);
2819 info.env = new_env;
2820 if (nptl_flags & CLONE_CHILD_SETTID)
2821 info.child_tidptr = child_tidptr;
2822 if (nptl_flags & CLONE_PARENT_SETTID)
2823 info.parent_tidptr = parent_tidptr;
2824
2825 ret = pthread_attr_init(&attr);
2826 ret = pthread_attr_setstack(&attr, new_stack, NEW_STACK_SIZE);
2827 /* It is not safe to deliver signals until the child has finished
2828 initializing, so temporarily block all signals. */
2829 sigfillset(&sigmask);
2830 sigprocmask(SIG_BLOCK, &sigmask, &info.sigmask);
2831
2832 ret = pthread_create(&info.thread, &attr, clone_func, &info);
2833
2834 sigprocmask(SIG_SETMASK, &info.sigmask, NULL);
2835 pthread_attr_destroy(&attr);
2836 if (ret == 0) {
2837 /* Wait for the child to initialize. */
2838 pthread_cond_wait(&info.cond, &info.mutex);
2839 ret = info.tid;
2840 if (flags & CLONE_PARENT_SETTID)
2841 put_user_u32(ret, parent_tidptr);
2842 } else {
2843 ret = -1;
2844 }
2845 pthread_mutex_unlock(&info.mutex);
2846 pthread_cond_destroy(&info.cond);
2847 pthread_mutex_destroy(&info.mutex);
2848 pthread_mutex_unlock(&clone_lock);
2849#else
2850 if (flags & CLONE_NPTL_FLAGS2)
2851 return -EINVAL;
2852 /* This is probably going to die very quickly, but do it anyway. */
bellard27725c12003-04-29 21:08:18 +00002853#ifdef __ia64__
bellardfd4a43e2006-04-24 20:32:17 +00002854 ret = __clone2(clone_func, new_stack + NEW_STACK_SIZE, flags, new_env);
bellard27725c12003-04-29 21:08:18 +00002855#else
2856 ret = clone(clone_func, new_stack + NEW_STACK_SIZE, flags, new_env);
2857#endif
pbrookd865bab2008-06-07 22:12:17 +00002858#endif
bellard1b6b0292003-03-22 17:31:38 +00002859 } else {
2860 /* if no CLONE_VM, we consider it is a fork */
pbrookd865bab2008-06-07 22:12:17 +00002861 if ((flags & ~(CSIGNAL | CLONE_NPTL_FLAGS2)) != 0)
bellard1b6b0292003-03-22 17:31:38 +00002862 return -EINVAL;
pbrookd865bab2008-06-07 22:12:17 +00002863 fork_start();
bellard1b6b0292003-03-22 17:31:38 +00002864 ret = fork();
pbrookd865bab2008-06-07 22:12:17 +00002865#if defined(USE_NPTL)
2866 /* There is a race condition here. The parent process could
2867 theoretically read the TID in the child process before the child
2868 tid is set. This would require using either ptrace
2869 (not implemented) or having *_tidptr to point at a shared memory
2870 mapping. We can't repeat the spinlock hack used above because
2871 the child process gets its own copy of the lock. */
2872 if (ret == 0) {
2873 cpu_clone_regs(env, newsp);
2874 fork_end(1);
2875 /* Child Process. */
2876 if (flags & CLONE_CHILD_SETTID)
2877 put_user_u32(gettid(), child_tidptr);
2878 if (flags & CLONE_PARENT_SETTID)
2879 put_user_u32(gettid(), parent_tidptr);
2880 ts = (TaskState *)env->opaque;
2881 if (flags & CLONE_SETTLS)
2882 cpu_set_tls (env, newtls);
2883 /* TODO: Implement CLONE_CHILD_CLEARTID. */
2884 } else {
2885 fork_end(0);
2886 }
2887#else
pbrook6e68e072008-05-30 17:22:15 +00002888 if (ret == 0) {
2889 cpu_clone_regs(env, newsp);
2890 }
pbrookd865bab2008-06-07 22:12:17 +00002891#endif
bellard1b6b0292003-03-22 17:31:38 +00002892 }
2893 return ret;
2894}
2895
blueswir1992f48a2007-10-14 16:27:31 +00002896static abi_long do_fcntl(int fd, int cmd, abi_ulong arg)
bellard7775e9e2003-05-14 22:46:48 +00002897{
2898 struct flock fl;
pbrook53a59602006-03-25 19:31:22 +00002899 struct target_flock *target_fl;
ths43f238d2007-01-05 20:55:49 +00002900 struct flock64 fl64;
2901 struct target_flock64 *target_fl64;
blueswir1992f48a2007-10-14 16:27:31 +00002902 abi_long ret;
pbrook53a59602006-03-25 19:31:22 +00002903
bellard7775e9e2003-05-14 22:46:48 +00002904 switch(cmd) {
2905 case TARGET_F_GETLK:
bellard579a97f2007-11-11 14:26:47 +00002906 if (!lock_user_struct(VERIFY_READ, target_fl, arg, 1))
2907 return -TARGET_EFAULT;
ths58134272007-03-31 18:59:32 +00002908 fl.l_type = tswap16(target_fl->l_type);
2909 fl.l_whence = tswap16(target_fl->l_whence);
2910 fl.l_start = tswapl(target_fl->l_start);
2911 fl.l_len = tswapl(target_fl->l_len);
2912 fl.l_pid = tswapl(target_fl->l_pid);
2913 unlock_user_struct(target_fl, arg, 0);
bellard9ee1fa22007-11-11 15:11:19 +00002914 ret = get_errno(fcntl(fd, cmd, &fl));
bellard7775e9e2003-05-14 22:46:48 +00002915 if (ret == 0) {
bellard579a97f2007-11-11 14:26:47 +00002916 if (!lock_user_struct(VERIFY_WRITE, target_fl, arg, 0))
2917 return -TARGET_EFAULT;
bellard7775e9e2003-05-14 22:46:48 +00002918 target_fl->l_type = tswap16(fl.l_type);
2919 target_fl->l_whence = tswap16(fl.l_whence);
2920 target_fl->l_start = tswapl(fl.l_start);
2921 target_fl->l_len = tswapl(fl.l_len);
2922 target_fl->l_pid = tswapl(fl.l_pid);
pbrook53a59602006-03-25 19:31:22 +00002923 unlock_user_struct(target_fl, arg, 1);
bellard7775e9e2003-05-14 22:46:48 +00002924 }
2925 break;
ths3b46e622007-09-17 08:09:54 +00002926
bellard7775e9e2003-05-14 22:46:48 +00002927 case TARGET_F_SETLK:
2928 case TARGET_F_SETLKW:
bellard579a97f2007-11-11 14:26:47 +00002929 if (!lock_user_struct(VERIFY_READ, target_fl, arg, 1))
2930 return -TARGET_EFAULT;
bellard7775e9e2003-05-14 22:46:48 +00002931 fl.l_type = tswap16(target_fl->l_type);
2932 fl.l_whence = tswap16(target_fl->l_whence);
2933 fl.l_start = tswapl(target_fl->l_start);
2934 fl.l_len = tswapl(target_fl->l_len);
2935 fl.l_pid = tswapl(target_fl->l_pid);
pbrook53a59602006-03-25 19:31:22 +00002936 unlock_user_struct(target_fl, arg, 0);
bellard9ee1fa22007-11-11 15:11:19 +00002937 ret = get_errno(fcntl(fd, cmd, &fl));
bellard7775e9e2003-05-14 22:46:48 +00002938 break;
ths3b46e622007-09-17 08:09:54 +00002939
bellard7775e9e2003-05-14 22:46:48 +00002940 case TARGET_F_GETLK64:
bellard579a97f2007-11-11 14:26:47 +00002941 if (!lock_user_struct(VERIFY_READ, target_fl64, arg, 1))
2942 return -TARGET_EFAULT;
ths58134272007-03-31 18:59:32 +00002943 fl64.l_type = tswap16(target_fl64->l_type) >> 1;
2944 fl64.l_whence = tswap16(target_fl64->l_whence);
2945 fl64.l_start = tswapl(target_fl64->l_start);
2946 fl64.l_len = tswapl(target_fl64->l_len);
2947 fl64.l_pid = tswap16(target_fl64->l_pid);
2948 unlock_user_struct(target_fl64, arg, 0);
bellard9ee1fa22007-11-11 15:11:19 +00002949 ret = get_errno(fcntl(fd, cmd >> 1, &fl64));
ths43f238d2007-01-05 20:55:49 +00002950 if (ret == 0) {
bellard579a97f2007-11-11 14:26:47 +00002951 if (!lock_user_struct(VERIFY_WRITE, target_fl64, arg, 0))
2952 return -TARGET_EFAULT;
ths43f238d2007-01-05 20:55:49 +00002953 target_fl64->l_type = tswap16(fl64.l_type) >> 1;
2954 target_fl64->l_whence = tswap16(fl64.l_whence);
2955 target_fl64->l_start = tswapl(fl64.l_start);
2956 target_fl64->l_len = tswapl(fl64.l_len);
2957 target_fl64->l_pid = tswapl(fl64.l_pid);
2958 unlock_user_struct(target_fl64, arg, 1);
2959 }
bellard9ee1fa22007-11-11 15:11:19 +00002960 break;
bellard7775e9e2003-05-14 22:46:48 +00002961 case TARGET_F_SETLK64:
2962 case TARGET_F_SETLKW64:
bellard579a97f2007-11-11 14:26:47 +00002963 if (!lock_user_struct(VERIFY_READ, target_fl64, arg, 1))
2964 return -TARGET_EFAULT;
ths43f238d2007-01-05 20:55:49 +00002965 fl64.l_type = tswap16(target_fl64->l_type) >> 1;
2966 fl64.l_whence = tswap16(target_fl64->l_whence);
2967 fl64.l_start = tswapl(target_fl64->l_start);
2968 fl64.l_len = tswapl(target_fl64->l_len);
2969 fl64.l_pid = tswap16(target_fl64->l_pid);
2970 unlock_user_struct(target_fl64, arg, 0);
bellard9ee1fa22007-11-11 15:11:19 +00002971 ret = get_errno(fcntl(fd, cmd >> 1, &fl64));
bellard7775e9e2003-05-14 22:46:48 +00002972 break;
2973
bellardffa65c32004-01-04 23:57:22 +00002974 case F_GETFL:
bellard9ee1fa22007-11-11 15:11:19 +00002975 ret = get_errno(fcntl(fd, cmd, arg));
2976 if (ret >= 0) {
2977 ret = host_to_target_bitmask(ret, fcntl_flags_tbl);
2978 }
bellardffa65c32004-01-04 23:57:22 +00002979 break;
2980
2981 case F_SETFL:
bellard9ee1fa22007-11-11 15:11:19 +00002982 ret = get_errno(fcntl(fd, cmd, target_to_host_bitmask(arg, fcntl_flags_tbl)));
bellardffa65c32004-01-04 23:57:22 +00002983 break;
2984
bellard7775e9e2003-05-14 22:46:48 +00002985 default:
bellard9ee1fa22007-11-11 15:11:19 +00002986 ret = get_errno(fcntl(fd, cmd, arg));
bellard7775e9e2003-05-14 22:46:48 +00002987 break;
2988 }
2989 return ret;
2990}
2991
bellard67867302003-11-23 17:05:30 +00002992#ifdef USE_UID16
bellard7775e9e2003-05-14 22:46:48 +00002993
bellard67867302003-11-23 17:05:30 +00002994static inline int high2lowuid(int uid)
2995{
2996 if (uid > 65535)
2997 return 65534;
2998 else
2999 return uid;
3000}
3001
3002static inline int high2lowgid(int gid)
3003{
3004 if (gid > 65535)
3005 return 65534;
3006 else
3007 return gid;
3008}
3009
3010static inline int low2highuid(int uid)
3011{
3012 if ((int16_t)uid == -1)
3013 return -1;
3014 else
3015 return uid;
3016}
3017
3018static inline int low2highgid(int gid)
3019{
3020 if ((int16_t)gid == -1)
3021 return -1;
3022 else
3023 return gid;
3024}
3025
3026#endif /* USE_UID16 */
bellard1b6b0292003-03-22 17:31:38 +00003027
bellard31e31b82003-02-18 22:55:36 +00003028void syscall_init(void)
3029{
bellard2ab83ea2003-06-15 19:56:46 +00003030 IOCTLEntry *ie;
3031 const argtype *arg_type;
3032 int size;
thsb92c47c2007-11-01 00:07:38 +00003033 int i;
bellard2ab83ea2003-06-15 19:56:46 +00003034
ths5fafdf22007-09-16 21:08:06 +00003035#define STRUCT(name, list...) thunk_register_struct(STRUCT_ ## name, #name, struct_ ## name ## _def);
3036#define STRUCT_SPECIAL(name) thunk_register_struct_direct(STRUCT_ ## name, #name, &struct_ ## name ## _def);
bellard31e31b82003-02-18 22:55:36 +00003037#include "syscall_types.h"
3038#undef STRUCT
3039#undef STRUCT_SPECIAL
bellard2ab83ea2003-06-15 19:56:46 +00003040
3041 /* we patch the ioctl size if necessary. We rely on the fact that
3042 no ioctl has all the bits at '1' in the size field */
3043 ie = ioctl_entries;
3044 while (ie->target_cmd != 0) {
3045 if (((ie->target_cmd >> TARGET_IOC_SIZESHIFT) & TARGET_IOC_SIZEMASK) ==
3046 TARGET_IOC_SIZEMASK) {
3047 arg_type = ie->arg_type;
3048 if (arg_type[0] != TYPE_PTR) {
ths5fafdf22007-09-16 21:08:06 +00003049 fprintf(stderr, "cannot patch size for ioctl 0x%x\n",
bellard2ab83ea2003-06-15 19:56:46 +00003050 ie->target_cmd);
3051 exit(1);
3052 }
3053 arg_type++;
3054 size = thunk_type_size(arg_type, 0);
ths5fafdf22007-09-16 21:08:06 +00003055 ie->target_cmd = (ie->target_cmd &
bellard2ab83ea2003-06-15 19:56:46 +00003056 ~(TARGET_IOC_SIZEMASK << TARGET_IOC_SIZESHIFT)) |
3057 (size << TARGET_IOC_SIZESHIFT);
3058 }
thsb92c47c2007-11-01 00:07:38 +00003059
3060 /* Build target_to_host_errno_table[] table from
3061 * host_to_target_errno_table[]. */
3062 for (i=0; i < ERRNO_TABLE_SIZE; i++)
3063 target_to_host_errno_table[host_to_target_errno_table[i]] = i;
3064
bellard2ab83ea2003-06-15 19:56:46 +00003065 /* automatic consistency check if same arch */
bellardd2fd1af2007-11-14 18:08:56 +00003066#if defined(__i386__) && defined(TARGET_I386) && defined(TARGET_ABI32)
bellard2ab83ea2003-06-15 19:56:46 +00003067 if (ie->target_cmd != ie->host_cmd) {
ths5fafdf22007-09-16 21:08:06 +00003068 fprintf(stderr, "ERROR: ioctl: target=0x%x host=0x%x\n",
bellard2ab83ea2003-06-15 19:56:46 +00003069 ie->target_cmd, ie->host_cmd);
3070 }
3071#endif
3072 ie++;
3073 }
bellard31e31b82003-02-18 22:55:36 +00003074}
bellardc573ff62004-01-04 15:51:36 +00003075
blueswir1992f48a2007-10-14 16:27:31 +00003076#if TARGET_ABI_BITS == 32
pbrookce4defa2006-02-09 16:49:55 +00003077static inline uint64_t target_offset64(uint32_t word0, uint32_t word1)
3078{
thsaf325d32008-06-10 15:29:15 +00003079#ifdef TARGET_WORDS_BIGENDIAN
pbrookce4defa2006-02-09 16:49:55 +00003080 return ((uint64_t)word0 << 32) | word1;
3081#else
3082 return ((uint64_t)word1 << 32) | word0;
3083#endif
3084}
blueswir1992f48a2007-10-14 16:27:31 +00003085#else /* TARGET_ABI_BITS == 32 */
j_mayer32407102007-09-26 23:01:49 +00003086static inline uint64_t target_offset64(uint64_t word0, uint64_t word1)
3087{
3088 return word0;
3089}
blueswir1992f48a2007-10-14 16:27:31 +00003090#endif /* TARGET_ABI_BITS != 32 */
pbrookce4defa2006-02-09 16:49:55 +00003091
3092#ifdef TARGET_NR_truncate64
blueswir1992f48a2007-10-14 16:27:31 +00003093static inline abi_long target_truncate64(void *cpu_env, const char *arg1,
3094 abi_long arg2,
3095 abi_long arg3,
3096 abi_long arg4)
pbrookce4defa2006-02-09 16:49:55 +00003097{
3098#ifdef TARGET_ARM
3099 if (((CPUARMState *)cpu_env)->eabi)
3100 {
3101 arg2 = arg3;
3102 arg3 = arg4;
3103 }
3104#endif
3105 return get_errno(truncate64(arg1, target_offset64(arg2, arg3)));
3106}
3107#endif
3108
3109#ifdef TARGET_NR_ftruncate64
blueswir1992f48a2007-10-14 16:27:31 +00003110static inline abi_long target_ftruncate64(void *cpu_env, abi_long arg1,
3111 abi_long arg2,
3112 abi_long arg3,
3113 abi_long arg4)
pbrookce4defa2006-02-09 16:49:55 +00003114{
3115#ifdef TARGET_ARM
3116 if (((CPUARMState *)cpu_env)->eabi)
3117 {
3118 arg2 = arg3;
3119 arg3 = arg4;
3120 }
3121#endif
3122 return get_errno(ftruncate64(arg1, target_offset64(arg2, arg3)));
3123}
3124#endif
3125
bellard579a97f2007-11-11 14:26:47 +00003126static inline abi_long target_to_host_timespec(struct timespec *host_ts,
3127 abi_ulong target_addr)
pbrook53a59602006-03-25 19:31:22 +00003128{
3129 struct target_timespec *target_ts;
3130
bellard579a97f2007-11-11 14:26:47 +00003131 if (!lock_user_struct(VERIFY_READ, target_ts, target_addr, 1))
3132 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00003133 host_ts->tv_sec = tswapl(target_ts->tv_sec);
3134 host_ts->tv_nsec = tswapl(target_ts->tv_nsec);
3135 unlock_user_struct(target_ts, target_addr, 0);
bellardb255bfa2008-05-10 21:51:02 +00003136 return 0;
pbrook53a59602006-03-25 19:31:22 +00003137}
3138
bellard579a97f2007-11-11 14:26:47 +00003139static inline abi_long host_to_target_timespec(abi_ulong target_addr,
3140 struct timespec *host_ts)
pbrook53a59602006-03-25 19:31:22 +00003141{
3142 struct target_timespec *target_ts;
3143
bellard579a97f2007-11-11 14:26:47 +00003144 if (!lock_user_struct(VERIFY_WRITE, target_ts, target_addr, 0))
3145 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00003146 target_ts->tv_sec = tswapl(host_ts->tv_sec);
3147 target_ts->tv_nsec = tswapl(host_ts->tv_nsec);
3148 unlock_user_struct(target_ts, target_addr, 1);
bellardb255bfa2008-05-10 21:51:02 +00003149 return 0;
pbrook53a59602006-03-25 19:31:22 +00003150}
3151
pbrookbd0c5662008-05-29 14:34:11 +00003152#if defined(USE_NPTL)
3153/* ??? Using host futex calls even when target atomic operations
3154 are not really atomic probably breaks things. However implementing
3155 futexes locally would make futexes shared between multiple processes
3156 tricky. However they're probably useless because guest atomic
3157 operations won't work either. */
blueswir18fcd3692008-08-17 20:26:25 +00003158static int do_futex(target_ulong uaddr, int op, int val, target_ulong timeout,
3159 target_ulong uaddr2, int val3)
pbrookbd0c5662008-05-29 14:34:11 +00003160{
3161 struct timespec ts, *pts;
3162
3163 /* ??? We assume FUTEX_* constants are the same on both host
3164 and target. */
3165 switch (op) {
3166 case FUTEX_WAIT:
3167 if (timeout) {
3168 pts = &ts;
3169 target_to_host_timespec(pts, timeout);
3170 } else {
3171 pts = NULL;
3172 }
3173 return get_errno(sys_futex(g2h(uaddr), FUTEX_WAIT, tswap32(val),
3174 pts, NULL, 0));
3175 case FUTEX_WAKE:
3176 return get_errno(sys_futex(g2h(uaddr), FUTEX_WAKE, val, NULL, NULL, 0));
3177 case FUTEX_FD:
3178 return get_errno(sys_futex(g2h(uaddr), FUTEX_FD, val, NULL, NULL, 0));
3179 case FUTEX_REQUEUE:
3180 return get_errno(sys_futex(g2h(uaddr), FUTEX_REQUEUE, val,
3181 NULL, g2h(uaddr2), 0));
3182 case FUTEX_CMP_REQUEUE:
3183 return get_errno(sys_futex(g2h(uaddr), FUTEX_CMP_REQUEUE, val,
3184 NULL, g2h(uaddr2), tswap32(val3)));
3185 default:
3186 return -TARGET_ENOSYS;
3187 }
3188}
3189#endif
3190
pbrooka745ec62008-05-06 15:36:17 +00003191int get_osversion(void)
3192{
3193 static int osversion;
3194 struct new_utsname buf;
3195 const char *s;
3196 int i, n, tmp;
3197 if (osversion)
3198 return osversion;
3199 if (qemu_uname_release && *qemu_uname_release) {
3200 s = qemu_uname_release;
3201 } else {
3202 if (sys_uname(&buf))
3203 return 0;
3204 s = buf.release;
3205 }
3206 tmp = 0;
3207 for (i = 0; i < 3; i++) {
3208 n = 0;
3209 while (*s >= '0' && *s <= '9') {
3210 n *= 10;
3211 n += *s - '0';
3212 s++;
3213 }
3214 tmp = (tmp << 8) + n;
3215 if (*s == '.')
3216 s++;
3217 }
3218 osversion = tmp;
3219 return osversion;
3220}
3221
ths0da46a62007-10-20 20:23:07 +00003222/* do_syscall() should always have a single exit point at the end so
3223 that actions, such as logging of syscall results, can be performed.
3224 All errnos that do_syscall() returns must be -TARGET_<errcode>. */
blueswir1992f48a2007-10-14 16:27:31 +00003225abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
3226 abi_long arg2, abi_long arg3, abi_long arg4,
3227 abi_long arg5, abi_long arg6)
bellard31e31b82003-02-18 22:55:36 +00003228{
blueswir1992f48a2007-10-14 16:27:31 +00003229 abi_long ret;
bellard31e31b82003-02-18 22:55:36 +00003230 struct stat st;
bellard56c8f682005-11-28 22:28:41 +00003231 struct statfs stfs;
pbrook53a59602006-03-25 19:31:22 +00003232 void *p;
ths3b46e622007-09-17 08:09:54 +00003233
bellard72f03902003-02-18 23:33:18 +00003234#ifdef DEBUG
bellardc573ff62004-01-04 15:51:36 +00003235 gemu_log("syscall %d", num);
bellard72f03902003-02-18 23:33:18 +00003236#endif
thsb92c47c2007-11-01 00:07:38 +00003237 if(do_strace)
3238 print_syscall(num, arg1, arg2, arg3, arg4, arg5, arg6);
3239
bellard31e31b82003-02-18 22:55:36 +00003240 switch(num) {
3241 case TARGET_NR_exit:
bellard7d132992003-03-06 23:23:54 +00003242#ifdef HAVE_GPROF
3243 _mcleanup();
3244#endif
bellarde9009672005-04-26 20:42:36 +00003245 gdb_exit(cpu_env, arg1);
bellard1b6b0292003-03-22 17:31:38 +00003246 /* XXX: should free thread stack and CPU env */
bellard31e31b82003-02-18 22:55:36 +00003247 _exit(arg1);
3248 ret = 0; /* avoid warning */
3249 break;
3250 case TARGET_NR_read:
bellard579a97f2007-11-11 14:26:47 +00003251 if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
3252 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003253 ret = get_errno(read(arg1, p, arg3));
3254 unlock_user(p, arg2, ret);
bellard31e31b82003-02-18 22:55:36 +00003255 break;
3256 case TARGET_NR_write:
bellard579a97f2007-11-11 14:26:47 +00003257 if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
3258 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003259 ret = get_errno(write(arg1, p, arg3));
3260 unlock_user(p, arg2, 0);
bellard31e31b82003-02-18 22:55:36 +00003261 break;
3262 case TARGET_NR_open:
bellard2f619692007-11-16 10:46:05 +00003263 if (!(p = lock_user_string(arg1)))
3264 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003265 ret = get_errno(open(path(p),
bellardffa65c32004-01-04 23:57:22 +00003266 target_to_host_bitmask(arg2, fcntl_flags_tbl),
3267 arg3));
pbrook53a59602006-03-25 19:31:22 +00003268 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003269 break;
ths82424832007-09-24 09:21:55 +00003270#if defined(TARGET_NR_openat) && defined(__NR_openat)
3271 case TARGET_NR_openat:
bellard579a97f2007-11-11 14:26:47 +00003272 if (!(p = lock_user_string(arg2)))
3273 goto efault;
3274 ret = get_errno(sys_openat(arg1,
3275 path(p),
3276 target_to_host_bitmask(arg3, fcntl_flags_tbl),
3277 arg4));
3278 unlock_user(p, arg2, 0);
ths82424832007-09-24 09:21:55 +00003279 break;
3280#endif
bellard31e31b82003-02-18 22:55:36 +00003281 case TARGET_NR_close:
3282 ret = get_errno(close(arg1));
3283 break;
3284 case TARGET_NR_brk:
pbrook53a59602006-03-25 19:31:22 +00003285 ret = do_brk(arg1);
bellard31e31b82003-02-18 22:55:36 +00003286 break;
3287 case TARGET_NR_fork:
pbrookd865bab2008-06-07 22:12:17 +00003288 ret = get_errno(do_fork(cpu_env, SIGCHLD, 0, 0, 0, 0));
bellard31e31b82003-02-18 22:55:36 +00003289 break;
thse5febef2007-04-01 18:31:35 +00003290#ifdef TARGET_NR_waitpid
bellard31e31b82003-02-18 22:55:36 +00003291 case TARGET_NR_waitpid:
3292 {
pbrook53a59602006-03-25 19:31:22 +00003293 int status;
3294 ret = get_errno(waitpid(arg1, &status, arg3));
bellard2f619692007-11-16 10:46:05 +00003295 if (!is_error(ret) && arg2
3296 && put_user_s32(status, arg2))
3297 goto efault;
bellard31e31b82003-02-18 22:55:36 +00003298 }
3299 break;
thse5febef2007-04-01 18:31:35 +00003300#endif
pbrookf0cbb612008-05-30 18:20:05 +00003301#ifdef TARGET_NR_waitid
3302 case TARGET_NR_waitid:
3303 {
3304 siginfo_t info;
3305 info.si_pid = 0;
3306 ret = get_errno(waitid(arg1, arg2, &info, arg4));
3307 if (!is_error(ret) && arg3 && info.si_pid != 0) {
3308 if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_siginfo_t), 0)))
3309 goto efault;
3310 host_to_target_siginfo(p, &info);
3311 unlock_user(p, arg3, sizeof(target_siginfo_t));
3312 }
3313 }
3314 break;
3315#endif
j_mayer7a3148a2007-04-05 07:13:51 +00003316#ifdef TARGET_NR_creat /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00003317 case TARGET_NR_creat:
bellard579a97f2007-11-11 14:26:47 +00003318 if (!(p = lock_user_string(arg1)))
3319 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003320 ret = get_errno(creat(p, arg2));
3321 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003322 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003323#endif
bellard31e31b82003-02-18 22:55:36 +00003324 case TARGET_NR_link:
pbrook53a59602006-03-25 19:31:22 +00003325 {
3326 void * p2;
3327 p = lock_user_string(arg1);
3328 p2 = lock_user_string(arg2);
bellard579a97f2007-11-11 14:26:47 +00003329 if (!p || !p2)
3330 ret = -TARGET_EFAULT;
3331 else
3332 ret = get_errno(link(p, p2));
pbrook53a59602006-03-25 19:31:22 +00003333 unlock_user(p2, arg2, 0);
3334 unlock_user(p, arg1, 0);
3335 }
bellard31e31b82003-02-18 22:55:36 +00003336 break;
ths64f0ce42007-09-24 09:25:06 +00003337#if defined(TARGET_NR_linkat) && defined(__NR_linkat)
3338 case TARGET_NR_linkat:
ths64f0ce42007-09-24 09:25:06 +00003339 {
3340 void * p2 = NULL;
bellard579a97f2007-11-11 14:26:47 +00003341 if (!arg2 || !arg4)
3342 goto efault;
ths64f0ce42007-09-24 09:25:06 +00003343 p = lock_user_string(arg2);
3344 p2 = lock_user_string(arg4);
bellard579a97f2007-11-11 14:26:47 +00003345 if (!p || !p2)
ths0da46a62007-10-20 20:23:07 +00003346 ret = -TARGET_EFAULT;
ths64f0ce42007-09-24 09:25:06 +00003347 else
3348 ret = get_errno(sys_linkat(arg1, p, arg3, p2, arg5));
bellard579a97f2007-11-11 14:26:47 +00003349 unlock_user(p, arg2, 0);
3350 unlock_user(p2, arg4, 0);
ths64f0ce42007-09-24 09:25:06 +00003351 }
3352 break;
3353#endif
bellard31e31b82003-02-18 22:55:36 +00003354 case TARGET_NR_unlink:
bellard579a97f2007-11-11 14:26:47 +00003355 if (!(p = lock_user_string(arg1)))
3356 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003357 ret = get_errno(unlink(p));
3358 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003359 break;
ths8170f562007-09-24 09:24:11 +00003360#if defined(TARGET_NR_unlinkat) && defined(__NR_unlinkat)
3361 case TARGET_NR_unlinkat:
bellard579a97f2007-11-11 14:26:47 +00003362 if (!(p = lock_user_string(arg2)))
3363 goto efault;
3364 ret = get_errno(sys_unlinkat(arg1, p, arg3));
3365 unlock_user(p, arg2, 0);
balroged494d82007-12-11 23:23:52 +00003366 break;
balrogb7d35e62007-12-12 00:40:24 +00003367#endif
bellard31e31b82003-02-18 22:55:36 +00003368 case TARGET_NR_execve:
bellard7854b052003-03-29 17:22:23 +00003369 {
3370 char **argp, **envp;
bellardf7341ff2003-03-30 21:00:25 +00003371 int argc, envc;
blueswir1992f48a2007-10-14 16:27:31 +00003372 abi_ulong gp;
3373 abi_ulong guest_argp;
3374 abi_ulong guest_envp;
3375 abi_ulong addr;
bellard7854b052003-03-29 17:22:23 +00003376 char **q;
3377
bellardf7341ff2003-03-30 21:00:25 +00003378 argc = 0;
pbrook53a59602006-03-25 19:31:22 +00003379 guest_argp = arg2;
pbrookda94d262008-05-30 18:24:00 +00003380 for (gp = guest_argp; gp; gp += sizeof(abi_ulong)) {
ths03aa1972007-12-02 06:28:08 +00003381 if (get_user_ual(addr, gp))
bellard2f619692007-11-16 10:46:05 +00003382 goto efault;
ths03aa1972007-12-02 06:28:08 +00003383 if (!addr)
bellard2f619692007-11-16 10:46:05 +00003384 break;
bellard7854b052003-03-29 17:22:23 +00003385 argc++;
bellard2f619692007-11-16 10:46:05 +00003386 }
bellardf7341ff2003-03-30 21:00:25 +00003387 envc = 0;
pbrook53a59602006-03-25 19:31:22 +00003388 guest_envp = arg3;
pbrookda94d262008-05-30 18:24:00 +00003389 for (gp = guest_envp; gp; gp += sizeof(abi_ulong)) {
ths03aa1972007-12-02 06:28:08 +00003390 if (get_user_ual(addr, gp))
bellard2f619692007-11-16 10:46:05 +00003391 goto efault;
ths03aa1972007-12-02 06:28:08 +00003392 if (!addr)
bellard2f619692007-11-16 10:46:05 +00003393 break;
bellard7854b052003-03-29 17:22:23 +00003394 envc++;
bellard2f619692007-11-16 10:46:05 +00003395 }
bellard7854b052003-03-29 17:22:23 +00003396
bellardf7341ff2003-03-30 21:00:25 +00003397 argp = alloca((argc + 1) * sizeof(void *));
3398 envp = alloca((envc + 1) * sizeof(void *));
bellard7854b052003-03-29 17:22:23 +00003399
pbrookda94d262008-05-30 18:24:00 +00003400 for (gp = guest_argp, q = argp; gp;
blueswir1992f48a2007-10-14 16:27:31 +00003401 gp += sizeof(abi_ulong), q++) {
bellard2f619692007-11-16 10:46:05 +00003402 if (get_user_ual(addr, gp))
3403 goto execve_efault;
pbrook53a59602006-03-25 19:31:22 +00003404 if (!addr)
3405 break;
bellard2f619692007-11-16 10:46:05 +00003406 if (!(*q = lock_user_string(addr)))
3407 goto execve_efault;
pbrook53a59602006-03-25 19:31:22 +00003408 }
bellardf7341ff2003-03-30 21:00:25 +00003409 *q = NULL;
3410
pbrookda94d262008-05-30 18:24:00 +00003411 for (gp = guest_envp, q = envp; gp;
blueswir1992f48a2007-10-14 16:27:31 +00003412 gp += sizeof(abi_ulong), q++) {
bellard2f619692007-11-16 10:46:05 +00003413 if (get_user_ual(addr, gp))
3414 goto execve_efault;
pbrook53a59602006-03-25 19:31:22 +00003415 if (!addr)
3416 break;
bellard2f619692007-11-16 10:46:05 +00003417 if (!(*q = lock_user_string(addr)))
3418 goto execve_efault;
pbrook53a59602006-03-25 19:31:22 +00003419 }
bellardf7341ff2003-03-30 21:00:25 +00003420 *q = NULL;
bellard7854b052003-03-29 17:22:23 +00003421
bellard2f619692007-11-16 10:46:05 +00003422 if (!(p = lock_user_string(arg1)))
3423 goto execve_efault;
pbrook53a59602006-03-25 19:31:22 +00003424 ret = get_errno(execve(p, argp, envp));
3425 unlock_user(p, arg1, 0);
3426
bellard2f619692007-11-16 10:46:05 +00003427 goto execve_end;
3428
3429 execve_efault:
3430 ret = -TARGET_EFAULT;
3431
3432 execve_end:
pbrook53a59602006-03-25 19:31:22 +00003433 for (gp = guest_argp, q = argp; *q;
blueswir1992f48a2007-10-14 16:27:31 +00003434 gp += sizeof(abi_ulong), q++) {
bellard2f619692007-11-16 10:46:05 +00003435 if (get_user_ual(addr, gp)
3436 || !addr)
3437 break;
pbrook53a59602006-03-25 19:31:22 +00003438 unlock_user(*q, addr, 0);
3439 }
3440 for (gp = guest_envp, q = envp; *q;
blueswir1992f48a2007-10-14 16:27:31 +00003441 gp += sizeof(abi_ulong), q++) {
bellard2f619692007-11-16 10:46:05 +00003442 if (get_user_ual(addr, gp)
3443 || !addr)
3444 break;
pbrook53a59602006-03-25 19:31:22 +00003445 unlock_user(*q, addr, 0);
3446 }
bellard7854b052003-03-29 17:22:23 +00003447 }
bellard31e31b82003-02-18 22:55:36 +00003448 break;
3449 case TARGET_NR_chdir:
bellard579a97f2007-11-11 14:26:47 +00003450 if (!(p = lock_user_string(arg1)))
3451 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003452 ret = get_errno(chdir(p));
3453 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003454 break;
bellarda315a142005-01-30 22:59:18 +00003455#ifdef TARGET_NR_time
bellard31e31b82003-02-18 22:55:36 +00003456 case TARGET_NR_time:
3457 {
pbrook53a59602006-03-25 19:31:22 +00003458 time_t host_time;
3459 ret = get_errno(time(&host_time));
bellard2f619692007-11-16 10:46:05 +00003460 if (!is_error(ret)
3461 && arg1
3462 && put_user_sal(host_time, arg1))
3463 goto efault;
bellard31e31b82003-02-18 22:55:36 +00003464 }
3465 break;
bellarda315a142005-01-30 22:59:18 +00003466#endif
bellard31e31b82003-02-18 22:55:36 +00003467 case TARGET_NR_mknod:
bellard579a97f2007-11-11 14:26:47 +00003468 if (!(p = lock_user_string(arg1)))
3469 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003470 ret = get_errno(mknod(p, arg2, arg3));
3471 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003472 break;
ths75ac37a2007-09-24 09:23:05 +00003473#if defined(TARGET_NR_mknodat) && defined(__NR_mknodat)
3474 case TARGET_NR_mknodat:
bellard579a97f2007-11-11 14:26:47 +00003475 if (!(p = lock_user_string(arg2)))
3476 goto efault;
3477 ret = get_errno(sys_mknodat(arg1, p, arg3, arg4));
3478 unlock_user(p, arg2, 0);
ths75ac37a2007-09-24 09:23:05 +00003479 break;
3480#endif
bellard31e31b82003-02-18 22:55:36 +00003481 case TARGET_NR_chmod:
bellard579a97f2007-11-11 14:26:47 +00003482 if (!(p = lock_user_string(arg1)))
3483 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003484 ret = get_errno(chmod(p, arg2));
3485 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003486 break;
bellardebc05482003-09-30 21:08:41 +00003487#ifdef TARGET_NR_break
bellard31e31b82003-02-18 22:55:36 +00003488 case TARGET_NR_break:
3489 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00003490#endif
3491#ifdef TARGET_NR_oldstat
bellard31e31b82003-02-18 22:55:36 +00003492 case TARGET_NR_oldstat:
3493 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00003494#endif
bellard31e31b82003-02-18 22:55:36 +00003495 case TARGET_NR_lseek:
3496 ret = get_errno(lseek(arg1, arg2, arg3));
3497 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003498#ifdef TARGET_NR_getxpid
3499 case TARGET_NR_getxpid:
3500#else
bellard31e31b82003-02-18 22:55:36 +00003501 case TARGET_NR_getpid:
j_mayer7a3148a2007-04-05 07:13:51 +00003502#endif
bellard31e31b82003-02-18 22:55:36 +00003503 ret = get_errno(getpid());
3504 break;
3505 case TARGET_NR_mount:
ths80265912007-02-17 22:25:41 +00003506 {
3507 /* need to look at the data field */
3508 void *p2, *p3;
3509 p = lock_user_string(arg1);
3510 p2 = lock_user_string(arg2);
3511 p3 = lock_user_string(arg3);
bellard579a97f2007-11-11 14:26:47 +00003512 if (!p || !p2 || !p3)
3513 ret = -TARGET_EFAULT;
3514 else
3515 /* FIXME - arg5 should be locked, but it isn't clear how to
3516 * do that since it's not guaranteed to be a NULL-terminated
3517 * string.
3518 */
3519 ret = get_errno(mount(p, p2, p3, (unsigned long)arg4, g2h(arg5)));
3520 unlock_user(p, arg1, 0);
3521 unlock_user(p2, arg2, 0);
3522 unlock_user(p3, arg3, 0);
ths80265912007-02-17 22:25:41 +00003523 break;
3524 }
thse5febef2007-04-01 18:31:35 +00003525#ifdef TARGET_NR_umount
bellard31e31b82003-02-18 22:55:36 +00003526 case TARGET_NR_umount:
bellard579a97f2007-11-11 14:26:47 +00003527 if (!(p = lock_user_string(arg1)))
3528 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003529 ret = get_errno(umount(p));
3530 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003531 break;
thse5febef2007-04-01 18:31:35 +00003532#endif
j_mayer7a3148a2007-04-05 07:13:51 +00003533#ifdef TARGET_NR_stime /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00003534 case TARGET_NR_stime:
3535 {
pbrook53a59602006-03-25 19:31:22 +00003536 time_t host_time;
bellard2f619692007-11-16 10:46:05 +00003537 if (get_user_sal(host_time, arg1))
3538 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003539 ret = get_errno(stime(&host_time));
bellard31e31b82003-02-18 22:55:36 +00003540 }
3541 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003542#endif
bellard31e31b82003-02-18 22:55:36 +00003543 case TARGET_NR_ptrace:
3544 goto unimplemented;
j_mayer7a3148a2007-04-05 07:13:51 +00003545#ifdef TARGET_NR_alarm /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00003546 case TARGET_NR_alarm:
3547 ret = alarm(arg1);
3548 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003549#endif
bellardebc05482003-09-30 21:08:41 +00003550#ifdef TARGET_NR_oldfstat
bellard31e31b82003-02-18 22:55:36 +00003551 case TARGET_NR_oldfstat:
3552 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00003553#endif
j_mayer7a3148a2007-04-05 07:13:51 +00003554#ifdef TARGET_NR_pause /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00003555 case TARGET_NR_pause:
3556 ret = get_errno(pause());
3557 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003558#endif
thse5febef2007-04-01 18:31:35 +00003559#ifdef TARGET_NR_utime
bellard31e31b82003-02-18 22:55:36 +00003560 case TARGET_NR_utime:
bellardebc05482003-09-30 21:08:41 +00003561 {
pbrook53a59602006-03-25 19:31:22 +00003562 struct utimbuf tbuf, *host_tbuf;
3563 struct target_utimbuf *target_tbuf;
3564 if (arg2) {
bellard579a97f2007-11-11 14:26:47 +00003565 if (!lock_user_struct(VERIFY_READ, target_tbuf, arg2, 1))
3566 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003567 tbuf.actime = tswapl(target_tbuf->actime);
3568 tbuf.modtime = tswapl(target_tbuf->modtime);
3569 unlock_user_struct(target_tbuf, arg2, 0);
3570 host_tbuf = &tbuf;
bellardf72e8ff2004-05-03 19:23:07 +00003571 } else {
pbrook53a59602006-03-25 19:31:22 +00003572 host_tbuf = NULL;
bellardf72e8ff2004-05-03 19:23:07 +00003573 }
bellard579a97f2007-11-11 14:26:47 +00003574 if (!(p = lock_user_string(arg1)))
3575 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003576 ret = get_errno(utime(p, host_tbuf));
3577 unlock_user(p, arg1, 0);
bellardebc05482003-09-30 21:08:41 +00003578 }
3579 break;
thse5febef2007-04-01 18:31:35 +00003580#endif
bellard978a66f2004-12-06 22:58:05 +00003581 case TARGET_NR_utimes:
3582 {
bellard978a66f2004-12-06 22:58:05 +00003583 struct timeval *tvp, tv[2];
pbrook53a59602006-03-25 19:31:22 +00003584 if (arg2) {
ths788f5ec2007-12-09 02:37:05 +00003585 if (copy_from_user_timeval(&tv[0], arg2)
3586 || copy_from_user_timeval(&tv[1],
3587 arg2 + sizeof(struct target_timeval)))
3588 goto efault;
bellard978a66f2004-12-06 22:58:05 +00003589 tvp = tv;
3590 } else {
3591 tvp = NULL;
3592 }
bellard579a97f2007-11-11 14:26:47 +00003593 if (!(p = lock_user_string(arg1)))
3594 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003595 ret = get_errno(utimes(p, tvp));
3596 unlock_user(p, arg1, 0);
bellard978a66f2004-12-06 22:58:05 +00003597 }
3598 break;
bellardebc05482003-09-30 21:08:41 +00003599#ifdef TARGET_NR_stty
bellard31e31b82003-02-18 22:55:36 +00003600 case TARGET_NR_stty:
3601 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00003602#endif
3603#ifdef TARGET_NR_gtty
bellard31e31b82003-02-18 22:55:36 +00003604 case TARGET_NR_gtty:
3605 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00003606#endif
bellard31e31b82003-02-18 22:55:36 +00003607 case TARGET_NR_access:
bellard579a97f2007-11-11 14:26:47 +00003608 if (!(p = lock_user_string(arg1)))
3609 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003610 ret = get_errno(access(p, arg2));
3611 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003612 break;
ths92a34c12007-09-24 09:27:49 +00003613#if defined(TARGET_NR_faccessat) && defined(__NR_faccessat)
3614 case TARGET_NR_faccessat:
bellard579a97f2007-11-11 14:26:47 +00003615 if (!(p = lock_user_string(arg2)))
3616 goto efault;
3617 ret = get_errno(sys_faccessat(arg1, p, arg3, arg4));
3618 unlock_user(p, arg2, 0);
ths92a34c12007-09-24 09:27:49 +00003619 break;
3620#endif
j_mayer7a3148a2007-04-05 07:13:51 +00003621#ifdef TARGET_NR_nice /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00003622 case TARGET_NR_nice:
3623 ret = get_errno(nice(arg1));
3624 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003625#endif
bellardebc05482003-09-30 21:08:41 +00003626#ifdef TARGET_NR_ftime
bellard31e31b82003-02-18 22:55:36 +00003627 case TARGET_NR_ftime:
3628 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00003629#endif
bellard31e31b82003-02-18 22:55:36 +00003630 case TARGET_NR_sync:
bellard04369ff2003-03-20 22:33:23 +00003631 sync();
3632 ret = 0;
bellard31e31b82003-02-18 22:55:36 +00003633 break;
3634 case TARGET_NR_kill:
pbrook4cb05962008-05-30 18:05:19 +00003635 ret = get_errno(kill(arg1, target_to_host_signal(arg2)));
bellard31e31b82003-02-18 22:55:36 +00003636 break;
3637 case TARGET_NR_rename:
pbrook53a59602006-03-25 19:31:22 +00003638 {
3639 void *p2;
3640 p = lock_user_string(arg1);
3641 p2 = lock_user_string(arg2);
bellard579a97f2007-11-11 14:26:47 +00003642 if (!p || !p2)
3643 ret = -TARGET_EFAULT;
3644 else
3645 ret = get_errno(rename(p, p2));
pbrook53a59602006-03-25 19:31:22 +00003646 unlock_user(p2, arg2, 0);
3647 unlock_user(p, arg1, 0);
3648 }
bellard31e31b82003-02-18 22:55:36 +00003649 break;
ths722183f2007-09-24 09:24:37 +00003650#if defined(TARGET_NR_renameat) && defined(__NR_renameat)
3651 case TARGET_NR_renameat:
ths722183f2007-09-24 09:24:37 +00003652 {
bellard579a97f2007-11-11 14:26:47 +00003653 void *p2;
ths722183f2007-09-24 09:24:37 +00003654 p = lock_user_string(arg2);
3655 p2 = lock_user_string(arg4);
bellard579a97f2007-11-11 14:26:47 +00003656 if (!p || !p2)
ths0da46a62007-10-20 20:23:07 +00003657 ret = -TARGET_EFAULT;
ths722183f2007-09-24 09:24:37 +00003658 else
3659 ret = get_errno(sys_renameat(arg1, p, arg3, p2));
bellard579a97f2007-11-11 14:26:47 +00003660 unlock_user(p2, arg4, 0);
3661 unlock_user(p, arg2, 0);
ths722183f2007-09-24 09:24:37 +00003662 }
3663 break;
3664#endif
bellard31e31b82003-02-18 22:55:36 +00003665 case TARGET_NR_mkdir:
bellard579a97f2007-11-11 14:26:47 +00003666 if (!(p = lock_user_string(arg1)))
3667 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003668 ret = get_errno(mkdir(p, arg2));
3669 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003670 break;
ths4472ad02007-09-24 09:22:32 +00003671#if defined(TARGET_NR_mkdirat) && defined(__NR_mkdirat)
3672 case TARGET_NR_mkdirat:
bellard579a97f2007-11-11 14:26:47 +00003673 if (!(p = lock_user_string(arg2)))
3674 goto efault;
3675 ret = get_errno(sys_mkdirat(arg1, p, arg3));
3676 unlock_user(p, arg2, 0);
ths4472ad02007-09-24 09:22:32 +00003677 break;
3678#endif
bellard31e31b82003-02-18 22:55:36 +00003679 case TARGET_NR_rmdir:
bellard579a97f2007-11-11 14:26:47 +00003680 if (!(p = lock_user_string(arg1)))
3681 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003682 ret = get_errno(rmdir(p));
3683 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003684 break;
3685 case TARGET_NR_dup:
3686 ret = get_errno(dup(arg1));
3687 break;
3688 case TARGET_NR_pipe:
3689 {
pbrook53a59602006-03-25 19:31:22 +00003690 int host_pipe[2];
3691 ret = get_errno(pipe(host_pipe));
bellard31e31b82003-02-18 22:55:36 +00003692 if (!is_error(ret)) {
thsc12ab052007-06-01 11:50:36 +00003693#if defined(TARGET_MIPS)
thsead93602007-09-06 00:18:15 +00003694 CPUMIPSState *env = (CPUMIPSState*)cpu_env;
thsb5dc7732008-06-27 10:02:35 +00003695 env->active_tc.gpr[3] = host_pipe[1];
thsc12ab052007-06-01 11:50:36 +00003696 ret = host_pipe[0];
aurel32b5eff352008-03-11 23:30:22 +00003697#elif defined(TARGET_SH4)
3698 ((CPUSH4State*)cpu_env)->gregs[1] = host_pipe[1];
3699 ret = host_pipe[0];
thsc12ab052007-06-01 11:50:36 +00003700#else
bellard2f619692007-11-16 10:46:05 +00003701 if (put_user_s32(host_pipe[0], arg1)
3702 || put_user_s32(host_pipe[1], arg1 + sizeof(host_pipe[0])))
3703 goto efault;
thsc12ab052007-06-01 11:50:36 +00003704#endif
bellard31e31b82003-02-18 22:55:36 +00003705 }
3706 }
3707 break;
3708 case TARGET_NR_times:
bellard32f36bc2003-03-30 21:29:48 +00003709 {
pbrook53a59602006-03-25 19:31:22 +00003710 struct target_tms *tmsp;
bellard32f36bc2003-03-30 21:29:48 +00003711 struct tms tms;
3712 ret = get_errno(times(&tms));
pbrook53a59602006-03-25 19:31:22 +00003713 if (arg1) {
bellard579a97f2007-11-11 14:26:47 +00003714 tmsp = lock_user(VERIFY_WRITE, arg1, sizeof(struct target_tms), 0);
3715 if (!tmsp)
3716 goto efault;
bellardc596ed12003-07-13 17:32:31 +00003717 tmsp->tms_utime = tswapl(host_to_target_clock_t(tms.tms_utime));
3718 tmsp->tms_stime = tswapl(host_to_target_clock_t(tms.tms_stime));
3719 tmsp->tms_cutime = tswapl(host_to_target_clock_t(tms.tms_cutime));
3720 tmsp->tms_cstime = tswapl(host_to_target_clock_t(tms.tms_cstime));
bellard32f36bc2003-03-30 21:29:48 +00003721 }
bellardc596ed12003-07-13 17:32:31 +00003722 if (!is_error(ret))
3723 ret = host_to_target_clock_t(ret);
bellard32f36bc2003-03-30 21:29:48 +00003724 }
3725 break;
bellardebc05482003-09-30 21:08:41 +00003726#ifdef TARGET_NR_prof
bellard31e31b82003-02-18 22:55:36 +00003727 case TARGET_NR_prof:
3728 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00003729#endif
thse5febef2007-04-01 18:31:35 +00003730#ifdef TARGET_NR_signal
bellard31e31b82003-02-18 22:55:36 +00003731 case TARGET_NR_signal:
3732 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00003733#endif
bellard31e31b82003-02-18 22:55:36 +00003734 case TARGET_NR_acct:
bellard579a97f2007-11-11 14:26:47 +00003735 if (!(p = lock_user_string(arg1)))
3736 goto efault;
pbrook24836682006-04-16 14:14:53 +00003737 ret = get_errno(acct(path(p)));
3738 unlock_user(p, arg1, 0);
3739 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003740#ifdef TARGET_NR_umount2 /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00003741 case TARGET_NR_umount2:
bellard579a97f2007-11-11 14:26:47 +00003742 if (!(p = lock_user_string(arg1)))
3743 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003744 ret = get_errno(umount2(p, arg2));
3745 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003746 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003747#endif
bellardebc05482003-09-30 21:08:41 +00003748#ifdef TARGET_NR_lock
bellard31e31b82003-02-18 22:55:36 +00003749 case TARGET_NR_lock:
3750 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00003751#endif
bellard31e31b82003-02-18 22:55:36 +00003752 case TARGET_NR_ioctl:
3753 ret = do_ioctl(arg1, arg2, arg3);
3754 break;
3755 case TARGET_NR_fcntl:
bellard9ee1fa22007-11-11 15:11:19 +00003756 ret = do_fcntl(arg1, arg2, arg3);
bellard31e31b82003-02-18 22:55:36 +00003757 break;
bellardebc05482003-09-30 21:08:41 +00003758#ifdef TARGET_NR_mpx
bellard31e31b82003-02-18 22:55:36 +00003759 case TARGET_NR_mpx:
3760 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00003761#endif
bellard31e31b82003-02-18 22:55:36 +00003762 case TARGET_NR_setpgid:
3763 ret = get_errno(setpgid(arg1, arg2));
3764 break;
bellardebc05482003-09-30 21:08:41 +00003765#ifdef TARGET_NR_ulimit
bellard31e31b82003-02-18 22:55:36 +00003766 case TARGET_NR_ulimit:
3767 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00003768#endif
3769#ifdef TARGET_NR_oldolduname
bellard31e31b82003-02-18 22:55:36 +00003770 case TARGET_NR_oldolduname:
3771 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00003772#endif
bellard31e31b82003-02-18 22:55:36 +00003773 case TARGET_NR_umask:
3774 ret = get_errno(umask(arg1));
3775 break;
3776 case TARGET_NR_chroot:
bellard579a97f2007-11-11 14:26:47 +00003777 if (!(p = lock_user_string(arg1)))
3778 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003779 ret = get_errno(chroot(p));
3780 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003781 break;
3782 case TARGET_NR_ustat:
3783 goto unimplemented;
3784 case TARGET_NR_dup2:
3785 ret = get_errno(dup2(arg1, arg2));
3786 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003787#ifdef TARGET_NR_getppid /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00003788 case TARGET_NR_getppid:
3789 ret = get_errno(getppid());
3790 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003791#endif
bellard31e31b82003-02-18 22:55:36 +00003792 case TARGET_NR_getpgrp:
3793 ret = get_errno(getpgrp());
3794 break;
3795 case TARGET_NR_setsid:
3796 ret = get_errno(setsid());
3797 break;
thse5febef2007-04-01 18:31:35 +00003798#ifdef TARGET_NR_sigaction
bellard31e31b82003-02-18 22:55:36 +00003799 case TARGET_NR_sigaction:
bellard31e31b82003-02-18 22:55:36 +00003800 {
ths388bb212007-05-13 13:58:00 +00003801#if !defined(TARGET_MIPS)
pbrook53a59602006-03-25 19:31:22 +00003802 struct target_old_sigaction *old_act;
bellard66fb9762003-03-23 01:06:05 +00003803 struct target_sigaction act, oact, *pact;
pbrook53a59602006-03-25 19:31:22 +00003804 if (arg2) {
bellard579a97f2007-11-11 14:26:47 +00003805 if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1))
3806 goto efault;
bellard66fb9762003-03-23 01:06:05 +00003807 act._sa_handler = old_act->_sa_handler;
3808 target_siginitset(&act.sa_mask, old_act->sa_mask);
3809 act.sa_flags = old_act->sa_flags;
3810 act.sa_restorer = old_act->sa_restorer;
pbrook53a59602006-03-25 19:31:22 +00003811 unlock_user_struct(old_act, arg2, 0);
bellard66fb9762003-03-23 01:06:05 +00003812 pact = &act;
3813 } else {
3814 pact = NULL;
3815 }
3816 ret = get_errno(do_sigaction(arg1, pact, &oact));
pbrook53a59602006-03-25 19:31:22 +00003817 if (!is_error(ret) && arg3) {
bellard579a97f2007-11-11 14:26:47 +00003818 if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0))
3819 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003820 old_act->_sa_handler = oact._sa_handler;
3821 old_act->sa_mask = oact.sa_mask.sig[0];
3822 old_act->sa_flags = oact.sa_flags;
3823 old_act->sa_restorer = oact.sa_restorer;
3824 unlock_user_struct(old_act, arg3, 1);
bellard66fb9762003-03-23 01:06:05 +00003825 }
ths388bb212007-05-13 13:58:00 +00003826#else
bellard106ec872006-06-27 21:08:10 +00003827 struct target_sigaction act, oact, *pact, *old_act;
3828
3829 if (arg2) {
bellard579a97f2007-11-11 14:26:47 +00003830 if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1))
3831 goto efault;
bellard106ec872006-06-27 21:08:10 +00003832 act._sa_handler = old_act->_sa_handler;
3833 target_siginitset(&act.sa_mask, old_act->sa_mask.sig[0]);
3834 act.sa_flags = old_act->sa_flags;
3835 unlock_user_struct(old_act, arg2, 0);
3836 pact = &act;
3837 } else {
3838 pact = NULL;
3839 }
3840
3841 ret = get_errno(do_sigaction(arg1, pact, &oact));
3842
3843 if (!is_error(ret) && arg3) {
bellard579a97f2007-11-11 14:26:47 +00003844 if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0))
3845 goto efault;
bellard106ec872006-06-27 21:08:10 +00003846 old_act->_sa_handler = oact._sa_handler;
3847 old_act->sa_flags = oact.sa_flags;
3848 old_act->sa_mask.sig[0] = oact.sa_mask.sig[0];
3849 old_act->sa_mask.sig[1] = 0;
3850 old_act->sa_mask.sig[2] = 0;
3851 old_act->sa_mask.sig[3] = 0;
3852 unlock_user_struct(old_act, arg3, 1);
3853 }
ths388bb212007-05-13 13:58:00 +00003854#endif
bellard31e31b82003-02-18 22:55:36 +00003855 }
3856 break;
thse5febef2007-04-01 18:31:35 +00003857#endif
bellard66fb9762003-03-23 01:06:05 +00003858 case TARGET_NR_rt_sigaction:
pbrook53a59602006-03-25 19:31:22 +00003859 {
3860 struct target_sigaction *act;
3861 struct target_sigaction *oact;
3862
bellard579a97f2007-11-11 14:26:47 +00003863 if (arg2) {
3864 if (!lock_user_struct(VERIFY_READ, act, arg2, 1))
3865 goto efault;
3866 } else
pbrook53a59602006-03-25 19:31:22 +00003867 act = NULL;
bellard579a97f2007-11-11 14:26:47 +00003868 if (arg3) {
3869 if (!lock_user_struct(VERIFY_WRITE, oact, arg3, 0)) {
3870 ret = -TARGET_EFAULT;
3871 goto rt_sigaction_fail;
3872 }
3873 } else
pbrook53a59602006-03-25 19:31:22 +00003874 oact = NULL;
3875 ret = get_errno(do_sigaction(arg1, act, oact));
bellard579a97f2007-11-11 14:26:47 +00003876 rt_sigaction_fail:
3877 if (act)
pbrook53a59602006-03-25 19:31:22 +00003878 unlock_user_struct(act, arg2, 0);
bellard579a97f2007-11-11 14:26:47 +00003879 if (oact)
pbrook53a59602006-03-25 19:31:22 +00003880 unlock_user_struct(oact, arg3, 1);
3881 }
bellard66fb9762003-03-23 01:06:05 +00003882 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003883#ifdef TARGET_NR_sgetmask /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00003884 case TARGET_NR_sgetmask:
bellard66fb9762003-03-23 01:06:05 +00003885 {
3886 sigset_t cur_set;
blueswir1992f48a2007-10-14 16:27:31 +00003887 abi_ulong target_set;
bellard66fb9762003-03-23 01:06:05 +00003888 sigprocmask(0, NULL, &cur_set);
3889 host_to_target_old_sigset(&target_set, &cur_set);
3890 ret = target_set;
3891 }
3892 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003893#endif
3894#ifdef TARGET_NR_ssetmask /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00003895 case TARGET_NR_ssetmask:
bellard66fb9762003-03-23 01:06:05 +00003896 {
3897 sigset_t set, oset, cur_set;
blueswir1992f48a2007-10-14 16:27:31 +00003898 abi_ulong target_set = arg1;
bellard66fb9762003-03-23 01:06:05 +00003899 sigprocmask(0, NULL, &cur_set);
3900 target_to_host_old_sigset(&set, &target_set);
3901 sigorset(&set, &set, &cur_set);
3902 sigprocmask(SIG_SETMASK, &set, &oset);
3903 host_to_target_old_sigset(&target_set, &oset);
3904 ret = target_set;
3905 }
3906 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003907#endif
thse5febef2007-04-01 18:31:35 +00003908#ifdef TARGET_NR_sigprocmask
bellard66fb9762003-03-23 01:06:05 +00003909 case TARGET_NR_sigprocmask:
3910 {
3911 int how = arg1;
3912 sigset_t set, oldset, *set_ptr;
ths3b46e622007-09-17 08:09:54 +00003913
pbrook53a59602006-03-25 19:31:22 +00003914 if (arg2) {
bellard66fb9762003-03-23 01:06:05 +00003915 switch(how) {
3916 case TARGET_SIG_BLOCK:
3917 how = SIG_BLOCK;
3918 break;
3919 case TARGET_SIG_UNBLOCK:
3920 how = SIG_UNBLOCK;
3921 break;
3922 case TARGET_SIG_SETMASK:
3923 how = SIG_SETMASK;
3924 break;
3925 default:
ths0da46a62007-10-20 20:23:07 +00003926 ret = -TARGET_EINVAL;
bellard66fb9762003-03-23 01:06:05 +00003927 goto fail;
3928 }
bellard579a97f2007-11-11 14:26:47 +00003929 if (!(p = lock_user(VERIFY_READ, arg2, sizeof(target_sigset_t), 1)))
3930 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003931 target_to_host_old_sigset(&set, p);
3932 unlock_user(p, arg2, 0);
bellard66fb9762003-03-23 01:06:05 +00003933 set_ptr = &set;
3934 } else {
3935 how = 0;
3936 set_ptr = NULL;
3937 }
3938 ret = get_errno(sigprocmask(arg1, set_ptr, &oldset));
pbrook53a59602006-03-25 19:31:22 +00003939 if (!is_error(ret) && arg3) {
bellard579a97f2007-11-11 14:26:47 +00003940 if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0)))
3941 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003942 host_to_target_old_sigset(p, &oldset);
3943 unlock_user(p, arg3, sizeof(target_sigset_t));
bellard66fb9762003-03-23 01:06:05 +00003944 }
3945 }
3946 break;
thse5febef2007-04-01 18:31:35 +00003947#endif
bellard66fb9762003-03-23 01:06:05 +00003948 case TARGET_NR_rt_sigprocmask:
3949 {
3950 int how = arg1;
3951 sigset_t set, oldset, *set_ptr;
ths3b46e622007-09-17 08:09:54 +00003952
pbrook53a59602006-03-25 19:31:22 +00003953 if (arg2) {
bellard66fb9762003-03-23 01:06:05 +00003954 switch(how) {
3955 case TARGET_SIG_BLOCK:
3956 how = SIG_BLOCK;
3957 break;
3958 case TARGET_SIG_UNBLOCK:
3959 how = SIG_UNBLOCK;
3960 break;
3961 case TARGET_SIG_SETMASK:
3962 how = SIG_SETMASK;
3963 break;
3964 default:
ths0da46a62007-10-20 20:23:07 +00003965 ret = -TARGET_EINVAL;
bellard66fb9762003-03-23 01:06:05 +00003966 goto fail;
3967 }
bellard579a97f2007-11-11 14:26:47 +00003968 if (!(p = lock_user(VERIFY_READ, arg2, sizeof(target_sigset_t), 1)))
3969 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003970 target_to_host_sigset(&set, p);
3971 unlock_user(p, arg2, 0);
bellard66fb9762003-03-23 01:06:05 +00003972 set_ptr = &set;
3973 } else {
3974 how = 0;
3975 set_ptr = NULL;
3976 }
3977 ret = get_errno(sigprocmask(how, set_ptr, &oldset));
pbrook53a59602006-03-25 19:31:22 +00003978 if (!is_error(ret) && arg3) {
bellard579a97f2007-11-11 14:26:47 +00003979 if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0)))
3980 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003981 host_to_target_sigset(p, &oldset);
3982 unlock_user(p, arg3, sizeof(target_sigset_t));
bellard66fb9762003-03-23 01:06:05 +00003983 }
3984 }
3985 break;
thse5febef2007-04-01 18:31:35 +00003986#ifdef TARGET_NR_sigpending
bellard66fb9762003-03-23 01:06:05 +00003987 case TARGET_NR_sigpending:
3988 {
3989 sigset_t set;
3990 ret = get_errno(sigpending(&set));
3991 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00003992 if (!(p = lock_user(VERIFY_WRITE, arg1, sizeof(target_sigset_t), 0)))
3993 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003994 host_to_target_old_sigset(p, &set);
3995 unlock_user(p, arg1, sizeof(target_sigset_t));
bellard66fb9762003-03-23 01:06:05 +00003996 }
3997 }
3998 break;
thse5febef2007-04-01 18:31:35 +00003999#endif
bellard66fb9762003-03-23 01:06:05 +00004000 case TARGET_NR_rt_sigpending:
4001 {
4002 sigset_t set;
4003 ret = get_errno(sigpending(&set));
4004 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00004005 if (!(p = lock_user(VERIFY_WRITE, arg1, sizeof(target_sigset_t), 0)))
4006 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004007 host_to_target_sigset(p, &set);
4008 unlock_user(p, arg1, sizeof(target_sigset_t));
bellard66fb9762003-03-23 01:06:05 +00004009 }
4010 }
4011 break;
thse5febef2007-04-01 18:31:35 +00004012#ifdef TARGET_NR_sigsuspend
bellard66fb9762003-03-23 01:06:05 +00004013 case TARGET_NR_sigsuspend:
4014 {
4015 sigset_t set;
bellard579a97f2007-11-11 14:26:47 +00004016 if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
4017 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004018 target_to_host_old_sigset(&set, p);
4019 unlock_user(p, arg1, 0);
bellard66fb9762003-03-23 01:06:05 +00004020 ret = get_errno(sigsuspend(&set));
4021 }
4022 break;
thse5febef2007-04-01 18:31:35 +00004023#endif
bellard66fb9762003-03-23 01:06:05 +00004024 case TARGET_NR_rt_sigsuspend:
4025 {
4026 sigset_t set;
bellard579a97f2007-11-11 14:26:47 +00004027 if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
4028 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004029 target_to_host_sigset(&set, p);
4030 unlock_user(p, arg1, 0);
bellard66fb9762003-03-23 01:06:05 +00004031 ret = get_errno(sigsuspend(&set));
4032 }
4033 break;
4034 case TARGET_NR_rt_sigtimedwait:
4035 {
bellard66fb9762003-03-23 01:06:05 +00004036 sigset_t set;
4037 struct timespec uts, *puts;
4038 siginfo_t uinfo;
ths3b46e622007-09-17 08:09:54 +00004039
bellard579a97f2007-11-11 14:26:47 +00004040 if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
4041 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004042 target_to_host_sigset(&set, p);
4043 unlock_user(p, arg1, 0);
4044 if (arg3) {
bellard66fb9762003-03-23 01:06:05 +00004045 puts = &uts;
pbrook53a59602006-03-25 19:31:22 +00004046 target_to_host_timespec(puts, arg3);
bellard66fb9762003-03-23 01:06:05 +00004047 } else {
4048 puts = NULL;
4049 }
4050 ret = get_errno(sigtimedwait(&set, &uinfo, puts));
pbrook53a59602006-03-25 19:31:22 +00004051 if (!is_error(ret) && arg2) {
pbrooke1e3f302008-05-30 21:53:38 +00004052 if (!(p = lock_user(VERIFY_WRITE, arg2, sizeof(target_siginfo_t), 0)))
bellard579a97f2007-11-11 14:26:47 +00004053 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004054 host_to_target_siginfo(p, &uinfo);
pbrooke1e3f302008-05-30 21:53:38 +00004055 unlock_user(p, arg2, sizeof(target_siginfo_t));
bellard66fb9762003-03-23 01:06:05 +00004056 }
4057 }
4058 break;
4059 case TARGET_NR_rt_sigqueueinfo:
4060 {
4061 siginfo_t uinfo;
bellard579a97f2007-11-11 14:26:47 +00004062 if (!(p = lock_user(VERIFY_READ, arg3, sizeof(target_sigset_t), 1)))
4063 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004064 target_to_host_siginfo(&uinfo, p);
4065 unlock_user(p, arg1, 0);
bellard66fb9762003-03-23 01:06:05 +00004066 ret = get_errno(sys_rt_sigqueueinfo(arg1, arg2, &uinfo));
4067 }
4068 break;
thse5febef2007-04-01 18:31:35 +00004069#ifdef TARGET_NR_sigreturn
bellard66fb9762003-03-23 01:06:05 +00004070 case TARGET_NR_sigreturn:
4071 /* NOTE: ret is eax, so not transcoding must be done */
4072 ret = do_sigreturn(cpu_env);
4073 break;
thse5febef2007-04-01 18:31:35 +00004074#endif
bellard66fb9762003-03-23 01:06:05 +00004075 case TARGET_NR_rt_sigreturn:
4076 /* NOTE: ret is eax, so not transcoding must be done */
4077 ret = do_rt_sigreturn(cpu_env);
4078 break;
bellard31e31b82003-02-18 22:55:36 +00004079 case TARGET_NR_sethostname:
bellard579a97f2007-11-11 14:26:47 +00004080 if (!(p = lock_user_string(arg1)))
4081 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004082 ret = get_errno(sethostname(p, arg2));
4083 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004084 break;
4085 case TARGET_NR_setrlimit:
bellard9de5e442003-03-23 16:49:39 +00004086 {
4087 /* XXX: convert resource ? */
4088 int resource = arg1;
pbrook53a59602006-03-25 19:31:22 +00004089 struct target_rlimit *target_rlim;
bellard9de5e442003-03-23 16:49:39 +00004090 struct rlimit rlim;
bellard579a97f2007-11-11 14:26:47 +00004091 if (!lock_user_struct(VERIFY_READ, target_rlim, arg2, 1))
4092 goto efault;
bellard9de5e442003-03-23 16:49:39 +00004093 rlim.rlim_cur = tswapl(target_rlim->rlim_cur);
4094 rlim.rlim_max = tswapl(target_rlim->rlim_max);
pbrook53a59602006-03-25 19:31:22 +00004095 unlock_user_struct(target_rlim, arg2, 0);
bellard9de5e442003-03-23 16:49:39 +00004096 ret = get_errno(setrlimit(resource, &rlim));
4097 }
4098 break;
bellard31e31b82003-02-18 22:55:36 +00004099 case TARGET_NR_getrlimit:
bellard9de5e442003-03-23 16:49:39 +00004100 {
4101 /* XXX: convert resource ? */
4102 int resource = arg1;
pbrook53a59602006-03-25 19:31:22 +00004103 struct target_rlimit *target_rlim;
bellard9de5e442003-03-23 16:49:39 +00004104 struct rlimit rlim;
ths3b46e622007-09-17 08:09:54 +00004105
bellard9de5e442003-03-23 16:49:39 +00004106 ret = get_errno(getrlimit(resource, &rlim));
4107 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00004108 if (!lock_user_struct(VERIFY_WRITE, target_rlim, arg2, 0))
4109 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004110 rlim.rlim_cur = tswapl(target_rlim->rlim_cur);
4111 rlim.rlim_max = tswapl(target_rlim->rlim_max);
4112 unlock_user_struct(target_rlim, arg2, 1);
bellard9de5e442003-03-23 16:49:39 +00004113 }
4114 }
4115 break;
bellard31e31b82003-02-18 22:55:36 +00004116 case TARGET_NR_getrusage:
bellardb4091862003-05-16 15:39:34 +00004117 {
4118 struct rusage rusage;
bellardb4091862003-05-16 15:39:34 +00004119 ret = get_errno(getrusage(arg1, &rusage));
4120 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00004121 host_to_target_rusage(arg2, &rusage);
bellardb4091862003-05-16 15:39:34 +00004122 }
4123 }
4124 break;
bellard31e31b82003-02-18 22:55:36 +00004125 case TARGET_NR_gettimeofday:
4126 {
bellard31e31b82003-02-18 22:55:36 +00004127 struct timeval tv;
4128 ret = get_errno(gettimeofday(&tv, NULL));
4129 if (!is_error(ret)) {
ths788f5ec2007-12-09 02:37:05 +00004130 if (copy_to_user_timeval(arg1, &tv))
4131 goto efault;
bellard31e31b82003-02-18 22:55:36 +00004132 }
4133 }
4134 break;
4135 case TARGET_NR_settimeofday:
4136 {
bellard31e31b82003-02-18 22:55:36 +00004137 struct timeval tv;
ths788f5ec2007-12-09 02:37:05 +00004138 if (copy_from_user_timeval(&tv, arg1))
4139 goto efault;
bellard31e31b82003-02-18 22:55:36 +00004140 ret = get_errno(settimeofday(&tv, NULL));
4141 }
4142 break;
bellard048f6b42005-11-26 18:47:20 +00004143#ifdef TARGET_NR_select
bellard31e31b82003-02-18 22:55:36 +00004144 case TARGET_NR_select:
bellardf2674e32003-07-09 12:26:09 +00004145 {
pbrook53a59602006-03-25 19:31:22 +00004146 struct target_sel_arg_struct *sel;
blueswir1992f48a2007-10-14 16:27:31 +00004147 abi_ulong inp, outp, exp, tvp;
pbrook53a59602006-03-25 19:31:22 +00004148 long nsel;
4149
bellard579a97f2007-11-11 14:26:47 +00004150 if (!lock_user_struct(VERIFY_READ, sel, arg1, 1))
4151 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004152 nsel = tswapl(sel->n);
4153 inp = tswapl(sel->inp);
4154 outp = tswapl(sel->outp);
4155 exp = tswapl(sel->exp);
4156 tvp = tswapl(sel->tvp);
4157 unlock_user_struct(sel, arg1, 0);
4158 ret = do_select(nsel, inp, outp, exp, tvp);
bellardf2674e32003-07-09 12:26:09 +00004159 }
4160 break;
bellard048f6b42005-11-26 18:47:20 +00004161#endif
bellard31e31b82003-02-18 22:55:36 +00004162 case TARGET_NR_symlink:
pbrook53a59602006-03-25 19:31:22 +00004163 {
4164 void *p2;
4165 p = lock_user_string(arg1);
4166 p2 = lock_user_string(arg2);
bellard579a97f2007-11-11 14:26:47 +00004167 if (!p || !p2)
4168 ret = -TARGET_EFAULT;
4169 else
4170 ret = get_errno(symlink(p, p2));
pbrook53a59602006-03-25 19:31:22 +00004171 unlock_user(p2, arg2, 0);
4172 unlock_user(p, arg1, 0);
4173 }
bellard31e31b82003-02-18 22:55:36 +00004174 break;
thsf0b62432007-09-24 09:25:40 +00004175#if defined(TARGET_NR_symlinkat) && defined(__NR_symlinkat)
4176 case TARGET_NR_symlinkat:
thsf0b62432007-09-24 09:25:40 +00004177 {
bellard579a97f2007-11-11 14:26:47 +00004178 void *p2;
thsf0b62432007-09-24 09:25:40 +00004179 p = lock_user_string(arg1);
4180 p2 = lock_user_string(arg3);
bellard579a97f2007-11-11 14:26:47 +00004181 if (!p || !p2)
ths0da46a62007-10-20 20:23:07 +00004182 ret = -TARGET_EFAULT;
thsf0b62432007-09-24 09:25:40 +00004183 else
4184 ret = get_errno(sys_symlinkat(p, arg2, p2));
bellard579a97f2007-11-11 14:26:47 +00004185 unlock_user(p2, arg3, 0);
4186 unlock_user(p, arg1, 0);
thsf0b62432007-09-24 09:25:40 +00004187 }
4188 break;
4189#endif
bellardebc05482003-09-30 21:08:41 +00004190#ifdef TARGET_NR_oldlstat
bellard31e31b82003-02-18 22:55:36 +00004191 case TARGET_NR_oldlstat:
4192 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004193#endif
bellard31e31b82003-02-18 22:55:36 +00004194 case TARGET_NR_readlink:
pbrook53a59602006-03-25 19:31:22 +00004195 {
4196 void *p2;
4197 p = lock_user_string(arg1);
bellard579a97f2007-11-11 14:26:47 +00004198 p2 = lock_user(VERIFY_WRITE, arg2, arg3, 0);
4199 if (!p || !p2)
4200 ret = -TARGET_EFAULT;
4201 else
4202 ret = get_errno(readlink(path(p), p2, arg3));
pbrook53a59602006-03-25 19:31:22 +00004203 unlock_user(p2, arg2, ret);
4204 unlock_user(p, arg1, 0);
4205 }
bellard31e31b82003-02-18 22:55:36 +00004206 break;
ths5e0ccb12007-09-24 09:26:10 +00004207#if defined(TARGET_NR_readlinkat) && defined(__NR_readlinkat)
4208 case TARGET_NR_readlinkat:
ths5e0ccb12007-09-24 09:26:10 +00004209 {
bellard579a97f2007-11-11 14:26:47 +00004210 void *p2;
ths5e0ccb12007-09-24 09:26:10 +00004211 p = lock_user_string(arg2);
bellard579a97f2007-11-11 14:26:47 +00004212 p2 = lock_user(VERIFY_WRITE, arg3, arg4, 0);
4213 if (!p || !p2)
ths0da46a62007-10-20 20:23:07 +00004214 ret = -TARGET_EFAULT;
ths5e0ccb12007-09-24 09:26:10 +00004215 else
4216 ret = get_errno(sys_readlinkat(arg1, path(p), p2, arg4));
bellard579a97f2007-11-11 14:26:47 +00004217 unlock_user(p2, arg3, ret);
4218 unlock_user(p, arg2, 0);
ths5e0ccb12007-09-24 09:26:10 +00004219 }
4220 break;
4221#endif
thse5febef2007-04-01 18:31:35 +00004222#ifdef TARGET_NR_uselib
bellard31e31b82003-02-18 22:55:36 +00004223 case TARGET_NR_uselib:
4224 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00004225#endif
4226#ifdef TARGET_NR_swapon
bellard31e31b82003-02-18 22:55:36 +00004227 case TARGET_NR_swapon:
bellard579a97f2007-11-11 14:26:47 +00004228 if (!(p = lock_user_string(arg1)))
4229 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004230 ret = get_errno(swapon(p, arg2));
4231 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004232 break;
thse5febef2007-04-01 18:31:35 +00004233#endif
bellard31e31b82003-02-18 22:55:36 +00004234 case TARGET_NR_reboot:
4235 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00004236#ifdef TARGET_NR_readdir
bellard31e31b82003-02-18 22:55:36 +00004237 case TARGET_NR_readdir:
4238 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00004239#endif
4240#ifdef TARGET_NR_mmap
bellard31e31b82003-02-18 22:55:36 +00004241 case TARGET_NR_mmap:
bellardd2fd1af2007-11-14 18:08:56 +00004242#if (defined(TARGET_I386) && defined(TARGET_ABI32)) || defined(TARGET_ARM) || defined(TARGET_M68K) || defined(TARGET_CRIS)
bellard31e31b82003-02-18 22:55:36 +00004243 {
blueswir1992f48a2007-10-14 16:27:31 +00004244 abi_ulong *v;
4245 abi_ulong v1, v2, v3, v4, v5, v6;
bellard579a97f2007-11-11 14:26:47 +00004246 if (!(v = lock_user(VERIFY_READ, arg1, 6 * sizeof(abi_ulong), 1)))
4247 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004248 v1 = tswapl(v[0]);
4249 v2 = tswapl(v[1]);
4250 v3 = tswapl(v[2]);
4251 v4 = tswapl(v[3]);
4252 v5 = tswapl(v[4]);
4253 v6 = tswapl(v[5]);
4254 unlock_user(v, arg1, 0);
ths5fafdf22007-09-16 21:08:06 +00004255 ret = get_errno(target_mmap(v1, v2, v3,
bellard5286db72003-06-05 00:57:30 +00004256 target_to_host_bitmask(v4, mmap_flags_tbl),
4257 v5, v6));
bellard31e31b82003-02-18 22:55:36 +00004258 }
bellard31e31b82003-02-18 22:55:36 +00004259#else
ths5fafdf22007-09-16 21:08:06 +00004260 ret = get_errno(target_mmap(arg1, arg2, arg3,
4261 target_to_host_bitmask(arg4, mmap_flags_tbl),
bellard6fb883e2003-07-09 17:12:39 +00004262 arg5,
4263 arg6));
bellard31e31b82003-02-18 22:55:36 +00004264#endif
bellard6fb883e2003-07-09 17:12:39 +00004265 break;
thse5febef2007-04-01 18:31:35 +00004266#endif
bellarda315a142005-01-30 22:59:18 +00004267#ifdef TARGET_NR_mmap2
bellard6fb883e2003-07-09 17:12:39 +00004268 case TARGET_NR_mmap2:
pbrookbb7ec042008-03-25 22:28:25 +00004269#ifndef MMAP_SHIFT
bellardc573ff62004-01-04 15:51:36 +00004270#define MMAP_SHIFT 12
bellardc573ff62004-01-04 15:51:36 +00004271#endif
ths5fafdf22007-09-16 21:08:06 +00004272 ret = get_errno(target_mmap(arg1, arg2, arg3,
4273 target_to_host_bitmask(arg4, mmap_flags_tbl),
bellard5286db72003-06-05 00:57:30 +00004274 arg5,
bellardc573ff62004-01-04 15:51:36 +00004275 arg6 << MMAP_SHIFT));
bellard31e31b82003-02-18 22:55:36 +00004276 break;
bellarda315a142005-01-30 22:59:18 +00004277#endif
bellard31e31b82003-02-18 22:55:36 +00004278 case TARGET_NR_munmap:
bellard54936002003-05-13 00:25:15 +00004279 ret = get_errno(target_munmap(arg1, arg2));
bellard31e31b82003-02-18 22:55:36 +00004280 break;
bellard9de5e442003-03-23 16:49:39 +00004281 case TARGET_NR_mprotect:
bellard54936002003-05-13 00:25:15 +00004282 ret = get_errno(target_mprotect(arg1, arg2, arg3));
bellard9de5e442003-03-23 16:49:39 +00004283 break;
thse5febef2007-04-01 18:31:35 +00004284#ifdef TARGET_NR_mremap
bellard9de5e442003-03-23 16:49:39 +00004285 case TARGET_NR_mremap:
bellard54936002003-05-13 00:25:15 +00004286 ret = get_errno(target_mremap(arg1, arg2, arg3, arg4, arg5));
bellard9de5e442003-03-23 16:49:39 +00004287 break;
thse5febef2007-04-01 18:31:35 +00004288#endif
pbrook53a59602006-03-25 19:31:22 +00004289 /* ??? msync/mlock/munlock are broken for softmmu. */
thse5febef2007-04-01 18:31:35 +00004290#ifdef TARGET_NR_msync
bellard9de5e442003-03-23 16:49:39 +00004291 case TARGET_NR_msync:
pbrook53a59602006-03-25 19:31:22 +00004292 ret = get_errno(msync(g2h(arg1), arg2, arg3));
bellard9de5e442003-03-23 16:49:39 +00004293 break;
thse5febef2007-04-01 18:31:35 +00004294#endif
4295#ifdef TARGET_NR_mlock
bellard9de5e442003-03-23 16:49:39 +00004296 case TARGET_NR_mlock:
pbrook53a59602006-03-25 19:31:22 +00004297 ret = get_errno(mlock(g2h(arg1), arg2));
bellard9de5e442003-03-23 16:49:39 +00004298 break;
thse5febef2007-04-01 18:31:35 +00004299#endif
4300#ifdef TARGET_NR_munlock
bellard9de5e442003-03-23 16:49:39 +00004301 case TARGET_NR_munlock:
pbrook53a59602006-03-25 19:31:22 +00004302 ret = get_errno(munlock(g2h(arg1), arg2));
bellard9de5e442003-03-23 16:49:39 +00004303 break;
thse5febef2007-04-01 18:31:35 +00004304#endif
4305#ifdef TARGET_NR_mlockall
bellard9de5e442003-03-23 16:49:39 +00004306 case TARGET_NR_mlockall:
4307 ret = get_errno(mlockall(arg1));
4308 break;
thse5febef2007-04-01 18:31:35 +00004309#endif
4310#ifdef TARGET_NR_munlockall
bellard9de5e442003-03-23 16:49:39 +00004311 case TARGET_NR_munlockall:
4312 ret = get_errno(munlockall());
4313 break;
thse5febef2007-04-01 18:31:35 +00004314#endif
bellard31e31b82003-02-18 22:55:36 +00004315 case TARGET_NR_truncate:
bellard579a97f2007-11-11 14:26:47 +00004316 if (!(p = lock_user_string(arg1)))
4317 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004318 ret = get_errno(truncate(p, arg2));
4319 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004320 break;
4321 case TARGET_NR_ftruncate:
4322 ret = get_errno(ftruncate(arg1, arg2));
4323 break;
4324 case TARGET_NR_fchmod:
4325 ret = get_errno(fchmod(arg1, arg2));
4326 break;
ths814d7972007-09-24 09:26:51 +00004327#if defined(TARGET_NR_fchmodat) && defined(__NR_fchmodat)
4328 case TARGET_NR_fchmodat:
bellard579a97f2007-11-11 14:26:47 +00004329 if (!(p = lock_user_string(arg2)))
4330 goto efault;
4331 ret = get_errno(sys_fchmodat(arg1, p, arg3, arg4));
4332 unlock_user(p, arg2, 0);
ths814d7972007-09-24 09:26:51 +00004333 break;
4334#endif
bellard31e31b82003-02-18 22:55:36 +00004335 case TARGET_NR_getpriority:
thsc6cda172007-10-09 03:42:34 +00004336 /* libc does special remapping of the return value of
4337 * sys_getpriority() so it's just easiest to call
4338 * sys_getpriority() directly rather than through libc. */
4339 ret = sys_getpriority(arg1, arg2);
bellard31e31b82003-02-18 22:55:36 +00004340 break;
4341 case TARGET_NR_setpriority:
4342 ret = get_errno(setpriority(arg1, arg2, arg3));
4343 break;
bellardebc05482003-09-30 21:08:41 +00004344#ifdef TARGET_NR_profil
bellard31e31b82003-02-18 22:55:36 +00004345 case TARGET_NR_profil:
4346 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004347#endif
bellard31e31b82003-02-18 22:55:36 +00004348 case TARGET_NR_statfs:
bellard579a97f2007-11-11 14:26:47 +00004349 if (!(p = lock_user_string(arg1)))
4350 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004351 ret = get_errno(statfs(path(p), &stfs));
4352 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004353 convert_statfs:
4354 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00004355 struct target_statfs *target_stfs;
ths3b46e622007-09-17 08:09:54 +00004356
bellard579a97f2007-11-11 14:26:47 +00004357 if (!lock_user_struct(VERIFY_WRITE, target_stfs, arg2, 0))
4358 goto efault;
4359 __put_user(stfs.f_type, &target_stfs->f_type);
4360 __put_user(stfs.f_bsize, &target_stfs->f_bsize);
4361 __put_user(stfs.f_blocks, &target_stfs->f_blocks);
4362 __put_user(stfs.f_bfree, &target_stfs->f_bfree);
4363 __put_user(stfs.f_bavail, &target_stfs->f_bavail);
4364 __put_user(stfs.f_files, &target_stfs->f_files);
4365 __put_user(stfs.f_ffree, &target_stfs->f_ffree);
4366 __put_user(stfs.f_fsid.__val[0], &target_stfs->f_fsid.val[0]);
4367 __put_user(stfs.f_fsid.__val[1], &target_stfs->f_fsid.val[1]);
4368 __put_user(stfs.f_namelen, &target_stfs->f_namelen);
pbrook53a59602006-03-25 19:31:22 +00004369 unlock_user_struct(target_stfs, arg2, 1);
bellard31e31b82003-02-18 22:55:36 +00004370 }
4371 break;
4372 case TARGET_NR_fstatfs:
bellard56c8f682005-11-28 22:28:41 +00004373 ret = get_errno(fstatfs(arg1, &stfs));
bellard31e31b82003-02-18 22:55:36 +00004374 goto convert_statfs;
bellard56c8f682005-11-28 22:28:41 +00004375#ifdef TARGET_NR_statfs64
4376 case TARGET_NR_statfs64:
bellard579a97f2007-11-11 14:26:47 +00004377 if (!(p = lock_user_string(arg1)))
4378 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004379 ret = get_errno(statfs(path(p), &stfs));
4380 unlock_user(p, arg1, 0);
bellard56c8f682005-11-28 22:28:41 +00004381 convert_statfs64:
4382 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00004383 struct target_statfs64 *target_stfs;
ths3b46e622007-09-17 08:09:54 +00004384
bellard579a97f2007-11-11 14:26:47 +00004385 if (!lock_user_struct(VERIFY_WRITE, target_stfs, arg3, 0))
4386 goto efault;
4387 __put_user(stfs.f_type, &target_stfs->f_type);
4388 __put_user(stfs.f_bsize, &target_stfs->f_bsize);
4389 __put_user(stfs.f_blocks, &target_stfs->f_blocks);
4390 __put_user(stfs.f_bfree, &target_stfs->f_bfree);
4391 __put_user(stfs.f_bavail, &target_stfs->f_bavail);
4392 __put_user(stfs.f_files, &target_stfs->f_files);
4393 __put_user(stfs.f_ffree, &target_stfs->f_ffree);
4394 __put_user(stfs.f_fsid.__val[0], &target_stfs->f_fsid.val[0]);
4395 __put_user(stfs.f_fsid.__val[1], &target_stfs->f_fsid.val[1]);
4396 __put_user(stfs.f_namelen, &target_stfs->f_namelen);
4397 unlock_user_struct(target_stfs, arg3, 1);
bellard56c8f682005-11-28 22:28:41 +00004398 }
4399 break;
4400 case TARGET_NR_fstatfs64:
4401 ret = get_errno(fstatfs(arg1, &stfs));
4402 goto convert_statfs64;
4403#endif
bellardebc05482003-09-30 21:08:41 +00004404#ifdef TARGET_NR_ioperm
bellard31e31b82003-02-18 22:55:36 +00004405 case TARGET_NR_ioperm:
4406 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004407#endif
thse5febef2007-04-01 18:31:35 +00004408#ifdef TARGET_NR_socketcall
bellard31e31b82003-02-18 22:55:36 +00004409 case TARGET_NR_socketcall:
pbrook53a59602006-03-25 19:31:22 +00004410 ret = do_socketcall(arg1, arg2);
bellard31e31b82003-02-18 22:55:36 +00004411 break;
thse5febef2007-04-01 18:31:35 +00004412#endif
bellard3532fa72006-06-24 15:06:03 +00004413#ifdef TARGET_NR_accept
4414 case TARGET_NR_accept:
pbrook1be9e1d2006-11-19 15:26:04 +00004415 ret = do_accept(arg1, arg2, arg3);
bellard3532fa72006-06-24 15:06:03 +00004416 break;
4417#endif
4418#ifdef TARGET_NR_bind
4419 case TARGET_NR_bind:
4420 ret = do_bind(arg1, arg2, arg3);
4421 break;
4422#endif
4423#ifdef TARGET_NR_connect
4424 case TARGET_NR_connect:
4425 ret = do_connect(arg1, arg2, arg3);
4426 break;
4427#endif
4428#ifdef TARGET_NR_getpeername
4429 case TARGET_NR_getpeername:
pbrook1be9e1d2006-11-19 15:26:04 +00004430 ret = do_getpeername(arg1, arg2, arg3);
bellard3532fa72006-06-24 15:06:03 +00004431 break;
4432#endif
4433#ifdef TARGET_NR_getsockname
4434 case TARGET_NR_getsockname:
pbrook1be9e1d2006-11-19 15:26:04 +00004435 ret = do_getsockname(arg1, arg2, arg3);
bellard3532fa72006-06-24 15:06:03 +00004436 break;
4437#endif
4438#ifdef TARGET_NR_getsockopt
4439 case TARGET_NR_getsockopt:
4440 ret = do_getsockopt(arg1, arg2, arg3, arg4, arg5);
4441 break;
4442#endif
4443#ifdef TARGET_NR_listen
4444 case TARGET_NR_listen:
pbrook1be9e1d2006-11-19 15:26:04 +00004445 ret = get_errno(listen(arg1, arg2));
bellard3532fa72006-06-24 15:06:03 +00004446 break;
4447#endif
4448#ifdef TARGET_NR_recv
4449 case TARGET_NR_recv:
pbrook214201b2007-03-17 01:27:24 +00004450 ret = do_recvfrom(arg1, arg2, arg3, arg4, 0, 0);
bellard3532fa72006-06-24 15:06:03 +00004451 break;
4452#endif
4453#ifdef TARGET_NR_recvfrom
4454 case TARGET_NR_recvfrom:
pbrook214201b2007-03-17 01:27:24 +00004455 ret = do_recvfrom(arg1, arg2, arg3, arg4, arg5, arg6);
bellard3532fa72006-06-24 15:06:03 +00004456 break;
4457#endif
4458#ifdef TARGET_NR_recvmsg
4459 case TARGET_NR_recvmsg:
4460 ret = do_sendrecvmsg(arg1, arg2, arg3, 0);
4461 break;
4462#endif
4463#ifdef TARGET_NR_send
4464 case TARGET_NR_send:
pbrook1be9e1d2006-11-19 15:26:04 +00004465 ret = do_sendto(arg1, arg2, arg3, arg4, 0, 0);
bellard3532fa72006-06-24 15:06:03 +00004466 break;
4467#endif
4468#ifdef TARGET_NR_sendmsg
4469 case TARGET_NR_sendmsg:
4470 ret = do_sendrecvmsg(arg1, arg2, arg3, 1);
4471 break;
4472#endif
4473#ifdef TARGET_NR_sendto
4474 case TARGET_NR_sendto:
pbrook1be9e1d2006-11-19 15:26:04 +00004475 ret = do_sendto(arg1, arg2, arg3, arg4, arg5, arg6);
bellard3532fa72006-06-24 15:06:03 +00004476 break;
4477#endif
4478#ifdef TARGET_NR_shutdown
4479 case TARGET_NR_shutdown:
pbrook1be9e1d2006-11-19 15:26:04 +00004480 ret = get_errno(shutdown(arg1, arg2));
bellard3532fa72006-06-24 15:06:03 +00004481 break;
4482#endif
4483#ifdef TARGET_NR_socket
4484 case TARGET_NR_socket:
4485 ret = do_socket(arg1, arg2, arg3);
4486 break;
4487#endif
4488#ifdef TARGET_NR_socketpair
4489 case TARGET_NR_socketpair:
pbrook1be9e1d2006-11-19 15:26:04 +00004490 ret = do_socketpair(arg1, arg2, arg3, arg4);
bellard3532fa72006-06-24 15:06:03 +00004491 break;
4492#endif
4493#ifdef TARGET_NR_setsockopt
4494 case TARGET_NR_setsockopt:
4495 ret = do_setsockopt(arg1, arg2, arg3, arg4, (socklen_t) arg5);
4496 break;
4497#endif
ths7494b0f2007-02-11 18:26:53 +00004498
bellard31e31b82003-02-18 22:55:36 +00004499 case TARGET_NR_syslog:
bellard579a97f2007-11-11 14:26:47 +00004500 if (!(p = lock_user_string(arg2)))
4501 goto efault;
thse5574482007-02-11 20:03:13 +00004502 ret = get_errno(sys_syslog((int)arg1, p, (int)arg3));
4503 unlock_user(p, arg2, 0);
ths7494b0f2007-02-11 18:26:53 +00004504 break;
4505
bellard31e31b82003-02-18 22:55:36 +00004506 case TARGET_NR_setitimer:
bellard66fb9762003-03-23 01:06:05 +00004507 {
bellard66fb9762003-03-23 01:06:05 +00004508 struct itimerval value, ovalue, *pvalue;
4509
pbrook53a59602006-03-25 19:31:22 +00004510 if (arg2) {
bellard66fb9762003-03-23 01:06:05 +00004511 pvalue = &value;
ths788f5ec2007-12-09 02:37:05 +00004512 if (copy_from_user_timeval(&pvalue->it_interval, arg2)
4513 || copy_from_user_timeval(&pvalue->it_value,
4514 arg2 + sizeof(struct target_timeval)))
4515 goto efault;
bellard66fb9762003-03-23 01:06:05 +00004516 } else {
4517 pvalue = NULL;
4518 }
4519 ret = get_errno(setitimer(arg1, pvalue, &ovalue));
pbrook53a59602006-03-25 19:31:22 +00004520 if (!is_error(ret) && arg3) {
ths788f5ec2007-12-09 02:37:05 +00004521 if (copy_to_user_timeval(arg3,
4522 &ovalue.it_interval)
4523 || copy_to_user_timeval(arg3 + sizeof(struct target_timeval),
4524 &ovalue.it_value))
4525 goto efault;
bellard66fb9762003-03-23 01:06:05 +00004526 }
4527 }
4528 break;
bellard31e31b82003-02-18 22:55:36 +00004529 case TARGET_NR_getitimer:
bellard66fb9762003-03-23 01:06:05 +00004530 {
bellard66fb9762003-03-23 01:06:05 +00004531 struct itimerval value;
ths3b46e622007-09-17 08:09:54 +00004532
bellard66fb9762003-03-23 01:06:05 +00004533 ret = get_errno(getitimer(arg1, &value));
pbrook53a59602006-03-25 19:31:22 +00004534 if (!is_error(ret) && arg2) {
ths788f5ec2007-12-09 02:37:05 +00004535 if (copy_to_user_timeval(arg2,
4536 &value.it_interval)
4537 || copy_to_user_timeval(arg2 + sizeof(struct target_timeval),
4538 &value.it_value))
4539 goto efault;
bellard66fb9762003-03-23 01:06:05 +00004540 }
4541 }
4542 break;
bellard31e31b82003-02-18 22:55:36 +00004543 case TARGET_NR_stat:
bellard579a97f2007-11-11 14:26:47 +00004544 if (!(p = lock_user_string(arg1)))
4545 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004546 ret = get_errno(stat(path(p), &st));
4547 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004548 goto do_stat;
4549 case TARGET_NR_lstat:
bellard579a97f2007-11-11 14:26:47 +00004550 if (!(p = lock_user_string(arg1)))
4551 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004552 ret = get_errno(lstat(path(p), &st));
4553 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004554 goto do_stat;
4555 case TARGET_NR_fstat:
4556 {
4557 ret = get_errno(fstat(arg1, &st));
4558 do_stat:
4559 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00004560 struct target_stat *target_st;
thse3584652007-06-01 11:49:38 +00004561
bellard579a97f2007-11-11 14:26:47 +00004562 if (!lock_user_struct(VERIFY_WRITE, target_st, arg2, 0))
4563 goto efault;
bellardd2fd1af2007-11-14 18:08:56 +00004564 __put_user(st.st_dev, &target_st->st_dev);
4565 __put_user(st.st_ino, &target_st->st_ino);
4566 __put_user(st.st_mode, &target_st->st_mode);
4567 __put_user(st.st_uid, &target_st->st_uid);
4568 __put_user(st.st_gid, &target_st->st_gid);
4569 __put_user(st.st_nlink, &target_st->st_nlink);
4570 __put_user(st.st_rdev, &target_st->st_rdev);
4571 __put_user(st.st_size, &target_st->st_size);
4572 __put_user(st.st_blksize, &target_st->st_blksize);
4573 __put_user(st.st_blocks, &target_st->st_blocks);
4574 __put_user(st.st_atime, &target_st->target_st_atime);
4575 __put_user(st.st_mtime, &target_st->target_st_mtime);
4576 __put_user(st.st_ctime, &target_st->target_st_ctime);
pbrook53a59602006-03-25 19:31:22 +00004577 unlock_user_struct(target_st, arg2, 1);
bellard31e31b82003-02-18 22:55:36 +00004578 }
4579 }
4580 break;
bellardebc05482003-09-30 21:08:41 +00004581#ifdef TARGET_NR_olduname
bellard31e31b82003-02-18 22:55:36 +00004582 case TARGET_NR_olduname:
4583 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004584#endif
4585#ifdef TARGET_NR_iopl
bellard31e31b82003-02-18 22:55:36 +00004586 case TARGET_NR_iopl:
4587 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004588#endif
bellard31e31b82003-02-18 22:55:36 +00004589 case TARGET_NR_vhangup:
4590 ret = get_errno(vhangup());
4591 break;
bellardebc05482003-09-30 21:08:41 +00004592#ifdef TARGET_NR_idle
bellard31e31b82003-02-18 22:55:36 +00004593 case TARGET_NR_idle:
4594 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004595#endif
bellard42ad6ae2005-01-03 22:48:11 +00004596#ifdef TARGET_NR_syscall
4597 case TARGET_NR_syscall:
4598 ret = do_syscall(cpu_env,arg1 & 0xffff,arg2,arg3,arg4,arg5,arg6,0);
4599 break;
4600#endif
bellard31e31b82003-02-18 22:55:36 +00004601 case TARGET_NR_wait4:
4602 {
4603 int status;
blueswir1992f48a2007-10-14 16:27:31 +00004604 abi_long status_ptr = arg2;
bellard31e31b82003-02-18 22:55:36 +00004605 struct rusage rusage, *rusage_ptr;
blueswir1992f48a2007-10-14 16:27:31 +00004606 abi_ulong target_rusage = arg4;
bellard31e31b82003-02-18 22:55:36 +00004607 if (target_rusage)
4608 rusage_ptr = &rusage;
4609 else
4610 rusage_ptr = NULL;
4611 ret = get_errno(wait4(arg1, &status, arg3, rusage_ptr));
4612 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +00004613 if (status_ptr) {
4614 if (put_user_s32(status, status_ptr))
4615 goto efault;
bellard31e31b82003-02-18 22:55:36 +00004616 }
bellard2f619692007-11-16 10:46:05 +00004617 if (target_rusage)
4618 host_to_target_rusage(target_rusage, &rusage);
bellard31e31b82003-02-18 22:55:36 +00004619 }
4620 }
4621 break;
thse5febef2007-04-01 18:31:35 +00004622#ifdef TARGET_NR_swapoff
bellard31e31b82003-02-18 22:55:36 +00004623 case TARGET_NR_swapoff:
bellard579a97f2007-11-11 14:26:47 +00004624 if (!(p = lock_user_string(arg1)))
4625 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004626 ret = get_errno(swapoff(p));
4627 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004628 break;
thse5febef2007-04-01 18:31:35 +00004629#endif
bellard31e31b82003-02-18 22:55:36 +00004630 case TARGET_NR_sysinfo:
bellarda5448a72004-06-19 16:59:03 +00004631 {
pbrook53a59602006-03-25 19:31:22 +00004632 struct target_sysinfo *target_value;
bellarda5448a72004-06-19 16:59:03 +00004633 struct sysinfo value;
4634 ret = get_errno(sysinfo(&value));
pbrook53a59602006-03-25 19:31:22 +00004635 if (!is_error(ret) && arg1)
bellarda5448a72004-06-19 16:59:03 +00004636 {
bellard579a97f2007-11-11 14:26:47 +00004637 if (!lock_user_struct(VERIFY_WRITE, target_value, arg1, 0))
4638 goto efault;
bellarda5448a72004-06-19 16:59:03 +00004639 __put_user(value.uptime, &target_value->uptime);
4640 __put_user(value.loads[0], &target_value->loads[0]);
4641 __put_user(value.loads[1], &target_value->loads[1]);
4642 __put_user(value.loads[2], &target_value->loads[2]);
4643 __put_user(value.totalram, &target_value->totalram);
4644 __put_user(value.freeram, &target_value->freeram);
4645 __put_user(value.sharedram, &target_value->sharedram);
4646 __put_user(value.bufferram, &target_value->bufferram);
4647 __put_user(value.totalswap, &target_value->totalswap);
4648 __put_user(value.freeswap, &target_value->freeswap);
4649 __put_user(value.procs, &target_value->procs);
4650 __put_user(value.totalhigh, &target_value->totalhigh);
4651 __put_user(value.freehigh, &target_value->freehigh);
4652 __put_user(value.mem_unit, &target_value->mem_unit);
pbrook53a59602006-03-25 19:31:22 +00004653 unlock_user_struct(target_value, arg1, 1);
bellarda5448a72004-06-19 16:59:03 +00004654 }
4655 }
4656 break;
thse5febef2007-04-01 18:31:35 +00004657#ifdef TARGET_NR_ipc
bellard31e31b82003-02-18 22:55:36 +00004658 case TARGET_NR_ipc:
bellard8853f862004-02-22 14:57:26 +00004659 ret = do_ipc(arg1, arg2, arg3, arg4, arg5, arg6);
4660 break;
thse5febef2007-04-01 18:31:35 +00004661#endif
bellard31e31b82003-02-18 22:55:36 +00004662 case TARGET_NR_fsync:
4663 ret = get_errno(fsync(arg1));
4664 break;
bellard31e31b82003-02-18 22:55:36 +00004665 case TARGET_NR_clone:
aurel320b6d3ae2008-09-15 07:43:43 +00004666#if defined(TARGET_SH4)
4667 ret = get_errno(do_fork(cpu_env, arg1, arg2, arg3, arg5, arg4));
4668#else
pbrookd865bab2008-06-07 22:12:17 +00004669 ret = get_errno(do_fork(cpu_env, arg1, arg2, arg3, arg4, arg5));
aurel320b6d3ae2008-09-15 07:43:43 +00004670#endif
bellard1b6b0292003-03-22 17:31:38 +00004671 break;
bellardec86b0f2003-04-11 00:15:04 +00004672#ifdef __NR_exit_group
4673 /* new thread calls */
4674 case TARGET_NR_exit_group:
bellarde9009672005-04-26 20:42:36 +00004675 gdb_exit(cpu_env, arg1);
bellardec86b0f2003-04-11 00:15:04 +00004676 ret = get_errno(exit_group(arg1));
4677 break;
4678#endif
bellard31e31b82003-02-18 22:55:36 +00004679 case TARGET_NR_setdomainname:
bellard579a97f2007-11-11 14:26:47 +00004680 if (!(p = lock_user_string(arg1)))
4681 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004682 ret = get_errno(setdomainname(p, arg2));
4683 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004684 break;
4685 case TARGET_NR_uname:
4686 /* no need to transcode because we use the linux syscall */
bellard29e619b2004-09-13 21:41:04 +00004687 {
4688 struct new_utsname * buf;
ths3b46e622007-09-17 08:09:54 +00004689
bellard579a97f2007-11-11 14:26:47 +00004690 if (!lock_user_struct(VERIFY_WRITE, buf, arg1, 0))
4691 goto efault;
bellard29e619b2004-09-13 21:41:04 +00004692 ret = get_errno(sys_uname(buf));
4693 if (!is_error(ret)) {
4694 /* Overrite the native machine name with whatever is being
4695 emulated. */
4696 strcpy (buf->machine, UNAME_MACHINE);
pbrookc5937222006-05-14 11:30:38 +00004697 /* Allow the user to override the reported release. */
4698 if (qemu_uname_release && *qemu_uname_release)
4699 strcpy (buf->release, qemu_uname_release);
bellard29e619b2004-09-13 21:41:04 +00004700 }
pbrook53a59602006-03-25 19:31:22 +00004701 unlock_user_struct(buf, arg1, 1);
bellard29e619b2004-09-13 21:41:04 +00004702 }
bellard31e31b82003-02-18 22:55:36 +00004703 break;
bellard6dbad632003-03-16 18:05:05 +00004704#ifdef TARGET_I386
bellard31e31b82003-02-18 22:55:36 +00004705 case TARGET_NR_modify_ldt:
bellard03acab62007-11-11 14:57:14 +00004706 ret = do_modify_ldt(cpu_env, arg1, arg2, arg3);
bellard5cd43932003-03-29 16:54:36 +00004707 break;
j_mayer84409dd2007-04-06 08:56:50 +00004708#if !defined(TARGET_X86_64)
bellard5cd43932003-03-29 16:54:36 +00004709 case TARGET_NR_vm86old:
4710 goto unimplemented;
4711 case TARGET_NR_vm86:
pbrook53a59602006-03-25 19:31:22 +00004712 ret = do_vm86(cpu_env, arg1, arg2);
bellard6dbad632003-03-16 18:05:05 +00004713 break;
4714#endif
j_mayer84409dd2007-04-06 08:56:50 +00004715#endif
bellard31e31b82003-02-18 22:55:36 +00004716 case TARGET_NR_adjtimex:
4717 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00004718#ifdef TARGET_NR_create_module
bellard31e31b82003-02-18 22:55:36 +00004719 case TARGET_NR_create_module:
thse5febef2007-04-01 18:31:35 +00004720#endif
bellard31e31b82003-02-18 22:55:36 +00004721 case TARGET_NR_init_module:
4722 case TARGET_NR_delete_module:
thse5febef2007-04-01 18:31:35 +00004723#ifdef TARGET_NR_get_kernel_syms
bellard31e31b82003-02-18 22:55:36 +00004724 case TARGET_NR_get_kernel_syms:
thse5febef2007-04-01 18:31:35 +00004725#endif
bellard31e31b82003-02-18 22:55:36 +00004726 goto unimplemented;
4727 case TARGET_NR_quotactl:
4728 goto unimplemented;
4729 case TARGET_NR_getpgid:
4730 ret = get_errno(getpgid(arg1));
4731 break;
4732 case TARGET_NR_fchdir:
4733 ret = get_errno(fchdir(arg1));
4734 break;
j_mayer84409dd2007-04-06 08:56:50 +00004735#ifdef TARGET_NR_bdflush /* not on x86_64 */
bellard31e31b82003-02-18 22:55:36 +00004736 case TARGET_NR_bdflush:
4737 goto unimplemented;
j_mayer84409dd2007-04-06 08:56:50 +00004738#endif
thse5febef2007-04-01 18:31:35 +00004739#ifdef TARGET_NR_sysfs
bellard31e31b82003-02-18 22:55:36 +00004740 case TARGET_NR_sysfs:
4741 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00004742#endif
bellard31e31b82003-02-18 22:55:36 +00004743 case TARGET_NR_personality:
bellard1b6b0292003-03-22 17:31:38 +00004744 ret = get_errno(personality(arg1));
bellard31e31b82003-02-18 22:55:36 +00004745 break;
thse5febef2007-04-01 18:31:35 +00004746#ifdef TARGET_NR_afs_syscall
bellard31e31b82003-02-18 22:55:36 +00004747 case TARGET_NR_afs_syscall:
4748 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00004749#endif
j_mayer7a3148a2007-04-05 07:13:51 +00004750#ifdef TARGET_NR__llseek /* Not on alpha */
bellard31e31b82003-02-18 22:55:36 +00004751 case TARGET_NR__llseek:
4752 {
bellard4f2ac232004-04-26 19:44:02 +00004753#if defined (__x86_64__)
4754 ret = get_errno(lseek(arg1, ((uint64_t )arg2 << 32) | arg3, arg5));
bellard2f619692007-11-16 10:46:05 +00004755 if (put_user_s64(ret, arg4))
4756 goto efault;
bellard4f2ac232004-04-26 19:44:02 +00004757#else
bellard31e31b82003-02-18 22:55:36 +00004758 int64_t res;
4759 ret = get_errno(_llseek(arg1, arg2, arg3, &res, arg5));
bellard2f619692007-11-16 10:46:05 +00004760 if (put_user_s64(res, arg4))
4761 goto efault;
bellard4f2ac232004-04-26 19:44:02 +00004762#endif
bellard31e31b82003-02-18 22:55:36 +00004763 }
4764 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004765#endif
bellard31e31b82003-02-18 22:55:36 +00004766 case TARGET_NR_getdents:
blueswir1992f48a2007-10-14 16:27:31 +00004767#if TARGET_ABI_BITS != 32
pbrook53a59602006-03-25 19:31:22 +00004768 goto unimplemented;
blueswir1992f48a2007-10-14 16:27:31 +00004769#elif TARGET_ABI_BITS == 32 && HOST_LONG_BITS == 64
bellard4add45b2003-06-05 01:52:59 +00004770 {
pbrook53a59602006-03-25 19:31:22 +00004771 struct target_dirent *target_dirp;
bellard4add45b2003-06-05 01:52:59 +00004772 struct dirent *dirp;
blueswir1992f48a2007-10-14 16:27:31 +00004773 abi_long count = arg3;
bellard4add45b2003-06-05 01:52:59 +00004774
4775 dirp = malloc(count);
ths0da46a62007-10-20 20:23:07 +00004776 if (!dirp) {
bellard579a97f2007-11-11 14:26:47 +00004777 ret = -TARGET_ENOMEM;
ths0da46a62007-10-20 20:23:07 +00004778 goto fail;
4779 }
ths3b46e622007-09-17 08:09:54 +00004780
bellard4add45b2003-06-05 01:52:59 +00004781 ret = get_errno(sys_getdents(arg1, dirp, count));
4782 if (!is_error(ret)) {
4783 struct dirent *de;
4784 struct target_dirent *tde;
4785 int len = ret;
4786 int reclen, treclen;
4787 int count1, tnamelen;
4788
4789 count1 = 0;
4790 de = dirp;
bellard579a97f2007-11-11 14:26:47 +00004791 if (!(target_dirp = lock_user(VERIFY_WRITE, arg2, count, 0)))
4792 goto efault;
bellard4add45b2003-06-05 01:52:59 +00004793 tde = target_dirp;
4794 while (len > 0) {
4795 reclen = de->d_reclen;
blueswir1992f48a2007-10-14 16:27:31 +00004796 treclen = reclen - (2 * (sizeof(long) - sizeof(abi_long)));
bellard4add45b2003-06-05 01:52:59 +00004797 tde->d_reclen = tswap16(treclen);
4798 tde->d_ino = tswapl(de->d_ino);
4799 tde->d_off = tswapl(de->d_off);
blueswir1992f48a2007-10-14 16:27:31 +00004800 tnamelen = treclen - (2 * sizeof(abi_long) + 2);
bellard4add45b2003-06-05 01:52:59 +00004801 if (tnamelen > 256)
4802 tnamelen = 256;
bellard80a9d032005-01-03 23:31:27 +00004803 /* XXX: may not be correct */
bellard4add45b2003-06-05 01:52:59 +00004804 strncpy(tde->d_name, de->d_name, tnamelen);
4805 de = (struct dirent *)((char *)de + reclen);
4806 len -= reclen;
j_mayer1c5bf3b2007-04-14 12:17:59 +00004807 tde = (struct target_dirent *)((char *)tde + treclen);
bellard4add45b2003-06-05 01:52:59 +00004808 count1 += treclen;
4809 }
4810 ret = count1;
bellard579a97f2007-11-11 14:26:47 +00004811 unlock_user(target_dirp, arg2, ret);
bellard4add45b2003-06-05 01:52:59 +00004812 }
4813 free(dirp);
4814 }
4815#else
bellard31e31b82003-02-18 22:55:36 +00004816 {
pbrook53a59602006-03-25 19:31:22 +00004817 struct dirent *dirp;
blueswir1992f48a2007-10-14 16:27:31 +00004818 abi_long count = arg3;
bellarddab2ed92003-03-22 15:23:14 +00004819
bellard579a97f2007-11-11 14:26:47 +00004820 if (!(dirp = lock_user(VERIFY_WRITE, arg2, count, 0)))
4821 goto efault;
bellard72f03902003-02-18 23:33:18 +00004822 ret = get_errno(sys_getdents(arg1, dirp, count));
bellard31e31b82003-02-18 22:55:36 +00004823 if (!is_error(ret)) {
4824 struct dirent *de;
4825 int len = ret;
4826 int reclen;
4827 de = dirp;
4828 while (len > 0) {
bellard8083a3e2003-03-24 23:12:16 +00004829 reclen = de->d_reclen;
bellard31e31b82003-02-18 22:55:36 +00004830 if (reclen > len)
4831 break;
bellard8083a3e2003-03-24 23:12:16 +00004832 de->d_reclen = tswap16(reclen);
bellard31e31b82003-02-18 22:55:36 +00004833 tswapls(&de->d_ino);
4834 tswapls(&de->d_off);
4835 de = (struct dirent *)((char *)de + reclen);
4836 len -= reclen;
4837 }
4838 }
pbrook53a59602006-03-25 19:31:22 +00004839 unlock_user(dirp, arg2, ret);
bellard31e31b82003-02-18 22:55:36 +00004840 }
bellard4add45b2003-06-05 01:52:59 +00004841#endif
bellard31e31b82003-02-18 22:55:36 +00004842 break;
ths3ae43202007-09-16 21:39:48 +00004843#if defined(TARGET_NR_getdents64) && defined(__NR_getdents64)
bellarddab2ed92003-03-22 15:23:14 +00004844 case TARGET_NR_getdents64:
4845 {
pbrook53a59602006-03-25 19:31:22 +00004846 struct dirent64 *dirp;
blueswir1992f48a2007-10-14 16:27:31 +00004847 abi_long count = arg3;
bellard579a97f2007-11-11 14:26:47 +00004848 if (!(dirp = lock_user(VERIFY_WRITE, arg2, count, 0)))
4849 goto efault;
bellarddab2ed92003-03-22 15:23:14 +00004850 ret = get_errno(sys_getdents64(arg1, dirp, count));
4851 if (!is_error(ret)) {
4852 struct dirent64 *de;
4853 int len = ret;
4854 int reclen;
4855 de = dirp;
4856 while (len > 0) {
bellard8083a3e2003-03-24 23:12:16 +00004857 reclen = de->d_reclen;
bellarddab2ed92003-03-22 15:23:14 +00004858 if (reclen > len)
4859 break;
bellard8083a3e2003-03-24 23:12:16 +00004860 de->d_reclen = tswap16(reclen);
bellard8582a532007-11-11 23:11:36 +00004861 tswap64s((uint64_t *)&de->d_ino);
4862 tswap64s((uint64_t *)&de->d_off);
bellarddab2ed92003-03-22 15:23:14 +00004863 de = (struct dirent64 *)((char *)de + reclen);
4864 len -= reclen;
4865 }
4866 }
pbrook53a59602006-03-25 19:31:22 +00004867 unlock_user(dirp, arg2, ret);
bellarddab2ed92003-03-22 15:23:14 +00004868 }
4869 break;
bellarda541f292004-04-12 20:39:29 +00004870#endif /* TARGET_NR_getdents64 */
thse5febef2007-04-01 18:31:35 +00004871#ifdef TARGET_NR__newselect
bellard31e31b82003-02-18 22:55:36 +00004872 case TARGET_NR__newselect:
pbrook53a59602006-03-25 19:31:22 +00004873 ret = do_select(arg1, arg2, arg3, arg4, arg5);
bellard31e31b82003-02-18 22:55:36 +00004874 break;
thse5febef2007-04-01 18:31:35 +00004875#endif
4876#ifdef TARGET_NR_poll
bellard9de5e442003-03-23 16:49:39 +00004877 case TARGET_NR_poll:
4878 {
pbrook53a59602006-03-25 19:31:22 +00004879 struct target_pollfd *target_pfd;
bellard9de5e442003-03-23 16:49:39 +00004880 unsigned int nfds = arg2;
4881 int timeout = arg3;
4882 struct pollfd *pfd;
bellard7854b052003-03-29 17:22:23 +00004883 unsigned int i;
bellard9de5e442003-03-23 16:49:39 +00004884
bellard579a97f2007-11-11 14:26:47 +00004885 target_pfd = lock_user(VERIFY_WRITE, arg1, sizeof(struct target_pollfd) * nfds, 1);
4886 if (!target_pfd)
4887 goto efault;
bellard9de5e442003-03-23 16:49:39 +00004888 pfd = alloca(sizeof(struct pollfd) * nfds);
4889 for(i = 0; i < nfds; i++) {
bellard5cd43932003-03-29 16:54:36 +00004890 pfd[i].fd = tswap32(target_pfd[i].fd);
4891 pfd[i].events = tswap16(target_pfd[i].events);
bellard9de5e442003-03-23 16:49:39 +00004892 }
4893 ret = get_errno(poll(pfd, nfds, timeout));
4894 if (!is_error(ret)) {
4895 for(i = 0; i < nfds; i++) {
bellard5cd43932003-03-29 16:54:36 +00004896 target_pfd[i].revents = tswap16(pfd[i].revents);
bellard9de5e442003-03-23 16:49:39 +00004897 }
pbrook53a59602006-03-25 19:31:22 +00004898 ret += nfds * (sizeof(struct target_pollfd)
4899 - sizeof(struct pollfd));
bellard9de5e442003-03-23 16:49:39 +00004900 }
pbrook53a59602006-03-25 19:31:22 +00004901 unlock_user(target_pfd, arg1, ret);
bellard9de5e442003-03-23 16:49:39 +00004902 }
4903 break;
thse5febef2007-04-01 18:31:35 +00004904#endif
bellard31e31b82003-02-18 22:55:36 +00004905 case TARGET_NR_flock:
bellard9de5e442003-03-23 16:49:39 +00004906 /* NOTE: the flock constant seems to be the same for every
4907 Linux platform */
4908 ret = get_errno(flock(arg1, arg2));
bellard31e31b82003-02-18 22:55:36 +00004909 break;
4910 case TARGET_NR_readv:
4911 {
4912 int count = arg3;
bellard31e31b82003-02-18 22:55:36 +00004913 struct iovec *vec;
bellard31e31b82003-02-18 22:55:36 +00004914
4915 vec = alloca(count * sizeof(struct iovec));
bellard41df8412008-02-04 22:26:57 +00004916 if (lock_iovec(VERIFY_WRITE, vec, arg2, count, 0) < 0)
4917 goto efault;
bellard31e31b82003-02-18 22:55:36 +00004918 ret = get_errno(readv(arg1, vec, count));
pbrook53a59602006-03-25 19:31:22 +00004919 unlock_iovec(vec, arg2, count, 1);
bellard31e31b82003-02-18 22:55:36 +00004920 }
4921 break;
4922 case TARGET_NR_writev:
4923 {
4924 int count = arg3;
bellard31e31b82003-02-18 22:55:36 +00004925 struct iovec *vec;
bellard31e31b82003-02-18 22:55:36 +00004926
4927 vec = alloca(count * sizeof(struct iovec));
bellard41df8412008-02-04 22:26:57 +00004928 if (lock_iovec(VERIFY_READ, vec, arg2, count, 1) < 0)
4929 goto efault;
bellard31e31b82003-02-18 22:55:36 +00004930 ret = get_errno(writev(arg1, vec, count));
pbrook53a59602006-03-25 19:31:22 +00004931 unlock_iovec(vec, arg2, count, 0);
bellard31e31b82003-02-18 22:55:36 +00004932 }
4933 break;
4934 case TARGET_NR_getsid:
4935 ret = get_errno(getsid(arg1));
4936 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004937#if defined(TARGET_NR_fdatasync) /* Not on alpha (osf_datasync ?) */
bellard31e31b82003-02-18 22:55:36 +00004938 case TARGET_NR_fdatasync:
bellard5cd43932003-03-29 16:54:36 +00004939 ret = get_errno(fdatasync(arg1));
4940 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004941#endif
bellard31e31b82003-02-18 22:55:36 +00004942 case TARGET_NR__sysctl:
ths0da46a62007-10-20 20:23:07 +00004943 /* We don't implement this, but ENOTDIR is always a safe
bellard29e619b2004-09-13 21:41:04 +00004944 return value. */
ths0da46a62007-10-20 20:23:07 +00004945 ret = -TARGET_ENOTDIR;
4946 break;
bellard31e31b82003-02-18 22:55:36 +00004947 case TARGET_NR_sched_setparam:
bellard5cd43932003-03-29 16:54:36 +00004948 {
pbrook53a59602006-03-25 19:31:22 +00004949 struct sched_param *target_schp;
bellard5cd43932003-03-29 16:54:36 +00004950 struct sched_param schp;
pbrook53a59602006-03-25 19:31:22 +00004951
bellard579a97f2007-11-11 14:26:47 +00004952 if (!lock_user_struct(VERIFY_READ, target_schp, arg2, 1))
4953 goto efault;
bellard5cd43932003-03-29 16:54:36 +00004954 schp.sched_priority = tswap32(target_schp->sched_priority);
pbrook53a59602006-03-25 19:31:22 +00004955 unlock_user_struct(target_schp, arg2, 0);
bellard5cd43932003-03-29 16:54:36 +00004956 ret = get_errno(sched_setparam(arg1, &schp));
4957 }
4958 break;
bellard31e31b82003-02-18 22:55:36 +00004959 case TARGET_NR_sched_getparam:
bellard5cd43932003-03-29 16:54:36 +00004960 {
pbrook53a59602006-03-25 19:31:22 +00004961 struct sched_param *target_schp;
bellard5cd43932003-03-29 16:54:36 +00004962 struct sched_param schp;
4963 ret = get_errno(sched_getparam(arg1, &schp));
4964 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00004965 if (!lock_user_struct(VERIFY_WRITE, target_schp, arg2, 0))
4966 goto efault;
bellard5cd43932003-03-29 16:54:36 +00004967 target_schp->sched_priority = tswap32(schp.sched_priority);
pbrook53a59602006-03-25 19:31:22 +00004968 unlock_user_struct(target_schp, arg2, 1);
bellard5cd43932003-03-29 16:54:36 +00004969 }
4970 }
4971 break;
bellard31e31b82003-02-18 22:55:36 +00004972 case TARGET_NR_sched_setscheduler:
bellard5cd43932003-03-29 16:54:36 +00004973 {
pbrook53a59602006-03-25 19:31:22 +00004974 struct sched_param *target_schp;
bellard5cd43932003-03-29 16:54:36 +00004975 struct sched_param schp;
bellard579a97f2007-11-11 14:26:47 +00004976 if (!lock_user_struct(VERIFY_READ, target_schp, arg3, 1))
4977 goto efault;
bellard5cd43932003-03-29 16:54:36 +00004978 schp.sched_priority = tswap32(target_schp->sched_priority);
pbrook53a59602006-03-25 19:31:22 +00004979 unlock_user_struct(target_schp, arg3, 0);
bellard5cd43932003-03-29 16:54:36 +00004980 ret = get_errno(sched_setscheduler(arg1, arg2, &schp));
4981 }
4982 break;
bellard31e31b82003-02-18 22:55:36 +00004983 case TARGET_NR_sched_getscheduler:
bellard5cd43932003-03-29 16:54:36 +00004984 ret = get_errno(sched_getscheduler(arg1));
4985 break;
bellard31e31b82003-02-18 22:55:36 +00004986 case TARGET_NR_sched_yield:
4987 ret = get_errno(sched_yield());
4988 break;
4989 case TARGET_NR_sched_get_priority_max:
bellard5cd43932003-03-29 16:54:36 +00004990 ret = get_errno(sched_get_priority_max(arg1));
4991 break;
bellard31e31b82003-02-18 22:55:36 +00004992 case TARGET_NR_sched_get_priority_min:
bellard5cd43932003-03-29 16:54:36 +00004993 ret = get_errno(sched_get_priority_min(arg1));
4994 break;
bellard31e31b82003-02-18 22:55:36 +00004995 case TARGET_NR_sched_rr_get_interval:
bellard5cd43932003-03-29 16:54:36 +00004996 {
bellard5cd43932003-03-29 16:54:36 +00004997 struct timespec ts;
4998 ret = get_errno(sched_rr_get_interval(arg1, &ts));
4999 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00005000 host_to_target_timespec(arg2, &ts);
bellard5cd43932003-03-29 16:54:36 +00005001 }
5002 }
5003 break;
bellard31e31b82003-02-18 22:55:36 +00005004 case TARGET_NR_nanosleep:
bellard1b6b0292003-03-22 17:31:38 +00005005 {
bellard1b6b0292003-03-22 17:31:38 +00005006 struct timespec req, rem;
pbrook53a59602006-03-25 19:31:22 +00005007 target_to_host_timespec(&req, arg1);
bellard1b6b0292003-03-22 17:31:38 +00005008 ret = get_errno(nanosleep(&req, &rem));
pbrook53a59602006-03-25 19:31:22 +00005009 if (is_error(ret) && arg2) {
5010 host_to_target_timespec(arg2, &rem);
bellard1b6b0292003-03-22 17:31:38 +00005011 }
5012 }
5013 break;
thse5febef2007-04-01 18:31:35 +00005014#ifdef TARGET_NR_query_module
bellard31e31b82003-02-18 22:55:36 +00005015 case TARGET_NR_query_module:
bellard5cd43932003-03-29 16:54:36 +00005016 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00005017#endif
5018#ifdef TARGET_NR_nfsservctl
bellard31e31b82003-02-18 22:55:36 +00005019 case TARGET_NR_nfsservctl:
bellard5cd43932003-03-29 16:54:36 +00005020 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00005021#endif
bellard31e31b82003-02-18 22:55:36 +00005022 case TARGET_NR_prctl:
thse5574482007-02-11 20:03:13 +00005023 switch (arg1)
5024 {
5025 case PR_GET_PDEATHSIG:
5026 {
5027 int deathsig;
5028 ret = get_errno(prctl(arg1, &deathsig, arg3, arg4, arg5));
bellard2f619692007-11-16 10:46:05 +00005029 if (!is_error(ret) && arg2
5030 && put_user_ual(deathsig, arg2))
5031 goto efault;
thse5574482007-02-11 20:03:13 +00005032 }
5033 break;
5034 default:
5035 ret = get_errno(prctl(arg1, arg2, arg3, arg4, arg5));
5036 break;
5037 }
ths39b9aae2007-02-11 18:36:44 +00005038 break;
bellardd2fd1af2007-11-14 18:08:56 +00005039#ifdef TARGET_NR_arch_prctl
5040 case TARGET_NR_arch_prctl:
5041#if defined(TARGET_I386) && !defined(TARGET_ABI32)
5042 ret = do_arch_prctl(cpu_env, arg1, arg2);
5043 break;
5044#else
5045 goto unimplemented;
5046#endif
5047#endif
bellard67867302003-11-23 17:05:30 +00005048#ifdef TARGET_NR_pread
bellard31e31b82003-02-18 22:55:36 +00005049 case TARGET_NR_pread:
bellard579a97f2007-11-11 14:26:47 +00005050 if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
5051 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005052 ret = get_errno(pread(arg1, p, arg3, arg4));
5053 unlock_user(p, arg2, ret);
bellard206f0fa2003-05-14 19:01:56 +00005054 break;
bellard31e31b82003-02-18 22:55:36 +00005055 case TARGET_NR_pwrite:
bellard579a97f2007-11-11 14:26:47 +00005056 if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
5057 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005058 ret = get_errno(pwrite(arg1, p, arg3, arg4));
5059 unlock_user(p, arg2, 0);
bellard206f0fa2003-05-14 19:01:56 +00005060 break;
bellard67867302003-11-23 17:05:30 +00005061#endif
aurel32f2c7ba12008-03-28 22:32:06 +00005062#ifdef TARGET_NR_pread64
5063 case TARGET_NR_pread64:
5064 if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
5065 goto efault;
5066 ret = get_errno(pread64(arg1, p, arg3, target_offset64(arg4, arg5)));
5067 unlock_user(p, arg2, ret);
5068 break;
5069 case TARGET_NR_pwrite64:
5070 if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
5071 goto efault;
5072 ret = get_errno(pwrite64(arg1, p, arg3, target_offset64(arg4, arg5)));
5073 unlock_user(p, arg2, 0);
5074 break;
5075#endif
bellard31e31b82003-02-18 22:55:36 +00005076 case TARGET_NR_getcwd:
bellard579a97f2007-11-11 14:26:47 +00005077 if (!(p = lock_user(VERIFY_WRITE, arg1, arg2, 0)))
5078 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005079 ret = get_errno(sys_getcwd1(p, arg2));
5080 unlock_user(p, arg1, ret);
bellard31e31b82003-02-18 22:55:36 +00005081 break;
5082 case TARGET_NR_capget:
bellard5cd43932003-03-29 16:54:36 +00005083 goto unimplemented;
bellard31e31b82003-02-18 22:55:36 +00005084 case TARGET_NR_capset:
bellard5cd43932003-03-29 16:54:36 +00005085 goto unimplemented;
bellard31e31b82003-02-18 22:55:36 +00005086 case TARGET_NR_sigaltstack:
ths198a74d2007-09-27 16:44:32 +00005087#if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_MIPS) || \
5088 defined(TARGET_SPARC) || defined(TARGET_PPC) || defined(TARGET_ALPHA)
bellard579a97f2007-11-11 14:26:47 +00005089 ret = do_sigaltstack(arg1, arg2, get_sp_from_cpustate((CPUState *)cpu_env));
thsa04e1342007-09-27 13:57:58 +00005090 break;
5091#else
bellard5cd43932003-03-29 16:54:36 +00005092 goto unimplemented;
thsa04e1342007-09-27 13:57:58 +00005093#endif
bellard31e31b82003-02-18 22:55:36 +00005094 case TARGET_NR_sendfile:
bellard5cd43932003-03-29 16:54:36 +00005095 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00005096#ifdef TARGET_NR_getpmsg
bellard31e31b82003-02-18 22:55:36 +00005097 case TARGET_NR_getpmsg:
bellard5cd43932003-03-29 16:54:36 +00005098 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00005099#endif
5100#ifdef TARGET_NR_putpmsg
bellard31e31b82003-02-18 22:55:36 +00005101 case TARGET_NR_putpmsg:
bellard5cd43932003-03-29 16:54:36 +00005102 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00005103#endif
bellard048f6b42005-11-26 18:47:20 +00005104#ifdef TARGET_NR_vfork
bellard31e31b82003-02-18 22:55:36 +00005105 case TARGET_NR_vfork:
pbrookd865bab2008-06-07 22:12:17 +00005106 ret = get_errno(do_fork(cpu_env, CLONE_VFORK | CLONE_VM | SIGCHLD,
5107 0, 0, 0, 0));
bellard31e31b82003-02-18 22:55:36 +00005108 break;
bellard048f6b42005-11-26 18:47:20 +00005109#endif
bellardebc05482003-09-30 21:08:41 +00005110#ifdef TARGET_NR_ugetrlimit
bellard31e31b82003-02-18 22:55:36 +00005111 case TARGET_NR_ugetrlimit:
bellard728584b2003-04-29 20:43:36 +00005112 {
5113 struct rlimit rlim;
5114 ret = get_errno(getrlimit(arg1, &rlim));
5115 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00005116 struct target_rlimit *target_rlim;
bellard579a97f2007-11-11 14:26:47 +00005117 if (!lock_user_struct(VERIFY_WRITE, target_rlim, arg2, 0))
5118 goto efault;
bellard728584b2003-04-29 20:43:36 +00005119 target_rlim->rlim_cur = tswapl(rlim.rlim_cur);
5120 target_rlim->rlim_max = tswapl(rlim.rlim_max);
pbrook53a59602006-03-25 19:31:22 +00005121 unlock_user_struct(target_rlim, arg2, 1);
bellard728584b2003-04-29 20:43:36 +00005122 }
5123 break;
5124 }
bellardebc05482003-09-30 21:08:41 +00005125#endif
bellarda315a142005-01-30 22:59:18 +00005126#ifdef TARGET_NR_truncate64
bellard31e31b82003-02-18 22:55:36 +00005127 case TARGET_NR_truncate64:
bellard579a97f2007-11-11 14:26:47 +00005128 if (!(p = lock_user_string(arg1)))
5129 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005130 ret = target_truncate64(cpu_env, p, arg2, arg3, arg4);
5131 unlock_user(p, arg1, 0);
bellard667f38b2005-07-23 14:46:27 +00005132 break;
bellarda315a142005-01-30 22:59:18 +00005133#endif
5134#ifdef TARGET_NR_ftruncate64
bellard31e31b82003-02-18 22:55:36 +00005135 case TARGET_NR_ftruncate64:
pbrookce4defa2006-02-09 16:49:55 +00005136 ret = target_ftruncate64(cpu_env, arg1, arg2, arg3, arg4);
bellard667f38b2005-07-23 14:46:27 +00005137 break;
bellarda315a142005-01-30 22:59:18 +00005138#endif
5139#ifdef TARGET_NR_stat64
bellard31e31b82003-02-18 22:55:36 +00005140 case TARGET_NR_stat64:
bellard579a97f2007-11-11 14:26:47 +00005141 if (!(p = lock_user_string(arg1)))
5142 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005143 ret = get_errno(stat(path(p), &st));
5144 unlock_user(p, arg1, 0);
bellard60cd49d2003-03-16 22:53:56 +00005145 goto do_stat64;
bellarda315a142005-01-30 22:59:18 +00005146#endif
5147#ifdef TARGET_NR_lstat64
bellard31e31b82003-02-18 22:55:36 +00005148 case TARGET_NR_lstat64:
bellard579a97f2007-11-11 14:26:47 +00005149 if (!(p = lock_user_string(arg1)))
5150 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005151 ret = get_errno(lstat(path(p), &st));
5152 unlock_user(p, arg1, 0);
bellard60cd49d2003-03-16 22:53:56 +00005153 goto do_stat64;
bellarda315a142005-01-30 22:59:18 +00005154#endif
5155#ifdef TARGET_NR_fstat64
bellard31e31b82003-02-18 22:55:36 +00005156 case TARGET_NR_fstat64:
bellard60cd49d2003-03-16 22:53:56 +00005157 {
5158 ret = get_errno(fstat(arg1, &st));
5159 do_stat64:
5160 if (!is_error(ret)) {
pbrookce4defa2006-02-09 16:49:55 +00005161#ifdef TARGET_ARM
5162 if (((CPUARMState *)cpu_env)->eabi) {
pbrook53a59602006-03-25 19:31:22 +00005163 struct target_eabi_stat64 *target_st;
bellard579a97f2007-11-11 14:26:47 +00005164
5165 if (!lock_user_struct(VERIFY_WRITE, target_st, arg2, 0))
5166 goto efault;
pbrookce4defa2006-02-09 16:49:55 +00005167 memset(target_st, 0, sizeof(struct target_eabi_stat64));
bellard579a97f2007-11-11 14:26:47 +00005168 __put_user(st.st_dev, &target_st->st_dev);
5169 __put_user(st.st_ino, &target_st->st_ino);
bellardec86b0f2003-04-11 00:15:04 +00005170#ifdef TARGET_STAT64_HAS_BROKEN_ST_INO
bellard579a97f2007-11-11 14:26:47 +00005171 __put_user(st.st_ino, &target_st->__st_ino);
bellardec86b0f2003-04-11 00:15:04 +00005172#endif
bellard579a97f2007-11-11 14:26:47 +00005173 __put_user(st.st_mode, &target_st->st_mode);
5174 __put_user(st.st_nlink, &target_st->st_nlink);
5175 __put_user(st.st_uid, &target_st->st_uid);
5176 __put_user(st.st_gid, &target_st->st_gid);
5177 __put_user(st.st_rdev, &target_st->st_rdev);
5178 __put_user(st.st_size, &target_st->st_size);
5179 __put_user(st.st_blksize, &target_st->st_blksize);
5180 __put_user(st.st_blocks, &target_st->st_blocks);
5181 __put_user(st.st_atime, &target_st->target_st_atime);
5182 __put_user(st.st_mtime, &target_st->target_st_mtime);
5183 __put_user(st.st_ctime, &target_st->target_st_ctime);
5184 unlock_user_struct(target_st, arg2, 1);
pbrookce4defa2006-02-09 16:49:55 +00005185 } else
5186#endif
5187 {
pbrook53a59602006-03-25 19:31:22 +00005188 struct target_stat64 *target_st;
bellard579a97f2007-11-11 14:26:47 +00005189
5190 if (!lock_user_struct(VERIFY_WRITE, target_st, arg2, 0))
5191 goto efault;
pbrookce4defa2006-02-09 16:49:55 +00005192 memset(target_st, 0, sizeof(struct target_stat64));
bellard579a97f2007-11-11 14:26:47 +00005193 __put_user(st.st_dev, &target_st->st_dev);
5194 __put_user(st.st_ino, &target_st->st_ino);
pbrookce4defa2006-02-09 16:49:55 +00005195#ifdef TARGET_STAT64_HAS_BROKEN_ST_INO
bellard579a97f2007-11-11 14:26:47 +00005196 __put_user(st.st_ino, &target_st->__st_ino);
pbrookce4defa2006-02-09 16:49:55 +00005197#endif
bellard579a97f2007-11-11 14:26:47 +00005198 __put_user(st.st_mode, &target_st->st_mode);
5199 __put_user(st.st_nlink, &target_st->st_nlink);
5200 __put_user(st.st_uid, &target_st->st_uid);
5201 __put_user(st.st_gid, &target_st->st_gid);
5202 __put_user(st.st_rdev, &target_st->st_rdev);
pbrookce4defa2006-02-09 16:49:55 +00005203 /* XXX: better use of kernel struct */
bellard579a97f2007-11-11 14:26:47 +00005204 __put_user(st.st_size, &target_st->st_size);
5205 __put_user(st.st_blksize, &target_st->st_blksize);
5206 __put_user(st.st_blocks, &target_st->st_blocks);
5207 __put_user(st.st_atime, &target_st->target_st_atime);
5208 __put_user(st.st_mtime, &target_st->target_st_mtime);
5209 __put_user(st.st_ctime, &target_st->target_st_ctime);
5210 unlock_user_struct(target_st, arg2, 1);
pbrookce4defa2006-02-09 16:49:55 +00005211 }
bellard60cd49d2003-03-16 22:53:56 +00005212 }
5213 }
5214 break;
bellarda315a142005-01-30 22:59:18 +00005215#endif
bellard67867302003-11-23 17:05:30 +00005216#ifdef USE_UID16
5217 case TARGET_NR_lchown:
bellard579a97f2007-11-11 14:26:47 +00005218 if (!(p = lock_user_string(arg1)))
5219 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005220 ret = get_errno(lchown(p, low2highuid(arg2), low2highgid(arg3)));
5221 unlock_user(p, arg1, 0);
bellard67867302003-11-23 17:05:30 +00005222 break;
5223 case TARGET_NR_getuid:
5224 ret = get_errno(high2lowuid(getuid()));
5225 break;
5226 case TARGET_NR_getgid:
5227 ret = get_errno(high2lowgid(getgid()));
5228 break;
5229 case TARGET_NR_geteuid:
5230 ret = get_errno(high2lowuid(geteuid()));
5231 break;
5232 case TARGET_NR_getegid:
5233 ret = get_errno(high2lowgid(getegid()));
5234 break;
5235 case TARGET_NR_setreuid:
5236 ret = get_errno(setreuid(low2highuid(arg1), low2highuid(arg2)));
5237 break;
5238 case TARGET_NR_setregid:
5239 ret = get_errno(setregid(low2highgid(arg1), low2highgid(arg2)));
5240 break;
5241 case TARGET_NR_getgroups:
5242 {
5243 int gidsetsize = arg1;
pbrook53a59602006-03-25 19:31:22 +00005244 uint16_t *target_grouplist;
bellard67867302003-11-23 17:05:30 +00005245 gid_t *grouplist;
5246 int i;
5247
5248 grouplist = alloca(gidsetsize * sizeof(gid_t));
5249 ret = get_errno(getgroups(gidsetsize, grouplist));
balrogcb3bc232008-09-20 02:08:13 +00005250 if (gidsetsize == 0)
5251 break;
bellard67867302003-11-23 17:05:30 +00005252 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00005253 target_grouplist = lock_user(VERIFY_WRITE, arg2, gidsetsize * 2, 0);
5254 if (!target_grouplist)
5255 goto efault;
bellard67867302003-11-23 17:05:30 +00005256 for(i = 0;i < gidsetsize; i++)
5257 target_grouplist[i] = tswap16(grouplist[i]);
pbrook53a59602006-03-25 19:31:22 +00005258 unlock_user(target_grouplist, arg2, gidsetsize * 2);
bellard67867302003-11-23 17:05:30 +00005259 }
5260 }
5261 break;
5262 case TARGET_NR_setgroups:
5263 {
5264 int gidsetsize = arg1;
pbrook53a59602006-03-25 19:31:22 +00005265 uint16_t *target_grouplist;
bellard67867302003-11-23 17:05:30 +00005266 gid_t *grouplist;
5267 int i;
5268
5269 grouplist = alloca(gidsetsize * sizeof(gid_t));
bellard579a97f2007-11-11 14:26:47 +00005270 target_grouplist = lock_user(VERIFY_READ, arg2, gidsetsize * 2, 1);
5271 if (!target_grouplist) {
5272 ret = -TARGET_EFAULT;
5273 goto fail;
5274 }
bellard67867302003-11-23 17:05:30 +00005275 for(i = 0;i < gidsetsize; i++)
5276 grouplist[i] = tswap16(target_grouplist[i]);
pbrook53a59602006-03-25 19:31:22 +00005277 unlock_user(target_grouplist, arg2, 0);
bellard67867302003-11-23 17:05:30 +00005278 ret = get_errno(setgroups(gidsetsize, grouplist));
5279 }
5280 break;
5281 case TARGET_NR_fchown:
5282 ret = get_errno(fchown(arg1, low2highuid(arg2), low2highgid(arg3)));
5283 break;
thsccfa72b2007-09-24 09:23:34 +00005284#if defined(TARGET_NR_fchownat) && defined(__NR_fchownat)
5285 case TARGET_NR_fchownat:
bellard579a97f2007-11-11 14:26:47 +00005286 if (!(p = lock_user_string(arg2)))
5287 goto efault;
5288 ret = get_errno(sys_fchownat(arg1, p, low2highuid(arg3), low2highgid(arg4), arg5));
5289 unlock_user(p, arg2, 0);
thsccfa72b2007-09-24 09:23:34 +00005290 break;
5291#endif
bellard67867302003-11-23 17:05:30 +00005292#ifdef TARGET_NR_setresuid
5293 case TARGET_NR_setresuid:
ths5fafdf22007-09-16 21:08:06 +00005294 ret = get_errno(setresuid(low2highuid(arg1),
5295 low2highuid(arg2),
bellard67867302003-11-23 17:05:30 +00005296 low2highuid(arg3)));
5297 break;
5298#endif
5299#ifdef TARGET_NR_getresuid
5300 case TARGET_NR_getresuid:
5301 {
pbrook53a59602006-03-25 19:31:22 +00005302 uid_t ruid, euid, suid;
bellard67867302003-11-23 17:05:30 +00005303 ret = get_errno(getresuid(&ruid, &euid, &suid));
5304 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +00005305 if (put_user_u16(high2lowuid(ruid), arg1)
5306 || put_user_u16(high2lowuid(euid), arg2)
5307 || put_user_u16(high2lowuid(suid), arg3))
5308 goto efault;
bellard67867302003-11-23 17:05:30 +00005309 }
5310 }
5311 break;
5312#endif
5313#ifdef TARGET_NR_getresgid
5314 case TARGET_NR_setresgid:
ths5fafdf22007-09-16 21:08:06 +00005315 ret = get_errno(setresgid(low2highgid(arg1),
5316 low2highgid(arg2),
bellard67867302003-11-23 17:05:30 +00005317 low2highgid(arg3)));
5318 break;
5319#endif
5320#ifdef TARGET_NR_getresgid
5321 case TARGET_NR_getresgid:
5322 {
pbrook53a59602006-03-25 19:31:22 +00005323 gid_t rgid, egid, sgid;
bellard67867302003-11-23 17:05:30 +00005324 ret = get_errno(getresgid(&rgid, &egid, &sgid));
5325 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +00005326 if (put_user_u16(high2lowgid(rgid), arg1)
5327 || put_user_u16(high2lowgid(egid), arg2)
5328 || put_user_u16(high2lowgid(sgid), arg3))
5329 goto efault;
bellard67867302003-11-23 17:05:30 +00005330 }
5331 }
5332 break;
5333#endif
5334 case TARGET_NR_chown:
bellard579a97f2007-11-11 14:26:47 +00005335 if (!(p = lock_user_string(arg1)))
5336 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005337 ret = get_errno(chown(p, low2highuid(arg2), low2highgid(arg3)));
5338 unlock_user(p, arg1, 0);
bellard67867302003-11-23 17:05:30 +00005339 break;
5340 case TARGET_NR_setuid:
5341 ret = get_errno(setuid(low2highuid(arg1)));
5342 break;
5343 case TARGET_NR_setgid:
5344 ret = get_errno(setgid(low2highgid(arg1)));
5345 break;
5346 case TARGET_NR_setfsuid:
5347 ret = get_errno(setfsuid(arg1));
5348 break;
5349 case TARGET_NR_setfsgid:
5350 ret = get_errno(setfsgid(arg1));
5351 break;
5352#endif /* USE_UID16 */
5353
bellarda315a142005-01-30 22:59:18 +00005354#ifdef TARGET_NR_lchown32
bellard31e31b82003-02-18 22:55:36 +00005355 case TARGET_NR_lchown32:
bellard579a97f2007-11-11 14:26:47 +00005356 if (!(p = lock_user_string(arg1)))
5357 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005358 ret = get_errno(lchown(p, arg2, arg3));
5359 unlock_user(p, arg1, 0);
bellardb03c60f2003-03-23 17:19:56 +00005360 break;
bellarda315a142005-01-30 22:59:18 +00005361#endif
5362#ifdef TARGET_NR_getuid32
bellard31e31b82003-02-18 22:55:36 +00005363 case TARGET_NR_getuid32:
bellardb03c60f2003-03-23 17:19:56 +00005364 ret = get_errno(getuid());
5365 break;
bellarda315a142005-01-30 22:59:18 +00005366#endif
5367#ifdef TARGET_NR_getgid32
bellard31e31b82003-02-18 22:55:36 +00005368 case TARGET_NR_getgid32:
bellardb03c60f2003-03-23 17:19:56 +00005369 ret = get_errno(getgid());
5370 break;
bellarda315a142005-01-30 22:59:18 +00005371#endif
5372#ifdef TARGET_NR_geteuid32
bellard31e31b82003-02-18 22:55:36 +00005373 case TARGET_NR_geteuid32:
bellardb03c60f2003-03-23 17:19:56 +00005374 ret = get_errno(geteuid());
5375 break;
bellarda315a142005-01-30 22:59:18 +00005376#endif
5377#ifdef TARGET_NR_getegid32
bellard31e31b82003-02-18 22:55:36 +00005378 case TARGET_NR_getegid32:
bellardb03c60f2003-03-23 17:19:56 +00005379 ret = get_errno(getegid());
5380 break;
bellarda315a142005-01-30 22:59:18 +00005381#endif
5382#ifdef TARGET_NR_setreuid32
bellard31e31b82003-02-18 22:55:36 +00005383 case TARGET_NR_setreuid32:
bellardb03c60f2003-03-23 17:19:56 +00005384 ret = get_errno(setreuid(arg1, arg2));
5385 break;
bellarda315a142005-01-30 22:59:18 +00005386#endif
5387#ifdef TARGET_NR_setregid32
bellard31e31b82003-02-18 22:55:36 +00005388 case TARGET_NR_setregid32:
bellardb03c60f2003-03-23 17:19:56 +00005389 ret = get_errno(setregid(arg1, arg2));
5390 break;
bellarda315a142005-01-30 22:59:18 +00005391#endif
5392#ifdef TARGET_NR_getgroups32
bellard31e31b82003-02-18 22:55:36 +00005393 case TARGET_NR_getgroups32:
bellard99c475a2005-01-31 20:45:13 +00005394 {
5395 int gidsetsize = arg1;
pbrook53a59602006-03-25 19:31:22 +00005396 uint32_t *target_grouplist;
bellard99c475a2005-01-31 20:45:13 +00005397 gid_t *grouplist;
5398 int i;
5399
5400 grouplist = alloca(gidsetsize * sizeof(gid_t));
5401 ret = get_errno(getgroups(gidsetsize, grouplist));
balrogcb3bc232008-09-20 02:08:13 +00005402 if (gidsetsize == 0)
5403 break;
bellard99c475a2005-01-31 20:45:13 +00005404 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00005405 target_grouplist = lock_user(VERIFY_WRITE, arg2, gidsetsize * 4, 0);
5406 if (!target_grouplist) {
5407 ret = -TARGET_EFAULT;
5408 goto fail;
5409 }
bellard99c475a2005-01-31 20:45:13 +00005410 for(i = 0;i < gidsetsize; i++)
pbrook53a59602006-03-25 19:31:22 +00005411 target_grouplist[i] = tswap32(grouplist[i]);
5412 unlock_user(target_grouplist, arg2, gidsetsize * 4);
bellard99c475a2005-01-31 20:45:13 +00005413 }
5414 }
5415 break;
bellarda315a142005-01-30 22:59:18 +00005416#endif
5417#ifdef TARGET_NR_setgroups32
bellard31e31b82003-02-18 22:55:36 +00005418 case TARGET_NR_setgroups32:
bellard99c475a2005-01-31 20:45:13 +00005419 {
5420 int gidsetsize = arg1;
pbrook53a59602006-03-25 19:31:22 +00005421 uint32_t *target_grouplist;
bellard99c475a2005-01-31 20:45:13 +00005422 gid_t *grouplist;
5423 int i;
ths3b46e622007-09-17 08:09:54 +00005424
bellard99c475a2005-01-31 20:45:13 +00005425 grouplist = alloca(gidsetsize * sizeof(gid_t));
bellard579a97f2007-11-11 14:26:47 +00005426 target_grouplist = lock_user(VERIFY_READ, arg2, gidsetsize * 4, 1);
5427 if (!target_grouplist) {
5428 ret = -TARGET_EFAULT;
5429 goto fail;
5430 }
bellard99c475a2005-01-31 20:45:13 +00005431 for(i = 0;i < gidsetsize; i++)
pbrook53a59602006-03-25 19:31:22 +00005432 grouplist[i] = tswap32(target_grouplist[i]);
5433 unlock_user(target_grouplist, arg2, 0);
bellard99c475a2005-01-31 20:45:13 +00005434 ret = get_errno(setgroups(gidsetsize, grouplist));
5435 }
5436 break;
bellarda315a142005-01-30 22:59:18 +00005437#endif
5438#ifdef TARGET_NR_fchown32
bellard31e31b82003-02-18 22:55:36 +00005439 case TARGET_NR_fchown32:
bellardb03c60f2003-03-23 17:19:56 +00005440 ret = get_errno(fchown(arg1, arg2, arg3));
5441 break;
bellarda315a142005-01-30 22:59:18 +00005442#endif
5443#ifdef TARGET_NR_setresuid32
bellard31e31b82003-02-18 22:55:36 +00005444 case TARGET_NR_setresuid32:
bellardb03c60f2003-03-23 17:19:56 +00005445 ret = get_errno(setresuid(arg1, arg2, arg3));
5446 break;
bellarda315a142005-01-30 22:59:18 +00005447#endif
5448#ifdef TARGET_NR_getresuid32
bellard31e31b82003-02-18 22:55:36 +00005449 case TARGET_NR_getresuid32:
bellardb03c60f2003-03-23 17:19:56 +00005450 {
pbrook53a59602006-03-25 19:31:22 +00005451 uid_t ruid, euid, suid;
bellardb03c60f2003-03-23 17:19:56 +00005452 ret = get_errno(getresuid(&ruid, &euid, &suid));
5453 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +00005454 if (put_user_u32(ruid, arg1)
5455 || put_user_u32(euid, arg2)
5456 || put_user_u32(suid, arg3))
5457 goto efault;
bellardb03c60f2003-03-23 17:19:56 +00005458 }
5459 }
5460 break;
bellarda315a142005-01-30 22:59:18 +00005461#endif
5462#ifdef TARGET_NR_setresgid32
bellard31e31b82003-02-18 22:55:36 +00005463 case TARGET_NR_setresgid32:
bellardb03c60f2003-03-23 17:19:56 +00005464 ret = get_errno(setresgid(arg1, arg2, arg3));
5465 break;
bellarda315a142005-01-30 22:59:18 +00005466#endif
5467#ifdef TARGET_NR_getresgid32
bellard31e31b82003-02-18 22:55:36 +00005468 case TARGET_NR_getresgid32:
bellardb03c60f2003-03-23 17:19:56 +00005469 {
pbrook53a59602006-03-25 19:31:22 +00005470 gid_t rgid, egid, sgid;
bellardb03c60f2003-03-23 17:19:56 +00005471 ret = get_errno(getresgid(&rgid, &egid, &sgid));
5472 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +00005473 if (put_user_u32(rgid, arg1)
5474 || put_user_u32(egid, arg2)
5475 || put_user_u32(sgid, arg3))
5476 goto efault;
bellardb03c60f2003-03-23 17:19:56 +00005477 }
5478 }
5479 break;
bellarda315a142005-01-30 22:59:18 +00005480#endif
5481#ifdef TARGET_NR_chown32
bellard31e31b82003-02-18 22:55:36 +00005482 case TARGET_NR_chown32:
bellard579a97f2007-11-11 14:26:47 +00005483 if (!(p = lock_user_string(arg1)))
5484 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005485 ret = get_errno(chown(p, arg2, arg3));
5486 unlock_user(p, arg1, 0);
bellardb03c60f2003-03-23 17:19:56 +00005487 break;
bellarda315a142005-01-30 22:59:18 +00005488#endif
5489#ifdef TARGET_NR_setuid32
bellard31e31b82003-02-18 22:55:36 +00005490 case TARGET_NR_setuid32:
bellardb03c60f2003-03-23 17:19:56 +00005491 ret = get_errno(setuid(arg1));
5492 break;
bellarda315a142005-01-30 22:59:18 +00005493#endif
5494#ifdef TARGET_NR_setgid32
bellard31e31b82003-02-18 22:55:36 +00005495 case TARGET_NR_setgid32:
bellardb03c60f2003-03-23 17:19:56 +00005496 ret = get_errno(setgid(arg1));
5497 break;
bellarda315a142005-01-30 22:59:18 +00005498#endif
5499#ifdef TARGET_NR_setfsuid32
bellard31e31b82003-02-18 22:55:36 +00005500 case TARGET_NR_setfsuid32:
bellardb03c60f2003-03-23 17:19:56 +00005501 ret = get_errno(setfsuid(arg1));
5502 break;
bellarda315a142005-01-30 22:59:18 +00005503#endif
5504#ifdef TARGET_NR_setfsgid32
bellard31e31b82003-02-18 22:55:36 +00005505 case TARGET_NR_setfsgid32:
bellardb03c60f2003-03-23 17:19:56 +00005506 ret = get_errno(setfsgid(arg1));
5507 break;
bellarda315a142005-01-30 22:59:18 +00005508#endif
bellard67867302003-11-23 17:05:30 +00005509
bellard31e31b82003-02-18 22:55:36 +00005510 case TARGET_NR_pivot_root:
bellardb03c60f2003-03-23 17:19:56 +00005511 goto unimplemented;
bellardffa65c32004-01-04 23:57:22 +00005512#ifdef TARGET_NR_mincore
bellard31e31b82003-02-18 22:55:36 +00005513 case TARGET_NR_mincore:
bellardb03c60f2003-03-23 17:19:56 +00005514 goto unimplemented;
bellardffa65c32004-01-04 23:57:22 +00005515#endif
5516#ifdef TARGET_NR_madvise
bellard31e31b82003-02-18 22:55:36 +00005517 case TARGET_NR_madvise:
pbrook24836682006-04-16 14:14:53 +00005518 /* A straight passthrough may not be safe because qemu sometimes
5519 turns private flie-backed mappings into anonymous mappings.
5520 This will break MADV_DONTNEED.
5521 This is a hint, so ignoring and returning success is ok. */
5522 ret = get_errno(0);
5523 break;
bellardffa65c32004-01-04 23:57:22 +00005524#endif
blueswir1992f48a2007-10-14 16:27:31 +00005525#if TARGET_ABI_BITS == 32
bellard31e31b82003-02-18 22:55:36 +00005526 case TARGET_NR_fcntl64:
bellard77e46722003-04-29 20:39:06 +00005527 {
thsb1e341e2007-03-20 21:50:52 +00005528 int cmd;
bellard77e46722003-04-29 20:39:06 +00005529 struct flock64 fl;
pbrook53a59602006-03-25 19:31:22 +00005530 struct target_flock64 *target_fl;
pbrookce4defa2006-02-09 16:49:55 +00005531#ifdef TARGET_ARM
pbrook53a59602006-03-25 19:31:22 +00005532 struct target_eabi_flock64 *target_efl;
pbrookce4defa2006-02-09 16:49:55 +00005533#endif
bellard77e46722003-04-29 20:39:06 +00005534
thsb1e341e2007-03-20 21:50:52 +00005535 switch(arg2){
5536 case TARGET_F_GETLK64:
5537 cmd = F_GETLK64;
thsa7222582007-03-22 15:08:55 +00005538 break;
thsb1e341e2007-03-20 21:50:52 +00005539 case TARGET_F_SETLK64:
5540 cmd = F_SETLK64;
thsa7222582007-03-22 15:08:55 +00005541 break;
thsb1e341e2007-03-20 21:50:52 +00005542 case TARGET_F_SETLKW64:
5543 cmd = F_SETLK64;
thsa7222582007-03-22 15:08:55 +00005544 break;
thsb1e341e2007-03-20 21:50:52 +00005545 default:
5546 cmd = arg2;
thsa7222582007-03-22 15:08:55 +00005547 break;
thsb1e341e2007-03-20 21:50:52 +00005548 }
5549
bellard60cd49d2003-03-16 22:53:56 +00005550 switch(arg2) {
thsb1e341e2007-03-20 21:50:52 +00005551 case TARGET_F_GETLK64:
ths58134272007-03-31 18:59:32 +00005552#ifdef TARGET_ARM
5553 if (((CPUARMState *)cpu_env)->eabi) {
bellard9ee1fa22007-11-11 15:11:19 +00005554 if (!lock_user_struct(VERIFY_READ, target_efl, arg3, 1))
5555 goto efault;
ths58134272007-03-31 18:59:32 +00005556 fl.l_type = tswap16(target_efl->l_type);
5557 fl.l_whence = tswap16(target_efl->l_whence);
5558 fl.l_start = tswap64(target_efl->l_start);
5559 fl.l_len = tswap64(target_efl->l_len);
5560 fl.l_pid = tswapl(target_efl->l_pid);
5561 unlock_user_struct(target_efl, arg3, 0);
5562 } else
5563#endif
5564 {
bellard9ee1fa22007-11-11 15:11:19 +00005565 if (!lock_user_struct(VERIFY_READ, target_fl, arg3, 1))
5566 goto efault;
ths58134272007-03-31 18:59:32 +00005567 fl.l_type = tswap16(target_fl->l_type);
5568 fl.l_whence = tswap16(target_fl->l_whence);
5569 fl.l_start = tswap64(target_fl->l_start);
5570 fl.l_len = tswap64(target_fl->l_len);
5571 fl.l_pid = tswapl(target_fl->l_pid);
5572 unlock_user_struct(target_fl, arg3, 0);
5573 }
thsb1e341e2007-03-20 21:50:52 +00005574 ret = get_errno(fcntl(arg1, cmd, &fl));
bellard77e46722003-04-29 20:39:06 +00005575 if (ret == 0) {
pbrookce4defa2006-02-09 16:49:55 +00005576#ifdef TARGET_ARM
5577 if (((CPUARMState *)cpu_env)->eabi) {
bellard9ee1fa22007-11-11 15:11:19 +00005578 if (!lock_user_struct(VERIFY_WRITE, target_efl, arg3, 0))
5579 goto efault;
pbrookce4defa2006-02-09 16:49:55 +00005580 target_efl->l_type = tswap16(fl.l_type);
5581 target_efl->l_whence = tswap16(fl.l_whence);
5582 target_efl->l_start = tswap64(fl.l_start);
5583 target_efl->l_len = tswap64(fl.l_len);
5584 target_efl->l_pid = tswapl(fl.l_pid);
pbrook53a59602006-03-25 19:31:22 +00005585 unlock_user_struct(target_efl, arg3, 1);
pbrookce4defa2006-02-09 16:49:55 +00005586 } else
5587#endif
5588 {
bellard9ee1fa22007-11-11 15:11:19 +00005589 if (!lock_user_struct(VERIFY_WRITE, target_fl, arg3, 0))
5590 goto efault;
pbrookce4defa2006-02-09 16:49:55 +00005591 target_fl->l_type = tswap16(fl.l_type);
5592 target_fl->l_whence = tswap16(fl.l_whence);
5593 target_fl->l_start = tswap64(fl.l_start);
5594 target_fl->l_len = tswap64(fl.l_len);
5595 target_fl->l_pid = tswapl(fl.l_pid);
pbrook53a59602006-03-25 19:31:22 +00005596 unlock_user_struct(target_fl, arg3, 1);
pbrookce4defa2006-02-09 16:49:55 +00005597 }
bellard77e46722003-04-29 20:39:06 +00005598 }
5599 break;
5600
thsb1e341e2007-03-20 21:50:52 +00005601 case TARGET_F_SETLK64:
5602 case TARGET_F_SETLKW64:
pbrookce4defa2006-02-09 16:49:55 +00005603#ifdef TARGET_ARM
5604 if (((CPUARMState *)cpu_env)->eabi) {
bellard9ee1fa22007-11-11 15:11:19 +00005605 if (!lock_user_struct(VERIFY_READ, target_efl, arg3, 1))
5606 goto efault;
pbrookce4defa2006-02-09 16:49:55 +00005607 fl.l_type = tswap16(target_efl->l_type);
5608 fl.l_whence = tswap16(target_efl->l_whence);
5609 fl.l_start = tswap64(target_efl->l_start);
5610 fl.l_len = tswap64(target_efl->l_len);
5611 fl.l_pid = tswapl(target_efl->l_pid);
pbrook53a59602006-03-25 19:31:22 +00005612 unlock_user_struct(target_efl, arg3, 0);
pbrookce4defa2006-02-09 16:49:55 +00005613 } else
5614#endif
5615 {
bellard9ee1fa22007-11-11 15:11:19 +00005616 if (!lock_user_struct(VERIFY_READ, target_fl, arg3, 1))
5617 goto efault;
pbrookce4defa2006-02-09 16:49:55 +00005618 fl.l_type = tswap16(target_fl->l_type);
5619 fl.l_whence = tswap16(target_fl->l_whence);
5620 fl.l_start = tswap64(target_fl->l_start);
5621 fl.l_len = tswap64(target_fl->l_len);
5622 fl.l_pid = tswapl(target_fl->l_pid);
pbrook53a59602006-03-25 19:31:22 +00005623 unlock_user_struct(target_fl, arg3, 0);
pbrookce4defa2006-02-09 16:49:55 +00005624 }
thsb1e341e2007-03-20 21:50:52 +00005625 ret = get_errno(fcntl(arg1, cmd, &fl));
bellard77e46722003-04-29 20:39:06 +00005626 break;
bellard60cd49d2003-03-16 22:53:56 +00005627 default:
bellard9ee1fa22007-11-11 15:11:19 +00005628 ret = do_fcntl(arg1, cmd, arg3);
bellard60cd49d2003-03-16 22:53:56 +00005629 break;
5630 }
bellard77e46722003-04-29 20:39:06 +00005631 break;
5632 }
bellard60cd49d2003-03-16 22:53:56 +00005633#endif
ths7d600c82006-12-08 01:32:58 +00005634#ifdef TARGET_NR_cacheflush
5635 case TARGET_NR_cacheflush:
5636 /* self-modifying code is handled automatically, so nothing needed */
5637 ret = 0;
5638 break;
5639#endif
bellardebc05482003-09-30 21:08:41 +00005640#ifdef TARGET_NR_security
bellard31e31b82003-02-18 22:55:36 +00005641 case TARGET_NR_security:
5642 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00005643#endif
bellardc573ff62004-01-04 15:51:36 +00005644#ifdef TARGET_NR_getpagesize
5645 case TARGET_NR_getpagesize:
5646 ret = TARGET_PAGE_SIZE;
5647 break;
5648#endif
bellard31e31b82003-02-18 22:55:36 +00005649 case TARGET_NR_gettid:
5650 ret = get_errno(gettid());
5651 break;
thse5febef2007-04-01 18:31:35 +00005652#ifdef TARGET_NR_readahead
bellard31e31b82003-02-18 22:55:36 +00005653 case TARGET_NR_readahead:
bellard5cd43932003-03-29 16:54:36 +00005654 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00005655#endif
bellardebc05482003-09-30 21:08:41 +00005656#ifdef TARGET_NR_setxattr
bellard31e31b82003-02-18 22:55:36 +00005657 case TARGET_NR_setxattr:
5658 case TARGET_NR_lsetxattr:
5659 case TARGET_NR_fsetxattr:
5660 case TARGET_NR_getxattr:
5661 case TARGET_NR_lgetxattr:
5662 case TARGET_NR_fgetxattr:
5663 case TARGET_NR_listxattr:
5664 case TARGET_NR_llistxattr:
5665 case TARGET_NR_flistxattr:
5666 case TARGET_NR_removexattr:
5667 case TARGET_NR_lremovexattr:
5668 case TARGET_NR_fremovexattr:
bellard5cd43932003-03-29 16:54:36 +00005669 goto unimplemented_nowarn;
bellardebc05482003-09-30 21:08:41 +00005670#endif
5671#ifdef TARGET_NR_set_thread_area
bellard5cd43932003-03-29 16:54:36 +00005672 case TARGET_NR_set_thread_area:
bellard8d18e892007-11-14 15:18:40 +00005673#if defined(TARGET_MIPS)
ths6f5b89a2007-03-02 20:48:00 +00005674 ((CPUMIPSState *) cpu_env)->tls_value = arg1;
5675 ret = 0;
5676 break;
bellard8d18e892007-11-14 15:18:40 +00005677#elif defined(TARGET_I386) && defined(TARGET_ABI32)
5678 ret = do_set_thread_area(cpu_env, arg1);
5679 break;
ths6f5b89a2007-03-02 20:48:00 +00005680#else
5681 goto unimplemented_nowarn;
5682#endif
5683#endif
5684#ifdef TARGET_NR_get_thread_area
bellard5cd43932003-03-29 16:54:36 +00005685 case TARGET_NR_get_thread_area:
bellard8d18e892007-11-14 15:18:40 +00005686#if defined(TARGET_I386) && defined(TARGET_ABI32)
5687 ret = do_get_thread_area(cpu_env, arg1);
5688#else
bellard5cd43932003-03-29 16:54:36 +00005689 goto unimplemented_nowarn;
bellardebc05482003-09-30 21:08:41 +00005690#endif
bellard8d18e892007-11-14 15:18:40 +00005691#endif
bellard48dc41e2006-06-21 18:15:50 +00005692#ifdef TARGET_NR_getdomainname
5693 case TARGET_NR_getdomainname:
5694 goto unimplemented_nowarn;
5695#endif
ths6f5b89a2007-03-02 20:48:00 +00005696
thsb5906f92007-03-19 13:32:45 +00005697#ifdef TARGET_NR_clock_gettime
5698 case TARGET_NR_clock_gettime:
5699 {
5700 struct timespec ts;
5701 ret = get_errno(clock_gettime(arg1, &ts));
5702 if (!is_error(ret)) {
5703 host_to_target_timespec(arg2, &ts);
5704 }
5705 break;
5706 }
5707#endif
5708#ifdef TARGET_NR_clock_getres
5709 case TARGET_NR_clock_getres:
5710 {
5711 struct timespec ts;
5712 ret = get_errno(clock_getres(arg1, &ts));
5713 if (!is_error(ret)) {
5714 host_to_target_timespec(arg2, &ts);
5715 }
5716 break;
5717 }
5718#endif
pbrook63d76512008-05-29 13:43:29 +00005719#ifdef TARGET_NR_clock_nanosleep
5720 case TARGET_NR_clock_nanosleep:
5721 {
5722 struct timespec ts;
5723 target_to_host_timespec(&ts, arg3);
5724 ret = get_errno(clock_nanosleep(arg1, arg2, &ts, arg4 ? &ts : NULL));
5725 if (arg4)
5726 host_to_target_timespec(arg4, &ts);
5727 break;
5728 }
5729#endif
thsb5906f92007-03-19 13:32:45 +00005730
ths6f5b89a2007-03-02 20:48:00 +00005731#if defined(TARGET_NR_set_tid_address) && defined(__NR_set_tid_address)
5732 case TARGET_NR_set_tid_address:
bellard579a97f2007-11-11 14:26:47 +00005733 ret = get_errno(set_tid_address((int *)g2h(arg1)));
5734 break;
ths6f5b89a2007-03-02 20:48:00 +00005735#endif
5736
ths3ae43202007-09-16 21:39:48 +00005737#if defined(TARGET_NR_tkill) && defined(__NR_tkill)
ths4cae1d12007-07-12 11:06:53 +00005738 case TARGET_NR_tkill:
pbrook4cb05962008-05-30 18:05:19 +00005739 ret = get_errno(sys_tkill((int)arg1, target_to_host_signal(arg2)));
ths4cae1d12007-07-12 11:06:53 +00005740 break;
5741#endif
5742
ths3ae43202007-09-16 21:39:48 +00005743#if defined(TARGET_NR_tgkill) && defined(__NR_tgkill)
ths71455572007-06-21 21:45:30 +00005744 case TARGET_NR_tgkill:
pbrook4cb05962008-05-30 18:05:19 +00005745 ret = get_errno(sys_tgkill((int)arg1, (int)arg2,
5746 target_to_host_signal(arg3)));
ths71455572007-06-21 21:45:30 +00005747 break;
5748#endif
5749
ths4f2b1fe2007-06-21 21:57:12 +00005750#ifdef TARGET_NR_set_robust_list
5751 case TARGET_NR_set_robust_list:
5752 goto unimplemented_nowarn;
5753#endif
5754
ths9007f0e2007-09-25 17:50:37 +00005755#if defined(TARGET_NR_utimensat) && defined(__NR_utimensat)
5756 case TARGET_NR_utimensat:
5757 {
5758 struct timespec ts[2];
5759 target_to_host_timespec(ts, arg3);
5760 target_to_host_timespec(ts+1, arg3+sizeof(struct target_timespec));
5761 if (!arg2)
5762 ret = get_errno(sys_utimensat(arg1, NULL, ts, arg4));
5763 else {
bellard579a97f2007-11-11 14:26:47 +00005764 if (!(p = lock_user_string(arg2))) {
ths0da46a62007-10-20 20:23:07 +00005765 ret = -TARGET_EFAULT;
bellard579a97f2007-11-11 14:26:47 +00005766 goto fail;
5767 }
5768 ret = get_errno(sys_utimensat(arg1, path(p), ts, arg4));
5769 unlock_user(p, arg2, 0);
ths9007f0e2007-09-25 17:50:37 +00005770 }
5771 }
5772 break;
5773#endif
pbrookbd0c5662008-05-29 14:34:11 +00005774#if defined(USE_NPTL)
5775 case TARGET_NR_futex:
5776 ret = do_futex(arg1, arg2, arg3, arg4, arg5, arg6);
5777 break;
5778#endif
ths9007f0e2007-09-25 17:50:37 +00005779
bellard31e31b82003-02-18 22:55:36 +00005780 default:
5781 unimplemented:
bellard5cd43932003-03-29 16:54:36 +00005782 gemu_log("qemu: Unsupported syscall: %d\n", num);
ths4f2b1fe2007-06-21 21:57:12 +00005783#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 +00005784 unimplemented_nowarn:
bellard80a9d032005-01-03 23:31:27 +00005785#endif
ths0da46a62007-10-20 20:23:07 +00005786 ret = -TARGET_ENOSYS;
bellard31e31b82003-02-18 22:55:36 +00005787 break;
5788 }
bellard579a97f2007-11-11 14:26:47 +00005789fail:
bellardc573ff62004-01-04 15:51:36 +00005790#ifdef DEBUG
5791 gemu_log(" = %ld\n", ret);
5792#endif
thsb92c47c2007-11-01 00:07:38 +00005793 if(do_strace)
5794 print_syscall_ret(num, ret);
bellard31e31b82003-02-18 22:55:36 +00005795 return ret;
bellard579a97f2007-11-11 14:26:47 +00005796efault:
5797 ret = -TARGET_EFAULT;
5798 goto fail;
bellard31e31b82003-02-18 22:55:36 +00005799}