blob: 0654f07a65f3cbc551dd74e988ae1001e12df89f [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
pbrookf0cbb612008-05-30 18:20:05 +00003172#ifdef TARGET_NR_waitid
3173 case TARGET_NR_waitid:
3174 {
3175 siginfo_t info;
3176 info.si_pid = 0;
3177 ret = get_errno(waitid(arg1, arg2, &info, arg4));
3178 if (!is_error(ret) && arg3 && info.si_pid != 0) {
3179 if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_siginfo_t), 0)))
3180 goto efault;
3181 host_to_target_siginfo(p, &info);
3182 unlock_user(p, arg3, sizeof(target_siginfo_t));
3183 }
3184 }
3185 break;
3186#endif
j_mayer7a3148a2007-04-05 07:13:51 +00003187#ifdef TARGET_NR_creat /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00003188 case TARGET_NR_creat:
bellard579a97f2007-11-11 14:26:47 +00003189 if (!(p = lock_user_string(arg1)))
3190 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003191 ret = get_errno(creat(p, arg2));
3192 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003193 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003194#endif
bellard31e31b82003-02-18 22:55:36 +00003195 case TARGET_NR_link:
pbrook53a59602006-03-25 19:31:22 +00003196 {
3197 void * p2;
3198 p = lock_user_string(arg1);
3199 p2 = lock_user_string(arg2);
bellard579a97f2007-11-11 14:26:47 +00003200 if (!p || !p2)
3201 ret = -TARGET_EFAULT;
3202 else
3203 ret = get_errno(link(p, p2));
pbrook53a59602006-03-25 19:31:22 +00003204 unlock_user(p2, arg2, 0);
3205 unlock_user(p, arg1, 0);
3206 }
bellard31e31b82003-02-18 22:55:36 +00003207 break;
ths64f0ce42007-09-24 09:25:06 +00003208#if defined(TARGET_NR_linkat) && defined(__NR_linkat)
3209 case TARGET_NR_linkat:
ths64f0ce42007-09-24 09:25:06 +00003210 {
3211 void * p2 = NULL;
bellard579a97f2007-11-11 14:26:47 +00003212 if (!arg2 || !arg4)
3213 goto efault;
ths64f0ce42007-09-24 09:25:06 +00003214 p = lock_user_string(arg2);
3215 p2 = lock_user_string(arg4);
bellard579a97f2007-11-11 14:26:47 +00003216 if (!p || !p2)
ths0da46a62007-10-20 20:23:07 +00003217 ret = -TARGET_EFAULT;
ths64f0ce42007-09-24 09:25:06 +00003218 else
3219 ret = get_errno(sys_linkat(arg1, p, arg3, p2, arg5));
bellard579a97f2007-11-11 14:26:47 +00003220 unlock_user(p, arg2, 0);
3221 unlock_user(p2, arg4, 0);
ths64f0ce42007-09-24 09:25:06 +00003222 }
3223 break;
3224#endif
bellard31e31b82003-02-18 22:55:36 +00003225 case TARGET_NR_unlink:
bellard579a97f2007-11-11 14:26:47 +00003226 if (!(p = lock_user_string(arg1)))
3227 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003228 ret = get_errno(unlink(p));
3229 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003230 break;
ths8170f562007-09-24 09:24:11 +00003231#if defined(TARGET_NR_unlinkat) && defined(__NR_unlinkat)
3232 case TARGET_NR_unlinkat:
bellard579a97f2007-11-11 14:26:47 +00003233 if (!(p = lock_user_string(arg2)))
3234 goto efault;
3235 ret = get_errno(sys_unlinkat(arg1, p, arg3));
3236 unlock_user(p, arg2, 0);
balroged494d82007-12-11 23:23:52 +00003237 break;
balrogb7d35e62007-12-12 00:40:24 +00003238#endif
bellard31e31b82003-02-18 22:55:36 +00003239 case TARGET_NR_execve:
bellard7854b052003-03-29 17:22:23 +00003240 {
3241 char **argp, **envp;
bellardf7341ff2003-03-30 21:00:25 +00003242 int argc, envc;
blueswir1992f48a2007-10-14 16:27:31 +00003243 abi_ulong gp;
3244 abi_ulong guest_argp;
3245 abi_ulong guest_envp;
3246 abi_ulong addr;
bellard7854b052003-03-29 17:22:23 +00003247 char **q;
3248
bellardf7341ff2003-03-30 21:00:25 +00003249 argc = 0;
pbrook53a59602006-03-25 19:31:22 +00003250 guest_argp = arg2;
pbrookda94d262008-05-30 18:24:00 +00003251 for (gp = guest_argp; gp; gp += sizeof(abi_ulong)) {
ths03aa1972007-12-02 06:28:08 +00003252 if (get_user_ual(addr, gp))
bellard2f619692007-11-16 10:46:05 +00003253 goto efault;
ths03aa1972007-12-02 06:28:08 +00003254 if (!addr)
bellard2f619692007-11-16 10:46:05 +00003255 break;
bellard7854b052003-03-29 17:22:23 +00003256 argc++;
bellard2f619692007-11-16 10:46:05 +00003257 }
bellardf7341ff2003-03-30 21:00:25 +00003258 envc = 0;
pbrook53a59602006-03-25 19:31:22 +00003259 guest_envp = arg3;
pbrookda94d262008-05-30 18:24:00 +00003260 for (gp = guest_envp; gp; gp += sizeof(abi_ulong)) {
ths03aa1972007-12-02 06:28:08 +00003261 if (get_user_ual(addr, gp))
bellard2f619692007-11-16 10:46:05 +00003262 goto efault;
ths03aa1972007-12-02 06:28:08 +00003263 if (!addr)
bellard2f619692007-11-16 10:46:05 +00003264 break;
bellard7854b052003-03-29 17:22:23 +00003265 envc++;
bellard2f619692007-11-16 10:46:05 +00003266 }
bellard7854b052003-03-29 17:22:23 +00003267
bellardf7341ff2003-03-30 21:00:25 +00003268 argp = alloca((argc + 1) * sizeof(void *));
3269 envp = alloca((envc + 1) * sizeof(void *));
bellard7854b052003-03-29 17:22:23 +00003270
pbrookda94d262008-05-30 18:24:00 +00003271 for (gp = guest_argp, q = argp; gp;
blueswir1992f48a2007-10-14 16:27:31 +00003272 gp += sizeof(abi_ulong), q++) {
bellard2f619692007-11-16 10:46:05 +00003273 if (get_user_ual(addr, gp))
3274 goto execve_efault;
pbrook53a59602006-03-25 19:31:22 +00003275 if (!addr)
3276 break;
bellard2f619692007-11-16 10:46:05 +00003277 if (!(*q = lock_user_string(addr)))
3278 goto execve_efault;
pbrook53a59602006-03-25 19:31:22 +00003279 }
bellardf7341ff2003-03-30 21:00:25 +00003280 *q = NULL;
3281
pbrookda94d262008-05-30 18:24:00 +00003282 for (gp = guest_envp, q = envp; gp;
blueswir1992f48a2007-10-14 16:27:31 +00003283 gp += sizeof(abi_ulong), q++) {
bellard2f619692007-11-16 10:46:05 +00003284 if (get_user_ual(addr, gp))
3285 goto execve_efault;
pbrook53a59602006-03-25 19:31:22 +00003286 if (!addr)
3287 break;
bellard2f619692007-11-16 10:46:05 +00003288 if (!(*q = lock_user_string(addr)))
3289 goto execve_efault;
pbrook53a59602006-03-25 19:31:22 +00003290 }
bellardf7341ff2003-03-30 21:00:25 +00003291 *q = NULL;
bellard7854b052003-03-29 17:22:23 +00003292
bellard2f619692007-11-16 10:46:05 +00003293 if (!(p = lock_user_string(arg1)))
3294 goto execve_efault;
pbrook53a59602006-03-25 19:31:22 +00003295 ret = get_errno(execve(p, argp, envp));
3296 unlock_user(p, arg1, 0);
3297
bellard2f619692007-11-16 10:46:05 +00003298 goto execve_end;
3299
3300 execve_efault:
3301 ret = -TARGET_EFAULT;
3302
3303 execve_end:
pbrook53a59602006-03-25 19:31:22 +00003304 for (gp = guest_argp, q = argp; *q;
blueswir1992f48a2007-10-14 16:27:31 +00003305 gp += sizeof(abi_ulong), q++) {
bellard2f619692007-11-16 10:46:05 +00003306 if (get_user_ual(addr, gp)
3307 || !addr)
3308 break;
pbrook53a59602006-03-25 19:31:22 +00003309 unlock_user(*q, addr, 0);
3310 }
3311 for (gp = guest_envp, q = envp; *q;
blueswir1992f48a2007-10-14 16:27:31 +00003312 gp += sizeof(abi_ulong), q++) {
bellard2f619692007-11-16 10:46:05 +00003313 if (get_user_ual(addr, gp)
3314 || !addr)
3315 break;
pbrook53a59602006-03-25 19:31:22 +00003316 unlock_user(*q, addr, 0);
3317 }
bellard7854b052003-03-29 17:22:23 +00003318 }
bellard31e31b82003-02-18 22:55:36 +00003319 break;
3320 case TARGET_NR_chdir:
bellard579a97f2007-11-11 14:26:47 +00003321 if (!(p = lock_user_string(arg1)))
3322 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003323 ret = get_errno(chdir(p));
3324 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003325 break;
bellarda315a142005-01-30 22:59:18 +00003326#ifdef TARGET_NR_time
bellard31e31b82003-02-18 22:55:36 +00003327 case TARGET_NR_time:
3328 {
pbrook53a59602006-03-25 19:31:22 +00003329 time_t host_time;
3330 ret = get_errno(time(&host_time));
bellard2f619692007-11-16 10:46:05 +00003331 if (!is_error(ret)
3332 && arg1
3333 && put_user_sal(host_time, arg1))
3334 goto efault;
bellard31e31b82003-02-18 22:55:36 +00003335 }
3336 break;
bellarda315a142005-01-30 22:59:18 +00003337#endif
bellard31e31b82003-02-18 22:55:36 +00003338 case TARGET_NR_mknod:
bellard579a97f2007-11-11 14:26:47 +00003339 if (!(p = lock_user_string(arg1)))
3340 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003341 ret = get_errno(mknod(p, arg2, arg3));
3342 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003343 break;
ths75ac37a2007-09-24 09:23:05 +00003344#if defined(TARGET_NR_mknodat) && defined(__NR_mknodat)
3345 case TARGET_NR_mknodat:
bellard579a97f2007-11-11 14:26:47 +00003346 if (!(p = lock_user_string(arg2)))
3347 goto efault;
3348 ret = get_errno(sys_mknodat(arg1, p, arg3, arg4));
3349 unlock_user(p, arg2, 0);
ths75ac37a2007-09-24 09:23:05 +00003350 break;
3351#endif
bellard31e31b82003-02-18 22:55:36 +00003352 case TARGET_NR_chmod:
bellard579a97f2007-11-11 14:26:47 +00003353 if (!(p = lock_user_string(arg1)))
3354 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003355 ret = get_errno(chmod(p, arg2));
3356 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003357 break;
bellardebc05482003-09-30 21:08:41 +00003358#ifdef TARGET_NR_break
bellard31e31b82003-02-18 22:55:36 +00003359 case TARGET_NR_break:
3360 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00003361#endif
3362#ifdef TARGET_NR_oldstat
bellard31e31b82003-02-18 22:55:36 +00003363 case TARGET_NR_oldstat:
3364 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00003365#endif
bellard31e31b82003-02-18 22:55:36 +00003366 case TARGET_NR_lseek:
3367 ret = get_errno(lseek(arg1, arg2, arg3));
3368 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003369#ifdef TARGET_NR_getxpid
3370 case TARGET_NR_getxpid:
3371#else
bellard31e31b82003-02-18 22:55:36 +00003372 case TARGET_NR_getpid:
j_mayer7a3148a2007-04-05 07:13:51 +00003373#endif
bellard31e31b82003-02-18 22:55:36 +00003374 ret = get_errno(getpid());
3375 break;
3376 case TARGET_NR_mount:
ths80265912007-02-17 22:25:41 +00003377 {
3378 /* need to look at the data field */
3379 void *p2, *p3;
3380 p = lock_user_string(arg1);
3381 p2 = lock_user_string(arg2);
3382 p3 = lock_user_string(arg3);
bellard579a97f2007-11-11 14:26:47 +00003383 if (!p || !p2 || !p3)
3384 ret = -TARGET_EFAULT;
3385 else
3386 /* FIXME - arg5 should be locked, but it isn't clear how to
3387 * do that since it's not guaranteed to be a NULL-terminated
3388 * string.
3389 */
3390 ret = get_errno(mount(p, p2, p3, (unsigned long)arg4, g2h(arg5)));
3391 unlock_user(p, arg1, 0);
3392 unlock_user(p2, arg2, 0);
3393 unlock_user(p3, arg3, 0);
ths80265912007-02-17 22:25:41 +00003394 break;
3395 }
thse5febef2007-04-01 18:31:35 +00003396#ifdef TARGET_NR_umount
bellard31e31b82003-02-18 22:55:36 +00003397 case TARGET_NR_umount:
bellard579a97f2007-11-11 14:26:47 +00003398 if (!(p = lock_user_string(arg1)))
3399 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003400 ret = get_errno(umount(p));
3401 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003402 break;
thse5febef2007-04-01 18:31:35 +00003403#endif
j_mayer7a3148a2007-04-05 07:13:51 +00003404#ifdef TARGET_NR_stime /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00003405 case TARGET_NR_stime:
3406 {
pbrook53a59602006-03-25 19:31:22 +00003407 time_t host_time;
bellard2f619692007-11-16 10:46:05 +00003408 if (get_user_sal(host_time, arg1))
3409 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003410 ret = get_errno(stime(&host_time));
bellard31e31b82003-02-18 22:55:36 +00003411 }
3412 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003413#endif
bellard31e31b82003-02-18 22:55:36 +00003414 case TARGET_NR_ptrace:
3415 goto unimplemented;
j_mayer7a3148a2007-04-05 07:13:51 +00003416#ifdef TARGET_NR_alarm /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00003417 case TARGET_NR_alarm:
3418 ret = alarm(arg1);
3419 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003420#endif
bellardebc05482003-09-30 21:08:41 +00003421#ifdef TARGET_NR_oldfstat
bellard31e31b82003-02-18 22:55:36 +00003422 case TARGET_NR_oldfstat:
3423 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00003424#endif
j_mayer7a3148a2007-04-05 07:13:51 +00003425#ifdef TARGET_NR_pause /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00003426 case TARGET_NR_pause:
3427 ret = get_errno(pause());
3428 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003429#endif
thse5febef2007-04-01 18:31:35 +00003430#ifdef TARGET_NR_utime
bellard31e31b82003-02-18 22:55:36 +00003431 case TARGET_NR_utime:
bellardebc05482003-09-30 21:08:41 +00003432 {
pbrook53a59602006-03-25 19:31:22 +00003433 struct utimbuf tbuf, *host_tbuf;
3434 struct target_utimbuf *target_tbuf;
3435 if (arg2) {
bellard579a97f2007-11-11 14:26:47 +00003436 if (!lock_user_struct(VERIFY_READ, target_tbuf, arg2, 1))
3437 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003438 tbuf.actime = tswapl(target_tbuf->actime);
3439 tbuf.modtime = tswapl(target_tbuf->modtime);
3440 unlock_user_struct(target_tbuf, arg2, 0);
3441 host_tbuf = &tbuf;
bellardf72e8ff2004-05-03 19:23:07 +00003442 } else {
pbrook53a59602006-03-25 19:31:22 +00003443 host_tbuf = NULL;
bellardf72e8ff2004-05-03 19:23:07 +00003444 }
bellard579a97f2007-11-11 14:26:47 +00003445 if (!(p = lock_user_string(arg1)))
3446 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003447 ret = get_errno(utime(p, host_tbuf));
3448 unlock_user(p, arg1, 0);
bellardebc05482003-09-30 21:08:41 +00003449 }
3450 break;
thse5febef2007-04-01 18:31:35 +00003451#endif
bellard978a66f2004-12-06 22:58:05 +00003452 case TARGET_NR_utimes:
3453 {
bellard978a66f2004-12-06 22:58:05 +00003454 struct timeval *tvp, tv[2];
pbrook53a59602006-03-25 19:31:22 +00003455 if (arg2) {
ths788f5ec2007-12-09 02:37:05 +00003456 if (copy_from_user_timeval(&tv[0], arg2)
3457 || copy_from_user_timeval(&tv[1],
3458 arg2 + sizeof(struct target_timeval)))
3459 goto efault;
bellard978a66f2004-12-06 22:58:05 +00003460 tvp = tv;
3461 } else {
3462 tvp = NULL;
3463 }
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(utimes(p, tvp));
3467 unlock_user(p, arg1, 0);
bellard978a66f2004-12-06 22:58:05 +00003468 }
3469 break;
bellardebc05482003-09-30 21:08:41 +00003470#ifdef TARGET_NR_stty
bellard31e31b82003-02-18 22:55:36 +00003471 case TARGET_NR_stty:
3472 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00003473#endif
3474#ifdef TARGET_NR_gtty
bellard31e31b82003-02-18 22:55:36 +00003475 case TARGET_NR_gtty:
3476 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00003477#endif
bellard31e31b82003-02-18 22:55:36 +00003478 case TARGET_NR_access:
bellard579a97f2007-11-11 14:26:47 +00003479 if (!(p = lock_user_string(arg1)))
3480 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003481 ret = get_errno(access(p, arg2));
3482 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003483 break;
ths92a34c12007-09-24 09:27:49 +00003484#if defined(TARGET_NR_faccessat) && defined(__NR_faccessat)
3485 case TARGET_NR_faccessat:
bellard579a97f2007-11-11 14:26:47 +00003486 if (!(p = lock_user_string(arg2)))
3487 goto efault;
3488 ret = get_errno(sys_faccessat(arg1, p, arg3, arg4));
3489 unlock_user(p, arg2, 0);
ths92a34c12007-09-24 09:27:49 +00003490 break;
3491#endif
j_mayer7a3148a2007-04-05 07:13:51 +00003492#ifdef TARGET_NR_nice /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00003493 case TARGET_NR_nice:
3494 ret = get_errno(nice(arg1));
3495 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003496#endif
bellardebc05482003-09-30 21:08:41 +00003497#ifdef TARGET_NR_ftime
bellard31e31b82003-02-18 22:55:36 +00003498 case TARGET_NR_ftime:
3499 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00003500#endif
bellard31e31b82003-02-18 22:55:36 +00003501 case TARGET_NR_sync:
bellard04369ff2003-03-20 22:33:23 +00003502 sync();
3503 ret = 0;
bellard31e31b82003-02-18 22:55:36 +00003504 break;
3505 case TARGET_NR_kill:
pbrook4cb05962008-05-30 18:05:19 +00003506 ret = get_errno(kill(arg1, target_to_host_signal(arg2)));
bellard31e31b82003-02-18 22:55:36 +00003507 break;
3508 case TARGET_NR_rename:
pbrook53a59602006-03-25 19:31:22 +00003509 {
3510 void *p2;
3511 p = lock_user_string(arg1);
3512 p2 = lock_user_string(arg2);
bellard579a97f2007-11-11 14:26:47 +00003513 if (!p || !p2)
3514 ret = -TARGET_EFAULT;
3515 else
3516 ret = get_errno(rename(p, p2));
pbrook53a59602006-03-25 19:31:22 +00003517 unlock_user(p2, arg2, 0);
3518 unlock_user(p, arg1, 0);
3519 }
bellard31e31b82003-02-18 22:55:36 +00003520 break;
ths722183f2007-09-24 09:24:37 +00003521#if defined(TARGET_NR_renameat) && defined(__NR_renameat)
3522 case TARGET_NR_renameat:
ths722183f2007-09-24 09:24:37 +00003523 {
bellard579a97f2007-11-11 14:26:47 +00003524 void *p2;
ths722183f2007-09-24 09:24:37 +00003525 p = lock_user_string(arg2);
3526 p2 = lock_user_string(arg4);
bellard579a97f2007-11-11 14:26:47 +00003527 if (!p || !p2)
ths0da46a62007-10-20 20:23:07 +00003528 ret = -TARGET_EFAULT;
ths722183f2007-09-24 09:24:37 +00003529 else
3530 ret = get_errno(sys_renameat(arg1, p, arg3, p2));
bellard579a97f2007-11-11 14:26:47 +00003531 unlock_user(p2, arg4, 0);
3532 unlock_user(p, arg2, 0);
ths722183f2007-09-24 09:24:37 +00003533 }
3534 break;
3535#endif
bellard31e31b82003-02-18 22:55:36 +00003536 case TARGET_NR_mkdir:
bellard579a97f2007-11-11 14:26:47 +00003537 if (!(p = lock_user_string(arg1)))
3538 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003539 ret = get_errno(mkdir(p, arg2));
3540 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003541 break;
ths4472ad02007-09-24 09:22:32 +00003542#if defined(TARGET_NR_mkdirat) && defined(__NR_mkdirat)
3543 case TARGET_NR_mkdirat:
bellard579a97f2007-11-11 14:26:47 +00003544 if (!(p = lock_user_string(arg2)))
3545 goto efault;
3546 ret = get_errno(sys_mkdirat(arg1, p, arg3));
3547 unlock_user(p, arg2, 0);
ths4472ad02007-09-24 09:22:32 +00003548 break;
3549#endif
bellard31e31b82003-02-18 22:55:36 +00003550 case TARGET_NR_rmdir:
bellard579a97f2007-11-11 14:26:47 +00003551 if (!(p = lock_user_string(arg1)))
3552 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003553 ret = get_errno(rmdir(p));
3554 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003555 break;
3556 case TARGET_NR_dup:
3557 ret = get_errno(dup(arg1));
3558 break;
3559 case TARGET_NR_pipe:
3560 {
pbrook53a59602006-03-25 19:31:22 +00003561 int host_pipe[2];
3562 ret = get_errno(pipe(host_pipe));
bellard31e31b82003-02-18 22:55:36 +00003563 if (!is_error(ret)) {
thsc12ab052007-06-01 11:50:36 +00003564#if defined(TARGET_MIPS)
thsead93602007-09-06 00:18:15 +00003565 CPUMIPSState *env = (CPUMIPSState*)cpu_env;
thsd0dc7dc2008-02-12 21:01:26 +00003566 env->gpr[env->current_tc][3] = host_pipe[1];
thsc12ab052007-06-01 11:50:36 +00003567 ret = host_pipe[0];
aurel32b5eff352008-03-11 23:30:22 +00003568#elif defined(TARGET_SH4)
3569 ((CPUSH4State*)cpu_env)->gregs[1] = host_pipe[1];
3570 ret = host_pipe[0];
thsc12ab052007-06-01 11:50:36 +00003571#else
bellard2f619692007-11-16 10:46:05 +00003572 if (put_user_s32(host_pipe[0], arg1)
3573 || put_user_s32(host_pipe[1], arg1 + sizeof(host_pipe[0])))
3574 goto efault;
thsc12ab052007-06-01 11:50:36 +00003575#endif
bellard31e31b82003-02-18 22:55:36 +00003576 }
3577 }
3578 break;
3579 case TARGET_NR_times:
bellard32f36bc2003-03-30 21:29:48 +00003580 {
pbrook53a59602006-03-25 19:31:22 +00003581 struct target_tms *tmsp;
bellard32f36bc2003-03-30 21:29:48 +00003582 struct tms tms;
3583 ret = get_errno(times(&tms));
pbrook53a59602006-03-25 19:31:22 +00003584 if (arg1) {
bellard579a97f2007-11-11 14:26:47 +00003585 tmsp = lock_user(VERIFY_WRITE, arg1, sizeof(struct target_tms), 0);
3586 if (!tmsp)
3587 goto efault;
bellardc596ed12003-07-13 17:32:31 +00003588 tmsp->tms_utime = tswapl(host_to_target_clock_t(tms.tms_utime));
3589 tmsp->tms_stime = tswapl(host_to_target_clock_t(tms.tms_stime));
3590 tmsp->tms_cutime = tswapl(host_to_target_clock_t(tms.tms_cutime));
3591 tmsp->tms_cstime = tswapl(host_to_target_clock_t(tms.tms_cstime));
bellard32f36bc2003-03-30 21:29:48 +00003592 }
bellardc596ed12003-07-13 17:32:31 +00003593 if (!is_error(ret))
3594 ret = host_to_target_clock_t(ret);
bellard32f36bc2003-03-30 21:29:48 +00003595 }
3596 break;
bellardebc05482003-09-30 21:08:41 +00003597#ifdef TARGET_NR_prof
bellard31e31b82003-02-18 22:55:36 +00003598 case TARGET_NR_prof:
3599 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00003600#endif
thse5febef2007-04-01 18:31:35 +00003601#ifdef TARGET_NR_signal
bellard31e31b82003-02-18 22:55:36 +00003602 case TARGET_NR_signal:
3603 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00003604#endif
bellard31e31b82003-02-18 22:55:36 +00003605 case TARGET_NR_acct:
bellard579a97f2007-11-11 14:26:47 +00003606 if (!(p = lock_user_string(arg1)))
3607 goto efault;
pbrook24836682006-04-16 14:14:53 +00003608 ret = get_errno(acct(path(p)));
3609 unlock_user(p, arg1, 0);
3610 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003611#ifdef TARGET_NR_umount2 /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00003612 case TARGET_NR_umount2:
bellard579a97f2007-11-11 14:26:47 +00003613 if (!(p = lock_user_string(arg1)))
3614 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003615 ret = get_errno(umount2(p, arg2));
3616 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003617 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003618#endif
bellardebc05482003-09-30 21:08:41 +00003619#ifdef TARGET_NR_lock
bellard31e31b82003-02-18 22:55:36 +00003620 case TARGET_NR_lock:
3621 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00003622#endif
bellard31e31b82003-02-18 22:55:36 +00003623 case TARGET_NR_ioctl:
3624 ret = do_ioctl(arg1, arg2, arg3);
3625 break;
3626 case TARGET_NR_fcntl:
bellard9ee1fa22007-11-11 15:11:19 +00003627 ret = do_fcntl(arg1, arg2, arg3);
bellard31e31b82003-02-18 22:55:36 +00003628 break;
bellardebc05482003-09-30 21:08:41 +00003629#ifdef TARGET_NR_mpx
bellard31e31b82003-02-18 22:55:36 +00003630 case TARGET_NR_mpx:
3631 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00003632#endif
bellard31e31b82003-02-18 22:55:36 +00003633 case TARGET_NR_setpgid:
3634 ret = get_errno(setpgid(arg1, arg2));
3635 break;
bellardebc05482003-09-30 21:08:41 +00003636#ifdef TARGET_NR_ulimit
bellard31e31b82003-02-18 22:55:36 +00003637 case TARGET_NR_ulimit:
3638 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00003639#endif
3640#ifdef TARGET_NR_oldolduname
bellard31e31b82003-02-18 22:55:36 +00003641 case TARGET_NR_oldolduname:
3642 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00003643#endif
bellard31e31b82003-02-18 22:55:36 +00003644 case TARGET_NR_umask:
3645 ret = get_errno(umask(arg1));
3646 break;
3647 case TARGET_NR_chroot:
bellard579a97f2007-11-11 14:26:47 +00003648 if (!(p = lock_user_string(arg1)))
3649 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003650 ret = get_errno(chroot(p));
3651 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003652 break;
3653 case TARGET_NR_ustat:
3654 goto unimplemented;
3655 case TARGET_NR_dup2:
3656 ret = get_errno(dup2(arg1, arg2));
3657 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003658#ifdef TARGET_NR_getppid /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00003659 case TARGET_NR_getppid:
3660 ret = get_errno(getppid());
3661 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003662#endif
bellard31e31b82003-02-18 22:55:36 +00003663 case TARGET_NR_getpgrp:
3664 ret = get_errno(getpgrp());
3665 break;
3666 case TARGET_NR_setsid:
3667 ret = get_errno(setsid());
3668 break;
thse5febef2007-04-01 18:31:35 +00003669#ifdef TARGET_NR_sigaction
bellard31e31b82003-02-18 22:55:36 +00003670 case TARGET_NR_sigaction:
bellard31e31b82003-02-18 22:55:36 +00003671 {
ths388bb212007-05-13 13:58:00 +00003672#if !defined(TARGET_MIPS)
pbrook53a59602006-03-25 19:31:22 +00003673 struct target_old_sigaction *old_act;
bellard66fb9762003-03-23 01:06:05 +00003674 struct target_sigaction act, oact, *pact;
pbrook53a59602006-03-25 19:31:22 +00003675 if (arg2) {
bellard579a97f2007-11-11 14:26:47 +00003676 if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1))
3677 goto efault;
bellard66fb9762003-03-23 01:06:05 +00003678 act._sa_handler = old_act->_sa_handler;
3679 target_siginitset(&act.sa_mask, old_act->sa_mask);
3680 act.sa_flags = old_act->sa_flags;
3681 act.sa_restorer = old_act->sa_restorer;
pbrook53a59602006-03-25 19:31:22 +00003682 unlock_user_struct(old_act, arg2, 0);
bellard66fb9762003-03-23 01:06:05 +00003683 pact = &act;
3684 } else {
3685 pact = NULL;
3686 }
3687 ret = get_errno(do_sigaction(arg1, pact, &oact));
pbrook53a59602006-03-25 19:31:22 +00003688 if (!is_error(ret) && arg3) {
bellard579a97f2007-11-11 14:26:47 +00003689 if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0))
3690 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003691 old_act->_sa_handler = oact._sa_handler;
3692 old_act->sa_mask = oact.sa_mask.sig[0];
3693 old_act->sa_flags = oact.sa_flags;
3694 old_act->sa_restorer = oact.sa_restorer;
3695 unlock_user_struct(old_act, arg3, 1);
bellard66fb9762003-03-23 01:06:05 +00003696 }
ths388bb212007-05-13 13:58:00 +00003697#else
bellard106ec872006-06-27 21:08:10 +00003698 struct target_sigaction act, oact, *pact, *old_act;
3699
3700 if (arg2) {
bellard579a97f2007-11-11 14:26:47 +00003701 if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1))
3702 goto efault;
bellard106ec872006-06-27 21:08:10 +00003703 act._sa_handler = old_act->_sa_handler;
3704 target_siginitset(&act.sa_mask, old_act->sa_mask.sig[0]);
3705 act.sa_flags = old_act->sa_flags;
3706 unlock_user_struct(old_act, arg2, 0);
3707 pact = &act;
3708 } else {
3709 pact = NULL;
3710 }
3711
3712 ret = get_errno(do_sigaction(arg1, pact, &oact));
3713
3714 if (!is_error(ret) && arg3) {
bellard579a97f2007-11-11 14:26:47 +00003715 if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0))
3716 goto efault;
bellard106ec872006-06-27 21:08:10 +00003717 old_act->_sa_handler = oact._sa_handler;
3718 old_act->sa_flags = oact.sa_flags;
3719 old_act->sa_mask.sig[0] = oact.sa_mask.sig[0];
3720 old_act->sa_mask.sig[1] = 0;
3721 old_act->sa_mask.sig[2] = 0;
3722 old_act->sa_mask.sig[3] = 0;
3723 unlock_user_struct(old_act, arg3, 1);
3724 }
ths388bb212007-05-13 13:58:00 +00003725#endif
bellard31e31b82003-02-18 22:55:36 +00003726 }
3727 break;
thse5febef2007-04-01 18:31:35 +00003728#endif
bellard66fb9762003-03-23 01:06:05 +00003729 case TARGET_NR_rt_sigaction:
pbrook53a59602006-03-25 19:31:22 +00003730 {
3731 struct target_sigaction *act;
3732 struct target_sigaction *oact;
3733
bellard579a97f2007-11-11 14:26:47 +00003734 if (arg2) {
3735 if (!lock_user_struct(VERIFY_READ, act, arg2, 1))
3736 goto efault;
3737 } else
pbrook53a59602006-03-25 19:31:22 +00003738 act = NULL;
bellard579a97f2007-11-11 14:26:47 +00003739 if (arg3) {
3740 if (!lock_user_struct(VERIFY_WRITE, oact, arg3, 0)) {
3741 ret = -TARGET_EFAULT;
3742 goto rt_sigaction_fail;
3743 }
3744 } else
pbrook53a59602006-03-25 19:31:22 +00003745 oact = NULL;
3746 ret = get_errno(do_sigaction(arg1, act, oact));
bellard579a97f2007-11-11 14:26:47 +00003747 rt_sigaction_fail:
3748 if (act)
pbrook53a59602006-03-25 19:31:22 +00003749 unlock_user_struct(act, arg2, 0);
bellard579a97f2007-11-11 14:26:47 +00003750 if (oact)
pbrook53a59602006-03-25 19:31:22 +00003751 unlock_user_struct(oact, arg3, 1);
3752 }
bellard66fb9762003-03-23 01:06:05 +00003753 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003754#ifdef TARGET_NR_sgetmask /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00003755 case TARGET_NR_sgetmask:
bellard66fb9762003-03-23 01:06:05 +00003756 {
3757 sigset_t cur_set;
blueswir1992f48a2007-10-14 16:27:31 +00003758 abi_ulong target_set;
bellard66fb9762003-03-23 01:06:05 +00003759 sigprocmask(0, NULL, &cur_set);
3760 host_to_target_old_sigset(&target_set, &cur_set);
3761 ret = target_set;
3762 }
3763 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003764#endif
3765#ifdef TARGET_NR_ssetmask /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00003766 case TARGET_NR_ssetmask:
bellard66fb9762003-03-23 01:06:05 +00003767 {
3768 sigset_t set, oset, cur_set;
blueswir1992f48a2007-10-14 16:27:31 +00003769 abi_ulong target_set = arg1;
bellard66fb9762003-03-23 01:06:05 +00003770 sigprocmask(0, NULL, &cur_set);
3771 target_to_host_old_sigset(&set, &target_set);
3772 sigorset(&set, &set, &cur_set);
3773 sigprocmask(SIG_SETMASK, &set, &oset);
3774 host_to_target_old_sigset(&target_set, &oset);
3775 ret = target_set;
3776 }
3777 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003778#endif
thse5febef2007-04-01 18:31:35 +00003779#ifdef TARGET_NR_sigprocmask
bellard66fb9762003-03-23 01:06:05 +00003780 case TARGET_NR_sigprocmask:
3781 {
3782 int how = arg1;
3783 sigset_t set, oldset, *set_ptr;
ths3b46e622007-09-17 08:09:54 +00003784
pbrook53a59602006-03-25 19:31:22 +00003785 if (arg2) {
bellard66fb9762003-03-23 01:06:05 +00003786 switch(how) {
3787 case TARGET_SIG_BLOCK:
3788 how = SIG_BLOCK;
3789 break;
3790 case TARGET_SIG_UNBLOCK:
3791 how = SIG_UNBLOCK;
3792 break;
3793 case TARGET_SIG_SETMASK:
3794 how = SIG_SETMASK;
3795 break;
3796 default:
ths0da46a62007-10-20 20:23:07 +00003797 ret = -TARGET_EINVAL;
bellard66fb9762003-03-23 01:06:05 +00003798 goto fail;
3799 }
bellard579a97f2007-11-11 14:26:47 +00003800 if (!(p = lock_user(VERIFY_READ, arg2, sizeof(target_sigset_t), 1)))
3801 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003802 target_to_host_old_sigset(&set, p);
3803 unlock_user(p, arg2, 0);
bellard66fb9762003-03-23 01:06:05 +00003804 set_ptr = &set;
3805 } else {
3806 how = 0;
3807 set_ptr = NULL;
3808 }
3809 ret = get_errno(sigprocmask(arg1, set_ptr, &oldset));
pbrook53a59602006-03-25 19:31:22 +00003810 if (!is_error(ret) && arg3) {
bellard579a97f2007-11-11 14:26:47 +00003811 if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0)))
3812 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003813 host_to_target_old_sigset(p, &oldset);
3814 unlock_user(p, arg3, sizeof(target_sigset_t));
bellard66fb9762003-03-23 01:06:05 +00003815 }
3816 }
3817 break;
thse5febef2007-04-01 18:31:35 +00003818#endif
bellard66fb9762003-03-23 01:06:05 +00003819 case TARGET_NR_rt_sigprocmask:
3820 {
3821 int how = arg1;
3822 sigset_t set, oldset, *set_ptr;
ths3b46e622007-09-17 08:09:54 +00003823
pbrook53a59602006-03-25 19:31:22 +00003824 if (arg2) {
bellard66fb9762003-03-23 01:06:05 +00003825 switch(how) {
3826 case TARGET_SIG_BLOCK:
3827 how = SIG_BLOCK;
3828 break;
3829 case TARGET_SIG_UNBLOCK:
3830 how = SIG_UNBLOCK;
3831 break;
3832 case TARGET_SIG_SETMASK:
3833 how = SIG_SETMASK;
3834 break;
3835 default:
ths0da46a62007-10-20 20:23:07 +00003836 ret = -TARGET_EINVAL;
bellard66fb9762003-03-23 01:06:05 +00003837 goto fail;
3838 }
bellard579a97f2007-11-11 14:26:47 +00003839 if (!(p = lock_user(VERIFY_READ, arg2, sizeof(target_sigset_t), 1)))
3840 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003841 target_to_host_sigset(&set, p);
3842 unlock_user(p, arg2, 0);
bellard66fb9762003-03-23 01:06:05 +00003843 set_ptr = &set;
3844 } else {
3845 how = 0;
3846 set_ptr = NULL;
3847 }
3848 ret = get_errno(sigprocmask(how, set_ptr, &oldset));
pbrook53a59602006-03-25 19:31:22 +00003849 if (!is_error(ret) && arg3) {
bellard579a97f2007-11-11 14:26:47 +00003850 if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0)))
3851 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003852 host_to_target_sigset(p, &oldset);
3853 unlock_user(p, arg3, sizeof(target_sigset_t));
bellard66fb9762003-03-23 01:06:05 +00003854 }
3855 }
3856 break;
thse5febef2007-04-01 18:31:35 +00003857#ifdef TARGET_NR_sigpending
bellard66fb9762003-03-23 01:06:05 +00003858 case TARGET_NR_sigpending:
3859 {
3860 sigset_t set;
3861 ret = get_errno(sigpending(&set));
3862 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00003863 if (!(p = lock_user(VERIFY_WRITE, arg1, sizeof(target_sigset_t), 0)))
3864 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003865 host_to_target_old_sigset(p, &set);
3866 unlock_user(p, arg1, sizeof(target_sigset_t));
bellard66fb9762003-03-23 01:06:05 +00003867 }
3868 }
3869 break;
thse5febef2007-04-01 18:31:35 +00003870#endif
bellard66fb9762003-03-23 01:06:05 +00003871 case TARGET_NR_rt_sigpending:
3872 {
3873 sigset_t set;
3874 ret = get_errno(sigpending(&set));
3875 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00003876 if (!(p = lock_user(VERIFY_WRITE, arg1, sizeof(target_sigset_t), 0)))
3877 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003878 host_to_target_sigset(p, &set);
3879 unlock_user(p, arg1, sizeof(target_sigset_t));
bellard66fb9762003-03-23 01:06:05 +00003880 }
3881 }
3882 break;
thse5febef2007-04-01 18:31:35 +00003883#ifdef TARGET_NR_sigsuspend
bellard66fb9762003-03-23 01:06:05 +00003884 case TARGET_NR_sigsuspend:
3885 {
3886 sigset_t set;
bellard579a97f2007-11-11 14:26:47 +00003887 if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
3888 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003889 target_to_host_old_sigset(&set, p);
3890 unlock_user(p, arg1, 0);
bellard66fb9762003-03-23 01:06:05 +00003891 ret = get_errno(sigsuspend(&set));
3892 }
3893 break;
thse5febef2007-04-01 18:31:35 +00003894#endif
bellard66fb9762003-03-23 01:06:05 +00003895 case TARGET_NR_rt_sigsuspend:
3896 {
3897 sigset_t set;
bellard579a97f2007-11-11 14:26:47 +00003898 if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
3899 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003900 target_to_host_sigset(&set, p);
3901 unlock_user(p, arg1, 0);
bellard66fb9762003-03-23 01:06:05 +00003902 ret = get_errno(sigsuspend(&set));
3903 }
3904 break;
3905 case TARGET_NR_rt_sigtimedwait:
3906 {
bellard66fb9762003-03-23 01:06:05 +00003907 sigset_t set;
3908 struct timespec uts, *puts;
3909 siginfo_t uinfo;
ths3b46e622007-09-17 08:09:54 +00003910
bellard579a97f2007-11-11 14:26:47 +00003911 if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
3912 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003913 target_to_host_sigset(&set, p);
3914 unlock_user(p, arg1, 0);
3915 if (arg3) {
bellard66fb9762003-03-23 01:06:05 +00003916 puts = &uts;
pbrook53a59602006-03-25 19:31:22 +00003917 target_to_host_timespec(puts, arg3);
bellard66fb9762003-03-23 01:06:05 +00003918 } else {
3919 puts = NULL;
3920 }
3921 ret = get_errno(sigtimedwait(&set, &uinfo, puts));
pbrook53a59602006-03-25 19:31:22 +00003922 if (!is_error(ret) && arg2) {
bellard579a97f2007-11-11 14:26:47 +00003923 if (!(p = lock_user(VERIFY_WRITE, arg2, sizeof(target_sigset_t), 0)))
3924 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003925 host_to_target_siginfo(p, &uinfo);
3926 unlock_user(p, arg2, sizeof(target_sigset_t));
bellard66fb9762003-03-23 01:06:05 +00003927 }
3928 }
3929 break;
3930 case TARGET_NR_rt_sigqueueinfo:
3931 {
3932 siginfo_t uinfo;
bellard579a97f2007-11-11 14:26:47 +00003933 if (!(p = lock_user(VERIFY_READ, arg3, sizeof(target_sigset_t), 1)))
3934 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003935 target_to_host_siginfo(&uinfo, p);
3936 unlock_user(p, arg1, 0);
bellard66fb9762003-03-23 01:06:05 +00003937 ret = get_errno(sys_rt_sigqueueinfo(arg1, arg2, &uinfo));
3938 }
3939 break;
thse5febef2007-04-01 18:31:35 +00003940#ifdef TARGET_NR_sigreturn
bellard66fb9762003-03-23 01:06:05 +00003941 case TARGET_NR_sigreturn:
3942 /* NOTE: ret is eax, so not transcoding must be done */
3943 ret = do_sigreturn(cpu_env);
3944 break;
thse5febef2007-04-01 18:31:35 +00003945#endif
bellard66fb9762003-03-23 01:06:05 +00003946 case TARGET_NR_rt_sigreturn:
3947 /* NOTE: ret is eax, so not transcoding must be done */
3948 ret = do_rt_sigreturn(cpu_env);
3949 break;
bellard31e31b82003-02-18 22:55:36 +00003950 case TARGET_NR_sethostname:
bellard579a97f2007-11-11 14:26:47 +00003951 if (!(p = lock_user_string(arg1)))
3952 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003953 ret = get_errno(sethostname(p, arg2));
3954 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003955 break;
3956 case TARGET_NR_setrlimit:
bellard9de5e442003-03-23 16:49:39 +00003957 {
3958 /* XXX: convert resource ? */
3959 int resource = arg1;
pbrook53a59602006-03-25 19:31:22 +00003960 struct target_rlimit *target_rlim;
bellard9de5e442003-03-23 16:49:39 +00003961 struct rlimit rlim;
bellard579a97f2007-11-11 14:26:47 +00003962 if (!lock_user_struct(VERIFY_READ, target_rlim, arg2, 1))
3963 goto efault;
bellard9de5e442003-03-23 16:49:39 +00003964 rlim.rlim_cur = tswapl(target_rlim->rlim_cur);
3965 rlim.rlim_max = tswapl(target_rlim->rlim_max);
pbrook53a59602006-03-25 19:31:22 +00003966 unlock_user_struct(target_rlim, arg2, 0);
bellard9de5e442003-03-23 16:49:39 +00003967 ret = get_errno(setrlimit(resource, &rlim));
3968 }
3969 break;
bellard31e31b82003-02-18 22:55:36 +00003970 case TARGET_NR_getrlimit:
bellard9de5e442003-03-23 16:49:39 +00003971 {
3972 /* XXX: convert resource ? */
3973 int resource = arg1;
pbrook53a59602006-03-25 19:31:22 +00003974 struct target_rlimit *target_rlim;
bellard9de5e442003-03-23 16:49:39 +00003975 struct rlimit rlim;
ths3b46e622007-09-17 08:09:54 +00003976
bellard9de5e442003-03-23 16:49:39 +00003977 ret = get_errno(getrlimit(resource, &rlim));
3978 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00003979 if (!lock_user_struct(VERIFY_WRITE, target_rlim, arg2, 0))
3980 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003981 rlim.rlim_cur = tswapl(target_rlim->rlim_cur);
3982 rlim.rlim_max = tswapl(target_rlim->rlim_max);
3983 unlock_user_struct(target_rlim, arg2, 1);
bellard9de5e442003-03-23 16:49:39 +00003984 }
3985 }
3986 break;
bellard31e31b82003-02-18 22:55:36 +00003987 case TARGET_NR_getrusage:
bellardb4091862003-05-16 15:39:34 +00003988 {
3989 struct rusage rusage;
bellardb4091862003-05-16 15:39:34 +00003990 ret = get_errno(getrusage(arg1, &rusage));
3991 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00003992 host_to_target_rusage(arg2, &rusage);
bellardb4091862003-05-16 15:39:34 +00003993 }
3994 }
3995 break;
bellard31e31b82003-02-18 22:55:36 +00003996 case TARGET_NR_gettimeofday:
3997 {
bellard31e31b82003-02-18 22:55:36 +00003998 struct timeval tv;
3999 ret = get_errno(gettimeofday(&tv, NULL));
4000 if (!is_error(ret)) {
ths788f5ec2007-12-09 02:37:05 +00004001 if (copy_to_user_timeval(arg1, &tv))
4002 goto efault;
bellard31e31b82003-02-18 22:55:36 +00004003 }
4004 }
4005 break;
4006 case TARGET_NR_settimeofday:
4007 {
bellard31e31b82003-02-18 22:55:36 +00004008 struct timeval tv;
ths788f5ec2007-12-09 02:37:05 +00004009 if (copy_from_user_timeval(&tv, arg1))
4010 goto efault;
bellard31e31b82003-02-18 22:55:36 +00004011 ret = get_errno(settimeofday(&tv, NULL));
4012 }
4013 break;
bellard048f6b42005-11-26 18:47:20 +00004014#ifdef TARGET_NR_select
bellard31e31b82003-02-18 22:55:36 +00004015 case TARGET_NR_select:
bellardf2674e32003-07-09 12:26:09 +00004016 {
pbrook53a59602006-03-25 19:31:22 +00004017 struct target_sel_arg_struct *sel;
blueswir1992f48a2007-10-14 16:27:31 +00004018 abi_ulong inp, outp, exp, tvp;
pbrook53a59602006-03-25 19:31:22 +00004019 long nsel;
4020
bellard579a97f2007-11-11 14:26:47 +00004021 if (!lock_user_struct(VERIFY_READ, sel, arg1, 1))
4022 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004023 nsel = tswapl(sel->n);
4024 inp = tswapl(sel->inp);
4025 outp = tswapl(sel->outp);
4026 exp = tswapl(sel->exp);
4027 tvp = tswapl(sel->tvp);
4028 unlock_user_struct(sel, arg1, 0);
4029 ret = do_select(nsel, inp, outp, exp, tvp);
bellardf2674e32003-07-09 12:26:09 +00004030 }
4031 break;
bellard048f6b42005-11-26 18:47:20 +00004032#endif
bellard31e31b82003-02-18 22:55:36 +00004033 case TARGET_NR_symlink:
pbrook53a59602006-03-25 19:31:22 +00004034 {
4035 void *p2;
4036 p = lock_user_string(arg1);
4037 p2 = lock_user_string(arg2);
bellard579a97f2007-11-11 14:26:47 +00004038 if (!p || !p2)
4039 ret = -TARGET_EFAULT;
4040 else
4041 ret = get_errno(symlink(p, p2));
pbrook53a59602006-03-25 19:31:22 +00004042 unlock_user(p2, arg2, 0);
4043 unlock_user(p, arg1, 0);
4044 }
bellard31e31b82003-02-18 22:55:36 +00004045 break;
thsf0b62432007-09-24 09:25:40 +00004046#if defined(TARGET_NR_symlinkat) && defined(__NR_symlinkat)
4047 case TARGET_NR_symlinkat:
thsf0b62432007-09-24 09:25:40 +00004048 {
bellard579a97f2007-11-11 14:26:47 +00004049 void *p2;
thsf0b62432007-09-24 09:25:40 +00004050 p = lock_user_string(arg1);
4051 p2 = lock_user_string(arg3);
bellard579a97f2007-11-11 14:26:47 +00004052 if (!p || !p2)
ths0da46a62007-10-20 20:23:07 +00004053 ret = -TARGET_EFAULT;
thsf0b62432007-09-24 09:25:40 +00004054 else
4055 ret = get_errno(sys_symlinkat(p, arg2, p2));
bellard579a97f2007-11-11 14:26:47 +00004056 unlock_user(p2, arg3, 0);
4057 unlock_user(p, arg1, 0);
thsf0b62432007-09-24 09:25:40 +00004058 }
4059 break;
4060#endif
bellardebc05482003-09-30 21:08:41 +00004061#ifdef TARGET_NR_oldlstat
bellard31e31b82003-02-18 22:55:36 +00004062 case TARGET_NR_oldlstat:
4063 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004064#endif
bellard31e31b82003-02-18 22:55:36 +00004065 case TARGET_NR_readlink:
pbrook53a59602006-03-25 19:31:22 +00004066 {
4067 void *p2;
4068 p = lock_user_string(arg1);
bellard579a97f2007-11-11 14:26:47 +00004069 p2 = lock_user(VERIFY_WRITE, arg2, arg3, 0);
4070 if (!p || !p2)
4071 ret = -TARGET_EFAULT;
4072 else
4073 ret = get_errno(readlink(path(p), p2, arg3));
pbrook53a59602006-03-25 19:31:22 +00004074 unlock_user(p2, arg2, ret);
4075 unlock_user(p, arg1, 0);
4076 }
bellard31e31b82003-02-18 22:55:36 +00004077 break;
ths5e0ccb12007-09-24 09:26:10 +00004078#if defined(TARGET_NR_readlinkat) && defined(__NR_readlinkat)
4079 case TARGET_NR_readlinkat:
ths5e0ccb12007-09-24 09:26:10 +00004080 {
bellard579a97f2007-11-11 14:26:47 +00004081 void *p2;
ths5e0ccb12007-09-24 09:26:10 +00004082 p = lock_user_string(arg2);
bellard579a97f2007-11-11 14:26:47 +00004083 p2 = lock_user(VERIFY_WRITE, arg3, arg4, 0);
4084 if (!p || !p2)
ths0da46a62007-10-20 20:23:07 +00004085 ret = -TARGET_EFAULT;
ths5e0ccb12007-09-24 09:26:10 +00004086 else
4087 ret = get_errno(sys_readlinkat(arg1, path(p), p2, arg4));
bellard579a97f2007-11-11 14:26:47 +00004088 unlock_user(p2, arg3, ret);
4089 unlock_user(p, arg2, 0);
ths5e0ccb12007-09-24 09:26:10 +00004090 }
4091 break;
4092#endif
thse5febef2007-04-01 18:31:35 +00004093#ifdef TARGET_NR_uselib
bellard31e31b82003-02-18 22:55:36 +00004094 case TARGET_NR_uselib:
4095 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00004096#endif
4097#ifdef TARGET_NR_swapon
bellard31e31b82003-02-18 22:55:36 +00004098 case TARGET_NR_swapon:
bellard579a97f2007-11-11 14:26:47 +00004099 if (!(p = lock_user_string(arg1)))
4100 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004101 ret = get_errno(swapon(p, arg2));
4102 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004103 break;
thse5febef2007-04-01 18:31:35 +00004104#endif
bellard31e31b82003-02-18 22:55:36 +00004105 case TARGET_NR_reboot:
4106 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00004107#ifdef TARGET_NR_readdir
bellard31e31b82003-02-18 22:55:36 +00004108 case TARGET_NR_readdir:
4109 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00004110#endif
4111#ifdef TARGET_NR_mmap
bellard31e31b82003-02-18 22:55:36 +00004112 case TARGET_NR_mmap:
bellardd2fd1af2007-11-14 18:08:56 +00004113#if (defined(TARGET_I386) && defined(TARGET_ABI32)) || defined(TARGET_ARM) || defined(TARGET_M68K) || defined(TARGET_CRIS)
bellard31e31b82003-02-18 22:55:36 +00004114 {
blueswir1992f48a2007-10-14 16:27:31 +00004115 abi_ulong *v;
4116 abi_ulong v1, v2, v3, v4, v5, v6;
bellard579a97f2007-11-11 14:26:47 +00004117 if (!(v = lock_user(VERIFY_READ, arg1, 6 * sizeof(abi_ulong), 1)))
4118 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004119 v1 = tswapl(v[0]);
4120 v2 = tswapl(v[1]);
4121 v3 = tswapl(v[2]);
4122 v4 = tswapl(v[3]);
4123 v5 = tswapl(v[4]);
4124 v6 = tswapl(v[5]);
4125 unlock_user(v, arg1, 0);
ths5fafdf22007-09-16 21:08:06 +00004126 ret = get_errno(target_mmap(v1, v2, v3,
bellard5286db72003-06-05 00:57:30 +00004127 target_to_host_bitmask(v4, mmap_flags_tbl),
4128 v5, v6));
bellard31e31b82003-02-18 22:55:36 +00004129 }
bellard31e31b82003-02-18 22:55:36 +00004130#else
ths5fafdf22007-09-16 21:08:06 +00004131 ret = get_errno(target_mmap(arg1, arg2, arg3,
4132 target_to_host_bitmask(arg4, mmap_flags_tbl),
bellard6fb883e2003-07-09 17:12:39 +00004133 arg5,
4134 arg6));
bellard31e31b82003-02-18 22:55:36 +00004135#endif
bellard6fb883e2003-07-09 17:12:39 +00004136 break;
thse5febef2007-04-01 18:31:35 +00004137#endif
bellarda315a142005-01-30 22:59:18 +00004138#ifdef TARGET_NR_mmap2
bellard6fb883e2003-07-09 17:12:39 +00004139 case TARGET_NR_mmap2:
pbrookbb7ec042008-03-25 22:28:25 +00004140#ifndef MMAP_SHIFT
bellardc573ff62004-01-04 15:51:36 +00004141#define MMAP_SHIFT 12
bellardc573ff62004-01-04 15:51:36 +00004142#endif
ths5fafdf22007-09-16 21:08:06 +00004143 ret = get_errno(target_mmap(arg1, arg2, arg3,
4144 target_to_host_bitmask(arg4, mmap_flags_tbl),
bellard5286db72003-06-05 00:57:30 +00004145 arg5,
bellardc573ff62004-01-04 15:51:36 +00004146 arg6 << MMAP_SHIFT));
bellard31e31b82003-02-18 22:55:36 +00004147 break;
bellarda315a142005-01-30 22:59:18 +00004148#endif
bellard31e31b82003-02-18 22:55:36 +00004149 case TARGET_NR_munmap:
bellard54936002003-05-13 00:25:15 +00004150 ret = get_errno(target_munmap(arg1, arg2));
bellard31e31b82003-02-18 22:55:36 +00004151 break;
bellard9de5e442003-03-23 16:49:39 +00004152 case TARGET_NR_mprotect:
bellard54936002003-05-13 00:25:15 +00004153 ret = get_errno(target_mprotect(arg1, arg2, arg3));
bellard9de5e442003-03-23 16:49:39 +00004154 break;
thse5febef2007-04-01 18:31:35 +00004155#ifdef TARGET_NR_mremap
bellard9de5e442003-03-23 16:49:39 +00004156 case TARGET_NR_mremap:
bellard54936002003-05-13 00:25:15 +00004157 ret = get_errno(target_mremap(arg1, arg2, arg3, arg4, arg5));
bellard9de5e442003-03-23 16:49:39 +00004158 break;
thse5febef2007-04-01 18:31:35 +00004159#endif
pbrook53a59602006-03-25 19:31:22 +00004160 /* ??? msync/mlock/munlock are broken for softmmu. */
thse5febef2007-04-01 18:31:35 +00004161#ifdef TARGET_NR_msync
bellard9de5e442003-03-23 16:49:39 +00004162 case TARGET_NR_msync:
pbrook53a59602006-03-25 19:31:22 +00004163 ret = get_errno(msync(g2h(arg1), arg2, arg3));
bellard9de5e442003-03-23 16:49:39 +00004164 break;
thse5febef2007-04-01 18:31:35 +00004165#endif
4166#ifdef TARGET_NR_mlock
bellard9de5e442003-03-23 16:49:39 +00004167 case TARGET_NR_mlock:
pbrook53a59602006-03-25 19:31:22 +00004168 ret = get_errno(mlock(g2h(arg1), arg2));
bellard9de5e442003-03-23 16:49:39 +00004169 break;
thse5febef2007-04-01 18:31:35 +00004170#endif
4171#ifdef TARGET_NR_munlock
bellard9de5e442003-03-23 16:49:39 +00004172 case TARGET_NR_munlock:
pbrook53a59602006-03-25 19:31:22 +00004173 ret = get_errno(munlock(g2h(arg1), arg2));
bellard9de5e442003-03-23 16:49:39 +00004174 break;
thse5febef2007-04-01 18:31:35 +00004175#endif
4176#ifdef TARGET_NR_mlockall
bellard9de5e442003-03-23 16:49:39 +00004177 case TARGET_NR_mlockall:
4178 ret = get_errno(mlockall(arg1));
4179 break;
thse5febef2007-04-01 18:31:35 +00004180#endif
4181#ifdef TARGET_NR_munlockall
bellard9de5e442003-03-23 16:49:39 +00004182 case TARGET_NR_munlockall:
4183 ret = get_errno(munlockall());
4184 break;
thse5febef2007-04-01 18:31:35 +00004185#endif
bellard31e31b82003-02-18 22:55:36 +00004186 case TARGET_NR_truncate:
bellard579a97f2007-11-11 14:26:47 +00004187 if (!(p = lock_user_string(arg1)))
4188 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004189 ret = get_errno(truncate(p, arg2));
4190 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004191 break;
4192 case TARGET_NR_ftruncate:
4193 ret = get_errno(ftruncate(arg1, arg2));
4194 break;
4195 case TARGET_NR_fchmod:
4196 ret = get_errno(fchmod(arg1, arg2));
4197 break;
ths814d7972007-09-24 09:26:51 +00004198#if defined(TARGET_NR_fchmodat) && defined(__NR_fchmodat)
4199 case TARGET_NR_fchmodat:
bellard579a97f2007-11-11 14:26:47 +00004200 if (!(p = lock_user_string(arg2)))
4201 goto efault;
4202 ret = get_errno(sys_fchmodat(arg1, p, arg3, arg4));
4203 unlock_user(p, arg2, 0);
ths814d7972007-09-24 09:26:51 +00004204 break;
4205#endif
bellard31e31b82003-02-18 22:55:36 +00004206 case TARGET_NR_getpriority:
thsc6cda172007-10-09 03:42:34 +00004207 /* libc does special remapping of the return value of
4208 * sys_getpriority() so it's just easiest to call
4209 * sys_getpriority() directly rather than through libc. */
4210 ret = sys_getpriority(arg1, arg2);
bellard31e31b82003-02-18 22:55:36 +00004211 break;
4212 case TARGET_NR_setpriority:
4213 ret = get_errno(setpriority(arg1, arg2, arg3));
4214 break;
bellardebc05482003-09-30 21:08:41 +00004215#ifdef TARGET_NR_profil
bellard31e31b82003-02-18 22:55:36 +00004216 case TARGET_NR_profil:
4217 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004218#endif
bellard31e31b82003-02-18 22:55:36 +00004219 case TARGET_NR_statfs:
bellard579a97f2007-11-11 14:26:47 +00004220 if (!(p = lock_user_string(arg1)))
4221 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004222 ret = get_errno(statfs(path(p), &stfs));
4223 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004224 convert_statfs:
4225 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00004226 struct target_statfs *target_stfs;
ths3b46e622007-09-17 08:09:54 +00004227
bellard579a97f2007-11-11 14:26:47 +00004228 if (!lock_user_struct(VERIFY_WRITE, target_stfs, arg2, 0))
4229 goto efault;
4230 __put_user(stfs.f_type, &target_stfs->f_type);
4231 __put_user(stfs.f_bsize, &target_stfs->f_bsize);
4232 __put_user(stfs.f_blocks, &target_stfs->f_blocks);
4233 __put_user(stfs.f_bfree, &target_stfs->f_bfree);
4234 __put_user(stfs.f_bavail, &target_stfs->f_bavail);
4235 __put_user(stfs.f_files, &target_stfs->f_files);
4236 __put_user(stfs.f_ffree, &target_stfs->f_ffree);
4237 __put_user(stfs.f_fsid.__val[0], &target_stfs->f_fsid.val[0]);
4238 __put_user(stfs.f_fsid.__val[1], &target_stfs->f_fsid.val[1]);
4239 __put_user(stfs.f_namelen, &target_stfs->f_namelen);
pbrook53a59602006-03-25 19:31:22 +00004240 unlock_user_struct(target_stfs, arg2, 1);
bellard31e31b82003-02-18 22:55:36 +00004241 }
4242 break;
4243 case TARGET_NR_fstatfs:
bellard56c8f682005-11-28 22:28:41 +00004244 ret = get_errno(fstatfs(arg1, &stfs));
bellard31e31b82003-02-18 22:55:36 +00004245 goto convert_statfs;
bellard56c8f682005-11-28 22:28:41 +00004246#ifdef TARGET_NR_statfs64
4247 case TARGET_NR_statfs64:
bellard579a97f2007-11-11 14:26:47 +00004248 if (!(p = lock_user_string(arg1)))
4249 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004250 ret = get_errno(statfs(path(p), &stfs));
4251 unlock_user(p, arg1, 0);
bellard56c8f682005-11-28 22:28:41 +00004252 convert_statfs64:
4253 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00004254 struct target_statfs64 *target_stfs;
ths3b46e622007-09-17 08:09:54 +00004255
bellard579a97f2007-11-11 14:26:47 +00004256 if (!lock_user_struct(VERIFY_WRITE, target_stfs, arg3, 0))
4257 goto efault;
4258 __put_user(stfs.f_type, &target_stfs->f_type);
4259 __put_user(stfs.f_bsize, &target_stfs->f_bsize);
4260 __put_user(stfs.f_blocks, &target_stfs->f_blocks);
4261 __put_user(stfs.f_bfree, &target_stfs->f_bfree);
4262 __put_user(stfs.f_bavail, &target_stfs->f_bavail);
4263 __put_user(stfs.f_files, &target_stfs->f_files);
4264 __put_user(stfs.f_ffree, &target_stfs->f_ffree);
4265 __put_user(stfs.f_fsid.__val[0], &target_stfs->f_fsid.val[0]);
4266 __put_user(stfs.f_fsid.__val[1], &target_stfs->f_fsid.val[1]);
4267 __put_user(stfs.f_namelen, &target_stfs->f_namelen);
4268 unlock_user_struct(target_stfs, arg3, 1);
bellard56c8f682005-11-28 22:28:41 +00004269 }
4270 break;
4271 case TARGET_NR_fstatfs64:
4272 ret = get_errno(fstatfs(arg1, &stfs));
4273 goto convert_statfs64;
4274#endif
bellardebc05482003-09-30 21:08:41 +00004275#ifdef TARGET_NR_ioperm
bellard31e31b82003-02-18 22:55:36 +00004276 case TARGET_NR_ioperm:
4277 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004278#endif
thse5febef2007-04-01 18:31:35 +00004279#ifdef TARGET_NR_socketcall
bellard31e31b82003-02-18 22:55:36 +00004280 case TARGET_NR_socketcall:
pbrook53a59602006-03-25 19:31:22 +00004281 ret = do_socketcall(arg1, arg2);
bellard31e31b82003-02-18 22:55:36 +00004282 break;
thse5febef2007-04-01 18:31:35 +00004283#endif
bellard3532fa72006-06-24 15:06:03 +00004284#ifdef TARGET_NR_accept
4285 case TARGET_NR_accept:
pbrook1be9e1d2006-11-19 15:26:04 +00004286 ret = do_accept(arg1, arg2, arg3);
bellard3532fa72006-06-24 15:06:03 +00004287 break;
4288#endif
4289#ifdef TARGET_NR_bind
4290 case TARGET_NR_bind:
4291 ret = do_bind(arg1, arg2, arg3);
4292 break;
4293#endif
4294#ifdef TARGET_NR_connect
4295 case TARGET_NR_connect:
4296 ret = do_connect(arg1, arg2, arg3);
4297 break;
4298#endif
4299#ifdef TARGET_NR_getpeername
4300 case TARGET_NR_getpeername:
pbrook1be9e1d2006-11-19 15:26:04 +00004301 ret = do_getpeername(arg1, arg2, arg3);
bellard3532fa72006-06-24 15:06:03 +00004302 break;
4303#endif
4304#ifdef TARGET_NR_getsockname
4305 case TARGET_NR_getsockname:
pbrook1be9e1d2006-11-19 15:26:04 +00004306 ret = do_getsockname(arg1, arg2, arg3);
bellard3532fa72006-06-24 15:06:03 +00004307 break;
4308#endif
4309#ifdef TARGET_NR_getsockopt
4310 case TARGET_NR_getsockopt:
4311 ret = do_getsockopt(arg1, arg2, arg3, arg4, arg5);
4312 break;
4313#endif
4314#ifdef TARGET_NR_listen
4315 case TARGET_NR_listen:
pbrook1be9e1d2006-11-19 15:26:04 +00004316 ret = get_errno(listen(arg1, arg2));
bellard3532fa72006-06-24 15:06:03 +00004317 break;
4318#endif
4319#ifdef TARGET_NR_recv
4320 case TARGET_NR_recv:
pbrook214201b2007-03-17 01:27:24 +00004321 ret = do_recvfrom(arg1, arg2, arg3, arg4, 0, 0);
bellard3532fa72006-06-24 15:06:03 +00004322 break;
4323#endif
4324#ifdef TARGET_NR_recvfrom
4325 case TARGET_NR_recvfrom:
pbrook214201b2007-03-17 01:27:24 +00004326 ret = do_recvfrom(arg1, arg2, arg3, arg4, arg5, arg6);
bellard3532fa72006-06-24 15:06:03 +00004327 break;
4328#endif
4329#ifdef TARGET_NR_recvmsg
4330 case TARGET_NR_recvmsg:
4331 ret = do_sendrecvmsg(arg1, arg2, arg3, 0);
4332 break;
4333#endif
4334#ifdef TARGET_NR_send
4335 case TARGET_NR_send:
pbrook1be9e1d2006-11-19 15:26:04 +00004336 ret = do_sendto(arg1, arg2, arg3, arg4, 0, 0);
bellard3532fa72006-06-24 15:06:03 +00004337 break;
4338#endif
4339#ifdef TARGET_NR_sendmsg
4340 case TARGET_NR_sendmsg:
4341 ret = do_sendrecvmsg(arg1, arg2, arg3, 1);
4342 break;
4343#endif
4344#ifdef TARGET_NR_sendto
4345 case TARGET_NR_sendto:
pbrook1be9e1d2006-11-19 15:26:04 +00004346 ret = do_sendto(arg1, arg2, arg3, arg4, arg5, arg6);
bellard3532fa72006-06-24 15:06:03 +00004347 break;
4348#endif
4349#ifdef TARGET_NR_shutdown
4350 case TARGET_NR_shutdown:
pbrook1be9e1d2006-11-19 15:26:04 +00004351 ret = get_errno(shutdown(arg1, arg2));
bellard3532fa72006-06-24 15:06:03 +00004352 break;
4353#endif
4354#ifdef TARGET_NR_socket
4355 case TARGET_NR_socket:
4356 ret = do_socket(arg1, arg2, arg3);
4357 break;
4358#endif
4359#ifdef TARGET_NR_socketpair
4360 case TARGET_NR_socketpair:
pbrook1be9e1d2006-11-19 15:26:04 +00004361 ret = do_socketpair(arg1, arg2, arg3, arg4);
bellard3532fa72006-06-24 15:06:03 +00004362 break;
4363#endif
4364#ifdef TARGET_NR_setsockopt
4365 case TARGET_NR_setsockopt:
4366 ret = do_setsockopt(arg1, arg2, arg3, arg4, (socklen_t) arg5);
4367 break;
4368#endif
ths7494b0f2007-02-11 18:26:53 +00004369
bellard31e31b82003-02-18 22:55:36 +00004370 case TARGET_NR_syslog:
bellard579a97f2007-11-11 14:26:47 +00004371 if (!(p = lock_user_string(arg2)))
4372 goto efault;
thse5574482007-02-11 20:03:13 +00004373 ret = get_errno(sys_syslog((int)arg1, p, (int)arg3));
4374 unlock_user(p, arg2, 0);
ths7494b0f2007-02-11 18:26:53 +00004375 break;
4376
bellard31e31b82003-02-18 22:55:36 +00004377 case TARGET_NR_setitimer:
bellard66fb9762003-03-23 01:06:05 +00004378 {
bellard66fb9762003-03-23 01:06:05 +00004379 struct itimerval value, ovalue, *pvalue;
4380
pbrook53a59602006-03-25 19:31:22 +00004381 if (arg2) {
bellard66fb9762003-03-23 01:06:05 +00004382 pvalue = &value;
ths788f5ec2007-12-09 02:37:05 +00004383 if (copy_from_user_timeval(&pvalue->it_interval, arg2)
4384 || copy_from_user_timeval(&pvalue->it_value,
4385 arg2 + sizeof(struct target_timeval)))
4386 goto efault;
bellard66fb9762003-03-23 01:06:05 +00004387 } else {
4388 pvalue = NULL;
4389 }
4390 ret = get_errno(setitimer(arg1, pvalue, &ovalue));
pbrook53a59602006-03-25 19:31:22 +00004391 if (!is_error(ret) && arg3) {
ths788f5ec2007-12-09 02:37:05 +00004392 if (copy_to_user_timeval(arg3,
4393 &ovalue.it_interval)
4394 || copy_to_user_timeval(arg3 + sizeof(struct target_timeval),
4395 &ovalue.it_value))
4396 goto efault;
bellard66fb9762003-03-23 01:06:05 +00004397 }
4398 }
4399 break;
bellard31e31b82003-02-18 22:55:36 +00004400 case TARGET_NR_getitimer:
bellard66fb9762003-03-23 01:06:05 +00004401 {
bellard66fb9762003-03-23 01:06:05 +00004402 struct itimerval value;
ths3b46e622007-09-17 08:09:54 +00004403
bellard66fb9762003-03-23 01:06:05 +00004404 ret = get_errno(getitimer(arg1, &value));
pbrook53a59602006-03-25 19:31:22 +00004405 if (!is_error(ret) && arg2) {
ths788f5ec2007-12-09 02:37:05 +00004406 if (copy_to_user_timeval(arg2,
4407 &value.it_interval)
4408 || copy_to_user_timeval(arg2 + sizeof(struct target_timeval),
4409 &value.it_value))
4410 goto efault;
bellard66fb9762003-03-23 01:06:05 +00004411 }
4412 }
4413 break;
bellard31e31b82003-02-18 22:55:36 +00004414 case TARGET_NR_stat:
bellard579a97f2007-11-11 14:26:47 +00004415 if (!(p = lock_user_string(arg1)))
4416 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004417 ret = get_errno(stat(path(p), &st));
4418 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004419 goto do_stat;
4420 case TARGET_NR_lstat:
bellard579a97f2007-11-11 14:26:47 +00004421 if (!(p = lock_user_string(arg1)))
4422 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004423 ret = get_errno(lstat(path(p), &st));
4424 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004425 goto do_stat;
4426 case TARGET_NR_fstat:
4427 {
4428 ret = get_errno(fstat(arg1, &st));
4429 do_stat:
4430 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00004431 struct target_stat *target_st;
thse3584652007-06-01 11:49:38 +00004432
bellard579a97f2007-11-11 14:26:47 +00004433 if (!lock_user_struct(VERIFY_WRITE, target_st, arg2, 0))
4434 goto efault;
bellardd2fd1af2007-11-14 18:08:56 +00004435 __put_user(st.st_dev, &target_st->st_dev);
4436 __put_user(st.st_ino, &target_st->st_ino);
4437 __put_user(st.st_mode, &target_st->st_mode);
4438 __put_user(st.st_uid, &target_st->st_uid);
4439 __put_user(st.st_gid, &target_st->st_gid);
4440 __put_user(st.st_nlink, &target_st->st_nlink);
4441 __put_user(st.st_rdev, &target_st->st_rdev);
4442 __put_user(st.st_size, &target_st->st_size);
4443 __put_user(st.st_blksize, &target_st->st_blksize);
4444 __put_user(st.st_blocks, &target_st->st_blocks);
4445 __put_user(st.st_atime, &target_st->target_st_atime);
4446 __put_user(st.st_mtime, &target_st->target_st_mtime);
4447 __put_user(st.st_ctime, &target_st->target_st_ctime);
pbrook53a59602006-03-25 19:31:22 +00004448 unlock_user_struct(target_st, arg2, 1);
bellard31e31b82003-02-18 22:55:36 +00004449 }
4450 }
4451 break;
bellardebc05482003-09-30 21:08:41 +00004452#ifdef TARGET_NR_olduname
bellard31e31b82003-02-18 22:55:36 +00004453 case TARGET_NR_olduname:
4454 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004455#endif
4456#ifdef TARGET_NR_iopl
bellard31e31b82003-02-18 22:55:36 +00004457 case TARGET_NR_iopl:
4458 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004459#endif
bellard31e31b82003-02-18 22:55:36 +00004460 case TARGET_NR_vhangup:
4461 ret = get_errno(vhangup());
4462 break;
bellardebc05482003-09-30 21:08:41 +00004463#ifdef TARGET_NR_idle
bellard31e31b82003-02-18 22:55:36 +00004464 case TARGET_NR_idle:
4465 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004466#endif
bellard42ad6ae2005-01-03 22:48:11 +00004467#ifdef TARGET_NR_syscall
4468 case TARGET_NR_syscall:
4469 ret = do_syscall(cpu_env,arg1 & 0xffff,arg2,arg3,arg4,arg5,arg6,0);
4470 break;
4471#endif
bellard31e31b82003-02-18 22:55:36 +00004472 case TARGET_NR_wait4:
4473 {
4474 int status;
blueswir1992f48a2007-10-14 16:27:31 +00004475 abi_long status_ptr = arg2;
bellard31e31b82003-02-18 22:55:36 +00004476 struct rusage rusage, *rusage_ptr;
blueswir1992f48a2007-10-14 16:27:31 +00004477 abi_ulong target_rusage = arg4;
bellard31e31b82003-02-18 22:55:36 +00004478 if (target_rusage)
4479 rusage_ptr = &rusage;
4480 else
4481 rusage_ptr = NULL;
4482 ret = get_errno(wait4(arg1, &status, arg3, rusage_ptr));
4483 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +00004484 if (status_ptr) {
4485 if (put_user_s32(status, status_ptr))
4486 goto efault;
bellard31e31b82003-02-18 22:55:36 +00004487 }
bellard2f619692007-11-16 10:46:05 +00004488 if (target_rusage)
4489 host_to_target_rusage(target_rusage, &rusage);
bellard31e31b82003-02-18 22:55:36 +00004490 }
4491 }
4492 break;
thse5febef2007-04-01 18:31:35 +00004493#ifdef TARGET_NR_swapoff
bellard31e31b82003-02-18 22:55:36 +00004494 case TARGET_NR_swapoff:
bellard579a97f2007-11-11 14:26:47 +00004495 if (!(p = lock_user_string(arg1)))
4496 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004497 ret = get_errno(swapoff(p));
4498 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004499 break;
thse5febef2007-04-01 18:31:35 +00004500#endif
bellard31e31b82003-02-18 22:55:36 +00004501 case TARGET_NR_sysinfo:
bellarda5448a72004-06-19 16:59:03 +00004502 {
pbrook53a59602006-03-25 19:31:22 +00004503 struct target_sysinfo *target_value;
bellarda5448a72004-06-19 16:59:03 +00004504 struct sysinfo value;
4505 ret = get_errno(sysinfo(&value));
pbrook53a59602006-03-25 19:31:22 +00004506 if (!is_error(ret) && arg1)
bellarda5448a72004-06-19 16:59:03 +00004507 {
bellard579a97f2007-11-11 14:26:47 +00004508 if (!lock_user_struct(VERIFY_WRITE, target_value, arg1, 0))
4509 goto efault;
bellarda5448a72004-06-19 16:59:03 +00004510 __put_user(value.uptime, &target_value->uptime);
4511 __put_user(value.loads[0], &target_value->loads[0]);
4512 __put_user(value.loads[1], &target_value->loads[1]);
4513 __put_user(value.loads[2], &target_value->loads[2]);
4514 __put_user(value.totalram, &target_value->totalram);
4515 __put_user(value.freeram, &target_value->freeram);
4516 __put_user(value.sharedram, &target_value->sharedram);
4517 __put_user(value.bufferram, &target_value->bufferram);
4518 __put_user(value.totalswap, &target_value->totalswap);
4519 __put_user(value.freeswap, &target_value->freeswap);
4520 __put_user(value.procs, &target_value->procs);
4521 __put_user(value.totalhigh, &target_value->totalhigh);
4522 __put_user(value.freehigh, &target_value->freehigh);
4523 __put_user(value.mem_unit, &target_value->mem_unit);
pbrook53a59602006-03-25 19:31:22 +00004524 unlock_user_struct(target_value, arg1, 1);
bellarda5448a72004-06-19 16:59:03 +00004525 }
4526 }
4527 break;
thse5febef2007-04-01 18:31:35 +00004528#ifdef TARGET_NR_ipc
bellard31e31b82003-02-18 22:55:36 +00004529 case TARGET_NR_ipc:
bellard8853f862004-02-22 14:57:26 +00004530 ret = do_ipc(arg1, arg2, arg3, arg4, arg5, arg6);
4531 break;
thse5febef2007-04-01 18:31:35 +00004532#endif
bellard31e31b82003-02-18 22:55:36 +00004533 case TARGET_NR_fsync:
4534 ret = get_errno(fsync(arg1));
4535 break;
bellard31e31b82003-02-18 22:55:36 +00004536 case TARGET_NR_clone:
bellard1b6b0292003-03-22 17:31:38 +00004537 ret = get_errno(do_fork(cpu_env, arg1, arg2));
4538 break;
bellardec86b0f2003-04-11 00:15:04 +00004539#ifdef __NR_exit_group
4540 /* new thread calls */
4541 case TARGET_NR_exit_group:
bellarde9009672005-04-26 20:42:36 +00004542 gdb_exit(cpu_env, arg1);
bellardec86b0f2003-04-11 00:15:04 +00004543 ret = get_errno(exit_group(arg1));
4544 break;
4545#endif
bellard31e31b82003-02-18 22:55:36 +00004546 case TARGET_NR_setdomainname:
bellard579a97f2007-11-11 14:26:47 +00004547 if (!(p = lock_user_string(arg1)))
4548 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004549 ret = get_errno(setdomainname(p, arg2));
4550 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004551 break;
4552 case TARGET_NR_uname:
4553 /* no need to transcode because we use the linux syscall */
bellard29e619b2004-09-13 21:41:04 +00004554 {
4555 struct new_utsname * buf;
ths3b46e622007-09-17 08:09:54 +00004556
bellard579a97f2007-11-11 14:26:47 +00004557 if (!lock_user_struct(VERIFY_WRITE, buf, arg1, 0))
4558 goto efault;
bellard29e619b2004-09-13 21:41:04 +00004559 ret = get_errno(sys_uname(buf));
4560 if (!is_error(ret)) {
4561 /* Overrite the native machine name with whatever is being
4562 emulated. */
4563 strcpy (buf->machine, UNAME_MACHINE);
pbrookc5937222006-05-14 11:30:38 +00004564 /* Allow the user to override the reported release. */
4565 if (qemu_uname_release && *qemu_uname_release)
4566 strcpy (buf->release, qemu_uname_release);
bellard29e619b2004-09-13 21:41:04 +00004567 }
pbrook53a59602006-03-25 19:31:22 +00004568 unlock_user_struct(buf, arg1, 1);
bellard29e619b2004-09-13 21:41:04 +00004569 }
bellard31e31b82003-02-18 22:55:36 +00004570 break;
bellard6dbad632003-03-16 18:05:05 +00004571#ifdef TARGET_I386
bellard31e31b82003-02-18 22:55:36 +00004572 case TARGET_NR_modify_ldt:
bellard03acab62007-11-11 14:57:14 +00004573 ret = do_modify_ldt(cpu_env, arg1, arg2, arg3);
bellard5cd43932003-03-29 16:54:36 +00004574 break;
j_mayer84409dd2007-04-06 08:56:50 +00004575#if !defined(TARGET_X86_64)
bellard5cd43932003-03-29 16:54:36 +00004576 case TARGET_NR_vm86old:
4577 goto unimplemented;
4578 case TARGET_NR_vm86:
pbrook53a59602006-03-25 19:31:22 +00004579 ret = do_vm86(cpu_env, arg1, arg2);
bellard6dbad632003-03-16 18:05:05 +00004580 break;
4581#endif
j_mayer84409dd2007-04-06 08:56:50 +00004582#endif
bellard31e31b82003-02-18 22:55:36 +00004583 case TARGET_NR_adjtimex:
4584 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00004585#ifdef TARGET_NR_create_module
bellard31e31b82003-02-18 22:55:36 +00004586 case TARGET_NR_create_module:
thse5febef2007-04-01 18:31:35 +00004587#endif
bellard31e31b82003-02-18 22:55:36 +00004588 case TARGET_NR_init_module:
4589 case TARGET_NR_delete_module:
thse5febef2007-04-01 18:31:35 +00004590#ifdef TARGET_NR_get_kernel_syms
bellard31e31b82003-02-18 22:55:36 +00004591 case TARGET_NR_get_kernel_syms:
thse5febef2007-04-01 18:31:35 +00004592#endif
bellard31e31b82003-02-18 22:55:36 +00004593 goto unimplemented;
4594 case TARGET_NR_quotactl:
4595 goto unimplemented;
4596 case TARGET_NR_getpgid:
4597 ret = get_errno(getpgid(arg1));
4598 break;
4599 case TARGET_NR_fchdir:
4600 ret = get_errno(fchdir(arg1));
4601 break;
j_mayer84409dd2007-04-06 08:56:50 +00004602#ifdef TARGET_NR_bdflush /* not on x86_64 */
bellard31e31b82003-02-18 22:55:36 +00004603 case TARGET_NR_bdflush:
4604 goto unimplemented;
j_mayer84409dd2007-04-06 08:56:50 +00004605#endif
thse5febef2007-04-01 18:31:35 +00004606#ifdef TARGET_NR_sysfs
bellard31e31b82003-02-18 22:55:36 +00004607 case TARGET_NR_sysfs:
4608 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00004609#endif
bellard31e31b82003-02-18 22:55:36 +00004610 case TARGET_NR_personality:
bellard1b6b0292003-03-22 17:31:38 +00004611 ret = get_errno(personality(arg1));
bellard31e31b82003-02-18 22:55:36 +00004612 break;
thse5febef2007-04-01 18:31:35 +00004613#ifdef TARGET_NR_afs_syscall
bellard31e31b82003-02-18 22:55:36 +00004614 case TARGET_NR_afs_syscall:
4615 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00004616#endif
j_mayer7a3148a2007-04-05 07:13:51 +00004617#ifdef TARGET_NR__llseek /* Not on alpha */
bellard31e31b82003-02-18 22:55:36 +00004618 case TARGET_NR__llseek:
4619 {
bellard4f2ac232004-04-26 19:44:02 +00004620#if defined (__x86_64__)
4621 ret = get_errno(lseek(arg1, ((uint64_t )arg2 << 32) | arg3, arg5));
bellard2f619692007-11-16 10:46:05 +00004622 if (put_user_s64(ret, arg4))
4623 goto efault;
bellard4f2ac232004-04-26 19:44:02 +00004624#else
bellard31e31b82003-02-18 22:55:36 +00004625 int64_t res;
4626 ret = get_errno(_llseek(arg1, arg2, arg3, &res, arg5));
bellard2f619692007-11-16 10:46:05 +00004627 if (put_user_s64(res, arg4))
4628 goto efault;
bellard4f2ac232004-04-26 19:44:02 +00004629#endif
bellard31e31b82003-02-18 22:55:36 +00004630 }
4631 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004632#endif
bellard31e31b82003-02-18 22:55:36 +00004633 case TARGET_NR_getdents:
blueswir1992f48a2007-10-14 16:27:31 +00004634#if TARGET_ABI_BITS != 32
pbrook53a59602006-03-25 19:31:22 +00004635 goto unimplemented;
blueswir1992f48a2007-10-14 16:27:31 +00004636#elif TARGET_ABI_BITS == 32 && HOST_LONG_BITS == 64
bellard4add45b2003-06-05 01:52:59 +00004637 {
pbrook53a59602006-03-25 19:31:22 +00004638 struct target_dirent *target_dirp;
bellard4add45b2003-06-05 01:52:59 +00004639 struct dirent *dirp;
blueswir1992f48a2007-10-14 16:27:31 +00004640 abi_long count = arg3;
bellard4add45b2003-06-05 01:52:59 +00004641
4642 dirp = malloc(count);
ths0da46a62007-10-20 20:23:07 +00004643 if (!dirp) {
bellard579a97f2007-11-11 14:26:47 +00004644 ret = -TARGET_ENOMEM;
ths0da46a62007-10-20 20:23:07 +00004645 goto fail;
4646 }
ths3b46e622007-09-17 08:09:54 +00004647
bellard4add45b2003-06-05 01:52:59 +00004648 ret = get_errno(sys_getdents(arg1, dirp, count));
4649 if (!is_error(ret)) {
4650 struct dirent *de;
4651 struct target_dirent *tde;
4652 int len = ret;
4653 int reclen, treclen;
4654 int count1, tnamelen;
4655
4656 count1 = 0;
4657 de = dirp;
bellard579a97f2007-11-11 14:26:47 +00004658 if (!(target_dirp = lock_user(VERIFY_WRITE, arg2, count, 0)))
4659 goto efault;
bellard4add45b2003-06-05 01:52:59 +00004660 tde = target_dirp;
4661 while (len > 0) {
4662 reclen = de->d_reclen;
blueswir1992f48a2007-10-14 16:27:31 +00004663 treclen = reclen - (2 * (sizeof(long) - sizeof(abi_long)));
bellard4add45b2003-06-05 01:52:59 +00004664 tde->d_reclen = tswap16(treclen);
4665 tde->d_ino = tswapl(de->d_ino);
4666 tde->d_off = tswapl(de->d_off);
blueswir1992f48a2007-10-14 16:27:31 +00004667 tnamelen = treclen - (2 * sizeof(abi_long) + 2);
bellard4add45b2003-06-05 01:52:59 +00004668 if (tnamelen > 256)
4669 tnamelen = 256;
bellard80a9d032005-01-03 23:31:27 +00004670 /* XXX: may not be correct */
bellard4add45b2003-06-05 01:52:59 +00004671 strncpy(tde->d_name, de->d_name, tnamelen);
4672 de = (struct dirent *)((char *)de + reclen);
4673 len -= reclen;
j_mayer1c5bf3b2007-04-14 12:17:59 +00004674 tde = (struct target_dirent *)((char *)tde + treclen);
bellard4add45b2003-06-05 01:52:59 +00004675 count1 += treclen;
4676 }
4677 ret = count1;
bellard579a97f2007-11-11 14:26:47 +00004678 unlock_user(target_dirp, arg2, ret);
bellard4add45b2003-06-05 01:52:59 +00004679 }
4680 free(dirp);
4681 }
4682#else
bellard31e31b82003-02-18 22:55:36 +00004683 {
pbrook53a59602006-03-25 19:31:22 +00004684 struct dirent *dirp;
blueswir1992f48a2007-10-14 16:27:31 +00004685 abi_long count = arg3;
bellarddab2ed92003-03-22 15:23:14 +00004686
bellard579a97f2007-11-11 14:26:47 +00004687 if (!(dirp = lock_user(VERIFY_WRITE, arg2, count, 0)))
4688 goto efault;
bellard72f03902003-02-18 23:33:18 +00004689 ret = get_errno(sys_getdents(arg1, dirp, count));
bellard31e31b82003-02-18 22:55:36 +00004690 if (!is_error(ret)) {
4691 struct dirent *de;
4692 int len = ret;
4693 int reclen;
4694 de = dirp;
4695 while (len > 0) {
bellard8083a3e2003-03-24 23:12:16 +00004696 reclen = de->d_reclen;
bellard31e31b82003-02-18 22:55:36 +00004697 if (reclen > len)
4698 break;
bellard8083a3e2003-03-24 23:12:16 +00004699 de->d_reclen = tswap16(reclen);
bellard31e31b82003-02-18 22:55:36 +00004700 tswapls(&de->d_ino);
4701 tswapls(&de->d_off);
4702 de = (struct dirent *)((char *)de + reclen);
4703 len -= reclen;
4704 }
4705 }
pbrook53a59602006-03-25 19:31:22 +00004706 unlock_user(dirp, arg2, ret);
bellard31e31b82003-02-18 22:55:36 +00004707 }
bellard4add45b2003-06-05 01:52:59 +00004708#endif
bellard31e31b82003-02-18 22:55:36 +00004709 break;
ths3ae43202007-09-16 21:39:48 +00004710#if defined(TARGET_NR_getdents64) && defined(__NR_getdents64)
bellarddab2ed92003-03-22 15:23:14 +00004711 case TARGET_NR_getdents64:
4712 {
pbrook53a59602006-03-25 19:31:22 +00004713 struct dirent64 *dirp;
blueswir1992f48a2007-10-14 16:27:31 +00004714 abi_long count = arg3;
bellard579a97f2007-11-11 14:26:47 +00004715 if (!(dirp = lock_user(VERIFY_WRITE, arg2, count, 0)))
4716 goto efault;
bellarddab2ed92003-03-22 15:23:14 +00004717 ret = get_errno(sys_getdents64(arg1, dirp, count));
4718 if (!is_error(ret)) {
4719 struct dirent64 *de;
4720 int len = ret;
4721 int reclen;
4722 de = dirp;
4723 while (len > 0) {
bellard8083a3e2003-03-24 23:12:16 +00004724 reclen = de->d_reclen;
bellarddab2ed92003-03-22 15:23:14 +00004725 if (reclen > len)
4726 break;
bellard8083a3e2003-03-24 23:12:16 +00004727 de->d_reclen = tswap16(reclen);
bellard8582a532007-11-11 23:11:36 +00004728 tswap64s((uint64_t *)&de->d_ino);
4729 tswap64s((uint64_t *)&de->d_off);
bellarddab2ed92003-03-22 15:23:14 +00004730 de = (struct dirent64 *)((char *)de + reclen);
4731 len -= reclen;
4732 }
4733 }
pbrook53a59602006-03-25 19:31:22 +00004734 unlock_user(dirp, arg2, ret);
bellarddab2ed92003-03-22 15:23:14 +00004735 }
4736 break;
bellarda541f292004-04-12 20:39:29 +00004737#endif /* TARGET_NR_getdents64 */
thse5febef2007-04-01 18:31:35 +00004738#ifdef TARGET_NR__newselect
bellard31e31b82003-02-18 22:55:36 +00004739 case TARGET_NR__newselect:
pbrook53a59602006-03-25 19:31:22 +00004740 ret = do_select(arg1, arg2, arg3, arg4, arg5);
bellard31e31b82003-02-18 22:55:36 +00004741 break;
thse5febef2007-04-01 18:31:35 +00004742#endif
4743#ifdef TARGET_NR_poll
bellard9de5e442003-03-23 16:49:39 +00004744 case TARGET_NR_poll:
4745 {
pbrook53a59602006-03-25 19:31:22 +00004746 struct target_pollfd *target_pfd;
bellard9de5e442003-03-23 16:49:39 +00004747 unsigned int nfds = arg2;
4748 int timeout = arg3;
4749 struct pollfd *pfd;
bellard7854b052003-03-29 17:22:23 +00004750 unsigned int i;
bellard9de5e442003-03-23 16:49:39 +00004751
bellard579a97f2007-11-11 14:26:47 +00004752 target_pfd = lock_user(VERIFY_WRITE, arg1, sizeof(struct target_pollfd) * nfds, 1);
4753 if (!target_pfd)
4754 goto efault;
bellard9de5e442003-03-23 16:49:39 +00004755 pfd = alloca(sizeof(struct pollfd) * nfds);
4756 for(i = 0; i < nfds; i++) {
bellard5cd43932003-03-29 16:54:36 +00004757 pfd[i].fd = tswap32(target_pfd[i].fd);
4758 pfd[i].events = tswap16(target_pfd[i].events);
bellard9de5e442003-03-23 16:49:39 +00004759 }
4760 ret = get_errno(poll(pfd, nfds, timeout));
4761 if (!is_error(ret)) {
4762 for(i = 0; i < nfds; i++) {
bellard5cd43932003-03-29 16:54:36 +00004763 target_pfd[i].revents = tswap16(pfd[i].revents);
bellard9de5e442003-03-23 16:49:39 +00004764 }
pbrook53a59602006-03-25 19:31:22 +00004765 ret += nfds * (sizeof(struct target_pollfd)
4766 - sizeof(struct pollfd));
bellard9de5e442003-03-23 16:49:39 +00004767 }
pbrook53a59602006-03-25 19:31:22 +00004768 unlock_user(target_pfd, arg1, ret);
bellard9de5e442003-03-23 16:49:39 +00004769 }
4770 break;
thse5febef2007-04-01 18:31:35 +00004771#endif
bellard31e31b82003-02-18 22:55:36 +00004772 case TARGET_NR_flock:
bellard9de5e442003-03-23 16:49:39 +00004773 /* NOTE: the flock constant seems to be the same for every
4774 Linux platform */
4775 ret = get_errno(flock(arg1, arg2));
bellard31e31b82003-02-18 22:55:36 +00004776 break;
4777 case TARGET_NR_readv:
4778 {
4779 int count = arg3;
bellard31e31b82003-02-18 22:55:36 +00004780 struct iovec *vec;
bellard31e31b82003-02-18 22:55:36 +00004781
4782 vec = alloca(count * sizeof(struct iovec));
bellard41df8412008-02-04 22:26:57 +00004783 if (lock_iovec(VERIFY_WRITE, vec, arg2, count, 0) < 0)
4784 goto efault;
bellard31e31b82003-02-18 22:55:36 +00004785 ret = get_errno(readv(arg1, vec, count));
pbrook53a59602006-03-25 19:31:22 +00004786 unlock_iovec(vec, arg2, count, 1);
bellard31e31b82003-02-18 22:55:36 +00004787 }
4788 break;
4789 case TARGET_NR_writev:
4790 {
4791 int count = arg3;
bellard31e31b82003-02-18 22:55:36 +00004792 struct iovec *vec;
bellard31e31b82003-02-18 22:55:36 +00004793
4794 vec = alloca(count * sizeof(struct iovec));
bellard41df8412008-02-04 22:26:57 +00004795 if (lock_iovec(VERIFY_READ, vec, arg2, count, 1) < 0)
4796 goto efault;
bellard31e31b82003-02-18 22:55:36 +00004797 ret = get_errno(writev(arg1, vec, count));
pbrook53a59602006-03-25 19:31:22 +00004798 unlock_iovec(vec, arg2, count, 0);
bellard31e31b82003-02-18 22:55:36 +00004799 }
4800 break;
4801 case TARGET_NR_getsid:
4802 ret = get_errno(getsid(arg1));
4803 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004804#if defined(TARGET_NR_fdatasync) /* Not on alpha (osf_datasync ?) */
bellard31e31b82003-02-18 22:55:36 +00004805 case TARGET_NR_fdatasync:
bellard5cd43932003-03-29 16:54:36 +00004806 ret = get_errno(fdatasync(arg1));
4807 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004808#endif
bellard31e31b82003-02-18 22:55:36 +00004809 case TARGET_NR__sysctl:
ths0da46a62007-10-20 20:23:07 +00004810 /* We don't implement this, but ENOTDIR is always a safe
bellard29e619b2004-09-13 21:41:04 +00004811 return value. */
ths0da46a62007-10-20 20:23:07 +00004812 ret = -TARGET_ENOTDIR;
4813 break;
bellard31e31b82003-02-18 22:55:36 +00004814 case TARGET_NR_sched_setparam:
bellard5cd43932003-03-29 16:54:36 +00004815 {
pbrook53a59602006-03-25 19:31:22 +00004816 struct sched_param *target_schp;
bellard5cd43932003-03-29 16:54:36 +00004817 struct sched_param schp;
pbrook53a59602006-03-25 19:31:22 +00004818
bellard579a97f2007-11-11 14:26:47 +00004819 if (!lock_user_struct(VERIFY_READ, target_schp, arg2, 1))
4820 goto efault;
bellard5cd43932003-03-29 16:54:36 +00004821 schp.sched_priority = tswap32(target_schp->sched_priority);
pbrook53a59602006-03-25 19:31:22 +00004822 unlock_user_struct(target_schp, arg2, 0);
bellard5cd43932003-03-29 16:54:36 +00004823 ret = get_errno(sched_setparam(arg1, &schp));
4824 }
4825 break;
bellard31e31b82003-02-18 22:55:36 +00004826 case TARGET_NR_sched_getparam:
bellard5cd43932003-03-29 16:54:36 +00004827 {
pbrook53a59602006-03-25 19:31:22 +00004828 struct sched_param *target_schp;
bellard5cd43932003-03-29 16:54:36 +00004829 struct sched_param schp;
4830 ret = get_errno(sched_getparam(arg1, &schp));
4831 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00004832 if (!lock_user_struct(VERIFY_WRITE, target_schp, arg2, 0))
4833 goto efault;
bellard5cd43932003-03-29 16:54:36 +00004834 target_schp->sched_priority = tswap32(schp.sched_priority);
pbrook53a59602006-03-25 19:31:22 +00004835 unlock_user_struct(target_schp, arg2, 1);
bellard5cd43932003-03-29 16:54:36 +00004836 }
4837 }
4838 break;
bellard31e31b82003-02-18 22:55:36 +00004839 case TARGET_NR_sched_setscheduler:
bellard5cd43932003-03-29 16:54:36 +00004840 {
pbrook53a59602006-03-25 19:31:22 +00004841 struct sched_param *target_schp;
bellard5cd43932003-03-29 16:54:36 +00004842 struct sched_param schp;
bellard579a97f2007-11-11 14:26:47 +00004843 if (!lock_user_struct(VERIFY_READ, target_schp, arg3, 1))
4844 goto efault;
bellard5cd43932003-03-29 16:54:36 +00004845 schp.sched_priority = tswap32(target_schp->sched_priority);
pbrook53a59602006-03-25 19:31:22 +00004846 unlock_user_struct(target_schp, arg3, 0);
bellard5cd43932003-03-29 16:54:36 +00004847 ret = get_errno(sched_setscheduler(arg1, arg2, &schp));
4848 }
4849 break;
bellard31e31b82003-02-18 22:55:36 +00004850 case TARGET_NR_sched_getscheduler:
bellard5cd43932003-03-29 16:54:36 +00004851 ret = get_errno(sched_getscheduler(arg1));
4852 break;
bellard31e31b82003-02-18 22:55:36 +00004853 case TARGET_NR_sched_yield:
4854 ret = get_errno(sched_yield());
4855 break;
4856 case TARGET_NR_sched_get_priority_max:
bellard5cd43932003-03-29 16:54:36 +00004857 ret = get_errno(sched_get_priority_max(arg1));
4858 break;
bellard31e31b82003-02-18 22:55:36 +00004859 case TARGET_NR_sched_get_priority_min:
bellard5cd43932003-03-29 16:54:36 +00004860 ret = get_errno(sched_get_priority_min(arg1));
4861 break;
bellard31e31b82003-02-18 22:55:36 +00004862 case TARGET_NR_sched_rr_get_interval:
bellard5cd43932003-03-29 16:54:36 +00004863 {
bellard5cd43932003-03-29 16:54:36 +00004864 struct timespec ts;
4865 ret = get_errno(sched_rr_get_interval(arg1, &ts));
4866 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00004867 host_to_target_timespec(arg2, &ts);
bellard5cd43932003-03-29 16:54:36 +00004868 }
4869 }
4870 break;
bellard31e31b82003-02-18 22:55:36 +00004871 case TARGET_NR_nanosleep:
bellard1b6b0292003-03-22 17:31:38 +00004872 {
bellard1b6b0292003-03-22 17:31:38 +00004873 struct timespec req, rem;
pbrook53a59602006-03-25 19:31:22 +00004874 target_to_host_timespec(&req, arg1);
bellard1b6b0292003-03-22 17:31:38 +00004875 ret = get_errno(nanosleep(&req, &rem));
pbrook53a59602006-03-25 19:31:22 +00004876 if (is_error(ret) && arg2) {
4877 host_to_target_timespec(arg2, &rem);
bellard1b6b0292003-03-22 17:31:38 +00004878 }
4879 }
4880 break;
thse5febef2007-04-01 18:31:35 +00004881#ifdef TARGET_NR_query_module
bellard31e31b82003-02-18 22:55:36 +00004882 case TARGET_NR_query_module:
bellard5cd43932003-03-29 16:54:36 +00004883 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00004884#endif
4885#ifdef TARGET_NR_nfsservctl
bellard31e31b82003-02-18 22:55:36 +00004886 case TARGET_NR_nfsservctl:
bellard5cd43932003-03-29 16:54:36 +00004887 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00004888#endif
bellard31e31b82003-02-18 22:55:36 +00004889 case TARGET_NR_prctl:
thse5574482007-02-11 20:03:13 +00004890 switch (arg1)
4891 {
4892 case PR_GET_PDEATHSIG:
4893 {
4894 int deathsig;
4895 ret = get_errno(prctl(arg1, &deathsig, arg3, arg4, arg5));
bellard2f619692007-11-16 10:46:05 +00004896 if (!is_error(ret) && arg2
4897 && put_user_ual(deathsig, arg2))
4898 goto efault;
thse5574482007-02-11 20:03:13 +00004899 }
4900 break;
4901 default:
4902 ret = get_errno(prctl(arg1, arg2, arg3, arg4, arg5));
4903 break;
4904 }
ths39b9aae2007-02-11 18:36:44 +00004905 break;
bellardd2fd1af2007-11-14 18:08:56 +00004906#ifdef TARGET_NR_arch_prctl
4907 case TARGET_NR_arch_prctl:
4908#if defined(TARGET_I386) && !defined(TARGET_ABI32)
4909 ret = do_arch_prctl(cpu_env, arg1, arg2);
4910 break;
4911#else
4912 goto unimplemented;
4913#endif
4914#endif
bellard67867302003-11-23 17:05:30 +00004915#ifdef TARGET_NR_pread
bellard31e31b82003-02-18 22:55:36 +00004916 case TARGET_NR_pread:
bellard579a97f2007-11-11 14:26:47 +00004917 if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
4918 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004919 ret = get_errno(pread(arg1, p, arg3, arg4));
4920 unlock_user(p, arg2, ret);
bellard206f0fa2003-05-14 19:01:56 +00004921 break;
bellard31e31b82003-02-18 22:55:36 +00004922 case TARGET_NR_pwrite:
bellard579a97f2007-11-11 14:26:47 +00004923 if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
4924 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004925 ret = get_errno(pwrite(arg1, p, arg3, arg4));
4926 unlock_user(p, arg2, 0);
bellard206f0fa2003-05-14 19:01:56 +00004927 break;
bellard67867302003-11-23 17:05:30 +00004928#endif
aurel32f2c7ba12008-03-28 22:32:06 +00004929#ifdef TARGET_NR_pread64
4930 case TARGET_NR_pread64:
4931 if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
4932 goto efault;
4933 ret = get_errno(pread64(arg1, p, arg3, target_offset64(arg4, arg5)));
4934 unlock_user(p, arg2, ret);
4935 break;
4936 case TARGET_NR_pwrite64:
4937 if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
4938 goto efault;
4939 ret = get_errno(pwrite64(arg1, p, arg3, target_offset64(arg4, arg5)));
4940 unlock_user(p, arg2, 0);
4941 break;
4942#endif
bellard31e31b82003-02-18 22:55:36 +00004943 case TARGET_NR_getcwd:
bellard579a97f2007-11-11 14:26:47 +00004944 if (!(p = lock_user(VERIFY_WRITE, arg1, arg2, 0)))
4945 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004946 ret = get_errno(sys_getcwd1(p, arg2));
4947 unlock_user(p, arg1, ret);
bellard31e31b82003-02-18 22:55:36 +00004948 break;
4949 case TARGET_NR_capget:
bellard5cd43932003-03-29 16:54:36 +00004950 goto unimplemented;
bellard31e31b82003-02-18 22:55:36 +00004951 case TARGET_NR_capset:
bellard5cd43932003-03-29 16:54:36 +00004952 goto unimplemented;
bellard31e31b82003-02-18 22:55:36 +00004953 case TARGET_NR_sigaltstack:
ths198a74d2007-09-27 16:44:32 +00004954#if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_MIPS) || \
4955 defined(TARGET_SPARC) || defined(TARGET_PPC) || defined(TARGET_ALPHA)
bellard579a97f2007-11-11 14:26:47 +00004956 ret = do_sigaltstack(arg1, arg2, get_sp_from_cpustate((CPUState *)cpu_env));
thsa04e1342007-09-27 13:57:58 +00004957 break;
4958#else
bellard5cd43932003-03-29 16:54:36 +00004959 goto unimplemented;
thsa04e1342007-09-27 13:57:58 +00004960#endif
bellard31e31b82003-02-18 22:55:36 +00004961 case TARGET_NR_sendfile:
bellard5cd43932003-03-29 16:54:36 +00004962 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004963#ifdef TARGET_NR_getpmsg
bellard31e31b82003-02-18 22:55:36 +00004964 case TARGET_NR_getpmsg:
bellard5cd43932003-03-29 16:54:36 +00004965 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004966#endif
4967#ifdef TARGET_NR_putpmsg
bellard31e31b82003-02-18 22:55:36 +00004968 case TARGET_NR_putpmsg:
bellard5cd43932003-03-29 16:54:36 +00004969 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004970#endif
bellard048f6b42005-11-26 18:47:20 +00004971#ifdef TARGET_NR_vfork
bellard31e31b82003-02-18 22:55:36 +00004972 case TARGET_NR_vfork:
bellard1b6b0292003-03-22 17:31:38 +00004973 ret = get_errno(do_fork(cpu_env, CLONE_VFORK | CLONE_VM | SIGCHLD, 0));
bellard31e31b82003-02-18 22:55:36 +00004974 break;
bellard048f6b42005-11-26 18:47:20 +00004975#endif
bellardebc05482003-09-30 21:08:41 +00004976#ifdef TARGET_NR_ugetrlimit
bellard31e31b82003-02-18 22:55:36 +00004977 case TARGET_NR_ugetrlimit:
bellard728584b2003-04-29 20:43:36 +00004978 {
4979 struct rlimit rlim;
4980 ret = get_errno(getrlimit(arg1, &rlim));
4981 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00004982 struct target_rlimit *target_rlim;
bellard579a97f2007-11-11 14:26:47 +00004983 if (!lock_user_struct(VERIFY_WRITE, target_rlim, arg2, 0))
4984 goto efault;
bellard728584b2003-04-29 20:43:36 +00004985 target_rlim->rlim_cur = tswapl(rlim.rlim_cur);
4986 target_rlim->rlim_max = tswapl(rlim.rlim_max);
pbrook53a59602006-03-25 19:31:22 +00004987 unlock_user_struct(target_rlim, arg2, 1);
bellard728584b2003-04-29 20:43:36 +00004988 }
4989 break;
4990 }
bellardebc05482003-09-30 21:08:41 +00004991#endif
bellarda315a142005-01-30 22:59:18 +00004992#ifdef TARGET_NR_truncate64
bellard31e31b82003-02-18 22:55:36 +00004993 case TARGET_NR_truncate64:
bellard579a97f2007-11-11 14:26:47 +00004994 if (!(p = lock_user_string(arg1)))
4995 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004996 ret = target_truncate64(cpu_env, p, arg2, arg3, arg4);
4997 unlock_user(p, arg1, 0);
bellard667f38b2005-07-23 14:46:27 +00004998 break;
bellarda315a142005-01-30 22:59:18 +00004999#endif
5000#ifdef TARGET_NR_ftruncate64
bellard31e31b82003-02-18 22:55:36 +00005001 case TARGET_NR_ftruncate64:
pbrookce4defa2006-02-09 16:49:55 +00005002 ret = target_ftruncate64(cpu_env, arg1, arg2, arg3, arg4);
bellard667f38b2005-07-23 14:46:27 +00005003 break;
bellarda315a142005-01-30 22:59:18 +00005004#endif
5005#ifdef TARGET_NR_stat64
bellard31e31b82003-02-18 22:55:36 +00005006 case TARGET_NR_stat64:
bellard579a97f2007-11-11 14:26:47 +00005007 if (!(p = lock_user_string(arg1)))
5008 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005009 ret = get_errno(stat(path(p), &st));
5010 unlock_user(p, arg1, 0);
bellard60cd49d2003-03-16 22:53:56 +00005011 goto do_stat64;
bellarda315a142005-01-30 22:59:18 +00005012#endif
5013#ifdef TARGET_NR_lstat64
bellard31e31b82003-02-18 22:55:36 +00005014 case TARGET_NR_lstat64:
bellard579a97f2007-11-11 14:26:47 +00005015 if (!(p = lock_user_string(arg1)))
5016 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005017 ret = get_errno(lstat(path(p), &st));
5018 unlock_user(p, arg1, 0);
bellard60cd49d2003-03-16 22:53:56 +00005019 goto do_stat64;
bellarda315a142005-01-30 22:59:18 +00005020#endif
5021#ifdef TARGET_NR_fstat64
bellard31e31b82003-02-18 22:55:36 +00005022 case TARGET_NR_fstat64:
bellard60cd49d2003-03-16 22:53:56 +00005023 {
5024 ret = get_errno(fstat(arg1, &st));
5025 do_stat64:
5026 if (!is_error(ret)) {
pbrookce4defa2006-02-09 16:49:55 +00005027#ifdef TARGET_ARM
5028 if (((CPUARMState *)cpu_env)->eabi) {
pbrook53a59602006-03-25 19:31:22 +00005029 struct target_eabi_stat64 *target_st;
bellard579a97f2007-11-11 14:26:47 +00005030
5031 if (!lock_user_struct(VERIFY_WRITE, target_st, arg2, 0))
5032 goto efault;
pbrookce4defa2006-02-09 16:49:55 +00005033 memset(target_st, 0, sizeof(struct target_eabi_stat64));
bellard579a97f2007-11-11 14:26:47 +00005034 __put_user(st.st_dev, &target_st->st_dev);
5035 __put_user(st.st_ino, &target_st->st_ino);
bellardec86b0f2003-04-11 00:15:04 +00005036#ifdef TARGET_STAT64_HAS_BROKEN_ST_INO
bellard579a97f2007-11-11 14:26:47 +00005037 __put_user(st.st_ino, &target_st->__st_ino);
bellardec86b0f2003-04-11 00:15:04 +00005038#endif
bellard579a97f2007-11-11 14:26:47 +00005039 __put_user(st.st_mode, &target_st->st_mode);
5040 __put_user(st.st_nlink, &target_st->st_nlink);
5041 __put_user(st.st_uid, &target_st->st_uid);
5042 __put_user(st.st_gid, &target_st->st_gid);
5043 __put_user(st.st_rdev, &target_st->st_rdev);
5044 __put_user(st.st_size, &target_st->st_size);
5045 __put_user(st.st_blksize, &target_st->st_blksize);
5046 __put_user(st.st_blocks, &target_st->st_blocks);
5047 __put_user(st.st_atime, &target_st->target_st_atime);
5048 __put_user(st.st_mtime, &target_st->target_st_mtime);
5049 __put_user(st.st_ctime, &target_st->target_st_ctime);
5050 unlock_user_struct(target_st, arg2, 1);
pbrookce4defa2006-02-09 16:49:55 +00005051 } else
5052#endif
5053 {
pbrook53a59602006-03-25 19:31:22 +00005054 struct target_stat64 *target_st;
bellard579a97f2007-11-11 14:26:47 +00005055
5056 if (!lock_user_struct(VERIFY_WRITE, target_st, arg2, 0))
5057 goto efault;
pbrookce4defa2006-02-09 16:49:55 +00005058 memset(target_st, 0, sizeof(struct target_stat64));
bellard579a97f2007-11-11 14:26:47 +00005059 __put_user(st.st_dev, &target_st->st_dev);
5060 __put_user(st.st_ino, &target_st->st_ino);
pbrookce4defa2006-02-09 16:49:55 +00005061#ifdef TARGET_STAT64_HAS_BROKEN_ST_INO
bellard579a97f2007-11-11 14:26:47 +00005062 __put_user(st.st_ino, &target_st->__st_ino);
pbrookce4defa2006-02-09 16:49:55 +00005063#endif
bellard579a97f2007-11-11 14:26:47 +00005064 __put_user(st.st_mode, &target_st->st_mode);
5065 __put_user(st.st_nlink, &target_st->st_nlink);
5066 __put_user(st.st_uid, &target_st->st_uid);
5067 __put_user(st.st_gid, &target_st->st_gid);
5068 __put_user(st.st_rdev, &target_st->st_rdev);
pbrookce4defa2006-02-09 16:49:55 +00005069 /* XXX: better use of kernel struct */
bellard579a97f2007-11-11 14:26:47 +00005070 __put_user(st.st_size, &target_st->st_size);
5071 __put_user(st.st_blksize, &target_st->st_blksize);
5072 __put_user(st.st_blocks, &target_st->st_blocks);
5073 __put_user(st.st_atime, &target_st->target_st_atime);
5074 __put_user(st.st_mtime, &target_st->target_st_mtime);
5075 __put_user(st.st_ctime, &target_st->target_st_ctime);
5076 unlock_user_struct(target_st, arg2, 1);
pbrookce4defa2006-02-09 16:49:55 +00005077 }
bellard60cd49d2003-03-16 22:53:56 +00005078 }
5079 }
5080 break;
bellarda315a142005-01-30 22:59:18 +00005081#endif
bellard67867302003-11-23 17:05:30 +00005082#ifdef USE_UID16
5083 case TARGET_NR_lchown:
bellard579a97f2007-11-11 14:26:47 +00005084 if (!(p = lock_user_string(arg1)))
5085 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005086 ret = get_errno(lchown(p, low2highuid(arg2), low2highgid(arg3)));
5087 unlock_user(p, arg1, 0);
bellard67867302003-11-23 17:05:30 +00005088 break;
5089 case TARGET_NR_getuid:
5090 ret = get_errno(high2lowuid(getuid()));
5091 break;
5092 case TARGET_NR_getgid:
5093 ret = get_errno(high2lowgid(getgid()));
5094 break;
5095 case TARGET_NR_geteuid:
5096 ret = get_errno(high2lowuid(geteuid()));
5097 break;
5098 case TARGET_NR_getegid:
5099 ret = get_errno(high2lowgid(getegid()));
5100 break;
5101 case TARGET_NR_setreuid:
5102 ret = get_errno(setreuid(low2highuid(arg1), low2highuid(arg2)));
5103 break;
5104 case TARGET_NR_setregid:
5105 ret = get_errno(setregid(low2highgid(arg1), low2highgid(arg2)));
5106 break;
5107 case TARGET_NR_getgroups:
5108 {
5109 int gidsetsize = arg1;
pbrook53a59602006-03-25 19:31:22 +00005110 uint16_t *target_grouplist;
bellard67867302003-11-23 17:05:30 +00005111 gid_t *grouplist;
5112 int i;
5113
5114 grouplist = alloca(gidsetsize * sizeof(gid_t));
5115 ret = get_errno(getgroups(gidsetsize, grouplist));
5116 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00005117 target_grouplist = lock_user(VERIFY_WRITE, arg2, gidsetsize * 2, 0);
5118 if (!target_grouplist)
5119 goto efault;
bellard67867302003-11-23 17:05:30 +00005120 for(i = 0;i < gidsetsize; i++)
5121 target_grouplist[i] = tswap16(grouplist[i]);
pbrook53a59602006-03-25 19:31:22 +00005122 unlock_user(target_grouplist, arg2, gidsetsize * 2);
bellard67867302003-11-23 17:05:30 +00005123 }
5124 }
5125 break;
5126 case TARGET_NR_setgroups:
5127 {
5128 int gidsetsize = arg1;
pbrook53a59602006-03-25 19:31:22 +00005129 uint16_t *target_grouplist;
bellard67867302003-11-23 17:05:30 +00005130 gid_t *grouplist;
5131 int i;
5132
5133 grouplist = alloca(gidsetsize * sizeof(gid_t));
bellard579a97f2007-11-11 14:26:47 +00005134 target_grouplist = lock_user(VERIFY_READ, arg2, gidsetsize * 2, 1);
5135 if (!target_grouplist) {
5136 ret = -TARGET_EFAULT;
5137 goto fail;
5138 }
bellard67867302003-11-23 17:05:30 +00005139 for(i = 0;i < gidsetsize; i++)
5140 grouplist[i] = tswap16(target_grouplist[i]);
pbrook53a59602006-03-25 19:31:22 +00005141 unlock_user(target_grouplist, arg2, 0);
bellard67867302003-11-23 17:05:30 +00005142 ret = get_errno(setgroups(gidsetsize, grouplist));
5143 }
5144 break;
5145 case TARGET_NR_fchown:
5146 ret = get_errno(fchown(arg1, low2highuid(arg2), low2highgid(arg3)));
5147 break;
thsccfa72b2007-09-24 09:23:34 +00005148#if defined(TARGET_NR_fchownat) && defined(__NR_fchownat)
5149 case TARGET_NR_fchownat:
bellard579a97f2007-11-11 14:26:47 +00005150 if (!(p = lock_user_string(arg2)))
5151 goto efault;
5152 ret = get_errno(sys_fchownat(arg1, p, low2highuid(arg3), low2highgid(arg4), arg5));
5153 unlock_user(p, arg2, 0);
thsccfa72b2007-09-24 09:23:34 +00005154 break;
5155#endif
bellard67867302003-11-23 17:05:30 +00005156#ifdef TARGET_NR_setresuid
5157 case TARGET_NR_setresuid:
ths5fafdf22007-09-16 21:08:06 +00005158 ret = get_errno(setresuid(low2highuid(arg1),
5159 low2highuid(arg2),
bellard67867302003-11-23 17:05:30 +00005160 low2highuid(arg3)));
5161 break;
5162#endif
5163#ifdef TARGET_NR_getresuid
5164 case TARGET_NR_getresuid:
5165 {
pbrook53a59602006-03-25 19:31:22 +00005166 uid_t ruid, euid, suid;
bellard67867302003-11-23 17:05:30 +00005167 ret = get_errno(getresuid(&ruid, &euid, &suid));
5168 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +00005169 if (put_user_u16(high2lowuid(ruid), arg1)
5170 || put_user_u16(high2lowuid(euid), arg2)
5171 || put_user_u16(high2lowuid(suid), arg3))
5172 goto efault;
bellard67867302003-11-23 17:05:30 +00005173 }
5174 }
5175 break;
5176#endif
5177#ifdef TARGET_NR_getresgid
5178 case TARGET_NR_setresgid:
ths5fafdf22007-09-16 21:08:06 +00005179 ret = get_errno(setresgid(low2highgid(arg1),
5180 low2highgid(arg2),
bellard67867302003-11-23 17:05:30 +00005181 low2highgid(arg3)));
5182 break;
5183#endif
5184#ifdef TARGET_NR_getresgid
5185 case TARGET_NR_getresgid:
5186 {
pbrook53a59602006-03-25 19:31:22 +00005187 gid_t rgid, egid, sgid;
bellard67867302003-11-23 17:05:30 +00005188 ret = get_errno(getresgid(&rgid, &egid, &sgid));
5189 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +00005190 if (put_user_u16(high2lowgid(rgid), arg1)
5191 || put_user_u16(high2lowgid(egid), arg2)
5192 || put_user_u16(high2lowgid(sgid), arg3))
5193 goto efault;
bellard67867302003-11-23 17:05:30 +00005194 }
5195 }
5196 break;
5197#endif
5198 case TARGET_NR_chown:
bellard579a97f2007-11-11 14:26:47 +00005199 if (!(p = lock_user_string(arg1)))
5200 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005201 ret = get_errno(chown(p, low2highuid(arg2), low2highgid(arg3)));
5202 unlock_user(p, arg1, 0);
bellard67867302003-11-23 17:05:30 +00005203 break;
5204 case TARGET_NR_setuid:
5205 ret = get_errno(setuid(low2highuid(arg1)));
5206 break;
5207 case TARGET_NR_setgid:
5208 ret = get_errno(setgid(low2highgid(arg1)));
5209 break;
5210 case TARGET_NR_setfsuid:
5211 ret = get_errno(setfsuid(arg1));
5212 break;
5213 case TARGET_NR_setfsgid:
5214 ret = get_errno(setfsgid(arg1));
5215 break;
5216#endif /* USE_UID16 */
5217
bellarda315a142005-01-30 22:59:18 +00005218#ifdef TARGET_NR_lchown32
bellard31e31b82003-02-18 22:55:36 +00005219 case TARGET_NR_lchown32:
bellard579a97f2007-11-11 14:26:47 +00005220 if (!(p = lock_user_string(arg1)))
5221 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005222 ret = get_errno(lchown(p, arg2, arg3));
5223 unlock_user(p, arg1, 0);
bellardb03c60f2003-03-23 17:19:56 +00005224 break;
bellarda315a142005-01-30 22:59:18 +00005225#endif
5226#ifdef TARGET_NR_getuid32
bellard31e31b82003-02-18 22:55:36 +00005227 case TARGET_NR_getuid32:
bellardb03c60f2003-03-23 17:19:56 +00005228 ret = get_errno(getuid());
5229 break;
bellarda315a142005-01-30 22:59:18 +00005230#endif
5231#ifdef TARGET_NR_getgid32
bellard31e31b82003-02-18 22:55:36 +00005232 case TARGET_NR_getgid32:
bellardb03c60f2003-03-23 17:19:56 +00005233 ret = get_errno(getgid());
5234 break;
bellarda315a142005-01-30 22:59:18 +00005235#endif
5236#ifdef TARGET_NR_geteuid32
bellard31e31b82003-02-18 22:55:36 +00005237 case TARGET_NR_geteuid32:
bellardb03c60f2003-03-23 17:19:56 +00005238 ret = get_errno(geteuid());
5239 break;
bellarda315a142005-01-30 22:59:18 +00005240#endif
5241#ifdef TARGET_NR_getegid32
bellard31e31b82003-02-18 22:55:36 +00005242 case TARGET_NR_getegid32:
bellardb03c60f2003-03-23 17:19:56 +00005243 ret = get_errno(getegid());
5244 break;
bellarda315a142005-01-30 22:59:18 +00005245#endif
5246#ifdef TARGET_NR_setreuid32
bellard31e31b82003-02-18 22:55:36 +00005247 case TARGET_NR_setreuid32:
bellardb03c60f2003-03-23 17:19:56 +00005248 ret = get_errno(setreuid(arg1, arg2));
5249 break;
bellarda315a142005-01-30 22:59:18 +00005250#endif
5251#ifdef TARGET_NR_setregid32
bellard31e31b82003-02-18 22:55:36 +00005252 case TARGET_NR_setregid32:
bellardb03c60f2003-03-23 17:19:56 +00005253 ret = get_errno(setregid(arg1, arg2));
5254 break;
bellarda315a142005-01-30 22:59:18 +00005255#endif
5256#ifdef TARGET_NR_getgroups32
bellard31e31b82003-02-18 22:55:36 +00005257 case TARGET_NR_getgroups32:
bellard99c475a2005-01-31 20:45:13 +00005258 {
5259 int gidsetsize = arg1;
pbrook53a59602006-03-25 19:31:22 +00005260 uint32_t *target_grouplist;
bellard99c475a2005-01-31 20:45:13 +00005261 gid_t *grouplist;
5262 int i;
5263
5264 grouplist = alloca(gidsetsize * sizeof(gid_t));
5265 ret = get_errno(getgroups(gidsetsize, grouplist));
5266 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00005267 target_grouplist = lock_user(VERIFY_WRITE, arg2, gidsetsize * 4, 0);
5268 if (!target_grouplist) {
5269 ret = -TARGET_EFAULT;
5270 goto fail;
5271 }
bellard99c475a2005-01-31 20:45:13 +00005272 for(i = 0;i < gidsetsize; i++)
pbrook53a59602006-03-25 19:31:22 +00005273 target_grouplist[i] = tswap32(grouplist[i]);
5274 unlock_user(target_grouplist, arg2, gidsetsize * 4);
bellard99c475a2005-01-31 20:45:13 +00005275 }
5276 }
5277 break;
bellarda315a142005-01-30 22:59:18 +00005278#endif
5279#ifdef TARGET_NR_setgroups32
bellard31e31b82003-02-18 22:55:36 +00005280 case TARGET_NR_setgroups32:
bellard99c475a2005-01-31 20:45:13 +00005281 {
5282 int gidsetsize = arg1;
pbrook53a59602006-03-25 19:31:22 +00005283 uint32_t *target_grouplist;
bellard99c475a2005-01-31 20:45:13 +00005284 gid_t *grouplist;
5285 int i;
ths3b46e622007-09-17 08:09:54 +00005286
bellard99c475a2005-01-31 20:45:13 +00005287 grouplist = alloca(gidsetsize * sizeof(gid_t));
bellard579a97f2007-11-11 14:26:47 +00005288 target_grouplist = lock_user(VERIFY_READ, arg2, gidsetsize * 4, 1);
5289 if (!target_grouplist) {
5290 ret = -TARGET_EFAULT;
5291 goto fail;
5292 }
bellard99c475a2005-01-31 20:45:13 +00005293 for(i = 0;i < gidsetsize; i++)
pbrook53a59602006-03-25 19:31:22 +00005294 grouplist[i] = tswap32(target_grouplist[i]);
5295 unlock_user(target_grouplist, arg2, 0);
bellard99c475a2005-01-31 20:45:13 +00005296 ret = get_errno(setgroups(gidsetsize, grouplist));
5297 }
5298 break;
bellarda315a142005-01-30 22:59:18 +00005299#endif
5300#ifdef TARGET_NR_fchown32
bellard31e31b82003-02-18 22:55:36 +00005301 case TARGET_NR_fchown32:
bellardb03c60f2003-03-23 17:19:56 +00005302 ret = get_errno(fchown(arg1, arg2, arg3));
5303 break;
bellarda315a142005-01-30 22:59:18 +00005304#endif
5305#ifdef TARGET_NR_setresuid32
bellard31e31b82003-02-18 22:55:36 +00005306 case TARGET_NR_setresuid32:
bellardb03c60f2003-03-23 17:19:56 +00005307 ret = get_errno(setresuid(arg1, arg2, arg3));
5308 break;
bellarda315a142005-01-30 22:59:18 +00005309#endif
5310#ifdef TARGET_NR_getresuid32
bellard31e31b82003-02-18 22:55:36 +00005311 case TARGET_NR_getresuid32:
bellardb03c60f2003-03-23 17:19:56 +00005312 {
pbrook53a59602006-03-25 19:31:22 +00005313 uid_t ruid, euid, suid;
bellardb03c60f2003-03-23 17:19:56 +00005314 ret = get_errno(getresuid(&ruid, &euid, &suid));
5315 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +00005316 if (put_user_u32(ruid, arg1)
5317 || put_user_u32(euid, arg2)
5318 || put_user_u32(suid, arg3))
5319 goto efault;
bellardb03c60f2003-03-23 17:19:56 +00005320 }
5321 }
5322 break;
bellarda315a142005-01-30 22:59:18 +00005323#endif
5324#ifdef TARGET_NR_setresgid32
bellard31e31b82003-02-18 22:55:36 +00005325 case TARGET_NR_setresgid32:
bellardb03c60f2003-03-23 17:19:56 +00005326 ret = get_errno(setresgid(arg1, arg2, arg3));
5327 break;
bellarda315a142005-01-30 22:59:18 +00005328#endif
5329#ifdef TARGET_NR_getresgid32
bellard31e31b82003-02-18 22:55:36 +00005330 case TARGET_NR_getresgid32:
bellardb03c60f2003-03-23 17:19:56 +00005331 {
pbrook53a59602006-03-25 19:31:22 +00005332 gid_t rgid, egid, sgid;
bellardb03c60f2003-03-23 17:19:56 +00005333 ret = get_errno(getresgid(&rgid, &egid, &sgid));
5334 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +00005335 if (put_user_u32(rgid, arg1)
5336 || put_user_u32(egid, arg2)
5337 || put_user_u32(sgid, arg3))
5338 goto efault;
bellardb03c60f2003-03-23 17:19:56 +00005339 }
5340 }
5341 break;
bellarda315a142005-01-30 22:59:18 +00005342#endif
5343#ifdef TARGET_NR_chown32
bellard31e31b82003-02-18 22:55:36 +00005344 case TARGET_NR_chown32:
bellard579a97f2007-11-11 14:26:47 +00005345 if (!(p = lock_user_string(arg1)))
5346 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005347 ret = get_errno(chown(p, arg2, arg3));
5348 unlock_user(p, arg1, 0);
bellardb03c60f2003-03-23 17:19:56 +00005349 break;
bellarda315a142005-01-30 22:59:18 +00005350#endif
5351#ifdef TARGET_NR_setuid32
bellard31e31b82003-02-18 22:55:36 +00005352 case TARGET_NR_setuid32:
bellardb03c60f2003-03-23 17:19:56 +00005353 ret = get_errno(setuid(arg1));
5354 break;
bellarda315a142005-01-30 22:59:18 +00005355#endif
5356#ifdef TARGET_NR_setgid32
bellard31e31b82003-02-18 22:55:36 +00005357 case TARGET_NR_setgid32:
bellardb03c60f2003-03-23 17:19:56 +00005358 ret = get_errno(setgid(arg1));
5359 break;
bellarda315a142005-01-30 22:59:18 +00005360#endif
5361#ifdef TARGET_NR_setfsuid32
bellard31e31b82003-02-18 22:55:36 +00005362 case TARGET_NR_setfsuid32:
bellardb03c60f2003-03-23 17:19:56 +00005363 ret = get_errno(setfsuid(arg1));
5364 break;
bellarda315a142005-01-30 22:59:18 +00005365#endif
5366#ifdef TARGET_NR_setfsgid32
bellard31e31b82003-02-18 22:55:36 +00005367 case TARGET_NR_setfsgid32:
bellardb03c60f2003-03-23 17:19:56 +00005368 ret = get_errno(setfsgid(arg1));
5369 break;
bellarda315a142005-01-30 22:59:18 +00005370#endif
bellard67867302003-11-23 17:05:30 +00005371
bellard31e31b82003-02-18 22:55:36 +00005372 case TARGET_NR_pivot_root:
bellardb03c60f2003-03-23 17:19:56 +00005373 goto unimplemented;
bellardffa65c32004-01-04 23:57:22 +00005374#ifdef TARGET_NR_mincore
bellard31e31b82003-02-18 22:55:36 +00005375 case TARGET_NR_mincore:
bellardb03c60f2003-03-23 17:19:56 +00005376 goto unimplemented;
bellardffa65c32004-01-04 23:57:22 +00005377#endif
5378#ifdef TARGET_NR_madvise
bellard31e31b82003-02-18 22:55:36 +00005379 case TARGET_NR_madvise:
pbrook24836682006-04-16 14:14:53 +00005380 /* A straight passthrough may not be safe because qemu sometimes
5381 turns private flie-backed mappings into anonymous mappings.
5382 This will break MADV_DONTNEED.
5383 This is a hint, so ignoring and returning success is ok. */
5384 ret = get_errno(0);
5385 break;
bellardffa65c32004-01-04 23:57:22 +00005386#endif
blueswir1992f48a2007-10-14 16:27:31 +00005387#if TARGET_ABI_BITS == 32
bellard31e31b82003-02-18 22:55:36 +00005388 case TARGET_NR_fcntl64:
bellard77e46722003-04-29 20:39:06 +00005389 {
thsb1e341e2007-03-20 21:50:52 +00005390 int cmd;
bellard77e46722003-04-29 20:39:06 +00005391 struct flock64 fl;
pbrook53a59602006-03-25 19:31:22 +00005392 struct target_flock64 *target_fl;
pbrookce4defa2006-02-09 16:49:55 +00005393#ifdef TARGET_ARM
pbrook53a59602006-03-25 19:31:22 +00005394 struct target_eabi_flock64 *target_efl;
pbrookce4defa2006-02-09 16:49:55 +00005395#endif
bellard77e46722003-04-29 20:39:06 +00005396
thsb1e341e2007-03-20 21:50:52 +00005397 switch(arg2){
5398 case TARGET_F_GETLK64:
5399 cmd = F_GETLK64;
thsa7222582007-03-22 15:08:55 +00005400 break;
thsb1e341e2007-03-20 21:50:52 +00005401 case TARGET_F_SETLK64:
5402 cmd = F_SETLK64;
thsa7222582007-03-22 15:08:55 +00005403 break;
thsb1e341e2007-03-20 21:50:52 +00005404 case TARGET_F_SETLKW64:
5405 cmd = F_SETLK64;
thsa7222582007-03-22 15:08:55 +00005406 break;
thsb1e341e2007-03-20 21:50:52 +00005407 default:
5408 cmd = arg2;
thsa7222582007-03-22 15:08:55 +00005409 break;
thsb1e341e2007-03-20 21:50:52 +00005410 }
5411
bellard60cd49d2003-03-16 22:53:56 +00005412 switch(arg2) {
thsb1e341e2007-03-20 21:50:52 +00005413 case TARGET_F_GETLK64:
ths58134272007-03-31 18:59:32 +00005414#ifdef TARGET_ARM
5415 if (((CPUARMState *)cpu_env)->eabi) {
bellard9ee1fa22007-11-11 15:11:19 +00005416 if (!lock_user_struct(VERIFY_READ, target_efl, arg3, 1))
5417 goto efault;
ths58134272007-03-31 18:59:32 +00005418 fl.l_type = tswap16(target_efl->l_type);
5419 fl.l_whence = tswap16(target_efl->l_whence);
5420 fl.l_start = tswap64(target_efl->l_start);
5421 fl.l_len = tswap64(target_efl->l_len);
5422 fl.l_pid = tswapl(target_efl->l_pid);
5423 unlock_user_struct(target_efl, arg3, 0);
5424 } else
5425#endif
5426 {
bellard9ee1fa22007-11-11 15:11:19 +00005427 if (!lock_user_struct(VERIFY_READ, target_fl, arg3, 1))
5428 goto efault;
ths58134272007-03-31 18:59:32 +00005429 fl.l_type = tswap16(target_fl->l_type);
5430 fl.l_whence = tswap16(target_fl->l_whence);
5431 fl.l_start = tswap64(target_fl->l_start);
5432 fl.l_len = tswap64(target_fl->l_len);
5433 fl.l_pid = tswapl(target_fl->l_pid);
5434 unlock_user_struct(target_fl, arg3, 0);
5435 }
thsb1e341e2007-03-20 21:50:52 +00005436 ret = get_errno(fcntl(arg1, cmd, &fl));
bellard77e46722003-04-29 20:39:06 +00005437 if (ret == 0) {
pbrookce4defa2006-02-09 16:49:55 +00005438#ifdef TARGET_ARM
5439 if (((CPUARMState *)cpu_env)->eabi) {
bellard9ee1fa22007-11-11 15:11:19 +00005440 if (!lock_user_struct(VERIFY_WRITE, target_efl, arg3, 0))
5441 goto efault;
pbrookce4defa2006-02-09 16:49:55 +00005442 target_efl->l_type = tswap16(fl.l_type);
5443 target_efl->l_whence = tswap16(fl.l_whence);
5444 target_efl->l_start = tswap64(fl.l_start);
5445 target_efl->l_len = tswap64(fl.l_len);
5446 target_efl->l_pid = tswapl(fl.l_pid);
pbrook53a59602006-03-25 19:31:22 +00005447 unlock_user_struct(target_efl, arg3, 1);
pbrookce4defa2006-02-09 16:49:55 +00005448 } else
5449#endif
5450 {
bellard9ee1fa22007-11-11 15:11:19 +00005451 if (!lock_user_struct(VERIFY_WRITE, target_fl, arg3, 0))
5452 goto efault;
pbrookce4defa2006-02-09 16:49:55 +00005453 target_fl->l_type = tswap16(fl.l_type);
5454 target_fl->l_whence = tswap16(fl.l_whence);
5455 target_fl->l_start = tswap64(fl.l_start);
5456 target_fl->l_len = tswap64(fl.l_len);
5457 target_fl->l_pid = tswapl(fl.l_pid);
pbrook53a59602006-03-25 19:31:22 +00005458 unlock_user_struct(target_fl, arg3, 1);
pbrookce4defa2006-02-09 16:49:55 +00005459 }
bellard77e46722003-04-29 20:39:06 +00005460 }
5461 break;
5462
thsb1e341e2007-03-20 21:50:52 +00005463 case TARGET_F_SETLK64:
5464 case TARGET_F_SETLKW64:
pbrookce4defa2006-02-09 16:49:55 +00005465#ifdef TARGET_ARM
5466 if (((CPUARMState *)cpu_env)->eabi) {
bellard9ee1fa22007-11-11 15:11:19 +00005467 if (!lock_user_struct(VERIFY_READ, target_efl, arg3, 1))
5468 goto efault;
pbrookce4defa2006-02-09 16:49:55 +00005469 fl.l_type = tswap16(target_efl->l_type);
5470 fl.l_whence = tswap16(target_efl->l_whence);
5471 fl.l_start = tswap64(target_efl->l_start);
5472 fl.l_len = tswap64(target_efl->l_len);
5473 fl.l_pid = tswapl(target_efl->l_pid);
pbrook53a59602006-03-25 19:31:22 +00005474 unlock_user_struct(target_efl, arg3, 0);
pbrookce4defa2006-02-09 16:49:55 +00005475 } else
5476#endif
5477 {
bellard9ee1fa22007-11-11 15:11:19 +00005478 if (!lock_user_struct(VERIFY_READ, target_fl, arg3, 1))
5479 goto efault;
pbrookce4defa2006-02-09 16:49:55 +00005480 fl.l_type = tswap16(target_fl->l_type);
5481 fl.l_whence = tswap16(target_fl->l_whence);
5482 fl.l_start = tswap64(target_fl->l_start);
5483 fl.l_len = tswap64(target_fl->l_len);
5484 fl.l_pid = tswapl(target_fl->l_pid);
pbrook53a59602006-03-25 19:31:22 +00005485 unlock_user_struct(target_fl, arg3, 0);
pbrookce4defa2006-02-09 16:49:55 +00005486 }
thsb1e341e2007-03-20 21:50:52 +00005487 ret = get_errno(fcntl(arg1, cmd, &fl));
bellard77e46722003-04-29 20:39:06 +00005488 break;
bellard60cd49d2003-03-16 22:53:56 +00005489 default:
bellard9ee1fa22007-11-11 15:11:19 +00005490 ret = do_fcntl(arg1, cmd, arg3);
bellard60cd49d2003-03-16 22:53:56 +00005491 break;
5492 }
bellard77e46722003-04-29 20:39:06 +00005493 break;
5494 }
bellard60cd49d2003-03-16 22:53:56 +00005495#endif
ths7d600c82006-12-08 01:32:58 +00005496#ifdef TARGET_NR_cacheflush
5497 case TARGET_NR_cacheflush:
5498 /* self-modifying code is handled automatically, so nothing needed */
5499 ret = 0;
5500 break;
5501#endif
bellardebc05482003-09-30 21:08:41 +00005502#ifdef TARGET_NR_security
bellard31e31b82003-02-18 22:55:36 +00005503 case TARGET_NR_security:
5504 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00005505#endif
bellardc573ff62004-01-04 15:51:36 +00005506#ifdef TARGET_NR_getpagesize
5507 case TARGET_NR_getpagesize:
5508 ret = TARGET_PAGE_SIZE;
5509 break;
5510#endif
bellard31e31b82003-02-18 22:55:36 +00005511 case TARGET_NR_gettid:
5512 ret = get_errno(gettid());
5513 break;
thse5febef2007-04-01 18:31:35 +00005514#ifdef TARGET_NR_readahead
bellard31e31b82003-02-18 22:55:36 +00005515 case TARGET_NR_readahead:
bellard5cd43932003-03-29 16:54:36 +00005516 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00005517#endif
bellardebc05482003-09-30 21:08:41 +00005518#ifdef TARGET_NR_setxattr
bellard31e31b82003-02-18 22:55:36 +00005519 case TARGET_NR_setxattr:
5520 case TARGET_NR_lsetxattr:
5521 case TARGET_NR_fsetxattr:
5522 case TARGET_NR_getxattr:
5523 case TARGET_NR_lgetxattr:
5524 case TARGET_NR_fgetxattr:
5525 case TARGET_NR_listxattr:
5526 case TARGET_NR_llistxattr:
5527 case TARGET_NR_flistxattr:
5528 case TARGET_NR_removexattr:
5529 case TARGET_NR_lremovexattr:
5530 case TARGET_NR_fremovexattr:
bellard5cd43932003-03-29 16:54:36 +00005531 goto unimplemented_nowarn;
bellardebc05482003-09-30 21:08:41 +00005532#endif
5533#ifdef TARGET_NR_set_thread_area
bellard5cd43932003-03-29 16:54:36 +00005534 case TARGET_NR_set_thread_area:
bellard8d18e892007-11-14 15:18:40 +00005535#if defined(TARGET_MIPS)
ths6f5b89a2007-03-02 20:48:00 +00005536 ((CPUMIPSState *) cpu_env)->tls_value = arg1;
5537 ret = 0;
5538 break;
bellard8d18e892007-11-14 15:18:40 +00005539#elif defined(TARGET_I386) && defined(TARGET_ABI32)
5540 ret = do_set_thread_area(cpu_env, arg1);
5541 break;
ths6f5b89a2007-03-02 20:48:00 +00005542#else
5543 goto unimplemented_nowarn;
5544#endif
5545#endif
5546#ifdef TARGET_NR_get_thread_area
bellard5cd43932003-03-29 16:54:36 +00005547 case TARGET_NR_get_thread_area:
bellard8d18e892007-11-14 15:18:40 +00005548#if defined(TARGET_I386) && defined(TARGET_ABI32)
5549 ret = do_get_thread_area(cpu_env, arg1);
5550#else
bellard5cd43932003-03-29 16:54:36 +00005551 goto unimplemented_nowarn;
bellardebc05482003-09-30 21:08:41 +00005552#endif
bellard8d18e892007-11-14 15:18:40 +00005553#endif
bellard48dc41e2006-06-21 18:15:50 +00005554#ifdef TARGET_NR_getdomainname
5555 case TARGET_NR_getdomainname:
5556 goto unimplemented_nowarn;
5557#endif
ths6f5b89a2007-03-02 20:48:00 +00005558
thsb5906f92007-03-19 13:32:45 +00005559#ifdef TARGET_NR_clock_gettime
5560 case TARGET_NR_clock_gettime:
5561 {
5562 struct timespec ts;
5563 ret = get_errno(clock_gettime(arg1, &ts));
5564 if (!is_error(ret)) {
5565 host_to_target_timespec(arg2, &ts);
5566 }
5567 break;
5568 }
5569#endif
5570#ifdef TARGET_NR_clock_getres
5571 case TARGET_NR_clock_getres:
5572 {
5573 struct timespec ts;
5574 ret = get_errno(clock_getres(arg1, &ts));
5575 if (!is_error(ret)) {
5576 host_to_target_timespec(arg2, &ts);
5577 }
5578 break;
5579 }
5580#endif
pbrook63d76512008-05-29 13:43:29 +00005581#ifdef TARGET_NR_clock_nanosleep
5582 case TARGET_NR_clock_nanosleep:
5583 {
5584 struct timespec ts;
5585 target_to_host_timespec(&ts, arg3);
5586 ret = get_errno(clock_nanosleep(arg1, arg2, &ts, arg4 ? &ts : NULL));
5587 if (arg4)
5588 host_to_target_timespec(arg4, &ts);
5589 break;
5590 }
5591#endif
thsb5906f92007-03-19 13:32:45 +00005592
ths6f5b89a2007-03-02 20:48:00 +00005593#if defined(TARGET_NR_set_tid_address) && defined(__NR_set_tid_address)
5594 case TARGET_NR_set_tid_address:
bellard579a97f2007-11-11 14:26:47 +00005595 ret = get_errno(set_tid_address((int *)g2h(arg1)));
5596 break;
ths6f5b89a2007-03-02 20:48:00 +00005597#endif
5598
ths3ae43202007-09-16 21:39:48 +00005599#if defined(TARGET_NR_tkill) && defined(__NR_tkill)
ths4cae1d12007-07-12 11:06:53 +00005600 case TARGET_NR_tkill:
pbrook4cb05962008-05-30 18:05:19 +00005601 ret = get_errno(sys_tkill((int)arg1, target_to_host_signal(arg2)));
ths4cae1d12007-07-12 11:06:53 +00005602 break;
5603#endif
5604
ths3ae43202007-09-16 21:39:48 +00005605#if defined(TARGET_NR_tgkill) && defined(__NR_tgkill)
ths71455572007-06-21 21:45:30 +00005606 case TARGET_NR_tgkill:
pbrook4cb05962008-05-30 18:05:19 +00005607 ret = get_errno(sys_tgkill((int)arg1, (int)arg2,
5608 target_to_host_signal(arg3)));
ths71455572007-06-21 21:45:30 +00005609 break;
5610#endif
5611
ths4f2b1fe2007-06-21 21:57:12 +00005612#ifdef TARGET_NR_set_robust_list
5613 case TARGET_NR_set_robust_list:
5614 goto unimplemented_nowarn;
5615#endif
5616
ths9007f0e2007-09-25 17:50:37 +00005617#if defined(TARGET_NR_utimensat) && defined(__NR_utimensat)
5618 case TARGET_NR_utimensat:
5619 {
5620 struct timespec ts[2];
5621 target_to_host_timespec(ts, arg3);
5622 target_to_host_timespec(ts+1, arg3+sizeof(struct target_timespec));
5623 if (!arg2)
5624 ret = get_errno(sys_utimensat(arg1, NULL, ts, arg4));
5625 else {
bellard579a97f2007-11-11 14:26:47 +00005626 if (!(p = lock_user_string(arg2))) {
ths0da46a62007-10-20 20:23:07 +00005627 ret = -TARGET_EFAULT;
bellard579a97f2007-11-11 14:26:47 +00005628 goto fail;
5629 }
5630 ret = get_errno(sys_utimensat(arg1, path(p), ts, arg4));
5631 unlock_user(p, arg2, 0);
ths9007f0e2007-09-25 17:50:37 +00005632 }
5633 }
5634 break;
5635#endif
pbrookbd0c5662008-05-29 14:34:11 +00005636#if defined(USE_NPTL)
5637 case TARGET_NR_futex:
5638 ret = do_futex(arg1, arg2, arg3, arg4, arg5, arg6);
5639 break;
5640#endif
ths9007f0e2007-09-25 17:50:37 +00005641
bellard31e31b82003-02-18 22:55:36 +00005642 default:
5643 unimplemented:
bellard5cd43932003-03-29 16:54:36 +00005644 gemu_log("qemu: Unsupported syscall: %d\n", num);
ths4f2b1fe2007-06-21 21:57:12 +00005645#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 +00005646 unimplemented_nowarn:
bellard80a9d032005-01-03 23:31:27 +00005647#endif
ths0da46a62007-10-20 20:23:07 +00005648 ret = -TARGET_ENOSYS;
bellard31e31b82003-02-18 22:55:36 +00005649 break;
5650 }
bellard579a97f2007-11-11 14:26:47 +00005651fail:
bellardc573ff62004-01-04 15:51:36 +00005652#ifdef DEBUG
5653 gemu_log(" = %ld\n", ret);
5654#endif
thsb92c47c2007-11-01 00:07:38 +00005655 if(do_strace)
5656 print_syscall_ret(num, ret);
bellard31e31b82003-02-18 22:55:36 +00005657 return ret;
bellard579a97f2007-11-11 14:26:47 +00005658efault:
5659 ret = -TARGET_EFAULT;
5660 goto fail;
bellard31e31b82003-02-18 22:55:36 +00005661}