blob: 7548ea79592b53fe7f5826708d4ab45057d7246e [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>
bellard31e31b82003-02-18 22:55:36 +000030#include <sys/types.h>
thsd08d3bb2007-03-19 13:09:22 +000031#include <sys/ipc.h>
32#include <sys/msg.h>
bellard31e31b82003-02-18 22:55:36 +000033#include <sys/wait.h>
34#include <sys/time.h>
35#include <sys/stat.h>
36#include <sys/mount.h>
ths39b9aae2007-02-11 18:36:44 +000037#include <sys/prctl.h>
bellard31e31b82003-02-18 22:55:36 +000038#include <sys/resource.h>
39#include <sys/mman.h>
40#include <sys/swap.h>
41#include <signal.h>
42#include <sched.h>
43#include <sys/socket.h>
44#include <sys/uio.h>
bellard9de5e442003-03-23 16:49:39 +000045#include <sys/poll.h>
bellard32f36bc2003-03-30 21:29:48 +000046#include <sys/times.h>
bellard8853f862004-02-22 14:57:26 +000047#include <sys/shm.h>
thsfa294812007-02-02 22:05:00 +000048#include <sys/sem.h>
bellard56c8f682005-11-28 22:28:41 +000049#include <sys/statfs.h>
bellardebc05482003-09-30 21:08:41 +000050#include <utime.h>
bellarda5448a72004-06-19 16:59:03 +000051#include <sys/sysinfo.h>
bellard72f03902003-02-18 23:33:18 +000052//#include <sys/user.h>
bellard8853f862004-02-22 14:57:26 +000053#include <netinet/ip.h>
bellard7854b052003-03-29 17:22:23 +000054#include <netinet/tcp.h>
pbrookbd0c5662008-05-29 14:34:11 +000055#if defined(USE_NPTL)
56#include <sys/futex.h>
57#endif
bellard31e31b82003-02-18 22:55:36 +000058
59#define termios host_termios
60#define winsize host_winsize
61#define termio host_termio
bellard04369ff2003-03-20 22:33:23 +000062#define sgttyb host_sgttyb /* same as target */
63#define tchars host_tchars /* same as target */
64#define ltchars host_ltchars /* same as target */
bellard31e31b82003-02-18 22:55:36 +000065
66#include <linux/termios.h>
67#include <linux/unistd.h>
68#include <linux/utsname.h>
69#include <linux/cdrom.h>
70#include <linux/hdreg.h>
71#include <linux/soundcard.h>
bellarddab2ed92003-03-22 15:23:14 +000072#include <linux/dirent.h>
bellard19b84f32003-05-08 15:41:49 +000073#include <linux/kd.h>
pbrookd7e40362008-05-23 16:06:43 +000074#include "linux_loop.h"
bellard31e31b82003-02-18 22:55:36 +000075
bellard3ef693a2003-03-23 20:17:16 +000076#include "qemu.h"
bellard31e31b82003-02-18 22:55:36 +000077
bellard72f03902003-02-18 23:33:18 +000078//#define DEBUG
bellard31e31b82003-02-18 22:55:36 +000079
pbrooke6e59062006-10-22 00:18:54 +000080#if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_SPARC) \
ths48733d12007-10-08 13:36:46 +000081 || defined(TARGET_M68K) || defined(TARGET_SH4) || defined(TARGET_CRIS)
bellard67867302003-11-23 17:05:30 +000082/* 16 bit uid wrappers emulation */
83#define USE_UID16
84#endif
85
bellard1a9353d2003-03-16 20:28:50 +000086//#include <linux/msdos_fs.h>
87#define VFAT_IOCTL_READDIR_BOTH _IOR('r', 1, struct dirent [2])
88#define VFAT_IOCTL_READDIR_SHORT _IOR('r', 2, struct dirent [2])
89
bellard70a194b2003-08-11 22:20:16 +000090
bellard70a194b2003-08-11 22:20:16 +000091#undef _syscall0
92#undef _syscall1
93#undef _syscall2
94#undef _syscall3
95#undef _syscall4
96#undef _syscall5
bellard83fcb512006-06-14 13:37:16 +000097#undef _syscall6
bellard70a194b2003-08-11 22:20:16 +000098
bellard83fcb512006-06-14 13:37:16 +000099#define _syscall0(type,name) \
100type name (void) \
101{ \
102 return syscall(__NR_##name); \
bellard70a194b2003-08-11 22:20:16 +0000103}
104
bellard83fcb512006-06-14 13:37:16 +0000105#define _syscall1(type,name,type1,arg1) \
106type name (type1 arg1) \
107{ \
108 return syscall(__NR_##name, arg1); \
bellard70a194b2003-08-11 22:20:16 +0000109}
110
bellard83fcb512006-06-14 13:37:16 +0000111#define _syscall2(type,name,type1,arg1,type2,arg2) \
112type name (type1 arg1,type2 arg2) \
113{ \
114 return syscall(__NR_##name, arg1, arg2); \
bellard70a194b2003-08-11 22:20:16 +0000115}
116
bellard83fcb512006-06-14 13:37:16 +0000117#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \
118type name (type1 arg1,type2 arg2,type3 arg3) \
119{ \
120 return syscall(__NR_##name, arg1, arg2, arg3); \
bellard70a194b2003-08-11 22:20:16 +0000121}
122
bellard83fcb512006-06-14 13:37:16 +0000123#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \
124type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4) \
125{ \
126 return syscall(__NR_##name, arg1, arg2, arg3, arg4); \
bellard70a194b2003-08-11 22:20:16 +0000127}
128
bellard83fcb512006-06-14 13:37:16 +0000129#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
130 type5,arg5) \
131type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \
132{ \
133 return syscall(__NR_##name, arg1, arg2, arg3, arg4, arg5); \
bellard70a194b2003-08-11 22:20:16 +0000134}
bellard83fcb512006-06-14 13:37:16 +0000135
136
137#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
138 type5,arg5,type6,arg6) \
139type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5,type6 arg6) \
140{ \
141 return syscall(__NR_##name, arg1, arg2, arg3, arg4, arg5, arg6); \
142}
143
bellard70a194b2003-08-11 22:20:16 +0000144
bellard31e31b82003-02-18 22:55:36 +0000145#define __NR_sys_uname __NR_uname
ths92a34c12007-09-24 09:27:49 +0000146#define __NR_sys_faccessat __NR_faccessat
ths814d7972007-09-24 09:26:51 +0000147#define __NR_sys_fchmodat __NR_fchmodat
thsccfa72b2007-09-24 09:23:34 +0000148#define __NR_sys_fchownat __NR_fchownat
bellard72f03902003-02-18 23:33:18 +0000149#define __NR_sys_getcwd1 __NR_getcwd
bellard72f03902003-02-18 23:33:18 +0000150#define __NR_sys_getdents __NR_getdents
bellarddab2ed92003-03-22 15:23:14 +0000151#define __NR_sys_getdents64 __NR_getdents64
thsc6cda172007-10-09 03:42:34 +0000152#define __NR_sys_getpriority __NR_getpriority
ths64f0ce42007-09-24 09:25:06 +0000153#define __NR_sys_linkat __NR_linkat
ths4472ad02007-09-24 09:22:32 +0000154#define __NR_sys_mkdirat __NR_mkdirat
ths75ac37a2007-09-24 09:23:05 +0000155#define __NR_sys_mknodat __NR_mknodat
ths82424832007-09-24 09:21:55 +0000156#define __NR_sys_openat __NR_openat
ths5e0ccb12007-09-24 09:26:10 +0000157#define __NR_sys_readlinkat __NR_readlinkat
ths722183f2007-09-24 09:24:37 +0000158#define __NR_sys_renameat __NR_renameat
bellard66fb9762003-03-23 01:06:05 +0000159#define __NR_sys_rt_sigqueueinfo __NR_rt_sigqueueinfo
thsf0b62432007-09-24 09:25:40 +0000160#define __NR_sys_symlinkat __NR_symlinkat
ths7494b0f2007-02-11 18:26:53 +0000161#define __NR_sys_syslog __NR_syslog
ths71455572007-06-21 21:45:30 +0000162#define __NR_sys_tgkill __NR_tgkill
ths4cae1d12007-07-12 11:06:53 +0000163#define __NR_sys_tkill __NR_tkill
ths8170f562007-09-24 09:24:11 +0000164#define __NR_sys_unlinkat __NR_unlinkat
ths9007f0e2007-09-25 17:50:37 +0000165#define __NR_sys_utimensat __NR_utimensat
pbrookbd0c5662008-05-29 14:34:11 +0000166#define __NR_sys_futex __NR_futex
bellard31e31b82003-02-18 22:55:36 +0000167
bellardbc51c5c2004-03-17 23:46:04 +0000168#if defined(__alpha__) || defined (__ia64__) || defined(__x86_64__)
bellard9af9eaa2003-04-07 21:34:41 +0000169#define __NR__llseek __NR_lseek
170#endif
171
bellard72f03902003-02-18 23:33:18 +0000172#ifdef __NR_gettid
bellard31e31b82003-02-18 22:55:36 +0000173_syscall0(int, gettid)
bellard72f03902003-02-18 23:33:18 +0000174#else
ths0da46a62007-10-20 20:23:07 +0000175/* This is a replacement for the host gettid() and must return a host
176 errno. */
bellard72f03902003-02-18 23:33:18 +0000177static int gettid(void) {
178 return -ENOSYS;
179}
180#endif
bellard31e31b82003-02-18 22:55:36 +0000181_syscall1(int,sys_uname,struct new_utsname *,buf)
ths92a34c12007-09-24 09:27:49 +0000182#if defined(TARGET_NR_faccessat) && defined(__NR_faccessat)
183_syscall4(int,sys_faccessat,int,dirfd,const char *,pathname,int,mode,int,flags)
184#endif
ths814d7972007-09-24 09:26:51 +0000185#if defined(TARGET_NR_fchmodat) && defined(__NR_fchmodat)
186_syscall4(int,sys_fchmodat,int,dirfd,const char *,pathname,
187 mode_t,mode,int,flags)
188#endif
thsccfa72b2007-09-24 09:23:34 +0000189#if defined(TARGET_NR_fchownat) && defined(__NR_fchownat)
190_syscall5(int,sys_fchownat,int,dirfd,const char *,pathname,
191 uid_t,owner,gid_t,group,int,flags)
192#endif
bellard72f03902003-02-18 23:33:18 +0000193_syscall2(int,sys_getcwd1,char *,buf,size_t,size)
194_syscall3(int, sys_getdents, uint, fd, struct dirent *, dirp, uint, count);
ths3ae43202007-09-16 21:39:48 +0000195#if defined(TARGET_NR_getdents64) && defined(__NR_getdents64)
bellarddab2ed92003-03-22 15:23:14 +0000196_syscall3(int, sys_getdents64, uint, fd, struct dirent64 *, dirp, uint, count);
ths3ae43202007-09-16 21:39:48 +0000197#endif
thsc6cda172007-10-09 03:42:34 +0000198_syscall2(int, sys_getpriority, int, which, int, who);
bellard31e31b82003-02-18 22:55:36 +0000199_syscall5(int, _llseek, uint, fd, ulong, hi, ulong, lo,
200 loff_t *, res, uint, wh);
ths64f0ce42007-09-24 09:25:06 +0000201#if defined(TARGET_NR_linkat) && defined(__NR_linkat)
202_syscall5(int,sys_linkat,int,olddirfd,const char *,oldpath,
203 int,newdirfd,const char *,newpath,int,flags)
204#endif
ths4472ad02007-09-24 09:22:32 +0000205#if defined(TARGET_NR_mkdirat) && defined(__NR_mkdirat)
206_syscall3(int,sys_mkdirat,int,dirfd,const char *,pathname,mode_t,mode)
207#endif
ths75ac37a2007-09-24 09:23:05 +0000208#if defined(TARGET_NR_mknodat) && defined(__NR_mknodat)
209_syscall4(int,sys_mknodat,int,dirfd,const char *,pathname,
210 mode_t,mode,dev_t,dev)
211#endif
ths82424832007-09-24 09:21:55 +0000212#if defined(TARGET_NR_openat) && defined(__NR_openat)
213_syscall4(int,sys_openat,int,dirfd,const char *,pathname,int,flags,mode_t,mode)
214#endif
ths5e0ccb12007-09-24 09:26:10 +0000215#if defined(TARGET_NR_readlinkat) && defined(__NR_readlinkat)
216_syscall4(int,sys_readlinkat,int,dirfd,const char *,pathname,
217 char *,buf,size_t,bufsize)
218#endif
ths722183f2007-09-24 09:24:37 +0000219#if defined(TARGET_NR_renameat) && defined(__NR_renameat)
220_syscall4(int,sys_renameat,int,olddirfd,const char *,oldpath,
221 int,newdirfd,const char *,newpath)
222#endif
bellard66fb9762003-03-23 01:06:05 +0000223_syscall3(int,sys_rt_sigqueueinfo,int,pid,int,sig,siginfo_t *,uinfo)
thsb51eaa82007-09-25 16:09:22 +0000224#if defined(TARGET_NR_symlinkat) && defined(__NR_symlinkat)
thsf0b62432007-09-24 09:25:40 +0000225_syscall3(int,sys_symlinkat,const char *,oldpath,
226 int,newdirfd,const char *,newpath)
227#endif
ths7494b0f2007-02-11 18:26:53 +0000228_syscall3(int,sys_syslog,int,type,char*,bufp,int,len)
ths3ae43202007-09-16 21:39:48 +0000229#if defined(TARGET_NR_tgkill) && defined(__NR_tgkill)
ths71455572007-06-21 21:45:30 +0000230_syscall3(int,sys_tgkill,int,tgid,int,pid,int,sig)
ths4cae1d12007-07-12 11:06:53 +0000231#endif
ths3ae43202007-09-16 21:39:48 +0000232#if defined(TARGET_NR_tkill) && defined(__NR_tkill)
ths4cae1d12007-07-12 11:06:53 +0000233_syscall2(int,sys_tkill,int,tid,int,sig)
234#endif
bellardec86b0f2003-04-11 00:15:04 +0000235#ifdef __NR_exit_group
236_syscall1(int,exit_group,int,error_code)
237#endif
ths6f5b89a2007-03-02 20:48:00 +0000238#if defined(TARGET_NR_set_tid_address) && defined(__NR_set_tid_address)
239_syscall1(int,set_tid_address,int *,tidptr)
240#endif
ths8170f562007-09-24 09:24:11 +0000241#if defined(TARGET_NR_unlinkat) && defined(__NR_unlinkat)
242_syscall3(int,sys_unlinkat,int,dirfd,const char *,pathname,int,flags)
243#endif
ths9007f0e2007-09-25 17:50:37 +0000244#if defined(TARGET_NR_utimensat) && defined(__NR_utimensat)
245_syscall4(int,sys_utimensat,int,dirfd,const char *,pathname,
246 const struct timespec *,tsp,int,flags)
247#endif
pbrookbd0c5662008-05-29 14:34:11 +0000248#if defined(TARGET_NR_futex) && defined(__NR_futex)
249_syscall6(int,sys_futex,int *,uaddr,int,op,int,val,
250 const struct timespec *,timeout,int *,uaddr2,int,val3)
251
252#endif
bellard66fb9762003-03-23 01:06:05 +0000253
254extern int personality(int);
bellard9de5e442003-03-23 16:49:39 +0000255extern int flock(int, int);
256extern int setfsuid(int);
257extern int setfsgid(int);
bellard5cd43932003-03-29 16:54:36 +0000258extern int setresuid(uid_t, uid_t, uid_t);
259extern int getresuid(uid_t *, uid_t *, uid_t *);
260extern int setresgid(gid_t, gid_t, gid_t);
261extern int getresgid(gid_t *, gid_t *, gid_t *);
bellard19b84f32003-05-08 15:41:49 +0000262extern int setgroups(int, gid_t *);
bellard31e31b82003-02-18 22:55:36 +0000263
thsb92c47c2007-11-01 00:07:38 +0000264#define ERRNO_TABLE_SIZE 1200
265
266/* target_to_host_errno_table[] is initialized from
267 * host_to_target_errno_table[] in syscall_init(). */
268static uint16_t target_to_host_errno_table[ERRNO_TABLE_SIZE] = {
269};
270
ths637947f2007-06-01 12:09:19 +0000271/*
thsfe8f0962007-07-12 10:59:21 +0000272 * This list is the union of errno values overridden in asm-<arch>/errno.h
ths637947f2007-06-01 12:09:19 +0000273 * minus the errnos that are not actually generic to all archs.
274 */
thsb92c47c2007-11-01 00:07:38 +0000275static uint16_t host_to_target_errno_table[ERRNO_TABLE_SIZE] = {
ths637947f2007-06-01 12:09:19 +0000276 [EIDRM] = TARGET_EIDRM,
277 [ECHRNG] = TARGET_ECHRNG,
278 [EL2NSYNC] = TARGET_EL2NSYNC,
279 [EL3HLT] = TARGET_EL3HLT,
280 [EL3RST] = TARGET_EL3RST,
281 [ELNRNG] = TARGET_ELNRNG,
282 [EUNATCH] = TARGET_EUNATCH,
283 [ENOCSI] = TARGET_ENOCSI,
284 [EL2HLT] = TARGET_EL2HLT,
285 [EDEADLK] = TARGET_EDEADLK,
286 [ENOLCK] = TARGET_ENOLCK,
287 [EBADE] = TARGET_EBADE,
288 [EBADR] = TARGET_EBADR,
289 [EXFULL] = TARGET_EXFULL,
290 [ENOANO] = TARGET_ENOANO,
291 [EBADRQC] = TARGET_EBADRQC,
292 [EBADSLT] = TARGET_EBADSLT,
293 [EBFONT] = TARGET_EBFONT,
294 [ENOSTR] = TARGET_ENOSTR,
295 [ENODATA] = TARGET_ENODATA,
296 [ETIME] = TARGET_ETIME,
297 [ENOSR] = TARGET_ENOSR,
298 [ENONET] = TARGET_ENONET,
299 [ENOPKG] = TARGET_ENOPKG,
300 [EREMOTE] = TARGET_EREMOTE,
301 [ENOLINK] = TARGET_ENOLINK,
302 [EADV] = TARGET_EADV,
303 [ESRMNT] = TARGET_ESRMNT,
304 [ECOMM] = TARGET_ECOMM,
305 [EPROTO] = TARGET_EPROTO,
306 [EDOTDOT] = TARGET_EDOTDOT,
307 [EMULTIHOP] = TARGET_EMULTIHOP,
308 [EBADMSG] = TARGET_EBADMSG,
309 [ENAMETOOLONG] = TARGET_ENAMETOOLONG,
310 [EOVERFLOW] = TARGET_EOVERFLOW,
311 [ENOTUNIQ] = TARGET_ENOTUNIQ,
312 [EBADFD] = TARGET_EBADFD,
313 [EREMCHG] = TARGET_EREMCHG,
314 [ELIBACC] = TARGET_ELIBACC,
315 [ELIBBAD] = TARGET_ELIBBAD,
316 [ELIBSCN] = TARGET_ELIBSCN,
317 [ELIBMAX] = TARGET_ELIBMAX,
318 [ELIBEXEC] = TARGET_ELIBEXEC,
319 [EILSEQ] = TARGET_EILSEQ,
320 [ENOSYS] = TARGET_ENOSYS,
321 [ELOOP] = TARGET_ELOOP,
322 [ERESTART] = TARGET_ERESTART,
323 [ESTRPIPE] = TARGET_ESTRPIPE,
324 [ENOTEMPTY] = TARGET_ENOTEMPTY,
325 [EUSERS] = TARGET_EUSERS,
326 [ENOTSOCK] = TARGET_ENOTSOCK,
327 [EDESTADDRREQ] = TARGET_EDESTADDRREQ,
328 [EMSGSIZE] = TARGET_EMSGSIZE,
329 [EPROTOTYPE] = TARGET_EPROTOTYPE,
330 [ENOPROTOOPT] = TARGET_ENOPROTOOPT,
331 [EPROTONOSUPPORT] = TARGET_EPROTONOSUPPORT,
332 [ESOCKTNOSUPPORT] = TARGET_ESOCKTNOSUPPORT,
333 [EOPNOTSUPP] = TARGET_EOPNOTSUPP,
334 [EPFNOSUPPORT] = TARGET_EPFNOSUPPORT,
335 [EAFNOSUPPORT] = TARGET_EAFNOSUPPORT,
336 [EADDRINUSE] = TARGET_EADDRINUSE,
337 [EADDRNOTAVAIL] = TARGET_EADDRNOTAVAIL,
338 [ENETDOWN] = TARGET_ENETDOWN,
339 [ENETUNREACH] = TARGET_ENETUNREACH,
340 [ENETRESET] = TARGET_ENETRESET,
341 [ECONNABORTED] = TARGET_ECONNABORTED,
342 [ECONNRESET] = TARGET_ECONNRESET,
343 [ENOBUFS] = TARGET_ENOBUFS,
344 [EISCONN] = TARGET_EISCONN,
345 [ENOTCONN] = TARGET_ENOTCONN,
346 [EUCLEAN] = TARGET_EUCLEAN,
347 [ENOTNAM] = TARGET_ENOTNAM,
348 [ENAVAIL] = TARGET_ENAVAIL,
349 [EISNAM] = TARGET_EISNAM,
350 [EREMOTEIO] = TARGET_EREMOTEIO,
351 [ESHUTDOWN] = TARGET_ESHUTDOWN,
352 [ETOOMANYREFS] = TARGET_ETOOMANYREFS,
353 [ETIMEDOUT] = TARGET_ETIMEDOUT,
354 [ECONNREFUSED] = TARGET_ECONNREFUSED,
355 [EHOSTDOWN] = TARGET_EHOSTDOWN,
356 [EHOSTUNREACH] = TARGET_EHOSTUNREACH,
357 [EALREADY] = TARGET_EALREADY,
358 [EINPROGRESS] = TARGET_EINPROGRESS,
359 [ESTALE] = TARGET_ESTALE,
360 [ECANCELED] = TARGET_ECANCELED,
361 [ENOMEDIUM] = TARGET_ENOMEDIUM,
362 [EMEDIUMTYPE] = TARGET_EMEDIUMTYPE,
thsb7fe5db2007-07-23 15:37:46 +0000363#ifdef ENOKEY
ths637947f2007-06-01 12:09:19 +0000364 [ENOKEY] = TARGET_ENOKEY,
thsb7fe5db2007-07-23 15:37:46 +0000365#endif
366#ifdef EKEYEXPIRED
ths637947f2007-06-01 12:09:19 +0000367 [EKEYEXPIRED] = TARGET_EKEYEXPIRED,
thsb7fe5db2007-07-23 15:37:46 +0000368#endif
369#ifdef EKEYREVOKED
ths637947f2007-06-01 12:09:19 +0000370 [EKEYREVOKED] = TARGET_EKEYREVOKED,
thsb7fe5db2007-07-23 15:37:46 +0000371#endif
372#ifdef EKEYREJECTED
ths637947f2007-06-01 12:09:19 +0000373 [EKEYREJECTED] = TARGET_EKEYREJECTED,
thsb7fe5db2007-07-23 15:37:46 +0000374#endif
375#ifdef EOWNERDEAD
ths637947f2007-06-01 12:09:19 +0000376 [EOWNERDEAD] = TARGET_EOWNERDEAD,
thsb7fe5db2007-07-23 15:37:46 +0000377#endif
378#ifdef ENOTRECOVERABLE
ths637947f2007-06-01 12:09:19 +0000379 [ENOTRECOVERABLE] = TARGET_ENOTRECOVERABLE,
thsb7fe5db2007-07-23 15:37:46 +0000380#endif
thsb92c47c2007-11-01 00:07:38 +0000381};
ths637947f2007-06-01 12:09:19 +0000382
383static inline int host_to_target_errno(int err)
384{
385 if(host_to_target_errno_table[err])
386 return host_to_target_errno_table[err];
387 return err;
388}
389
thsb92c47c2007-11-01 00:07:38 +0000390static inline int target_to_host_errno(int err)
391{
392 if (target_to_host_errno_table[err])
393 return target_to_host_errno_table[err];
394 return err;
395}
396
blueswir1992f48a2007-10-14 16:27:31 +0000397static inline abi_long get_errno(abi_long ret)
bellard31e31b82003-02-18 22:55:36 +0000398{
399 if (ret == -1)
ths637947f2007-06-01 12:09:19 +0000400 return -host_to_target_errno(errno);
bellard31e31b82003-02-18 22:55:36 +0000401 else
402 return ret;
403}
404
blueswir1992f48a2007-10-14 16:27:31 +0000405static inline int is_error(abi_long ret)
bellard31e31b82003-02-18 22:55:36 +0000406{
blueswir1992f48a2007-10-14 16:27:31 +0000407 return (abi_ulong)ret >= (abi_ulong)(-4096);
bellard31e31b82003-02-18 22:55:36 +0000408}
409
thsb92c47c2007-11-01 00:07:38 +0000410char *target_strerror(int err)
411{
412 return strerror(target_to_host_errno(err));
413}
414
blueswir1992f48a2007-10-14 16:27:31 +0000415static abi_ulong target_brk;
416static abi_ulong target_original_brk;
bellard31e31b82003-02-18 22:55:36 +0000417
blueswir1992f48a2007-10-14 16:27:31 +0000418void target_set_brk(abi_ulong new_brk)
bellard31e31b82003-02-18 22:55:36 +0000419{
blueswir14c1de732007-07-07 20:45:44 +0000420 target_original_brk = target_brk = HOST_PAGE_ALIGN(new_brk);
bellard31e31b82003-02-18 22:55:36 +0000421}
422
ths0da46a62007-10-20 20:23:07 +0000423/* do_brk() must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +0000424abi_long do_brk(abi_ulong new_brk)
bellard31e31b82003-02-18 22:55:36 +0000425{
blueswir1992f48a2007-10-14 16:27:31 +0000426 abi_ulong brk_page;
427 abi_long mapped_addr;
bellard31e31b82003-02-18 22:55:36 +0000428 int new_alloc_size;
429
430 if (!new_brk)
pbrook53a59602006-03-25 19:31:22 +0000431 return target_brk;
bellard31e31b82003-02-18 22:55:36 +0000432 if (new_brk < target_original_brk)
balrog7ab240a2008-04-26 12:17:34 +0000433 return target_brk;
ths3b46e622007-09-17 08:09:54 +0000434
pbrook53a59602006-03-25 19:31:22 +0000435 brk_page = HOST_PAGE_ALIGN(target_brk);
bellard31e31b82003-02-18 22:55:36 +0000436
437 /* If the new brk is less than this, set it and we're done... */
438 if (new_brk < brk_page) {
439 target_brk = new_brk;
pbrook53a59602006-03-25 19:31:22 +0000440 return target_brk;
bellard31e31b82003-02-18 22:55:36 +0000441 }
442
443 /* We need to allocate more memory after the brk... */
bellard54936002003-05-13 00:25:15 +0000444 new_alloc_size = HOST_PAGE_ALIGN(new_brk - brk_page + 1);
ths5fafdf22007-09-16 21:08:06 +0000445 mapped_addr = get_errno(target_mmap(brk_page, new_alloc_size,
bellard54936002003-05-13 00:25:15 +0000446 PROT_READ|PROT_WRITE,
447 MAP_ANON|MAP_FIXED|MAP_PRIVATE, 0, 0));
balrog7ab240a2008-04-26 12:17:34 +0000448
449 if (!is_error(mapped_addr))
bellard31e31b82003-02-18 22:55:36 +0000450 target_brk = new_brk;
balrog7ab240a2008-04-26 12:17:34 +0000451
452 return target_brk;
bellard31e31b82003-02-18 22:55:36 +0000453}
454
ths26edcf42007-12-09 02:25:24 +0000455static inline abi_long copy_from_user_fdset(fd_set *fds,
456 abi_ulong target_fds_addr,
457 int n)
bellard31e31b82003-02-18 22:55:36 +0000458{
ths26edcf42007-12-09 02:25:24 +0000459 int i, nw, j, k;
460 abi_ulong b, *target_fds;
461
462 nw = (n + TARGET_ABI_BITS - 1) / TARGET_ABI_BITS;
463 if (!(target_fds = lock_user(VERIFY_READ,
464 target_fds_addr,
465 sizeof(abi_ulong) * nw,
466 1)))
467 return -TARGET_EFAULT;
468
469 FD_ZERO(fds);
470 k = 0;
471 for (i = 0; i < nw; i++) {
472 /* grab the abi_ulong */
473 __get_user(b, &target_fds[i]);
474 for (j = 0; j < TARGET_ABI_BITS; j++) {
475 /* check the bit inside the abi_ulong */
476 if ((b >> j) & 1)
477 FD_SET(k, fds);
478 k++;
bellard31e31b82003-02-18 22:55:36 +0000479 }
bellard31e31b82003-02-18 22:55:36 +0000480 }
ths26edcf42007-12-09 02:25:24 +0000481
482 unlock_user(target_fds, target_fds_addr, 0);
483
484 return 0;
bellard31e31b82003-02-18 22:55:36 +0000485}
486
ths26edcf42007-12-09 02:25:24 +0000487static inline abi_long copy_to_user_fdset(abi_ulong target_fds_addr,
488 const fd_set *fds,
489 int n)
bellard31e31b82003-02-18 22:55:36 +0000490{
bellard31e31b82003-02-18 22:55:36 +0000491 int i, nw, j, k;
blueswir1992f48a2007-10-14 16:27:31 +0000492 abi_long v;
ths26edcf42007-12-09 02:25:24 +0000493 abi_ulong *target_fds;
bellard31e31b82003-02-18 22:55:36 +0000494
ths26edcf42007-12-09 02:25:24 +0000495 nw = (n + TARGET_ABI_BITS - 1) / TARGET_ABI_BITS;
496 if (!(target_fds = lock_user(VERIFY_WRITE,
497 target_fds_addr,
498 sizeof(abi_ulong) * nw,
499 0)))
500 return -TARGET_EFAULT;
501
502 k = 0;
503 for (i = 0; i < nw; i++) {
504 v = 0;
505 for (j = 0; j < TARGET_ABI_BITS; j++) {
506 v |= ((FD_ISSET(k, fds) != 0) << j);
507 k++;
bellard31e31b82003-02-18 22:55:36 +0000508 }
ths26edcf42007-12-09 02:25:24 +0000509 __put_user(v, &target_fds[i]);
bellard31e31b82003-02-18 22:55:36 +0000510 }
ths26edcf42007-12-09 02:25:24 +0000511
512 unlock_user(target_fds, target_fds_addr, sizeof(abi_ulong) * nw);
513
514 return 0;
bellard31e31b82003-02-18 22:55:36 +0000515}
516
bellardc596ed12003-07-13 17:32:31 +0000517#if defined(__alpha__)
518#define HOST_HZ 1024
519#else
520#define HOST_HZ 100
521#endif
522
blueswir1992f48a2007-10-14 16:27:31 +0000523static inline abi_long host_to_target_clock_t(long ticks)
bellardc596ed12003-07-13 17:32:31 +0000524{
525#if HOST_HZ == TARGET_HZ
526 return ticks;
527#else
528 return ((int64_t)ticks * TARGET_HZ) / HOST_HZ;
529#endif
530}
531
bellard579a97f2007-11-11 14:26:47 +0000532static inline abi_long host_to_target_rusage(abi_ulong target_addr,
533 const struct rusage *rusage)
bellardb4091862003-05-16 15:39:34 +0000534{
pbrook53a59602006-03-25 19:31:22 +0000535 struct target_rusage *target_rusage;
536
bellard579a97f2007-11-11 14:26:47 +0000537 if (!lock_user_struct(VERIFY_WRITE, target_rusage, target_addr, 0))
538 return -TARGET_EFAULT;
bellardb4091862003-05-16 15:39:34 +0000539 target_rusage->ru_utime.tv_sec = tswapl(rusage->ru_utime.tv_sec);
540 target_rusage->ru_utime.tv_usec = tswapl(rusage->ru_utime.tv_usec);
541 target_rusage->ru_stime.tv_sec = tswapl(rusage->ru_stime.tv_sec);
542 target_rusage->ru_stime.tv_usec = tswapl(rusage->ru_stime.tv_usec);
543 target_rusage->ru_maxrss = tswapl(rusage->ru_maxrss);
544 target_rusage->ru_ixrss = tswapl(rusage->ru_ixrss);
545 target_rusage->ru_idrss = tswapl(rusage->ru_idrss);
546 target_rusage->ru_isrss = tswapl(rusage->ru_isrss);
547 target_rusage->ru_minflt = tswapl(rusage->ru_minflt);
548 target_rusage->ru_majflt = tswapl(rusage->ru_majflt);
549 target_rusage->ru_nswap = tswapl(rusage->ru_nswap);
550 target_rusage->ru_inblock = tswapl(rusage->ru_inblock);
551 target_rusage->ru_oublock = tswapl(rusage->ru_oublock);
552 target_rusage->ru_msgsnd = tswapl(rusage->ru_msgsnd);
553 target_rusage->ru_msgrcv = tswapl(rusage->ru_msgrcv);
554 target_rusage->ru_nsignals = tswapl(rusage->ru_nsignals);
555 target_rusage->ru_nvcsw = tswapl(rusage->ru_nvcsw);
556 target_rusage->ru_nivcsw = tswapl(rusage->ru_nivcsw);
pbrook53a59602006-03-25 19:31:22 +0000557 unlock_user_struct(target_rusage, target_addr, 1);
bellard579a97f2007-11-11 14:26:47 +0000558
559 return 0;
bellardb4091862003-05-16 15:39:34 +0000560}
561
ths788f5ec2007-12-09 02:37:05 +0000562static inline abi_long copy_from_user_timeval(struct timeval *tv,
563 abi_ulong target_tv_addr)
bellard31e31b82003-02-18 22:55:36 +0000564{
pbrook53a59602006-03-25 19:31:22 +0000565 struct target_timeval *target_tv;
566
ths788f5ec2007-12-09 02:37:05 +0000567 if (!lock_user_struct(VERIFY_READ, target_tv, target_tv_addr, 1))
bellard579a97f2007-11-11 14:26:47 +0000568 return -TARGET_EFAULT;
ths788f5ec2007-12-09 02:37:05 +0000569
570 __get_user(tv->tv_sec, &target_tv->tv_sec);
571 __get_user(tv->tv_usec, &target_tv->tv_usec);
572
573 unlock_user_struct(target_tv, target_tv_addr, 0);
bellard579a97f2007-11-11 14:26:47 +0000574
575 return 0;
bellard31e31b82003-02-18 22:55:36 +0000576}
577
ths788f5ec2007-12-09 02:37:05 +0000578static inline abi_long copy_to_user_timeval(abi_ulong target_tv_addr,
579 const struct timeval *tv)
bellard31e31b82003-02-18 22:55:36 +0000580{
pbrook53a59602006-03-25 19:31:22 +0000581 struct target_timeval *target_tv;
582
ths788f5ec2007-12-09 02:37:05 +0000583 if (!lock_user_struct(VERIFY_WRITE, target_tv, target_tv_addr, 0))
bellard579a97f2007-11-11 14:26:47 +0000584 return -TARGET_EFAULT;
ths788f5ec2007-12-09 02:37:05 +0000585
586 __put_user(tv->tv_sec, &target_tv->tv_sec);
587 __put_user(tv->tv_usec, &target_tv->tv_usec);
588
589 unlock_user_struct(target_tv, target_tv_addr, 1);
bellard579a97f2007-11-11 14:26:47 +0000590
591 return 0;
bellard31e31b82003-02-18 22:55:36 +0000592}
593
594
ths0da46a62007-10-20 20:23:07 +0000595/* do_select() must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +0000596static abi_long do_select(int n,
ths26edcf42007-12-09 02:25:24 +0000597 abi_ulong rfd_addr, abi_ulong wfd_addr,
598 abi_ulong efd_addr, abi_ulong target_tv_addr)
bellard31e31b82003-02-18 22:55:36 +0000599{
600 fd_set rfds, wfds, efds;
601 fd_set *rfds_ptr, *wfds_ptr, *efds_ptr;
602 struct timeval tv, *tv_ptr;
blueswir1992f48a2007-10-14 16:27:31 +0000603 abi_long ret;
bellard31e31b82003-02-18 22:55:36 +0000604
ths26edcf42007-12-09 02:25:24 +0000605 if (rfd_addr) {
606 if (copy_from_user_fdset(&rfds, rfd_addr, n))
607 return -TARGET_EFAULT;
608 rfds_ptr = &rfds;
pbrook53a59602006-03-25 19:31:22 +0000609 } else {
pbrook53a59602006-03-25 19:31:22 +0000610 rfds_ptr = NULL;
611 }
ths26edcf42007-12-09 02:25:24 +0000612 if (wfd_addr) {
613 if (copy_from_user_fdset(&wfds, wfd_addr, n))
614 return -TARGET_EFAULT;
615 wfds_ptr = &wfds;
pbrook53a59602006-03-25 19:31:22 +0000616 } else {
pbrook53a59602006-03-25 19:31:22 +0000617 wfds_ptr = NULL;
618 }
ths26edcf42007-12-09 02:25:24 +0000619 if (efd_addr) {
620 if (copy_from_user_fdset(&efds, efd_addr, n))
621 return -TARGET_EFAULT;
622 efds_ptr = &efds;
pbrook53a59602006-03-25 19:31:22 +0000623 } else {
pbrook53a59602006-03-25 19:31:22 +0000624 efds_ptr = NULL;
625 }
ths3b46e622007-09-17 08:09:54 +0000626
ths26edcf42007-12-09 02:25:24 +0000627 if (target_tv_addr) {
ths788f5ec2007-12-09 02:37:05 +0000628 if (copy_from_user_timeval(&tv, target_tv_addr))
629 return -TARGET_EFAULT;
bellard31e31b82003-02-18 22:55:36 +0000630 tv_ptr = &tv;
631 } else {
632 tv_ptr = NULL;
633 }
ths26edcf42007-12-09 02:25:24 +0000634
bellard31e31b82003-02-18 22:55:36 +0000635 ret = get_errno(select(n, rfds_ptr, wfds_ptr, efds_ptr, tv_ptr));
pbrook53a59602006-03-25 19:31:22 +0000636
ths26edcf42007-12-09 02:25:24 +0000637 if (!is_error(ret)) {
638 if (rfd_addr && copy_to_user_fdset(rfd_addr, &rfds, n))
639 return -TARGET_EFAULT;
640 if (wfd_addr && copy_to_user_fdset(wfd_addr, &wfds, n))
641 return -TARGET_EFAULT;
642 if (efd_addr && copy_to_user_fdset(efd_addr, &efds, n))
643 return -TARGET_EFAULT;
bellard31e31b82003-02-18 22:55:36 +0000644
ths788f5ec2007-12-09 02:37:05 +0000645 if (target_tv_addr && copy_to_user_timeval(target_tv_addr, &tv))
646 return -TARGET_EFAULT;
bellard31e31b82003-02-18 22:55:36 +0000647 }
bellard579a97f2007-11-11 14:26:47 +0000648
bellard31e31b82003-02-18 22:55:36 +0000649 return ret;
650}
651
bellard579a97f2007-11-11 14:26:47 +0000652static inline abi_long target_to_host_sockaddr(struct sockaddr *addr,
653 abi_ulong target_addr,
654 socklen_t len)
bellard7854b052003-03-29 17:22:23 +0000655{
pbrook53a59602006-03-25 19:31:22 +0000656 struct target_sockaddr *target_saddr;
657
bellard579a97f2007-11-11 14:26:47 +0000658 target_saddr = lock_user(VERIFY_READ, target_addr, len, 1);
659 if (!target_saddr)
660 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +0000661 memcpy(addr, target_saddr, len);
662 addr->sa_family = tswap16(target_saddr->sa_family);
663 unlock_user(target_saddr, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +0000664
665 return 0;
bellard7854b052003-03-29 17:22:23 +0000666}
667
bellard579a97f2007-11-11 14:26:47 +0000668static inline abi_long host_to_target_sockaddr(abi_ulong target_addr,
669 struct sockaddr *addr,
670 socklen_t len)
bellard7854b052003-03-29 17:22:23 +0000671{
pbrook53a59602006-03-25 19:31:22 +0000672 struct target_sockaddr *target_saddr;
673
bellard579a97f2007-11-11 14:26:47 +0000674 target_saddr = lock_user(VERIFY_WRITE, target_addr, len, 0);
675 if (!target_saddr)
676 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +0000677 memcpy(target_saddr, addr, len);
678 target_saddr->sa_family = tswap16(addr->sa_family);
679 unlock_user(target_saddr, target_addr, len);
bellard579a97f2007-11-11 14:26:47 +0000680
681 return 0;
bellard7854b052003-03-29 17:22:23 +0000682}
683
pbrook53a59602006-03-25 19:31:22 +0000684/* ??? Should this also swap msgh->name? */
bellard5a4a8982007-11-11 17:39:18 +0000685static inline abi_long target_to_host_cmsg(struct msghdr *msgh,
686 struct target_msghdr *target_msgh)
bellard7854b052003-03-29 17:22:23 +0000687{
688 struct cmsghdr *cmsg = CMSG_FIRSTHDR(msgh);
bellard5a4a8982007-11-11 17:39:18 +0000689 abi_long msg_controllen;
690 abi_ulong target_cmsg_addr;
691 struct target_cmsghdr *target_cmsg;
bellard7854b052003-03-29 17:22:23 +0000692 socklen_t space = 0;
bellard5a4a8982007-11-11 17:39:18 +0000693
694 msg_controllen = tswapl(target_msgh->msg_controllen);
695 if (msg_controllen < sizeof (struct target_cmsghdr))
696 goto the_end;
697 target_cmsg_addr = tswapl(target_msgh->msg_control);
698 target_cmsg = lock_user(VERIFY_READ, target_cmsg_addr, msg_controllen, 1);
699 if (!target_cmsg)
700 return -TARGET_EFAULT;
bellard7854b052003-03-29 17:22:23 +0000701
702 while (cmsg && target_cmsg) {
703 void *data = CMSG_DATA(cmsg);
704 void *target_data = TARGET_CMSG_DATA(target_cmsg);
705
ths5fafdf22007-09-16 21:08:06 +0000706 int len = tswapl(target_cmsg->cmsg_len)
bellard7854b052003-03-29 17:22:23 +0000707 - TARGET_CMSG_ALIGN(sizeof (struct target_cmsghdr));
708
709 space += CMSG_SPACE(len);
710 if (space > msgh->msg_controllen) {
711 space -= CMSG_SPACE(len);
bellard31febb72005-12-18 20:03:27 +0000712 gemu_log("Host cmsg overflow\n");
bellard7854b052003-03-29 17:22:23 +0000713 break;
714 }
715
716 cmsg->cmsg_level = tswap32(target_cmsg->cmsg_level);
717 cmsg->cmsg_type = tswap32(target_cmsg->cmsg_type);
718 cmsg->cmsg_len = CMSG_LEN(len);
719
bellard3532fa72006-06-24 15:06:03 +0000720 if (cmsg->cmsg_level != TARGET_SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS) {
bellard7854b052003-03-29 17:22:23 +0000721 gemu_log("Unsupported ancillary data: %d/%d\n", cmsg->cmsg_level, cmsg->cmsg_type);
722 memcpy(data, target_data, len);
723 } else {
724 int *fd = (int *)data;
725 int *target_fd = (int *)target_data;
726 int i, numfds = len / sizeof(int);
727
728 for (i = 0; i < numfds; i++)
729 fd[i] = tswap32(target_fd[i]);
730 }
731
732 cmsg = CMSG_NXTHDR(msgh, cmsg);
733 target_cmsg = TARGET_CMSG_NXTHDR(target_msgh, target_cmsg);
734 }
bellard5a4a8982007-11-11 17:39:18 +0000735 unlock_user(target_cmsg, target_cmsg_addr, 0);
736 the_end:
bellard7854b052003-03-29 17:22:23 +0000737 msgh->msg_controllen = space;
bellard5a4a8982007-11-11 17:39:18 +0000738 return 0;
bellard7854b052003-03-29 17:22:23 +0000739}
740
pbrook53a59602006-03-25 19:31:22 +0000741/* ??? Should this also swap msgh->name? */
bellard5a4a8982007-11-11 17:39:18 +0000742static inline abi_long host_to_target_cmsg(struct target_msghdr *target_msgh,
743 struct msghdr *msgh)
bellard7854b052003-03-29 17:22:23 +0000744{
745 struct cmsghdr *cmsg = CMSG_FIRSTHDR(msgh);
bellard5a4a8982007-11-11 17:39:18 +0000746 abi_long msg_controllen;
747 abi_ulong target_cmsg_addr;
748 struct target_cmsghdr *target_cmsg;
bellard7854b052003-03-29 17:22:23 +0000749 socklen_t space = 0;
750
bellard5a4a8982007-11-11 17:39:18 +0000751 msg_controllen = tswapl(target_msgh->msg_controllen);
752 if (msg_controllen < sizeof (struct target_cmsghdr))
753 goto the_end;
754 target_cmsg_addr = tswapl(target_msgh->msg_control);
755 target_cmsg = lock_user(VERIFY_WRITE, target_cmsg_addr, msg_controllen, 0);
756 if (!target_cmsg)
757 return -TARGET_EFAULT;
758
bellard7854b052003-03-29 17:22:23 +0000759 while (cmsg && target_cmsg) {
760 void *data = CMSG_DATA(cmsg);
761 void *target_data = TARGET_CMSG_DATA(target_cmsg);
762
763 int len = cmsg->cmsg_len - CMSG_ALIGN(sizeof (struct cmsghdr));
764
765 space += TARGET_CMSG_SPACE(len);
bellard5a4a8982007-11-11 17:39:18 +0000766 if (space > msg_controllen) {
bellard7854b052003-03-29 17:22:23 +0000767 space -= TARGET_CMSG_SPACE(len);
bellard31febb72005-12-18 20:03:27 +0000768 gemu_log("Target cmsg overflow\n");
bellard7854b052003-03-29 17:22:23 +0000769 break;
770 }
771
772 target_cmsg->cmsg_level = tswap32(cmsg->cmsg_level);
773 target_cmsg->cmsg_type = tswap32(cmsg->cmsg_type);
774 target_cmsg->cmsg_len = tswapl(TARGET_CMSG_LEN(len));
775
bellard3532fa72006-06-24 15:06:03 +0000776 if (cmsg->cmsg_level != TARGET_SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS) {
bellard7854b052003-03-29 17:22:23 +0000777 gemu_log("Unsupported ancillary data: %d/%d\n", cmsg->cmsg_level, cmsg->cmsg_type);
778 memcpy(target_data, data, len);
779 } else {
780 int *fd = (int *)data;
781 int *target_fd = (int *)target_data;
782 int i, numfds = len / sizeof(int);
783
784 for (i = 0; i < numfds; i++)
785 target_fd[i] = tswap32(fd[i]);
786 }
787
788 cmsg = CMSG_NXTHDR(msgh, cmsg);
789 target_cmsg = TARGET_CMSG_NXTHDR(target_msgh, target_cmsg);
790 }
bellard5a4a8982007-11-11 17:39:18 +0000791 unlock_user(target_cmsg, target_cmsg_addr, space);
792 the_end:
793 target_msgh->msg_controllen = tswapl(space);
794 return 0;
bellard7854b052003-03-29 17:22:23 +0000795}
796
ths0da46a62007-10-20 20:23:07 +0000797/* do_setsockopt() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +0000798static abi_long do_setsockopt(int sockfd, int level, int optname,
bellard2f619692007-11-16 10:46:05 +0000799 abi_ulong optval_addr, socklen_t optlen)
bellard7854b052003-03-29 17:22:23 +0000800{
blueswir1992f48a2007-10-14 16:27:31 +0000801 abi_long ret;
j_mayer32407102007-09-26 23:01:49 +0000802 int val;
ths3b46e622007-09-17 08:09:54 +0000803
bellard8853f862004-02-22 14:57:26 +0000804 switch(level) {
805 case SOL_TCP:
bellard7854b052003-03-29 17:22:23 +0000806 /* TCP options all take an 'int' value. */
bellard7854b052003-03-29 17:22:23 +0000807 if (optlen < sizeof(uint32_t))
ths0da46a62007-10-20 20:23:07 +0000808 return -TARGET_EINVAL;
ths3b46e622007-09-17 08:09:54 +0000809
bellard2f619692007-11-16 10:46:05 +0000810 if (get_user_u32(val, optval_addr))
811 return -TARGET_EFAULT;
bellard8853f862004-02-22 14:57:26 +0000812 ret = get_errno(setsockopt(sockfd, level, optname, &val, sizeof(val)));
813 break;
814 case SOL_IP:
815 switch(optname) {
bellard2efbe912005-07-23 15:10:20 +0000816 case IP_TOS:
817 case IP_TTL:
bellard8853f862004-02-22 14:57:26 +0000818 case IP_HDRINCL:
bellard2efbe912005-07-23 15:10:20 +0000819 case IP_ROUTER_ALERT:
820 case IP_RECVOPTS:
821 case IP_RETOPTS:
822 case IP_PKTINFO:
823 case IP_MTU_DISCOVER:
824 case IP_RECVERR:
825 case IP_RECVTOS:
826#ifdef IP_FREEBIND
827 case IP_FREEBIND:
828#endif
829 case IP_MULTICAST_TTL:
830 case IP_MULTICAST_LOOP:
bellard8853f862004-02-22 14:57:26 +0000831 val = 0;
832 if (optlen >= sizeof(uint32_t)) {
bellard2f619692007-11-16 10:46:05 +0000833 if (get_user_u32(val, optval_addr))
834 return -TARGET_EFAULT;
bellard8853f862004-02-22 14:57:26 +0000835 } else if (optlen >= 1) {
bellard2f619692007-11-16 10:46:05 +0000836 if (get_user_u8(val, optval_addr))
837 return -TARGET_EFAULT;
bellard8853f862004-02-22 14:57:26 +0000838 }
839 ret = get_errno(setsockopt(sockfd, level, optname, &val, sizeof(val)));
840 break;
841 default:
842 goto unimplemented;
843 }
844 break;
bellard3532fa72006-06-24 15:06:03 +0000845 case TARGET_SOL_SOCKET:
bellard8853f862004-02-22 14:57:26 +0000846 switch (optname) {
847 /* Options with 'int' argument. */
bellard3532fa72006-06-24 15:06:03 +0000848 case TARGET_SO_DEBUG:
849 optname = SO_DEBUG;
850 break;
851 case TARGET_SO_REUSEADDR:
852 optname = SO_REUSEADDR;
853 break;
854 case TARGET_SO_TYPE:
855 optname = SO_TYPE;
856 break;
857 case TARGET_SO_ERROR:
858 optname = SO_ERROR;
859 break;
860 case TARGET_SO_DONTROUTE:
861 optname = SO_DONTROUTE;
862 break;
863 case TARGET_SO_BROADCAST:
864 optname = SO_BROADCAST;
865 break;
866 case TARGET_SO_SNDBUF:
867 optname = SO_SNDBUF;
868 break;
869 case TARGET_SO_RCVBUF:
870 optname = SO_RCVBUF;
871 break;
872 case TARGET_SO_KEEPALIVE:
873 optname = SO_KEEPALIVE;
874 break;
875 case TARGET_SO_OOBINLINE:
876 optname = SO_OOBINLINE;
877 break;
878 case TARGET_SO_NO_CHECK:
879 optname = SO_NO_CHECK;
880 break;
881 case TARGET_SO_PRIORITY:
882 optname = SO_PRIORITY;
883 break;
bellard5e83e8e2005-03-01 22:32:06 +0000884#ifdef SO_BSDCOMPAT
bellard3532fa72006-06-24 15:06:03 +0000885 case TARGET_SO_BSDCOMPAT:
886 optname = SO_BSDCOMPAT;
887 break;
bellard5e83e8e2005-03-01 22:32:06 +0000888#endif
bellard3532fa72006-06-24 15:06:03 +0000889 case TARGET_SO_PASSCRED:
890 optname = SO_PASSCRED;
891 break;
892 case TARGET_SO_TIMESTAMP:
893 optname = SO_TIMESTAMP;
894 break;
895 case TARGET_SO_RCVLOWAT:
896 optname = SO_RCVLOWAT;
897 break;
898 case TARGET_SO_RCVTIMEO:
899 optname = SO_RCVTIMEO;
900 break;
901 case TARGET_SO_SNDTIMEO:
902 optname = SO_SNDTIMEO;
903 break;
bellard8853f862004-02-22 14:57:26 +0000904 break;
905 default:
906 goto unimplemented;
907 }
bellard3532fa72006-06-24 15:06:03 +0000908 if (optlen < sizeof(uint32_t))
bellard2f619692007-11-16 10:46:05 +0000909 return -TARGET_EINVAL;
bellard3532fa72006-06-24 15:06:03 +0000910
bellard2f619692007-11-16 10:46:05 +0000911 if (get_user_u32(val, optval_addr))
912 return -TARGET_EFAULT;
bellard3532fa72006-06-24 15:06:03 +0000913 ret = get_errno(setsockopt(sockfd, SOL_SOCKET, optname, &val, sizeof(val)));
bellard8853f862004-02-22 14:57:26 +0000914 break;
bellard7854b052003-03-29 17:22:23 +0000915 default:
bellard8853f862004-02-22 14:57:26 +0000916 unimplemented:
917 gemu_log("Unsupported setsockopt level=%d optname=%d \n", level, optname);
ths6fa13c12007-12-18 02:41:04 +0000918 ret = -TARGET_ENOPROTOOPT;
bellard7854b052003-03-29 17:22:23 +0000919 }
bellard8853f862004-02-22 14:57:26 +0000920 return ret;
bellard7854b052003-03-29 17:22:23 +0000921}
922
ths0da46a62007-10-20 20:23:07 +0000923/* do_getsockopt() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +0000924static abi_long do_getsockopt(int sockfd, int level, int optname,
bellard2f619692007-11-16 10:46:05 +0000925 abi_ulong optval_addr, abi_ulong optlen)
bellard7854b052003-03-29 17:22:23 +0000926{
blueswir1992f48a2007-10-14 16:27:31 +0000927 abi_long ret;
j_mayer32407102007-09-26 23:01:49 +0000928 int len, lv, val;
bellard8853f862004-02-22 14:57:26 +0000929
930 switch(level) {
bellard3532fa72006-06-24 15:06:03 +0000931 case TARGET_SOL_SOCKET:
932 level = SOL_SOCKET;
bellard8853f862004-02-22 14:57:26 +0000933 switch (optname) {
bellard3532fa72006-06-24 15:06:03 +0000934 case TARGET_SO_LINGER:
935 case TARGET_SO_RCVTIMEO:
936 case TARGET_SO_SNDTIMEO:
937 case TARGET_SO_PEERCRED:
938 case TARGET_SO_PEERNAME:
bellard8853f862004-02-22 14:57:26 +0000939 /* These don't just return a single integer */
940 goto unimplemented;
941 default:
bellard2efbe912005-07-23 15:10:20 +0000942 goto int_case;
943 }
944 break;
945 case SOL_TCP:
946 /* TCP options all take an 'int' value. */
947 int_case:
bellard2f619692007-11-16 10:46:05 +0000948 if (get_user_u32(len, optlen))
949 return -TARGET_EFAULT;
bellard2efbe912005-07-23 15:10:20 +0000950 if (len < 0)
ths0da46a62007-10-20 20:23:07 +0000951 return -TARGET_EINVAL;
bellard2efbe912005-07-23 15:10:20 +0000952 lv = sizeof(int);
953 ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
954 if (ret < 0)
955 return ret;
956 val = tswap32(val);
957 if (len > lv)
958 len = lv;
bellard2f619692007-11-16 10:46:05 +0000959 if (len == 4) {
960 if (put_user_u32(val, optval_addr))
961 return -TARGET_EFAULT;
962 } else {
963 if (put_user_u8(val, optval_addr))
964 return -TARGET_EFAULT;
965 }
966 if (put_user_u32(len, optlen))
967 return -TARGET_EFAULT;
bellard2efbe912005-07-23 15:10:20 +0000968 break;
969 case SOL_IP:
970 switch(optname) {
971 case IP_TOS:
972 case IP_TTL:
973 case IP_HDRINCL:
974 case IP_ROUTER_ALERT:
975 case IP_RECVOPTS:
976 case IP_RETOPTS:
977 case IP_PKTINFO:
978 case IP_MTU_DISCOVER:
979 case IP_RECVERR:
980 case IP_RECVTOS:
981#ifdef IP_FREEBIND
982 case IP_FREEBIND:
983#endif
984 case IP_MULTICAST_TTL:
985 case IP_MULTICAST_LOOP:
bellard2f619692007-11-16 10:46:05 +0000986 if (get_user_u32(len, optlen))
987 return -TARGET_EFAULT;
bellard8853f862004-02-22 14:57:26 +0000988 if (len < 0)
ths0da46a62007-10-20 20:23:07 +0000989 return -TARGET_EINVAL;
bellard8853f862004-02-22 14:57:26 +0000990 lv = sizeof(int);
991 ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
992 if (ret < 0)
993 return ret;
bellard2efbe912005-07-23 15:10:20 +0000994 if (len < sizeof(int) && len > 0 && val >= 0 && val < 255) {
bellard2efbe912005-07-23 15:10:20 +0000995 len = 1;
bellard2f619692007-11-16 10:46:05 +0000996 if (put_user_u32(len, optlen)
997 || put_user_u8(val, optval_addr))
998 return -TARGET_EFAULT;
bellard2efbe912005-07-23 15:10:20 +0000999 } else {
bellard2efbe912005-07-23 15:10:20 +00001000 if (len > sizeof(int))
1001 len = sizeof(int);
bellard2f619692007-11-16 10:46:05 +00001002 if (put_user_u32(len, optlen)
1003 || put_user_u32(val, optval_addr))
1004 return -TARGET_EFAULT;
bellard2efbe912005-07-23 15:10:20 +00001005 }
bellard8853f862004-02-22 14:57:26 +00001006 break;
bellard2efbe912005-07-23 15:10:20 +00001007 default:
thsc02f4992007-12-18 02:39:59 +00001008 ret = -TARGET_ENOPROTOOPT;
1009 break;
bellard8853f862004-02-22 14:57:26 +00001010 }
1011 break;
1012 default:
1013 unimplemented:
1014 gemu_log("getsockopt level=%d optname=%d not yet supported\n",
1015 level, optname);
thsc02f4992007-12-18 02:39:59 +00001016 ret = -TARGET_EOPNOTSUPP;
bellard8853f862004-02-22 14:57:26 +00001017 break;
1018 }
1019 return ret;
bellard7854b052003-03-29 17:22:23 +00001020}
1021
bellard579a97f2007-11-11 14:26:47 +00001022/* FIXME
1023 * lock_iovec()/unlock_iovec() have a return code of 0 for success where
1024 * other lock functions have a return code of 0 for failure.
1025 */
1026static abi_long lock_iovec(int type, struct iovec *vec, abi_ulong target_addr,
1027 int count, int copy)
pbrook53a59602006-03-25 19:31:22 +00001028{
1029 struct target_iovec *target_vec;
blueswir1992f48a2007-10-14 16:27:31 +00001030 abi_ulong base;
bellard579a97f2007-11-11 14:26:47 +00001031 int i, j;
pbrook53a59602006-03-25 19:31:22 +00001032
bellard579a97f2007-11-11 14:26:47 +00001033 target_vec = lock_user(VERIFY_READ, target_addr, count * sizeof(struct target_iovec), 1);
1034 if (!target_vec)
1035 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00001036 for(i = 0;i < count; i++) {
1037 base = tswapl(target_vec[i].iov_base);
1038 vec[i].iov_len = tswapl(target_vec[i].iov_len);
bellard41df8412008-02-04 22:26:57 +00001039 if (vec[i].iov_len != 0) {
1040 vec[i].iov_base = lock_user(type, base, vec[i].iov_len, copy);
balrog7bedce82008-02-10 13:28:08 +00001041 if (!vec[i].iov_base && vec[i].iov_len)
bellard41df8412008-02-04 22:26:57 +00001042 goto fail;
1043 } else {
1044 /* zero length pointer is ignored */
1045 vec[i].iov_base = NULL;
1046 }
pbrook53a59602006-03-25 19:31:22 +00001047 }
1048 unlock_user (target_vec, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00001049 return 0;
1050 fail:
1051 /* failure - unwind locks */
1052 for (j = 0; j < i; j++) {
1053 base = tswapl(target_vec[j].iov_base);
1054 unlock_user(vec[j].iov_base, base, 0);
1055 }
1056 unlock_user (target_vec, target_addr, 0);
1057 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00001058}
1059
bellard579a97f2007-11-11 14:26:47 +00001060static abi_long unlock_iovec(struct iovec *vec, abi_ulong target_addr,
1061 int count, int copy)
pbrook53a59602006-03-25 19:31:22 +00001062{
1063 struct target_iovec *target_vec;
blueswir1992f48a2007-10-14 16:27:31 +00001064 abi_ulong base;
pbrook53a59602006-03-25 19:31:22 +00001065 int i;
1066
bellard579a97f2007-11-11 14:26:47 +00001067 target_vec = lock_user(VERIFY_READ, target_addr, count * sizeof(struct target_iovec), 1);
1068 if (!target_vec)
1069 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00001070 for(i = 0;i < count; i++) {
1071 base = tswapl(target_vec[i].iov_base);
1072 unlock_user(vec[i].iov_base, base, copy ? vec[i].iov_len : 0);
1073 }
1074 unlock_user (target_vec, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00001075
1076 return 0;
pbrook53a59602006-03-25 19:31:22 +00001077}
1078
ths0da46a62007-10-20 20:23:07 +00001079/* do_socket() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001080static abi_long do_socket(int domain, int type, int protocol)
bellard3532fa72006-06-24 15:06:03 +00001081{
1082#if defined(TARGET_MIPS)
1083 switch(type) {
1084 case TARGET_SOCK_DGRAM:
1085 type = SOCK_DGRAM;
1086 break;
1087 case TARGET_SOCK_STREAM:
1088 type = SOCK_STREAM;
1089 break;
1090 case TARGET_SOCK_RAW:
1091 type = SOCK_RAW;
1092 break;
1093 case TARGET_SOCK_RDM:
1094 type = SOCK_RDM;
1095 break;
1096 case TARGET_SOCK_SEQPACKET:
1097 type = SOCK_SEQPACKET;
1098 break;
1099 case TARGET_SOCK_PACKET:
1100 type = SOCK_PACKET;
1101 break;
1102 }
1103#endif
balrog12bc92a2007-10-30 21:06:14 +00001104 if (domain == PF_NETLINK)
1105 return -EAFNOSUPPORT; /* do not NETLINK socket connections possible */
bellard3532fa72006-06-24 15:06:03 +00001106 return get_errno(socket(domain, type, protocol));
1107}
1108
ths0da46a62007-10-20 20:23:07 +00001109/* do_bind() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001110static abi_long do_bind(int sockfd, abi_ulong target_addr,
1111 socklen_t addrlen)
bellard3532fa72006-06-24 15:06:03 +00001112{
1113 void *addr = alloca(addrlen);
ths3b46e622007-09-17 08:09:54 +00001114
bellard3532fa72006-06-24 15:06:03 +00001115 target_to_host_sockaddr(addr, target_addr, addrlen);
1116 return get_errno(bind(sockfd, addr, addrlen));
1117}
1118
ths0da46a62007-10-20 20:23:07 +00001119/* do_connect() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001120static abi_long do_connect(int sockfd, abi_ulong target_addr,
1121 socklen_t addrlen)
bellard3532fa72006-06-24 15:06:03 +00001122{
1123 void *addr = alloca(addrlen);
ths3b46e622007-09-17 08:09:54 +00001124
bellard3532fa72006-06-24 15:06:03 +00001125 target_to_host_sockaddr(addr, target_addr, addrlen);
1126 return get_errno(connect(sockfd, addr, addrlen));
1127}
1128
ths0da46a62007-10-20 20:23:07 +00001129/* do_sendrecvmsg() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001130static abi_long do_sendrecvmsg(int fd, abi_ulong target_msg,
1131 int flags, int send)
bellard3532fa72006-06-24 15:06:03 +00001132{
blueswir1992f48a2007-10-14 16:27:31 +00001133 abi_long ret;
bellard3532fa72006-06-24 15:06:03 +00001134 struct target_msghdr *msgp;
1135 struct msghdr msg;
1136 int count;
1137 struct iovec *vec;
blueswir1992f48a2007-10-14 16:27:31 +00001138 abi_ulong target_vec;
bellard3532fa72006-06-24 15:06:03 +00001139
bellard579a97f2007-11-11 14:26:47 +00001140 /* FIXME */
1141 if (!lock_user_struct(send ? VERIFY_READ : VERIFY_WRITE,
1142 msgp,
1143 target_msg,
1144 send ? 1 : 0))
1145 return -TARGET_EFAULT;
bellard3532fa72006-06-24 15:06:03 +00001146 if (msgp->msg_name) {
1147 msg.msg_namelen = tswap32(msgp->msg_namelen);
1148 msg.msg_name = alloca(msg.msg_namelen);
1149 target_to_host_sockaddr(msg.msg_name, tswapl(msgp->msg_name),
1150 msg.msg_namelen);
1151 } else {
1152 msg.msg_name = NULL;
1153 msg.msg_namelen = 0;
1154 }
1155 msg.msg_controllen = 2 * tswapl(msgp->msg_controllen);
1156 msg.msg_control = alloca(msg.msg_controllen);
1157 msg.msg_flags = tswap32(msgp->msg_flags);
ths3b46e622007-09-17 08:09:54 +00001158
bellard3532fa72006-06-24 15:06:03 +00001159 count = tswapl(msgp->msg_iovlen);
1160 vec = alloca(count * sizeof(struct iovec));
1161 target_vec = tswapl(msgp->msg_iov);
bellard579a97f2007-11-11 14:26:47 +00001162 lock_iovec(send ? VERIFY_READ : VERIFY_WRITE, vec, target_vec, count, send);
bellard3532fa72006-06-24 15:06:03 +00001163 msg.msg_iovlen = count;
1164 msg.msg_iov = vec;
ths3b46e622007-09-17 08:09:54 +00001165
bellard3532fa72006-06-24 15:06:03 +00001166 if (send) {
bellard5a4a8982007-11-11 17:39:18 +00001167 ret = target_to_host_cmsg(&msg, msgp);
1168 if (ret == 0)
1169 ret = get_errno(sendmsg(fd, &msg, flags));
bellard3532fa72006-06-24 15:06:03 +00001170 } else {
1171 ret = get_errno(recvmsg(fd, &msg, flags));
1172 if (!is_error(ret))
bellard5a4a8982007-11-11 17:39:18 +00001173 ret = host_to_target_cmsg(msgp, &msg);
bellard3532fa72006-06-24 15:06:03 +00001174 }
1175 unlock_iovec(vec, target_vec, count, !send);
bellard579a97f2007-11-11 14:26:47 +00001176 unlock_user_struct(msgp, target_msg, send ? 0 : 1);
bellard3532fa72006-06-24 15:06:03 +00001177 return ret;
1178}
1179
ths0da46a62007-10-20 20:23:07 +00001180/* do_accept() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001181static abi_long do_accept(int fd, abi_ulong target_addr,
bellard2f619692007-11-16 10:46:05 +00001182 abi_ulong target_addrlen_addr)
pbrook1be9e1d2006-11-19 15:26:04 +00001183{
bellard2f619692007-11-16 10:46:05 +00001184 socklen_t addrlen;
1185 void *addr;
blueswir1992f48a2007-10-14 16:27:31 +00001186 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00001187
bellard2f619692007-11-16 10:46:05 +00001188 if (get_user_u32(addrlen, target_addrlen_addr))
1189 return -TARGET_EFAULT;
1190
1191 addr = alloca(addrlen);
1192
pbrook1be9e1d2006-11-19 15:26:04 +00001193 ret = get_errno(accept(fd, addr, &addrlen));
1194 if (!is_error(ret)) {
1195 host_to_target_sockaddr(target_addr, addr, addrlen);
bellard2f619692007-11-16 10:46:05 +00001196 if (put_user_u32(addrlen, target_addrlen_addr))
1197 ret = -TARGET_EFAULT;
pbrook1be9e1d2006-11-19 15:26:04 +00001198 }
1199 return ret;
1200}
1201
ths0da46a62007-10-20 20:23:07 +00001202/* do_getpeername() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001203static abi_long do_getpeername(int fd, abi_ulong target_addr,
bellard2f619692007-11-16 10:46:05 +00001204 abi_ulong target_addrlen_addr)
pbrook1be9e1d2006-11-19 15:26:04 +00001205{
bellard2f619692007-11-16 10:46:05 +00001206 socklen_t addrlen;
1207 void *addr;
blueswir1992f48a2007-10-14 16:27:31 +00001208 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00001209
bellard2f619692007-11-16 10:46:05 +00001210 if (get_user_u32(addrlen, target_addrlen_addr))
1211 return -TARGET_EFAULT;
1212
1213 addr = alloca(addrlen);
1214
pbrook1be9e1d2006-11-19 15:26:04 +00001215 ret = get_errno(getpeername(fd, addr, &addrlen));
1216 if (!is_error(ret)) {
1217 host_to_target_sockaddr(target_addr, addr, addrlen);
bellard2f619692007-11-16 10:46:05 +00001218 if (put_user_u32(addrlen, target_addrlen_addr))
1219 ret = -TARGET_EFAULT;
pbrook1be9e1d2006-11-19 15:26:04 +00001220 }
1221 return ret;
1222}
1223
ths0da46a62007-10-20 20:23:07 +00001224/* do_getsockname() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001225static abi_long do_getsockname(int fd, abi_ulong target_addr,
bellard2f619692007-11-16 10:46:05 +00001226 abi_ulong target_addrlen_addr)
pbrook1be9e1d2006-11-19 15:26:04 +00001227{
bellard2f619692007-11-16 10:46:05 +00001228 socklen_t addrlen;
1229 void *addr;
blueswir1992f48a2007-10-14 16:27:31 +00001230 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00001231
bellard2f619692007-11-16 10:46:05 +00001232 if (get_user_u32(addrlen, target_addrlen_addr))
1233 return -TARGET_EFAULT;
1234
1235 addr = alloca(addrlen);
1236
pbrook1be9e1d2006-11-19 15:26:04 +00001237 ret = get_errno(getsockname(fd, addr, &addrlen));
1238 if (!is_error(ret)) {
1239 host_to_target_sockaddr(target_addr, addr, addrlen);
bellard2f619692007-11-16 10:46:05 +00001240 if (put_user_u32(addrlen, target_addrlen_addr))
1241 ret = -TARGET_EFAULT;
pbrook1be9e1d2006-11-19 15:26:04 +00001242 }
1243 return ret;
1244}
1245
ths0da46a62007-10-20 20:23:07 +00001246/* do_socketpair() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001247static abi_long do_socketpair(int domain, int type, int protocol,
bellard2f619692007-11-16 10:46:05 +00001248 abi_ulong target_tab_addr)
pbrook1be9e1d2006-11-19 15:26:04 +00001249{
1250 int tab[2];
blueswir1992f48a2007-10-14 16:27:31 +00001251 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00001252
1253 ret = get_errno(socketpair(domain, type, protocol, tab));
1254 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +00001255 if (put_user_s32(tab[0], target_tab_addr)
1256 || put_user_s32(tab[1], target_tab_addr + sizeof(tab[0])))
1257 ret = -TARGET_EFAULT;
pbrook1be9e1d2006-11-19 15:26:04 +00001258 }
1259 return ret;
1260}
1261
ths0da46a62007-10-20 20:23:07 +00001262/* do_sendto() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001263static abi_long do_sendto(int fd, abi_ulong msg, size_t len, int flags,
1264 abi_ulong target_addr, socklen_t addrlen)
pbrook1be9e1d2006-11-19 15:26:04 +00001265{
1266 void *addr;
1267 void *host_msg;
blueswir1992f48a2007-10-14 16:27:31 +00001268 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00001269
bellard579a97f2007-11-11 14:26:47 +00001270 host_msg = lock_user(VERIFY_READ, msg, len, 1);
1271 if (!host_msg)
1272 return -TARGET_EFAULT;
pbrook1be9e1d2006-11-19 15:26:04 +00001273 if (target_addr) {
1274 addr = alloca(addrlen);
1275 target_to_host_sockaddr(addr, target_addr, addrlen);
1276 ret = get_errno(sendto(fd, host_msg, len, flags, addr, addrlen));
1277 } else {
1278 ret = get_errno(send(fd, host_msg, len, flags));
1279 }
1280 unlock_user(host_msg, msg, 0);
1281 return ret;
1282}
1283
ths0da46a62007-10-20 20:23:07 +00001284/* do_recvfrom() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001285static abi_long do_recvfrom(int fd, abi_ulong msg, size_t len, int flags,
1286 abi_ulong target_addr,
1287 abi_ulong target_addrlen)
pbrook1be9e1d2006-11-19 15:26:04 +00001288{
1289 socklen_t addrlen;
1290 void *addr;
1291 void *host_msg;
blueswir1992f48a2007-10-14 16:27:31 +00001292 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00001293
bellard579a97f2007-11-11 14:26:47 +00001294 host_msg = lock_user(VERIFY_WRITE, msg, len, 0);
1295 if (!host_msg)
1296 return -TARGET_EFAULT;
pbrook1be9e1d2006-11-19 15:26:04 +00001297 if (target_addr) {
bellard2f619692007-11-16 10:46:05 +00001298 if (get_user_u32(addrlen, target_addrlen)) {
1299 ret = -TARGET_EFAULT;
1300 goto fail;
1301 }
pbrook1be9e1d2006-11-19 15:26:04 +00001302 addr = alloca(addrlen);
1303 ret = get_errno(recvfrom(fd, host_msg, len, flags, addr, &addrlen));
1304 } else {
1305 addr = NULL; /* To keep compiler quiet. */
1306 ret = get_errno(recv(fd, host_msg, len, flags));
1307 }
1308 if (!is_error(ret)) {
1309 if (target_addr) {
1310 host_to_target_sockaddr(target_addr, addr, addrlen);
bellard2f619692007-11-16 10:46:05 +00001311 if (put_user_u32(addrlen, target_addrlen)) {
1312 ret = -TARGET_EFAULT;
1313 goto fail;
1314 }
pbrook1be9e1d2006-11-19 15:26:04 +00001315 }
1316 unlock_user(host_msg, msg, len);
1317 } else {
bellard2f619692007-11-16 10:46:05 +00001318fail:
pbrook1be9e1d2006-11-19 15:26:04 +00001319 unlock_user(host_msg, msg, 0);
1320 }
1321 return ret;
1322}
1323
j_mayer32407102007-09-26 23:01:49 +00001324#ifdef TARGET_NR_socketcall
ths0da46a62007-10-20 20:23:07 +00001325/* do_socketcall() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001326static abi_long do_socketcall(int num, abi_ulong vptr)
bellard31e31b82003-02-18 22:55:36 +00001327{
blueswir1992f48a2007-10-14 16:27:31 +00001328 abi_long ret;
1329 const int n = sizeof(abi_ulong);
bellard31e31b82003-02-18 22:55:36 +00001330
1331 switch(num) {
1332 case SOCKOP_socket:
bellard7854b052003-03-29 17:22:23 +00001333 {
bellard2f619692007-11-16 10:46:05 +00001334 int domain, type, protocol;
1335
1336 if (get_user_s32(domain, vptr)
1337 || get_user_s32(type, vptr + n)
1338 || get_user_s32(protocol, vptr + 2 * n))
1339 return -TARGET_EFAULT;
1340
bellard3532fa72006-06-24 15:06:03 +00001341 ret = do_socket(domain, type, protocol);
bellard7854b052003-03-29 17:22:23 +00001342 }
bellard31e31b82003-02-18 22:55:36 +00001343 break;
1344 case SOCKOP_bind:
bellard7854b052003-03-29 17:22:23 +00001345 {
bellard2f619692007-11-16 10:46:05 +00001346 int sockfd;
1347 abi_ulong target_addr;
1348 socklen_t addrlen;
1349
1350 if (get_user_s32(sockfd, vptr)
1351 || get_user_ual(target_addr, vptr + n)
1352 || get_user_u32(addrlen, vptr + 2 * n))
1353 return -TARGET_EFAULT;
1354
bellard3532fa72006-06-24 15:06:03 +00001355 ret = do_bind(sockfd, target_addr, addrlen);
bellard7854b052003-03-29 17:22:23 +00001356 }
bellard31e31b82003-02-18 22:55:36 +00001357 break;
1358 case SOCKOP_connect:
bellard7854b052003-03-29 17:22:23 +00001359 {
bellard2f619692007-11-16 10:46:05 +00001360 int sockfd;
1361 abi_ulong target_addr;
1362 socklen_t addrlen;
1363
1364 if (get_user_s32(sockfd, vptr)
1365 || get_user_ual(target_addr, vptr + n)
1366 || get_user_u32(addrlen, vptr + 2 * n))
1367 return -TARGET_EFAULT;
1368
bellard3532fa72006-06-24 15:06:03 +00001369 ret = do_connect(sockfd, target_addr, addrlen);
bellard7854b052003-03-29 17:22:23 +00001370 }
bellard31e31b82003-02-18 22:55:36 +00001371 break;
1372 case SOCKOP_listen:
bellard7854b052003-03-29 17:22:23 +00001373 {
bellard2f619692007-11-16 10:46:05 +00001374 int sockfd, backlog;
1375
1376 if (get_user_s32(sockfd, vptr)
1377 || get_user_s32(backlog, vptr + n))
1378 return -TARGET_EFAULT;
1379
bellard7854b052003-03-29 17:22:23 +00001380 ret = get_errno(listen(sockfd, backlog));
1381 }
bellard31e31b82003-02-18 22:55:36 +00001382 break;
1383 case SOCKOP_accept:
1384 {
bellard2f619692007-11-16 10:46:05 +00001385 int sockfd;
1386 abi_ulong target_addr, target_addrlen;
1387
1388 if (get_user_s32(sockfd, vptr)
1389 || get_user_ual(target_addr, vptr + n)
1390 || get_user_u32(target_addrlen, vptr + 2 * n))
1391 return -TARGET_EFAULT;
1392
pbrook1be9e1d2006-11-19 15:26:04 +00001393 ret = do_accept(sockfd, target_addr, target_addrlen);
bellard31e31b82003-02-18 22:55:36 +00001394 }
1395 break;
1396 case SOCKOP_getsockname:
1397 {
bellard2f619692007-11-16 10:46:05 +00001398 int sockfd;
1399 abi_ulong target_addr, target_addrlen;
1400
1401 if (get_user_s32(sockfd, vptr)
1402 || get_user_ual(target_addr, vptr + n)
1403 || get_user_u32(target_addrlen, vptr + 2 * n))
1404 return -TARGET_EFAULT;
1405
pbrook1be9e1d2006-11-19 15:26:04 +00001406 ret = do_getsockname(sockfd, target_addr, target_addrlen);
bellard31e31b82003-02-18 22:55:36 +00001407 }
1408 break;
1409 case SOCKOP_getpeername:
1410 {
bellard2f619692007-11-16 10:46:05 +00001411 int sockfd;
1412 abi_ulong target_addr, target_addrlen;
1413
1414 if (get_user_s32(sockfd, vptr)
1415 || get_user_ual(target_addr, vptr + n)
1416 || get_user_u32(target_addrlen, vptr + 2 * n))
1417 return -TARGET_EFAULT;
1418
pbrook1be9e1d2006-11-19 15:26:04 +00001419 ret = do_getpeername(sockfd, target_addr, target_addrlen);
bellard31e31b82003-02-18 22:55:36 +00001420 }
1421 break;
1422 case SOCKOP_socketpair:
1423 {
bellard2f619692007-11-16 10:46:05 +00001424 int domain, type, protocol;
1425 abi_ulong tab;
1426
1427 if (get_user_s32(domain, vptr)
1428 || get_user_s32(type, vptr + n)
1429 || get_user_s32(protocol, vptr + 2 * n)
1430 || get_user_ual(tab, vptr + 3 * n))
1431 return -TARGET_EFAULT;
1432
pbrook1be9e1d2006-11-19 15:26:04 +00001433 ret = do_socketpair(domain, type, protocol, tab);
bellard31e31b82003-02-18 22:55:36 +00001434 }
1435 break;
1436 case SOCKOP_send:
bellard7854b052003-03-29 17:22:23 +00001437 {
bellard2f619692007-11-16 10:46:05 +00001438 int sockfd;
1439 abi_ulong msg;
1440 size_t len;
1441 int flags;
1442
1443 if (get_user_s32(sockfd, vptr)
1444 || get_user_ual(msg, vptr + n)
1445 || get_user_ual(len, vptr + 2 * n)
1446 || get_user_s32(flags, vptr + 3 * n))
1447 return -TARGET_EFAULT;
1448
pbrook1be9e1d2006-11-19 15:26:04 +00001449 ret = do_sendto(sockfd, msg, len, flags, 0, 0);
bellard7854b052003-03-29 17:22:23 +00001450 }
bellard31e31b82003-02-18 22:55:36 +00001451 break;
1452 case SOCKOP_recv:
bellard7854b052003-03-29 17:22:23 +00001453 {
bellard2f619692007-11-16 10:46:05 +00001454 int sockfd;
1455 abi_ulong msg;
1456 size_t len;
1457 int flags;
1458
1459 if (get_user_s32(sockfd, vptr)
1460 || get_user_ual(msg, vptr + n)
1461 || get_user_ual(len, vptr + 2 * n)
1462 || get_user_s32(flags, vptr + 3 * n))
1463 return -TARGET_EFAULT;
1464
pbrook1be9e1d2006-11-19 15:26:04 +00001465 ret = do_recvfrom(sockfd, msg, len, flags, 0, 0);
bellard7854b052003-03-29 17:22:23 +00001466 }
bellard31e31b82003-02-18 22:55:36 +00001467 break;
1468 case SOCKOP_sendto:
bellard7854b052003-03-29 17:22:23 +00001469 {
bellard2f619692007-11-16 10:46:05 +00001470 int sockfd;
1471 abi_ulong msg;
1472 size_t len;
1473 int flags;
1474 abi_ulong addr;
1475 socklen_t addrlen;
1476
1477 if (get_user_s32(sockfd, vptr)
1478 || get_user_ual(msg, vptr + n)
1479 || get_user_ual(len, vptr + 2 * n)
1480 || get_user_s32(flags, vptr + 3 * n)
1481 || get_user_ual(addr, vptr + 4 * n)
1482 || get_user_u32(addrlen, vptr + 5 * n))
1483 return -TARGET_EFAULT;
1484
pbrook1be9e1d2006-11-19 15:26:04 +00001485 ret = do_sendto(sockfd, msg, len, flags, addr, addrlen);
bellard7854b052003-03-29 17:22:23 +00001486 }
bellard31e31b82003-02-18 22:55:36 +00001487 break;
1488 case SOCKOP_recvfrom:
1489 {
bellard2f619692007-11-16 10:46:05 +00001490 int sockfd;
1491 abi_ulong msg;
1492 size_t len;
1493 int flags;
1494 abi_ulong addr;
1495 socklen_t addrlen;
1496
1497 if (get_user_s32(sockfd, vptr)
1498 || get_user_ual(msg, vptr + n)
1499 || get_user_ual(len, vptr + 2 * n)
1500 || get_user_s32(flags, vptr + 3 * n)
1501 || get_user_ual(addr, vptr + 4 * n)
1502 || get_user_u32(addrlen, vptr + 5 * n))
1503 return -TARGET_EFAULT;
1504
pbrook1be9e1d2006-11-19 15:26:04 +00001505 ret = do_recvfrom(sockfd, msg, len, flags, addr, addrlen);
bellard31e31b82003-02-18 22:55:36 +00001506 }
1507 break;
1508 case SOCKOP_shutdown:
bellard7854b052003-03-29 17:22:23 +00001509 {
bellard2f619692007-11-16 10:46:05 +00001510 int sockfd, how;
1511
1512 if (get_user_s32(sockfd, vptr)
1513 || get_user_s32(how, vptr + n))
1514 return -TARGET_EFAULT;
bellard7854b052003-03-29 17:22:23 +00001515
1516 ret = get_errno(shutdown(sockfd, how));
1517 }
bellard31e31b82003-02-18 22:55:36 +00001518 break;
1519 case SOCKOP_sendmsg:
1520 case SOCKOP_recvmsg:
bellard1a9353d2003-03-16 20:28:50 +00001521 {
1522 int fd;
blueswir1992f48a2007-10-14 16:27:31 +00001523 abi_ulong target_msg;
bellard3532fa72006-06-24 15:06:03 +00001524 int flags;
bellard1a9353d2003-03-16 20:28:50 +00001525
bellard2f619692007-11-16 10:46:05 +00001526 if (get_user_s32(fd, vptr)
1527 || get_user_ual(target_msg, vptr + n)
1528 || get_user_s32(flags, vptr + 2 * n))
1529 return -TARGET_EFAULT;
bellard3532fa72006-06-24 15:06:03 +00001530
ths5fafdf22007-09-16 21:08:06 +00001531 ret = do_sendrecvmsg(fd, target_msg, flags,
bellard3532fa72006-06-24 15:06:03 +00001532 (num == SOCKOP_sendmsg));
bellard1a9353d2003-03-16 20:28:50 +00001533 }
1534 break;
bellard31e31b82003-02-18 22:55:36 +00001535 case SOCKOP_setsockopt:
bellard7854b052003-03-29 17:22:23 +00001536 {
bellard2f619692007-11-16 10:46:05 +00001537 int sockfd;
1538 int level;
1539 int optname;
1540 abi_ulong optval;
1541 socklen_t optlen;
1542
1543 if (get_user_s32(sockfd, vptr)
1544 || get_user_s32(level, vptr + n)
1545 || get_user_s32(optname, vptr + 2 * n)
1546 || get_user_ual(optval, vptr + 3 * n)
1547 || get_user_u32(optlen, vptr + 4 * n))
1548 return -TARGET_EFAULT;
bellard7854b052003-03-29 17:22:23 +00001549
1550 ret = do_setsockopt(sockfd, level, optname, optval, optlen);
1551 }
1552 break;
bellard31e31b82003-02-18 22:55:36 +00001553 case SOCKOP_getsockopt:
bellard7854b052003-03-29 17:22:23 +00001554 {
bellard2f619692007-11-16 10:46:05 +00001555 int sockfd;
1556 int level;
1557 int optname;
1558 abi_ulong optval;
1559 socklen_t optlen;
bellard7854b052003-03-29 17:22:23 +00001560
bellard2f619692007-11-16 10:46:05 +00001561 if (get_user_s32(sockfd, vptr)
1562 || get_user_s32(level, vptr + n)
1563 || get_user_s32(optname, vptr + 2 * n)
1564 || get_user_ual(optval, vptr + 3 * n)
1565 || get_user_u32(optlen, vptr + 4 * n))
1566 return -TARGET_EFAULT;
1567
1568 ret = do_getsockopt(sockfd, level, optname, optval, optlen);
bellard7854b052003-03-29 17:22:23 +00001569 }
1570 break;
bellard31e31b82003-02-18 22:55:36 +00001571 default:
1572 gemu_log("Unsupported socketcall: %d\n", num);
ths0da46a62007-10-20 20:23:07 +00001573 ret = -TARGET_ENOSYS;
bellard31e31b82003-02-18 22:55:36 +00001574 break;
1575 }
1576 return ret;
1577}
j_mayer32407102007-09-26 23:01:49 +00001578#endif
bellard31e31b82003-02-18 22:55:36 +00001579
j_mayer32407102007-09-26 23:01:49 +00001580#ifdef TARGET_NR_ipc
bellard8853f862004-02-22 14:57:26 +00001581#define N_SHM_REGIONS 32
1582
1583static struct shm_region {
bellard5a4a8982007-11-11 17:39:18 +00001584 abi_ulong start;
1585 abi_ulong size;
bellard8853f862004-02-22 14:57:26 +00001586} shm_regions[N_SHM_REGIONS];
1587
ths3eb6b042007-06-03 14:26:27 +00001588struct target_ipc_perm
1589{
blueswir1992f48a2007-10-14 16:27:31 +00001590 abi_long __key;
1591 abi_ulong uid;
1592 abi_ulong gid;
1593 abi_ulong cuid;
1594 abi_ulong cgid;
ths3eb6b042007-06-03 14:26:27 +00001595 unsigned short int mode;
1596 unsigned short int __pad1;
1597 unsigned short int __seq;
1598 unsigned short int __pad2;
blueswir1992f48a2007-10-14 16:27:31 +00001599 abi_ulong __unused1;
1600 abi_ulong __unused2;
ths3eb6b042007-06-03 14:26:27 +00001601};
1602
1603struct target_semid_ds
1604{
1605 struct target_ipc_perm sem_perm;
blueswir1992f48a2007-10-14 16:27:31 +00001606 abi_ulong sem_otime;
1607 abi_ulong __unused1;
1608 abi_ulong sem_ctime;
1609 abi_ulong __unused2;
1610 abi_ulong sem_nsems;
1611 abi_ulong __unused3;
1612 abi_ulong __unused4;
ths3eb6b042007-06-03 14:26:27 +00001613};
1614
bellard579a97f2007-11-11 14:26:47 +00001615static inline abi_long target_to_host_ipc_perm(struct ipc_perm *host_ip,
1616 abi_ulong target_addr)
ths3eb6b042007-06-03 14:26:27 +00001617{
1618 struct target_ipc_perm *target_ip;
1619 struct target_semid_ds *target_sd;
1620
bellard579a97f2007-11-11 14:26:47 +00001621 if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
1622 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00001623 target_ip=&(target_sd->sem_perm);
1624 host_ip->__key = tswapl(target_ip->__key);
1625 host_ip->uid = tswapl(target_ip->uid);
1626 host_ip->gid = tswapl(target_ip->gid);
1627 host_ip->cuid = tswapl(target_ip->cuid);
1628 host_ip->cgid = tswapl(target_ip->cgid);
1629 host_ip->mode = tswapl(target_ip->mode);
1630 unlock_user_struct(target_sd, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00001631 return 0;
ths3eb6b042007-06-03 14:26:27 +00001632}
1633
bellard579a97f2007-11-11 14:26:47 +00001634static inline abi_long host_to_target_ipc_perm(abi_ulong target_addr,
1635 struct ipc_perm *host_ip)
ths3eb6b042007-06-03 14:26:27 +00001636{
1637 struct target_ipc_perm *target_ip;
1638 struct target_semid_ds *target_sd;
1639
bellard579a97f2007-11-11 14:26:47 +00001640 if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
1641 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00001642 target_ip = &(target_sd->sem_perm);
1643 target_ip->__key = tswapl(host_ip->__key);
1644 target_ip->uid = tswapl(host_ip->uid);
1645 target_ip->gid = tswapl(host_ip->gid);
1646 target_ip->cuid = tswapl(host_ip->cuid);
1647 target_ip->cgid = tswapl(host_ip->cgid);
1648 target_ip->mode = tswapl(host_ip->mode);
1649 unlock_user_struct(target_sd, target_addr, 1);
bellard579a97f2007-11-11 14:26:47 +00001650 return 0;
ths3eb6b042007-06-03 14:26:27 +00001651}
1652
bellard579a97f2007-11-11 14:26:47 +00001653static inline abi_long target_to_host_semid_ds(struct semid_ds *host_sd,
1654 abi_ulong target_addr)
ths3eb6b042007-06-03 14:26:27 +00001655{
1656 struct target_semid_ds *target_sd;
1657
bellard579a97f2007-11-11 14:26:47 +00001658 if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
1659 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00001660 target_to_host_ipc_perm(&(host_sd->sem_perm),target_addr);
1661 host_sd->sem_nsems = tswapl(target_sd->sem_nsems);
1662 host_sd->sem_otime = tswapl(target_sd->sem_otime);
1663 host_sd->sem_ctime = tswapl(target_sd->sem_ctime);
1664 unlock_user_struct(target_sd, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00001665 return 0;
ths3eb6b042007-06-03 14:26:27 +00001666}
1667
bellard579a97f2007-11-11 14:26:47 +00001668static inline abi_long host_to_target_semid_ds(abi_ulong target_addr,
1669 struct semid_ds *host_sd)
ths3eb6b042007-06-03 14:26:27 +00001670{
1671 struct target_semid_ds *target_sd;
1672
bellard579a97f2007-11-11 14:26:47 +00001673 if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
1674 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00001675 host_to_target_ipc_perm(target_addr,&(host_sd->sem_perm));
1676 target_sd->sem_nsems = tswapl(host_sd->sem_nsems);
1677 target_sd->sem_otime = tswapl(host_sd->sem_otime);
1678 target_sd->sem_ctime = tswapl(host_sd->sem_ctime);
1679 unlock_user_struct(target_sd, target_addr, 1);
bellard579a97f2007-11-11 14:26:47 +00001680 return 0;
ths3eb6b042007-06-03 14:26:27 +00001681}
1682
thsfa294812007-02-02 22:05:00 +00001683union semun {
1684 int val;
ths3eb6b042007-06-03 14:26:27 +00001685 struct semid_ds *buf;
thsfa294812007-02-02 22:05:00 +00001686 unsigned short *array;
1687};
1688
ths3eb6b042007-06-03 14:26:27 +00001689union target_semun {
1690 int val;
blueswir1992f48a2007-10-14 16:27:31 +00001691 abi_long buf;
ths3eb6b042007-06-03 14:26:27 +00001692 unsigned short int *array;
1693};
1694
bellard579a97f2007-11-11 14:26:47 +00001695static inline abi_long target_to_host_semun(int cmd,
1696 union semun *host_su,
1697 abi_ulong target_addr,
1698 struct semid_ds *ds)
ths3eb6b042007-06-03 14:26:27 +00001699{
1700 union target_semun *target_su;
1701
1702 switch( cmd ) {
1703 case IPC_STAT:
1704 case IPC_SET:
bellard579a97f2007-11-11 14:26:47 +00001705 if (!lock_user_struct(VERIFY_READ, target_su, target_addr, 1))
1706 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00001707 target_to_host_semid_ds(ds,target_su->buf);
1708 host_su->buf = ds;
1709 unlock_user_struct(target_su, target_addr, 0);
1710 break;
1711 case GETVAL:
1712 case SETVAL:
bellard579a97f2007-11-11 14:26:47 +00001713 if (!lock_user_struct(VERIFY_READ, target_su, target_addr, 1))
1714 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00001715 host_su->val = tswapl(target_su->val);
1716 unlock_user_struct(target_su, target_addr, 0);
1717 break;
1718 case GETALL:
1719 case SETALL:
bellard579a97f2007-11-11 14:26:47 +00001720 if (!lock_user_struct(VERIFY_READ, target_su, target_addr, 1))
1721 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00001722 *host_su->array = tswap16(*target_su->array);
1723 unlock_user_struct(target_su, target_addr, 0);
1724 break;
1725 default:
1726 gemu_log("semun operation not fully supported: %d\n", (int)cmd);
1727 }
bellard579a97f2007-11-11 14:26:47 +00001728 return 0;
ths3eb6b042007-06-03 14:26:27 +00001729}
1730
bellard579a97f2007-11-11 14:26:47 +00001731static inline abi_long host_to_target_semun(int cmd,
1732 abi_ulong target_addr,
1733 union semun *host_su,
1734 struct semid_ds *ds)
ths3eb6b042007-06-03 14:26:27 +00001735{
1736 union target_semun *target_su;
1737
1738 switch( cmd ) {
1739 case IPC_STAT:
1740 case IPC_SET:
bellard579a97f2007-11-11 14:26:47 +00001741 if (lock_user_struct(VERIFY_WRITE, target_su, target_addr, 0))
1742 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00001743 host_to_target_semid_ds(target_su->buf,ds);
1744 unlock_user_struct(target_su, target_addr, 1);
1745 break;
1746 case GETVAL:
1747 case SETVAL:
bellard579a97f2007-11-11 14:26:47 +00001748 if (lock_user_struct(VERIFY_WRITE, target_su, target_addr, 0))
1749 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00001750 target_su->val = tswapl(host_su->val);
1751 unlock_user_struct(target_su, target_addr, 1);
1752 break;
1753 case GETALL:
1754 case SETALL:
bellard579a97f2007-11-11 14:26:47 +00001755 if (lock_user_struct(VERIFY_WRITE, target_su, target_addr, 0))
1756 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00001757 *target_su->array = tswap16(*host_su->array);
1758 unlock_user_struct(target_su, target_addr, 1);
1759 break;
1760 default:
1761 gemu_log("semun operation not fully supported: %d\n", (int)cmd);
1762 }
bellard579a97f2007-11-11 14:26:47 +00001763 return 0;
ths3eb6b042007-06-03 14:26:27 +00001764}
1765
blueswir1992f48a2007-10-14 16:27:31 +00001766static inline abi_long do_semctl(int first, int second, int third,
1767 abi_long ptr)
ths3eb6b042007-06-03 14:26:27 +00001768{
1769 union semun arg;
1770 struct semid_ds dsarg;
1771 int cmd = third&0xff;
blueswir1992f48a2007-10-14 16:27:31 +00001772 abi_long ret = 0;
ths3eb6b042007-06-03 14:26:27 +00001773
1774 switch( cmd ) {
1775 case GETVAL:
1776 target_to_host_semun(cmd,&arg,ptr,&dsarg);
1777 ret = get_errno(semctl(first, second, cmd, arg));
1778 host_to_target_semun(cmd,ptr,&arg,&dsarg);
1779 break;
1780 case SETVAL:
1781 target_to_host_semun(cmd,&arg,ptr,&dsarg);
1782 ret = get_errno(semctl(first, second, cmd, arg));
1783 host_to_target_semun(cmd,ptr,&arg,&dsarg);
1784 break;
1785 case GETALL:
1786 target_to_host_semun(cmd,&arg,ptr,&dsarg);
1787 ret = get_errno(semctl(first, second, cmd, arg));
1788 host_to_target_semun(cmd,ptr,&arg,&dsarg);
1789 break;
1790 case SETALL:
1791 target_to_host_semun(cmd,&arg,ptr,&dsarg);
1792 ret = get_errno(semctl(first, second, cmd, arg));
1793 host_to_target_semun(cmd,ptr,&arg,&dsarg);
1794 break;
1795 case IPC_STAT:
1796 target_to_host_semun(cmd,&arg,ptr,&dsarg);
1797 ret = get_errno(semctl(first, second, cmd, arg));
1798 host_to_target_semun(cmd,ptr,&arg,&dsarg);
1799 break;
1800 case IPC_SET:
1801 target_to_host_semun(cmd,&arg,ptr,&dsarg);
1802 ret = get_errno(semctl(first, second, cmd, arg));
1803 host_to_target_semun(cmd,ptr,&arg,&dsarg);
1804 break;
1805 default:
1806 ret = get_errno(semctl(first, second, cmd, arg));
1807 }
1808
1809 return ret;
1810}
1811
ths1bc012f2007-06-03 14:27:49 +00001812struct target_msqid_ds
1813{
1814 struct target_ipc_perm msg_perm;
blueswir1992f48a2007-10-14 16:27:31 +00001815 abi_ulong msg_stime;
1816 abi_ulong __unused1;
1817 abi_ulong msg_rtime;
1818 abi_ulong __unused2;
1819 abi_ulong msg_ctime;
1820 abi_ulong __unused3;
1821 abi_ulong __msg_cbytes;
1822 abi_ulong msg_qnum;
1823 abi_ulong msg_qbytes;
1824 abi_ulong msg_lspid;
1825 abi_ulong msg_lrpid;
1826 abi_ulong __unused4;
1827 abi_ulong __unused5;
ths1bc012f2007-06-03 14:27:49 +00001828};
1829
bellard579a97f2007-11-11 14:26:47 +00001830static inline abi_long target_to_host_msqid_ds(struct msqid_ds *host_md,
1831 abi_ulong target_addr)
ths1bc012f2007-06-03 14:27:49 +00001832{
1833 struct target_msqid_ds *target_md;
1834
bellard579a97f2007-11-11 14:26:47 +00001835 if (!lock_user_struct(VERIFY_READ, target_md, target_addr, 1))
1836 return -TARGET_EFAULT;
ths1bc012f2007-06-03 14:27:49 +00001837 target_to_host_ipc_perm(&(host_md->msg_perm),target_addr);
1838 host_md->msg_stime = tswapl(target_md->msg_stime);
1839 host_md->msg_rtime = tswapl(target_md->msg_rtime);
1840 host_md->msg_ctime = tswapl(target_md->msg_ctime);
1841 host_md->__msg_cbytes = tswapl(target_md->__msg_cbytes);
1842 host_md->msg_qnum = tswapl(target_md->msg_qnum);
1843 host_md->msg_qbytes = tswapl(target_md->msg_qbytes);
1844 host_md->msg_lspid = tswapl(target_md->msg_lspid);
1845 host_md->msg_lrpid = tswapl(target_md->msg_lrpid);
1846 unlock_user_struct(target_md, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00001847 return 0;
ths1bc012f2007-06-03 14:27:49 +00001848}
1849
bellard579a97f2007-11-11 14:26:47 +00001850static inline abi_long host_to_target_msqid_ds(abi_ulong target_addr,
1851 struct msqid_ds *host_md)
ths1bc012f2007-06-03 14:27:49 +00001852{
1853 struct target_msqid_ds *target_md;
1854
bellard579a97f2007-11-11 14:26:47 +00001855 if (!lock_user_struct(VERIFY_WRITE, target_md, target_addr, 0))
1856 return -TARGET_EFAULT;
ths1bc012f2007-06-03 14:27:49 +00001857 host_to_target_ipc_perm(target_addr,&(host_md->msg_perm));
1858 target_md->msg_stime = tswapl(host_md->msg_stime);
1859 target_md->msg_rtime = tswapl(host_md->msg_rtime);
1860 target_md->msg_ctime = tswapl(host_md->msg_ctime);
1861 target_md->__msg_cbytes = tswapl(host_md->__msg_cbytes);
1862 target_md->msg_qnum = tswapl(host_md->msg_qnum);
1863 target_md->msg_qbytes = tswapl(host_md->msg_qbytes);
1864 target_md->msg_lspid = tswapl(host_md->msg_lspid);
1865 target_md->msg_lrpid = tswapl(host_md->msg_lrpid);
1866 unlock_user_struct(target_md, target_addr, 1);
bellard579a97f2007-11-11 14:26:47 +00001867 return 0;
ths1bc012f2007-06-03 14:27:49 +00001868}
1869
blueswir1992f48a2007-10-14 16:27:31 +00001870static inline abi_long do_msgctl(int first, int second, abi_long ptr)
ths1bc012f2007-06-03 14:27:49 +00001871{
1872 struct msqid_ds dsarg;
1873 int cmd = second&0xff;
blueswir1992f48a2007-10-14 16:27:31 +00001874 abi_long ret = 0;
ths1bc012f2007-06-03 14:27:49 +00001875 switch( cmd ) {
1876 case IPC_STAT:
1877 case IPC_SET:
1878 target_to_host_msqid_ds(&dsarg,ptr);
1879 ret = get_errno(msgctl(first, cmd, &dsarg));
1880 host_to_target_msqid_ds(ptr,&dsarg);
1881 default:
1882 ret = get_errno(msgctl(first, cmd, &dsarg));
1883 }
1884 return ret;
1885}
1886
1887struct target_msgbuf {
blueswir1992f48a2007-10-14 16:27:31 +00001888 abi_ulong mtype;
ths1bc012f2007-06-03 14:27:49 +00001889 char mtext[1];
1890};
1891
blueswir1992f48a2007-10-14 16:27:31 +00001892static inline abi_long do_msgsnd(int msqid, abi_long msgp,
1893 unsigned int msgsz, int msgflg)
ths1bc012f2007-06-03 14:27:49 +00001894{
1895 struct target_msgbuf *target_mb;
1896 struct msgbuf *host_mb;
blueswir1992f48a2007-10-14 16:27:31 +00001897 abi_long ret = 0;
ths1bc012f2007-06-03 14:27:49 +00001898
bellard579a97f2007-11-11 14:26:47 +00001899 if (!lock_user_struct(VERIFY_READ, target_mb, msgp, 0))
1900 return -TARGET_EFAULT;
ths1bc012f2007-06-03 14:27:49 +00001901 host_mb = malloc(msgsz+sizeof(long));
1902 host_mb->mtype = tswapl(target_mb->mtype);
1903 memcpy(host_mb->mtext,target_mb->mtext,msgsz);
1904 ret = get_errno(msgsnd(msqid, host_mb, msgsz, msgflg));
1905 free(host_mb);
1906 unlock_user_struct(target_mb, msgp, 0);
1907
1908 return ret;
1909}
1910
blueswir1992f48a2007-10-14 16:27:31 +00001911static inline abi_long do_msgrcv(int msqid, abi_long msgp,
1912 unsigned int msgsz, int msgtype,
1913 int msgflg)
ths1bc012f2007-06-03 14:27:49 +00001914{
1915 struct target_msgbuf *target_mb;
bellard579a97f2007-11-11 14:26:47 +00001916 char *target_mtext;
ths1bc012f2007-06-03 14:27:49 +00001917 struct msgbuf *host_mb;
blueswir1992f48a2007-10-14 16:27:31 +00001918 abi_long ret = 0;
ths1bc012f2007-06-03 14:27:49 +00001919
bellard579a97f2007-11-11 14:26:47 +00001920 if (!lock_user_struct(VERIFY_WRITE, target_mb, msgp, 0))
1921 return -TARGET_EFAULT;
ths1bc012f2007-06-03 14:27:49 +00001922 host_mb = malloc(msgsz+sizeof(long));
1923 ret = get_errno(msgrcv(msqid, host_mb, msgsz, 1, msgflg));
bellard579a97f2007-11-11 14:26:47 +00001924 if (ret > 0) {
1925 abi_ulong target_mtext_addr = msgp + sizeof(abi_ulong);
1926 target_mtext = lock_user(VERIFY_WRITE, target_mtext_addr, ret, 0);
1927 if (!target_mtext) {
1928 ret = -TARGET_EFAULT;
1929 goto end;
1930 }
ths1bc012f2007-06-03 14:27:49 +00001931 memcpy(target_mb->mtext, host_mb->mtext, ret);
bellard579a97f2007-11-11 14:26:47 +00001932 unlock_user(target_mtext, target_mtext_addr, ret);
1933 }
ths1bc012f2007-06-03 14:27:49 +00001934 target_mb->mtype = tswapl(host_mb->mtype);
1935 free(host_mb);
ths1bc012f2007-06-03 14:27:49 +00001936
bellard579a97f2007-11-11 14:26:47 +00001937end:
1938 if (target_mb)
1939 unlock_user_struct(target_mb, msgp, 1);
ths1bc012f2007-06-03 14:27:49 +00001940 return ret;
1941}
1942
pbrook53a59602006-03-25 19:31:22 +00001943/* ??? This only works with linear mappings. */
ths0da46a62007-10-20 20:23:07 +00001944/* do_ipc() must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001945static abi_long do_ipc(unsigned int call, int first,
1946 int second, int third,
1947 abi_long ptr, abi_long fifth)
bellard8853f862004-02-22 14:57:26 +00001948{
1949 int version;
blueswir1992f48a2007-10-14 16:27:31 +00001950 abi_long ret = 0;
bellard8853f862004-02-22 14:57:26 +00001951 struct shmid_ds shm_info;
1952 int i;
1953
1954 version = call >> 16;
1955 call &= 0xffff;
1956
1957 switch (call) {
thsfa294812007-02-02 22:05:00 +00001958 case IPCOP_semop:
bellard579a97f2007-11-11 14:26:47 +00001959 ret = get_errno(semop(first,(struct sembuf *)g2h(ptr), second));
thsfa294812007-02-02 22:05:00 +00001960 break;
1961
1962 case IPCOP_semget:
1963 ret = get_errno(semget(first, second, third));
1964 break;
1965
1966 case IPCOP_semctl:
ths3eb6b042007-06-03 14:26:27 +00001967 ret = do_semctl(first, second, third, ptr);
thsfa294812007-02-02 22:05:00 +00001968 break;
1969
1970 case IPCOP_semtimedop:
j_mayer32407102007-09-26 23:01:49 +00001971 gemu_log("Unsupported ipc call: %d (version %d)\n", call, version);
ths0da46a62007-10-20 20:23:07 +00001972 ret = -TARGET_ENOSYS;
thsfa294812007-02-02 22:05:00 +00001973 break;
thsd96372e2007-02-02 22:05:44 +00001974
1975 case IPCOP_msgget:
1976 ret = get_errno(msgget(first, second));
1977 break;
1978
1979 case IPCOP_msgsnd:
ths1bc012f2007-06-03 14:27:49 +00001980 ret = do_msgsnd(first, ptr, second, third);
thsd96372e2007-02-02 22:05:44 +00001981 break;
1982
1983 case IPCOP_msgctl:
ths1bc012f2007-06-03 14:27:49 +00001984 ret = do_msgctl(first, second, ptr);
thsd96372e2007-02-02 22:05:44 +00001985 break;
1986
1987 case IPCOP_msgrcv:
ths1bc012f2007-06-03 14:27:49 +00001988 {
bellard579a97f2007-11-11 14:26:47 +00001989 /* XXX: this code is not correct */
ths1bc012f2007-06-03 14:27:49 +00001990 struct ipc_kludge
1991 {
1992 void *__unbounded msgp;
1993 long int msgtyp;
1994 };
thsd96372e2007-02-02 22:05:44 +00001995
bellard579a97f2007-11-11 14:26:47 +00001996 struct ipc_kludge *foo = (struct ipc_kludge *)g2h(ptr);
ths1bc012f2007-06-03 14:27:49 +00001997 struct msgbuf *msgp = (struct msgbuf *) foo->msgp;
thsd96372e2007-02-02 22:05:44 +00001998
ths1bc012f2007-06-03 14:27:49 +00001999 ret = do_msgrcv(first, (long)msgp, second, 0, third);
thsd96372e2007-02-02 22:05:44 +00002000
ths1bc012f2007-06-03 14:27:49 +00002001 }
thsd96372e2007-02-02 22:05:44 +00002002 break;
2003
bellard8853f862004-02-22 14:57:26 +00002004 case IPCOP_shmat:
bellard5a4a8982007-11-11 17:39:18 +00002005 {
2006 abi_ulong raddr;
2007 void *host_addr;
2008 /* SHM_* flags are the same on all linux platforms */
2009 host_addr = shmat(first, (void *)g2h(ptr), second);
2010 if (host_addr == (void *)-1) {
2011 ret = get_errno((long)host_addr);
bellard8853f862004-02-22 14:57:26 +00002012 break;
bellard5a4a8982007-11-11 17:39:18 +00002013 }
2014 raddr = h2g((unsigned long)host_addr);
2015 /* find out the length of the shared memory segment */
2016
2017 ret = get_errno(shmctl(first, IPC_STAT, &shm_info));
2018 if (is_error(ret)) {
2019 /* can't get length, bail out */
2020 shmdt(host_addr);
2021 break;
2022 }
2023 page_set_flags(raddr, raddr + shm_info.shm_segsz,
2024 PAGE_VALID | PAGE_READ |
2025 ((second & SHM_RDONLY)? 0: PAGE_WRITE));
2026 for (i = 0; i < N_SHM_REGIONS; ++i) {
2027 if (shm_regions[i].start == 0) {
2028 shm_regions[i].start = raddr;
2029 shm_regions[i].size = shm_info.shm_segsz;
2030 break;
2031 }
2032 }
bellard2f619692007-11-16 10:46:05 +00002033 if (put_user_ual(raddr, third))
bellard5a4a8982007-11-11 17:39:18 +00002034 return -TARGET_EFAULT;
2035 ret = 0;
2036 }
bellard8853f862004-02-22 14:57:26 +00002037 break;
2038 case IPCOP_shmdt:
2039 for (i = 0; i < N_SHM_REGIONS; ++i) {
2040 if (shm_regions[i].start == ptr) {
2041 shm_regions[i].start = 0;
2042 page_set_flags(ptr, shm_regions[i].size, 0);
2043 break;
2044 }
2045 }
bellard5a4a8982007-11-11 17:39:18 +00002046 ret = get_errno(shmdt((void *)g2h(ptr)));
bellard8853f862004-02-22 14:57:26 +00002047 break;
2048
2049 case IPCOP_shmget:
2050 /* IPC_* flag values are the same on all linux platforms */
2051 ret = get_errno(shmget(first, second, third));
2052 break;
2053
2054 /* IPC_* and SHM_* command values are the same on all linux platforms */
2055 case IPCOP_shmctl:
2056 switch(second) {
2057 case IPC_RMID:
2058 case SHM_LOCK:
2059 case SHM_UNLOCK:
2060 ret = get_errno(shmctl(first, second, NULL));
2061 break;
2062 default:
2063 goto unimplemented;
2064 }
2065 break;
2066 default:
2067 unimplemented:
j_mayer32407102007-09-26 23:01:49 +00002068 gemu_log("Unsupported ipc call: %d (version %d)\n", call, version);
ths0da46a62007-10-20 20:23:07 +00002069 ret = -TARGET_ENOSYS;
bellard8853f862004-02-22 14:57:26 +00002070 break;
2071 }
2072 return ret;
2073}
j_mayer32407102007-09-26 23:01:49 +00002074#endif
bellard8853f862004-02-22 14:57:26 +00002075
bellard31e31b82003-02-18 22:55:36 +00002076/* kernel structure types definitions */
2077#define IFNAMSIZ 16
2078
2079#define STRUCT(name, list...) STRUCT_ ## name,
2080#define STRUCT_SPECIAL(name) STRUCT_ ## name,
2081enum {
2082#include "syscall_types.h"
2083};
2084#undef STRUCT
2085#undef STRUCT_SPECIAL
2086
2087#define STRUCT(name, list...) const argtype struct_ ## name ## _def[] = { list, TYPE_NULL };
2088#define STRUCT_SPECIAL(name)
2089#include "syscall_types.h"
2090#undef STRUCT
2091#undef STRUCT_SPECIAL
2092
2093typedef struct IOCTLEntry {
bellard2ab83ea2003-06-15 19:56:46 +00002094 unsigned int target_cmd;
2095 unsigned int host_cmd;
bellard31e31b82003-02-18 22:55:36 +00002096 const char *name;
2097 int access;
bellard1a9353d2003-03-16 20:28:50 +00002098 const argtype arg_type[5];
bellard31e31b82003-02-18 22:55:36 +00002099} IOCTLEntry;
2100
2101#define IOC_R 0x0001
2102#define IOC_W 0x0002
2103#define IOC_RW (IOC_R | IOC_W)
2104
2105#define MAX_STRUCT_SIZE 4096
2106
bellard2ab83ea2003-06-15 19:56:46 +00002107IOCTLEntry ioctl_entries[] = {
bellard31e31b82003-02-18 22:55:36 +00002108#define IOCTL(cmd, access, types...) \
2109 { TARGET_ ## cmd, cmd, #cmd, access, { types } },
2110#include "ioctls.h"
2111 { 0, 0, },
2112};
2113
pbrook53a59602006-03-25 19:31:22 +00002114/* ??? Implement proper locking for ioctls. */
ths0da46a62007-10-20 20:23:07 +00002115/* do_ioctl() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00002116static abi_long do_ioctl(int fd, abi_long cmd, abi_long arg)
bellard31e31b82003-02-18 22:55:36 +00002117{
2118 const IOCTLEntry *ie;
2119 const argtype *arg_type;
blueswir1992f48a2007-10-14 16:27:31 +00002120 abi_long ret;
bellard31e31b82003-02-18 22:55:36 +00002121 uint8_t buf_temp[MAX_STRUCT_SIZE];
pbrook53a59602006-03-25 19:31:22 +00002122 int target_size;
2123 void *argptr;
bellard31e31b82003-02-18 22:55:36 +00002124
2125 ie = ioctl_entries;
2126 for(;;) {
2127 if (ie->target_cmd == 0) {
j_mayer32407102007-09-26 23:01:49 +00002128 gemu_log("Unsupported ioctl: cmd=0x%04lx\n", (long)cmd);
ths0da46a62007-10-20 20:23:07 +00002129 return -TARGET_ENOSYS;
bellard31e31b82003-02-18 22:55:36 +00002130 }
2131 if (ie->target_cmd == cmd)
2132 break;
2133 ie++;
2134 }
2135 arg_type = ie->arg_type;
bellard9de5e442003-03-23 16:49:39 +00002136#if defined(DEBUG)
j_mayer32407102007-09-26 23:01:49 +00002137 gemu_log("ioctl: cmd=0x%04lx (%s)\n", (long)cmd, ie->name);
bellard72f03902003-02-18 23:33:18 +00002138#endif
bellard31e31b82003-02-18 22:55:36 +00002139 switch(arg_type[0]) {
2140 case TYPE_NULL:
2141 /* no argument */
2142 ret = get_errno(ioctl(fd, ie->host_cmd));
2143 break;
2144 case TYPE_PTRVOID:
2145 case TYPE_INT:
2146 /* int argment */
2147 ret = get_errno(ioctl(fd, ie->host_cmd, arg));
2148 break;
2149 case TYPE_PTR:
2150 arg_type++;
pbrook53a59602006-03-25 19:31:22 +00002151 target_size = thunk_type_size(arg_type, 0);
bellard31e31b82003-02-18 22:55:36 +00002152 switch(ie->access) {
2153 case IOC_R:
2154 ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
2155 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00002156 argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
2157 if (!argptr)
2158 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00002159 thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
2160 unlock_user(argptr, arg, target_size);
bellard31e31b82003-02-18 22:55:36 +00002161 }
2162 break;
2163 case IOC_W:
bellard579a97f2007-11-11 14:26:47 +00002164 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
2165 if (!argptr)
2166 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00002167 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
2168 unlock_user(argptr, arg, 0);
bellard31e31b82003-02-18 22:55:36 +00002169 ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
2170 break;
2171 default:
2172 case IOC_RW:
bellard579a97f2007-11-11 14:26:47 +00002173 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
2174 if (!argptr)
2175 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00002176 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
2177 unlock_user(argptr, arg, 0);
bellard31e31b82003-02-18 22:55:36 +00002178 ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
2179 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00002180 argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
2181 if (!argptr)
2182 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00002183 thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
2184 unlock_user(argptr, arg, target_size);
bellard31e31b82003-02-18 22:55:36 +00002185 }
2186 break;
2187 }
2188 break;
2189 default:
j_mayer32407102007-09-26 23:01:49 +00002190 gemu_log("Unsupported ioctl type: cmd=0x%04lx type=%d\n",
2191 (long)cmd, arg_type[0]);
ths0da46a62007-10-20 20:23:07 +00002192 ret = -TARGET_ENOSYS;
bellard31e31b82003-02-18 22:55:36 +00002193 break;
2194 }
2195 return ret;
2196}
2197
2198bitmask_transtbl iflag_tbl[] = {
2199 { TARGET_IGNBRK, TARGET_IGNBRK, IGNBRK, IGNBRK },
2200 { TARGET_BRKINT, TARGET_BRKINT, BRKINT, BRKINT },
2201 { TARGET_IGNPAR, TARGET_IGNPAR, IGNPAR, IGNPAR },
2202 { TARGET_PARMRK, TARGET_PARMRK, PARMRK, PARMRK },
2203 { TARGET_INPCK, TARGET_INPCK, INPCK, INPCK },
2204 { TARGET_ISTRIP, TARGET_ISTRIP, ISTRIP, ISTRIP },
2205 { TARGET_INLCR, TARGET_INLCR, INLCR, INLCR },
2206 { TARGET_IGNCR, TARGET_IGNCR, IGNCR, IGNCR },
2207 { TARGET_ICRNL, TARGET_ICRNL, ICRNL, ICRNL },
2208 { TARGET_IUCLC, TARGET_IUCLC, IUCLC, IUCLC },
2209 { TARGET_IXON, TARGET_IXON, IXON, IXON },
2210 { TARGET_IXANY, TARGET_IXANY, IXANY, IXANY },
2211 { TARGET_IXOFF, TARGET_IXOFF, IXOFF, IXOFF },
2212 { TARGET_IMAXBEL, TARGET_IMAXBEL, IMAXBEL, IMAXBEL },
2213 { 0, 0, 0, 0 }
2214};
2215
2216bitmask_transtbl oflag_tbl[] = {
2217 { TARGET_OPOST, TARGET_OPOST, OPOST, OPOST },
2218 { TARGET_OLCUC, TARGET_OLCUC, OLCUC, OLCUC },
2219 { TARGET_ONLCR, TARGET_ONLCR, ONLCR, ONLCR },
2220 { TARGET_OCRNL, TARGET_OCRNL, OCRNL, OCRNL },
2221 { TARGET_ONOCR, TARGET_ONOCR, ONOCR, ONOCR },
2222 { TARGET_ONLRET, TARGET_ONLRET, ONLRET, ONLRET },
2223 { TARGET_OFILL, TARGET_OFILL, OFILL, OFILL },
2224 { TARGET_OFDEL, TARGET_OFDEL, OFDEL, OFDEL },
2225 { TARGET_NLDLY, TARGET_NL0, NLDLY, NL0 },
2226 { TARGET_NLDLY, TARGET_NL1, NLDLY, NL1 },
2227 { TARGET_CRDLY, TARGET_CR0, CRDLY, CR0 },
2228 { TARGET_CRDLY, TARGET_CR1, CRDLY, CR1 },
2229 { TARGET_CRDLY, TARGET_CR2, CRDLY, CR2 },
2230 { TARGET_CRDLY, TARGET_CR3, CRDLY, CR3 },
2231 { TARGET_TABDLY, TARGET_TAB0, TABDLY, TAB0 },
2232 { TARGET_TABDLY, TARGET_TAB1, TABDLY, TAB1 },
2233 { TARGET_TABDLY, TARGET_TAB2, TABDLY, TAB2 },
2234 { TARGET_TABDLY, TARGET_TAB3, TABDLY, TAB3 },
2235 { TARGET_BSDLY, TARGET_BS0, BSDLY, BS0 },
2236 { TARGET_BSDLY, TARGET_BS1, BSDLY, BS1 },
2237 { TARGET_VTDLY, TARGET_VT0, VTDLY, VT0 },
2238 { TARGET_VTDLY, TARGET_VT1, VTDLY, VT1 },
2239 { TARGET_FFDLY, TARGET_FF0, FFDLY, FF0 },
2240 { TARGET_FFDLY, TARGET_FF1, FFDLY, FF1 },
2241 { 0, 0, 0, 0 }
2242};
2243
2244bitmask_transtbl cflag_tbl[] = {
2245 { TARGET_CBAUD, TARGET_B0, CBAUD, B0 },
2246 { TARGET_CBAUD, TARGET_B50, CBAUD, B50 },
2247 { TARGET_CBAUD, TARGET_B75, CBAUD, B75 },
2248 { TARGET_CBAUD, TARGET_B110, CBAUD, B110 },
2249 { TARGET_CBAUD, TARGET_B134, CBAUD, B134 },
2250 { TARGET_CBAUD, TARGET_B150, CBAUD, B150 },
2251 { TARGET_CBAUD, TARGET_B200, CBAUD, B200 },
2252 { TARGET_CBAUD, TARGET_B300, CBAUD, B300 },
2253 { TARGET_CBAUD, TARGET_B600, CBAUD, B600 },
2254 { TARGET_CBAUD, TARGET_B1200, CBAUD, B1200 },
2255 { TARGET_CBAUD, TARGET_B1800, CBAUD, B1800 },
2256 { TARGET_CBAUD, TARGET_B2400, CBAUD, B2400 },
2257 { TARGET_CBAUD, TARGET_B4800, CBAUD, B4800 },
2258 { TARGET_CBAUD, TARGET_B9600, CBAUD, B9600 },
2259 { TARGET_CBAUD, TARGET_B19200, CBAUD, B19200 },
2260 { TARGET_CBAUD, TARGET_B38400, CBAUD, B38400 },
2261 { TARGET_CBAUD, TARGET_B57600, CBAUD, B57600 },
2262 { TARGET_CBAUD, TARGET_B115200, CBAUD, B115200 },
2263 { TARGET_CBAUD, TARGET_B230400, CBAUD, B230400 },
2264 { TARGET_CBAUD, TARGET_B460800, CBAUD, B460800 },
2265 { TARGET_CSIZE, TARGET_CS5, CSIZE, CS5 },
2266 { TARGET_CSIZE, TARGET_CS6, CSIZE, CS6 },
2267 { TARGET_CSIZE, TARGET_CS7, CSIZE, CS7 },
2268 { TARGET_CSIZE, TARGET_CS8, CSIZE, CS8 },
2269 { TARGET_CSTOPB, TARGET_CSTOPB, CSTOPB, CSTOPB },
2270 { TARGET_CREAD, TARGET_CREAD, CREAD, CREAD },
2271 { TARGET_PARENB, TARGET_PARENB, PARENB, PARENB },
2272 { TARGET_PARODD, TARGET_PARODD, PARODD, PARODD },
2273 { TARGET_HUPCL, TARGET_HUPCL, HUPCL, HUPCL },
2274 { TARGET_CLOCAL, TARGET_CLOCAL, CLOCAL, CLOCAL },
2275 { TARGET_CRTSCTS, TARGET_CRTSCTS, CRTSCTS, CRTSCTS },
2276 { 0, 0, 0, 0 }
2277};
2278
2279bitmask_transtbl lflag_tbl[] = {
2280 { TARGET_ISIG, TARGET_ISIG, ISIG, ISIG },
2281 { TARGET_ICANON, TARGET_ICANON, ICANON, ICANON },
2282 { TARGET_XCASE, TARGET_XCASE, XCASE, XCASE },
2283 { TARGET_ECHO, TARGET_ECHO, ECHO, ECHO },
2284 { TARGET_ECHOE, TARGET_ECHOE, ECHOE, ECHOE },
2285 { TARGET_ECHOK, TARGET_ECHOK, ECHOK, ECHOK },
2286 { TARGET_ECHONL, TARGET_ECHONL, ECHONL, ECHONL },
2287 { TARGET_NOFLSH, TARGET_NOFLSH, NOFLSH, NOFLSH },
2288 { TARGET_TOSTOP, TARGET_TOSTOP, TOSTOP, TOSTOP },
2289 { TARGET_ECHOCTL, TARGET_ECHOCTL, ECHOCTL, ECHOCTL },
2290 { TARGET_ECHOPRT, TARGET_ECHOPRT, ECHOPRT, ECHOPRT },
2291 { TARGET_ECHOKE, TARGET_ECHOKE, ECHOKE, ECHOKE },
2292 { TARGET_FLUSHO, TARGET_FLUSHO, FLUSHO, FLUSHO },
2293 { TARGET_PENDIN, TARGET_PENDIN, PENDIN, PENDIN },
2294 { TARGET_IEXTEN, TARGET_IEXTEN, IEXTEN, IEXTEN },
2295 { 0, 0, 0, 0 }
2296};
2297
2298static void target_to_host_termios (void *dst, const void *src)
2299{
2300 struct host_termios *host = dst;
2301 const struct target_termios *target = src;
ths3b46e622007-09-17 08:09:54 +00002302
ths5fafdf22007-09-16 21:08:06 +00002303 host->c_iflag =
bellard31e31b82003-02-18 22:55:36 +00002304 target_to_host_bitmask(tswap32(target->c_iflag), iflag_tbl);
ths5fafdf22007-09-16 21:08:06 +00002305 host->c_oflag =
bellard31e31b82003-02-18 22:55:36 +00002306 target_to_host_bitmask(tswap32(target->c_oflag), oflag_tbl);
ths5fafdf22007-09-16 21:08:06 +00002307 host->c_cflag =
bellard31e31b82003-02-18 22:55:36 +00002308 target_to_host_bitmask(tswap32(target->c_cflag), cflag_tbl);
ths5fafdf22007-09-16 21:08:06 +00002309 host->c_lflag =
bellard31e31b82003-02-18 22:55:36 +00002310 target_to_host_bitmask(tswap32(target->c_lflag), lflag_tbl);
2311 host->c_line = target->c_line;
ths3b46e622007-09-17 08:09:54 +00002312
ths5fafdf22007-09-16 21:08:06 +00002313 host->c_cc[VINTR] = target->c_cc[TARGET_VINTR];
2314 host->c_cc[VQUIT] = target->c_cc[TARGET_VQUIT];
ths3b46e622007-09-17 08:09:54 +00002315 host->c_cc[VERASE] = target->c_cc[TARGET_VERASE];
ths5fafdf22007-09-16 21:08:06 +00002316 host->c_cc[VKILL] = target->c_cc[TARGET_VKILL];
ths3b46e622007-09-17 08:09:54 +00002317 host->c_cc[VEOF] = target->c_cc[TARGET_VEOF];
ths5fafdf22007-09-16 21:08:06 +00002318 host->c_cc[VTIME] = target->c_cc[TARGET_VTIME];
ths3b46e622007-09-17 08:09:54 +00002319 host->c_cc[VMIN] = target->c_cc[TARGET_VMIN];
ths5fafdf22007-09-16 21:08:06 +00002320 host->c_cc[VSWTC] = target->c_cc[TARGET_VSWTC];
ths3b46e622007-09-17 08:09:54 +00002321 host->c_cc[VSTART] = target->c_cc[TARGET_VSTART];
ths5fafdf22007-09-16 21:08:06 +00002322 host->c_cc[VSTOP] = target->c_cc[TARGET_VSTOP];
2323 host->c_cc[VSUSP] = target->c_cc[TARGET_VSUSP];
ths3b46e622007-09-17 08:09:54 +00002324 host->c_cc[VEOL] = target->c_cc[TARGET_VEOL];
2325 host->c_cc[VREPRINT] = target->c_cc[TARGET_VREPRINT];
2326 host->c_cc[VDISCARD] = target->c_cc[TARGET_VDISCARD];
2327 host->c_cc[VWERASE] = target->c_cc[TARGET_VWERASE];
2328 host->c_cc[VLNEXT] = target->c_cc[TARGET_VLNEXT];
ths5fafdf22007-09-16 21:08:06 +00002329 host->c_cc[VEOL2] = target->c_cc[TARGET_VEOL2];
bellard31e31b82003-02-18 22:55:36 +00002330}
ths3b46e622007-09-17 08:09:54 +00002331
bellard31e31b82003-02-18 22:55:36 +00002332static void host_to_target_termios (void *dst, const void *src)
2333{
2334 struct target_termios *target = dst;
2335 const struct host_termios *host = src;
2336
ths5fafdf22007-09-16 21:08:06 +00002337 target->c_iflag =
bellard31e31b82003-02-18 22:55:36 +00002338 tswap32(host_to_target_bitmask(host->c_iflag, iflag_tbl));
ths5fafdf22007-09-16 21:08:06 +00002339 target->c_oflag =
bellard31e31b82003-02-18 22:55:36 +00002340 tswap32(host_to_target_bitmask(host->c_oflag, oflag_tbl));
ths5fafdf22007-09-16 21:08:06 +00002341 target->c_cflag =
bellard31e31b82003-02-18 22:55:36 +00002342 tswap32(host_to_target_bitmask(host->c_cflag, cflag_tbl));
ths5fafdf22007-09-16 21:08:06 +00002343 target->c_lflag =
bellard31e31b82003-02-18 22:55:36 +00002344 tswap32(host_to_target_bitmask(host->c_lflag, lflag_tbl));
2345 target->c_line = host->c_line;
ths3b46e622007-09-17 08:09:54 +00002346
bellard31e31b82003-02-18 22:55:36 +00002347 target->c_cc[TARGET_VINTR] = host->c_cc[VINTR];
2348 target->c_cc[TARGET_VQUIT] = host->c_cc[VQUIT];
2349 target->c_cc[TARGET_VERASE] = host->c_cc[VERASE];
2350 target->c_cc[TARGET_VKILL] = host->c_cc[VKILL];
2351 target->c_cc[TARGET_VEOF] = host->c_cc[VEOF];
2352 target->c_cc[TARGET_VTIME] = host->c_cc[VTIME];
2353 target->c_cc[TARGET_VMIN] = host->c_cc[VMIN];
2354 target->c_cc[TARGET_VSWTC] = host->c_cc[VSWTC];
2355 target->c_cc[TARGET_VSTART] = host->c_cc[VSTART];
2356 target->c_cc[TARGET_VSTOP] = host->c_cc[VSTOP];
2357 target->c_cc[TARGET_VSUSP] = host->c_cc[VSUSP];
2358 target->c_cc[TARGET_VEOL] = host->c_cc[VEOL];
2359 target->c_cc[TARGET_VREPRINT] = host->c_cc[VREPRINT];
2360 target->c_cc[TARGET_VDISCARD] = host->c_cc[VDISCARD];
2361 target->c_cc[TARGET_VWERASE] = host->c_cc[VWERASE];
2362 target->c_cc[TARGET_VLNEXT] = host->c_cc[VLNEXT];
2363 target->c_cc[TARGET_VEOL2] = host->c_cc[VEOL2];
2364}
2365
2366StructEntry struct_termios_def = {
2367 .convert = { host_to_target_termios, target_to_host_termios },
2368 .size = { sizeof(struct target_termios), sizeof(struct host_termios) },
2369 .align = { __alignof__(struct target_termios), __alignof__(struct host_termios) },
2370};
2371
bellard5286db72003-06-05 00:57:30 +00002372static bitmask_transtbl mmap_flags_tbl[] = {
2373 { TARGET_MAP_SHARED, TARGET_MAP_SHARED, MAP_SHARED, MAP_SHARED },
2374 { TARGET_MAP_PRIVATE, TARGET_MAP_PRIVATE, MAP_PRIVATE, MAP_PRIVATE },
2375 { TARGET_MAP_FIXED, TARGET_MAP_FIXED, MAP_FIXED, MAP_FIXED },
2376 { TARGET_MAP_ANONYMOUS, TARGET_MAP_ANONYMOUS, MAP_ANONYMOUS, MAP_ANONYMOUS },
2377 { TARGET_MAP_GROWSDOWN, TARGET_MAP_GROWSDOWN, MAP_GROWSDOWN, MAP_GROWSDOWN },
2378 { TARGET_MAP_DENYWRITE, TARGET_MAP_DENYWRITE, MAP_DENYWRITE, MAP_DENYWRITE },
2379 { TARGET_MAP_EXECUTABLE, TARGET_MAP_EXECUTABLE, MAP_EXECUTABLE, MAP_EXECUTABLE },
2380 { TARGET_MAP_LOCKED, TARGET_MAP_LOCKED, MAP_LOCKED, MAP_LOCKED },
2381 { 0, 0, 0, 0 }
2382};
2383
bellardffa65c32004-01-04 23:57:22 +00002384static bitmask_transtbl fcntl_flags_tbl[] = {
2385 { TARGET_O_ACCMODE, TARGET_O_WRONLY, O_ACCMODE, O_WRONLY, },
2386 { TARGET_O_ACCMODE, TARGET_O_RDWR, O_ACCMODE, O_RDWR, },
2387 { TARGET_O_CREAT, TARGET_O_CREAT, O_CREAT, O_CREAT, },
2388 { TARGET_O_EXCL, TARGET_O_EXCL, O_EXCL, O_EXCL, },
2389 { TARGET_O_NOCTTY, TARGET_O_NOCTTY, O_NOCTTY, O_NOCTTY, },
2390 { TARGET_O_TRUNC, TARGET_O_TRUNC, O_TRUNC, O_TRUNC, },
2391 { TARGET_O_APPEND, TARGET_O_APPEND, O_APPEND, O_APPEND, },
2392 { TARGET_O_NONBLOCK, TARGET_O_NONBLOCK, O_NONBLOCK, O_NONBLOCK, },
2393 { TARGET_O_SYNC, TARGET_O_SYNC, O_SYNC, O_SYNC, },
2394 { TARGET_FASYNC, TARGET_FASYNC, FASYNC, FASYNC, },
2395 { TARGET_O_DIRECTORY, TARGET_O_DIRECTORY, O_DIRECTORY, O_DIRECTORY, },
2396 { TARGET_O_NOFOLLOW, TARGET_O_NOFOLLOW, O_NOFOLLOW, O_NOFOLLOW, },
2397 { TARGET_O_LARGEFILE, TARGET_O_LARGEFILE, O_LARGEFILE, O_LARGEFILE, },
bellard121061d2004-02-22 11:56:01 +00002398#if defined(O_DIRECT)
bellardffa65c32004-01-04 23:57:22 +00002399 { TARGET_O_DIRECT, TARGET_O_DIRECT, O_DIRECT, O_DIRECT, },
bellard121061d2004-02-22 11:56:01 +00002400#endif
bellardffa65c32004-01-04 23:57:22 +00002401 { 0, 0, 0, 0 }
2402};
2403
bellard2ab83ea2003-06-15 19:56:46 +00002404#if defined(TARGET_I386)
bellard6dbad632003-03-16 18:05:05 +00002405
2406/* NOTE: there is really one LDT for all the threads */
2407uint8_t *ldt_table;
2408
bellard03acab62007-11-11 14:57:14 +00002409static abi_long read_ldt(abi_ulong ptr, unsigned long bytecount)
bellard6dbad632003-03-16 18:05:05 +00002410{
2411 int size;
pbrook53a59602006-03-25 19:31:22 +00002412 void *p;
bellard6dbad632003-03-16 18:05:05 +00002413
2414 if (!ldt_table)
2415 return 0;
2416 size = TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE;
2417 if (size > bytecount)
2418 size = bytecount;
bellard579a97f2007-11-11 14:26:47 +00002419 p = lock_user(VERIFY_WRITE, ptr, size, 0);
2420 if (!p)
bellard03acab62007-11-11 14:57:14 +00002421 return -TARGET_EFAULT;
bellard579a97f2007-11-11 14:26:47 +00002422 /* ??? Should this by byteswapped? */
pbrook53a59602006-03-25 19:31:22 +00002423 memcpy(p, ldt_table, size);
2424 unlock_user(p, ptr, size);
bellard6dbad632003-03-16 18:05:05 +00002425 return size;
2426}
2427
2428/* XXX: add locking support */
bellard03acab62007-11-11 14:57:14 +00002429static abi_long write_ldt(CPUX86State *env,
2430 abi_ulong ptr, unsigned long bytecount, int oldmode)
bellard6dbad632003-03-16 18:05:05 +00002431{
2432 struct target_modify_ldt_ldt_s ldt_info;
pbrook53a59602006-03-25 19:31:22 +00002433 struct target_modify_ldt_ldt_s *target_ldt_info;
bellard6dbad632003-03-16 18:05:05 +00002434 int seg_32bit, contents, read_exec_only, limit_in_pages;
bellard8d18e892007-11-14 15:18:40 +00002435 int seg_not_present, useable, lm;
bellard6dbad632003-03-16 18:05:05 +00002436 uint32_t *lp, entry_1, entry_2;
2437
2438 if (bytecount != sizeof(ldt_info))
bellard03acab62007-11-11 14:57:14 +00002439 return -TARGET_EINVAL;
bellard579a97f2007-11-11 14:26:47 +00002440 if (!lock_user_struct(VERIFY_READ, target_ldt_info, ptr, 1))
bellard03acab62007-11-11 14:57:14 +00002441 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00002442 ldt_info.entry_number = tswap32(target_ldt_info->entry_number);
2443 ldt_info.base_addr = tswapl(target_ldt_info->base_addr);
2444 ldt_info.limit = tswap32(target_ldt_info->limit);
2445 ldt_info.flags = tswap32(target_ldt_info->flags);
2446 unlock_user_struct(target_ldt_info, ptr, 0);
ths3b46e622007-09-17 08:09:54 +00002447
bellard6dbad632003-03-16 18:05:05 +00002448 if (ldt_info.entry_number >= TARGET_LDT_ENTRIES)
bellard03acab62007-11-11 14:57:14 +00002449 return -TARGET_EINVAL;
bellard6dbad632003-03-16 18:05:05 +00002450 seg_32bit = ldt_info.flags & 1;
2451 contents = (ldt_info.flags >> 1) & 3;
2452 read_exec_only = (ldt_info.flags >> 3) & 1;
2453 limit_in_pages = (ldt_info.flags >> 4) & 1;
2454 seg_not_present = (ldt_info.flags >> 5) & 1;
2455 useable = (ldt_info.flags >> 6) & 1;
bellard8d18e892007-11-14 15:18:40 +00002456#ifdef TARGET_ABI32
2457 lm = 0;
2458#else
2459 lm = (ldt_info.flags >> 7) & 1;
2460#endif
bellard6dbad632003-03-16 18:05:05 +00002461 if (contents == 3) {
2462 if (oldmode)
bellard03acab62007-11-11 14:57:14 +00002463 return -TARGET_EINVAL;
bellard6dbad632003-03-16 18:05:05 +00002464 if (seg_not_present == 0)
bellard03acab62007-11-11 14:57:14 +00002465 return -TARGET_EINVAL;
bellard6dbad632003-03-16 18:05:05 +00002466 }
2467 /* allocate the LDT */
2468 if (!ldt_table) {
2469 ldt_table = malloc(TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE);
2470 if (!ldt_table)
bellard03acab62007-11-11 14:57:14 +00002471 return -TARGET_ENOMEM;
bellard6dbad632003-03-16 18:05:05 +00002472 memset(ldt_table, 0, TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE);
bellardeeeac3f2007-11-11 19:34:32 +00002473 env->ldt.base = h2g((unsigned long)ldt_table);
bellard6dbad632003-03-16 18:05:05 +00002474 env->ldt.limit = 0xffff;
2475 }
2476
2477 /* NOTE: same code as Linux kernel */
2478 /* Allow LDTs to be cleared by the user. */
2479 if (ldt_info.base_addr == 0 && ldt_info.limit == 0) {
2480 if (oldmode ||
2481 (contents == 0 &&
2482 read_exec_only == 1 &&
2483 seg_32bit == 0 &&
2484 limit_in_pages == 0 &&
2485 seg_not_present == 1 &&
2486 useable == 0 )) {
2487 entry_1 = 0;
2488 entry_2 = 0;
2489 goto install;
2490 }
2491 }
ths3b46e622007-09-17 08:09:54 +00002492
bellard6dbad632003-03-16 18:05:05 +00002493 entry_1 = ((ldt_info.base_addr & 0x0000ffff) << 16) |
2494 (ldt_info.limit & 0x0ffff);
2495 entry_2 = (ldt_info.base_addr & 0xff000000) |
2496 ((ldt_info.base_addr & 0x00ff0000) >> 16) |
2497 (ldt_info.limit & 0xf0000) |
2498 ((read_exec_only ^ 1) << 9) |
2499 (contents << 10) |
2500 ((seg_not_present ^ 1) << 15) |
2501 (seg_32bit << 22) |
2502 (limit_in_pages << 23) |
bellard8d18e892007-11-14 15:18:40 +00002503 (lm << 21) |
bellard6dbad632003-03-16 18:05:05 +00002504 0x7000;
2505 if (!oldmode)
2506 entry_2 |= (useable << 20);
bellard14ae3ba2003-05-27 23:25:06 +00002507
bellard6dbad632003-03-16 18:05:05 +00002508 /* Install the new entry ... */
2509install:
2510 lp = (uint32_t *)(ldt_table + (ldt_info.entry_number << 3));
2511 lp[0] = tswap32(entry_1);
2512 lp[1] = tswap32(entry_2);
2513 return 0;
2514}
2515
2516/* specific and weird i386 syscalls */
bellard03acab62007-11-11 14:57:14 +00002517abi_long do_modify_ldt(CPUX86State *env, int func, abi_ulong ptr,
2518 unsigned long bytecount)
bellard6dbad632003-03-16 18:05:05 +00002519{
bellard03acab62007-11-11 14:57:14 +00002520 abi_long ret;
ths3b46e622007-09-17 08:09:54 +00002521
bellard6dbad632003-03-16 18:05:05 +00002522 switch (func) {
2523 case 0:
2524 ret = read_ldt(ptr, bytecount);
2525 break;
2526 case 1:
2527 ret = write_ldt(env, ptr, bytecount, 1);
2528 break;
2529 case 0x11:
2530 ret = write_ldt(env, ptr, bytecount, 0);
2531 break;
bellard03acab62007-11-11 14:57:14 +00002532 default:
2533 ret = -TARGET_ENOSYS;
2534 break;
bellard6dbad632003-03-16 18:05:05 +00002535 }
2536 return ret;
2537}
bellard1b6b0292003-03-22 17:31:38 +00002538
bellard8d18e892007-11-14 15:18:40 +00002539abi_long do_set_thread_area(CPUX86State *env, abi_ulong ptr)
2540{
2541 uint64_t *gdt_table = g2h(env->gdt.base);
2542 struct target_modify_ldt_ldt_s ldt_info;
2543 struct target_modify_ldt_ldt_s *target_ldt_info;
2544 int seg_32bit, contents, read_exec_only, limit_in_pages;
2545 int seg_not_present, useable, lm;
2546 uint32_t *lp, entry_1, entry_2;
2547 int i;
2548
2549 lock_user_struct(VERIFY_WRITE, target_ldt_info, ptr, 1);
2550 if (!target_ldt_info)
2551 return -TARGET_EFAULT;
2552 ldt_info.entry_number = tswap32(target_ldt_info->entry_number);
2553 ldt_info.base_addr = tswapl(target_ldt_info->base_addr);
2554 ldt_info.limit = tswap32(target_ldt_info->limit);
2555 ldt_info.flags = tswap32(target_ldt_info->flags);
2556 if (ldt_info.entry_number == -1) {
2557 for (i=TARGET_GDT_ENTRY_TLS_MIN; i<=TARGET_GDT_ENTRY_TLS_MAX; i++) {
2558 if (gdt_table[i] == 0) {
2559 ldt_info.entry_number = i;
2560 target_ldt_info->entry_number = tswap32(i);
2561 break;
2562 }
2563 }
2564 }
2565 unlock_user_struct(target_ldt_info, ptr, 1);
2566
2567 if (ldt_info.entry_number < TARGET_GDT_ENTRY_TLS_MIN ||
2568 ldt_info.entry_number > TARGET_GDT_ENTRY_TLS_MAX)
2569 return -TARGET_EINVAL;
2570 seg_32bit = ldt_info.flags & 1;
2571 contents = (ldt_info.flags >> 1) & 3;
2572 read_exec_only = (ldt_info.flags >> 3) & 1;
2573 limit_in_pages = (ldt_info.flags >> 4) & 1;
2574 seg_not_present = (ldt_info.flags >> 5) & 1;
2575 useable = (ldt_info.flags >> 6) & 1;
2576#ifdef TARGET_ABI32
2577 lm = 0;
2578#else
2579 lm = (ldt_info.flags >> 7) & 1;
2580#endif
2581
2582 if (contents == 3) {
2583 if (seg_not_present == 0)
2584 return -TARGET_EINVAL;
2585 }
2586
2587 /* NOTE: same code as Linux kernel */
2588 /* Allow LDTs to be cleared by the user. */
2589 if (ldt_info.base_addr == 0 && ldt_info.limit == 0) {
2590 if ((contents == 0 &&
2591 read_exec_only == 1 &&
2592 seg_32bit == 0 &&
2593 limit_in_pages == 0 &&
2594 seg_not_present == 1 &&
2595 useable == 0 )) {
2596 entry_1 = 0;
2597 entry_2 = 0;
2598 goto install;
2599 }
2600 }
2601
2602 entry_1 = ((ldt_info.base_addr & 0x0000ffff) << 16) |
2603 (ldt_info.limit & 0x0ffff);
2604 entry_2 = (ldt_info.base_addr & 0xff000000) |
2605 ((ldt_info.base_addr & 0x00ff0000) >> 16) |
2606 (ldt_info.limit & 0xf0000) |
2607 ((read_exec_only ^ 1) << 9) |
2608 (contents << 10) |
2609 ((seg_not_present ^ 1) << 15) |
2610 (seg_32bit << 22) |
2611 (limit_in_pages << 23) |
2612 (useable << 20) |
2613 (lm << 21) |
2614 0x7000;
2615
2616 /* Install the new entry ... */
2617install:
2618 lp = (uint32_t *)(gdt_table + ldt_info.entry_number);
2619 lp[0] = tswap32(entry_1);
2620 lp[1] = tswap32(entry_2);
2621 return 0;
2622}
2623
2624abi_long do_get_thread_area(CPUX86State *env, abi_ulong ptr)
2625{
2626 struct target_modify_ldt_ldt_s *target_ldt_info;
2627 uint64_t *gdt_table = g2h(env->gdt.base);
2628 uint32_t base_addr, limit, flags;
2629 int seg_32bit, contents, read_exec_only, limit_in_pages, idx;
2630 int seg_not_present, useable, lm;
2631 uint32_t *lp, entry_1, entry_2;
2632
2633 lock_user_struct(VERIFY_WRITE, target_ldt_info, ptr, 1);
2634 if (!target_ldt_info)
2635 return -TARGET_EFAULT;
2636 idx = tswap32(target_ldt_info->entry_number);
2637 if (idx < TARGET_GDT_ENTRY_TLS_MIN ||
2638 idx > TARGET_GDT_ENTRY_TLS_MAX) {
2639 unlock_user_struct(target_ldt_info, ptr, 1);
2640 return -TARGET_EINVAL;
2641 }
2642 lp = (uint32_t *)(gdt_table + idx);
2643 entry_1 = tswap32(lp[0]);
2644 entry_2 = tswap32(lp[1]);
2645
2646 read_exec_only = ((entry_2 >> 9) & 1) ^ 1;
2647 contents = (entry_2 >> 10) & 3;
2648 seg_not_present = ((entry_2 >> 15) & 1) ^ 1;
2649 seg_32bit = (entry_2 >> 22) & 1;
2650 limit_in_pages = (entry_2 >> 23) & 1;
2651 useable = (entry_2 >> 20) & 1;
2652#ifdef TARGET_ABI32
2653 lm = 0;
2654#else
2655 lm = (entry_2 >> 21) & 1;
2656#endif
2657 flags = (seg_32bit << 0) | (contents << 1) |
2658 (read_exec_only << 3) | (limit_in_pages << 4) |
2659 (seg_not_present << 5) | (useable << 6) | (lm << 7);
2660 limit = (entry_1 & 0xffff) | (entry_2 & 0xf0000);
2661 base_addr = (entry_1 >> 16) |
2662 (entry_2 & 0xff000000) |
2663 ((entry_2 & 0xff) << 16);
2664 target_ldt_info->base_addr = tswapl(base_addr);
2665 target_ldt_info->limit = tswap32(limit);
2666 target_ldt_info->flags = tswap32(flags);
2667 unlock_user_struct(target_ldt_info, ptr, 1);
2668 return 0;
2669}
2670
bellardd2fd1af2007-11-14 18:08:56 +00002671#ifndef TARGET_ABI32
2672abi_long do_arch_prctl(CPUX86State *env, int code, abi_ulong addr)
2673{
2674 abi_long ret;
2675 abi_ulong val;
2676 int idx;
2677
2678 switch(code) {
2679 case TARGET_ARCH_SET_GS:
2680 case TARGET_ARCH_SET_FS:
2681 if (code == TARGET_ARCH_SET_GS)
2682 idx = R_GS;
2683 else
2684 idx = R_FS;
2685 cpu_x86_load_seg(env, idx, 0);
2686 env->segs[idx].base = addr;
2687 break;
2688 case TARGET_ARCH_GET_GS:
2689 case TARGET_ARCH_GET_FS:
2690 if (code == TARGET_ARCH_GET_GS)
2691 idx = R_GS;
2692 else
2693 idx = R_FS;
2694 val = env->segs[idx].base;
2695 if (put_user(val, addr, abi_ulong))
2696 return -TARGET_EFAULT;
2697 break;
2698 default:
2699 ret = -TARGET_EINVAL;
2700 break;
2701 }
2702 return 0;
2703}
2704#endif
2705
bellard2ab83ea2003-06-15 19:56:46 +00002706#endif /* defined(TARGET_I386) */
2707
bellard1b6b0292003-03-22 17:31:38 +00002708/* this stack is the equivalent of the kernel stack associated with a
2709 thread/process */
2710#define NEW_STACK_SIZE 8192
2711
2712static int clone_func(void *arg)
2713{
bellard2ab83ea2003-06-15 19:56:46 +00002714 CPUState *env = arg;
bellard1b6b0292003-03-22 17:31:38 +00002715 cpu_loop(env);
2716 /* never exits */
2717 return 0;
2718}
2719
ths0da46a62007-10-20 20:23:07 +00002720/* do_fork() Must return host values and target errnos (unlike most
2721 do_*() functions). */
blueswir1992f48a2007-10-14 16:27:31 +00002722int do_fork(CPUState *env, unsigned int flags, abi_ulong newsp)
bellard1b6b0292003-03-22 17:31:38 +00002723{
2724 int ret;
bellard5cd43932003-03-29 16:54:36 +00002725 TaskState *ts;
bellard1b6b0292003-03-22 17:31:38 +00002726 uint8_t *new_stack;
bellard2ab83ea2003-06-15 19:56:46 +00002727 CPUState *new_env;
ths3b46e622007-09-17 08:09:54 +00002728
bellard1b6b0292003-03-22 17:31:38 +00002729 if (flags & CLONE_VM) {
pbrookbd0c5662008-05-29 14:34:11 +00002730#if defined(USE_NPTL)
2731 /* qemu is not threadsafe. Bail out immediately if application
2732 tries to create a thread. */
2733 if (!(flags & CLONE_VFORK)) {
2734 gemu_log ("clone(CLONE_VM) not supported\n");
2735 return -EINVAL;
2736 }
2737#endif
bellard5cd43932003-03-29 16:54:36 +00002738 ts = malloc(sizeof(TaskState) + NEW_STACK_SIZE);
2739 memset(ts, 0, sizeof(TaskState));
2740 new_stack = ts->stack;
2741 ts->used = 1;
2742 /* add in task state list */
2743 ts->next = first_task_state;
2744 first_task_state = ts;
bellard1b6b0292003-03-22 17:31:38 +00002745 /* we create a new CPU instance. */
thsc5be9f02007-02-28 20:20:53 +00002746 new_env = cpu_copy(env);
pbrook6e68e072008-05-30 17:22:15 +00002747 /* Init regs that differ from the parent. */
2748 cpu_clone_regs(new_env, newsp);
bellard5cd43932003-03-29 16:54:36 +00002749 new_env->opaque = ts;
bellard27725c12003-04-29 21:08:18 +00002750#ifdef __ia64__
bellardfd4a43e2006-04-24 20:32:17 +00002751 ret = __clone2(clone_func, new_stack + NEW_STACK_SIZE, flags, new_env);
bellard27725c12003-04-29 21:08:18 +00002752#else
2753 ret = clone(clone_func, new_stack + NEW_STACK_SIZE, flags, new_env);
2754#endif
bellard1b6b0292003-03-22 17:31:38 +00002755 } else {
2756 /* if no CLONE_VM, we consider it is a fork */
2757 if ((flags & ~CSIGNAL) != 0)
2758 return -EINVAL;
2759 ret = fork();
pbrook6e68e072008-05-30 17:22:15 +00002760 if (ret == 0) {
2761 cpu_clone_regs(env, newsp);
2762 }
bellard1b6b0292003-03-22 17:31:38 +00002763 }
2764 return ret;
2765}
2766
blueswir1992f48a2007-10-14 16:27:31 +00002767static abi_long do_fcntl(int fd, int cmd, abi_ulong arg)
bellard7775e9e2003-05-14 22:46:48 +00002768{
2769 struct flock fl;
pbrook53a59602006-03-25 19:31:22 +00002770 struct target_flock *target_fl;
ths43f238d2007-01-05 20:55:49 +00002771 struct flock64 fl64;
2772 struct target_flock64 *target_fl64;
blueswir1992f48a2007-10-14 16:27:31 +00002773 abi_long ret;
pbrook53a59602006-03-25 19:31:22 +00002774
bellard7775e9e2003-05-14 22:46:48 +00002775 switch(cmd) {
2776 case TARGET_F_GETLK:
bellard579a97f2007-11-11 14:26:47 +00002777 if (!lock_user_struct(VERIFY_READ, target_fl, arg, 1))
2778 return -TARGET_EFAULT;
ths58134272007-03-31 18:59:32 +00002779 fl.l_type = tswap16(target_fl->l_type);
2780 fl.l_whence = tswap16(target_fl->l_whence);
2781 fl.l_start = tswapl(target_fl->l_start);
2782 fl.l_len = tswapl(target_fl->l_len);
2783 fl.l_pid = tswapl(target_fl->l_pid);
2784 unlock_user_struct(target_fl, arg, 0);
bellard9ee1fa22007-11-11 15:11:19 +00002785 ret = get_errno(fcntl(fd, cmd, &fl));
bellard7775e9e2003-05-14 22:46:48 +00002786 if (ret == 0) {
bellard579a97f2007-11-11 14:26:47 +00002787 if (!lock_user_struct(VERIFY_WRITE, target_fl, arg, 0))
2788 return -TARGET_EFAULT;
bellard7775e9e2003-05-14 22:46:48 +00002789 target_fl->l_type = tswap16(fl.l_type);
2790 target_fl->l_whence = tswap16(fl.l_whence);
2791 target_fl->l_start = tswapl(fl.l_start);
2792 target_fl->l_len = tswapl(fl.l_len);
2793 target_fl->l_pid = tswapl(fl.l_pid);
pbrook53a59602006-03-25 19:31:22 +00002794 unlock_user_struct(target_fl, arg, 1);
bellard7775e9e2003-05-14 22:46:48 +00002795 }
2796 break;
ths3b46e622007-09-17 08:09:54 +00002797
bellard7775e9e2003-05-14 22:46:48 +00002798 case TARGET_F_SETLK:
2799 case TARGET_F_SETLKW:
bellard579a97f2007-11-11 14:26:47 +00002800 if (!lock_user_struct(VERIFY_READ, target_fl, arg, 1))
2801 return -TARGET_EFAULT;
bellard7775e9e2003-05-14 22:46:48 +00002802 fl.l_type = tswap16(target_fl->l_type);
2803 fl.l_whence = tswap16(target_fl->l_whence);
2804 fl.l_start = tswapl(target_fl->l_start);
2805 fl.l_len = tswapl(target_fl->l_len);
2806 fl.l_pid = tswapl(target_fl->l_pid);
pbrook53a59602006-03-25 19:31:22 +00002807 unlock_user_struct(target_fl, arg, 0);
bellard9ee1fa22007-11-11 15:11:19 +00002808 ret = get_errno(fcntl(fd, cmd, &fl));
bellard7775e9e2003-05-14 22:46:48 +00002809 break;
ths3b46e622007-09-17 08:09:54 +00002810
bellard7775e9e2003-05-14 22:46:48 +00002811 case TARGET_F_GETLK64:
bellard579a97f2007-11-11 14:26:47 +00002812 if (!lock_user_struct(VERIFY_READ, target_fl64, arg, 1))
2813 return -TARGET_EFAULT;
ths58134272007-03-31 18:59:32 +00002814 fl64.l_type = tswap16(target_fl64->l_type) >> 1;
2815 fl64.l_whence = tswap16(target_fl64->l_whence);
2816 fl64.l_start = tswapl(target_fl64->l_start);
2817 fl64.l_len = tswapl(target_fl64->l_len);
2818 fl64.l_pid = tswap16(target_fl64->l_pid);
2819 unlock_user_struct(target_fl64, arg, 0);
bellard9ee1fa22007-11-11 15:11:19 +00002820 ret = get_errno(fcntl(fd, cmd >> 1, &fl64));
ths43f238d2007-01-05 20:55:49 +00002821 if (ret == 0) {
bellard579a97f2007-11-11 14:26:47 +00002822 if (!lock_user_struct(VERIFY_WRITE, target_fl64, arg, 0))
2823 return -TARGET_EFAULT;
ths43f238d2007-01-05 20:55:49 +00002824 target_fl64->l_type = tswap16(fl64.l_type) >> 1;
2825 target_fl64->l_whence = tswap16(fl64.l_whence);
2826 target_fl64->l_start = tswapl(fl64.l_start);
2827 target_fl64->l_len = tswapl(fl64.l_len);
2828 target_fl64->l_pid = tswapl(fl64.l_pid);
2829 unlock_user_struct(target_fl64, arg, 1);
2830 }
bellard9ee1fa22007-11-11 15:11:19 +00002831 break;
bellard7775e9e2003-05-14 22:46:48 +00002832 case TARGET_F_SETLK64:
2833 case TARGET_F_SETLKW64:
bellard579a97f2007-11-11 14:26:47 +00002834 if (!lock_user_struct(VERIFY_READ, target_fl64, arg, 1))
2835 return -TARGET_EFAULT;
ths43f238d2007-01-05 20:55:49 +00002836 fl64.l_type = tswap16(target_fl64->l_type) >> 1;
2837 fl64.l_whence = tswap16(target_fl64->l_whence);
2838 fl64.l_start = tswapl(target_fl64->l_start);
2839 fl64.l_len = tswapl(target_fl64->l_len);
2840 fl64.l_pid = tswap16(target_fl64->l_pid);
2841 unlock_user_struct(target_fl64, arg, 0);
bellard9ee1fa22007-11-11 15:11:19 +00002842 ret = get_errno(fcntl(fd, cmd >> 1, &fl64));
bellard7775e9e2003-05-14 22:46:48 +00002843 break;
2844
bellardffa65c32004-01-04 23:57:22 +00002845 case F_GETFL:
bellard9ee1fa22007-11-11 15:11:19 +00002846 ret = get_errno(fcntl(fd, cmd, arg));
2847 if (ret >= 0) {
2848 ret = host_to_target_bitmask(ret, fcntl_flags_tbl);
2849 }
bellardffa65c32004-01-04 23:57:22 +00002850 break;
2851
2852 case F_SETFL:
bellard9ee1fa22007-11-11 15:11:19 +00002853 ret = get_errno(fcntl(fd, cmd, target_to_host_bitmask(arg, fcntl_flags_tbl)));
bellardffa65c32004-01-04 23:57:22 +00002854 break;
2855
bellard7775e9e2003-05-14 22:46:48 +00002856 default:
bellard9ee1fa22007-11-11 15:11:19 +00002857 ret = get_errno(fcntl(fd, cmd, arg));
bellard7775e9e2003-05-14 22:46:48 +00002858 break;
2859 }
2860 return ret;
2861}
2862
bellard67867302003-11-23 17:05:30 +00002863#ifdef USE_UID16
bellard7775e9e2003-05-14 22:46:48 +00002864
bellard67867302003-11-23 17:05:30 +00002865static inline int high2lowuid(int uid)
2866{
2867 if (uid > 65535)
2868 return 65534;
2869 else
2870 return uid;
2871}
2872
2873static inline int high2lowgid(int gid)
2874{
2875 if (gid > 65535)
2876 return 65534;
2877 else
2878 return gid;
2879}
2880
2881static inline int low2highuid(int uid)
2882{
2883 if ((int16_t)uid == -1)
2884 return -1;
2885 else
2886 return uid;
2887}
2888
2889static inline int low2highgid(int gid)
2890{
2891 if ((int16_t)gid == -1)
2892 return -1;
2893 else
2894 return gid;
2895}
2896
2897#endif /* USE_UID16 */
bellard1b6b0292003-03-22 17:31:38 +00002898
bellard31e31b82003-02-18 22:55:36 +00002899void syscall_init(void)
2900{
bellard2ab83ea2003-06-15 19:56:46 +00002901 IOCTLEntry *ie;
2902 const argtype *arg_type;
2903 int size;
thsb92c47c2007-11-01 00:07:38 +00002904 int i;
bellard2ab83ea2003-06-15 19:56:46 +00002905
ths5fafdf22007-09-16 21:08:06 +00002906#define STRUCT(name, list...) thunk_register_struct(STRUCT_ ## name, #name, struct_ ## name ## _def);
2907#define STRUCT_SPECIAL(name) thunk_register_struct_direct(STRUCT_ ## name, #name, &struct_ ## name ## _def);
bellard31e31b82003-02-18 22:55:36 +00002908#include "syscall_types.h"
2909#undef STRUCT
2910#undef STRUCT_SPECIAL
bellard2ab83ea2003-06-15 19:56:46 +00002911
2912 /* we patch the ioctl size if necessary. We rely on the fact that
2913 no ioctl has all the bits at '1' in the size field */
2914 ie = ioctl_entries;
2915 while (ie->target_cmd != 0) {
2916 if (((ie->target_cmd >> TARGET_IOC_SIZESHIFT) & TARGET_IOC_SIZEMASK) ==
2917 TARGET_IOC_SIZEMASK) {
2918 arg_type = ie->arg_type;
2919 if (arg_type[0] != TYPE_PTR) {
ths5fafdf22007-09-16 21:08:06 +00002920 fprintf(stderr, "cannot patch size for ioctl 0x%x\n",
bellard2ab83ea2003-06-15 19:56:46 +00002921 ie->target_cmd);
2922 exit(1);
2923 }
2924 arg_type++;
2925 size = thunk_type_size(arg_type, 0);
ths5fafdf22007-09-16 21:08:06 +00002926 ie->target_cmd = (ie->target_cmd &
bellard2ab83ea2003-06-15 19:56:46 +00002927 ~(TARGET_IOC_SIZEMASK << TARGET_IOC_SIZESHIFT)) |
2928 (size << TARGET_IOC_SIZESHIFT);
2929 }
thsb92c47c2007-11-01 00:07:38 +00002930
2931 /* Build target_to_host_errno_table[] table from
2932 * host_to_target_errno_table[]. */
2933 for (i=0; i < ERRNO_TABLE_SIZE; i++)
2934 target_to_host_errno_table[host_to_target_errno_table[i]] = i;
2935
bellard2ab83ea2003-06-15 19:56:46 +00002936 /* automatic consistency check if same arch */
bellardd2fd1af2007-11-14 18:08:56 +00002937#if defined(__i386__) && defined(TARGET_I386) && defined(TARGET_ABI32)
bellard2ab83ea2003-06-15 19:56:46 +00002938 if (ie->target_cmd != ie->host_cmd) {
ths5fafdf22007-09-16 21:08:06 +00002939 fprintf(stderr, "ERROR: ioctl: target=0x%x host=0x%x\n",
bellard2ab83ea2003-06-15 19:56:46 +00002940 ie->target_cmd, ie->host_cmd);
2941 }
2942#endif
2943 ie++;
2944 }
bellard31e31b82003-02-18 22:55:36 +00002945}
bellardc573ff62004-01-04 15:51:36 +00002946
blueswir1992f48a2007-10-14 16:27:31 +00002947#if TARGET_ABI_BITS == 32
pbrookce4defa2006-02-09 16:49:55 +00002948static inline uint64_t target_offset64(uint32_t word0, uint32_t word1)
2949{
2950#ifdef TARGET_WORDS_BIG_ENDIAN
2951 return ((uint64_t)word0 << 32) | word1;
2952#else
2953 return ((uint64_t)word1 << 32) | word0;
2954#endif
2955}
blueswir1992f48a2007-10-14 16:27:31 +00002956#else /* TARGET_ABI_BITS == 32 */
j_mayer32407102007-09-26 23:01:49 +00002957static inline uint64_t target_offset64(uint64_t word0, uint64_t word1)
2958{
2959 return word0;
2960}
blueswir1992f48a2007-10-14 16:27:31 +00002961#endif /* TARGET_ABI_BITS != 32 */
pbrookce4defa2006-02-09 16:49:55 +00002962
2963#ifdef TARGET_NR_truncate64
blueswir1992f48a2007-10-14 16:27:31 +00002964static inline abi_long target_truncate64(void *cpu_env, const char *arg1,
2965 abi_long arg2,
2966 abi_long arg3,
2967 abi_long arg4)
pbrookce4defa2006-02-09 16:49:55 +00002968{
2969#ifdef TARGET_ARM
2970 if (((CPUARMState *)cpu_env)->eabi)
2971 {
2972 arg2 = arg3;
2973 arg3 = arg4;
2974 }
2975#endif
2976 return get_errno(truncate64(arg1, target_offset64(arg2, arg3)));
2977}
2978#endif
2979
2980#ifdef TARGET_NR_ftruncate64
blueswir1992f48a2007-10-14 16:27:31 +00002981static inline abi_long target_ftruncate64(void *cpu_env, abi_long arg1,
2982 abi_long arg2,
2983 abi_long arg3,
2984 abi_long arg4)
pbrookce4defa2006-02-09 16:49:55 +00002985{
2986#ifdef TARGET_ARM
2987 if (((CPUARMState *)cpu_env)->eabi)
2988 {
2989 arg2 = arg3;
2990 arg3 = arg4;
2991 }
2992#endif
2993 return get_errno(ftruncate64(arg1, target_offset64(arg2, arg3)));
2994}
2995#endif
2996
bellard579a97f2007-11-11 14:26:47 +00002997static inline abi_long target_to_host_timespec(struct timespec *host_ts,
2998 abi_ulong target_addr)
pbrook53a59602006-03-25 19:31:22 +00002999{
3000 struct target_timespec *target_ts;
3001
bellard579a97f2007-11-11 14:26:47 +00003002 if (!lock_user_struct(VERIFY_READ, target_ts, target_addr, 1))
3003 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00003004 host_ts->tv_sec = tswapl(target_ts->tv_sec);
3005 host_ts->tv_nsec = tswapl(target_ts->tv_nsec);
3006 unlock_user_struct(target_ts, target_addr, 0);
bellardb255bfa2008-05-10 21:51:02 +00003007 return 0;
pbrook53a59602006-03-25 19:31:22 +00003008}
3009
bellard579a97f2007-11-11 14:26:47 +00003010static inline abi_long host_to_target_timespec(abi_ulong target_addr,
3011 struct timespec *host_ts)
pbrook53a59602006-03-25 19:31:22 +00003012{
3013 struct target_timespec *target_ts;
3014
bellard579a97f2007-11-11 14:26:47 +00003015 if (!lock_user_struct(VERIFY_WRITE, target_ts, target_addr, 0))
3016 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00003017 target_ts->tv_sec = tswapl(host_ts->tv_sec);
3018 target_ts->tv_nsec = tswapl(host_ts->tv_nsec);
3019 unlock_user_struct(target_ts, target_addr, 1);
bellardb255bfa2008-05-10 21:51:02 +00003020 return 0;
pbrook53a59602006-03-25 19:31:22 +00003021}
3022
pbrookbd0c5662008-05-29 14:34:11 +00003023#if defined(USE_NPTL)
3024/* ??? Using host futex calls even when target atomic operations
3025 are not really atomic probably breaks things. However implementing
3026 futexes locally would make futexes shared between multiple processes
3027 tricky. However they're probably useless because guest atomic
3028 operations won't work either. */
3029int do_futex(target_ulong uaddr, int op, int val, target_ulong timeout,
3030 target_ulong uaddr2, int val3)
3031{
3032 struct timespec ts, *pts;
3033
3034 /* ??? We assume FUTEX_* constants are the same on both host
3035 and target. */
3036 switch (op) {
3037 case FUTEX_WAIT:
3038 if (timeout) {
3039 pts = &ts;
3040 target_to_host_timespec(pts, timeout);
3041 } else {
3042 pts = NULL;
3043 }
3044 return get_errno(sys_futex(g2h(uaddr), FUTEX_WAIT, tswap32(val),
3045 pts, NULL, 0));
3046 case FUTEX_WAKE:
3047 return get_errno(sys_futex(g2h(uaddr), FUTEX_WAKE, val, NULL, NULL, 0));
3048 case FUTEX_FD:
3049 return get_errno(sys_futex(g2h(uaddr), FUTEX_FD, val, NULL, NULL, 0));
3050 case FUTEX_REQUEUE:
3051 return get_errno(sys_futex(g2h(uaddr), FUTEX_REQUEUE, val,
3052 NULL, g2h(uaddr2), 0));
3053 case FUTEX_CMP_REQUEUE:
3054 return get_errno(sys_futex(g2h(uaddr), FUTEX_CMP_REQUEUE, val,
3055 NULL, g2h(uaddr2), tswap32(val3)));
3056 default:
3057 return -TARGET_ENOSYS;
3058 }
3059}
3060#endif
3061
pbrooka745ec62008-05-06 15:36:17 +00003062int get_osversion(void)
3063{
3064 static int osversion;
3065 struct new_utsname buf;
3066 const char *s;
3067 int i, n, tmp;
3068 if (osversion)
3069 return osversion;
3070 if (qemu_uname_release && *qemu_uname_release) {
3071 s = qemu_uname_release;
3072 } else {
3073 if (sys_uname(&buf))
3074 return 0;
3075 s = buf.release;
3076 }
3077 tmp = 0;
3078 for (i = 0; i < 3; i++) {
3079 n = 0;
3080 while (*s >= '0' && *s <= '9') {
3081 n *= 10;
3082 n += *s - '0';
3083 s++;
3084 }
3085 tmp = (tmp << 8) + n;
3086 if (*s == '.')
3087 s++;
3088 }
3089 osversion = tmp;
3090 return osversion;
3091}
3092
ths0da46a62007-10-20 20:23:07 +00003093/* do_syscall() should always have a single exit point at the end so
3094 that actions, such as logging of syscall results, can be performed.
3095 All errnos that do_syscall() returns must be -TARGET_<errcode>. */
blueswir1992f48a2007-10-14 16:27:31 +00003096abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
3097 abi_long arg2, abi_long arg3, abi_long arg4,
3098 abi_long arg5, abi_long arg6)
bellard31e31b82003-02-18 22:55:36 +00003099{
blueswir1992f48a2007-10-14 16:27:31 +00003100 abi_long ret;
bellard31e31b82003-02-18 22:55:36 +00003101 struct stat st;
bellard56c8f682005-11-28 22:28:41 +00003102 struct statfs stfs;
pbrook53a59602006-03-25 19:31:22 +00003103 void *p;
ths3b46e622007-09-17 08:09:54 +00003104
bellard72f03902003-02-18 23:33:18 +00003105#ifdef DEBUG
bellardc573ff62004-01-04 15:51:36 +00003106 gemu_log("syscall %d", num);
bellard72f03902003-02-18 23:33:18 +00003107#endif
thsb92c47c2007-11-01 00:07:38 +00003108 if(do_strace)
3109 print_syscall(num, arg1, arg2, arg3, arg4, arg5, arg6);
3110
bellard31e31b82003-02-18 22:55:36 +00003111 switch(num) {
3112 case TARGET_NR_exit:
bellard7d132992003-03-06 23:23:54 +00003113#ifdef HAVE_GPROF
3114 _mcleanup();
3115#endif
bellarde9009672005-04-26 20:42:36 +00003116 gdb_exit(cpu_env, arg1);
bellard1b6b0292003-03-22 17:31:38 +00003117 /* XXX: should free thread stack and CPU env */
bellard31e31b82003-02-18 22:55:36 +00003118 _exit(arg1);
3119 ret = 0; /* avoid warning */
3120 break;
3121 case TARGET_NR_read:
bellard579a97f2007-11-11 14:26:47 +00003122 if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
3123 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003124 ret = get_errno(read(arg1, p, arg3));
3125 unlock_user(p, arg2, ret);
bellard31e31b82003-02-18 22:55:36 +00003126 break;
3127 case TARGET_NR_write:
bellard579a97f2007-11-11 14:26:47 +00003128 if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
3129 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003130 ret = get_errno(write(arg1, p, arg3));
3131 unlock_user(p, arg2, 0);
bellard31e31b82003-02-18 22:55:36 +00003132 break;
3133 case TARGET_NR_open:
bellard2f619692007-11-16 10:46:05 +00003134 if (!(p = lock_user_string(arg1)))
3135 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003136 ret = get_errno(open(path(p),
bellardffa65c32004-01-04 23:57:22 +00003137 target_to_host_bitmask(arg2, fcntl_flags_tbl),
3138 arg3));
pbrook53a59602006-03-25 19:31:22 +00003139 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003140 break;
ths82424832007-09-24 09:21:55 +00003141#if defined(TARGET_NR_openat) && defined(__NR_openat)
3142 case TARGET_NR_openat:
bellard579a97f2007-11-11 14:26:47 +00003143 if (!(p = lock_user_string(arg2)))
3144 goto efault;
3145 ret = get_errno(sys_openat(arg1,
3146 path(p),
3147 target_to_host_bitmask(arg3, fcntl_flags_tbl),
3148 arg4));
3149 unlock_user(p, arg2, 0);
ths82424832007-09-24 09:21:55 +00003150 break;
3151#endif
bellard31e31b82003-02-18 22:55:36 +00003152 case TARGET_NR_close:
3153 ret = get_errno(close(arg1));
3154 break;
3155 case TARGET_NR_brk:
pbrook53a59602006-03-25 19:31:22 +00003156 ret = do_brk(arg1);
bellard31e31b82003-02-18 22:55:36 +00003157 break;
3158 case TARGET_NR_fork:
bellard1b6b0292003-03-22 17:31:38 +00003159 ret = get_errno(do_fork(cpu_env, SIGCHLD, 0));
bellard31e31b82003-02-18 22:55:36 +00003160 break;
thse5febef2007-04-01 18:31:35 +00003161#ifdef TARGET_NR_waitpid
bellard31e31b82003-02-18 22:55:36 +00003162 case TARGET_NR_waitpid:
3163 {
pbrook53a59602006-03-25 19:31:22 +00003164 int status;
3165 ret = get_errno(waitpid(arg1, &status, arg3));
bellard2f619692007-11-16 10:46:05 +00003166 if (!is_error(ret) && arg2
3167 && put_user_s32(status, arg2))
3168 goto efault;
bellard31e31b82003-02-18 22:55:36 +00003169 }
3170 break;
thse5febef2007-04-01 18:31:35 +00003171#endif
j_mayer7a3148a2007-04-05 07:13:51 +00003172#ifdef TARGET_NR_creat /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00003173 case TARGET_NR_creat:
bellard579a97f2007-11-11 14:26:47 +00003174 if (!(p = lock_user_string(arg1)))
3175 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003176 ret = get_errno(creat(p, arg2));
3177 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003178 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003179#endif
bellard31e31b82003-02-18 22:55:36 +00003180 case TARGET_NR_link:
pbrook53a59602006-03-25 19:31:22 +00003181 {
3182 void * p2;
3183 p = lock_user_string(arg1);
3184 p2 = lock_user_string(arg2);
bellard579a97f2007-11-11 14:26:47 +00003185 if (!p || !p2)
3186 ret = -TARGET_EFAULT;
3187 else
3188 ret = get_errno(link(p, p2));
pbrook53a59602006-03-25 19:31:22 +00003189 unlock_user(p2, arg2, 0);
3190 unlock_user(p, arg1, 0);
3191 }
bellard31e31b82003-02-18 22:55:36 +00003192 break;
ths64f0ce42007-09-24 09:25:06 +00003193#if defined(TARGET_NR_linkat) && defined(__NR_linkat)
3194 case TARGET_NR_linkat:
ths64f0ce42007-09-24 09:25:06 +00003195 {
3196 void * p2 = NULL;
bellard579a97f2007-11-11 14:26:47 +00003197 if (!arg2 || !arg4)
3198 goto efault;
ths64f0ce42007-09-24 09:25:06 +00003199 p = lock_user_string(arg2);
3200 p2 = lock_user_string(arg4);
bellard579a97f2007-11-11 14:26:47 +00003201 if (!p || !p2)
ths0da46a62007-10-20 20:23:07 +00003202 ret = -TARGET_EFAULT;
ths64f0ce42007-09-24 09:25:06 +00003203 else
3204 ret = get_errno(sys_linkat(arg1, p, arg3, p2, arg5));
bellard579a97f2007-11-11 14:26:47 +00003205 unlock_user(p, arg2, 0);
3206 unlock_user(p2, arg4, 0);
ths64f0ce42007-09-24 09:25:06 +00003207 }
3208 break;
3209#endif
bellard31e31b82003-02-18 22:55:36 +00003210 case TARGET_NR_unlink:
bellard579a97f2007-11-11 14:26:47 +00003211 if (!(p = lock_user_string(arg1)))
3212 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003213 ret = get_errno(unlink(p));
3214 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003215 break;
ths8170f562007-09-24 09:24:11 +00003216#if defined(TARGET_NR_unlinkat) && defined(__NR_unlinkat)
3217 case TARGET_NR_unlinkat:
bellard579a97f2007-11-11 14:26:47 +00003218 if (!(p = lock_user_string(arg2)))
3219 goto efault;
3220 ret = get_errno(sys_unlinkat(arg1, p, arg3));
3221 unlock_user(p, arg2, 0);
balroged494d82007-12-11 23:23:52 +00003222 break;
balrogb7d35e62007-12-12 00:40:24 +00003223#endif
bellard31e31b82003-02-18 22:55:36 +00003224 case TARGET_NR_execve:
bellard7854b052003-03-29 17:22:23 +00003225 {
3226 char **argp, **envp;
bellardf7341ff2003-03-30 21:00:25 +00003227 int argc, envc;
blueswir1992f48a2007-10-14 16:27:31 +00003228 abi_ulong gp;
3229 abi_ulong guest_argp;
3230 abi_ulong guest_envp;
3231 abi_ulong addr;
bellard7854b052003-03-29 17:22:23 +00003232 char **q;
3233
bellardf7341ff2003-03-30 21:00:25 +00003234 argc = 0;
pbrook53a59602006-03-25 19:31:22 +00003235 guest_argp = arg2;
ths982f3ab2007-12-09 23:12:55 +00003236 for (gp = guest_argp; ; gp += sizeof(abi_ulong)) {
ths03aa1972007-12-02 06:28:08 +00003237 if (get_user_ual(addr, gp))
bellard2f619692007-11-16 10:46:05 +00003238 goto efault;
ths03aa1972007-12-02 06:28:08 +00003239 if (!addr)
bellard2f619692007-11-16 10:46:05 +00003240 break;
bellard7854b052003-03-29 17:22:23 +00003241 argc++;
bellard2f619692007-11-16 10:46:05 +00003242 }
bellardf7341ff2003-03-30 21:00:25 +00003243 envc = 0;
pbrook53a59602006-03-25 19:31:22 +00003244 guest_envp = arg3;
ths982f3ab2007-12-09 23:12:55 +00003245 for (gp = guest_envp; ; gp += sizeof(abi_ulong)) {
ths03aa1972007-12-02 06:28:08 +00003246 if (get_user_ual(addr, gp))
bellard2f619692007-11-16 10:46:05 +00003247 goto efault;
ths03aa1972007-12-02 06:28:08 +00003248 if (!addr)
bellard2f619692007-11-16 10:46:05 +00003249 break;
bellard7854b052003-03-29 17:22:23 +00003250 envc++;
bellard2f619692007-11-16 10:46:05 +00003251 }
bellard7854b052003-03-29 17:22:23 +00003252
bellardf7341ff2003-03-30 21:00:25 +00003253 argp = alloca((argc + 1) * sizeof(void *));
3254 envp = alloca((envc + 1) * sizeof(void *));
bellard7854b052003-03-29 17:22:23 +00003255
pbrook53a59602006-03-25 19:31:22 +00003256 for (gp = guest_argp, q = argp; ;
blueswir1992f48a2007-10-14 16:27:31 +00003257 gp += sizeof(abi_ulong), q++) {
bellard2f619692007-11-16 10:46:05 +00003258 if (get_user_ual(addr, gp))
3259 goto execve_efault;
pbrook53a59602006-03-25 19:31:22 +00003260 if (!addr)
3261 break;
bellard2f619692007-11-16 10:46:05 +00003262 if (!(*q = lock_user_string(addr)))
3263 goto execve_efault;
pbrook53a59602006-03-25 19:31:22 +00003264 }
bellardf7341ff2003-03-30 21:00:25 +00003265 *q = NULL;
3266
pbrook53a59602006-03-25 19:31:22 +00003267 for (gp = guest_envp, q = envp; ;
blueswir1992f48a2007-10-14 16:27:31 +00003268 gp += sizeof(abi_ulong), q++) {
bellard2f619692007-11-16 10:46:05 +00003269 if (get_user_ual(addr, gp))
3270 goto execve_efault;
pbrook53a59602006-03-25 19:31:22 +00003271 if (!addr)
3272 break;
bellard2f619692007-11-16 10:46:05 +00003273 if (!(*q = lock_user_string(addr)))
3274 goto execve_efault;
pbrook53a59602006-03-25 19:31:22 +00003275 }
bellardf7341ff2003-03-30 21:00:25 +00003276 *q = NULL;
bellard7854b052003-03-29 17:22:23 +00003277
bellard2f619692007-11-16 10:46:05 +00003278 if (!(p = lock_user_string(arg1)))
3279 goto execve_efault;
pbrook53a59602006-03-25 19:31:22 +00003280 ret = get_errno(execve(p, argp, envp));
3281 unlock_user(p, arg1, 0);
3282
bellard2f619692007-11-16 10:46:05 +00003283 goto execve_end;
3284
3285 execve_efault:
3286 ret = -TARGET_EFAULT;
3287
3288 execve_end:
pbrook53a59602006-03-25 19:31:22 +00003289 for (gp = guest_argp, q = argp; *q;
blueswir1992f48a2007-10-14 16:27:31 +00003290 gp += sizeof(abi_ulong), q++) {
bellard2f619692007-11-16 10:46:05 +00003291 if (get_user_ual(addr, gp)
3292 || !addr)
3293 break;
pbrook53a59602006-03-25 19:31:22 +00003294 unlock_user(*q, addr, 0);
3295 }
3296 for (gp = guest_envp, q = envp; *q;
blueswir1992f48a2007-10-14 16:27:31 +00003297 gp += sizeof(abi_ulong), q++) {
bellard2f619692007-11-16 10:46:05 +00003298 if (get_user_ual(addr, gp)
3299 || !addr)
3300 break;
pbrook53a59602006-03-25 19:31:22 +00003301 unlock_user(*q, addr, 0);
3302 }
bellard7854b052003-03-29 17:22:23 +00003303 }
bellard31e31b82003-02-18 22:55:36 +00003304 break;
3305 case TARGET_NR_chdir:
bellard579a97f2007-11-11 14:26:47 +00003306 if (!(p = lock_user_string(arg1)))
3307 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003308 ret = get_errno(chdir(p));
3309 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003310 break;
bellarda315a142005-01-30 22:59:18 +00003311#ifdef TARGET_NR_time
bellard31e31b82003-02-18 22:55:36 +00003312 case TARGET_NR_time:
3313 {
pbrook53a59602006-03-25 19:31:22 +00003314 time_t host_time;
3315 ret = get_errno(time(&host_time));
bellard2f619692007-11-16 10:46:05 +00003316 if (!is_error(ret)
3317 && arg1
3318 && put_user_sal(host_time, arg1))
3319 goto efault;
bellard31e31b82003-02-18 22:55:36 +00003320 }
3321 break;
bellarda315a142005-01-30 22:59:18 +00003322#endif
bellard31e31b82003-02-18 22:55:36 +00003323 case TARGET_NR_mknod:
bellard579a97f2007-11-11 14:26:47 +00003324 if (!(p = lock_user_string(arg1)))
3325 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003326 ret = get_errno(mknod(p, arg2, arg3));
3327 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003328 break;
ths75ac37a2007-09-24 09:23:05 +00003329#if defined(TARGET_NR_mknodat) && defined(__NR_mknodat)
3330 case TARGET_NR_mknodat:
bellard579a97f2007-11-11 14:26:47 +00003331 if (!(p = lock_user_string(arg2)))
3332 goto efault;
3333 ret = get_errno(sys_mknodat(arg1, p, arg3, arg4));
3334 unlock_user(p, arg2, 0);
ths75ac37a2007-09-24 09:23:05 +00003335 break;
3336#endif
bellard31e31b82003-02-18 22:55:36 +00003337 case TARGET_NR_chmod:
bellard579a97f2007-11-11 14:26:47 +00003338 if (!(p = lock_user_string(arg1)))
3339 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003340 ret = get_errno(chmod(p, arg2));
3341 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003342 break;
bellardebc05482003-09-30 21:08:41 +00003343#ifdef TARGET_NR_break
bellard31e31b82003-02-18 22:55:36 +00003344 case TARGET_NR_break:
3345 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00003346#endif
3347#ifdef TARGET_NR_oldstat
bellard31e31b82003-02-18 22:55:36 +00003348 case TARGET_NR_oldstat:
3349 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00003350#endif
bellard31e31b82003-02-18 22:55:36 +00003351 case TARGET_NR_lseek:
3352 ret = get_errno(lseek(arg1, arg2, arg3));
3353 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003354#ifdef TARGET_NR_getxpid
3355 case TARGET_NR_getxpid:
3356#else
bellard31e31b82003-02-18 22:55:36 +00003357 case TARGET_NR_getpid:
j_mayer7a3148a2007-04-05 07:13:51 +00003358#endif
bellard31e31b82003-02-18 22:55:36 +00003359 ret = get_errno(getpid());
3360 break;
3361 case TARGET_NR_mount:
ths80265912007-02-17 22:25:41 +00003362 {
3363 /* need to look at the data field */
3364 void *p2, *p3;
3365 p = lock_user_string(arg1);
3366 p2 = lock_user_string(arg2);
3367 p3 = lock_user_string(arg3);
bellard579a97f2007-11-11 14:26:47 +00003368 if (!p || !p2 || !p3)
3369 ret = -TARGET_EFAULT;
3370 else
3371 /* FIXME - arg5 should be locked, but it isn't clear how to
3372 * do that since it's not guaranteed to be a NULL-terminated
3373 * string.
3374 */
3375 ret = get_errno(mount(p, p2, p3, (unsigned long)arg4, g2h(arg5)));
3376 unlock_user(p, arg1, 0);
3377 unlock_user(p2, arg2, 0);
3378 unlock_user(p3, arg3, 0);
ths80265912007-02-17 22:25:41 +00003379 break;
3380 }
thse5febef2007-04-01 18:31:35 +00003381#ifdef TARGET_NR_umount
bellard31e31b82003-02-18 22:55:36 +00003382 case TARGET_NR_umount:
bellard579a97f2007-11-11 14:26:47 +00003383 if (!(p = lock_user_string(arg1)))
3384 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003385 ret = get_errno(umount(p));
3386 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003387 break;
thse5febef2007-04-01 18:31:35 +00003388#endif
j_mayer7a3148a2007-04-05 07:13:51 +00003389#ifdef TARGET_NR_stime /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00003390 case TARGET_NR_stime:
3391 {
pbrook53a59602006-03-25 19:31:22 +00003392 time_t host_time;
bellard2f619692007-11-16 10:46:05 +00003393 if (get_user_sal(host_time, arg1))
3394 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003395 ret = get_errno(stime(&host_time));
bellard31e31b82003-02-18 22:55:36 +00003396 }
3397 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003398#endif
bellard31e31b82003-02-18 22:55:36 +00003399 case TARGET_NR_ptrace:
3400 goto unimplemented;
j_mayer7a3148a2007-04-05 07:13:51 +00003401#ifdef TARGET_NR_alarm /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00003402 case TARGET_NR_alarm:
3403 ret = alarm(arg1);
3404 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003405#endif
bellardebc05482003-09-30 21:08:41 +00003406#ifdef TARGET_NR_oldfstat
bellard31e31b82003-02-18 22:55:36 +00003407 case TARGET_NR_oldfstat:
3408 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00003409#endif
j_mayer7a3148a2007-04-05 07:13:51 +00003410#ifdef TARGET_NR_pause /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00003411 case TARGET_NR_pause:
3412 ret = get_errno(pause());
3413 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003414#endif
thse5febef2007-04-01 18:31:35 +00003415#ifdef TARGET_NR_utime
bellard31e31b82003-02-18 22:55:36 +00003416 case TARGET_NR_utime:
bellardebc05482003-09-30 21:08:41 +00003417 {
pbrook53a59602006-03-25 19:31:22 +00003418 struct utimbuf tbuf, *host_tbuf;
3419 struct target_utimbuf *target_tbuf;
3420 if (arg2) {
bellard579a97f2007-11-11 14:26:47 +00003421 if (!lock_user_struct(VERIFY_READ, target_tbuf, arg2, 1))
3422 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003423 tbuf.actime = tswapl(target_tbuf->actime);
3424 tbuf.modtime = tswapl(target_tbuf->modtime);
3425 unlock_user_struct(target_tbuf, arg2, 0);
3426 host_tbuf = &tbuf;
bellardf72e8ff2004-05-03 19:23:07 +00003427 } else {
pbrook53a59602006-03-25 19:31:22 +00003428 host_tbuf = NULL;
bellardf72e8ff2004-05-03 19:23:07 +00003429 }
bellard579a97f2007-11-11 14:26:47 +00003430 if (!(p = lock_user_string(arg1)))
3431 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003432 ret = get_errno(utime(p, host_tbuf));
3433 unlock_user(p, arg1, 0);
bellardebc05482003-09-30 21:08:41 +00003434 }
3435 break;
thse5febef2007-04-01 18:31:35 +00003436#endif
bellard978a66f2004-12-06 22:58:05 +00003437 case TARGET_NR_utimes:
3438 {
bellard978a66f2004-12-06 22:58:05 +00003439 struct timeval *tvp, tv[2];
pbrook53a59602006-03-25 19:31:22 +00003440 if (arg2) {
ths788f5ec2007-12-09 02:37:05 +00003441 if (copy_from_user_timeval(&tv[0], arg2)
3442 || copy_from_user_timeval(&tv[1],
3443 arg2 + sizeof(struct target_timeval)))
3444 goto efault;
bellard978a66f2004-12-06 22:58:05 +00003445 tvp = tv;
3446 } else {
3447 tvp = NULL;
3448 }
bellard579a97f2007-11-11 14:26:47 +00003449 if (!(p = lock_user_string(arg1)))
3450 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003451 ret = get_errno(utimes(p, tvp));
3452 unlock_user(p, arg1, 0);
bellard978a66f2004-12-06 22:58:05 +00003453 }
3454 break;
bellardebc05482003-09-30 21:08:41 +00003455#ifdef TARGET_NR_stty
bellard31e31b82003-02-18 22:55:36 +00003456 case TARGET_NR_stty:
3457 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00003458#endif
3459#ifdef TARGET_NR_gtty
bellard31e31b82003-02-18 22:55:36 +00003460 case TARGET_NR_gtty:
3461 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00003462#endif
bellard31e31b82003-02-18 22:55:36 +00003463 case TARGET_NR_access:
bellard579a97f2007-11-11 14:26:47 +00003464 if (!(p = lock_user_string(arg1)))
3465 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003466 ret = get_errno(access(p, arg2));
3467 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003468 break;
ths92a34c12007-09-24 09:27:49 +00003469#if defined(TARGET_NR_faccessat) && defined(__NR_faccessat)
3470 case TARGET_NR_faccessat:
bellard579a97f2007-11-11 14:26:47 +00003471 if (!(p = lock_user_string(arg2)))
3472 goto efault;
3473 ret = get_errno(sys_faccessat(arg1, p, arg3, arg4));
3474 unlock_user(p, arg2, 0);
ths92a34c12007-09-24 09:27:49 +00003475 break;
3476#endif
j_mayer7a3148a2007-04-05 07:13:51 +00003477#ifdef TARGET_NR_nice /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00003478 case TARGET_NR_nice:
3479 ret = get_errno(nice(arg1));
3480 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003481#endif
bellardebc05482003-09-30 21:08:41 +00003482#ifdef TARGET_NR_ftime
bellard31e31b82003-02-18 22:55:36 +00003483 case TARGET_NR_ftime:
3484 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00003485#endif
bellard31e31b82003-02-18 22:55:36 +00003486 case TARGET_NR_sync:
bellard04369ff2003-03-20 22:33:23 +00003487 sync();
3488 ret = 0;
bellard31e31b82003-02-18 22:55:36 +00003489 break;
3490 case TARGET_NR_kill:
pbrook4cb05962008-05-30 18:05:19 +00003491 ret = get_errno(kill(arg1, target_to_host_signal(arg2)));
bellard31e31b82003-02-18 22:55:36 +00003492 break;
3493 case TARGET_NR_rename:
pbrook53a59602006-03-25 19:31:22 +00003494 {
3495 void *p2;
3496 p = lock_user_string(arg1);
3497 p2 = lock_user_string(arg2);
bellard579a97f2007-11-11 14:26:47 +00003498 if (!p || !p2)
3499 ret = -TARGET_EFAULT;
3500 else
3501 ret = get_errno(rename(p, p2));
pbrook53a59602006-03-25 19:31:22 +00003502 unlock_user(p2, arg2, 0);
3503 unlock_user(p, arg1, 0);
3504 }
bellard31e31b82003-02-18 22:55:36 +00003505 break;
ths722183f2007-09-24 09:24:37 +00003506#if defined(TARGET_NR_renameat) && defined(__NR_renameat)
3507 case TARGET_NR_renameat:
ths722183f2007-09-24 09:24:37 +00003508 {
bellard579a97f2007-11-11 14:26:47 +00003509 void *p2;
ths722183f2007-09-24 09:24:37 +00003510 p = lock_user_string(arg2);
3511 p2 = lock_user_string(arg4);
bellard579a97f2007-11-11 14:26:47 +00003512 if (!p || !p2)
ths0da46a62007-10-20 20:23:07 +00003513 ret = -TARGET_EFAULT;
ths722183f2007-09-24 09:24:37 +00003514 else
3515 ret = get_errno(sys_renameat(arg1, p, arg3, p2));
bellard579a97f2007-11-11 14:26:47 +00003516 unlock_user(p2, arg4, 0);
3517 unlock_user(p, arg2, 0);
ths722183f2007-09-24 09:24:37 +00003518 }
3519 break;
3520#endif
bellard31e31b82003-02-18 22:55:36 +00003521 case TARGET_NR_mkdir:
bellard579a97f2007-11-11 14:26:47 +00003522 if (!(p = lock_user_string(arg1)))
3523 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003524 ret = get_errno(mkdir(p, arg2));
3525 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003526 break;
ths4472ad02007-09-24 09:22:32 +00003527#if defined(TARGET_NR_mkdirat) && defined(__NR_mkdirat)
3528 case TARGET_NR_mkdirat:
bellard579a97f2007-11-11 14:26:47 +00003529 if (!(p = lock_user_string(arg2)))
3530 goto efault;
3531 ret = get_errno(sys_mkdirat(arg1, p, arg3));
3532 unlock_user(p, arg2, 0);
ths4472ad02007-09-24 09:22:32 +00003533 break;
3534#endif
bellard31e31b82003-02-18 22:55:36 +00003535 case TARGET_NR_rmdir:
bellard579a97f2007-11-11 14:26:47 +00003536 if (!(p = lock_user_string(arg1)))
3537 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003538 ret = get_errno(rmdir(p));
3539 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003540 break;
3541 case TARGET_NR_dup:
3542 ret = get_errno(dup(arg1));
3543 break;
3544 case TARGET_NR_pipe:
3545 {
pbrook53a59602006-03-25 19:31:22 +00003546 int host_pipe[2];
3547 ret = get_errno(pipe(host_pipe));
bellard31e31b82003-02-18 22:55:36 +00003548 if (!is_error(ret)) {
thsc12ab052007-06-01 11:50:36 +00003549#if defined(TARGET_MIPS)
thsead93602007-09-06 00:18:15 +00003550 CPUMIPSState *env = (CPUMIPSState*)cpu_env;
thsd0dc7dc2008-02-12 21:01:26 +00003551 env->gpr[env->current_tc][3] = host_pipe[1];
thsc12ab052007-06-01 11:50:36 +00003552 ret = host_pipe[0];
aurel32b5eff352008-03-11 23:30:22 +00003553#elif defined(TARGET_SH4)
3554 ((CPUSH4State*)cpu_env)->gregs[1] = host_pipe[1];
3555 ret = host_pipe[0];
thsc12ab052007-06-01 11:50:36 +00003556#else
bellard2f619692007-11-16 10:46:05 +00003557 if (put_user_s32(host_pipe[0], arg1)
3558 || put_user_s32(host_pipe[1], arg1 + sizeof(host_pipe[0])))
3559 goto efault;
thsc12ab052007-06-01 11:50:36 +00003560#endif
bellard31e31b82003-02-18 22:55:36 +00003561 }
3562 }
3563 break;
3564 case TARGET_NR_times:
bellard32f36bc2003-03-30 21:29:48 +00003565 {
pbrook53a59602006-03-25 19:31:22 +00003566 struct target_tms *tmsp;
bellard32f36bc2003-03-30 21:29:48 +00003567 struct tms tms;
3568 ret = get_errno(times(&tms));
pbrook53a59602006-03-25 19:31:22 +00003569 if (arg1) {
bellard579a97f2007-11-11 14:26:47 +00003570 tmsp = lock_user(VERIFY_WRITE, arg1, sizeof(struct target_tms), 0);
3571 if (!tmsp)
3572 goto efault;
bellardc596ed12003-07-13 17:32:31 +00003573 tmsp->tms_utime = tswapl(host_to_target_clock_t(tms.tms_utime));
3574 tmsp->tms_stime = tswapl(host_to_target_clock_t(tms.tms_stime));
3575 tmsp->tms_cutime = tswapl(host_to_target_clock_t(tms.tms_cutime));
3576 tmsp->tms_cstime = tswapl(host_to_target_clock_t(tms.tms_cstime));
bellard32f36bc2003-03-30 21:29:48 +00003577 }
bellardc596ed12003-07-13 17:32:31 +00003578 if (!is_error(ret))
3579 ret = host_to_target_clock_t(ret);
bellard32f36bc2003-03-30 21:29:48 +00003580 }
3581 break;
bellardebc05482003-09-30 21:08:41 +00003582#ifdef TARGET_NR_prof
bellard31e31b82003-02-18 22:55:36 +00003583 case TARGET_NR_prof:
3584 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00003585#endif
thse5febef2007-04-01 18:31:35 +00003586#ifdef TARGET_NR_signal
bellard31e31b82003-02-18 22:55:36 +00003587 case TARGET_NR_signal:
3588 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00003589#endif
bellard31e31b82003-02-18 22:55:36 +00003590 case TARGET_NR_acct:
bellard579a97f2007-11-11 14:26:47 +00003591 if (!(p = lock_user_string(arg1)))
3592 goto efault;
pbrook24836682006-04-16 14:14:53 +00003593 ret = get_errno(acct(path(p)));
3594 unlock_user(p, arg1, 0);
3595 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003596#ifdef TARGET_NR_umount2 /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00003597 case TARGET_NR_umount2:
bellard579a97f2007-11-11 14:26:47 +00003598 if (!(p = lock_user_string(arg1)))
3599 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003600 ret = get_errno(umount2(p, arg2));
3601 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003602 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003603#endif
bellardebc05482003-09-30 21:08:41 +00003604#ifdef TARGET_NR_lock
bellard31e31b82003-02-18 22:55:36 +00003605 case TARGET_NR_lock:
3606 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00003607#endif
bellard31e31b82003-02-18 22:55:36 +00003608 case TARGET_NR_ioctl:
3609 ret = do_ioctl(arg1, arg2, arg3);
3610 break;
3611 case TARGET_NR_fcntl:
bellard9ee1fa22007-11-11 15:11:19 +00003612 ret = do_fcntl(arg1, arg2, arg3);
bellard31e31b82003-02-18 22:55:36 +00003613 break;
bellardebc05482003-09-30 21:08:41 +00003614#ifdef TARGET_NR_mpx
bellard31e31b82003-02-18 22:55:36 +00003615 case TARGET_NR_mpx:
3616 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00003617#endif
bellard31e31b82003-02-18 22:55:36 +00003618 case TARGET_NR_setpgid:
3619 ret = get_errno(setpgid(arg1, arg2));
3620 break;
bellardebc05482003-09-30 21:08:41 +00003621#ifdef TARGET_NR_ulimit
bellard31e31b82003-02-18 22:55:36 +00003622 case TARGET_NR_ulimit:
3623 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00003624#endif
3625#ifdef TARGET_NR_oldolduname
bellard31e31b82003-02-18 22:55:36 +00003626 case TARGET_NR_oldolduname:
3627 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00003628#endif
bellard31e31b82003-02-18 22:55:36 +00003629 case TARGET_NR_umask:
3630 ret = get_errno(umask(arg1));
3631 break;
3632 case TARGET_NR_chroot:
bellard579a97f2007-11-11 14:26:47 +00003633 if (!(p = lock_user_string(arg1)))
3634 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003635 ret = get_errno(chroot(p));
3636 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003637 break;
3638 case TARGET_NR_ustat:
3639 goto unimplemented;
3640 case TARGET_NR_dup2:
3641 ret = get_errno(dup2(arg1, arg2));
3642 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003643#ifdef TARGET_NR_getppid /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00003644 case TARGET_NR_getppid:
3645 ret = get_errno(getppid());
3646 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003647#endif
bellard31e31b82003-02-18 22:55:36 +00003648 case TARGET_NR_getpgrp:
3649 ret = get_errno(getpgrp());
3650 break;
3651 case TARGET_NR_setsid:
3652 ret = get_errno(setsid());
3653 break;
thse5febef2007-04-01 18:31:35 +00003654#ifdef TARGET_NR_sigaction
bellard31e31b82003-02-18 22:55:36 +00003655 case TARGET_NR_sigaction:
bellard31e31b82003-02-18 22:55:36 +00003656 {
ths388bb212007-05-13 13:58:00 +00003657#if !defined(TARGET_MIPS)
pbrook53a59602006-03-25 19:31:22 +00003658 struct target_old_sigaction *old_act;
bellard66fb9762003-03-23 01:06:05 +00003659 struct target_sigaction act, oact, *pact;
pbrook53a59602006-03-25 19:31:22 +00003660 if (arg2) {
bellard579a97f2007-11-11 14:26:47 +00003661 if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1))
3662 goto efault;
bellard66fb9762003-03-23 01:06:05 +00003663 act._sa_handler = old_act->_sa_handler;
3664 target_siginitset(&act.sa_mask, old_act->sa_mask);
3665 act.sa_flags = old_act->sa_flags;
3666 act.sa_restorer = old_act->sa_restorer;
pbrook53a59602006-03-25 19:31:22 +00003667 unlock_user_struct(old_act, arg2, 0);
bellard66fb9762003-03-23 01:06:05 +00003668 pact = &act;
3669 } else {
3670 pact = NULL;
3671 }
3672 ret = get_errno(do_sigaction(arg1, pact, &oact));
pbrook53a59602006-03-25 19:31:22 +00003673 if (!is_error(ret) && arg3) {
bellard579a97f2007-11-11 14:26:47 +00003674 if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0))
3675 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003676 old_act->_sa_handler = oact._sa_handler;
3677 old_act->sa_mask = oact.sa_mask.sig[0];
3678 old_act->sa_flags = oact.sa_flags;
3679 old_act->sa_restorer = oact.sa_restorer;
3680 unlock_user_struct(old_act, arg3, 1);
bellard66fb9762003-03-23 01:06:05 +00003681 }
ths388bb212007-05-13 13:58:00 +00003682#else
bellard106ec872006-06-27 21:08:10 +00003683 struct target_sigaction act, oact, *pact, *old_act;
3684
3685 if (arg2) {
bellard579a97f2007-11-11 14:26:47 +00003686 if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1))
3687 goto efault;
bellard106ec872006-06-27 21:08:10 +00003688 act._sa_handler = old_act->_sa_handler;
3689 target_siginitset(&act.sa_mask, old_act->sa_mask.sig[0]);
3690 act.sa_flags = old_act->sa_flags;
3691 unlock_user_struct(old_act, arg2, 0);
3692 pact = &act;
3693 } else {
3694 pact = NULL;
3695 }
3696
3697 ret = get_errno(do_sigaction(arg1, pact, &oact));
3698
3699 if (!is_error(ret) && arg3) {
bellard579a97f2007-11-11 14:26:47 +00003700 if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0))
3701 goto efault;
bellard106ec872006-06-27 21:08:10 +00003702 old_act->_sa_handler = oact._sa_handler;
3703 old_act->sa_flags = oact.sa_flags;
3704 old_act->sa_mask.sig[0] = oact.sa_mask.sig[0];
3705 old_act->sa_mask.sig[1] = 0;
3706 old_act->sa_mask.sig[2] = 0;
3707 old_act->sa_mask.sig[3] = 0;
3708 unlock_user_struct(old_act, arg3, 1);
3709 }
ths388bb212007-05-13 13:58:00 +00003710#endif
bellard31e31b82003-02-18 22:55:36 +00003711 }
3712 break;
thse5febef2007-04-01 18:31:35 +00003713#endif
bellard66fb9762003-03-23 01:06:05 +00003714 case TARGET_NR_rt_sigaction:
pbrook53a59602006-03-25 19:31:22 +00003715 {
3716 struct target_sigaction *act;
3717 struct target_sigaction *oact;
3718
bellard579a97f2007-11-11 14:26:47 +00003719 if (arg2) {
3720 if (!lock_user_struct(VERIFY_READ, act, arg2, 1))
3721 goto efault;
3722 } else
pbrook53a59602006-03-25 19:31:22 +00003723 act = NULL;
bellard579a97f2007-11-11 14:26:47 +00003724 if (arg3) {
3725 if (!lock_user_struct(VERIFY_WRITE, oact, arg3, 0)) {
3726 ret = -TARGET_EFAULT;
3727 goto rt_sigaction_fail;
3728 }
3729 } else
pbrook53a59602006-03-25 19:31:22 +00003730 oact = NULL;
3731 ret = get_errno(do_sigaction(arg1, act, oact));
bellard579a97f2007-11-11 14:26:47 +00003732 rt_sigaction_fail:
3733 if (act)
pbrook53a59602006-03-25 19:31:22 +00003734 unlock_user_struct(act, arg2, 0);
bellard579a97f2007-11-11 14:26:47 +00003735 if (oact)
pbrook53a59602006-03-25 19:31:22 +00003736 unlock_user_struct(oact, arg3, 1);
3737 }
bellard66fb9762003-03-23 01:06:05 +00003738 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003739#ifdef TARGET_NR_sgetmask /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00003740 case TARGET_NR_sgetmask:
bellard66fb9762003-03-23 01:06:05 +00003741 {
3742 sigset_t cur_set;
blueswir1992f48a2007-10-14 16:27:31 +00003743 abi_ulong target_set;
bellard66fb9762003-03-23 01:06:05 +00003744 sigprocmask(0, NULL, &cur_set);
3745 host_to_target_old_sigset(&target_set, &cur_set);
3746 ret = target_set;
3747 }
3748 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003749#endif
3750#ifdef TARGET_NR_ssetmask /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00003751 case TARGET_NR_ssetmask:
bellard66fb9762003-03-23 01:06:05 +00003752 {
3753 sigset_t set, oset, cur_set;
blueswir1992f48a2007-10-14 16:27:31 +00003754 abi_ulong target_set = arg1;
bellard66fb9762003-03-23 01:06:05 +00003755 sigprocmask(0, NULL, &cur_set);
3756 target_to_host_old_sigset(&set, &target_set);
3757 sigorset(&set, &set, &cur_set);
3758 sigprocmask(SIG_SETMASK, &set, &oset);
3759 host_to_target_old_sigset(&target_set, &oset);
3760 ret = target_set;
3761 }
3762 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003763#endif
thse5febef2007-04-01 18:31:35 +00003764#ifdef TARGET_NR_sigprocmask
bellard66fb9762003-03-23 01:06:05 +00003765 case TARGET_NR_sigprocmask:
3766 {
3767 int how = arg1;
3768 sigset_t set, oldset, *set_ptr;
ths3b46e622007-09-17 08:09:54 +00003769
pbrook53a59602006-03-25 19:31:22 +00003770 if (arg2) {
bellard66fb9762003-03-23 01:06:05 +00003771 switch(how) {
3772 case TARGET_SIG_BLOCK:
3773 how = SIG_BLOCK;
3774 break;
3775 case TARGET_SIG_UNBLOCK:
3776 how = SIG_UNBLOCK;
3777 break;
3778 case TARGET_SIG_SETMASK:
3779 how = SIG_SETMASK;
3780 break;
3781 default:
ths0da46a62007-10-20 20:23:07 +00003782 ret = -TARGET_EINVAL;
bellard66fb9762003-03-23 01:06:05 +00003783 goto fail;
3784 }
bellard579a97f2007-11-11 14:26:47 +00003785 if (!(p = lock_user(VERIFY_READ, arg2, sizeof(target_sigset_t), 1)))
3786 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003787 target_to_host_old_sigset(&set, p);
3788 unlock_user(p, arg2, 0);
bellard66fb9762003-03-23 01:06:05 +00003789 set_ptr = &set;
3790 } else {
3791 how = 0;
3792 set_ptr = NULL;
3793 }
3794 ret = get_errno(sigprocmask(arg1, set_ptr, &oldset));
pbrook53a59602006-03-25 19:31:22 +00003795 if (!is_error(ret) && arg3) {
bellard579a97f2007-11-11 14:26:47 +00003796 if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0)))
3797 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003798 host_to_target_old_sigset(p, &oldset);
3799 unlock_user(p, arg3, sizeof(target_sigset_t));
bellard66fb9762003-03-23 01:06:05 +00003800 }
3801 }
3802 break;
thse5febef2007-04-01 18:31:35 +00003803#endif
bellard66fb9762003-03-23 01:06:05 +00003804 case TARGET_NR_rt_sigprocmask:
3805 {
3806 int how = arg1;
3807 sigset_t set, oldset, *set_ptr;
ths3b46e622007-09-17 08:09:54 +00003808
pbrook53a59602006-03-25 19:31:22 +00003809 if (arg2) {
bellard66fb9762003-03-23 01:06:05 +00003810 switch(how) {
3811 case TARGET_SIG_BLOCK:
3812 how = SIG_BLOCK;
3813 break;
3814 case TARGET_SIG_UNBLOCK:
3815 how = SIG_UNBLOCK;
3816 break;
3817 case TARGET_SIG_SETMASK:
3818 how = SIG_SETMASK;
3819 break;
3820 default:
ths0da46a62007-10-20 20:23:07 +00003821 ret = -TARGET_EINVAL;
bellard66fb9762003-03-23 01:06:05 +00003822 goto fail;
3823 }
bellard579a97f2007-11-11 14:26:47 +00003824 if (!(p = lock_user(VERIFY_READ, arg2, sizeof(target_sigset_t), 1)))
3825 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003826 target_to_host_sigset(&set, p);
3827 unlock_user(p, arg2, 0);
bellard66fb9762003-03-23 01:06:05 +00003828 set_ptr = &set;
3829 } else {
3830 how = 0;
3831 set_ptr = NULL;
3832 }
3833 ret = get_errno(sigprocmask(how, set_ptr, &oldset));
pbrook53a59602006-03-25 19:31:22 +00003834 if (!is_error(ret) && arg3) {
bellard579a97f2007-11-11 14:26:47 +00003835 if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0)))
3836 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003837 host_to_target_sigset(p, &oldset);
3838 unlock_user(p, arg3, sizeof(target_sigset_t));
bellard66fb9762003-03-23 01:06:05 +00003839 }
3840 }
3841 break;
thse5febef2007-04-01 18:31:35 +00003842#ifdef TARGET_NR_sigpending
bellard66fb9762003-03-23 01:06:05 +00003843 case TARGET_NR_sigpending:
3844 {
3845 sigset_t set;
3846 ret = get_errno(sigpending(&set));
3847 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00003848 if (!(p = lock_user(VERIFY_WRITE, arg1, sizeof(target_sigset_t), 0)))
3849 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003850 host_to_target_old_sigset(p, &set);
3851 unlock_user(p, arg1, sizeof(target_sigset_t));
bellard66fb9762003-03-23 01:06:05 +00003852 }
3853 }
3854 break;
thse5febef2007-04-01 18:31:35 +00003855#endif
bellard66fb9762003-03-23 01:06:05 +00003856 case TARGET_NR_rt_sigpending:
3857 {
3858 sigset_t set;
3859 ret = get_errno(sigpending(&set));
3860 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00003861 if (!(p = lock_user(VERIFY_WRITE, arg1, sizeof(target_sigset_t), 0)))
3862 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003863 host_to_target_sigset(p, &set);
3864 unlock_user(p, arg1, sizeof(target_sigset_t));
bellard66fb9762003-03-23 01:06:05 +00003865 }
3866 }
3867 break;
thse5febef2007-04-01 18:31:35 +00003868#ifdef TARGET_NR_sigsuspend
bellard66fb9762003-03-23 01:06:05 +00003869 case TARGET_NR_sigsuspend:
3870 {
3871 sigset_t set;
bellard579a97f2007-11-11 14:26:47 +00003872 if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
3873 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003874 target_to_host_old_sigset(&set, p);
3875 unlock_user(p, arg1, 0);
bellard66fb9762003-03-23 01:06:05 +00003876 ret = get_errno(sigsuspend(&set));
3877 }
3878 break;
thse5febef2007-04-01 18:31:35 +00003879#endif
bellard66fb9762003-03-23 01:06:05 +00003880 case TARGET_NR_rt_sigsuspend:
3881 {
3882 sigset_t set;
bellard579a97f2007-11-11 14:26:47 +00003883 if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
3884 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003885 target_to_host_sigset(&set, p);
3886 unlock_user(p, arg1, 0);
bellard66fb9762003-03-23 01:06:05 +00003887 ret = get_errno(sigsuspend(&set));
3888 }
3889 break;
3890 case TARGET_NR_rt_sigtimedwait:
3891 {
bellard66fb9762003-03-23 01:06:05 +00003892 sigset_t set;
3893 struct timespec uts, *puts;
3894 siginfo_t uinfo;
ths3b46e622007-09-17 08:09:54 +00003895
bellard579a97f2007-11-11 14:26:47 +00003896 if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
3897 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003898 target_to_host_sigset(&set, p);
3899 unlock_user(p, arg1, 0);
3900 if (arg3) {
bellard66fb9762003-03-23 01:06:05 +00003901 puts = &uts;
pbrook53a59602006-03-25 19:31:22 +00003902 target_to_host_timespec(puts, arg3);
bellard66fb9762003-03-23 01:06:05 +00003903 } else {
3904 puts = NULL;
3905 }
3906 ret = get_errno(sigtimedwait(&set, &uinfo, puts));
pbrook53a59602006-03-25 19:31:22 +00003907 if (!is_error(ret) && arg2) {
bellard579a97f2007-11-11 14:26:47 +00003908 if (!(p = lock_user(VERIFY_WRITE, arg2, sizeof(target_sigset_t), 0)))
3909 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003910 host_to_target_siginfo(p, &uinfo);
3911 unlock_user(p, arg2, sizeof(target_sigset_t));
bellard66fb9762003-03-23 01:06:05 +00003912 }
3913 }
3914 break;
3915 case TARGET_NR_rt_sigqueueinfo:
3916 {
3917 siginfo_t uinfo;
bellard579a97f2007-11-11 14:26:47 +00003918 if (!(p = lock_user(VERIFY_READ, arg3, sizeof(target_sigset_t), 1)))
3919 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003920 target_to_host_siginfo(&uinfo, p);
3921 unlock_user(p, arg1, 0);
bellard66fb9762003-03-23 01:06:05 +00003922 ret = get_errno(sys_rt_sigqueueinfo(arg1, arg2, &uinfo));
3923 }
3924 break;
thse5febef2007-04-01 18:31:35 +00003925#ifdef TARGET_NR_sigreturn
bellard66fb9762003-03-23 01:06:05 +00003926 case TARGET_NR_sigreturn:
3927 /* NOTE: ret is eax, so not transcoding must be done */
3928 ret = do_sigreturn(cpu_env);
3929 break;
thse5febef2007-04-01 18:31:35 +00003930#endif
bellard66fb9762003-03-23 01:06:05 +00003931 case TARGET_NR_rt_sigreturn:
3932 /* NOTE: ret is eax, so not transcoding must be done */
3933 ret = do_rt_sigreturn(cpu_env);
3934 break;
bellard31e31b82003-02-18 22:55:36 +00003935 case TARGET_NR_sethostname:
bellard579a97f2007-11-11 14:26:47 +00003936 if (!(p = lock_user_string(arg1)))
3937 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003938 ret = get_errno(sethostname(p, arg2));
3939 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003940 break;
3941 case TARGET_NR_setrlimit:
bellard9de5e442003-03-23 16:49:39 +00003942 {
3943 /* XXX: convert resource ? */
3944 int resource = arg1;
pbrook53a59602006-03-25 19:31:22 +00003945 struct target_rlimit *target_rlim;
bellard9de5e442003-03-23 16:49:39 +00003946 struct rlimit rlim;
bellard579a97f2007-11-11 14:26:47 +00003947 if (!lock_user_struct(VERIFY_READ, target_rlim, arg2, 1))
3948 goto efault;
bellard9de5e442003-03-23 16:49:39 +00003949 rlim.rlim_cur = tswapl(target_rlim->rlim_cur);
3950 rlim.rlim_max = tswapl(target_rlim->rlim_max);
pbrook53a59602006-03-25 19:31:22 +00003951 unlock_user_struct(target_rlim, arg2, 0);
bellard9de5e442003-03-23 16:49:39 +00003952 ret = get_errno(setrlimit(resource, &rlim));
3953 }
3954 break;
bellard31e31b82003-02-18 22:55:36 +00003955 case TARGET_NR_getrlimit:
bellard9de5e442003-03-23 16:49:39 +00003956 {
3957 /* XXX: convert resource ? */
3958 int resource = arg1;
pbrook53a59602006-03-25 19:31:22 +00003959 struct target_rlimit *target_rlim;
bellard9de5e442003-03-23 16:49:39 +00003960 struct rlimit rlim;
ths3b46e622007-09-17 08:09:54 +00003961
bellard9de5e442003-03-23 16:49:39 +00003962 ret = get_errno(getrlimit(resource, &rlim));
3963 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00003964 if (!lock_user_struct(VERIFY_WRITE, target_rlim, arg2, 0))
3965 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003966 rlim.rlim_cur = tswapl(target_rlim->rlim_cur);
3967 rlim.rlim_max = tswapl(target_rlim->rlim_max);
3968 unlock_user_struct(target_rlim, arg2, 1);
bellard9de5e442003-03-23 16:49:39 +00003969 }
3970 }
3971 break;
bellard31e31b82003-02-18 22:55:36 +00003972 case TARGET_NR_getrusage:
bellardb4091862003-05-16 15:39:34 +00003973 {
3974 struct rusage rusage;
bellardb4091862003-05-16 15:39:34 +00003975 ret = get_errno(getrusage(arg1, &rusage));
3976 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00003977 host_to_target_rusage(arg2, &rusage);
bellardb4091862003-05-16 15:39:34 +00003978 }
3979 }
3980 break;
bellard31e31b82003-02-18 22:55:36 +00003981 case TARGET_NR_gettimeofday:
3982 {
bellard31e31b82003-02-18 22:55:36 +00003983 struct timeval tv;
3984 ret = get_errno(gettimeofday(&tv, NULL));
3985 if (!is_error(ret)) {
ths788f5ec2007-12-09 02:37:05 +00003986 if (copy_to_user_timeval(arg1, &tv))
3987 goto efault;
bellard31e31b82003-02-18 22:55:36 +00003988 }
3989 }
3990 break;
3991 case TARGET_NR_settimeofday:
3992 {
bellard31e31b82003-02-18 22:55:36 +00003993 struct timeval tv;
ths788f5ec2007-12-09 02:37:05 +00003994 if (copy_from_user_timeval(&tv, arg1))
3995 goto efault;
bellard31e31b82003-02-18 22:55:36 +00003996 ret = get_errno(settimeofday(&tv, NULL));
3997 }
3998 break;
bellard048f6b42005-11-26 18:47:20 +00003999#ifdef TARGET_NR_select
bellard31e31b82003-02-18 22:55:36 +00004000 case TARGET_NR_select:
bellardf2674e32003-07-09 12:26:09 +00004001 {
pbrook53a59602006-03-25 19:31:22 +00004002 struct target_sel_arg_struct *sel;
blueswir1992f48a2007-10-14 16:27:31 +00004003 abi_ulong inp, outp, exp, tvp;
pbrook53a59602006-03-25 19:31:22 +00004004 long nsel;
4005
bellard579a97f2007-11-11 14:26:47 +00004006 if (!lock_user_struct(VERIFY_READ, sel, arg1, 1))
4007 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004008 nsel = tswapl(sel->n);
4009 inp = tswapl(sel->inp);
4010 outp = tswapl(sel->outp);
4011 exp = tswapl(sel->exp);
4012 tvp = tswapl(sel->tvp);
4013 unlock_user_struct(sel, arg1, 0);
4014 ret = do_select(nsel, inp, outp, exp, tvp);
bellardf2674e32003-07-09 12:26:09 +00004015 }
4016 break;
bellard048f6b42005-11-26 18:47:20 +00004017#endif
bellard31e31b82003-02-18 22:55:36 +00004018 case TARGET_NR_symlink:
pbrook53a59602006-03-25 19:31:22 +00004019 {
4020 void *p2;
4021 p = lock_user_string(arg1);
4022 p2 = lock_user_string(arg2);
bellard579a97f2007-11-11 14:26:47 +00004023 if (!p || !p2)
4024 ret = -TARGET_EFAULT;
4025 else
4026 ret = get_errno(symlink(p, p2));
pbrook53a59602006-03-25 19:31:22 +00004027 unlock_user(p2, arg2, 0);
4028 unlock_user(p, arg1, 0);
4029 }
bellard31e31b82003-02-18 22:55:36 +00004030 break;
thsf0b62432007-09-24 09:25:40 +00004031#if defined(TARGET_NR_symlinkat) && defined(__NR_symlinkat)
4032 case TARGET_NR_symlinkat:
thsf0b62432007-09-24 09:25:40 +00004033 {
bellard579a97f2007-11-11 14:26:47 +00004034 void *p2;
thsf0b62432007-09-24 09:25:40 +00004035 p = lock_user_string(arg1);
4036 p2 = lock_user_string(arg3);
bellard579a97f2007-11-11 14:26:47 +00004037 if (!p || !p2)
ths0da46a62007-10-20 20:23:07 +00004038 ret = -TARGET_EFAULT;
thsf0b62432007-09-24 09:25:40 +00004039 else
4040 ret = get_errno(sys_symlinkat(p, arg2, p2));
bellard579a97f2007-11-11 14:26:47 +00004041 unlock_user(p2, arg3, 0);
4042 unlock_user(p, arg1, 0);
thsf0b62432007-09-24 09:25:40 +00004043 }
4044 break;
4045#endif
bellardebc05482003-09-30 21:08:41 +00004046#ifdef TARGET_NR_oldlstat
bellard31e31b82003-02-18 22:55:36 +00004047 case TARGET_NR_oldlstat:
4048 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004049#endif
bellard31e31b82003-02-18 22:55:36 +00004050 case TARGET_NR_readlink:
pbrook53a59602006-03-25 19:31:22 +00004051 {
4052 void *p2;
4053 p = lock_user_string(arg1);
bellard579a97f2007-11-11 14:26:47 +00004054 p2 = lock_user(VERIFY_WRITE, arg2, arg3, 0);
4055 if (!p || !p2)
4056 ret = -TARGET_EFAULT;
4057 else
4058 ret = get_errno(readlink(path(p), p2, arg3));
pbrook53a59602006-03-25 19:31:22 +00004059 unlock_user(p2, arg2, ret);
4060 unlock_user(p, arg1, 0);
4061 }
bellard31e31b82003-02-18 22:55:36 +00004062 break;
ths5e0ccb12007-09-24 09:26:10 +00004063#if defined(TARGET_NR_readlinkat) && defined(__NR_readlinkat)
4064 case TARGET_NR_readlinkat:
ths5e0ccb12007-09-24 09:26:10 +00004065 {
bellard579a97f2007-11-11 14:26:47 +00004066 void *p2;
ths5e0ccb12007-09-24 09:26:10 +00004067 p = lock_user_string(arg2);
bellard579a97f2007-11-11 14:26:47 +00004068 p2 = lock_user(VERIFY_WRITE, arg3, arg4, 0);
4069 if (!p || !p2)
ths0da46a62007-10-20 20:23:07 +00004070 ret = -TARGET_EFAULT;
ths5e0ccb12007-09-24 09:26:10 +00004071 else
4072 ret = get_errno(sys_readlinkat(arg1, path(p), p2, arg4));
bellard579a97f2007-11-11 14:26:47 +00004073 unlock_user(p2, arg3, ret);
4074 unlock_user(p, arg2, 0);
ths5e0ccb12007-09-24 09:26:10 +00004075 }
4076 break;
4077#endif
thse5febef2007-04-01 18:31:35 +00004078#ifdef TARGET_NR_uselib
bellard31e31b82003-02-18 22:55:36 +00004079 case TARGET_NR_uselib:
4080 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00004081#endif
4082#ifdef TARGET_NR_swapon
bellard31e31b82003-02-18 22:55:36 +00004083 case TARGET_NR_swapon:
bellard579a97f2007-11-11 14:26:47 +00004084 if (!(p = lock_user_string(arg1)))
4085 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004086 ret = get_errno(swapon(p, arg2));
4087 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004088 break;
thse5febef2007-04-01 18:31:35 +00004089#endif
bellard31e31b82003-02-18 22:55:36 +00004090 case TARGET_NR_reboot:
4091 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00004092#ifdef TARGET_NR_readdir
bellard31e31b82003-02-18 22:55:36 +00004093 case TARGET_NR_readdir:
4094 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00004095#endif
4096#ifdef TARGET_NR_mmap
bellard31e31b82003-02-18 22:55:36 +00004097 case TARGET_NR_mmap:
bellardd2fd1af2007-11-14 18:08:56 +00004098#if (defined(TARGET_I386) && defined(TARGET_ABI32)) || defined(TARGET_ARM) || defined(TARGET_M68K) || defined(TARGET_CRIS)
bellard31e31b82003-02-18 22:55:36 +00004099 {
blueswir1992f48a2007-10-14 16:27:31 +00004100 abi_ulong *v;
4101 abi_ulong v1, v2, v3, v4, v5, v6;
bellard579a97f2007-11-11 14:26:47 +00004102 if (!(v = lock_user(VERIFY_READ, arg1, 6 * sizeof(abi_ulong), 1)))
4103 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004104 v1 = tswapl(v[0]);
4105 v2 = tswapl(v[1]);
4106 v3 = tswapl(v[2]);
4107 v4 = tswapl(v[3]);
4108 v5 = tswapl(v[4]);
4109 v6 = tswapl(v[5]);
4110 unlock_user(v, arg1, 0);
ths5fafdf22007-09-16 21:08:06 +00004111 ret = get_errno(target_mmap(v1, v2, v3,
bellard5286db72003-06-05 00:57:30 +00004112 target_to_host_bitmask(v4, mmap_flags_tbl),
4113 v5, v6));
bellard31e31b82003-02-18 22:55:36 +00004114 }
bellard31e31b82003-02-18 22:55:36 +00004115#else
ths5fafdf22007-09-16 21:08:06 +00004116 ret = get_errno(target_mmap(arg1, arg2, arg3,
4117 target_to_host_bitmask(arg4, mmap_flags_tbl),
bellard6fb883e2003-07-09 17:12:39 +00004118 arg5,
4119 arg6));
bellard31e31b82003-02-18 22:55:36 +00004120#endif
bellard6fb883e2003-07-09 17:12:39 +00004121 break;
thse5febef2007-04-01 18:31:35 +00004122#endif
bellarda315a142005-01-30 22:59:18 +00004123#ifdef TARGET_NR_mmap2
bellard6fb883e2003-07-09 17:12:39 +00004124 case TARGET_NR_mmap2:
pbrookbb7ec042008-03-25 22:28:25 +00004125#ifndef MMAP_SHIFT
bellardc573ff62004-01-04 15:51:36 +00004126#define MMAP_SHIFT 12
bellardc573ff62004-01-04 15:51:36 +00004127#endif
ths5fafdf22007-09-16 21:08:06 +00004128 ret = get_errno(target_mmap(arg1, arg2, arg3,
4129 target_to_host_bitmask(arg4, mmap_flags_tbl),
bellard5286db72003-06-05 00:57:30 +00004130 arg5,
bellardc573ff62004-01-04 15:51:36 +00004131 arg6 << MMAP_SHIFT));
bellard31e31b82003-02-18 22:55:36 +00004132 break;
bellarda315a142005-01-30 22:59:18 +00004133#endif
bellard31e31b82003-02-18 22:55:36 +00004134 case TARGET_NR_munmap:
bellard54936002003-05-13 00:25:15 +00004135 ret = get_errno(target_munmap(arg1, arg2));
bellard31e31b82003-02-18 22:55:36 +00004136 break;
bellard9de5e442003-03-23 16:49:39 +00004137 case TARGET_NR_mprotect:
bellard54936002003-05-13 00:25:15 +00004138 ret = get_errno(target_mprotect(arg1, arg2, arg3));
bellard9de5e442003-03-23 16:49:39 +00004139 break;
thse5febef2007-04-01 18:31:35 +00004140#ifdef TARGET_NR_mremap
bellard9de5e442003-03-23 16:49:39 +00004141 case TARGET_NR_mremap:
bellard54936002003-05-13 00:25:15 +00004142 ret = get_errno(target_mremap(arg1, arg2, arg3, arg4, arg5));
bellard9de5e442003-03-23 16:49:39 +00004143 break;
thse5febef2007-04-01 18:31:35 +00004144#endif
pbrook53a59602006-03-25 19:31:22 +00004145 /* ??? msync/mlock/munlock are broken for softmmu. */
thse5febef2007-04-01 18:31:35 +00004146#ifdef TARGET_NR_msync
bellard9de5e442003-03-23 16:49:39 +00004147 case TARGET_NR_msync:
pbrook53a59602006-03-25 19:31:22 +00004148 ret = get_errno(msync(g2h(arg1), arg2, arg3));
bellard9de5e442003-03-23 16:49:39 +00004149 break;
thse5febef2007-04-01 18:31:35 +00004150#endif
4151#ifdef TARGET_NR_mlock
bellard9de5e442003-03-23 16:49:39 +00004152 case TARGET_NR_mlock:
pbrook53a59602006-03-25 19:31:22 +00004153 ret = get_errno(mlock(g2h(arg1), arg2));
bellard9de5e442003-03-23 16:49:39 +00004154 break;
thse5febef2007-04-01 18:31:35 +00004155#endif
4156#ifdef TARGET_NR_munlock
bellard9de5e442003-03-23 16:49:39 +00004157 case TARGET_NR_munlock:
pbrook53a59602006-03-25 19:31:22 +00004158 ret = get_errno(munlock(g2h(arg1), arg2));
bellard9de5e442003-03-23 16:49:39 +00004159 break;
thse5febef2007-04-01 18:31:35 +00004160#endif
4161#ifdef TARGET_NR_mlockall
bellard9de5e442003-03-23 16:49:39 +00004162 case TARGET_NR_mlockall:
4163 ret = get_errno(mlockall(arg1));
4164 break;
thse5febef2007-04-01 18:31:35 +00004165#endif
4166#ifdef TARGET_NR_munlockall
bellard9de5e442003-03-23 16:49:39 +00004167 case TARGET_NR_munlockall:
4168 ret = get_errno(munlockall());
4169 break;
thse5febef2007-04-01 18:31:35 +00004170#endif
bellard31e31b82003-02-18 22:55:36 +00004171 case TARGET_NR_truncate:
bellard579a97f2007-11-11 14:26:47 +00004172 if (!(p = lock_user_string(arg1)))
4173 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004174 ret = get_errno(truncate(p, arg2));
4175 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004176 break;
4177 case TARGET_NR_ftruncate:
4178 ret = get_errno(ftruncate(arg1, arg2));
4179 break;
4180 case TARGET_NR_fchmod:
4181 ret = get_errno(fchmod(arg1, arg2));
4182 break;
ths814d7972007-09-24 09:26:51 +00004183#if defined(TARGET_NR_fchmodat) && defined(__NR_fchmodat)
4184 case TARGET_NR_fchmodat:
bellard579a97f2007-11-11 14:26:47 +00004185 if (!(p = lock_user_string(arg2)))
4186 goto efault;
4187 ret = get_errno(sys_fchmodat(arg1, p, arg3, arg4));
4188 unlock_user(p, arg2, 0);
ths814d7972007-09-24 09:26:51 +00004189 break;
4190#endif
bellard31e31b82003-02-18 22:55:36 +00004191 case TARGET_NR_getpriority:
thsc6cda172007-10-09 03:42:34 +00004192 /* libc does special remapping of the return value of
4193 * sys_getpriority() so it's just easiest to call
4194 * sys_getpriority() directly rather than through libc. */
4195 ret = sys_getpriority(arg1, arg2);
bellard31e31b82003-02-18 22:55:36 +00004196 break;
4197 case TARGET_NR_setpriority:
4198 ret = get_errno(setpriority(arg1, arg2, arg3));
4199 break;
bellardebc05482003-09-30 21:08:41 +00004200#ifdef TARGET_NR_profil
bellard31e31b82003-02-18 22:55:36 +00004201 case TARGET_NR_profil:
4202 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004203#endif
bellard31e31b82003-02-18 22:55:36 +00004204 case TARGET_NR_statfs:
bellard579a97f2007-11-11 14:26:47 +00004205 if (!(p = lock_user_string(arg1)))
4206 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004207 ret = get_errno(statfs(path(p), &stfs));
4208 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004209 convert_statfs:
4210 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00004211 struct target_statfs *target_stfs;
ths3b46e622007-09-17 08:09:54 +00004212
bellard579a97f2007-11-11 14:26:47 +00004213 if (!lock_user_struct(VERIFY_WRITE, target_stfs, arg2, 0))
4214 goto efault;
4215 __put_user(stfs.f_type, &target_stfs->f_type);
4216 __put_user(stfs.f_bsize, &target_stfs->f_bsize);
4217 __put_user(stfs.f_blocks, &target_stfs->f_blocks);
4218 __put_user(stfs.f_bfree, &target_stfs->f_bfree);
4219 __put_user(stfs.f_bavail, &target_stfs->f_bavail);
4220 __put_user(stfs.f_files, &target_stfs->f_files);
4221 __put_user(stfs.f_ffree, &target_stfs->f_ffree);
4222 __put_user(stfs.f_fsid.__val[0], &target_stfs->f_fsid.val[0]);
4223 __put_user(stfs.f_fsid.__val[1], &target_stfs->f_fsid.val[1]);
4224 __put_user(stfs.f_namelen, &target_stfs->f_namelen);
pbrook53a59602006-03-25 19:31:22 +00004225 unlock_user_struct(target_stfs, arg2, 1);
bellard31e31b82003-02-18 22:55:36 +00004226 }
4227 break;
4228 case TARGET_NR_fstatfs:
bellard56c8f682005-11-28 22:28:41 +00004229 ret = get_errno(fstatfs(arg1, &stfs));
bellard31e31b82003-02-18 22:55:36 +00004230 goto convert_statfs;
bellard56c8f682005-11-28 22:28:41 +00004231#ifdef TARGET_NR_statfs64
4232 case TARGET_NR_statfs64:
bellard579a97f2007-11-11 14:26:47 +00004233 if (!(p = lock_user_string(arg1)))
4234 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004235 ret = get_errno(statfs(path(p), &stfs));
4236 unlock_user(p, arg1, 0);
bellard56c8f682005-11-28 22:28:41 +00004237 convert_statfs64:
4238 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00004239 struct target_statfs64 *target_stfs;
ths3b46e622007-09-17 08:09:54 +00004240
bellard579a97f2007-11-11 14:26:47 +00004241 if (!lock_user_struct(VERIFY_WRITE, target_stfs, arg3, 0))
4242 goto efault;
4243 __put_user(stfs.f_type, &target_stfs->f_type);
4244 __put_user(stfs.f_bsize, &target_stfs->f_bsize);
4245 __put_user(stfs.f_blocks, &target_stfs->f_blocks);
4246 __put_user(stfs.f_bfree, &target_stfs->f_bfree);
4247 __put_user(stfs.f_bavail, &target_stfs->f_bavail);
4248 __put_user(stfs.f_files, &target_stfs->f_files);
4249 __put_user(stfs.f_ffree, &target_stfs->f_ffree);
4250 __put_user(stfs.f_fsid.__val[0], &target_stfs->f_fsid.val[0]);
4251 __put_user(stfs.f_fsid.__val[1], &target_stfs->f_fsid.val[1]);
4252 __put_user(stfs.f_namelen, &target_stfs->f_namelen);
4253 unlock_user_struct(target_stfs, arg3, 1);
bellard56c8f682005-11-28 22:28:41 +00004254 }
4255 break;
4256 case TARGET_NR_fstatfs64:
4257 ret = get_errno(fstatfs(arg1, &stfs));
4258 goto convert_statfs64;
4259#endif
bellardebc05482003-09-30 21:08:41 +00004260#ifdef TARGET_NR_ioperm
bellard31e31b82003-02-18 22:55:36 +00004261 case TARGET_NR_ioperm:
4262 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004263#endif
thse5febef2007-04-01 18:31:35 +00004264#ifdef TARGET_NR_socketcall
bellard31e31b82003-02-18 22:55:36 +00004265 case TARGET_NR_socketcall:
pbrook53a59602006-03-25 19:31:22 +00004266 ret = do_socketcall(arg1, arg2);
bellard31e31b82003-02-18 22:55:36 +00004267 break;
thse5febef2007-04-01 18:31:35 +00004268#endif
bellard3532fa72006-06-24 15:06:03 +00004269#ifdef TARGET_NR_accept
4270 case TARGET_NR_accept:
pbrook1be9e1d2006-11-19 15:26:04 +00004271 ret = do_accept(arg1, arg2, arg3);
bellard3532fa72006-06-24 15:06:03 +00004272 break;
4273#endif
4274#ifdef TARGET_NR_bind
4275 case TARGET_NR_bind:
4276 ret = do_bind(arg1, arg2, arg3);
4277 break;
4278#endif
4279#ifdef TARGET_NR_connect
4280 case TARGET_NR_connect:
4281 ret = do_connect(arg1, arg2, arg3);
4282 break;
4283#endif
4284#ifdef TARGET_NR_getpeername
4285 case TARGET_NR_getpeername:
pbrook1be9e1d2006-11-19 15:26:04 +00004286 ret = do_getpeername(arg1, arg2, arg3);
bellard3532fa72006-06-24 15:06:03 +00004287 break;
4288#endif
4289#ifdef TARGET_NR_getsockname
4290 case TARGET_NR_getsockname:
pbrook1be9e1d2006-11-19 15:26:04 +00004291 ret = do_getsockname(arg1, arg2, arg3);
bellard3532fa72006-06-24 15:06:03 +00004292 break;
4293#endif
4294#ifdef TARGET_NR_getsockopt
4295 case TARGET_NR_getsockopt:
4296 ret = do_getsockopt(arg1, arg2, arg3, arg4, arg5);
4297 break;
4298#endif
4299#ifdef TARGET_NR_listen
4300 case TARGET_NR_listen:
pbrook1be9e1d2006-11-19 15:26:04 +00004301 ret = get_errno(listen(arg1, arg2));
bellard3532fa72006-06-24 15:06:03 +00004302 break;
4303#endif
4304#ifdef TARGET_NR_recv
4305 case TARGET_NR_recv:
pbrook214201b2007-03-17 01:27:24 +00004306 ret = do_recvfrom(arg1, arg2, arg3, arg4, 0, 0);
bellard3532fa72006-06-24 15:06:03 +00004307 break;
4308#endif
4309#ifdef TARGET_NR_recvfrom
4310 case TARGET_NR_recvfrom:
pbrook214201b2007-03-17 01:27:24 +00004311 ret = do_recvfrom(arg1, arg2, arg3, arg4, arg5, arg6);
bellard3532fa72006-06-24 15:06:03 +00004312 break;
4313#endif
4314#ifdef TARGET_NR_recvmsg
4315 case TARGET_NR_recvmsg:
4316 ret = do_sendrecvmsg(arg1, arg2, arg3, 0);
4317 break;
4318#endif
4319#ifdef TARGET_NR_send
4320 case TARGET_NR_send:
pbrook1be9e1d2006-11-19 15:26:04 +00004321 ret = do_sendto(arg1, arg2, arg3, arg4, 0, 0);
bellard3532fa72006-06-24 15:06:03 +00004322 break;
4323#endif
4324#ifdef TARGET_NR_sendmsg
4325 case TARGET_NR_sendmsg:
4326 ret = do_sendrecvmsg(arg1, arg2, arg3, 1);
4327 break;
4328#endif
4329#ifdef TARGET_NR_sendto
4330 case TARGET_NR_sendto:
pbrook1be9e1d2006-11-19 15:26:04 +00004331 ret = do_sendto(arg1, arg2, arg3, arg4, arg5, arg6);
bellard3532fa72006-06-24 15:06:03 +00004332 break;
4333#endif
4334#ifdef TARGET_NR_shutdown
4335 case TARGET_NR_shutdown:
pbrook1be9e1d2006-11-19 15:26:04 +00004336 ret = get_errno(shutdown(arg1, arg2));
bellard3532fa72006-06-24 15:06:03 +00004337 break;
4338#endif
4339#ifdef TARGET_NR_socket
4340 case TARGET_NR_socket:
4341 ret = do_socket(arg1, arg2, arg3);
4342 break;
4343#endif
4344#ifdef TARGET_NR_socketpair
4345 case TARGET_NR_socketpair:
pbrook1be9e1d2006-11-19 15:26:04 +00004346 ret = do_socketpair(arg1, arg2, arg3, arg4);
bellard3532fa72006-06-24 15:06:03 +00004347 break;
4348#endif
4349#ifdef TARGET_NR_setsockopt
4350 case TARGET_NR_setsockopt:
4351 ret = do_setsockopt(arg1, arg2, arg3, arg4, (socklen_t) arg5);
4352 break;
4353#endif
ths7494b0f2007-02-11 18:26:53 +00004354
bellard31e31b82003-02-18 22:55:36 +00004355 case TARGET_NR_syslog:
bellard579a97f2007-11-11 14:26:47 +00004356 if (!(p = lock_user_string(arg2)))
4357 goto efault;
thse5574482007-02-11 20:03:13 +00004358 ret = get_errno(sys_syslog((int)arg1, p, (int)arg3));
4359 unlock_user(p, arg2, 0);
ths7494b0f2007-02-11 18:26:53 +00004360 break;
4361
bellard31e31b82003-02-18 22:55:36 +00004362 case TARGET_NR_setitimer:
bellard66fb9762003-03-23 01:06:05 +00004363 {
bellard66fb9762003-03-23 01:06:05 +00004364 struct itimerval value, ovalue, *pvalue;
4365
pbrook53a59602006-03-25 19:31:22 +00004366 if (arg2) {
bellard66fb9762003-03-23 01:06:05 +00004367 pvalue = &value;
ths788f5ec2007-12-09 02:37:05 +00004368 if (copy_from_user_timeval(&pvalue->it_interval, arg2)
4369 || copy_from_user_timeval(&pvalue->it_value,
4370 arg2 + sizeof(struct target_timeval)))
4371 goto efault;
bellard66fb9762003-03-23 01:06:05 +00004372 } else {
4373 pvalue = NULL;
4374 }
4375 ret = get_errno(setitimer(arg1, pvalue, &ovalue));
pbrook53a59602006-03-25 19:31:22 +00004376 if (!is_error(ret) && arg3) {
ths788f5ec2007-12-09 02:37:05 +00004377 if (copy_to_user_timeval(arg3,
4378 &ovalue.it_interval)
4379 || copy_to_user_timeval(arg3 + sizeof(struct target_timeval),
4380 &ovalue.it_value))
4381 goto efault;
bellard66fb9762003-03-23 01:06:05 +00004382 }
4383 }
4384 break;
bellard31e31b82003-02-18 22:55:36 +00004385 case TARGET_NR_getitimer:
bellard66fb9762003-03-23 01:06:05 +00004386 {
bellard66fb9762003-03-23 01:06:05 +00004387 struct itimerval value;
ths3b46e622007-09-17 08:09:54 +00004388
bellard66fb9762003-03-23 01:06:05 +00004389 ret = get_errno(getitimer(arg1, &value));
pbrook53a59602006-03-25 19:31:22 +00004390 if (!is_error(ret) && arg2) {
ths788f5ec2007-12-09 02:37:05 +00004391 if (copy_to_user_timeval(arg2,
4392 &value.it_interval)
4393 || copy_to_user_timeval(arg2 + sizeof(struct target_timeval),
4394 &value.it_value))
4395 goto efault;
bellard66fb9762003-03-23 01:06:05 +00004396 }
4397 }
4398 break;
bellard31e31b82003-02-18 22:55:36 +00004399 case TARGET_NR_stat:
bellard579a97f2007-11-11 14:26:47 +00004400 if (!(p = lock_user_string(arg1)))
4401 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004402 ret = get_errno(stat(path(p), &st));
4403 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004404 goto do_stat;
4405 case TARGET_NR_lstat:
bellard579a97f2007-11-11 14:26:47 +00004406 if (!(p = lock_user_string(arg1)))
4407 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004408 ret = get_errno(lstat(path(p), &st));
4409 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004410 goto do_stat;
4411 case TARGET_NR_fstat:
4412 {
4413 ret = get_errno(fstat(arg1, &st));
4414 do_stat:
4415 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00004416 struct target_stat *target_st;
thse3584652007-06-01 11:49:38 +00004417
bellard579a97f2007-11-11 14:26:47 +00004418 if (!lock_user_struct(VERIFY_WRITE, target_st, arg2, 0))
4419 goto efault;
bellardd2fd1af2007-11-14 18:08:56 +00004420 __put_user(st.st_dev, &target_st->st_dev);
4421 __put_user(st.st_ino, &target_st->st_ino);
4422 __put_user(st.st_mode, &target_st->st_mode);
4423 __put_user(st.st_uid, &target_st->st_uid);
4424 __put_user(st.st_gid, &target_st->st_gid);
4425 __put_user(st.st_nlink, &target_st->st_nlink);
4426 __put_user(st.st_rdev, &target_st->st_rdev);
4427 __put_user(st.st_size, &target_st->st_size);
4428 __put_user(st.st_blksize, &target_st->st_blksize);
4429 __put_user(st.st_blocks, &target_st->st_blocks);
4430 __put_user(st.st_atime, &target_st->target_st_atime);
4431 __put_user(st.st_mtime, &target_st->target_st_mtime);
4432 __put_user(st.st_ctime, &target_st->target_st_ctime);
pbrook53a59602006-03-25 19:31:22 +00004433 unlock_user_struct(target_st, arg2, 1);
bellard31e31b82003-02-18 22:55:36 +00004434 }
4435 }
4436 break;
bellardebc05482003-09-30 21:08:41 +00004437#ifdef TARGET_NR_olduname
bellard31e31b82003-02-18 22:55:36 +00004438 case TARGET_NR_olduname:
4439 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004440#endif
4441#ifdef TARGET_NR_iopl
bellard31e31b82003-02-18 22:55:36 +00004442 case TARGET_NR_iopl:
4443 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004444#endif
bellard31e31b82003-02-18 22:55:36 +00004445 case TARGET_NR_vhangup:
4446 ret = get_errno(vhangup());
4447 break;
bellardebc05482003-09-30 21:08:41 +00004448#ifdef TARGET_NR_idle
bellard31e31b82003-02-18 22:55:36 +00004449 case TARGET_NR_idle:
4450 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004451#endif
bellard42ad6ae2005-01-03 22:48:11 +00004452#ifdef TARGET_NR_syscall
4453 case TARGET_NR_syscall:
4454 ret = do_syscall(cpu_env,arg1 & 0xffff,arg2,arg3,arg4,arg5,arg6,0);
4455 break;
4456#endif
bellard31e31b82003-02-18 22:55:36 +00004457 case TARGET_NR_wait4:
4458 {
4459 int status;
blueswir1992f48a2007-10-14 16:27:31 +00004460 abi_long status_ptr = arg2;
bellard31e31b82003-02-18 22:55:36 +00004461 struct rusage rusage, *rusage_ptr;
blueswir1992f48a2007-10-14 16:27:31 +00004462 abi_ulong target_rusage = arg4;
bellard31e31b82003-02-18 22:55:36 +00004463 if (target_rusage)
4464 rusage_ptr = &rusage;
4465 else
4466 rusage_ptr = NULL;
4467 ret = get_errno(wait4(arg1, &status, arg3, rusage_ptr));
4468 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +00004469 if (status_ptr) {
4470 if (put_user_s32(status, status_ptr))
4471 goto efault;
bellard31e31b82003-02-18 22:55:36 +00004472 }
bellard2f619692007-11-16 10:46:05 +00004473 if (target_rusage)
4474 host_to_target_rusage(target_rusage, &rusage);
bellard31e31b82003-02-18 22:55:36 +00004475 }
4476 }
4477 break;
thse5febef2007-04-01 18:31:35 +00004478#ifdef TARGET_NR_swapoff
bellard31e31b82003-02-18 22:55:36 +00004479 case TARGET_NR_swapoff:
bellard579a97f2007-11-11 14:26:47 +00004480 if (!(p = lock_user_string(arg1)))
4481 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004482 ret = get_errno(swapoff(p));
4483 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004484 break;
thse5febef2007-04-01 18:31:35 +00004485#endif
bellard31e31b82003-02-18 22:55:36 +00004486 case TARGET_NR_sysinfo:
bellarda5448a72004-06-19 16:59:03 +00004487 {
pbrook53a59602006-03-25 19:31:22 +00004488 struct target_sysinfo *target_value;
bellarda5448a72004-06-19 16:59:03 +00004489 struct sysinfo value;
4490 ret = get_errno(sysinfo(&value));
pbrook53a59602006-03-25 19:31:22 +00004491 if (!is_error(ret) && arg1)
bellarda5448a72004-06-19 16:59:03 +00004492 {
bellard579a97f2007-11-11 14:26:47 +00004493 if (!lock_user_struct(VERIFY_WRITE, target_value, arg1, 0))
4494 goto efault;
bellarda5448a72004-06-19 16:59:03 +00004495 __put_user(value.uptime, &target_value->uptime);
4496 __put_user(value.loads[0], &target_value->loads[0]);
4497 __put_user(value.loads[1], &target_value->loads[1]);
4498 __put_user(value.loads[2], &target_value->loads[2]);
4499 __put_user(value.totalram, &target_value->totalram);
4500 __put_user(value.freeram, &target_value->freeram);
4501 __put_user(value.sharedram, &target_value->sharedram);
4502 __put_user(value.bufferram, &target_value->bufferram);
4503 __put_user(value.totalswap, &target_value->totalswap);
4504 __put_user(value.freeswap, &target_value->freeswap);
4505 __put_user(value.procs, &target_value->procs);
4506 __put_user(value.totalhigh, &target_value->totalhigh);
4507 __put_user(value.freehigh, &target_value->freehigh);
4508 __put_user(value.mem_unit, &target_value->mem_unit);
pbrook53a59602006-03-25 19:31:22 +00004509 unlock_user_struct(target_value, arg1, 1);
bellarda5448a72004-06-19 16:59:03 +00004510 }
4511 }
4512 break;
thse5febef2007-04-01 18:31:35 +00004513#ifdef TARGET_NR_ipc
bellard31e31b82003-02-18 22:55:36 +00004514 case TARGET_NR_ipc:
bellard8853f862004-02-22 14:57:26 +00004515 ret = do_ipc(arg1, arg2, arg3, arg4, arg5, arg6);
4516 break;
thse5febef2007-04-01 18:31:35 +00004517#endif
bellard31e31b82003-02-18 22:55:36 +00004518 case TARGET_NR_fsync:
4519 ret = get_errno(fsync(arg1));
4520 break;
bellard31e31b82003-02-18 22:55:36 +00004521 case TARGET_NR_clone:
bellard1b6b0292003-03-22 17:31:38 +00004522 ret = get_errno(do_fork(cpu_env, arg1, arg2));
4523 break;
bellardec86b0f2003-04-11 00:15:04 +00004524#ifdef __NR_exit_group
4525 /* new thread calls */
4526 case TARGET_NR_exit_group:
bellarde9009672005-04-26 20:42:36 +00004527 gdb_exit(cpu_env, arg1);
bellardec86b0f2003-04-11 00:15:04 +00004528 ret = get_errno(exit_group(arg1));
4529 break;
4530#endif
bellard31e31b82003-02-18 22:55:36 +00004531 case TARGET_NR_setdomainname:
bellard579a97f2007-11-11 14:26:47 +00004532 if (!(p = lock_user_string(arg1)))
4533 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004534 ret = get_errno(setdomainname(p, arg2));
4535 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004536 break;
4537 case TARGET_NR_uname:
4538 /* no need to transcode because we use the linux syscall */
bellard29e619b2004-09-13 21:41:04 +00004539 {
4540 struct new_utsname * buf;
ths3b46e622007-09-17 08:09:54 +00004541
bellard579a97f2007-11-11 14:26:47 +00004542 if (!lock_user_struct(VERIFY_WRITE, buf, arg1, 0))
4543 goto efault;
bellard29e619b2004-09-13 21:41:04 +00004544 ret = get_errno(sys_uname(buf));
4545 if (!is_error(ret)) {
4546 /* Overrite the native machine name with whatever is being
4547 emulated. */
4548 strcpy (buf->machine, UNAME_MACHINE);
pbrookc5937222006-05-14 11:30:38 +00004549 /* Allow the user to override the reported release. */
4550 if (qemu_uname_release && *qemu_uname_release)
4551 strcpy (buf->release, qemu_uname_release);
bellard29e619b2004-09-13 21:41:04 +00004552 }
pbrook53a59602006-03-25 19:31:22 +00004553 unlock_user_struct(buf, arg1, 1);
bellard29e619b2004-09-13 21:41:04 +00004554 }
bellard31e31b82003-02-18 22:55:36 +00004555 break;
bellard6dbad632003-03-16 18:05:05 +00004556#ifdef TARGET_I386
bellard31e31b82003-02-18 22:55:36 +00004557 case TARGET_NR_modify_ldt:
bellard03acab62007-11-11 14:57:14 +00004558 ret = do_modify_ldt(cpu_env, arg1, arg2, arg3);
bellard5cd43932003-03-29 16:54:36 +00004559 break;
j_mayer84409dd2007-04-06 08:56:50 +00004560#if !defined(TARGET_X86_64)
bellard5cd43932003-03-29 16:54:36 +00004561 case TARGET_NR_vm86old:
4562 goto unimplemented;
4563 case TARGET_NR_vm86:
pbrook53a59602006-03-25 19:31:22 +00004564 ret = do_vm86(cpu_env, arg1, arg2);
bellard6dbad632003-03-16 18:05:05 +00004565 break;
4566#endif
j_mayer84409dd2007-04-06 08:56:50 +00004567#endif
bellard31e31b82003-02-18 22:55:36 +00004568 case TARGET_NR_adjtimex:
4569 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00004570#ifdef TARGET_NR_create_module
bellard31e31b82003-02-18 22:55:36 +00004571 case TARGET_NR_create_module:
thse5febef2007-04-01 18:31:35 +00004572#endif
bellard31e31b82003-02-18 22:55:36 +00004573 case TARGET_NR_init_module:
4574 case TARGET_NR_delete_module:
thse5febef2007-04-01 18:31:35 +00004575#ifdef TARGET_NR_get_kernel_syms
bellard31e31b82003-02-18 22:55:36 +00004576 case TARGET_NR_get_kernel_syms:
thse5febef2007-04-01 18:31:35 +00004577#endif
bellard31e31b82003-02-18 22:55:36 +00004578 goto unimplemented;
4579 case TARGET_NR_quotactl:
4580 goto unimplemented;
4581 case TARGET_NR_getpgid:
4582 ret = get_errno(getpgid(arg1));
4583 break;
4584 case TARGET_NR_fchdir:
4585 ret = get_errno(fchdir(arg1));
4586 break;
j_mayer84409dd2007-04-06 08:56:50 +00004587#ifdef TARGET_NR_bdflush /* not on x86_64 */
bellard31e31b82003-02-18 22:55:36 +00004588 case TARGET_NR_bdflush:
4589 goto unimplemented;
j_mayer84409dd2007-04-06 08:56:50 +00004590#endif
thse5febef2007-04-01 18:31:35 +00004591#ifdef TARGET_NR_sysfs
bellard31e31b82003-02-18 22:55:36 +00004592 case TARGET_NR_sysfs:
4593 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00004594#endif
bellard31e31b82003-02-18 22:55:36 +00004595 case TARGET_NR_personality:
bellard1b6b0292003-03-22 17:31:38 +00004596 ret = get_errno(personality(arg1));
bellard31e31b82003-02-18 22:55:36 +00004597 break;
thse5febef2007-04-01 18:31:35 +00004598#ifdef TARGET_NR_afs_syscall
bellard31e31b82003-02-18 22:55:36 +00004599 case TARGET_NR_afs_syscall:
4600 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00004601#endif
j_mayer7a3148a2007-04-05 07:13:51 +00004602#ifdef TARGET_NR__llseek /* Not on alpha */
bellard31e31b82003-02-18 22:55:36 +00004603 case TARGET_NR__llseek:
4604 {
bellard4f2ac232004-04-26 19:44:02 +00004605#if defined (__x86_64__)
4606 ret = get_errno(lseek(arg1, ((uint64_t )arg2 << 32) | arg3, arg5));
bellard2f619692007-11-16 10:46:05 +00004607 if (put_user_s64(ret, arg4))
4608 goto efault;
bellard4f2ac232004-04-26 19:44:02 +00004609#else
bellard31e31b82003-02-18 22:55:36 +00004610 int64_t res;
4611 ret = get_errno(_llseek(arg1, arg2, arg3, &res, arg5));
bellard2f619692007-11-16 10:46:05 +00004612 if (put_user_s64(res, arg4))
4613 goto efault;
bellard4f2ac232004-04-26 19:44:02 +00004614#endif
bellard31e31b82003-02-18 22:55:36 +00004615 }
4616 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004617#endif
bellard31e31b82003-02-18 22:55:36 +00004618 case TARGET_NR_getdents:
blueswir1992f48a2007-10-14 16:27:31 +00004619#if TARGET_ABI_BITS != 32
pbrook53a59602006-03-25 19:31:22 +00004620 goto unimplemented;
blueswir1992f48a2007-10-14 16:27:31 +00004621#elif TARGET_ABI_BITS == 32 && HOST_LONG_BITS == 64
bellard4add45b2003-06-05 01:52:59 +00004622 {
pbrook53a59602006-03-25 19:31:22 +00004623 struct target_dirent *target_dirp;
bellard4add45b2003-06-05 01:52:59 +00004624 struct dirent *dirp;
blueswir1992f48a2007-10-14 16:27:31 +00004625 abi_long count = arg3;
bellard4add45b2003-06-05 01:52:59 +00004626
4627 dirp = malloc(count);
ths0da46a62007-10-20 20:23:07 +00004628 if (!dirp) {
bellard579a97f2007-11-11 14:26:47 +00004629 ret = -TARGET_ENOMEM;
ths0da46a62007-10-20 20:23:07 +00004630 goto fail;
4631 }
ths3b46e622007-09-17 08:09:54 +00004632
bellard4add45b2003-06-05 01:52:59 +00004633 ret = get_errno(sys_getdents(arg1, dirp, count));
4634 if (!is_error(ret)) {
4635 struct dirent *de;
4636 struct target_dirent *tde;
4637 int len = ret;
4638 int reclen, treclen;
4639 int count1, tnamelen;
4640
4641 count1 = 0;
4642 de = dirp;
bellard579a97f2007-11-11 14:26:47 +00004643 if (!(target_dirp = lock_user(VERIFY_WRITE, arg2, count, 0)))
4644 goto efault;
bellard4add45b2003-06-05 01:52:59 +00004645 tde = target_dirp;
4646 while (len > 0) {
4647 reclen = de->d_reclen;
blueswir1992f48a2007-10-14 16:27:31 +00004648 treclen = reclen - (2 * (sizeof(long) - sizeof(abi_long)));
bellard4add45b2003-06-05 01:52:59 +00004649 tde->d_reclen = tswap16(treclen);
4650 tde->d_ino = tswapl(de->d_ino);
4651 tde->d_off = tswapl(de->d_off);
blueswir1992f48a2007-10-14 16:27:31 +00004652 tnamelen = treclen - (2 * sizeof(abi_long) + 2);
bellard4add45b2003-06-05 01:52:59 +00004653 if (tnamelen > 256)
4654 tnamelen = 256;
bellard80a9d032005-01-03 23:31:27 +00004655 /* XXX: may not be correct */
bellard4add45b2003-06-05 01:52:59 +00004656 strncpy(tde->d_name, de->d_name, tnamelen);
4657 de = (struct dirent *)((char *)de + reclen);
4658 len -= reclen;
j_mayer1c5bf3b2007-04-14 12:17:59 +00004659 tde = (struct target_dirent *)((char *)tde + treclen);
bellard4add45b2003-06-05 01:52:59 +00004660 count1 += treclen;
4661 }
4662 ret = count1;
bellard579a97f2007-11-11 14:26:47 +00004663 unlock_user(target_dirp, arg2, ret);
bellard4add45b2003-06-05 01:52:59 +00004664 }
4665 free(dirp);
4666 }
4667#else
bellard31e31b82003-02-18 22:55:36 +00004668 {
pbrook53a59602006-03-25 19:31:22 +00004669 struct dirent *dirp;
blueswir1992f48a2007-10-14 16:27:31 +00004670 abi_long count = arg3;
bellarddab2ed92003-03-22 15:23:14 +00004671
bellard579a97f2007-11-11 14:26:47 +00004672 if (!(dirp = lock_user(VERIFY_WRITE, arg2, count, 0)))
4673 goto efault;
bellard72f03902003-02-18 23:33:18 +00004674 ret = get_errno(sys_getdents(arg1, dirp, count));
bellard31e31b82003-02-18 22:55:36 +00004675 if (!is_error(ret)) {
4676 struct dirent *de;
4677 int len = ret;
4678 int reclen;
4679 de = dirp;
4680 while (len > 0) {
bellard8083a3e2003-03-24 23:12:16 +00004681 reclen = de->d_reclen;
bellard31e31b82003-02-18 22:55:36 +00004682 if (reclen > len)
4683 break;
bellard8083a3e2003-03-24 23:12:16 +00004684 de->d_reclen = tswap16(reclen);
bellard31e31b82003-02-18 22:55:36 +00004685 tswapls(&de->d_ino);
4686 tswapls(&de->d_off);
4687 de = (struct dirent *)((char *)de + reclen);
4688 len -= reclen;
4689 }
4690 }
pbrook53a59602006-03-25 19:31:22 +00004691 unlock_user(dirp, arg2, ret);
bellard31e31b82003-02-18 22:55:36 +00004692 }
bellard4add45b2003-06-05 01:52:59 +00004693#endif
bellard31e31b82003-02-18 22:55:36 +00004694 break;
ths3ae43202007-09-16 21:39:48 +00004695#if defined(TARGET_NR_getdents64) && defined(__NR_getdents64)
bellarddab2ed92003-03-22 15:23:14 +00004696 case TARGET_NR_getdents64:
4697 {
pbrook53a59602006-03-25 19:31:22 +00004698 struct dirent64 *dirp;
blueswir1992f48a2007-10-14 16:27:31 +00004699 abi_long count = arg3;
bellard579a97f2007-11-11 14:26:47 +00004700 if (!(dirp = lock_user(VERIFY_WRITE, arg2, count, 0)))
4701 goto efault;
bellarddab2ed92003-03-22 15:23:14 +00004702 ret = get_errno(sys_getdents64(arg1, dirp, count));
4703 if (!is_error(ret)) {
4704 struct dirent64 *de;
4705 int len = ret;
4706 int reclen;
4707 de = dirp;
4708 while (len > 0) {
bellard8083a3e2003-03-24 23:12:16 +00004709 reclen = de->d_reclen;
bellarddab2ed92003-03-22 15:23:14 +00004710 if (reclen > len)
4711 break;
bellard8083a3e2003-03-24 23:12:16 +00004712 de->d_reclen = tswap16(reclen);
bellard8582a532007-11-11 23:11:36 +00004713 tswap64s((uint64_t *)&de->d_ino);
4714 tswap64s((uint64_t *)&de->d_off);
bellarddab2ed92003-03-22 15:23:14 +00004715 de = (struct dirent64 *)((char *)de + reclen);
4716 len -= reclen;
4717 }
4718 }
pbrook53a59602006-03-25 19:31:22 +00004719 unlock_user(dirp, arg2, ret);
bellarddab2ed92003-03-22 15:23:14 +00004720 }
4721 break;
bellarda541f292004-04-12 20:39:29 +00004722#endif /* TARGET_NR_getdents64 */
thse5febef2007-04-01 18:31:35 +00004723#ifdef TARGET_NR__newselect
bellard31e31b82003-02-18 22:55:36 +00004724 case TARGET_NR__newselect:
pbrook53a59602006-03-25 19:31:22 +00004725 ret = do_select(arg1, arg2, arg3, arg4, arg5);
bellard31e31b82003-02-18 22:55:36 +00004726 break;
thse5febef2007-04-01 18:31:35 +00004727#endif
4728#ifdef TARGET_NR_poll
bellard9de5e442003-03-23 16:49:39 +00004729 case TARGET_NR_poll:
4730 {
pbrook53a59602006-03-25 19:31:22 +00004731 struct target_pollfd *target_pfd;
bellard9de5e442003-03-23 16:49:39 +00004732 unsigned int nfds = arg2;
4733 int timeout = arg3;
4734 struct pollfd *pfd;
bellard7854b052003-03-29 17:22:23 +00004735 unsigned int i;
bellard9de5e442003-03-23 16:49:39 +00004736
bellard579a97f2007-11-11 14:26:47 +00004737 target_pfd = lock_user(VERIFY_WRITE, arg1, sizeof(struct target_pollfd) * nfds, 1);
4738 if (!target_pfd)
4739 goto efault;
bellard9de5e442003-03-23 16:49:39 +00004740 pfd = alloca(sizeof(struct pollfd) * nfds);
4741 for(i = 0; i < nfds; i++) {
bellard5cd43932003-03-29 16:54:36 +00004742 pfd[i].fd = tswap32(target_pfd[i].fd);
4743 pfd[i].events = tswap16(target_pfd[i].events);
bellard9de5e442003-03-23 16:49:39 +00004744 }
4745 ret = get_errno(poll(pfd, nfds, timeout));
4746 if (!is_error(ret)) {
4747 for(i = 0; i < nfds; i++) {
bellard5cd43932003-03-29 16:54:36 +00004748 target_pfd[i].revents = tswap16(pfd[i].revents);
bellard9de5e442003-03-23 16:49:39 +00004749 }
pbrook53a59602006-03-25 19:31:22 +00004750 ret += nfds * (sizeof(struct target_pollfd)
4751 - sizeof(struct pollfd));
bellard9de5e442003-03-23 16:49:39 +00004752 }
pbrook53a59602006-03-25 19:31:22 +00004753 unlock_user(target_pfd, arg1, ret);
bellard9de5e442003-03-23 16:49:39 +00004754 }
4755 break;
thse5febef2007-04-01 18:31:35 +00004756#endif
bellard31e31b82003-02-18 22:55:36 +00004757 case TARGET_NR_flock:
bellard9de5e442003-03-23 16:49:39 +00004758 /* NOTE: the flock constant seems to be the same for every
4759 Linux platform */
4760 ret = get_errno(flock(arg1, arg2));
bellard31e31b82003-02-18 22:55:36 +00004761 break;
4762 case TARGET_NR_readv:
4763 {
4764 int count = arg3;
bellard31e31b82003-02-18 22:55:36 +00004765 struct iovec *vec;
bellard31e31b82003-02-18 22:55:36 +00004766
4767 vec = alloca(count * sizeof(struct iovec));
bellard41df8412008-02-04 22:26:57 +00004768 if (lock_iovec(VERIFY_WRITE, vec, arg2, count, 0) < 0)
4769 goto efault;
bellard31e31b82003-02-18 22:55:36 +00004770 ret = get_errno(readv(arg1, vec, count));
pbrook53a59602006-03-25 19:31:22 +00004771 unlock_iovec(vec, arg2, count, 1);
bellard31e31b82003-02-18 22:55:36 +00004772 }
4773 break;
4774 case TARGET_NR_writev:
4775 {
4776 int count = arg3;
bellard31e31b82003-02-18 22:55:36 +00004777 struct iovec *vec;
bellard31e31b82003-02-18 22:55:36 +00004778
4779 vec = alloca(count * sizeof(struct iovec));
bellard41df8412008-02-04 22:26:57 +00004780 if (lock_iovec(VERIFY_READ, vec, arg2, count, 1) < 0)
4781 goto efault;
bellard31e31b82003-02-18 22:55:36 +00004782 ret = get_errno(writev(arg1, vec, count));
pbrook53a59602006-03-25 19:31:22 +00004783 unlock_iovec(vec, arg2, count, 0);
bellard31e31b82003-02-18 22:55:36 +00004784 }
4785 break;
4786 case TARGET_NR_getsid:
4787 ret = get_errno(getsid(arg1));
4788 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004789#if defined(TARGET_NR_fdatasync) /* Not on alpha (osf_datasync ?) */
bellard31e31b82003-02-18 22:55:36 +00004790 case TARGET_NR_fdatasync:
bellard5cd43932003-03-29 16:54:36 +00004791 ret = get_errno(fdatasync(arg1));
4792 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004793#endif
bellard31e31b82003-02-18 22:55:36 +00004794 case TARGET_NR__sysctl:
ths0da46a62007-10-20 20:23:07 +00004795 /* We don't implement this, but ENOTDIR is always a safe
bellard29e619b2004-09-13 21:41:04 +00004796 return value. */
ths0da46a62007-10-20 20:23:07 +00004797 ret = -TARGET_ENOTDIR;
4798 break;
bellard31e31b82003-02-18 22:55:36 +00004799 case TARGET_NR_sched_setparam:
bellard5cd43932003-03-29 16:54:36 +00004800 {
pbrook53a59602006-03-25 19:31:22 +00004801 struct sched_param *target_schp;
bellard5cd43932003-03-29 16:54:36 +00004802 struct sched_param schp;
pbrook53a59602006-03-25 19:31:22 +00004803
bellard579a97f2007-11-11 14:26:47 +00004804 if (!lock_user_struct(VERIFY_READ, target_schp, arg2, 1))
4805 goto efault;
bellard5cd43932003-03-29 16:54:36 +00004806 schp.sched_priority = tswap32(target_schp->sched_priority);
pbrook53a59602006-03-25 19:31:22 +00004807 unlock_user_struct(target_schp, arg2, 0);
bellard5cd43932003-03-29 16:54:36 +00004808 ret = get_errno(sched_setparam(arg1, &schp));
4809 }
4810 break;
bellard31e31b82003-02-18 22:55:36 +00004811 case TARGET_NR_sched_getparam:
bellard5cd43932003-03-29 16:54:36 +00004812 {
pbrook53a59602006-03-25 19:31:22 +00004813 struct sched_param *target_schp;
bellard5cd43932003-03-29 16:54:36 +00004814 struct sched_param schp;
4815 ret = get_errno(sched_getparam(arg1, &schp));
4816 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00004817 if (!lock_user_struct(VERIFY_WRITE, target_schp, arg2, 0))
4818 goto efault;
bellard5cd43932003-03-29 16:54:36 +00004819 target_schp->sched_priority = tswap32(schp.sched_priority);
pbrook53a59602006-03-25 19:31:22 +00004820 unlock_user_struct(target_schp, arg2, 1);
bellard5cd43932003-03-29 16:54:36 +00004821 }
4822 }
4823 break;
bellard31e31b82003-02-18 22:55:36 +00004824 case TARGET_NR_sched_setscheduler:
bellard5cd43932003-03-29 16:54:36 +00004825 {
pbrook53a59602006-03-25 19:31:22 +00004826 struct sched_param *target_schp;
bellard5cd43932003-03-29 16:54:36 +00004827 struct sched_param schp;
bellard579a97f2007-11-11 14:26:47 +00004828 if (!lock_user_struct(VERIFY_READ, target_schp, arg3, 1))
4829 goto efault;
bellard5cd43932003-03-29 16:54:36 +00004830 schp.sched_priority = tswap32(target_schp->sched_priority);
pbrook53a59602006-03-25 19:31:22 +00004831 unlock_user_struct(target_schp, arg3, 0);
bellard5cd43932003-03-29 16:54:36 +00004832 ret = get_errno(sched_setscheduler(arg1, arg2, &schp));
4833 }
4834 break;
bellard31e31b82003-02-18 22:55:36 +00004835 case TARGET_NR_sched_getscheduler:
bellard5cd43932003-03-29 16:54:36 +00004836 ret = get_errno(sched_getscheduler(arg1));
4837 break;
bellard31e31b82003-02-18 22:55:36 +00004838 case TARGET_NR_sched_yield:
4839 ret = get_errno(sched_yield());
4840 break;
4841 case TARGET_NR_sched_get_priority_max:
bellard5cd43932003-03-29 16:54:36 +00004842 ret = get_errno(sched_get_priority_max(arg1));
4843 break;
bellard31e31b82003-02-18 22:55:36 +00004844 case TARGET_NR_sched_get_priority_min:
bellard5cd43932003-03-29 16:54:36 +00004845 ret = get_errno(sched_get_priority_min(arg1));
4846 break;
bellard31e31b82003-02-18 22:55:36 +00004847 case TARGET_NR_sched_rr_get_interval:
bellard5cd43932003-03-29 16:54:36 +00004848 {
bellard5cd43932003-03-29 16:54:36 +00004849 struct timespec ts;
4850 ret = get_errno(sched_rr_get_interval(arg1, &ts));
4851 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00004852 host_to_target_timespec(arg2, &ts);
bellard5cd43932003-03-29 16:54:36 +00004853 }
4854 }
4855 break;
bellard31e31b82003-02-18 22:55:36 +00004856 case TARGET_NR_nanosleep:
bellard1b6b0292003-03-22 17:31:38 +00004857 {
bellard1b6b0292003-03-22 17:31:38 +00004858 struct timespec req, rem;
pbrook53a59602006-03-25 19:31:22 +00004859 target_to_host_timespec(&req, arg1);
bellard1b6b0292003-03-22 17:31:38 +00004860 ret = get_errno(nanosleep(&req, &rem));
pbrook53a59602006-03-25 19:31:22 +00004861 if (is_error(ret) && arg2) {
4862 host_to_target_timespec(arg2, &rem);
bellard1b6b0292003-03-22 17:31:38 +00004863 }
4864 }
4865 break;
thse5febef2007-04-01 18:31:35 +00004866#ifdef TARGET_NR_query_module
bellard31e31b82003-02-18 22:55:36 +00004867 case TARGET_NR_query_module:
bellard5cd43932003-03-29 16:54:36 +00004868 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00004869#endif
4870#ifdef TARGET_NR_nfsservctl
bellard31e31b82003-02-18 22:55:36 +00004871 case TARGET_NR_nfsservctl:
bellard5cd43932003-03-29 16:54:36 +00004872 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00004873#endif
bellard31e31b82003-02-18 22:55:36 +00004874 case TARGET_NR_prctl:
thse5574482007-02-11 20:03:13 +00004875 switch (arg1)
4876 {
4877 case PR_GET_PDEATHSIG:
4878 {
4879 int deathsig;
4880 ret = get_errno(prctl(arg1, &deathsig, arg3, arg4, arg5));
bellard2f619692007-11-16 10:46:05 +00004881 if (!is_error(ret) && arg2
4882 && put_user_ual(deathsig, arg2))
4883 goto efault;
thse5574482007-02-11 20:03:13 +00004884 }
4885 break;
4886 default:
4887 ret = get_errno(prctl(arg1, arg2, arg3, arg4, arg5));
4888 break;
4889 }
ths39b9aae2007-02-11 18:36:44 +00004890 break;
bellardd2fd1af2007-11-14 18:08:56 +00004891#ifdef TARGET_NR_arch_prctl
4892 case TARGET_NR_arch_prctl:
4893#if defined(TARGET_I386) && !defined(TARGET_ABI32)
4894 ret = do_arch_prctl(cpu_env, arg1, arg2);
4895 break;
4896#else
4897 goto unimplemented;
4898#endif
4899#endif
bellard67867302003-11-23 17:05:30 +00004900#ifdef TARGET_NR_pread
bellard31e31b82003-02-18 22:55:36 +00004901 case TARGET_NR_pread:
bellard579a97f2007-11-11 14:26:47 +00004902 if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
4903 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004904 ret = get_errno(pread(arg1, p, arg3, arg4));
4905 unlock_user(p, arg2, ret);
bellard206f0fa2003-05-14 19:01:56 +00004906 break;
bellard31e31b82003-02-18 22:55:36 +00004907 case TARGET_NR_pwrite:
bellard579a97f2007-11-11 14:26:47 +00004908 if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
4909 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004910 ret = get_errno(pwrite(arg1, p, arg3, arg4));
4911 unlock_user(p, arg2, 0);
bellard206f0fa2003-05-14 19:01:56 +00004912 break;
bellard67867302003-11-23 17:05:30 +00004913#endif
aurel32f2c7ba12008-03-28 22:32:06 +00004914#ifdef TARGET_NR_pread64
4915 case TARGET_NR_pread64:
4916 if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
4917 goto efault;
4918 ret = get_errno(pread64(arg1, p, arg3, target_offset64(arg4, arg5)));
4919 unlock_user(p, arg2, ret);
4920 break;
4921 case TARGET_NR_pwrite64:
4922 if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
4923 goto efault;
4924 ret = get_errno(pwrite64(arg1, p, arg3, target_offset64(arg4, arg5)));
4925 unlock_user(p, arg2, 0);
4926 break;
4927#endif
bellard31e31b82003-02-18 22:55:36 +00004928 case TARGET_NR_getcwd:
bellard579a97f2007-11-11 14:26:47 +00004929 if (!(p = lock_user(VERIFY_WRITE, arg1, arg2, 0)))
4930 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004931 ret = get_errno(sys_getcwd1(p, arg2));
4932 unlock_user(p, arg1, ret);
bellard31e31b82003-02-18 22:55:36 +00004933 break;
4934 case TARGET_NR_capget:
bellard5cd43932003-03-29 16:54:36 +00004935 goto unimplemented;
bellard31e31b82003-02-18 22:55:36 +00004936 case TARGET_NR_capset:
bellard5cd43932003-03-29 16:54:36 +00004937 goto unimplemented;
bellard31e31b82003-02-18 22:55:36 +00004938 case TARGET_NR_sigaltstack:
ths198a74d2007-09-27 16:44:32 +00004939#if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_MIPS) || \
4940 defined(TARGET_SPARC) || defined(TARGET_PPC) || defined(TARGET_ALPHA)
bellard579a97f2007-11-11 14:26:47 +00004941 ret = do_sigaltstack(arg1, arg2, get_sp_from_cpustate((CPUState *)cpu_env));
thsa04e1342007-09-27 13:57:58 +00004942 break;
4943#else
bellard5cd43932003-03-29 16:54:36 +00004944 goto unimplemented;
thsa04e1342007-09-27 13:57:58 +00004945#endif
bellard31e31b82003-02-18 22:55:36 +00004946 case TARGET_NR_sendfile:
bellard5cd43932003-03-29 16:54:36 +00004947 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004948#ifdef TARGET_NR_getpmsg
bellard31e31b82003-02-18 22:55:36 +00004949 case TARGET_NR_getpmsg:
bellard5cd43932003-03-29 16:54:36 +00004950 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004951#endif
4952#ifdef TARGET_NR_putpmsg
bellard31e31b82003-02-18 22:55:36 +00004953 case TARGET_NR_putpmsg:
bellard5cd43932003-03-29 16:54:36 +00004954 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004955#endif
bellard048f6b42005-11-26 18:47:20 +00004956#ifdef TARGET_NR_vfork
bellard31e31b82003-02-18 22:55:36 +00004957 case TARGET_NR_vfork:
bellard1b6b0292003-03-22 17:31:38 +00004958 ret = get_errno(do_fork(cpu_env, CLONE_VFORK | CLONE_VM | SIGCHLD, 0));
bellard31e31b82003-02-18 22:55:36 +00004959 break;
bellard048f6b42005-11-26 18:47:20 +00004960#endif
bellardebc05482003-09-30 21:08:41 +00004961#ifdef TARGET_NR_ugetrlimit
bellard31e31b82003-02-18 22:55:36 +00004962 case TARGET_NR_ugetrlimit:
bellard728584b2003-04-29 20:43:36 +00004963 {
4964 struct rlimit rlim;
4965 ret = get_errno(getrlimit(arg1, &rlim));
4966 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00004967 struct target_rlimit *target_rlim;
bellard579a97f2007-11-11 14:26:47 +00004968 if (!lock_user_struct(VERIFY_WRITE, target_rlim, arg2, 0))
4969 goto efault;
bellard728584b2003-04-29 20:43:36 +00004970 target_rlim->rlim_cur = tswapl(rlim.rlim_cur);
4971 target_rlim->rlim_max = tswapl(rlim.rlim_max);
pbrook53a59602006-03-25 19:31:22 +00004972 unlock_user_struct(target_rlim, arg2, 1);
bellard728584b2003-04-29 20:43:36 +00004973 }
4974 break;
4975 }
bellardebc05482003-09-30 21:08:41 +00004976#endif
bellarda315a142005-01-30 22:59:18 +00004977#ifdef TARGET_NR_truncate64
bellard31e31b82003-02-18 22:55:36 +00004978 case TARGET_NR_truncate64:
bellard579a97f2007-11-11 14:26:47 +00004979 if (!(p = lock_user_string(arg1)))
4980 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004981 ret = target_truncate64(cpu_env, p, arg2, arg3, arg4);
4982 unlock_user(p, arg1, 0);
bellard667f38b2005-07-23 14:46:27 +00004983 break;
bellarda315a142005-01-30 22:59:18 +00004984#endif
4985#ifdef TARGET_NR_ftruncate64
bellard31e31b82003-02-18 22:55:36 +00004986 case TARGET_NR_ftruncate64:
pbrookce4defa2006-02-09 16:49:55 +00004987 ret = target_ftruncate64(cpu_env, arg1, arg2, arg3, arg4);
bellard667f38b2005-07-23 14:46:27 +00004988 break;
bellarda315a142005-01-30 22:59:18 +00004989#endif
4990#ifdef TARGET_NR_stat64
bellard31e31b82003-02-18 22:55:36 +00004991 case TARGET_NR_stat64:
bellard579a97f2007-11-11 14:26:47 +00004992 if (!(p = lock_user_string(arg1)))
4993 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004994 ret = get_errno(stat(path(p), &st));
4995 unlock_user(p, arg1, 0);
bellard60cd49d2003-03-16 22:53:56 +00004996 goto do_stat64;
bellarda315a142005-01-30 22:59:18 +00004997#endif
4998#ifdef TARGET_NR_lstat64
bellard31e31b82003-02-18 22:55:36 +00004999 case TARGET_NR_lstat64:
bellard579a97f2007-11-11 14:26:47 +00005000 if (!(p = lock_user_string(arg1)))
5001 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005002 ret = get_errno(lstat(path(p), &st));
5003 unlock_user(p, arg1, 0);
bellard60cd49d2003-03-16 22:53:56 +00005004 goto do_stat64;
bellarda315a142005-01-30 22:59:18 +00005005#endif
5006#ifdef TARGET_NR_fstat64
bellard31e31b82003-02-18 22:55:36 +00005007 case TARGET_NR_fstat64:
bellard60cd49d2003-03-16 22:53:56 +00005008 {
5009 ret = get_errno(fstat(arg1, &st));
5010 do_stat64:
5011 if (!is_error(ret)) {
pbrookce4defa2006-02-09 16:49:55 +00005012#ifdef TARGET_ARM
5013 if (((CPUARMState *)cpu_env)->eabi) {
pbrook53a59602006-03-25 19:31:22 +00005014 struct target_eabi_stat64 *target_st;
bellard579a97f2007-11-11 14:26:47 +00005015
5016 if (!lock_user_struct(VERIFY_WRITE, target_st, arg2, 0))
5017 goto efault;
pbrookce4defa2006-02-09 16:49:55 +00005018 memset(target_st, 0, sizeof(struct target_eabi_stat64));
bellard579a97f2007-11-11 14:26:47 +00005019 __put_user(st.st_dev, &target_st->st_dev);
5020 __put_user(st.st_ino, &target_st->st_ino);
bellardec86b0f2003-04-11 00:15:04 +00005021#ifdef TARGET_STAT64_HAS_BROKEN_ST_INO
bellard579a97f2007-11-11 14:26:47 +00005022 __put_user(st.st_ino, &target_st->__st_ino);
bellardec86b0f2003-04-11 00:15:04 +00005023#endif
bellard579a97f2007-11-11 14:26:47 +00005024 __put_user(st.st_mode, &target_st->st_mode);
5025 __put_user(st.st_nlink, &target_st->st_nlink);
5026 __put_user(st.st_uid, &target_st->st_uid);
5027 __put_user(st.st_gid, &target_st->st_gid);
5028 __put_user(st.st_rdev, &target_st->st_rdev);
5029 __put_user(st.st_size, &target_st->st_size);
5030 __put_user(st.st_blksize, &target_st->st_blksize);
5031 __put_user(st.st_blocks, &target_st->st_blocks);
5032 __put_user(st.st_atime, &target_st->target_st_atime);
5033 __put_user(st.st_mtime, &target_st->target_st_mtime);
5034 __put_user(st.st_ctime, &target_st->target_st_ctime);
5035 unlock_user_struct(target_st, arg2, 1);
pbrookce4defa2006-02-09 16:49:55 +00005036 } else
5037#endif
5038 {
pbrook53a59602006-03-25 19:31:22 +00005039 struct target_stat64 *target_st;
bellard579a97f2007-11-11 14:26:47 +00005040
5041 if (!lock_user_struct(VERIFY_WRITE, target_st, arg2, 0))
5042 goto efault;
pbrookce4defa2006-02-09 16:49:55 +00005043 memset(target_st, 0, sizeof(struct target_stat64));
bellard579a97f2007-11-11 14:26:47 +00005044 __put_user(st.st_dev, &target_st->st_dev);
5045 __put_user(st.st_ino, &target_st->st_ino);
pbrookce4defa2006-02-09 16:49:55 +00005046#ifdef TARGET_STAT64_HAS_BROKEN_ST_INO
bellard579a97f2007-11-11 14:26:47 +00005047 __put_user(st.st_ino, &target_st->__st_ino);
pbrookce4defa2006-02-09 16:49:55 +00005048#endif
bellard579a97f2007-11-11 14:26:47 +00005049 __put_user(st.st_mode, &target_st->st_mode);
5050 __put_user(st.st_nlink, &target_st->st_nlink);
5051 __put_user(st.st_uid, &target_st->st_uid);
5052 __put_user(st.st_gid, &target_st->st_gid);
5053 __put_user(st.st_rdev, &target_st->st_rdev);
pbrookce4defa2006-02-09 16:49:55 +00005054 /* XXX: better use of kernel struct */
bellard579a97f2007-11-11 14:26:47 +00005055 __put_user(st.st_size, &target_st->st_size);
5056 __put_user(st.st_blksize, &target_st->st_blksize);
5057 __put_user(st.st_blocks, &target_st->st_blocks);
5058 __put_user(st.st_atime, &target_st->target_st_atime);
5059 __put_user(st.st_mtime, &target_st->target_st_mtime);
5060 __put_user(st.st_ctime, &target_st->target_st_ctime);
5061 unlock_user_struct(target_st, arg2, 1);
pbrookce4defa2006-02-09 16:49:55 +00005062 }
bellard60cd49d2003-03-16 22:53:56 +00005063 }
5064 }
5065 break;
bellarda315a142005-01-30 22:59:18 +00005066#endif
bellard67867302003-11-23 17:05:30 +00005067#ifdef USE_UID16
5068 case TARGET_NR_lchown:
bellard579a97f2007-11-11 14:26:47 +00005069 if (!(p = lock_user_string(arg1)))
5070 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005071 ret = get_errno(lchown(p, low2highuid(arg2), low2highgid(arg3)));
5072 unlock_user(p, arg1, 0);
bellard67867302003-11-23 17:05:30 +00005073 break;
5074 case TARGET_NR_getuid:
5075 ret = get_errno(high2lowuid(getuid()));
5076 break;
5077 case TARGET_NR_getgid:
5078 ret = get_errno(high2lowgid(getgid()));
5079 break;
5080 case TARGET_NR_geteuid:
5081 ret = get_errno(high2lowuid(geteuid()));
5082 break;
5083 case TARGET_NR_getegid:
5084 ret = get_errno(high2lowgid(getegid()));
5085 break;
5086 case TARGET_NR_setreuid:
5087 ret = get_errno(setreuid(low2highuid(arg1), low2highuid(arg2)));
5088 break;
5089 case TARGET_NR_setregid:
5090 ret = get_errno(setregid(low2highgid(arg1), low2highgid(arg2)));
5091 break;
5092 case TARGET_NR_getgroups:
5093 {
5094 int gidsetsize = arg1;
pbrook53a59602006-03-25 19:31:22 +00005095 uint16_t *target_grouplist;
bellard67867302003-11-23 17:05:30 +00005096 gid_t *grouplist;
5097 int i;
5098
5099 grouplist = alloca(gidsetsize * sizeof(gid_t));
5100 ret = get_errno(getgroups(gidsetsize, grouplist));
5101 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00005102 target_grouplist = lock_user(VERIFY_WRITE, arg2, gidsetsize * 2, 0);
5103 if (!target_grouplist)
5104 goto efault;
bellard67867302003-11-23 17:05:30 +00005105 for(i = 0;i < gidsetsize; i++)
5106 target_grouplist[i] = tswap16(grouplist[i]);
pbrook53a59602006-03-25 19:31:22 +00005107 unlock_user(target_grouplist, arg2, gidsetsize * 2);
bellard67867302003-11-23 17:05:30 +00005108 }
5109 }
5110 break;
5111 case TARGET_NR_setgroups:
5112 {
5113 int gidsetsize = arg1;
pbrook53a59602006-03-25 19:31:22 +00005114 uint16_t *target_grouplist;
bellard67867302003-11-23 17:05:30 +00005115 gid_t *grouplist;
5116 int i;
5117
5118 grouplist = alloca(gidsetsize * sizeof(gid_t));
bellard579a97f2007-11-11 14:26:47 +00005119 target_grouplist = lock_user(VERIFY_READ, arg2, gidsetsize * 2, 1);
5120 if (!target_grouplist) {
5121 ret = -TARGET_EFAULT;
5122 goto fail;
5123 }
bellard67867302003-11-23 17:05:30 +00005124 for(i = 0;i < gidsetsize; i++)
5125 grouplist[i] = tswap16(target_grouplist[i]);
pbrook53a59602006-03-25 19:31:22 +00005126 unlock_user(target_grouplist, arg2, 0);
bellard67867302003-11-23 17:05:30 +00005127 ret = get_errno(setgroups(gidsetsize, grouplist));
5128 }
5129 break;
5130 case TARGET_NR_fchown:
5131 ret = get_errno(fchown(arg1, low2highuid(arg2), low2highgid(arg3)));
5132 break;
thsccfa72b2007-09-24 09:23:34 +00005133#if defined(TARGET_NR_fchownat) && defined(__NR_fchownat)
5134 case TARGET_NR_fchownat:
bellard579a97f2007-11-11 14:26:47 +00005135 if (!(p = lock_user_string(arg2)))
5136 goto efault;
5137 ret = get_errno(sys_fchownat(arg1, p, low2highuid(arg3), low2highgid(arg4), arg5));
5138 unlock_user(p, arg2, 0);
thsccfa72b2007-09-24 09:23:34 +00005139 break;
5140#endif
bellard67867302003-11-23 17:05:30 +00005141#ifdef TARGET_NR_setresuid
5142 case TARGET_NR_setresuid:
ths5fafdf22007-09-16 21:08:06 +00005143 ret = get_errno(setresuid(low2highuid(arg1),
5144 low2highuid(arg2),
bellard67867302003-11-23 17:05:30 +00005145 low2highuid(arg3)));
5146 break;
5147#endif
5148#ifdef TARGET_NR_getresuid
5149 case TARGET_NR_getresuid:
5150 {
pbrook53a59602006-03-25 19:31:22 +00005151 uid_t ruid, euid, suid;
bellard67867302003-11-23 17:05:30 +00005152 ret = get_errno(getresuid(&ruid, &euid, &suid));
5153 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +00005154 if (put_user_u16(high2lowuid(ruid), arg1)
5155 || put_user_u16(high2lowuid(euid), arg2)
5156 || put_user_u16(high2lowuid(suid), arg3))
5157 goto efault;
bellard67867302003-11-23 17:05:30 +00005158 }
5159 }
5160 break;
5161#endif
5162#ifdef TARGET_NR_getresgid
5163 case TARGET_NR_setresgid:
ths5fafdf22007-09-16 21:08:06 +00005164 ret = get_errno(setresgid(low2highgid(arg1),
5165 low2highgid(arg2),
bellard67867302003-11-23 17:05:30 +00005166 low2highgid(arg3)));
5167 break;
5168#endif
5169#ifdef TARGET_NR_getresgid
5170 case TARGET_NR_getresgid:
5171 {
pbrook53a59602006-03-25 19:31:22 +00005172 gid_t rgid, egid, sgid;
bellard67867302003-11-23 17:05:30 +00005173 ret = get_errno(getresgid(&rgid, &egid, &sgid));
5174 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +00005175 if (put_user_u16(high2lowgid(rgid), arg1)
5176 || put_user_u16(high2lowgid(egid), arg2)
5177 || put_user_u16(high2lowgid(sgid), arg3))
5178 goto efault;
bellard67867302003-11-23 17:05:30 +00005179 }
5180 }
5181 break;
5182#endif
5183 case TARGET_NR_chown:
bellard579a97f2007-11-11 14:26:47 +00005184 if (!(p = lock_user_string(arg1)))
5185 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005186 ret = get_errno(chown(p, low2highuid(arg2), low2highgid(arg3)));
5187 unlock_user(p, arg1, 0);
bellard67867302003-11-23 17:05:30 +00005188 break;
5189 case TARGET_NR_setuid:
5190 ret = get_errno(setuid(low2highuid(arg1)));
5191 break;
5192 case TARGET_NR_setgid:
5193 ret = get_errno(setgid(low2highgid(arg1)));
5194 break;
5195 case TARGET_NR_setfsuid:
5196 ret = get_errno(setfsuid(arg1));
5197 break;
5198 case TARGET_NR_setfsgid:
5199 ret = get_errno(setfsgid(arg1));
5200 break;
5201#endif /* USE_UID16 */
5202
bellarda315a142005-01-30 22:59:18 +00005203#ifdef TARGET_NR_lchown32
bellard31e31b82003-02-18 22:55:36 +00005204 case TARGET_NR_lchown32:
bellard579a97f2007-11-11 14:26:47 +00005205 if (!(p = lock_user_string(arg1)))
5206 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005207 ret = get_errno(lchown(p, arg2, arg3));
5208 unlock_user(p, arg1, 0);
bellardb03c60f2003-03-23 17:19:56 +00005209 break;
bellarda315a142005-01-30 22:59:18 +00005210#endif
5211#ifdef TARGET_NR_getuid32
bellard31e31b82003-02-18 22:55:36 +00005212 case TARGET_NR_getuid32:
bellardb03c60f2003-03-23 17:19:56 +00005213 ret = get_errno(getuid());
5214 break;
bellarda315a142005-01-30 22:59:18 +00005215#endif
5216#ifdef TARGET_NR_getgid32
bellard31e31b82003-02-18 22:55:36 +00005217 case TARGET_NR_getgid32:
bellardb03c60f2003-03-23 17:19:56 +00005218 ret = get_errno(getgid());
5219 break;
bellarda315a142005-01-30 22:59:18 +00005220#endif
5221#ifdef TARGET_NR_geteuid32
bellard31e31b82003-02-18 22:55:36 +00005222 case TARGET_NR_geteuid32:
bellardb03c60f2003-03-23 17:19:56 +00005223 ret = get_errno(geteuid());
5224 break;
bellarda315a142005-01-30 22:59:18 +00005225#endif
5226#ifdef TARGET_NR_getegid32
bellard31e31b82003-02-18 22:55:36 +00005227 case TARGET_NR_getegid32:
bellardb03c60f2003-03-23 17:19:56 +00005228 ret = get_errno(getegid());
5229 break;
bellarda315a142005-01-30 22:59:18 +00005230#endif
5231#ifdef TARGET_NR_setreuid32
bellard31e31b82003-02-18 22:55:36 +00005232 case TARGET_NR_setreuid32:
bellardb03c60f2003-03-23 17:19:56 +00005233 ret = get_errno(setreuid(arg1, arg2));
5234 break;
bellarda315a142005-01-30 22:59:18 +00005235#endif
5236#ifdef TARGET_NR_setregid32
bellard31e31b82003-02-18 22:55:36 +00005237 case TARGET_NR_setregid32:
bellardb03c60f2003-03-23 17:19:56 +00005238 ret = get_errno(setregid(arg1, arg2));
5239 break;
bellarda315a142005-01-30 22:59:18 +00005240#endif
5241#ifdef TARGET_NR_getgroups32
bellard31e31b82003-02-18 22:55:36 +00005242 case TARGET_NR_getgroups32:
bellard99c475a2005-01-31 20:45:13 +00005243 {
5244 int gidsetsize = arg1;
pbrook53a59602006-03-25 19:31:22 +00005245 uint32_t *target_grouplist;
bellard99c475a2005-01-31 20:45:13 +00005246 gid_t *grouplist;
5247 int i;
5248
5249 grouplist = alloca(gidsetsize * sizeof(gid_t));
5250 ret = get_errno(getgroups(gidsetsize, grouplist));
5251 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00005252 target_grouplist = lock_user(VERIFY_WRITE, arg2, gidsetsize * 4, 0);
5253 if (!target_grouplist) {
5254 ret = -TARGET_EFAULT;
5255 goto fail;
5256 }
bellard99c475a2005-01-31 20:45:13 +00005257 for(i = 0;i < gidsetsize; i++)
pbrook53a59602006-03-25 19:31:22 +00005258 target_grouplist[i] = tswap32(grouplist[i]);
5259 unlock_user(target_grouplist, arg2, gidsetsize * 4);
bellard99c475a2005-01-31 20:45:13 +00005260 }
5261 }
5262 break;
bellarda315a142005-01-30 22:59:18 +00005263#endif
5264#ifdef TARGET_NR_setgroups32
bellard31e31b82003-02-18 22:55:36 +00005265 case TARGET_NR_setgroups32:
bellard99c475a2005-01-31 20:45:13 +00005266 {
5267 int gidsetsize = arg1;
pbrook53a59602006-03-25 19:31:22 +00005268 uint32_t *target_grouplist;
bellard99c475a2005-01-31 20:45:13 +00005269 gid_t *grouplist;
5270 int i;
ths3b46e622007-09-17 08:09:54 +00005271
bellard99c475a2005-01-31 20:45:13 +00005272 grouplist = alloca(gidsetsize * sizeof(gid_t));
bellard579a97f2007-11-11 14:26:47 +00005273 target_grouplist = lock_user(VERIFY_READ, arg2, gidsetsize * 4, 1);
5274 if (!target_grouplist) {
5275 ret = -TARGET_EFAULT;
5276 goto fail;
5277 }
bellard99c475a2005-01-31 20:45:13 +00005278 for(i = 0;i < gidsetsize; i++)
pbrook53a59602006-03-25 19:31:22 +00005279 grouplist[i] = tswap32(target_grouplist[i]);
5280 unlock_user(target_grouplist, arg2, 0);
bellard99c475a2005-01-31 20:45:13 +00005281 ret = get_errno(setgroups(gidsetsize, grouplist));
5282 }
5283 break;
bellarda315a142005-01-30 22:59:18 +00005284#endif
5285#ifdef TARGET_NR_fchown32
bellard31e31b82003-02-18 22:55:36 +00005286 case TARGET_NR_fchown32:
bellardb03c60f2003-03-23 17:19:56 +00005287 ret = get_errno(fchown(arg1, arg2, arg3));
5288 break;
bellarda315a142005-01-30 22:59:18 +00005289#endif
5290#ifdef TARGET_NR_setresuid32
bellard31e31b82003-02-18 22:55:36 +00005291 case TARGET_NR_setresuid32:
bellardb03c60f2003-03-23 17:19:56 +00005292 ret = get_errno(setresuid(arg1, arg2, arg3));
5293 break;
bellarda315a142005-01-30 22:59:18 +00005294#endif
5295#ifdef TARGET_NR_getresuid32
bellard31e31b82003-02-18 22:55:36 +00005296 case TARGET_NR_getresuid32:
bellardb03c60f2003-03-23 17:19:56 +00005297 {
pbrook53a59602006-03-25 19:31:22 +00005298 uid_t ruid, euid, suid;
bellardb03c60f2003-03-23 17:19:56 +00005299 ret = get_errno(getresuid(&ruid, &euid, &suid));
5300 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +00005301 if (put_user_u32(ruid, arg1)
5302 || put_user_u32(euid, arg2)
5303 || put_user_u32(suid, arg3))
5304 goto efault;
bellardb03c60f2003-03-23 17:19:56 +00005305 }
5306 }
5307 break;
bellarda315a142005-01-30 22:59:18 +00005308#endif
5309#ifdef TARGET_NR_setresgid32
bellard31e31b82003-02-18 22:55:36 +00005310 case TARGET_NR_setresgid32:
bellardb03c60f2003-03-23 17:19:56 +00005311 ret = get_errno(setresgid(arg1, arg2, arg3));
5312 break;
bellarda315a142005-01-30 22:59:18 +00005313#endif
5314#ifdef TARGET_NR_getresgid32
bellard31e31b82003-02-18 22:55:36 +00005315 case TARGET_NR_getresgid32:
bellardb03c60f2003-03-23 17:19:56 +00005316 {
pbrook53a59602006-03-25 19:31:22 +00005317 gid_t rgid, egid, sgid;
bellardb03c60f2003-03-23 17:19:56 +00005318 ret = get_errno(getresgid(&rgid, &egid, &sgid));
5319 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +00005320 if (put_user_u32(rgid, arg1)
5321 || put_user_u32(egid, arg2)
5322 || put_user_u32(sgid, arg3))
5323 goto efault;
bellardb03c60f2003-03-23 17:19:56 +00005324 }
5325 }
5326 break;
bellarda315a142005-01-30 22:59:18 +00005327#endif
5328#ifdef TARGET_NR_chown32
bellard31e31b82003-02-18 22:55:36 +00005329 case TARGET_NR_chown32:
bellard579a97f2007-11-11 14:26:47 +00005330 if (!(p = lock_user_string(arg1)))
5331 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005332 ret = get_errno(chown(p, arg2, arg3));
5333 unlock_user(p, arg1, 0);
bellardb03c60f2003-03-23 17:19:56 +00005334 break;
bellarda315a142005-01-30 22:59:18 +00005335#endif
5336#ifdef TARGET_NR_setuid32
bellard31e31b82003-02-18 22:55:36 +00005337 case TARGET_NR_setuid32:
bellardb03c60f2003-03-23 17:19:56 +00005338 ret = get_errno(setuid(arg1));
5339 break;
bellarda315a142005-01-30 22:59:18 +00005340#endif
5341#ifdef TARGET_NR_setgid32
bellard31e31b82003-02-18 22:55:36 +00005342 case TARGET_NR_setgid32:
bellardb03c60f2003-03-23 17:19:56 +00005343 ret = get_errno(setgid(arg1));
5344 break;
bellarda315a142005-01-30 22:59:18 +00005345#endif
5346#ifdef TARGET_NR_setfsuid32
bellard31e31b82003-02-18 22:55:36 +00005347 case TARGET_NR_setfsuid32:
bellardb03c60f2003-03-23 17:19:56 +00005348 ret = get_errno(setfsuid(arg1));
5349 break;
bellarda315a142005-01-30 22:59:18 +00005350#endif
5351#ifdef TARGET_NR_setfsgid32
bellard31e31b82003-02-18 22:55:36 +00005352 case TARGET_NR_setfsgid32:
bellardb03c60f2003-03-23 17:19:56 +00005353 ret = get_errno(setfsgid(arg1));
5354 break;
bellarda315a142005-01-30 22:59:18 +00005355#endif
bellard67867302003-11-23 17:05:30 +00005356
bellard31e31b82003-02-18 22:55:36 +00005357 case TARGET_NR_pivot_root:
bellardb03c60f2003-03-23 17:19:56 +00005358 goto unimplemented;
bellardffa65c32004-01-04 23:57:22 +00005359#ifdef TARGET_NR_mincore
bellard31e31b82003-02-18 22:55:36 +00005360 case TARGET_NR_mincore:
bellardb03c60f2003-03-23 17:19:56 +00005361 goto unimplemented;
bellardffa65c32004-01-04 23:57:22 +00005362#endif
5363#ifdef TARGET_NR_madvise
bellard31e31b82003-02-18 22:55:36 +00005364 case TARGET_NR_madvise:
pbrook24836682006-04-16 14:14:53 +00005365 /* A straight passthrough may not be safe because qemu sometimes
5366 turns private flie-backed mappings into anonymous mappings.
5367 This will break MADV_DONTNEED.
5368 This is a hint, so ignoring and returning success is ok. */
5369 ret = get_errno(0);
5370 break;
bellardffa65c32004-01-04 23:57:22 +00005371#endif
blueswir1992f48a2007-10-14 16:27:31 +00005372#if TARGET_ABI_BITS == 32
bellard31e31b82003-02-18 22:55:36 +00005373 case TARGET_NR_fcntl64:
bellard77e46722003-04-29 20:39:06 +00005374 {
thsb1e341e2007-03-20 21:50:52 +00005375 int cmd;
bellard77e46722003-04-29 20:39:06 +00005376 struct flock64 fl;
pbrook53a59602006-03-25 19:31:22 +00005377 struct target_flock64 *target_fl;
pbrookce4defa2006-02-09 16:49:55 +00005378#ifdef TARGET_ARM
pbrook53a59602006-03-25 19:31:22 +00005379 struct target_eabi_flock64 *target_efl;
pbrookce4defa2006-02-09 16:49:55 +00005380#endif
bellard77e46722003-04-29 20:39:06 +00005381
thsb1e341e2007-03-20 21:50:52 +00005382 switch(arg2){
5383 case TARGET_F_GETLK64:
5384 cmd = F_GETLK64;
thsa7222582007-03-22 15:08:55 +00005385 break;
thsb1e341e2007-03-20 21:50:52 +00005386 case TARGET_F_SETLK64:
5387 cmd = F_SETLK64;
thsa7222582007-03-22 15:08:55 +00005388 break;
thsb1e341e2007-03-20 21:50:52 +00005389 case TARGET_F_SETLKW64:
5390 cmd = F_SETLK64;
thsa7222582007-03-22 15:08:55 +00005391 break;
thsb1e341e2007-03-20 21:50:52 +00005392 default:
5393 cmd = arg2;
thsa7222582007-03-22 15:08:55 +00005394 break;
thsb1e341e2007-03-20 21:50:52 +00005395 }
5396
bellard60cd49d2003-03-16 22:53:56 +00005397 switch(arg2) {
thsb1e341e2007-03-20 21:50:52 +00005398 case TARGET_F_GETLK64:
ths58134272007-03-31 18:59:32 +00005399#ifdef TARGET_ARM
5400 if (((CPUARMState *)cpu_env)->eabi) {
bellard9ee1fa22007-11-11 15:11:19 +00005401 if (!lock_user_struct(VERIFY_READ, target_efl, arg3, 1))
5402 goto efault;
ths58134272007-03-31 18:59:32 +00005403 fl.l_type = tswap16(target_efl->l_type);
5404 fl.l_whence = tswap16(target_efl->l_whence);
5405 fl.l_start = tswap64(target_efl->l_start);
5406 fl.l_len = tswap64(target_efl->l_len);
5407 fl.l_pid = tswapl(target_efl->l_pid);
5408 unlock_user_struct(target_efl, arg3, 0);
5409 } else
5410#endif
5411 {
bellard9ee1fa22007-11-11 15:11:19 +00005412 if (!lock_user_struct(VERIFY_READ, target_fl, arg3, 1))
5413 goto efault;
ths58134272007-03-31 18:59:32 +00005414 fl.l_type = tswap16(target_fl->l_type);
5415 fl.l_whence = tswap16(target_fl->l_whence);
5416 fl.l_start = tswap64(target_fl->l_start);
5417 fl.l_len = tswap64(target_fl->l_len);
5418 fl.l_pid = tswapl(target_fl->l_pid);
5419 unlock_user_struct(target_fl, arg3, 0);
5420 }
thsb1e341e2007-03-20 21:50:52 +00005421 ret = get_errno(fcntl(arg1, cmd, &fl));
bellard77e46722003-04-29 20:39:06 +00005422 if (ret == 0) {
pbrookce4defa2006-02-09 16:49:55 +00005423#ifdef TARGET_ARM
5424 if (((CPUARMState *)cpu_env)->eabi) {
bellard9ee1fa22007-11-11 15:11:19 +00005425 if (!lock_user_struct(VERIFY_WRITE, target_efl, arg3, 0))
5426 goto efault;
pbrookce4defa2006-02-09 16:49:55 +00005427 target_efl->l_type = tswap16(fl.l_type);
5428 target_efl->l_whence = tswap16(fl.l_whence);
5429 target_efl->l_start = tswap64(fl.l_start);
5430 target_efl->l_len = tswap64(fl.l_len);
5431 target_efl->l_pid = tswapl(fl.l_pid);
pbrook53a59602006-03-25 19:31:22 +00005432 unlock_user_struct(target_efl, arg3, 1);
pbrookce4defa2006-02-09 16:49:55 +00005433 } else
5434#endif
5435 {
bellard9ee1fa22007-11-11 15:11:19 +00005436 if (!lock_user_struct(VERIFY_WRITE, target_fl, arg3, 0))
5437 goto efault;
pbrookce4defa2006-02-09 16:49:55 +00005438 target_fl->l_type = tswap16(fl.l_type);
5439 target_fl->l_whence = tswap16(fl.l_whence);
5440 target_fl->l_start = tswap64(fl.l_start);
5441 target_fl->l_len = tswap64(fl.l_len);
5442 target_fl->l_pid = tswapl(fl.l_pid);
pbrook53a59602006-03-25 19:31:22 +00005443 unlock_user_struct(target_fl, arg3, 1);
pbrookce4defa2006-02-09 16:49:55 +00005444 }
bellard77e46722003-04-29 20:39:06 +00005445 }
5446 break;
5447
thsb1e341e2007-03-20 21:50:52 +00005448 case TARGET_F_SETLK64:
5449 case TARGET_F_SETLKW64:
pbrookce4defa2006-02-09 16:49:55 +00005450#ifdef TARGET_ARM
5451 if (((CPUARMState *)cpu_env)->eabi) {
bellard9ee1fa22007-11-11 15:11:19 +00005452 if (!lock_user_struct(VERIFY_READ, target_efl, arg3, 1))
5453 goto efault;
pbrookce4defa2006-02-09 16:49:55 +00005454 fl.l_type = tswap16(target_efl->l_type);
5455 fl.l_whence = tswap16(target_efl->l_whence);
5456 fl.l_start = tswap64(target_efl->l_start);
5457 fl.l_len = tswap64(target_efl->l_len);
5458 fl.l_pid = tswapl(target_efl->l_pid);
pbrook53a59602006-03-25 19:31:22 +00005459 unlock_user_struct(target_efl, arg3, 0);
pbrookce4defa2006-02-09 16:49:55 +00005460 } else
5461#endif
5462 {
bellard9ee1fa22007-11-11 15:11:19 +00005463 if (!lock_user_struct(VERIFY_READ, target_fl, arg3, 1))
5464 goto efault;
pbrookce4defa2006-02-09 16:49:55 +00005465 fl.l_type = tswap16(target_fl->l_type);
5466 fl.l_whence = tswap16(target_fl->l_whence);
5467 fl.l_start = tswap64(target_fl->l_start);
5468 fl.l_len = tswap64(target_fl->l_len);
5469 fl.l_pid = tswapl(target_fl->l_pid);
pbrook53a59602006-03-25 19:31:22 +00005470 unlock_user_struct(target_fl, arg3, 0);
pbrookce4defa2006-02-09 16:49:55 +00005471 }
thsb1e341e2007-03-20 21:50:52 +00005472 ret = get_errno(fcntl(arg1, cmd, &fl));
bellard77e46722003-04-29 20:39:06 +00005473 break;
bellard60cd49d2003-03-16 22:53:56 +00005474 default:
bellard9ee1fa22007-11-11 15:11:19 +00005475 ret = do_fcntl(arg1, cmd, arg3);
bellard60cd49d2003-03-16 22:53:56 +00005476 break;
5477 }
bellard77e46722003-04-29 20:39:06 +00005478 break;
5479 }
bellard60cd49d2003-03-16 22:53:56 +00005480#endif
ths7d600c82006-12-08 01:32:58 +00005481#ifdef TARGET_NR_cacheflush
5482 case TARGET_NR_cacheflush:
5483 /* self-modifying code is handled automatically, so nothing needed */
5484 ret = 0;
5485 break;
5486#endif
bellardebc05482003-09-30 21:08:41 +00005487#ifdef TARGET_NR_security
bellard31e31b82003-02-18 22:55:36 +00005488 case TARGET_NR_security:
5489 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00005490#endif
bellardc573ff62004-01-04 15:51:36 +00005491#ifdef TARGET_NR_getpagesize
5492 case TARGET_NR_getpagesize:
5493 ret = TARGET_PAGE_SIZE;
5494 break;
5495#endif
bellard31e31b82003-02-18 22:55:36 +00005496 case TARGET_NR_gettid:
5497 ret = get_errno(gettid());
5498 break;
thse5febef2007-04-01 18:31:35 +00005499#ifdef TARGET_NR_readahead
bellard31e31b82003-02-18 22:55:36 +00005500 case TARGET_NR_readahead:
bellard5cd43932003-03-29 16:54:36 +00005501 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00005502#endif
bellardebc05482003-09-30 21:08:41 +00005503#ifdef TARGET_NR_setxattr
bellard31e31b82003-02-18 22:55:36 +00005504 case TARGET_NR_setxattr:
5505 case TARGET_NR_lsetxattr:
5506 case TARGET_NR_fsetxattr:
5507 case TARGET_NR_getxattr:
5508 case TARGET_NR_lgetxattr:
5509 case TARGET_NR_fgetxattr:
5510 case TARGET_NR_listxattr:
5511 case TARGET_NR_llistxattr:
5512 case TARGET_NR_flistxattr:
5513 case TARGET_NR_removexattr:
5514 case TARGET_NR_lremovexattr:
5515 case TARGET_NR_fremovexattr:
bellard5cd43932003-03-29 16:54:36 +00005516 goto unimplemented_nowarn;
bellardebc05482003-09-30 21:08:41 +00005517#endif
5518#ifdef TARGET_NR_set_thread_area
bellard5cd43932003-03-29 16:54:36 +00005519 case TARGET_NR_set_thread_area:
bellard8d18e892007-11-14 15:18:40 +00005520#if defined(TARGET_MIPS)
ths6f5b89a2007-03-02 20:48:00 +00005521 ((CPUMIPSState *) cpu_env)->tls_value = arg1;
5522 ret = 0;
5523 break;
bellard8d18e892007-11-14 15:18:40 +00005524#elif defined(TARGET_I386) && defined(TARGET_ABI32)
5525 ret = do_set_thread_area(cpu_env, arg1);
5526 break;
ths6f5b89a2007-03-02 20:48:00 +00005527#else
5528 goto unimplemented_nowarn;
5529#endif
5530#endif
5531#ifdef TARGET_NR_get_thread_area
bellard5cd43932003-03-29 16:54:36 +00005532 case TARGET_NR_get_thread_area:
bellard8d18e892007-11-14 15:18:40 +00005533#if defined(TARGET_I386) && defined(TARGET_ABI32)
5534 ret = do_get_thread_area(cpu_env, arg1);
5535#else
bellard5cd43932003-03-29 16:54:36 +00005536 goto unimplemented_nowarn;
bellardebc05482003-09-30 21:08:41 +00005537#endif
bellard8d18e892007-11-14 15:18:40 +00005538#endif
bellard48dc41e2006-06-21 18:15:50 +00005539#ifdef TARGET_NR_getdomainname
5540 case TARGET_NR_getdomainname:
5541 goto unimplemented_nowarn;
5542#endif
ths6f5b89a2007-03-02 20:48:00 +00005543
thsb5906f92007-03-19 13:32:45 +00005544#ifdef TARGET_NR_clock_gettime
5545 case TARGET_NR_clock_gettime:
5546 {
5547 struct timespec ts;
5548 ret = get_errno(clock_gettime(arg1, &ts));
5549 if (!is_error(ret)) {
5550 host_to_target_timespec(arg2, &ts);
5551 }
5552 break;
5553 }
5554#endif
5555#ifdef TARGET_NR_clock_getres
5556 case TARGET_NR_clock_getres:
5557 {
5558 struct timespec ts;
5559 ret = get_errno(clock_getres(arg1, &ts));
5560 if (!is_error(ret)) {
5561 host_to_target_timespec(arg2, &ts);
5562 }
5563 break;
5564 }
5565#endif
pbrook63d76512008-05-29 13:43:29 +00005566#ifdef TARGET_NR_clock_nanosleep
5567 case TARGET_NR_clock_nanosleep:
5568 {
5569 struct timespec ts;
5570 target_to_host_timespec(&ts, arg3);
5571 ret = get_errno(clock_nanosleep(arg1, arg2, &ts, arg4 ? &ts : NULL));
5572 if (arg4)
5573 host_to_target_timespec(arg4, &ts);
5574 break;
5575 }
5576#endif
thsb5906f92007-03-19 13:32:45 +00005577
ths6f5b89a2007-03-02 20:48:00 +00005578#if defined(TARGET_NR_set_tid_address) && defined(__NR_set_tid_address)
5579 case TARGET_NR_set_tid_address:
bellard579a97f2007-11-11 14:26:47 +00005580 ret = get_errno(set_tid_address((int *)g2h(arg1)));
5581 break;
ths6f5b89a2007-03-02 20:48:00 +00005582#endif
5583
ths3ae43202007-09-16 21:39:48 +00005584#if defined(TARGET_NR_tkill) && defined(__NR_tkill)
ths4cae1d12007-07-12 11:06:53 +00005585 case TARGET_NR_tkill:
pbrook4cb05962008-05-30 18:05:19 +00005586 ret = get_errno(sys_tkill((int)arg1, target_to_host_signal(arg2)));
ths4cae1d12007-07-12 11:06:53 +00005587 break;
5588#endif
5589
ths3ae43202007-09-16 21:39:48 +00005590#if defined(TARGET_NR_tgkill) && defined(__NR_tgkill)
ths71455572007-06-21 21:45:30 +00005591 case TARGET_NR_tgkill:
pbrook4cb05962008-05-30 18:05:19 +00005592 ret = get_errno(sys_tgkill((int)arg1, (int)arg2,
5593 target_to_host_signal(arg3)));
ths71455572007-06-21 21:45:30 +00005594 break;
5595#endif
5596
ths4f2b1fe2007-06-21 21:57:12 +00005597#ifdef TARGET_NR_set_robust_list
5598 case TARGET_NR_set_robust_list:
5599 goto unimplemented_nowarn;
5600#endif
5601
ths9007f0e2007-09-25 17:50:37 +00005602#if defined(TARGET_NR_utimensat) && defined(__NR_utimensat)
5603 case TARGET_NR_utimensat:
5604 {
5605 struct timespec ts[2];
5606 target_to_host_timespec(ts, arg3);
5607 target_to_host_timespec(ts+1, arg3+sizeof(struct target_timespec));
5608 if (!arg2)
5609 ret = get_errno(sys_utimensat(arg1, NULL, ts, arg4));
5610 else {
bellard579a97f2007-11-11 14:26:47 +00005611 if (!(p = lock_user_string(arg2))) {
ths0da46a62007-10-20 20:23:07 +00005612 ret = -TARGET_EFAULT;
bellard579a97f2007-11-11 14:26:47 +00005613 goto fail;
5614 }
5615 ret = get_errno(sys_utimensat(arg1, path(p), ts, arg4));
5616 unlock_user(p, arg2, 0);
ths9007f0e2007-09-25 17:50:37 +00005617 }
5618 }
5619 break;
5620#endif
pbrookbd0c5662008-05-29 14:34:11 +00005621#if defined(USE_NPTL)
5622 case TARGET_NR_futex:
5623 ret = do_futex(arg1, arg2, arg3, arg4, arg5, arg6);
5624 break;
5625#endif
ths9007f0e2007-09-25 17:50:37 +00005626
bellard31e31b82003-02-18 22:55:36 +00005627 default:
5628 unimplemented:
bellard5cd43932003-03-29 16:54:36 +00005629 gemu_log("qemu: Unsupported syscall: %d\n", num);
ths4f2b1fe2007-06-21 21:57:12 +00005630#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 +00005631 unimplemented_nowarn:
bellard80a9d032005-01-03 23:31:27 +00005632#endif
ths0da46a62007-10-20 20:23:07 +00005633 ret = -TARGET_ENOSYS;
bellard31e31b82003-02-18 22:55:36 +00005634 break;
5635 }
bellard579a97f2007-11-11 14:26:47 +00005636fail:
bellardc573ff62004-01-04 15:51:36 +00005637#ifdef DEBUG
5638 gemu_log(" = %ld\n", ret);
5639#endif
thsb92c47c2007-11-01 00:07:38 +00005640 if(do_strace)
5641 print_syscall_ret(num, ret);
bellard31e31b82003-02-18 22:55:36 +00005642 return ret;
bellard579a97f2007-11-11 14:26:47 +00005643efault:
5644 ret = -TARGET_EFAULT;
5645 goto fail;
bellard31e31b82003-02-18 22:55:36 +00005646}