blob: cd90946aeb2bf26a8fc0727ef21a917cd56e250c [file] [log] [blame]
bellard31e31b82003-02-18 22:55:36 +00001/*
2 * Linux syscalls
ths5fafdf22007-09-16 21:08:06 +00003 *
bellard31e31b82003-02-18 22:55:36 +00004 * Copyright (c) 2003 Fabrice Bellard
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20#include <stdlib.h>
21#include <stdio.h>
22#include <stdarg.h>
bellard04369ff2003-03-20 22:33:23 +000023#include <string.h>
bellard31e31b82003-02-18 22:55:36 +000024#include <elf.h>
25#include <endian.h>
26#include <errno.h>
27#include <unistd.h>
28#include <fcntl.h>
bellard7854b052003-03-29 17:22:23 +000029#include <time.h>
pbrook82e671d2008-06-09 12:10:22 +000030#include <limits.h>
bellard31e31b82003-02-18 22:55:36 +000031#include <sys/types.h>
thsd08d3bb2007-03-19 13:09:22 +000032#include <sys/ipc.h>
33#include <sys/msg.h>
bellard31e31b82003-02-18 22:55:36 +000034#include <sys/wait.h>
35#include <sys/time.h>
36#include <sys/stat.h>
37#include <sys/mount.h>
ths39b9aae2007-02-11 18:36:44 +000038#include <sys/prctl.h>
bellard31e31b82003-02-18 22:55:36 +000039#include <sys/resource.h>
40#include <sys/mman.h>
41#include <sys/swap.h>
42#include <signal.h>
43#include <sched.h>
44#include <sys/socket.h>
45#include <sys/uio.h>
bellard9de5e442003-03-23 16:49:39 +000046#include <sys/poll.h>
bellard32f36bc2003-03-30 21:29:48 +000047#include <sys/times.h>
bellard8853f862004-02-22 14:57:26 +000048#include <sys/shm.h>
thsfa294812007-02-02 22:05:00 +000049#include <sys/sem.h>
bellard56c8f682005-11-28 22:28:41 +000050#include <sys/statfs.h>
bellardebc05482003-09-30 21:08:41 +000051#include <utime.h>
bellarda5448a72004-06-19 16:59:03 +000052#include <sys/sysinfo.h>
bellard72f03902003-02-18 23:33:18 +000053//#include <sys/user.h>
bellard8853f862004-02-22 14:57:26 +000054#include <netinet/ip.h>
bellard7854b052003-03-29 17:22:23 +000055#include <netinet/tcp.h>
bellard31e31b82003-02-18 22:55:36 +000056
57#define termios host_termios
58#define winsize host_winsize
59#define termio host_termio
bellard04369ff2003-03-20 22:33:23 +000060#define sgttyb host_sgttyb /* same as target */
61#define tchars host_tchars /* same as target */
62#define ltchars host_ltchars /* same as target */
bellard31e31b82003-02-18 22:55:36 +000063
64#include <linux/termios.h>
65#include <linux/unistd.h>
66#include <linux/utsname.h>
67#include <linux/cdrom.h>
68#include <linux/hdreg.h>
69#include <linux/soundcard.h>
bellarddab2ed92003-03-22 15:23:14 +000070#include <linux/dirent.h>
bellard19b84f32003-05-08 15:41:49 +000071#include <linux/kd.h>
pbrookd7e40362008-05-23 16:06:43 +000072#include "linux_loop.h"
bellard31e31b82003-02-18 22:55:36 +000073
bellard3ef693a2003-03-23 20:17:16 +000074#include "qemu.h"
bellard31e31b82003-02-18 22:55:36 +000075
pbrook30813ce2008-06-02 15:45:44 +000076#if defined(USE_NPTL)
77#include <linux/futex.h>
pbrookd865bab2008-06-07 22:12:17 +000078#define CLONE_NPTL_FLAGS2 (CLONE_SETTLS | \
79 CLONE_PARENT_SETTID | CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID)
80#else
81/* XXX: Hardcode the above values. */
82#define CLONE_NPTL_FLAGS2 0
pbrook30813ce2008-06-02 15:45:44 +000083#endif
84
bellard72f03902003-02-18 23:33:18 +000085//#define DEBUG
bellard31e31b82003-02-18 22:55:36 +000086
pbrooke6e59062006-10-22 00:18:54 +000087#if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_SPARC) \
ths48733d12007-10-08 13:36:46 +000088 || defined(TARGET_M68K) || defined(TARGET_SH4) || defined(TARGET_CRIS)
bellard67867302003-11-23 17:05:30 +000089/* 16 bit uid wrappers emulation */
90#define USE_UID16
91#endif
92
bellard1a9353d2003-03-16 20:28:50 +000093//#include <linux/msdos_fs.h>
94#define VFAT_IOCTL_READDIR_BOTH _IOR('r', 1, struct dirent [2])
95#define VFAT_IOCTL_READDIR_SHORT _IOR('r', 2, struct dirent [2])
96
bellard70a194b2003-08-11 22:20:16 +000097
bellard70a194b2003-08-11 22:20:16 +000098#undef _syscall0
99#undef _syscall1
100#undef _syscall2
101#undef _syscall3
102#undef _syscall4
103#undef _syscall5
bellard83fcb512006-06-14 13:37:16 +0000104#undef _syscall6
bellard70a194b2003-08-11 22:20:16 +0000105
bellard83fcb512006-06-14 13:37:16 +0000106#define _syscall0(type,name) \
107type name (void) \
108{ \
109 return syscall(__NR_##name); \
bellard70a194b2003-08-11 22:20:16 +0000110}
111
bellard83fcb512006-06-14 13:37:16 +0000112#define _syscall1(type,name,type1,arg1) \
113type name (type1 arg1) \
114{ \
115 return syscall(__NR_##name, arg1); \
bellard70a194b2003-08-11 22:20:16 +0000116}
117
bellard83fcb512006-06-14 13:37:16 +0000118#define _syscall2(type,name,type1,arg1,type2,arg2) \
119type name (type1 arg1,type2 arg2) \
120{ \
121 return syscall(__NR_##name, arg1, arg2); \
bellard70a194b2003-08-11 22:20:16 +0000122}
123
bellard83fcb512006-06-14 13:37:16 +0000124#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \
125type name (type1 arg1,type2 arg2,type3 arg3) \
126{ \
127 return syscall(__NR_##name, arg1, arg2, arg3); \
bellard70a194b2003-08-11 22:20:16 +0000128}
129
bellard83fcb512006-06-14 13:37:16 +0000130#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \
131type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4) \
132{ \
133 return syscall(__NR_##name, arg1, arg2, arg3, arg4); \
bellard70a194b2003-08-11 22:20:16 +0000134}
135
bellard83fcb512006-06-14 13:37:16 +0000136#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
137 type5,arg5) \
138type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \
139{ \
140 return syscall(__NR_##name, arg1, arg2, arg3, arg4, arg5); \
bellard70a194b2003-08-11 22:20:16 +0000141}
bellard83fcb512006-06-14 13:37:16 +0000142
143
144#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
145 type5,arg5,type6,arg6) \
146type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5,type6 arg6) \
147{ \
148 return syscall(__NR_##name, arg1, arg2, arg3, arg4, arg5, arg6); \
149}
150
bellard70a194b2003-08-11 22:20:16 +0000151
bellard31e31b82003-02-18 22:55:36 +0000152#define __NR_sys_uname __NR_uname
ths92a34c12007-09-24 09:27:49 +0000153#define __NR_sys_faccessat __NR_faccessat
ths814d7972007-09-24 09:26:51 +0000154#define __NR_sys_fchmodat __NR_fchmodat
thsccfa72b2007-09-24 09:23:34 +0000155#define __NR_sys_fchownat __NR_fchownat
bellard72f03902003-02-18 23:33:18 +0000156#define __NR_sys_getcwd1 __NR_getcwd
bellard72f03902003-02-18 23:33:18 +0000157#define __NR_sys_getdents __NR_getdents
bellarddab2ed92003-03-22 15:23:14 +0000158#define __NR_sys_getdents64 __NR_getdents64
thsc6cda172007-10-09 03:42:34 +0000159#define __NR_sys_getpriority __NR_getpriority
ths64f0ce42007-09-24 09:25:06 +0000160#define __NR_sys_linkat __NR_linkat
ths4472ad02007-09-24 09:22:32 +0000161#define __NR_sys_mkdirat __NR_mkdirat
ths75ac37a2007-09-24 09:23:05 +0000162#define __NR_sys_mknodat __NR_mknodat
ths82424832007-09-24 09:21:55 +0000163#define __NR_sys_openat __NR_openat
ths5e0ccb12007-09-24 09:26:10 +0000164#define __NR_sys_readlinkat __NR_readlinkat
ths722183f2007-09-24 09:24:37 +0000165#define __NR_sys_renameat __NR_renameat
bellard66fb9762003-03-23 01:06:05 +0000166#define __NR_sys_rt_sigqueueinfo __NR_rt_sigqueueinfo
thsf0b62432007-09-24 09:25:40 +0000167#define __NR_sys_symlinkat __NR_symlinkat
ths7494b0f2007-02-11 18:26:53 +0000168#define __NR_sys_syslog __NR_syslog
ths71455572007-06-21 21:45:30 +0000169#define __NR_sys_tgkill __NR_tgkill
ths4cae1d12007-07-12 11:06:53 +0000170#define __NR_sys_tkill __NR_tkill
ths8170f562007-09-24 09:24:11 +0000171#define __NR_sys_unlinkat __NR_unlinkat
ths9007f0e2007-09-25 17:50:37 +0000172#define __NR_sys_utimensat __NR_utimensat
pbrookbd0c5662008-05-29 14:34:11 +0000173#define __NR_sys_futex __NR_futex
bellard31e31b82003-02-18 22:55:36 +0000174
bellardbc51c5c2004-03-17 23:46:04 +0000175#if defined(__alpha__) || defined (__ia64__) || defined(__x86_64__)
bellard9af9eaa2003-04-07 21:34:41 +0000176#define __NR__llseek __NR_lseek
177#endif
178
bellard72f03902003-02-18 23:33:18 +0000179#ifdef __NR_gettid
bellard31e31b82003-02-18 22:55:36 +0000180_syscall0(int, gettid)
bellard72f03902003-02-18 23:33:18 +0000181#else
ths0da46a62007-10-20 20:23:07 +0000182/* This is a replacement for the host gettid() and must return a host
183 errno. */
bellard72f03902003-02-18 23:33:18 +0000184static int gettid(void) {
185 return -ENOSYS;
186}
187#endif
bellard31e31b82003-02-18 22:55:36 +0000188_syscall1(int,sys_uname,struct new_utsname *,buf)
ths92a34c12007-09-24 09:27:49 +0000189#if defined(TARGET_NR_faccessat) && defined(__NR_faccessat)
190_syscall4(int,sys_faccessat,int,dirfd,const char *,pathname,int,mode,int,flags)
191#endif
ths814d7972007-09-24 09:26:51 +0000192#if defined(TARGET_NR_fchmodat) && defined(__NR_fchmodat)
193_syscall4(int,sys_fchmodat,int,dirfd,const char *,pathname,
194 mode_t,mode,int,flags)
195#endif
thsccfa72b2007-09-24 09:23:34 +0000196#if defined(TARGET_NR_fchownat) && defined(__NR_fchownat)
197_syscall5(int,sys_fchownat,int,dirfd,const char *,pathname,
198 uid_t,owner,gid_t,group,int,flags)
199#endif
bellard72f03902003-02-18 23:33:18 +0000200_syscall2(int,sys_getcwd1,char *,buf,size_t,size)
201_syscall3(int, sys_getdents, uint, fd, struct dirent *, dirp, uint, count);
ths3ae43202007-09-16 21:39:48 +0000202#if defined(TARGET_NR_getdents64) && defined(__NR_getdents64)
bellarddab2ed92003-03-22 15:23:14 +0000203_syscall3(int, sys_getdents64, uint, fd, struct dirent64 *, dirp, uint, count);
ths3ae43202007-09-16 21:39:48 +0000204#endif
thsc6cda172007-10-09 03:42:34 +0000205_syscall2(int, sys_getpriority, int, which, int, who);
bellard31e31b82003-02-18 22:55:36 +0000206_syscall5(int, _llseek, uint, fd, ulong, hi, ulong, lo,
207 loff_t *, res, uint, wh);
ths64f0ce42007-09-24 09:25:06 +0000208#if defined(TARGET_NR_linkat) && defined(__NR_linkat)
209_syscall5(int,sys_linkat,int,olddirfd,const char *,oldpath,
210 int,newdirfd,const char *,newpath,int,flags)
211#endif
ths4472ad02007-09-24 09:22:32 +0000212#if defined(TARGET_NR_mkdirat) && defined(__NR_mkdirat)
213_syscall3(int,sys_mkdirat,int,dirfd,const char *,pathname,mode_t,mode)
214#endif
ths75ac37a2007-09-24 09:23:05 +0000215#if defined(TARGET_NR_mknodat) && defined(__NR_mknodat)
216_syscall4(int,sys_mknodat,int,dirfd,const char *,pathname,
217 mode_t,mode,dev_t,dev)
218#endif
ths82424832007-09-24 09:21:55 +0000219#if defined(TARGET_NR_openat) && defined(__NR_openat)
220_syscall4(int,sys_openat,int,dirfd,const char *,pathname,int,flags,mode_t,mode)
221#endif
ths5e0ccb12007-09-24 09:26:10 +0000222#if defined(TARGET_NR_readlinkat) && defined(__NR_readlinkat)
223_syscall4(int,sys_readlinkat,int,dirfd,const char *,pathname,
224 char *,buf,size_t,bufsize)
225#endif
ths722183f2007-09-24 09:24:37 +0000226#if defined(TARGET_NR_renameat) && defined(__NR_renameat)
227_syscall4(int,sys_renameat,int,olddirfd,const char *,oldpath,
228 int,newdirfd,const char *,newpath)
229#endif
bellard66fb9762003-03-23 01:06:05 +0000230_syscall3(int,sys_rt_sigqueueinfo,int,pid,int,sig,siginfo_t *,uinfo)
thsb51eaa82007-09-25 16:09:22 +0000231#if defined(TARGET_NR_symlinkat) && defined(__NR_symlinkat)
thsf0b62432007-09-24 09:25:40 +0000232_syscall3(int,sys_symlinkat,const char *,oldpath,
233 int,newdirfd,const char *,newpath)
234#endif
ths7494b0f2007-02-11 18:26:53 +0000235_syscall3(int,sys_syslog,int,type,char*,bufp,int,len)
ths3ae43202007-09-16 21:39:48 +0000236#if defined(TARGET_NR_tgkill) && defined(__NR_tgkill)
ths71455572007-06-21 21:45:30 +0000237_syscall3(int,sys_tgkill,int,tgid,int,pid,int,sig)
ths4cae1d12007-07-12 11:06:53 +0000238#endif
ths3ae43202007-09-16 21:39:48 +0000239#if defined(TARGET_NR_tkill) && defined(__NR_tkill)
ths4cae1d12007-07-12 11:06:53 +0000240_syscall2(int,sys_tkill,int,tid,int,sig)
241#endif
bellardec86b0f2003-04-11 00:15:04 +0000242#ifdef __NR_exit_group
243_syscall1(int,exit_group,int,error_code)
244#endif
ths6f5b89a2007-03-02 20:48:00 +0000245#if defined(TARGET_NR_set_tid_address) && defined(__NR_set_tid_address)
246_syscall1(int,set_tid_address,int *,tidptr)
247#endif
ths8170f562007-09-24 09:24:11 +0000248#if defined(TARGET_NR_unlinkat) && defined(__NR_unlinkat)
249_syscall3(int,sys_unlinkat,int,dirfd,const char *,pathname,int,flags)
250#endif
ths9007f0e2007-09-25 17:50:37 +0000251#if defined(TARGET_NR_utimensat) && defined(__NR_utimensat)
252_syscall4(int,sys_utimensat,int,dirfd,const char *,pathname,
253 const struct timespec *,tsp,int,flags)
254#endif
pbrookbd0c5662008-05-29 14:34:11 +0000255#if defined(TARGET_NR_futex) && defined(__NR_futex)
256_syscall6(int,sys_futex,int *,uaddr,int,op,int,val,
257 const struct timespec *,timeout,int *,uaddr2,int,val3)
258
259#endif
bellard66fb9762003-03-23 01:06:05 +0000260
261extern int personality(int);
bellard9de5e442003-03-23 16:49:39 +0000262extern int flock(int, int);
263extern int setfsuid(int);
264extern int setfsgid(int);
bellard5cd43932003-03-29 16:54:36 +0000265extern int setresuid(uid_t, uid_t, uid_t);
266extern int getresuid(uid_t *, uid_t *, uid_t *);
267extern int setresgid(gid_t, gid_t, gid_t);
268extern int getresgid(gid_t *, gid_t *, gid_t *);
bellard19b84f32003-05-08 15:41:49 +0000269extern int setgroups(int, gid_t *);
bellard31e31b82003-02-18 22:55:36 +0000270
thsb92c47c2007-11-01 00:07:38 +0000271#define ERRNO_TABLE_SIZE 1200
272
273/* target_to_host_errno_table[] is initialized from
274 * host_to_target_errno_table[] in syscall_init(). */
275static uint16_t target_to_host_errno_table[ERRNO_TABLE_SIZE] = {
276};
277
ths637947f2007-06-01 12:09:19 +0000278/*
thsfe8f0962007-07-12 10:59:21 +0000279 * This list is the union of errno values overridden in asm-<arch>/errno.h
ths637947f2007-06-01 12:09:19 +0000280 * minus the errnos that are not actually generic to all archs.
281 */
thsb92c47c2007-11-01 00:07:38 +0000282static uint16_t host_to_target_errno_table[ERRNO_TABLE_SIZE] = {
ths637947f2007-06-01 12:09:19 +0000283 [EIDRM] = TARGET_EIDRM,
284 [ECHRNG] = TARGET_ECHRNG,
285 [EL2NSYNC] = TARGET_EL2NSYNC,
286 [EL3HLT] = TARGET_EL3HLT,
287 [EL3RST] = TARGET_EL3RST,
288 [ELNRNG] = TARGET_ELNRNG,
289 [EUNATCH] = TARGET_EUNATCH,
290 [ENOCSI] = TARGET_ENOCSI,
291 [EL2HLT] = TARGET_EL2HLT,
292 [EDEADLK] = TARGET_EDEADLK,
293 [ENOLCK] = TARGET_ENOLCK,
294 [EBADE] = TARGET_EBADE,
295 [EBADR] = TARGET_EBADR,
296 [EXFULL] = TARGET_EXFULL,
297 [ENOANO] = TARGET_ENOANO,
298 [EBADRQC] = TARGET_EBADRQC,
299 [EBADSLT] = TARGET_EBADSLT,
300 [EBFONT] = TARGET_EBFONT,
301 [ENOSTR] = TARGET_ENOSTR,
302 [ENODATA] = TARGET_ENODATA,
303 [ETIME] = TARGET_ETIME,
304 [ENOSR] = TARGET_ENOSR,
305 [ENONET] = TARGET_ENONET,
306 [ENOPKG] = TARGET_ENOPKG,
307 [EREMOTE] = TARGET_EREMOTE,
308 [ENOLINK] = TARGET_ENOLINK,
309 [EADV] = TARGET_EADV,
310 [ESRMNT] = TARGET_ESRMNT,
311 [ECOMM] = TARGET_ECOMM,
312 [EPROTO] = TARGET_EPROTO,
313 [EDOTDOT] = TARGET_EDOTDOT,
314 [EMULTIHOP] = TARGET_EMULTIHOP,
315 [EBADMSG] = TARGET_EBADMSG,
316 [ENAMETOOLONG] = TARGET_ENAMETOOLONG,
317 [EOVERFLOW] = TARGET_EOVERFLOW,
318 [ENOTUNIQ] = TARGET_ENOTUNIQ,
319 [EBADFD] = TARGET_EBADFD,
320 [EREMCHG] = TARGET_EREMCHG,
321 [ELIBACC] = TARGET_ELIBACC,
322 [ELIBBAD] = TARGET_ELIBBAD,
323 [ELIBSCN] = TARGET_ELIBSCN,
324 [ELIBMAX] = TARGET_ELIBMAX,
325 [ELIBEXEC] = TARGET_ELIBEXEC,
326 [EILSEQ] = TARGET_EILSEQ,
327 [ENOSYS] = TARGET_ENOSYS,
328 [ELOOP] = TARGET_ELOOP,
329 [ERESTART] = TARGET_ERESTART,
330 [ESTRPIPE] = TARGET_ESTRPIPE,
331 [ENOTEMPTY] = TARGET_ENOTEMPTY,
332 [EUSERS] = TARGET_EUSERS,
333 [ENOTSOCK] = TARGET_ENOTSOCK,
334 [EDESTADDRREQ] = TARGET_EDESTADDRREQ,
335 [EMSGSIZE] = TARGET_EMSGSIZE,
336 [EPROTOTYPE] = TARGET_EPROTOTYPE,
337 [ENOPROTOOPT] = TARGET_ENOPROTOOPT,
338 [EPROTONOSUPPORT] = TARGET_EPROTONOSUPPORT,
339 [ESOCKTNOSUPPORT] = TARGET_ESOCKTNOSUPPORT,
340 [EOPNOTSUPP] = TARGET_EOPNOTSUPP,
341 [EPFNOSUPPORT] = TARGET_EPFNOSUPPORT,
342 [EAFNOSUPPORT] = TARGET_EAFNOSUPPORT,
343 [EADDRINUSE] = TARGET_EADDRINUSE,
344 [EADDRNOTAVAIL] = TARGET_EADDRNOTAVAIL,
345 [ENETDOWN] = TARGET_ENETDOWN,
346 [ENETUNREACH] = TARGET_ENETUNREACH,
347 [ENETRESET] = TARGET_ENETRESET,
348 [ECONNABORTED] = TARGET_ECONNABORTED,
349 [ECONNRESET] = TARGET_ECONNRESET,
350 [ENOBUFS] = TARGET_ENOBUFS,
351 [EISCONN] = TARGET_EISCONN,
352 [ENOTCONN] = TARGET_ENOTCONN,
353 [EUCLEAN] = TARGET_EUCLEAN,
354 [ENOTNAM] = TARGET_ENOTNAM,
355 [ENAVAIL] = TARGET_ENAVAIL,
356 [EISNAM] = TARGET_EISNAM,
357 [EREMOTEIO] = TARGET_EREMOTEIO,
358 [ESHUTDOWN] = TARGET_ESHUTDOWN,
359 [ETOOMANYREFS] = TARGET_ETOOMANYREFS,
360 [ETIMEDOUT] = TARGET_ETIMEDOUT,
361 [ECONNREFUSED] = TARGET_ECONNREFUSED,
362 [EHOSTDOWN] = TARGET_EHOSTDOWN,
363 [EHOSTUNREACH] = TARGET_EHOSTUNREACH,
364 [EALREADY] = TARGET_EALREADY,
365 [EINPROGRESS] = TARGET_EINPROGRESS,
366 [ESTALE] = TARGET_ESTALE,
367 [ECANCELED] = TARGET_ECANCELED,
368 [ENOMEDIUM] = TARGET_ENOMEDIUM,
369 [EMEDIUMTYPE] = TARGET_EMEDIUMTYPE,
thsb7fe5db2007-07-23 15:37:46 +0000370#ifdef ENOKEY
ths637947f2007-06-01 12:09:19 +0000371 [ENOKEY] = TARGET_ENOKEY,
thsb7fe5db2007-07-23 15:37:46 +0000372#endif
373#ifdef EKEYEXPIRED
ths637947f2007-06-01 12:09:19 +0000374 [EKEYEXPIRED] = TARGET_EKEYEXPIRED,
thsb7fe5db2007-07-23 15:37:46 +0000375#endif
376#ifdef EKEYREVOKED
ths637947f2007-06-01 12:09:19 +0000377 [EKEYREVOKED] = TARGET_EKEYREVOKED,
thsb7fe5db2007-07-23 15:37:46 +0000378#endif
379#ifdef EKEYREJECTED
ths637947f2007-06-01 12:09:19 +0000380 [EKEYREJECTED] = TARGET_EKEYREJECTED,
thsb7fe5db2007-07-23 15:37:46 +0000381#endif
382#ifdef EOWNERDEAD
ths637947f2007-06-01 12:09:19 +0000383 [EOWNERDEAD] = TARGET_EOWNERDEAD,
thsb7fe5db2007-07-23 15:37:46 +0000384#endif
385#ifdef ENOTRECOVERABLE
ths637947f2007-06-01 12:09:19 +0000386 [ENOTRECOVERABLE] = TARGET_ENOTRECOVERABLE,
thsb7fe5db2007-07-23 15:37:46 +0000387#endif
thsb92c47c2007-11-01 00:07:38 +0000388};
ths637947f2007-06-01 12:09:19 +0000389
390static inline int host_to_target_errno(int err)
391{
392 if(host_to_target_errno_table[err])
393 return host_to_target_errno_table[err];
394 return err;
395}
396
thsb92c47c2007-11-01 00:07:38 +0000397static inline int target_to_host_errno(int err)
398{
399 if (target_to_host_errno_table[err])
400 return target_to_host_errno_table[err];
401 return err;
402}
403
blueswir1992f48a2007-10-14 16:27:31 +0000404static inline abi_long get_errno(abi_long ret)
bellard31e31b82003-02-18 22:55:36 +0000405{
406 if (ret == -1)
ths637947f2007-06-01 12:09:19 +0000407 return -host_to_target_errno(errno);
bellard31e31b82003-02-18 22:55:36 +0000408 else
409 return ret;
410}
411
blueswir1992f48a2007-10-14 16:27:31 +0000412static inline int is_error(abi_long ret)
bellard31e31b82003-02-18 22:55:36 +0000413{
blueswir1992f48a2007-10-14 16:27:31 +0000414 return (abi_ulong)ret >= (abi_ulong)(-4096);
bellard31e31b82003-02-18 22:55:36 +0000415}
416
thsb92c47c2007-11-01 00:07:38 +0000417char *target_strerror(int err)
418{
419 return strerror(target_to_host_errno(err));
420}
421
blueswir1992f48a2007-10-14 16:27:31 +0000422static abi_ulong target_brk;
423static abi_ulong target_original_brk;
bellard31e31b82003-02-18 22:55:36 +0000424
blueswir1992f48a2007-10-14 16:27:31 +0000425void target_set_brk(abi_ulong new_brk)
bellard31e31b82003-02-18 22:55:36 +0000426{
blueswir14c1de732007-07-07 20:45:44 +0000427 target_original_brk = target_brk = HOST_PAGE_ALIGN(new_brk);
bellard31e31b82003-02-18 22:55:36 +0000428}
429
ths0da46a62007-10-20 20:23:07 +0000430/* do_brk() must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +0000431abi_long do_brk(abi_ulong new_brk)
bellard31e31b82003-02-18 22:55:36 +0000432{
blueswir1992f48a2007-10-14 16:27:31 +0000433 abi_ulong brk_page;
434 abi_long mapped_addr;
bellard31e31b82003-02-18 22:55:36 +0000435 int new_alloc_size;
436
437 if (!new_brk)
pbrook53a59602006-03-25 19:31:22 +0000438 return target_brk;
bellard31e31b82003-02-18 22:55:36 +0000439 if (new_brk < target_original_brk)
balrog7ab240a2008-04-26 12:17:34 +0000440 return target_brk;
ths3b46e622007-09-17 08:09:54 +0000441
pbrook53a59602006-03-25 19:31:22 +0000442 brk_page = HOST_PAGE_ALIGN(target_brk);
bellard31e31b82003-02-18 22:55:36 +0000443
444 /* If the new brk is less than this, set it and we're done... */
445 if (new_brk < brk_page) {
446 target_brk = new_brk;
pbrook53a59602006-03-25 19:31:22 +0000447 return target_brk;
bellard31e31b82003-02-18 22:55:36 +0000448 }
449
450 /* We need to allocate more memory after the brk... */
bellard54936002003-05-13 00:25:15 +0000451 new_alloc_size = HOST_PAGE_ALIGN(new_brk - brk_page + 1);
ths5fafdf22007-09-16 21:08:06 +0000452 mapped_addr = get_errno(target_mmap(brk_page, new_alloc_size,
bellard54936002003-05-13 00:25:15 +0000453 PROT_READ|PROT_WRITE,
454 MAP_ANON|MAP_FIXED|MAP_PRIVATE, 0, 0));
balrog7ab240a2008-04-26 12:17:34 +0000455
456 if (!is_error(mapped_addr))
bellard31e31b82003-02-18 22:55:36 +0000457 target_brk = new_brk;
balrog7ab240a2008-04-26 12:17:34 +0000458
459 return target_brk;
bellard31e31b82003-02-18 22:55:36 +0000460}
461
ths26edcf42007-12-09 02:25:24 +0000462static inline abi_long copy_from_user_fdset(fd_set *fds,
463 abi_ulong target_fds_addr,
464 int n)
bellard31e31b82003-02-18 22:55:36 +0000465{
ths26edcf42007-12-09 02:25:24 +0000466 int i, nw, j, k;
467 abi_ulong b, *target_fds;
468
469 nw = (n + TARGET_ABI_BITS - 1) / TARGET_ABI_BITS;
470 if (!(target_fds = lock_user(VERIFY_READ,
471 target_fds_addr,
472 sizeof(abi_ulong) * nw,
473 1)))
474 return -TARGET_EFAULT;
475
476 FD_ZERO(fds);
477 k = 0;
478 for (i = 0; i < nw; i++) {
479 /* grab the abi_ulong */
480 __get_user(b, &target_fds[i]);
481 for (j = 0; j < TARGET_ABI_BITS; j++) {
482 /* check the bit inside the abi_ulong */
483 if ((b >> j) & 1)
484 FD_SET(k, fds);
485 k++;
bellard31e31b82003-02-18 22:55:36 +0000486 }
bellard31e31b82003-02-18 22:55:36 +0000487 }
ths26edcf42007-12-09 02:25:24 +0000488
489 unlock_user(target_fds, target_fds_addr, 0);
490
491 return 0;
bellard31e31b82003-02-18 22:55:36 +0000492}
493
ths26edcf42007-12-09 02:25:24 +0000494static inline abi_long copy_to_user_fdset(abi_ulong target_fds_addr,
495 const fd_set *fds,
496 int n)
bellard31e31b82003-02-18 22:55:36 +0000497{
bellard31e31b82003-02-18 22:55:36 +0000498 int i, nw, j, k;
blueswir1992f48a2007-10-14 16:27:31 +0000499 abi_long v;
ths26edcf42007-12-09 02:25:24 +0000500 abi_ulong *target_fds;
bellard31e31b82003-02-18 22:55:36 +0000501
ths26edcf42007-12-09 02:25:24 +0000502 nw = (n + TARGET_ABI_BITS - 1) / TARGET_ABI_BITS;
503 if (!(target_fds = lock_user(VERIFY_WRITE,
504 target_fds_addr,
505 sizeof(abi_ulong) * nw,
506 0)))
507 return -TARGET_EFAULT;
508
509 k = 0;
510 for (i = 0; i < nw; i++) {
511 v = 0;
512 for (j = 0; j < TARGET_ABI_BITS; j++) {
513 v |= ((FD_ISSET(k, fds) != 0) << j);
514 k++;
bellard31e31b82003-02-18 22:55:36 +0000515 }
ths26edcf42007-12-09 02:25:24 +0000516 __put_user(v, &target_fds[i]);
bellard31e31b82003-02-18 22:55:36 +0000517 }
ths26edcf42007-12-09 02:25:24 +0000518
519 unlock_user(target_fds, target_fds_addr, sizeof(abi_ulong) * nw);
520
521 return 0;
bellard31e31b82003-02-18 22:55:36 +0000522}
523
bellardc596ed12003-07-13 17:32:31 +0000524#if defined(__alpha__)
525#define HOST_HZ 1024
526#else
527#define HOST_HZ 100
528#endif
529
blueswir1992f48a2007-10-14 16:27:31 +0000530static inline abi_long host_to_target_clock_t(long ticks)
bellardc596ed12003-07-13 17:32:31 +0000531{
532#if HOST_HZ == TARGET_HZ
533 return ticks;
534#else
535 return ((int64_t)ticks * TARGET_HZ) / HOST_HZ;
536#endif
537}
538
bellard579a97f2007-11-11 14:26:47 +0000539static inline abi_long host_to_target_rusage(abi_ulong target_addr,
540 const struct rusage *rusage)
bellardb4091862003-05-16 15:39:34 +0000541{
pbrook53a59602006-03-25 19:31:22 +0000542 struct target_rusage *target_rusage;
543
bellard579a97f2007-11-11 14:26:47 +0000544 if (!lock_user_struct(VERIFY_WRITE, target_rusage, target_addr, 0))
545 return -TARGET_EFAULT;
bellardb4091862003-05-16 15:39:34 +0000546 target_rusage->ru_utime.tv_sec = tswapl(rusage->ru_utime.tv_sec);
547 target_rusage->ru_utime.tv_usec = tswapl(rusage->ru_utime.tv_usec);
548 target_rusage->ru_stime.tv_sec = tswapl(rusage->ru_stime.tv_sec);
549 target_rusage->ru_stime.tv_usec = tswapl(rusage->ru_stime.tv_usec);
550 target_rusage->ru_maxrss = tswapl(rusage->ru_maxrss);
551 target_rusage->ru_ixrss = tswapl(rusage->ru_ixrss);
552 target_rusage->ru_idrss = tswapl(rusage->ru_idrss);
553 target_rusage->ru_isrss = tswapl(rusage->ru_isrss);
554 target_rusage->ru_minflt = tswapl(rusage->ru_minflt);
555 target_rusage->ru_majflt = tswapl(rusage->ru_majflt);
556 target_rusage->ru_nswap = tswapl(rusage->ru_nswap);
557 target_rusage->ru_inblock = tswapl(rusage->ru_inblock);
558 target_rusage->ru_oublock = tswapl(rusage->ru_oublock);
559 target_rusage->ru_msgsnd = tswapl(rusage->ru_msgsnd);
560 target_rusage->ru_msgrcv = tswapl(rusage->ru_msgrcv);
561 target_rusage->ru_nsignals = tswapl(rusage->ru_nsignals);
562 target_rusage->ru_nvcsw = tswapl(rusage->ru_nvcsw);
563 target_rusage->ru_nivcsw = tswapl(rusage->ru_nivcsw);
pbrook53a59602006-03-25 19:31:22 +0000564 unlock_user_struct(target_rusage, target_addr, 1);
bellard579a97f2007-11-11 14:26:47 +0000565
566 return 0;
bellardb4091862003-05-16 15:39:34 +0000567}
568
ths788f5ec2007-12-09 02:37:05 +0000569static inline abi_long copy_from_user_timeval(struct timeval *tv,
570 abi_ulong target_tv_addr)
bellard31e31b82003-02-18 22:55:36 +0000571{
pbrook53a59602006-03-25 19:31:22 +0000572 struct target_timeval *target_tv;
573
ths788f5ec2007-12-09 02:37:05 +0000574 if (!lock_user_struct(VERIFY_READ, target_tv, target_tv_addr, 1))
bellard579a97f2007-11-11 14:26:47 +0000575 return -TARGET_EFAULT;
ths788f5ec2007-12-09 02:37:05 +0000576
577 __get_user(tv->tv_sec, &target_tv->tv_sec);
578 __get_user(tv->tv_usec, &target_tv->tv_usec);
579
580 unlock_user_struct(target_tv, target_tv_addr, 0);
bellard579a97f2007-11-11 14:26:47 +0000581
582 return 0;
bellard31e31b82003-02-18 22:55:36 +0000583}
584
ths788f5ec2007-12-09 02:37:05 +0000585static inline abi_long copy_to_user_timeval(abi_ulong target_tv_addr,
586 const struct timeval *tv)
bellard31e31b82003-02-18 22:55:36 +0000587{
pbrook53a59602006-03-25 19:31:22 +0000588 struct target_timeval *target_tv;
589
ths788f5ec2007-12-09 02:37:05 +0000590 if (!lock_user_struct(VERIFY_WRITE, target_tv, target_tv_addr, 0))
bellard579a97f2007-11-11 14:26:47 +0000591 return -TARGET_EFAULT;
ths788f5ec2007-12-09 02:37:05 +0000592
593 __put_user(tv->tv_sec, &target_tv->tv_sec);
594 __put_user(tv->tv_usec, &target_tv->tv_usec);
595
596 unlock_user_struct(target_tv, target_tv_addr, 1);
bellard579a97f2007-11-11 14:26:47 +0000597
598 return 0;
bellard31e31b82003-02-18 22:55:36 +0000599}
600
601
ths0da46a62007-10-20 20:23:07 +0000602/* do_select() must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +0000603static abi_long do_select(int n,
ths26edcf42007-12-09 02:25:24 +0000604 abi_ulong rfd_addr, abi_ulong wfd_addr,
605 abi_ulong efd_addr, abi_ulong target_tv_addr)
bellard31e31b82003-02-18 22:55:36 +0000606{
607 fd_set rfds, wfds, efds;
608 fd_set *rfds_ptr, *wfds_ptr, *efds_ptr;
609 struct timeval tv, *tv_ptr;
blueswir1992f48a2007-10-14 16:27:31 +0000610 abi_long ret;
bellard31e31b82003-02-18 22:55:36 +0000611
ths26edcf42007-12-09 02:25:24 +0000612 if (rfd_addr) {
613 if (copy_from_user_fdset(&rfds, rfd_addr, n))
614 return -TARGET_EFAULT;
615 rfds_ptr = &rfds;
pbrook53a59602006-03-25 19:31:22 +0000616 } else {
pbrook53a59602006-03-25 19:31:22 +0000617 rfds_ptr = NULL;
618 }
ths26edcf42007-12-09 02:25:24 +0000619 if (wfd_addr) {
620 if (copy_from_user_fdset(&wfds, wfd_addr, n))
621 return -TARGET_EFAULT;
622 wfds_ptr = &wfds;
pbrook53a59602006-03-25 19:31:22 +0000623 } else {
pbrook53a59602006-03-25 19:31:22 +0000624 wfds_ptr = NULL;
625 }
ths26edcf42007-12-09 02:25:24 +0000626 if (efd_addr) {
627 if (copy_from_user_fdset(&efds, efd_addr, n))
628 return -TARGET_EFAULT;
629 efds_ptr = &efds;
pbrook53a59602006-03-25 19:31:22 +0000630 } else {
pbrook53a59602006-03-25 19:31:22 +0000631 efds_ptr = NULL;
632 }
ths3b46e622007-09-17 08:09:54 +0000633
ths26edcf42007-12-09 02:25:24 +0000634 if (target_tv_addr) {
ths788f5ec2007-12-09 02:37:05 +0000635 if (copy_from_user_timeval(&tv, target_tv_addr))
636 return -TARGET_EFAULT;
bellard31e31b82003-02-18 22:55:36 +0000637 tv_ptr = &tv;
638 } else {
639 tv_ptr = NULL;
640 }
ths26edcf42007-12-09 02:25:24 +0000641
bellard31e31b82003-02-18 22:55:36 +0000642 ret = get_errno(select(n, rfds_ptr, wfds_ptr, efds_ptr, tv_ptr));
pbrook53a59602006-03-25 19:31:22 +0000643
ths26edcf42007-12-09 02:25:24 +0000644 if (!is_error(ret)) {
645 if (rfd_addr && copy_to_user_fdset(rfd_addr, &rfds, n))
646 return -TARGET_EFAULT;
647 if (wfd_addr && copy_to_user_fdset(wfd_addr, &wfds, n))
648 return -TARGET_EFAULT;
649 if (efd_addr && copy_to_user_fdset(efd_addr, &efds, n))
650 return -TARGET_EFAULT;
bellard31e31b82003-02-18 22:55:36 +0000651
ths788f5ec2007-12-09 02:37:05 +0000652 if (target_tv_addr && copy_to_user_timeval(target_tv_addr, &tv))
653 return -TARGET_EFAULT;
bellard31e31b82003-02-18 22:55:36 +0000654 }
bellard579a97f2007-11-11 14:26:47 +0000655
bellard31e31b82003-02-18 22:55:36 +0000656 return ret;
657}
658
bellard579a97f2007-11-11 14:26:47 +0000659static inline abi_long target_to_host_sockaddr(struct sockaddr *addr,
660 abi_ulong target_addr,
661 socklen_t len)
bellard7854b052003-03-29 17:22:23 +0000662{
pbrook53a59602006-03-25 19:31:22 +0000663 struct target_sockaddr *target_saddr;
664
bellard579a97f2007-11-11 14:26:47 +0000665 target_saddr = lock_user(VERIFY_READ, target_addr, len, 1);
666 if (!target_saddr)
667 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +0000668 memcpy(addr, target_saddr, len);
669 addr->sa_family = tswap16(target_saddr->sa_family);
670 unlock_user(target_saddr, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +0000671
672 return 0;
bellard7854b052003-03-29 17:22:23 +0000673}
674
bellard579a97f2007-11-11 14:26:47 +0000675static inline abi_long host_to_target_sockaddr(abi_ulong target_addr,
676 struct sockaddr *addr,
677 socklen_t len)
bellard7854b052003-03-29 17:22:23 +0000678{
pbrook53a59602006-03-25 19:31:22 +0000679 struct target_sockaddr *target_saddr;
680
bellard579a97f2007-11-11 14:26:47 +0000681 target_saddr = lock_user(VERIFY_WRITE, target_addr, len, 0);
682 if (!target_saddr)
683 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +0000684 memcpy(target_saddr, addr, len);
685 target_saddr->sa_family = tswap16(addr->sa_family);
686 unlock_user(target_saddr, target_addr, len);
bellard579a97f2007-11-11 14:26:47 +0000687
688 return 0;
bellard7854b052003-03-29 17:22:23 +0000689}
690
pbrook53a59602006-03-25 19:31:22 +0000691/* ??? Should this also swap msgh->name? */
bellard5a4a8982007-11-11 17:39:18 +0000692static inline abi_long target_to_host_cmsg(struct msghdr *msgh,
693 struct target_msghdr *target_msgh)
bellard7854b052003-03-29 17:22:23 +0000694{
695 struct cmsghdr *cmsg = CMSG_FIRSTHDR(msgh);
bellard5a4a8982007-11-11 17:39:18 +0000696 abi_long msg_controllen;
697 abi_ulong target_cmsg_addr;
698 struct target_cmsghdr *target_cmsg;
bellard7854b052003-03-29 17:22:23 +0000699 socklen_t space = 0;
bellard5a4a8982007-11-11 17:39:18 +0000700
701 msg_controllen = tswapl(target_msgh->msg_controllen);
702 if (msg_controllen < sizeof (struct target_cmsghdr))
703 goto the_end;
704 target_cmsg_addr = tswapl(target_msgh->msg_control);
705 target_cmsg = lock_user(VERIFY_READ, target_cmsg_addr, msg_controllen, 1);
706 if (!target_cmsg)
707 return -TARGET_EFAULT;
bellard7854b052003-03-29 17:22:23 +0000708
709 while (cmsg && target_cmsg) {
710 void *data = CMSG_DATA(cmsg);
711 void *target_data = TARGET_CMSG_DATA(target_cmsg);
712
ths5fafdf22007-09-16 21:08:06 +0000713 int len = tswapl(target_cmsg->cmsg_len)
bellard7854b052003-03-29 17:22:23 +0000714 - TARGET_CMSG_ALIGN(sizeof (struct target_cmsghdr));
715
716 space += CMSG_SPACE(len);
717 if (space > msgh->msg_controllen) {
718 space -= CMSG_SPACE(len);
bellard31febb72005-12-18 20:03:27 +0000719 gemu_log("Host cmsg overflow\n");
bellard7854b052003-03-29 17:22:23 +0000720 break;
721 }
722
723 cmsg->cmsg_level = tswap32(target_cmsg->cmsg_level);
724 cmsg->cmsg_type = tswap32(target_cmsg->cmsg_type);
725 cmsg->cmsg_len = CMSG_LEN(len);
726
bellard3532fa72006-06-24 15:06:03 +0000727 if (cmsg->cmsg_level != TARGET_SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS) {
bellard7854b052003-03-29 17:22:23 +0000728 gemu_log("Unsupported ancillary data: %d/%d\n", cmsg->cmsg_level, cmsg->cmsg_type);
729 memcpy(data, target_data, len);
730 } else {
731 int *fd = (int *)data;
732 int *target_fd = (int *)target_data;
733 int i, numfds = len / sizeof(int);
734
735 for (i = 0; i < numfds; i++)
736 fd[i] = tswap32(target_fd[i]);
737 }
738
739 cmsg = CMSG_NXTHDR(msgh, cmsg);
740 target_cmsg = TARGET_CMSG_NXTHDR(target_msgh, target_cmsg);
741 }
bellard5a4a8982007-11-11 17:39:18 +0000742 unlock_user(target_cmsg, target_cmsg_addr, 0);
743 the_end:
bellard7854b052003-03-29 17:22:23 +0000744 msgh->msg_controllen = space;
bellard5a4a8982007-11-11 17:39:18 +0000745 return 0;
bellard7854b052003-03-29 17:22:23 +0000746}
747
pbrook53a59602006-03-25 19:31:22 +0000748/* ??? Should this also swap msgh->name? */
bellard5a4a8982007-11-11 17:39:18 +0000749static inline abi_long host_to_target_cmsg(struct target_msghdr *target_msgh,
750 struct msghdr *msgh)
bellard7854b052003-03-29 17:22:23 +0000751{
752 struct cmsghdr *cmsg = CMSG_FIRSTHDR(msgh);
bellard5a4a8982007-11-11 17:39:18 +0000753 abi_long msg_controllen;
754 abi_ulong target_cmsg_addr;
755 struct target_cmsghdr *target_cmsg;
bellard7854b052003-03-29 17:22:23 +0000756 socklen_t space = 0;
757
bellard5a4a8982007-11-11 17:39:18 +0000758 msg_controllen = tswapl(target_msgh->msg_controllen);
759 if (msg_controllen < sizeof (struct target_cmsghdr))
760 goto the_end;
761 target_cmsg_addr = tswapl(target_msgh->msg_control);
762 target_cmsg = lock_user(VERIFY_WRITE, target_cmsg_addr, msg_controllen, 0);
763 if (!target_cmsg)
764 return -TARGET_EFAULT;
765
bellard7854b052003-03-29 17:22:23 +0000766 while (cmsg && target_cmsg) {
767 void *data = CMSG_DATA(cmsg);
768 void *target_data = TARGET_CMSG_DATA(target_cmsg);
769
770 int len = cmsg->cmsg_len - CMSG_ALIGN(sizeof (struct cmsghdr));
771
772 space += TARGET_CMSG_SPACE(len);
bellard5a4a8982007-11-11 17:39:18 +0000773 if (space > msg_controllen) {
bellard7854b052003-03-29 17:22:23 +0000774 space -= TARGET_CMSG_SPACE(len);
bellard31febb72005-12-18 20:03:27 +0000775 gemu_log("Target cmsg overflow\n");
bellard7854b052003-03-29 17:22:23 +0000776 break;
777 }
778
779 target_cmsg->cmsg_level = tswap32(cmsg->cmsg_level);
780 target_cmsg->cmsg_type = tswap32(cmsg->cmsg_type);
781 target_cmsg->cmsg_len = tswapl(TARGET_CMSG_LEN(len));
782
bellard3532fa72006-06-24 15:06:03 +0000783 if (cmsg->cmsg_level != TARGET_SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS) {
bellard7854b052003-03-29 17:22:23 +0000784 gemu_log("Unsupported ancillary data: %d/%d\n", cmsg->cmsg_level, cmsg->cmsg_type);
785 memcpy(target_data, data, len);
786 } else {
787 int *fd = (int *)data;
788 int *target_fd = (int *)target_data;
789 int i, numfds = len / sizeof(int);
790
791 for (i = 0; i < numfds; i++)
792 target_fd[i] = tswap32(fd[i]);
793 }
794
795 cmsg = CMSG_NXTHDR(msgh, cmsg);
796 target_cmsg = TARGET_CMSG_NXTHDR(target_msgh, target_cmsg);
797 }
bellard5a4a8982007-11-11 17:39:18 +0000798 unlock_user(target_cmsg, target_cmsg_addr, space);
799 the_end:
800 target_msgh->msg_controllen = tswapl(space);
801 return 0;
bellard7854b052003-03-29 17:22:23 +0000802}
803
ths0da46a62007-10-20 20:23:07 +0000804/* do_setsockopt() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +0000805static abi_long do_setsockopt(int sockfd, int level, int optname,
bellard2f619692007-11-16 10:46:05 +0000806 abi_ulong optval_addr, socklen_t optlen)
bellard7854b052003-03-29 17:22:23 +0000807{
blueswir1992f48a2007-10-14 16:27:31 +0000808 abi_long ret;
j_mayer32407102007-09-26 23:01:49 +0000809 int val;
ths3b46e622007-09-17 08:09:54 +0000810
bellard8853f862004-02-22 14:57:26 +0000811 switch(level) {
812 case SOL_TCP:
bellard7854b052003-03-29 17:22:23 +0000813 /* TCP options all take an 'int' value. */
bellard7854b052003-03-29 17:22:23 +0000814 if (optlen < sizeof(uint32_t))
ths0da46a62007-10-20 20:23:07 +0000815 return -TARGET_EINVAL;
ths3b46e622007-09-17 08:09:54 +0000816
bellard2f619692007-11-16 10:46:05 +0000817 if (get_user_u32(val, optval_addr))
818 return -TARGET_EFAULT;
bellard8853f862004-02-22 14:57:26 +0000819 ret = get_errno(setsockopt(sockfd, level, optname, &val, sizeof(val)));
820 break;
821 case SOL_IP:
822 switch(optname) {
bellard2efbe912005-07-23 15:10:20 +0000823 case IP_TOS:
824 case IP_TTL:
bellard8853f862004-02-22 14:57:26 +0000825 case IP_HDRINCL:
bellard2efbe912005-07-23 15:10:20 +0000826 case IP_ROUTER_ALERT:
827 case IP_RECVOPTS:
828 case IP_RETOPTS:
829 case IP_PKTINFO:
830 case IP_MTU_DISCOVER:
831 case IP_RECVERR:
832 case IP_RECVTOS:
833#ifdef IP_FREEBIND
834 case IP_FREEBIND:
835#endif
836 case IP_MULTICAST_TTL:
837 case IP_MULTICAST_LOOP:
bellard8853f862004-02-22 14:57:26 +0000838 val = 0;
839 if (optlen >= sizeof(uint32_t)) {
bellard2f619692007-11-16 10:46:05 +0000840 if (get_user_u32(val, optval_addr))
841 return -TARGET_EFAULT;
bellard8853f862004-02-22 14:57:26 +0000842 } else if (optlen >= 1) {
bellard2f619692007-11-16 10:46:05 +0000843 if (get_user_u8(val, optval_addr))
844 return -TARGET_EFAULT;
bellard8853f862004-02-22 14:57:26 +0000845 }
846 ret = get_errno(setsockopt(sockfd, level, optname, &val, sizeof(val)));
847 break;
848 default:
849 goto unimplemented;
850 }
851 break;
bellard3532fa72006-06-24 15:06:03 +0000852 case TARGET_SOL_SOCKET:
bellard8853f862004-02-22 14:57:26 +0000853 switch (optname) {
854 /* Options with 'int' argument. */
bellard3532fa72006-06-24 15:06:03 +0000855 case TARGET_SO_DEBUG:
856 optname = SO_DEBUG;
857 break;
858 case TARGET_SO_REUSEADDR:
859 optname = SO_REUSEADDR;
860 break;
861 case TARGET_SO_TYPE:
862 optname = SO_TYPE;
863 break;
864 case TARGET_SO_ERROR:
865 optname = SO_ERROR;
866 break;
867 case TARGET_SO_DONTROUTE:
868 optname = SO_DONTROUTE;
869 break;
870 case TARGET_SO_BROADCAST:
871 optname = SO_BROADCAST;
872 break;
873 case TARGET_SO_SNDBUF:
874 optname = SO_SNDBUF;
875 break;
876 case TARGET_SO_RCVBUF:
877 optname = SO_RCVBUF;
878 break;
879 case TARGET_SO_KEEPALIVE:
880 optname = SO_KEEPALIVE;
881 break;
882 case TARGET_SO_OOBINLINE:
883 optname = SO_OOBINLINE;
884 break;
885 case TARGET_SO_NO_CHECK:
886 optname = SO_NO_CHECK;
887 break;
888 case TARGET_SO_PRIORITY:
889 optname = SO_PRIORITY;
890 break;
bellard5e83e8e2005-03-01 22:32:06 +0000891#ifdef SO_BSDCOMPAT
bellard3532fa72006-06-24 15:06:03 +0000892 case TARGET_SO_BSDCOMPAT:
893 optname = SO_BSDCOMPAT;
894 break;
bellard5e83e8e2005-03-01 22:32:06 +0000895#endif
bellard3532fa72006-06-24 15:06:03 +0000896 case TARGET_SO_PASSCRED:
897 optname = SO_PASSCRED;
898 break;
899 case TARGET_SO_TIMESTAMP:
900 optname = SO_TIMESTAMP;
901 break;
902 case TARGET_SO_RCVLOWAT:
903 optname = SO_RCVLOWAT;
904 break;
905 case TARGET_SO_RCVTIMEO:
906 optname = SO_RCVTIMEO;
907 break;
908 case TARGET_SO_SNDTIMEO:
909 optname = SO_SNDTIMEO;
910 break;
bellard8853f862004-02-22 14:57:26 +0000911 break;
912 default:
913 goto unimplemented;
914 }
bellard3532fa72006-06-24 15:06:03 +0000915 if (optlen < sizeof(uint32_t))
bellard2f619692007-11-16 10:46:05 +0000916 return -TARGET_EINVAL;
bellard3532fa72006-06-24 15:06:03 +0000917
bellard2f619692007-11-16 10:46:05 +0000918 if (get_user_u32(val, optval_addr))
919 return -TARGET_EFAULT;
bellard3532fa72006-06-24 15:06:03 +0000920 ret = get_errno(setsockopt(sockfd, SOL_SOCKET, optname, &val, sizeof(val)));
bellard8853f862004-02-22 14:57:26 +0000921 break;
bellard7854b052003-03-29 17:22:23 +0000922 default:
bellard8853f862004-02-22 14:57:26 +0000923 unimplemented:
924 gemu_log("Unsupported setsockopt level=%d optname=%d \n", level, optname);
ths6fa13c12007-12-18 02:41:04 +0000925 ret = -TARGET_ENOPROTOOPT;
bellard7854b052003-03-29 17:22:23 +0000926 }
bellard8853f862004-02-22 14:57:26 +0000927 return ret;
bellard7854b052003-03-29 17:22:23 +0000928}
929
ths0da46a62007-10-20 20:23:07 +0000930/* do_getsockopt() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +0000931static abi_long do_getsockopt(int sockfd, int level, int optname,
bellard2f619692007-11-16 10:46:05 +0000932 abi_ulong optval_addr, abi_ulong optlen)
bellard7854b052003-03-29 17:22:23 +0000933{
blueswir1992f48a2007-10-14 16:27:31 +0000934 abi_long ret;
j_mayer32407102007-09-26 23:01:49 +0000935 int len, lv, val;
bellard8853f862004-02-22 14:57:26 +0000936
937 switch(level) {
bellard3532fa72006-06-24 15:06:03 +0000938 case TARGET_SOL_SOCKET:
939 level = SOL_SOCKET;
bellard8853f862004-02-22 14:57:26 +0000940 switch (optname) {
bellard3532fa72006-06-24 15:06:03 +0000941 case TARGET_SO_LINGER:
942 case TARGET_SO_RCVTIMEO:
943 case TARGET_SO_SNDTIMEO:
944 case TARGET_SO_PEERCRED:
945 case TARGET_SO_PEERNAME:
bellard8853f862004-02-22 14:57:26 +0000946 /* These don't just return a single integer */
947 goto unimplemented;
948 default:
bellard2efbe912005-07-23 15:10:20 +0000949 goto int_case;
950 }
951 break;
952 case SOL_TCP:
953 /* TCP options all take an 'int' value. */
954 int_case:
bellard2f619692007-11-16 10:46:05 +0000955 if (get_user_u32(len, optlen))
956 return -TARGET_EFAULT;
bellard2efbe912005-07-23 15:10:20 +0000957 if (len < 0)
ths0da46a62007-10-20 20:23:07 +0000958 return -TARGET_EINVAL;
bellard2efbe912005-07-23 15:10:20 +0000959 lv = sizeof(int);
960 ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
961 if (ret < 0)
962 return ret;
963 val = tswap32(val);
964 if (len > lv)
965 len = lv;
bellard2f619692007-11-16 10:46:05 +0000966 if (len == 4) {
967 if (put_user_u32(val, optval_addr))
968 return -TARGET_EFAULT;
969 } else {
970 if (put_user_u8(val, optval_addr))
971 return -TARGET_EFAULT;
972 }
973 if (put_user_u32(len, optlen))
974 return -TARGET_EFAULT;
bellard2efbe912005-07-23 15:10:20 +0000975 break;
976 case SOL_IP:
977 switch(optname) {
978 case IP_TOS:
979 case IP_TTL:
980 case IP_HDRINCL:
981 case IP_ROUTER_ALERT:
982 case IP_RECVOPTS:
983 case IP_RETOPTS:
984 case IP_PKTINFO:
985 case IP_MTU_DISCOVER:
986 case IP_RECVERR:
987 case IP_RECVTOS:
988#ifdef IP_FREEBIND
989 case IP_FREEBIND:
990#endif
991 case IP_MULTICAST_TTL:
992 case IP_MULTICAST_LOOP:
bellard2f619692007-11-16 10:46:05 +0000993 if (get_user_u32(len, optlen))
994 return -TARGET_EFAULT;
bellard8853f862004-02-22 14:57:26 +0000995 if (len < 0)
ths0da46a62007-10-20 20:23:07 +0000996 return -TARGET_EINVAL;
bellard8853f862004-02-22 14:57:26 +0000997 lv = sizeof(int);
998 ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
999 if (ret < 0)
1000 return ret;
bellard2efbe912005-07-23 15:10:20 +00001001 if (len < sizeof(int) && len > 0 && val >= 0 && val < 255) {
bellard2efbe912005-07-23 15:10:20 +00001002 len = 1;
bellard2f619692007-11-16 10:46:05 +00001003 if (put_user_u32(len, optlen)
1004 || put_user_u8(val, optval_addr))
1005 return -TARGET_EFAULT;
bellard2efbe912005-07-23 15:10:20 +00001006 } else {
bellard2efbe912005-07-23 15:10:20 +00001007 if (len > sizeof(int))
1008 len = sizeof(int);
bellard2f619692007-11-16 10:46:05 +00001009 if (put_user_u32(len, optlen)
1010 || put_user_u32(val, optval_addr))
1011 return -TARGET_EFAULT;
bellard2efbe912005-07-23 15:10:20 +00001012 }
bellard8853f862004-02-22 14:57:26 +00001013 break;
bellard2efbe912005-07-23 15:10:20 +00001014 default:
thsc02f4992007-12-18 02:39:59 +00001015 ret = -TARGET_ENOPROTOOPT;
1016 break;
bellard8853f862004-02-22 14:57:26 +00001017 }
1018 break;
1019 default:
1020 unimplemented:
1021 gemu_log("getsockopt level=%d optname=%d not yet supported\n",
1022 level, optname);
thsc02f4992007-12-18 02:39:59 +00001023 ret = -TARGET_EOPNOTSUPP;
bellard8853f862004-02-22 14:57:26 +00001024 break;
1025 }
1026 return ret;
bellard7854b052003-03-29 17:22:23 +00001027}
1028
bellard579a97f2007-11-11 14:26:47 +00001029/* FIXME
1030 * lock_iovec()/unlock_iovec() have a return code of 0 for success where
1031 * other lock functions have a return code of 0 for failure.
1032 */
1033static abi_long lock_iovec(int type, struct iovec *vec, abi_ulong target_addr,
1034 int count, int copy)
pbrook53a59602006-03-25 19:31:22 +00001035{
1036 struct target_iovec *target_vec;
blueswir1992f48a2007-10-14 16:27:31 +00001037 abi_ulong base;
bellard579a97f2007-11-11 14:26:47 +00001038 int i, j;
pbrook53a59602006-03-25 19:31:22 +00001039
bellard579a97f2007-11-11 14:26:47 +00001040 target_vec = lock_user(VERIFY_READ, target_addr, count * sizeof(struct target_iovec), 1);
1041 if (!target_vec)
1042 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00001043 for(i = 0;i < count; i++) {
1044 base = tswapl(target_vec[i].iov_base);
1045 vec[i].iov_len = tswapl(target_vec[i].iov_len);
bellard41df8412008-02-04 22:26:57 +00001046 if (vec[i].iov_len != 0) {
1047 vec[i].iov_base = lock_user(type, base, vec[i].iov_len, copy);
balrog7bedce82008-02-10 13:28:08 +00001048 if (!vec[i].iov_base && vec[i].iov_len)
bellard41df8412008-02-04 22:26:57 +00001049 goto fail;
1050 } else {
1051 /* zero length pointer is ignored */
1052 vec[i].iov_base = NULL;
1053 }
pbrook53a59602006-03-25 19:31:22 +00001054 }
1055 unlock_user (target_vec, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00001056 return 0;
1057 fail:
1058 /* failure - unwind locks */
1059 for (j = 0; j < i; j++) {
1060 base = tswapl(target_vec[j].iov_base);
1061 unlock_user(vec[j].iov_base, base, 0);
1062 }
1063 unlock_user (target_vec, target_addr, 0);
1064 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00001065}
1066
bellard579a97f2007-11-11 14:26:47 +00001067static abi_long unlock_iovec(struct iovec *vec, abi_ulong target_addr,
1068 int count, int copy)
pbrook53a59602006-03-25 19:31:22 +00001069{
1070 struct target_iovec *target_vec;
blueswir1992f48a2007-10-14 16:27:31 +00001071 abi_ulong base;
pbrook53a59602006-03-25 19:31:22 +00001072 int i;
1073
bellard579a97f2007-11-11 14:26:47 +00001074 target_vec = lock_user(VERIFY_READ, target_addr, count * sizeof(struct target_iovec), 1);
1075 if (!target_vec)
1076 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00001077 for(i = 0;i < count; i++) {
1078 base = tswapl(target_vec[i].iov_base);
1079 unlock_user(vec[i].iov_base, base, copy ? vec[i].iov_len : 0);
1080 }
1081 unlock_user (target_vec, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00001082
1083 return 0;
pbrook53a59602006-03-25 19:31:22 +00001084}
1085
ths0da46a62007-10-20 20:23:07 +00001086/* do_socket() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001087static abi_long do_socket(int domain, int type, int protocol)
bellard3532fa72006-06-24 15:06:03 +00001088{
1089#if defined(TARGET_MIPS)
1090 switch(type) {
1091 case TARGET_SOCK_DGRAM:
1092 type = SOCK_DGRAM;
1093 break;
1094 case TARGET_SOCK_STREAM:
1095 type = SOCK_STREAM;
1096 break;
1097 case TARGET_SOCK_RAW:
1098 type = SOCK_RAW;
1099 break;
1100 case TARGET_SOCK_RDM:
1101 type = SOCK_RDM;
1102 break;
1103 case TARGET_SOCK_SEQPACKET:
1104 type = SOCK_SEQPACKET;
1105 break;
1106 case TARGET_SOCK_PACKET:
1107 type = SOCK_PACKET;
1108 break;
1109 }
1110#endif
balrog12bc92a2007-10-30 21:06:14 +00001111 if (domain == PF_NETLINK)
1112 return -EAFNOSUPPORT; /* do not NETLINK socket connections possible */
bellard3532fa72006-06-24 15:06:03 +00001113 return get_errno(socket(domain, type, protocol));
1114}
1115
ths0da46a62007-10-20 20:23:07 +00001116/* do_bind() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001117static abi_long do_bind(int sockfd, abi_ulong target_addr,
1118 socklen_t addrlen)
bellard3532fa72006-06-24 15:06:03 +00001119{
1120 void *addr = alloca(addrlen);
ths3b46e622007-09-17 08:09:54 +00001121
bellard3532fa72006-06-24 15:06:03 +00001122 target_to_host_sockaddr(addr, target_addr, addrlen);
1123 return get_errno(bind(sockfd, addr, addrlen));
1124}
1125
ths0da46a62007-10-20 20:23:07 +00001126/* do_connect() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001127static abi_long do_connect(int sockfd, abi_ulong target_addr,
1128 socklen_t addrlen)
bellard3532fa72006-06-24 15:06:03 +00001129{
1130 void *addr = alloca(addrlen);
ths3b46e622007-09-17 08:09:54 +00001131
bellard3532fa72006-06-24 15:06:03 +00001132 target_to_host_sockaddr(addr, target_addr, addrlen);
1133 return get_errno(connect(sockfd, addr, addrlen));
1134}
1135
ths0da46a62007-10-20 20:23:07 +00001136/* do_sendrecvmsg() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001137static abi_long do_sendrecvmsg(int fd, abi_ulong target_msg,
1138 int flags, int send)
bellard3532fa72006-06-24 15:06:03 +00001139{
blueswir1992f48a2007-10-14 16:27:31 +00001140 abi_long ret;
bellard3532fa72006-06-24 15:06:03 +00001141 struct target_msghdr *msgp;
1142 struct msghdr msg;
1143 int count;
1144 struct iovec *vec;
blueswir1992f48a2007-10-14 16:27:31 +00001145 abi_ulong target_vec;
bellard3532fa72006-06-24 15:06:03 +00001146
bellard579a97f2007-11-11 14:26:47 +00001147 /* FIXME */
1148 if (!lock_user_struct(send ? VERIFY_READ : VERIFY_WRITE,
1149 msgp,
1150 target_msg,
1151 send ? 1 : 0))
1152 return -TARGET_EFAULT;
bellard3532fa72006-06-24 15:06:03 +00001153 if (msgp->msg_name) {
1154 msg.msg_namelen = tswap32(msgp->msg_namelen);
1155 msg.msg_name = alloca(msg.msg_namelen);
1156 target_to_host_sockaddr(msg.msg_name, tswapl(msgp->msg_name),
1157 msg.msg_namelen);
1158 } else {
1159 msg.msg_name = NULL;
1160 msg.msg_namelen = 0;
1161 }
1162 msg.msg_controllen = 2 * tswapl(msgp->msg_controllen);
1163 msg.msg_control = alloca(msg.msg_controllen);
1164 msg.msg_flags = tswap32(msgp->msg_flags);
ths3b46e622007-09-17 08:09:54 +00001165
bellard3532fa72006-06-24 15:06:03 +00001166 count = tswapl(msgp->msg_iovlen);
1167 vec = alloca(count * sizeof(struct iovec));
1168 target_vec = tswapl(msgp->msg_iov);
bellard579a97f2007-11-11 14:26:47 +00001169 lock_iovec(send ? VERIFY_READ : VERIFY_WRITE, vec, target_vec, count, send);
bellard3532fa72006-06-24 15:06:03 +00001170 msg.msg_iovlen = count;
1171 msg.msg_iov = vec;
ths3b46e622007-09-17 08:09:54 +00001172
bellard3532fa72006-06-24 15:06:03 +00001173 if (send) {
bellard5a4a8982007-11-11 17:39:18 +00001174 ret = target_to_host_cmsg(&msg, msgp);
1175 if (ret == 0)
1176 ret = get_errno(sendmsg(fd, &msg, flags));
bellard3532fa72006-06-24 15:06:03 +00001177 } else {
1178 ret = get_errno(recvmsg(fd, &msg, flags));
1179 if (!is_error(ret))
bellard5a4a8982007-11-11 17:39:18 +00001180 ret = host_to_target_cmsg(msgp, &msg);
bellard3532fa72006-06-24 15:06:03 +00001181 }
1182 unlock_iovec(vec, target_vec, count, !send);
bellard579a97f2007-11-11 14:26:47 +00001183 unlock_user_struct(msgp, target_msg, send ? 0 : 1);
bellard3532fa72006-06-24 15:06:03 +00001184 return ret;
1185}
1186
ths0da46a62007-10-20 20:23:07 +00001187/* do_accept() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001188static abi_long do_accept(int fd, abi_ulong target_addr,
bellard2f619692007-11-16 10:46:05 +00001189 abi_ulong target_addrlen_addr)
pbrook1be9e1d2006-11-19 15:26:04 +00001190{
bellard2f619692007-11-16 10:46:05 +00001191 socklen_t addrlen;
1192 void *addr;
blueswir1992f48a2007-10-14 16:27:31 +00001193 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00001194
bellard2f619692007-11-16 10:46:05 +00001195 if (get_user_u32(addrlen, target_addrlen_addr))
1196 return -TARGET_EFAULT;
1197
1198 addr = alloca(addrlen);
1199
pbrook1be9e1d2006-11-19 15:26:04 +00001200 ret = get_errno(accept(fd, addr, &addrlen));
1201 if (!is_error(ret)) {
1202 host_to_target_sockaddr(target_addr, addr, addrlen);
bellard2f619692007-11-16 10:46:05 +00001203 if (put_user_u32(addrlen, target_addrlen_addr))
1204 ret = -TARGET_EFAULT;
pbrook1be9e1d2006-11-19 15:26:04 +00001205 }
1206 return ret;
1207}
1208
ths0da46a62007-10-20 20:23:07 +00001209/* do_getpeername() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001210static abi_long do_getpeername(int fd, abi_ulong target_addr,
bellard2f619692007-11-16 10:46:05 +00001211 abi_ulong target_addrlen_addr)
pbrook1be9e1d2006-11-19 15:26:04 +00001212{
bellard2f619692007-11-16 10:46:05 +00001213 socklen_t addrlen;
1214 void *addr;
blueswir1992f48a2007-10-14 16:27:31 +00001215 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00001216
bellard2f619692007-11-16 10:46:05 +00001217 if (get_user_u32(addrlen, target_addrlen_addr))
1218 return -TARGET_EFAULT;
1219
1220 addr = alloca(addrlen);
1221
pbrook1be9e1d2006-11-19 15:26:04 +00001222 ret = get_errno(getpeername(fd, addr, &addrlen));
1223 if (!is_error(ret)) {
1224 host_to_target_sockaddr(target_addr, addr, addrlen);
bellard2f619692007-11-16 10:46:05 +00001225 if (put_user_u32(addrlen, target_addrlen_addr))
1226 ret = -TARGET_EFAULT;
pbrook1be9e1d2006-11-19 15:26:04 +00001227 }
1228 return ret;
1229}
1230
ths0da46a62007-10-20 20:23:07 +00001231/* do_getsockname() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001232static abi_long do_getsockname(int fd, abi_ulong target_addr,
bellard2f619692007-11-16 10:46:05 +00001233 abi_ulong target_addrlen_addr)
pbrook1be9e1d2006-11-19 15:26:04 +00001234{
bellard2f619692007-11-16 10:46:05 +00001235 socklen_t addrlen;
1236 void *addr;
blueswir1992f48a2007-10-14 16:27:31 +00001237 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00001238
bellard2f619692007-11-16 10:46:05 +00001239 if (get_user_u32(addrlen, target_addrlen_addr))
1240 return -TARGET_EFAULT;
1241
1242 addr = alloca(addrlen);
1243
pbrook1be9e1d2006-11-19 15:26:04 +00001244 ret = get_errno(getsockname(fd, addr, &addrlen));
1245 if (!is_error(ret)) {
1246 host_to_target_sockaddr(target_addr, addr, addrlen);
bellard2f619692007-11-16 10:46:05 +00001247 if (put_user_u32(addrlen, target_addrlen_addr))
1248 ret = -TARGET_EFAULT;
pbrook1be9e1d2006-11-19 15:26:04 +00001249 }
1250 return ret;
1251}
1252
ths0da46a62007-10-20 20:23:07 +00001253/* do_socketpair() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001254static abi_long do_socketpair(int domain, int type, int protocol,
bellard2f619692007-11-16 10:46:05 +00001255 abi_ulong target_tab_addr)
pbrook1be9e1d2006-11-19 15:26:04 +00001256{
1257 int tab[2];
blueswir1992f48a2007-10-14 16:27:31 +00001258 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00001259
1260 ret = get_errno(socketpair(domain, type, protocol, tab));
1261 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +00001262 if (put_user_s32(tab[0], target_tab_addr)
1263 || put_user_s32(tab[1], target_tab_addr + sizeof(tab[0])))
1264 ret = -TARGET_EFAULT;
pbrook1be9e1d2006-11-19 15:26:04 +00001265 }
1266 return ret;
1267}
1268
ths0da46a62007-10-20 20:23:07 +00001269/* do_sendto() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001270static abi_long do_sendto(int fd, abi_ulong msg, size_t len, int flags,
1271 abi_ulong target_addr, socklen_t addrlen)
pbrook1be9e1d2006-11-19 15:26:04 +00001272{
1273 void *addr;
1274 void *host_msg;
blueswir1992f48a2007-10-14 16:27:31 +00001275 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00001276
bellard579a97f2007-11-11 14:26:47 +00001277 host_msg = lock_user(VERIFY_READ, msg, len, 1);
1278 if (!host_msg)
1279 return -TARGET_EFAULT;
pbrook1be9e1d2006-11-19 15:26:04 +00001280 if (target_addr) {
1281 addr = alloca(addrlen);
1282 target_to_host_sockaddr(addr, target_addr, addrlen);
1283 ret = get_errno(sendto(fd, host_msg, len, flags, addr, addrlen));
1284 } else {
1285 ret = get_errno(send(fd, host_msg, len, flags));
1286 }
1287 unlock_user(host_msg, msg, 0);
1288 return ret;
1289}
1290
ths0da46a62007-10-20 20:23:07 +00001291/* do_recvfrom() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001292static abi_long do_recvfrom(int fd, abi_ulong msg, size_t len, int flags,
1293 abi_ulong target_addr,
1294 abi_ulong target_addrlen)
pbrook1be9e1d2006-11-19 15:26:04 +00001295{
1296 socklen_t addrlen;
1297 void *addr;
1298 void *host_msg;
blueswir1992f48a2007-10-14 16:27:31 +00001299 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00001300
bellard579a97f2007-11-11 14:26:47 +00001301 host_msg = lock_user(VERIFY_WRITE, msg, len, 0);
1302 if (!host_msg)
1303 return -TARGET_EFAULT;
pbrook1be9e1d2006-11-19 15:26:04 +00001304 if (target_addr) {
bellard2f619692007-11-16 10:46:05 +00001305 if (get_user_u32(addrlen, target_addrlen)) {
1306 ret = -TARGET_EFAULT;
1307 goto fail;
1308 }
pbrook1be9e1d2006-11-19 15:26:04 +00001309 addr = alloca(addrlen);
1310 ret = get_errno(recvfrom(fd, host_msg, len, flags, addr, &addrlen));
1311 } else {
1312 addr = NULL; /* To keep compiler quiet. */
1313 ret = get_errno(recv(fd, host_msg, len, flags));
1314 }
1315 if (!is_error(ret)) {
1316 if (target_addr) {
1317 host_to_target_sockaddr(target_addr, addr, addrlen);
bellard2f619692007-11-16 10:46:05 +00001318 if (put_user_u32(addrlen, target_addrlen)) {
1319 ret = -TARGET_EFAULT;
1320 goto fail;
1321 }
pbrook1be9e1d2006-11-19 15:26:04 +00001322 }
1323 unlock_user(host_msg, msg, len);
1324 } else {
bellard2f619692007-11-16 10:46:05 +00001325fail:
pbrook1be9e1d2006-11-19 15:26:04 +00001326 unlock_user(host_msg, msg, 0);
1327 }
1328 return ret;
1329}
1330
j_mayer32407102007-09-26 23:01:49 +00001331#ifdef TARGET_NR_socketcall
ths0da46a62007-10-20 20:23:07 +00001332/* do_socketcall() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001333static abi_long do_socketcall(int num, abi_ulong vptr)
bellard31e31b82003-02-18 22:55:36 +00001334{
blueswir1992f48a2007-10-14 16:27:31 +00001335 abi_long ret;
1336 const int n = sizeof(abi_ulong);
bellard31e31b82003-02-18 22:55:36 +00001337
1338 switch(num) {
1339 case SOCKOP_socket:
bellard7854b052003-03-29 17:22:23 +00001340 {
bellard2f619692007-11-16 10:46:05 +00001341 int domain, type, protocol;
1342
1343 if (get_user_s32(domain, vptr)
1344 || get_user_s32(type, vptr + n)
1345 || get_user_s32(protocol, vptr + 2 * n))
1346 return -TARGET_EFAULT;
1347
bellard3532fa72006-06-24 15:06:03 +00001348 ret = do_socket(domain, type, protocol);
bellard7854b052003-03-29 17:22:23 +00001349 }
bellard31e31b82003-02-18 22:55:36 +00001350 break;
1351 case SOCKOP_bind:
bellard7854b052003-03-29 17:22:23 +00001352 {
bellard2f619692007-11-16 10:46:05 +00001353 int sockfd;
1354 abi_ulong target_addr;
1355 socklen_t addrlen;
1356
1357 if (get_user_s32(sockfd, vptr)
1358 || get_user_ual(target_addr, vptr + n)
1359 || get_user_u32(addrlen, vptr + 2 * n))
1360 return -TARGET_EFAULT;
1361
bellard3532fa72006-06-24 15:06:03 +00001362 ret = do_bind(sockfd, target_addr, addrlen);
bellard7854b052003-03-29 17:22:23 +00001363 }
bellard31e31b82003-02-18 22:55:36 +00001364 break;
1365 case SOCKOP_connect:
bellard7854b052003-03-29 17:22:23 +00001366 {
bellard2f619692007-11-16 10:46:05 +00001367 int sockfd;
1368 abi_ulong target_addr;
1369 socklen_t addrlen;
1370
1371 if (get_user_s32(sockfd, vptr)
1372 || get_user_ual(target_addr, vptr + n)
1373 || get_user_u32(addrlen, vptr + 2 * n))
1374 return -TARGET_EFAULT;
1375
bellard3532fa72006-06-24 15:06:03 +00001376 ret = do_connect(sockfd, target_addr, addrlen);
bellard7854b052003-03-29 17:22:23 +00001377 }
bellard31e31b82003-02-18 22:55:36 +00001378 break;
1379 case SOCKOP_listen:
bellard7854b052003-03-29 17:22:23 +00001380 {
bellard2f619692007-11-16 10:46:05 +00001381 int sockfd, backlog;
1382
1383 if (get_user_s32(sockfd, vptr)
1384 || get_user_s32(backlog, vptr + n))
1385 return -TARGET_EFAULT;
1386
bellard7854b052003-03-29 17:22:23 +00001387 ret = get_errno(listen(sockfd, backlog));
1388 }
bellard31e31b82003-02-18 22:55:36 +00001389 break;
1390 case SOCKOP_accept:
1391 {
bellard2f619692007-11-16 10:46:05 +00001392 int sockfd;
1393 abi_ulong target_addr, target_addrlen;
1394
1395 if (get_user_s32(sockfd, vptr)
1396 || get_user_ual(target_addr, vptr + n)
1397 || get_user_u32(target_addrlen, vptr + 2 * n))
1398 return -TARGET_EFAULT;
1399
pbrook1be9e1d2006-11-19 15:26:04 +00001400 ret = do_accept(sockfd, target_addr, target_addrlen);
bellard31e31b82003-02-18 22:55:36 +00001401 }
1402 break;
1403 case SOCKOP_getsockname:
1404 {
bellard2f619692007-11-16 10:46:05 +00001405 int sockfd;
1406 abi_ulong target_addr, target_addrlen;
1407
1408 if (get_user_s32(sockfd, vptr)
1409 || get_user_ual(target_addr, vptr + n)
1410 || get_user_u32(target_addrlen, vptr + 2 * n))
1411 return -TARGET_EFAULT;
1412
pbrook1be9e1d2006-11-19 15:26:04 +00001413 ret = do_getsockname(sockfd, target_addr, target_addrlen);
bellard31e31b82003-02-18 22:55:36 +00001414 }
1415 break;
1416 case SOCKOP_getpeername:
1417 {
bellard2f619692007-11-16 10:46:05 +00001418 int sockfd;
1419 abi_ulong target_addr, target_addrlen;
1420
1421 if (get_user_s32(sockfd, vptr)
1422 || get_user_ual(target_addr, vptr + n)
1423 || get_user_u32(target_addrlen, vptr + 2 * n))
1424 return -TARGET_EFAULT;
1425
pbrook1be9e1d2006-11-19 15:26:04 +00001426 ret = do_getpeername(sockfd, target_addr, target_addrlen);
bellard31e31b82003-02-18 22:55:36 +00001427 }
1428 break;
1429 case SOCKOP_socketpair:
1430 {
bellard2f619692007-11-16 10:46:05 +00001431 int domain, type, protocol;
1432 abi_ulong tab;
1433
1434 if (get_user_s32(domain, vptr)
1435 || get_user_s32(type, vptr + n)
1436 || get_user_s32(protocol, vptr + 2 * n)
1437 || get_user_ual(tab, vptr + 3 * n))
1438 return -TARGET_EFAULT;
1439
pbrook1be9e1d2006-11-19 15:26:04 +00001440 ret = do_socketpair(domain, type, protocol, tab);
bellard31e31b82003-02-18 22:55:36 +00001441 }
1442 break;
1443 case SOCKOP_send:
bellard7854b052003-03-29 17:22:23 +00001444 {
bellard2f619692007-11-16 10:46:05 +00001445 int sockfd;
1446 abi_ulong msg;
1447 size_t len;
1448 int flags;
1449
1450 if (get_user_s32(sockfd, vptr)
1451 || get_user_ual(msg, vptr + n)
1452 || get_user_ual(len, vptr + 2 * n)
1453 || get_user_s32(flags, vptr + 3 * n))
1454 return -TARGET_EFAULT;
1455
pbrook1be9e1d2006-11-19 15:26:04 +00001456 ret = do_sendto(sockfd, msg, len, flags, 0, 0);
bellard7854b052003-03-29 17:22:23 +00001457 }
bellard31e31b82003-02-18 22:55:36 +00001458 break;
1459 case SOCKOP_recv:
bellard7854b052003-03-29 17:22:23 +00001460 {
bellard2f619692007-11-16 10:46:05 +00001461 int sockfd;
1462 abi_ulong msg;
1463 size_t len;
1464 int flags;
1465
1466 if (get_user_s32(sockfd, vptr)
1467 || get_user_ual(msg, vptr + n)
1468 || get_user_ual(len, vptr + 2 * n)
1469 || get_user_s32(flags, vptr + 3 * n))
1470 return -TARGET_EFAULT;
1471
pbrook1be9e1d2006-11-19 15:26:04 +00001472 ret = do_recvfrom(sockfd, msg, len, flags, 0, 0);
bellard7854b052003-03-29 17:22:23 +00001473 }
bellard31e31b82003-02-18 22:55:36 +00001474 break;
1475 case SOCKOP_sendto:
bellard7854b052003-03-29 17:22:23 +00001476 {
bellard2f619692007-11-16 10:46:05 +00001477 int sockfd;
1478 abi_ulong msg;
1479 size_t len;
1480 int flags;
1481 abi_ulong addr;
1482 socklen_t addrlen;
1483
1484 if (get_user_s32(sockfd, vptr)
1485 || get_user_ual(msg, vptr + n)
1486 || get_user_ual(len, vptr + 2 * n)
1487 || get_user_s32(flags, vptr + 3 * n)
1488 || get_user_ual(addr, vptr + 4 * n)
1489 || get_user_u32(addrlen, vptr + 5 * n))
1490 return -TARGET_EFAULT;
1491
pbrook1be9e1d2006-11-19 15:26:04 +00001492 ret = do_sendto(sockfd, msg, len, flags, addr, addrlen);
bellard7854b052003-03-29 17:22:23 +00001493 }
bellard31e31b82003-02-18 22:55:36 +00001494 break;
1495 case SOCKOP_recvfrom:
1496 {
bellard2f619692007-11-16 10:46:05 +00001497 int sockfd;
1498 abi_ulong msg;
1499 size_t len;
1500 int flags;
1501 abi_ulong addr;
1502 socklen_t addrlen;
1503
1504 if (get_user_s32(sockfd, vptr)
1505 || get_user_ual(msg, vptr + n)
1506 || get_user_ual(len, vptr + 2 * n)
1507 || get_user_s32(flags, vptr + 3 * n)
1508 || get_user_ual(addr, vptr + 4 * n)
1509 || get_user_u32(addrlen, vptr + 5 * n))
1510 return -TARGET_EFAULT;
1511
pbrook1be9e1d2006-11-19 15:26:04 +00001512 ret = do_recvfrom(sockfd, msg, len, flags, addr, addrlen);
bellard31e31b82003-02-18 22:55:36 +00001513 }
1514 break;
1515 case SOCKOP_shutdown:
bellard7854b052003-03-29 17:22:23 +00001516 {
bellard2f619692007-11-16 10:46:05 +00001517 int sockfd, how;
1518
1519 if (get_user_s32(sockfd, vptr)
1520 || get_user_s32(how, vptr + n))
1521 return -TARGET_EFAULT;
bellard7854b052003-03-29 17:22:23 +00001522
1523 ret = get_errno(shutdown(sockfd, how));
1524 }
bellard31e31b82003-02-18 22:55:36 +00001525 break;
1526 case SOCKOP_sendmsg:
1527 case SOCKOP_recvmsg:
bellard1a9353d2003-03-16 20:28:50 +00001528 {
1529 int fd;
blueswir1992f48a2007-10-14 16:27:31 +00001530 abi_ulong target_msg;
bellard3532fa72006-06-24 15:06:03 +00001531 int flags;
bellard1a9353d2003-03-16 20:28:50 +00001532
bellard2f619692007-11-16 10:46:05 +00001533 if (get_user_s32(fd, vptr)
1534 || get_user_ual(target_msg, vptr + n)
1535 || get_user_s32(flags, vptr + 2 * n))
1536 return -TARGET_EFAULT;
bellard3532fa72006-06-24 15:06:03 +00001537
ths5fafdf22007-09-16 21:08:06 +00001538 ret = do_sendrecvmsg(fd, target_msg, flags,
bellard3532fa72006-06-24 15:06:03 +00001539 (num == SOCKOP_sendmsg));
bellard1a9353d2003-03-16 20:28:50 +00001540 }
1541 break;
bellard31e31b82003-02-18 22:55:36 +00001542 case SOCKOP_setsockopt:
bellard7854b052003-03-29 17:22:23 +00001543 {
bellard2f619692007-11-16 10:46:05 +00001544 int sockfd;
1545 int level;
1546 int optname;
1547 abi_ulong optval;
1548 socklen_t optlen;
1549
1550 if (get_user_s32(sockfd, vptr)
1551 || get_user_s32(level, vptr + n)
1552 || get_user_s32(optname, vptr + 2 * n)
1553 || get_user_ual(optval, vptr + 3 * n)
1554 || get_user_u32(optlen, vptr + 4 * n))
1555 return -TARGET_EFAULT;
bellard7854b052003-03-29 17:22:23 +00001556
1557 ret = do_setsockopt(sockfd, level, optname, optval, optlen);
1558 }
1559 break;
bellard31e31b82003-02-18 22:55:36 +00001560 case SOCKOP_getsockopt:
bellard7854b052003-03-29 17:22:23 +00001561 {
bellard2f619692007-11-16 10:46:05 +00001562 int sockfd;
1563 int level;
1564 int optname;
1565 abi_ulong optval;
1566 socklen_t optlen;
bellard7854b052003-03-29 17:22:23 +00001567
bellard2f619692007-11-16 10:46:05 +00001568 if (get_user_s32(sockfd, vptr)
1569 || get_user_s32(level, vptr + n)
1570 || get_user_s32(optname, vptr + 2 * n)
1571 || get_user_ual(optval, vptr + 3 * n)
1572 || get_user_u32(optlen, vptr + 4 * n))
1573 return -TARGET_EFAULT;
1574
1575 ret = do_getsockopt(sockfd, level, optname, optval, optlen);
bellard7854b052003-03-29 17:22:23 +00001576 }
1577 break;
bellard31e31b82003-02-18 22:55:36 +00001578 default:
1579 gemu_log("Unsupported socketcall: %d\n", num);
ths0da46a62007-10-20 20:23:07 +00001580 ret = -TARGET_ENOSYS;
bellard31e31b82003-02-18 22:55:36 +00001581 break;
1582 }
1583 return ret;
1584}
j_mayer32407102007-09-26 23:01:49 +00001585#endif
bellard31e31b82003-02-18 22:55:36 +00001586
j_mayer32407102007-09-26 23:01:49 +00001587#ifdef TARGET_NR_ipc
bellard8853f862004-02-22 14:57:26 +00001588#define N_SHM_REGIONS 32
1589
1590static struct shm_region {
bellard5a4a8982007-11-11 17:39:18 +00001591 abi_ulong start;
1592 abi_ulong size;
bellard8853f862004-02-22 14:57:26 +00001593} shm_regions[N_SHM_REGIONS];
1594
ths3eb6b042007-06-03 14:26:27 +00001595struct target_ipc_perm
1596{
blueswir1992f48a2007-10-14 16:27:31 +00001597 abi_long __key;
1598 abi_ulong uid;
1599 abi_ulong gid;
1600 abi_ulong cuid;
1601 abi_ulong cgid;
ths3eb6b042007-06-03 14:26:27 +00001602 unsigned short int mode;
1603 unsigned short int __pad1;
1604 unsigned short int __seq;
1605 unsigned short int __pad2;
blueswir1992f48a2007-10-14 16:27:31 +00001606 abi_ulong __unused1;
1607 abi_ulong __unused2;
ths3eb6b042007-06-03 14:26:27 +00001608};
1609
1610struct target_semid_ds
1611{
1612 struct target_ipc_perm sem_perm;
blueswir1992f48a2007-10-14 16:27:31 +00001613 abi_ulong sem_otime;
1614 abi_ulong __unused1;
1615 abi_ulong sem_ctime;
1616 abi_ulong __unused2;
1617 abi_ulong sem_nsems;
1618 abi_ulong __unused3;
1619 abi_ulong __unused4;
ths3eb6b042007-06-03 14:26:27 +00001620};
1621
bellard579a97f2007-11-11 14:26:47 +00001622static inline abi_long target_to_host_ipc_perm(struct ipc_perm *host_ip,
1623 abi_ulong target_addr)
ths3eb6b042007-06-03 14:26:27 +00001624{
1625 struct target_ipc_perm *target_ip;
1626 struct target_semid_ds *target_sd;
1627
bellard579a97f2007-11-11 14:26:47 +00001628 if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
1629 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00001630 target_ip=&(target_sd->sem_perm);
1631 host_ip->__key = tswapl(target_ip->__key);
1632 host_ip->uid = tswapl(target_ip->uid);
1633 host_ip->gid = tswapl(target_ip->gid);
1634 host_ip->cuid = tswapl(target_ip->cuid);
1635 host_ip->cgid = tswapl(target_ip->cgid);
1636 host_ip->mode = tswapl(target_ip->mode);
1637 unlock_user_struct(target_sd, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00001638 return 0;
ths3eb6b042007-06-03 14:26:27 +00001639}
1640
bellard579a97f2007-11-11 14:26:47 +00001641static inline abi_long host_to_target_ipc_perm(abi_ulong target_addr,
1642 struct ipc_perm *host_ip)
ths3eb6b042007-06-03 14:26:27 +00001643{
1644 struct target_ipc_perm *target_ip;
1645 struct target_semid_ds *target_sd;
1646
bellard579a97f2007-11-11 14:26:47 +00001647 if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
1648 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00001649 target_ip = &(target_sd->sem_perm);
1650 target_ip->__key = tswapl(host_ip->__key);
1651 target_ip->uid = tswapl(host_ip->uid);
1652 target_ip->gid = tswapl(host_ip->gid);
1653 target_ip->cuid = tswapl(host_ip->cuid);
1654 target_ip->cgid = tswapl(host_ip->cgid);
1655 target_ip->mode = tswapl(host_ip->mode);
1656 unlock_user_struct(target_sd, target_addr, 1);
bellard579a97f2007-11-11 14:26:47 +00001657 return 0;
ths3eb6b042007-06-03 14:26:27 +00001658}
1659
bellard579a97f2007-11-11 14:26:47 +00001660static inline abi_long target_to_host_semid_ds(struct semid_ds *host_sd,
1661 abi_ulong target_addr)
ths3eb6b042007-06-03 14:26:27 +00001662{
1663 struct target_semid_ds *target_sd;
1664
bellard579a97f2007-11-11 14:26:47 +00001665 if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
1666 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00001667 target_to_host_ipc_perm(&(host_sd->sem_perm),target_addr);
1668 host_sd->sem_nsems = tswapl(target_sd->sem_nsems);
1669 host_sd->sem_otime = tswapl(target_sd->sem_otime);
1670 host_sd->sem_ctime = tswapl(target_sd->sem_ctime);
1671 unlock_user_struct(target_sd, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00001672 return 0;
ths3eb6b042007-06-03 14:26:27 +00001673}
1674
bellard579a97f2007-11-11 14:26:47 +00001675static inline abi_long host_to_target_semid_ds(abi_ulong target_addr,
1676 struct semid_ds *host_sd)
ths3eb6b042007-06-03 14:26:27 +00001677{
1678 struct target_semid_ds *target_sd;
1679
bellard579a97f2007-11-11 14:26:47 +00001680 if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
1681 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00001682 host_to_target_ipc_perm(target_addr,&(host_sd->sem_perm));
1683 target_sd->sem_nsems = tswapl(host_sd->sem_nsems);
1684 target_sd->sem_otime = tswapl(host_sd->sem_otime);
1685 target_sd->sem_ctime = tswapl(host_sd->sem_ctime);
1686 unlock_user_struct(target_sd, target_addr, 1);
bellard579a97f2007-11-11 14:26:47 +00001687 return 0;
ths3eb6b042007-06-03 14:26:27 +00001688}
1689
thsfa294812007-02-02 22:05:00 +00001690union semun {
1691 int val;
ths3eb6b042007-06-03 14:26:27 +00001692 struct semid_ds *buf;
thsfa294812007-02-02 22:05:00 +00001693 unsigned short *array;
1694};
1695
ths3eb6b042007-06-03 14:26:27 +00001696union target_semun {
1697 int val;
blueswir1992f48a2007-10-14 16:27:31 +00001698 abi_long buf;
ths3eb6b042007-06-03 14:26:27 +00001699 unsigned short int *array;
1700};
1701
bellard579a97f2007-11-11 14:26:47 +00001702static inline abi_long target_to_host_semun(int cmd,
1703 union semun *host_su,
1704 abi_ulong target_addr,
1705 struct semid_ds *ds)
ths3eb6b042007-06-03 14:26:27 +00001706{
1707 union target_semun *target_su;
1708
1709 switch( cmd ) {
1710 case IPC_STAT:
1711 case IPC_SET:
bellard579a97f2007-11-11 14:26:47 +00001712 if (!lock_user_struct(VERIFY_READ, target_su, target_addr, 1))
1713 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00001714 target_to_host_semid_ds(ds,target_su->buf);
1715 host_su->buf = ds;
1716 unlock_user_struct(target_su, target_addr, 0);
1717 break;
1718 case GETVAL:
1719 case SETVAL:
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->val = tswapl(target_su->val);
1723 unlock_user_struct(target_su, target_addr, 0);
1724 break;
1725 case GETALL:
1726 case SETALL:
bellard579a97f2007-11-11 14:26:47 +00001727 if (!lock_user_struct(VERIFY_READ, target_su, target_addr, 1))
1728 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00001729 *host_su->array = tswap16(*target_su->array);
1730 unlock_user_struct(target_su, target_addr, 0);
1731 break;
1732 default:
1733 gemu_log("semun operation not fully supported: %d\n", (int)cmd);
1734 }
bellard579a97f2007-11-11 14:26:47 +00001735 return 0;
ths3eb6b042007-06-03 14:26:27 +00001736}
1737
bellard579a97f2007-11-11 14:26:47 +00001738static inline abi_long host_to_target_semun(int cmd,
1739 abi_ulong target_addr,
1740 union semun *host_su,
1741 struct semid_ds *ds)
ths3eb6b042007-06-03 14:26:27 +00001742{
1743 union target_semun *target_su;
1744
1745 switch( cmd ) {
1746 case IPC_STAT:
1747 case IPC_SET:
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 host_to_target_semid_ds(target_su->buf,ds);
1751 unlock_user_struct(target_su, target_addr, 1);
1752 break;
1753 case GETVAL:
1754 case SETVAL:
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->val = tswapl(host_su->val);
1758 unlock_user_struct(target_su, target_addr, 1);
1759 break;
1760 case GETALL:
1761 case SETALL:
bellard579a97f2007-11-11 14:26:47 +00001762 if (lock_user_struct(VERIFY_WRITE, target_su, target_addr, 0))
1763 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00001764 *target_su->array = tswap16(*host_su->array);
1765 unlock_user_struct(target_su, target_addr, 1);
1766 break;
1767 default:
1768 gemu_log("semun operation not fully supported: %d\n", (int)cmd);
1769 }
bellard579a97f2007-11-11 14:26:47 +00001770 return 0;
ths3eb6b042007-06-03 14:26:27 +00001771}
1772
blueswir1992f48a2007-10-14 16:27:31 +00001773static inline abi_long do_semctl(int first, int second, int third,
1774 abi_long ptr)
ths3eb6b042007-06-03 14:26:27 +00001775{
1776 union semun arg;
1777 struct semid_ds dsarg;
1778 int cmd = third&0xff;
blueswir1992f48a2007-10-14 16:27:31 +00001779 abi_long ret = 0;
ths3eb6b042007-06-03 14:26:27 +00001780
1781 switch( cmd ) {
1782 case GETVAL:
1783 target_to_host_semun(cmd,&arg,ptr,&dsarg);
1784 ret = get_errno(semctl(first, second, cmd, arg));
1785 host_to_target_semun(cmd,ptr,&arg,&dsarg);
1786 break;
1787 case SETVAL:
1788 target_to_host_semun(cmd,&arg,ptr,&dsarg);
1789 ret = get_errno(semctl(first, second, cmd, arg));
1790 host_to_target_semun(cmd,ptr,&arg,&dsarg);
1791 break;
1792 case GETALL:
1793 target_to_host_semun(cmd,&arg,ptr,&dsarg);
1794 ret = get_errno(semctl(first, second, cmd, arg));
1795 host_to_target_semun(cmd,ptr,&arg,&dsarg);
1796 break;
1797 case SETALL:
1798 target_to_host_semun(cmd,&arg,ptr,&dsarg);
1799 ret = get_errno(semctl(first, second, cmd, arg));
1800 host_to_target_semun(cmd,ptr,&arg,&dsarg);
1801 break;
1802 case IPC_STAT:
1803 target_to_host_semun(cmd,&arg,ptr,&dsarg);
1804 ret = get_errno(semctl(first, second, cmd, arg));
1805 host_to_target_semun(cmd,ptr,&arg,&dsarg);
1806 break;
1807 case IPC_SET:
1808 target_to_host_semun(cmd,&arg,ptr,&dsarg);
1809 ret = get_errno(semctl(first, second, cmd, arg));
1810 host_to_target_semun(cmd,ptr,&arg,&dsarg);
1811 break;
1812 default:
1813 ret = get_errno(semctl(first, second, cmd, arg));
1814 }
1815
1816 return ret;
1817}
1818
ths1bc012f2007-06-03 14:27:49 +00001819struct target_msqid_ds
1820{
1821 struct target_ipc_perm msg_perm;
blueswir1992f48a2007-10-14 16:27:31 +00001822 abi_ulong msg_stime;
1823 abi_ulong __unused1;
1824 abi_ulong msg_rtime;
1825 abi_ulong __unused2;
1826 abi_ulong msg_ctime;
1827 abi_ulong __unused3;
1828 abi_ulong __msg_cbytes;
1829 abi_ulong msg_qnum;
1830 abi_ulong msg_qbytes;
1831 abi_ulong msg_lspid;
1832 abi_ulong msg_lrpid;
1833 abi_ulong __unused4;
1834 abi_ulong __unused5;
ths1bc012f2007-06-03 14:27:49 +00001835};
1836
bellard579a97f2007-11-11 14:26:47 +00001837static inline abi_long target_to_host_msqid_ds(struct msqid_ds *host_md,
1838 abi_ulong target_addr)
ths1bc012f2007-06-03 14:27:49 +00001839{
1840 struct target_msqid_ds *target_md;
1841
bellard579a97f2007-11-11 14:26:47 +00001842 if (!lock_user_struct(VERIFY_READ, target_md, target_addr, 1))
1843 return -TARGET_EFAULT;
ths1bc012f2007-06-03 14:27:49 +00001844 target_to_host_ipc_perm(&(host_md->msg_perm),target_addr);
1845 host_md->msg_stime = tswapl(target_md->msg_stime);
1846 host_md->msg_rtime = tswapl(target_md->msg_rtime);
1847 host_md->msg_ctime = tswapl(target_md->msg_ctime);
1848 host_md->__msg_cbytes = tswapl(target_md->__msg_cbytes);
1849 host_md->msg_qnum = tswapl(target_md->msg_qnum);
1850 host_md->msg_qbytes = tswapl(target_md->msg_qbytes);
1851 host_md->msg_lspid = tswapl(target_md->msg_lspid);
1852 host_md->msg_lrpid = tswapl(target_md->msg_lrpid);
1853 unlock_user_struct(target_md, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00001854 return 0;
ths1bc012f2007-06-03 14:27:49 +00001855}
1856
bellard579a97f2007-11-11 14:26:47 +00001857static inline abi_long host_to_target_msqid_ds(abi_ulong target_addr,
1858 struct msqid_ds *host_md)
ths1bc012f2007-06-03 14:27:49 +00001859{
1860 struct target_msqid_ds *target_md;
1861
bellard579a97f2007-11-11 14:26:47 +00001862 if (!lock_user_struct(VERIFY_WRITE, target_md, target_addr, 0))
1863 return -TARGET_EFAULT;
ths1bc012f2007-06-03 14:27:49 +00001864 host_to_target_ipc_perm(target_addr,&(host_md->msg_perm));
1865 target_md->msg_stime = tswapl(host_md->msg_stime);
1866 target_md->msg_rtime = tswapl(host_md->msg_rtime);
1867 target_md->msg_ctime = tswapl(host_md->msg_ctime);
1868 target_md->__msg_cbytes = tswapl(host_md->__msg_cbytes);
1869 target_md->msg_qnum = tswapl(host_md->msg_qnum);
1870 target_md->msg_qbytes = tswapl(host_md->msg_qbytes);
1871 target_md->msg_lspid = tswapl(host_md->msg_lspid);
1872 target_md->msg_lrpid = tswapl(host_md->msg_lrpid);
1873 unlock_user_struct(target_md, target_addr, 1);
bellard579a97f2007-11-11 14:26:47 +00001874 return 0;
ths1bc012f2007-06-03 14:27:49 +00001875}
1876
blueswir1992f48a2007-10-14 16:27:31 +00001877static inline abi_long do_msgctl(int first, int second, abi_long ptr)
ths1bc012f2007-06-03 14:27:49 +00001878{
1879 struct msqid_ds dsarg;
1880 int cmd = second&0xff;
blueswir1992f48a2007-10-14 16:27:31 +00001881 abi_long ret = 0;
ths1bc012f2007-06-03 14:27:49 +00001882 switch( cmd ) {
1883 case IPC_STAT:
1884 case IPC_SET:
1885 target_to_host_msqid_ds(&dsarg,ptr);
1886 ret = get_errno(msgctl(first, cmd, &dsarg));
1887 host_to_target_msqid_ds(ptr,&dsarg);
1888 default:
1889 ret = get_errno(msgctl(first, cmd, &dsarg));
1890 }
1891 return ret;
1892}
1893
1894struct target_msgbuf {
blueswir1992f48a2007-10-14 16:27:31 +00001895 abi_ulong mtype;
ths1bc012f2007-06-03 14:27:49 +00001896 char mtext[1];
1897};
1898
blueswir1992f48a2007-10-14 16:27:31 +00001899static inline abi_long do_msgsnd(int msqid, abi_long msgp,
1900 unsigned int msgsz, int msgflg)
ths1bc012f2007-06-03 14:27:49 +00001901{
1902 struct target_msgbuf *target_mb;
1903 struct msgbuf *host_mb;
blueswir1992f48a2007-10-14 16:27:31 +00001904 abi_long ret = 0;
ths1bc012f2007-06-03 14:27:49 +00001905
bellard579a97f2007-11-11 14:26:47 +00001906 if (!lock_user_struct(VERIFY_READ, target_mb, msgp, 0))
1907 return -TARGET_EFAULT;
ths1bc012f2007-06-03 14:27:49 +00001908 host_mb = malloc(msgsz+sizeof(long));
1909 host_mb->mtype = tswapl(target_mb->mtype);
1910 memcpy(host_mb->mtext,target_mb->mtext,msgsz);
1911 ret = get_errno(msgsnd(msqid, host_mb, msgsz, msgflg));
1912 free(host_mb);
1913 unlock_user_struct(target_mb, msgp, 0);
1914
1915 return ret;
1916}
1917
blueswir1992f48a2007-10-14 16:27:31 +00001918static inline abi_long do_msgrcv(int msqid, abi_long msgp,
1919 unsigned int msgsz, int msgtype,
1920 int msgflg)
ths1bc012f2007-06-03 14:27:49 +00001921{
1922 struct target_msgbuf *target_mb;
bellard579a97f2007-11-11 14:26:47 +00001923 char *target_mtext;
ths1bc012f2007-06-03 14:27:49 +00001924 struct msgbuf *host_mb;
blueswir1992f48a2007-10-14 16:27:31 +00001925 abi_long ret = 0;
ths1bc012f2007-06-03 14:27:49 +00001926
bellard579a97f2007-11-11 14:26:47 +00001927 if (!lock_user_struct(VERIFY_WRITE, target_mb, msgp, 0))
1928 return -TARGET_EFAULT;
ths1bc012f2007-06-03 14:27:49 +00001929 host_mb = malloc(msgsz+sizeof(long));
1930 ret = get_errno(msgrcv(msqid, host_mb, msgsz, 1, msgflg));
bellard579a97f2007-11-11 14:26:47 +00001931 if (ret > 0) {
1932 abi_ulong target_mtext_addr = msgp + sizeof(abi_ulong);
1933 target_mtext = lock_user(VERIFY_WRITE, target_mtext_addr, ret, 0);
1934 if (!target_mtext) {
1935 ret = -TARGET_EFAULT;
1936 goto end;
1937 }
ths1bc012f2007-06-03 14:27:49 +00001938 memcpy(target_mb->mtext, host_mb->mtext, ret);
bellard579a97f2007-11-11 14:26:47 +00001939 unlock_user(target_mtext, target_mtext_addr, ret);
1940 }
ths1bc012f2007-06-03 14:27:49 +00001941 target_mb->mtype = tswapl(host_mb->mtype);
1942 free(host_mb);
ths1bc012f2007-06-03 14:27:49 +00001943
bellard579a97f2007-11-11 14:26:47 +00001944end:
1945 if (target_mb)
1946 unlock_user_struct(target_mb, msgp, 1);
ths1bc012f2007-06-03 14:27:49 +00001947 return ret;
1948}
1949
pbrook53a59602006-03-25 19:31:22 +00001950/* ??? This only works with linear mappings. */
ths0da46a62007-10-20 20:23:07 +00001951/* do_ipc() must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001952static abi_long do_ipc(unsigned int call, int first,
1953 int second, int third,
1954 abi_long ptr, abi_long fifth)
bellard8853f862004-02-22 14:57:26 +00001955{
1956 int version;
blueswir1992f48a2007-10-14 16:27:31 +00001957 abi_long ret = 0;
bellard8853f862004-02-22 14:57:26 +00001958 struct shmid_ds shm_info;
1959 int i;
1960
1961 version = call >> 16;
1962 call &= 0xffff;
1963
1964 switch (call) {
thsfa294812007-02-02 22:05:00 +00001965 case IPCOP_semop:
bellard579a97f2007-11-11 14:26:47 +00001966 ret = get_errno(semop(first,(struct sembuf *)g2h(ptr), second));
thsfa294812007-02-02 22:05:00 +00001967 break;
1968
1969 case IPCOP_semget:
1970 ret = get_errno(semget(first, second, third));
1971 break;
1972
1973 case IPCOP_semctl:
ths3eb6b042007-06-03 14:26:27 +00001974 ret = do_semctl(first, second, third, ptr);
thsfa294812007-02-02 22:05:00 +00001975 break;
1976
1977 case IPCOP_semtimedop:
j_mayer32407102007-09-26 23:01:49 +00001978 gemu_log("Unsupported ipc call: %d (version %d)\n", call, version);
ths0da46a62007-10-20 20:23:07 +00001979 ret = -TARGET_ENOSYS;
thsfa294812007-02-02 22:05:00 +00001980 break;
thsd96372e2007-02-02 22:05:44 +00001981
1982 case IPCOP_msgget:
1983 ret = get_errno(msgget(first, second));
1984 break;
1985
1986 case IPCOP_msgsnd:
ths1bc012f2007-06-03 14:27:49 +00001987 ret = do_msgsnd(first, ptr, second, third);
thsd96372e2007-02-02 22:05:44 +00001988 break;
1989
1990 case IPCOP_msgctl:
ths1bc012f2007-06-03 14:27:49 +00001991 ret = do_msgctl(first, second, ptr);
thsd96372e2007-02-02 22:05:44 +00001992 break;
1993
1994 case IPCOP_msgrcv:
ths1bc012f2007-06-03 14:27:49 +00001995 {
bellard579a97f2007-11-11 14:26:47 +00001996 /* XXX: this code is not correct */
ths1bc012f2007-06-03 14:27:49 +00001997 struct ipc_kludge
1998 {
1999 void *__unbounded msgp;
2000 long int msgtyp;
2001 };
thsd96372e2007-02-02 22:05:44 +00002002
bellard579a97f2007-11-11 14:26:47 +00002003 struct ipc_kludge *foo = (struct ipc_kludge *)g2h(ptr);
ths1bc012f2007-06-03 14:27:49 +00002004 struct msgbuf *msgp = (struct msgbuf *) foo->msgp;
thsd96372e2007-02-02 22:05:44 +00002005
ths1bc012f2007-06-03 14:27:49 +00002006 ret = do_msgrcv(first, (long)msgp, second, 0, third);
thsd96372e2007-02-02 22:05:44 +00002007
ths1bc012f2007-06-03 14:27:49 +00002008 }
thsd96372e2007-02-02 22:05:44 +00002009 break;
2010
bellard8853f862004-02-22 14:57:26 +00002011 case IPCOP_shmat:
bellard5a4a8982007-11-11 17:39:18 +00002012 {
2013 abi_ulong raddr;
2014 void *host_addr;
2015 /* SHM_* flags are the same on all linux platforms */
2016 host_addr = shmat(first, (void *)g2h(ptr), second);
2017 if (host_addr == (void *)-1) {
2018 ret = get_errno((long)host_addr);
bellard8853f862004-02-22 14:57:26 +00002019 break;
bellard5a4a8982007-11-11 17:39:18 +00002020 }
2021 raddr = h2g((unsigned long)host_addr);
2022 /* find out the length of the shared memory segment */
2023
2024 ret = get_errno(shmctl(first, IPC_STAT, &shm_info));
2025 if (is_error(ret)) {
2026 /* can't get length, bail out */
2027 shmdt(host_addr);
2028 break;
2029 }
2030 page_set_flags(raddr, raddr + shm_info.shm_segsz,
2031 PAGE_VALID | PAGE_READ |
2032 ((second & SHM_RDONLY)? 0: PAGE_WRITE));
2033 for (i = 0; i < N_SHM_REGIONS; ++i) {
2034 if (shm_regions[i].start == 0) {
2035 shm_regions[i].start = raddr;
2036 shm_regions[i].size = shm_info.shm_segsz;
2037 break;
2038 }
2039 }
bellard2f619692007-11-16 10:46:05 +00002040 if (put_user_ual(raddr, third))
bellard5a4a8982007-11-11 17:39:18 +00002041 return -TARGET_EFAULT;
2042 ret = 0;
2043 }
bellard8853f862004-02-22 14:57:26 +00002044 break;
2045 case IPCOP_shmdt:
2046 for (i = 0; i < N_SHM_REGIONS; ++i) {
2047 if (shm_regions[i].start == ptr) {
2048 shm_regions[i].start = 0;
2049 page_set_flags(ptr, shm_regions[i].size, 0);
2050 break;
2051 }
2052 }
bellard5a4a8982007-11-11 17:39:18 +00002053 ret = get_errno(shmdt((void *)g2h(ptr)));
bellard8853f862004-02-22 14:57:26 +00002054 break;
2055
2056 case IPCOP_shmget:
2057 /* IPC_* flag values are the same on all linux platforms */
2058 ret = get_errno(shmget(first, second, third));
2059 break;
2060
2061 /* IPC_* and SHM_* command values are the same on all linux platforms */
2062 case IPCOP_shmctl:
2063 switch(second) {
2064 case IPC_RMID:
2065 case SHM_LOCK:
2066 case SHM_UNLOCK:
2067 ret = get_errno(shmctl(first, second, NULL));
2068 break;
2069 default:
2070 goto unimplemented;
2071 }
2072 break;
2073 default:
2074 unimplemented:
j_mayer32407102007-09-26 23:01:49 +00002075 gemu_log("Unsupported ipc call: %d (version %d)\n", call, version);
ths0da46a62007-10-20 20:23:07 +00002076 ret = -TARGET_ENOSYS;
bellard8853f862004-02-22 14:57:26 +00002077 break;
2078 }
2079 return ret;
2080}
j_mayer32407102007-09-26 23:01:49 +00002081#endif
bellard8853f862004-02-22 14:57:26 +00002082
bellard31e31b82003-02-18 22:55:36 +00002083/* kernel structure types definitions */
2084#define IFNAMSIZ 16
2085
2086#define STRUCT(name, list...) STRUCT_ ## name,
2087#define STRUCT_SPECIAL(name) STRUCT_ ## name,
2088enum {
2089#include "syscall_types.h"
2090};
2091#undef STRUCT
2092#undef STRUCT_SPECIAL
2093
2094#define STRUCT(name, list...) const argtype struct_ ## name ## _def[] = { list, TYPE_NULL };
2095#define STRUCT_SPECIAL(name)
2096#include "syscall_types.h"
2097#undef STRUCT
2098#undef STRUCT_SPECIAL
2099
2100typedef struct IOCTLEntry {
bellard2ab83ea2003-06-15 19:56:46 +00002101 unsigned int target_cmd;
2102 unsigned int host_cmd;
bellard31e31b82003-02-18 22:55:36 +00002103 const char *name;
2104 int access;
bellard1a9353d2003-03-16 20:28:50 +00002105 const argtype arg_type[5];
bellard31e31b82003-02-18 22:55:36 +00002106} IOCTLEntry;
2107
2108#define IOC_R 0x0001
2109#define IOC_W 0x0002
2110#define IOC_RW (IOC_R | IOC_W)
2111
2112#define MAX_STRUCT_SIZE 4096
2113
bellard2ab83ea2003-06-15 19:56:46 +00002114IOCTLEntry ioctl_entries[] = {
bellard31e31b82003-02-18 22:55:36 +00002115#define IOCTL(cmd, access, types...) \
2116 { TARGET_ ## cmd, cmd, #cmd, access, { types } },
2117#include "ioctls.h"
2118 { 0, 0, },
2119};
2120
pbrook53a59602006-03-25 19:31:22 +00002121/* ??? Implement proper locking for ioctls. */
ths0da46a62007-10-20 20:23:07 +00002122/* do_ioctl() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00002123static abi_long do_ioctl(int fd, abi_long cmd, abi_long arg)
bellard31e31b82003-02-18 22:55:36 +00002124{
2125 const IOCTLEntry *ie;
2126 const argtype *arg_type;
blueswir1992f48a2007-10-14 16:27:31 +00002127 abi_long ret;
bellard31e31b82003-02-18 22:55:36 +00002128 uint8_t buf_temp[MAX_STRUCT_SIZE];
pbrook53a59602006-03-25 19:31:22 +00002129 int target_size;
2130 void *argptr;
bellard31e31b82003-02-18 22:55:36 +00002131
2132 ie = ioctl_entries;
2133 for(;;) {
2134 if (ie->target_cmd == 0) {
j_mayer32407102007-09-26 23:01:49 +00002135 gemu_log("Unsupported ioctl: cmd=0x%04lx\n", (long)cmd);
ths0da46a62007-10-20 20:23:07 +00002136 return -TARGET_ENOSYS;
bellard31e31b82003-02-18 22:55:36 +00002137 }
2138 if (ie->target_cmd == cmd)
2139 break;
2140 ie++;
2141 }
2142 arg_type = ie->arg_type;
bellard9de5e442003-03-23 16:49:39 +00002143#if defined(DEBUG)
j_mayer32407102007-09-26 23:01:49 +00002144 gemu_log("ioctl: cmd=0x%04lx (%s)\n", (long)cmd, ie->name);
bellard72f03902003-02-18 23:33:18 +00002145#endif
bellard31e31b82003-02-18 22:55:36 +00002146 switch(arg_type[0]) {
2147 case TYPE_NULL:
2148 /* no argument */
2149 ret = get_errno(ioctl(fd, ie->host_cmd));
2150 break;
2151 case TYPE_PTRVOID:
2152 case TYPE_INT:
2153 /* int argment */
2154 ret = get_errno(ioctl(fd, ie->host_cmd, arg));
2155 break;
2156 case TYPE_PTR:
2157 arg_type++;
pbrook53a59602006-03-25 19:31:22 +00002158 target_size = thunk_type_size(arg_type, 0);
bellard31e31b82003-02-18 22:55:36 +00002159 switch(ie->access) {
2160 case IOC_R:
2161 ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
2162 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00002163 argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
2164 if (!argptr)
2165 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00002166 thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
2167 unlock_user(argptr, arg, target_size);
bellard31e31b82003-02-18 22:55:36 +00002168 }
2169 break;
2170 case IOC_W:
bellard579a97f2007-11-11 14:26:47 +00002171 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
2172 if (!argptr)
2173 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00002174 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
2175 unlock_user(argptr, arg, 0);
bellard31e31b82003-02-18 22:55:36 +00002176 ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
2177 break;
2178 default:
2179 case IOC_RW:
bellard579a97f2007-11-11 14:26:47 +00002180 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
2181 if (!argptr)
2182 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00002183 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
2184 unlock_user(argptr, arg, 0);
bellard31e31b82003-02-18 22:55:36 +00002185 ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
2186 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00002187 argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
2188 if (!argptr)
2189 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00002190 thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
2191 unlock_user(argptr, arg, target_size);
bellard31e31b82003-02-18 22:55:36 +00002192 }
2193 break;
2194 }
2195 break;
2196 default:
j_mayer32407102007-09-26 23:01:49 +00002197 gemu_log("Unsupported ioctl type: cmd=0x%04lx type=%d\n",
2198 (long)cmd, arg_type[0]);
ths0da46a62007-10-20 20:23:07 +00002199 ret = -TARGET_ENOSYS;
bellard31e31b82003-02-18 22:55:36 +00002200 break;
2201 }
2202 return ret;
2203}
2204
2205bitmask_transtbl iflag_tbl[] = {
2206 { TARGET_IGNBRK, TARGET_IGNBRK, IGNBRK, IGNBRK },
2207 { TARGET_BRKINT, TARGET_BRKINT, BRKINT, BRKINT },
2208 { TARGET_IGNPAR, TARGET_IGNPAR, IGNPAR, IGNPAR },
2209 { TARGET_PARMRK, TARGET_PARMRK, PARMRK, PARMRK },
2210 { TARGET_INPCK, TARGET_INPCK, INPCK, INPCK },
2211 { TARGET_ISTRIP, TARGET_ISTRIP, ISTRIP, ISTRIP },
2212 { TARGET_INLCR, TARGET_INLCR, INLCR, INLCR },
2213 { TARGET_IGNCR, TARGET_IGNCR, IGNCR, IGNCR },
2214 { TARGET_ICRNL, TARGET_ICRNL, ICRNL, ICRNL },
2215 { TARGET_IUCLC, TARGET_IUCLC, IUCLC, IUCLC },
2216 { TARGET_IXON, TARGET_IXON, IXON, IXON },
2217 { TARGET_IXANY, TARGET_IXANY, IXANY, IXANY },
2218 { TARGET_IXOFF, TARGET_IXOFF, IXOFF, IXOFF },
2219 { TARGET_IMAXBEL, TARGET_IMAXBEL, IMAXBEL, IMAXBEL },
2220 { 0, 0, 0, 0 }
2221};
2222
2223bitmask_transtbl oflag_tbl[] = {
2224 { TARGET_OPOST, TARGET_OPOST, OPOST, OPOST },
2225 { TARGET_OLCUC, TARGET_OLCUC, OLCUC, OLCUC },
2226 { TARGET_ONLCR, TARGET_ONLCR, ONLCR, ONLCR },
2227 { TARGET_OCRNL, TARGET_OCRNL, OCRNL, OCRNL },
2228 { TARGET_ONOCR, TARGET_ONOCR, ONOCR, ONOCR },
2229 { TARGET_ONLRET, TARGET_ONLRET, ONLRET, ONLRET },
2230 { TARGET_OFILL, TARGET_OFILL, OFILL, OFILL },
2231 { TARGET_OFDEL, TARGET_OFDEL, OFDEL, OFDEL },
2232 { TARGET_NLDLY, TARGET_NL0, NLDLY, NL0 },
2233 { TARGET_NLDLY, TARGET_NL1, NLDLY, NL1 },
2234 { TARGET_CRDLY, TARGET_CR0, CRDLY, CR0 },
2235 { TARGET_CRDLY, TARGET_CR1, CRDLY, CR1 },
2236 { TARGET_CRDLY, TARGET_CR2, CRDLY, CR2 },
2237 { TARGET_CRDLY, TARGET_CR3, CRDLY, CR3 },
2238 { TARGET_TABDLY, TARGET_TAB0, TABDLY, TAB0 },
2239 { TARGET_TABDLY, TARGET_TAB1, TABDLY, TAB1 },
2240 { TARGET_TABDLY, TARGET_TAB2, TABDLY, TAB2 },
2241 { TARGET_TABDLY, TARGET_TAB3, TABDLY, TAB3 },
2242 { TARGET_BSDLY, TARGET_BS0, BSDLY, BS0 },
2243 { TARGET_BSDLY, TARGET_BS1, BSDLY, BS1 },
2244 { TARGET_VTDLY, TARGET_VT0, VTDLY, VT0 },
2245 { TARGET_VTDLY, TARGET_VT1, VTDLY, VT1 },
2246 { TARGET_FFDLY, TARGET_FF0, FFDLY, FF0 },
2247 { TARGET_FFDLY, TARGET_FF1, FFDLY, FF1 },
2248 { 0, 0, 0, 0 }
2249};
2250
2251bitmask_transtbl cflag_tbl[] = {
2252 { TARGET_CBAUD, TARGET_B0, CBAUD, B0 },
2253 { TARGET_CBAUD, TARGET_B50, CBAUD, B50 },
2254 { TARGET_CBAUD, TARGET_B75, CBAUD, B75 },
2255 { TARGET_CBAUD, TARGET_B110, CBAUD, B110 },
2256 { TARGET_CBAUD, TARGET_B134, CBAUD, B134 },
2257 { TARGET_CBAUD, TARGET_B150, CBAUD, B150 },
2258 { TARGET_CBAUD, TARGET_B200, CBAUD, B200 },
2259 { TARGET_CBAUD, TARGET_B300, CBAUD, B300 },
2260 { TARGET_CBAUD, TARGET_B600, CBAUD, B600 },
2261 { TARGET_CBAUD, TARGET_B1200, CBAUD, B1200 },
2262 { TARGET_CBAUD, TARGET_B1800, CBAUD, B1800 },
2263 { TARGET_CBAUD, TARGET_B2400, CBAUD, B2400 },
2264 { TARGET_CBAUD, TARGET_B4800, CBAUD, B4800 },
2265 { TARGET_CBAUD, TARGET_B9600, CBAUD, B9600 },
2266 { TARGET_CBAUD, TARGET_B19200, CBAUD, B19200 },
2267 { TARGET_CBAUD, TARGET_B38400, CBAUD, B38400 },
2268 { TARGET_CBAUD, TARGET_B57600, CBAUD, B57600 },
2269 { TARGET_CBAUD, TARGET_B115200, CBAUD, B115200 },
2270 { TARGET_CBAUD, TARGET_B230400, CBAUD, B230400 },
2271 { TARGET_CBAUD, TARGET_B460800, CBAUD, B460800 },
2272 { TARGET_CSIZE, TARGET_CS5, CSIZE, CS5 },
2273 { TARGET_CSIZE, TARGET_CS6, CSIZE, CS6 },
2274 { TARGET_CSIZE, TARGET_CS7, CSIZE, CS7 },
2275 { TARGET_CSIZE, TARGET_CS8, CSIZE, CS8 },
2276 { TARGET_CSTOPB, TARGET_CSTOPB, CSTOPB, CSTOPB },
2277 { TARGET_CREAD, TARGET_CREAD, CREAD, CREAD },
2278 { TARGET_PARENB, TARGET_PARENB, PARENB, PARENB },
2279 { TARGET_PARODD, TARGET_PARODD, PARODD, PARODD },
2280 { TARGET_HUPCL, TARGET_HUPCL, HUPCL, HUPCL },
2281 { TARGET_CLOCAL, TARGET_CLOCAL, CLOCAL, CLOCAL },
2282 { TARGET_CRTSCTS, TARGET_CRTSCTS, CRTSCTS, CRTSCTS },
2283 { 0, 0, 0, 0 }
2284};
2285
2286bitmask_transtbl lflag_tbl[] = {
2287 { TARGET_ISIG, TARGET_ISIG, ISIG, ISIG },
2288 { TARGET_ICANON, TARGET_ICANON, ICANON, ICANON },
2289 { TARGET_XCASE, TARGET_XCASE, XCASE, XCASE },
2290 { TARGET_ECHO, TARGET_ECHO, ECHO, ECHO },
2291 { TARGET_ECHOE, TARGET_ECHOE, ECHOE, ECHOE },
2292 { TARGET_ECHOK, TARGET_ECHOK, ECHOK, ECHOK },
2293 { TARGET_ECHONL, TARGET_ECHONL, ECHONL, ECHONL },
2294 { TARGET_NOFLSH, TARGET_NOFLSH, NOFLSH, NOFLSH },
2295 { TARGET_TOSTOP, TARGET_TOSTOP, TOSTOP, TOSTOP },
2296 { TARGET_ECHOCTL, TARGET_ECHOCTL, ECHOCTL, ECHOCTL },
2297 { TARGET_ECHOPRT, TARGET_ECHOPRT, ECHOPRT, ECHOPRT },
2298 { TARGET_ECHOKE, TARGET_ECHOKE, ECHOKE, ECHOKE },
2299 { TARGET_FLUSHO, TARGET_FLUSHO, FLUSHO, FLUSHO },
2300 { TARGET_PENDIN, TARGET_PENDIN, PENDIN, PENDIN },
2301 { TARGET_IEXTEN, TARGET_IEXTEN, IEXTEN, IEXTEN },
2302 { 0, 0, 0, 0 }
2303};
2304
2305static void target_to_host_termios (void *dst, const void *src)
2306{
2307 struct host_termios *host = dst;
2308 const struct target_termios *target = src;
ths3b46e622007-09-17 08:09:54 +00002309
ths5fafdf22007-09-16 21:08:06 +00002310 host->c_iflag =
bellard31e31b82003-02-18 22:55:36 +00002311 target_to_host_bitmask(tswap32(target->c_iflag), iflag_tbl);
ths5fafdf22007-09-16 21:08:06 +00002312 host->c_oflag =
bellard31e31b82003-02-18 22:55:36 +00002313 target_to_host_bitmask(tswap32(target->c_oflag), oflag_tbl);
ths5fafdf22007-09-16 21:08:06 +00002314 host->c_cflag =
bellard31e31b82003-02-18 22:55:36 +00002315 target_to_host_bitmask(tswap32(target->c_cflag), cflag_tbl);
ths5fafdf22007-09-16 21:08:06 +00002316 host->c_lflag =
bellard31e31b82003-02-18 22:55:36 +00002317 target_to_host_bitmask(tswap32(target->c_lflag), lflag_tbl);
2318 host->c_line = target->c_line;
ths3b46e622007-09-17 08:09:54 +00002319
ths5fafdf22007-09-16 21:08:06 +00002320 host->c_cc[VINTR] = target->c_cc[TARGET_VINTR];
2321 host->c_cc[VQUIT] = target->c_cc[TARGET_VQUIT];
ths3b46e622007-09-17 08:09:54 +00002322 host->c_cc[VERASE] = target->c_cc[TARGET_VERASE];
ths5fafdf22007-09-16 21:08:06 +00002323 host->c_cc[VKILL] = target->c_cc[TARGET_VKILL];
ths3b46e622007-09-17 08:09:54 +00002324 host->c_cc[VEOF] = target->c_cc[TARGET_VEOF];
ths5fafdf22007-09-16 21:08:06 +00002325 host->c_cc[VTIME] = target->c_cc[TARGET_VTIME];
ths3b46e622007-09-17 08:09:54 +00002326 host->c_cc[VMIN] = target->c_cc[TARGET_VMIN];
ths5fafdf22007-09-16 21:08:06 +00002327 host->c_cc[VSWTC] = target->c_cc[TARGET_VSWTC];
ths3b46e622007-09-17 08:09:54 +00002328 host->c_cc[VSTART] = target->c_cc[TARGET_VSTART];
ths5fafdf22007-09-16 21:08:06 +00002329 host->c_cc[VSTOP] = target->c_cc[TARGET_VSTOP];
2330 host->c_cc[VSUSP] = target->c_cc[TARGET_VSUSP];
ths3b46e622007-09-17 08:09:54 +00002331 host->c_cc[VEOL] = target->c_cc[TARGET_VEOL];
2332 host->c_cc[VREPRINT] = target->c_cc[TARGET_VREPRINT];
2333 host->c_cc[VDISCARD] = target->c_cc[TARGET_VDISCARD];
2334 host->c_cc[VWERASE] = target->c_cc[TARGET_VWERASE];
2335 host->c_cc[VLNEXT] = target->c_cc[TARGET_VLNEXT];
ths5fafdf22007-09-16 21:08:06 +00002336 host->c_cc[VEOL2] = target->c_cc[TARGET_VEOL2];
bellard31e31b82003-02-18 22:55:36 +00002337}
ths3b46e622007-09-17 08:09:54 +00002338
bellard31e31b82003-02-18 22:55:36 +00002339static void host_to_target_termios (void *dst, const void *src)
2340{
2341 struct target_termios *target = dst;
2342 const struct host_termios *host = src;
2343
ths5fafdf22007-09-16 21:08:06 +00002344 target->c_iflag =
bellard31e31b82003-02-18 22:55:36 +00002345 tswap32(host_to_target_bitmask(host->c_iflag, iflag_tbl));
ths5fafdf22007-09-16 21:08:06 +00002346 target->c_oflag =
bellard31e31b82003-02-18 22:55:36 +00002347 tswap32(host_to_target_bitmask(host->c_oflag, oflag_tbl));
ths5fafdf22007-09-16 21:08:06 +00002348 target->c_cflag =
bellard31e31b82003-02-18 22:55:36 +00002349 tswap32(host_to_target_bitmask(host->c_cflag, cflag_tbl));
ths5fafdf22007-09-16 21:08:06 +00002350 target->c_lflag =
bellard31e31b82003-02-18 22:55:36 +00002351 tswap32(host_to_target_bitmask(host->c_lflag, lflag_tbl));
2352 target->c_line = host->c_line;
ths3b46e622007-09-17 08:09:54 +00002353
bellard31e31b82003-02-18 22:55:36 +00002354 target->c_cc[TARGET_VINTR] = host->c_cc[VINTR];
2355 target->c_cc[TARGET_VQUIT] = host->c_cc[VQUIT];
2356 target->c_cc[TARGET_VERASE] = host->c_cc[VERASE];
2357 target->c_cc[TARGET_VKILL] = host->c_cc[VKILL];
2358 target->c_cc[TARGET_VEOF] = host->c_cc[VEOF];
2359 target->c_cc[TARGET_VTIME] = host->c_cc[VTIME];
2360 target->c_cc[TARGET_VMIN] = host->c_cc[VMIN];
2361 target->c_cc[TARGET_VSWTC] = host->c_cc[VSWTC];
2362 target->c_cc[TARGET_VSTART] = host->c_cc[VSTART];
2363 target->c_cc[TARGET_VSTOP] = host->c_cc[VSTOP];
2364 target->c_cc[TARGET_VSUSP] = host->c_cc[VSUSP];
2365 target->c_cc[TARGET_VEOL] = host->c_cc[VEOL];
2366 target->c_cc[TARGET_VREPRINT] = host->c_cc[VREPRINT];
2367 target->c_cc[TARGET_VDISCARD] = host->c_cc[VDISCARD];
2368 target->c_cc[TARGET_VWERASE] = host->c_cc[VWERASE];
2369 target->c_cc[TARGET_VLNEXT] = host->c_cc[VLNEXT];
2370 target->c_cc[TARGET_VEOL2] = host->c_cc[VEOL2];
2371}
2372
2373StructEntry struct_termios_def = {
2374 .convert = { host_to_target_termios, target_to_host_termios },
2375 .size = { sizeof(struct target_termios), sizeof(struct host_termios) },
2376 .align = { __alignof__(struct target_termios), __alignof__(struct host_termios) },
2377};
2378
bellard5286db72003-06-05 00:57:30 +00002379static bitmask_transtbl mmap_flags_tbl[] = {
2380 { TARGET_MAP_SHARED, TARGET_MAP_SHARED, MAP_SHARED, MAP_SHARED },
2381 { TARGET_MAP_PRIVATE, TARGET_MAP_PRIVATE, MAP_PRIVATE, MAP_PRIVATE },
2382 { TARGET_MAP_FIXED, TARGET_MAP_FIXED, MAP_FIXED, MAP_FIXED },
2383 { TARGET_MAP_ANONYMOUS, TARGET_MAP_ANONYMOUS, MAP_ANONYMOUS, MAP_ANONYMOUS },
2384 { TARGET_MAP_GROWSDOWN, TARGET_MAP_GROWSDOWN, MAP_GROWSDOWN, MAP_GROWSDOWN },
2385 { TARGET_MAP_DENYWRITE, TARGET_MAP_DENYWRITE, MAP_DENYWRITE, MAP_DENYWRITE },
2386 { TARGET_MAP_EXECUTABLE, TARGET_MAP_EXECUTABLE, MAP_EXECUTABLE, MAP_EXECUTABLE },
2387 { TARGET_MAP_LOCKED, TARGET_MAP_LOCKED, MAP_LOCKED, MAP_LOCKED },
2388 { 0, 0, 0, 0 }
2389};
2390
bellardffa65c32004-01-04 23:57:22 +00002391static bitmask_transtbl fcntl_flags_tbl[] = {
2392 { TARGET_O_ACCMODE, TARGET_O_WRONLY, O_ACCMODE, O_WRONLY, },
2393 { TARGET_O_ACCMODE, TARGET_O_RDWR, O_ACCMODE, O_RDWR, },
2394 { TARGET_O_CREAT, TARGET_O_CREAT, O_CREAT, O_CREAT, },
2395 { TARGET_O_EXCL, TARGET_O_EXCL, O_EXCL, O_EXCL, },
2396 { TARGET_O_NOCTTY, TARGET_O_NOCTTY, O_NOCTTY, O_NOCTTY, },
2397 { TARGET_O_TRUNC, TARGET_O_TRUNC, O_TRUNC, O_TRUNC, },
2398 { TARGET_O_APPEND, TARGET_O_APPEND, O_APPEND, O_APPEND, },
2399 { TARGET_O_NONBLOCK, TARGET_O_NONBLOCK, O_NONBLOCK, O_NONBLOCK, },
2400 { TARGET_O_SYNC, TARGET_O_SYNC, O_SYNC, O_SYNC, },
2401 { TARGET_FASYNC, TARGET_FASYNC, FASYNC, FASYNC, },
2402 { TARGET_O_DIRECTORY, TARGET_O_DIRECTORY, O_DIRECTORY, O_DIRECTORY, },
2403 { TARGET_O_NOFOLLOW, TARGET_O_NOFOLLOW, O_NOFOLLOW, O_NOFOLLOW, },
2404 { TARGET_O_LARGEFILE, TARGET_O_LARGEFILE, O_LARGEFILE, O_LARGEFILE, },
bellard121061d2004-02-22 11:56:01 +00002405#if defined(O_DIRECT)
bellardffa65c32004-01-04 23:57:22 +00002406 { TARGET_O_DIRECT, TARGET_O_DIRECT, O_DIRECT, O_DIRECT, },
bellard121061d2004-02-22 11:56:01 +00002407#endif
bellardffa65c32004-01-04 23:57:22 +00002408 { 0, 0, 0, 0 }
2409};
2410
bellard2ab83ea2003-06-15 19:56:46 +00002411#if defined(TARGET_I386)
bellard6dbad632003-03-16 18:05:05 +00002412
2413/* NOTE: there is really one LDT for all the threads */
2414uint8_t *ldt_table;
2415
bellard03acab62007-11-11 14:57:14 +00002416static abi_long read_ldt(abi_ulong ptr, unsigned long bytecount)
bellard6dbad632003-03-16 18:05:05 +00002417{
2418 int size;
pbrook53a59602006-03-25 19:31:22 +00002419 void *p;
bellard6dbad632003-03-16 18:05:05 +00002420
2421 if (!ldt_table)
2422 return 0;
2423 size = TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE;
2424 if (size > bytecount)
2425 size = bytecount;
bellard579a97f2007-11-11 14:26:47 +00002426 p = lock_user(VERIFY_WRITE, ptr, size, 0);
2427 if (!p)
bellard03acab62007-11-11 14:57:14 +00002428 return -TARGET_EFAULT;
bellard579a97f2007-11-11 14:26:47 +00002429 /* ??? Should this by byteswapped? */
pbrook53a59602006-03-25 19:31:22 +00002430 memcpy(p, ldt_table, size);
2431 unlock_user(p, ptr, size);
bellard6dbad632003-03-16 18:05:05 +00002432 return size;
2433}
2434
2435/* XXX: add locking support */
bellard03acab62007-11-11 14:57:14 +00002436static abi_long write_ldt(CPUX86State *env,
2437 abi_ulong ptr, unsigned long bytecount, int oldmode)
bellard6dbad632003-03-16 18:05:05 +00002438{
2439 struct target_modify_ldt_ldt_s ldt_info;
pbrook53a59602006-03-25 19:31:22 +00002440 struct target_modify_ldt_ldt_s *target_ldt_info;
bellard6dbad632003-03-16 18:05:05 +00002441 int seg_32bit, contents, read_exec_only, limit_in_pages;
bellard8d18e892007-11-14 15:18:40 +00002442 int seg_not_present, useable, lm;
bellard6dbad632003-03-16 18:05:05 +00002443 uint32_t *lp, entry_1, entry_2;
2444
2445 if (bytecount != sizeof(ldt_info))
bellard03acab62007-11-11 14:57:14 +00002446 return -TARGET_EINVAL;
bellard579a97f2007-11-11 14:26:47 +00002447 if (!lock_user_struct(VERIFY_READ, target_ldt_info, ptr, 1))
bellard03acab62007-11-11 14:57:14 +00002448 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00002449 ldt_info.entry_number = tswap32(target_ldt_info->entry_number);
2450 ldt_info.base_addr = tswapl(target_ldt_info->base_addr);
2451 ldt_info.limit = tswap32(target_ldt_info->limit);
2452 ldt_info.flags = tswap32(target_ldt_info->flags);
2453 unlock_user_struct(target_ldt_info, ptr, 0);
ths3b46e622007-09-17 08:09:54 +00002454
bellard6dbad632003-03-16 18:05:05 +00002455 if (ldt_info.entry_number >= TARGET_LDT_ENTRIES)
bellard03acab62007-11-11 14:57:14 +00002456 return -TARGET_EINVAL;
bellard6dbad632003-03-16 18:05:05 +00002457 seg_32bit = ldt_info.flags & 1;
2458 contents = (ldt_info.flags >> 1) & 3;
2459 read_exec_only = (ldt_info.flags >> 3) & 1;
2460 limit_in_pages = (ldt_info.flags >> 4) & 1;
2461 seg_not_present = (ldt_info.flags >> 5) & 1;
2462 useable = (ldt_info.flags >> 6) & 1;
bellard8d18e892007-11-14 15:18:40 +00002463#ifdef TARGET_ABI32
2464 lm = 0;
2465#else
2466 lm = (ldt_info.flags >> 7) & 1;
2467#endif
bellard6dbad632003-03-16 18:05:05 +00002468 if (contents == 3) {
2469 if (oldmode)
bellard03acab62007-11-11 14:57:14 +00002470 return -TARGET_EINVAL;
bellard6dbad632003-03-16 18:05:05 +00002471 if (seg_not_present == 0)
bellard03acab62007-11-11 14:57:14 +00002472 return -TARGET_EINVAL;
bellard6dbad632003-03-16 18:05:05 +00002473 }
2474 /* allocate the LDT */
2475 if (!ldt_table) {
2476 ldt_table = malloc(TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE);
2477 if (!ldt_table)
bellard03acab62007-11-11 14:57:14 +00002478 return -TARGET_ENOMEM;
bellard6dbad632003-03-16 18:05:05 +00002479 memset(ldt_table, 0, TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE);
bellardeeeac3f2007-11-11 19:34:32 +00002480 env->ldt.base = h2g((unsigned long)ldt_table);
bellard6dbad632003-03-16 18:05:05 +00002481 env->ldt.limit = 0xffff;
2482 }
2483
2484 /* NOTE: same code as Linux kernel */
2485 /* Allow LDTs to be cleared by the user. */
2486 if (ldt_info.base_addr == 0 && ldt_info.limit == 0) {
2487 if (oldmode ||
2488 (contents == 0 &&
2489 read_exec_only == 1 &&
2490 seg_32bit == 0 &&
2491 limit_in_pages == 0 &&
2492 seg_not_present == 1 &&
2493 useable == 0 )) {
2494 entry_1 = 0;
2495 entry_2 = 0;
2496 goto install;
2497 }
2498 }
ths3b46e622007-09-17 08:09:54 +00002499
bellard6dbad632003-03-16 18:05:05 +00002500 entry_1 = ((ldt_info.base_addr & 0x0000ffff) << 16) |
2501 (ldt_info.limit & 0x0ffff);
2502 entry_2 = (ldt_info.base_addr & 0xff000000) |
2503 ((ldt_info.base_addr & 0x00ff0000) >> 16) |
2504 (ldt_info.limit & 0xf0000) |
2505 ((read_exec_only ^ 1) << 9) |
2506 (contents << 10) |
2507 ((seg_not_present ^ 1) << 15) |
2508 (seg_32bit << 22) |
2509 (limit_in_pages << 23) |
bellard8d18e892007-11-14 15:18:40 +00002510 (lm << 21) |
bellard6dbad632003-03-16 18:05:05 +00002511 0x7000;
2512 if (!oldmode)
2513 entry_2 |= (useable << 20);
bellard14ae3ba2003-05-27 23:25:06 +00002514
bellard6dbad632003-03-16 18:05:05 +00002515 /* Install the new entry ... */
2516install:
2517 lp = (uint32_t *)(ldt_table + (ldt_info.entry_number << 3));
2518 lp[0] = tswap32(entry_1);
2519 lp[1] = tswap32(entry_2);
2520 return 0;
2521}
2522
2523/* specific and weird i386 syscalls */
bellard03acab62007-11-11 14:57:14 +00002524abi_long do_modify_ldt(CPUX86State *env, int func, abi_ulong ptr,
2525 unsigned long bytecount)
bellard6dbad632003-03-16 18:05:05 +00002526{
bellard03acab62007-11-11 14:57:14 +00002527 abi_long ret;
ths3b46e622007-09-17 08:09:54 +00002528
bellard6dbad632003-03-16 18:05:05 +00002529 switch (func) {
2530 case 0:
2531 ret = read_ldt(ptr, bytecount);
2532 break;
2533 case 1:
2534 ret = write_ldt(env, ptr, bytecount, 1);
2535 break;
2536 case 0x11:
2537 ret = write_ldt(env, ptr, bytecount, 0);
2538 break;
bellard03acab62007-11-11 14:57:14 +00002539 default:
2540 ret = -TARGET_ENOSYS;
2541 break;
bellard6dbad632003-03-16 18:05:05 +00002542 }
2543 return ret;
2544}
bellard1b6b0292003-03-22 17:31:38 +00002545
bellard8d18e892007-11-14 15:18:40 +00002546abi_long do_set_thread_area(CPUX86State *env, abi_ulong ptr)
2547{
2548 uint64_t *gdt_table = g2h(env->gdt.base);
2549 struct target_modify_ldt_ldt_s ldt_info;
2550 struct target_modify_ldt_ldt_s *target_ldt_info;
2551 int seg_32bit, contents, read_exec_only, limit_in_pages;
2552 int seg_not_present, useable, lm;
2553 uint32_t *lp, entry_1, entry_2;
2554 int i;
2555
2556 lock_user_struct(VERIFY_WRITE, target_ldt_info, ptr, 1);
2557 if (!target_ldt_info)
2558 return -TARGET_EFAULT;
2559 ldt_info.entry_number = tswap32(target_ldt_info->entry_number);
2560 ldt_info.base_addr = tswapl(target_ldt_info->base_addr);
2561 ldt_info.limit = tswap32(target_ldt_info->limit);
2562 ldt_info.flags = tswap32(target_ldt_info->flags);
2563 if (ldt_info.entry_number == -1) {
2564 for (i=TARGET_GDT_ENTRY_TLS_MIN; i<=TARGET_GDT_ENTRY_TLS_MAX; i++) {
2565 if (gdt_table[i] == 0) {
2566 ldt_info.entry_number = i;
2567 target_ldt_info->entry_number = tswap32(i);
2568 break;
2569 }
2570 }
2571 }
2572 unlock_user_struct(target_ldt_info, ptr, 1);
2573
2574 if (ldt_info.entry_number < TARGET_GDT_ENTRY_TLS_MIN ||
2575 ldt_info.entry_number > TARGET_GDT_ENTRY_TLS_MAX)
2576 return -TARGET_EINVAL;
2577 seg_32bit = ldt_info.flags & 1;
2578 contents = (ldt_info.flags >> 1) & 3;
2579 read_exec_only = (ldt_info.flags >> 3) & 1;
2580 limit_in_pages = (ldt_info.flags >> 4) & 1;
2581 seg_not_present = (ldt_info.flags >> 5) & 1;
2582 useable = (ldt_info.flags >> 6) & 1;
2583#ifdef TARGET_ABI32
2584 lm = 0;
2585#else
2586 lm = (ldt_info.flags >> 7) & 1;
2587#endif
2588
2589 if (contents == 3) {
2590 if (seg_not_present == 0)
2591 return -TARGET_EINVAL;
2592 }
2593
2594 /* NOTE: same code as Linux kernel */
2595 /* Allow LDTs to be cleared by the user. */
2596 if (ldt_info.base_addr == 0 && ldt_info.limit == 0) {
2597 if ((contents == 0 &&
2598 read_exec_only == 1 &&
2599 seg_32bit == 0 &&
2600 limit_in_pages == 0 &&
2601 seg_not_present == 1 &&
2602 useable == 0 )) {
2603 entry_1 = 0;
2604 entry_2 = 0;
2605 goto install;
2606 }
2607 }
2608
2609 entry_1 = ((ldt_info.base_addr & 0x0000ffff) << 16) |
2610 (ldt_info.limit & 0x0ffff);
2611 entry_2 = (ldt_info.base_addr & 0xff000000) |
2612 ((ldt_info.base_addr & 0x00ff0000) >> 16) |
2613 (ldt_info.limit & 0xf0000) |
2614 ((read_exec_only ^ 1) << 9) |
2615 (contents << 10) |
2616 ((seg_not_present ^ 1) << 15) |
2617 (seg_32bit << 22) |
2618 (limit_in_pages << 23) |
2619 (useable << 20) |
2620 (lm << 21) |
2621 0x7000;
2622
2623 /* Install the new entry ... */
2624install:
2625 lp = (uint32_t *)(gdt_table + ldt_info.entry_number);
2626 lp[0] = tswap32(entry_1);
2627 lp[1] = tswap32(entry_2);
2628 return 0;
2629}
2630
2631abi_long do_get_thread_area(CPUX86State *env, abi_ulong ptr)
2632{
2633 struct target_modify_ldt_ldt_s *target_ldt_info;
2634 uint64_t *gdt_table = g2h(env->gdt.base);
2635 uint32_t base_addr, limit, flags;
2636 int seg_32bit, contents, read_exec_only, limit_in_pages, idx;
2637 int seg_not_present, useable, lm;
2638 uint32_t *lp, entry_1, entry_2;
2639
2640 lock_user_struct(VERIFY_WRITE, target_ldt_info, ptr, 1);
2641 if (!target_ldt_info)
2642 return -TARGET_EFAULT;
2643 idx = tswap32(target_ldt_info->entry_number);
2644 if (idx < TARGET_GDT_ENTRY_TLS_MIN ||
2645 idx > TARGET_GDT_ENTRY_TLS_MAX) {
2646 unlock_user_struct(target_ldt_info, ptr, 1);
2647 return -TARGET_EINVAL;
2648 }
2649 lp = (uint32_t *)(gdt_table + idx);
2650 entry_1 = tswap32(lp[0]);
2651 entry_2 = tswap32(lp[1]);
2652
2653 read_exec_only = ((entry_2 >> 9) & 1) ^ 1;
2654 contents = (entry_2 >> 10) & 3;
2655 seg_not_present = ((entry_2 >> 15) & 1) ^ 1;
2656 seg_32bit = (entry_2 >> 22) & 1;
2657 limit_in_pages = (entry_2 >> 23) & 1;
2658 useable = (entry_2 >> 20) & 1;
2659#ifdef TARGET_ABI32
2660 lm = 0;
2661#else
2662 lm = (entry_2 >> 21) & 1;
2663#endif
2664 flags = (seg_32bit << 0) | (contents << 1) |
2665 (read_exec_only << 3) | (limit_in_pages << 4) |
2666 (seg_not_present << 5) | (useable << 6) | (lm << 7);
2667 limit = (entry_1 & 0xffff) | (entry_2 & 0xf0000);
2668 base_addr = (entry_1 >> 16) |
2669 (entry_2 & 0xff000000) |
2670 ((entry_2 & 0xff) << 16);
2671 target_ldt_info->base_addr = tswapl(base_addr);
2672 target_ldt_info->limit = tswap32(limit);
2673 target_ldt_info->flags = tswap32(flags);
2674 unlock_user_struct(target_ldt_info, ptr, 1);
2675 return 0;
2676}
2677
bellardd2fd1af2007-11-14 18:08:56 +00002678#ifndef TARGET_ABI32
2679abi_long do_arch_prctl(CPUX86State *env, int code, abi_ulong addr)
2680{
2681 abi_long ret;
2682 abi_ulong val;
2683 int idx;
2684
2685 switch(code) {
2686 case TARGET_ARCH_SET_GS:
2687 case TARGET_ARCH_SET_FS:
2688 if (code == TARGET_ARCH_SET_GS)
2689 idx = R_GS;
2690 else
2691 idx = R_FS;
2692 cpu_x86_load_seg(env, idx, 0);
2693 env->segs[idx].base = addr;
2694 break;
2695 case TARGET_ARCH_GET_GS:
2696 case TARGET_ARCH_GET_FS:
2697 if (code == TARGET_ARCH_GET_GS)
2698 idx = R_GS;
2699 else
2700 idx = R_FS;
2701 val = env->segs[idx].base;
2702 if (put_user(val, addr, abi_ulong))
2703 return -TARGET_EFAULT;
2704 break;
2705 default:
2706 ret = -TARGET_EINVAL;
2707 break;
2708 }
2709 return 0;
2710}
2711#endif
2712
bellard2ab83ea2003-06-15 19:56:46 +00002713#endif /* defined(TARGET_I386) */
2714
pbrookd865bab2008-06-07 22:12:17 +00002715#if defined(USE_NPTL)
2716
2717#define NEW_STACK_SIZE PTHREAD_STACK_MIN
2718
2719static pthread_mutex_t clone_lock = PTHREAD_MUTEX_INITIALIZER;
2720typedef struct {
2721 CPUState *env;
2722 pthread_mutex_t mutex;
2723 pthread_cond_t cond;
2724 pthread_t thread;
2725 uint32_t tid;
2726 abi_ulong child_tidptr;
2727 abi_ulong parent_tidptr;
2728 sigset_t sigmask;
2729} new_thread_info;
2730
2731static void *clone_func(void *arg)
2732{
2733 new_thread_info *info = arg;
2734 CPUState *env;
2735
2736 env = info->env;
2737 thread_env = env;
2738 info->tid = gettid();
2739 if (info->child_tidptr)
2740 put_user_u32(info->tid, info->child_tidptr);
2741 if (info->parent_tidptr)
2742 put_user_u32(info->tid, info->parent_tidptr);
2743 /* Enable signals. */
2744 sigprocmask(SIG_SETMASK, &info->sigmask, NULL);
2745 /* Signal to the parent that we're ready. */
2746 pthread_mutex_lock(&info->mutex);
2747 pthread_cond_broadcast(&info->cond);
2748 pthread_mutex_unlock(&info->mutex);
2749 /* Wait until the parent has finshed initializing the tls state. */
2750 pthread_mutex_lock(&clone_lock);
2751 pthread_mutex_unlock(&clone_lock);
2752 cpu_loop(env);
2753 /* never exits */
2754 return NULL;
2755}
2756#else
bellard1b6b0292003-03-22 17:31:38 +00002757/* this stack is the equivalent of the kernel stack associated with a
2758 thread/process */
2759#define NEW_STACK_SIZE 8192
2760
2761static int clone_func(void *arg)
2762{
bellard2ab83ea2003-06-15 19:56:46 +00002763 CPUState *env = arg;
bellard1b6b0292003-03-22 17:31:38 +00002764 cpu_loop(env);
2765 /* never exits */
2766 return 0;
2767}
pbrookd865bab2008-06-07 22:12:17 +00002768#endif
bellard1b6b0292003-03-22 17:31:38 +00002769
ths0da46a62007-10-20 20:23:07 +00002770/* do_fork() Must return host values and target errnos (unlike most
2771 do_*() functions). */
pbrookd865bab2008-06-07 22:12:17 +00002772static int do_fork(CPUState *env, unsigned int flags, abi_ulong newsp,
2773 abi_ulong parent_tidptr, target_ulong newtls,
2774 abi_ulong child_tidptr)
bellard1b6b0292003-03-22 17:31:38 +00002775{
2776 int ret;
bellard5cd43932003-03-29 16:54:36 +00002777 TaskState *ts;
bellard1b6b0292003-03-22 17:31:38 +00002778 uint8_t *new_stack;
bellard2ab83ea2003-06-15 19:56:46 +00002779 CPUState *new_env;
pbrookd865bab2008-06-07 22:12:17 +00002780#if defined(USE_NPTL)
2781 unsigned int nptl_flags;
2782 sigset_t sigmask;
2783#endif
ths3b46e622007-09-17 08:09:54 +00002784
bellard1b6b0292003-03-22 17:31:38 +00002785 if (flags & CLONE_VM) {
pbrookbd0c5662008-05-29 14:34:11 +00002786#if defined(USE_NPTL)
pbrookd865bab2008-06-07 22:12:17 +00002787 new_thread_info info;
2788 pthread_attr_t attr;
pbrookbd0c5662008-05-29 14:34:11 +00002789#endif
pbrookc3a92832008-06-09 14:02:50 +00002790 ts = qemu_mallocz(sizeof(TaskState) + NEW_STACK_SIZE);
pbrook624f7972008-05-31 16:11:38 +00002791 init_task_state(ts);
bellard5cd43932003-03-29 16:54:36 +00002792 new_stack = ts->stack;
bellard1b6b0292003-03-22 17:31:38 +00002793 /* we create a new CPU instance. */
thsc5be9f02007-02-28 20:20:53 +00002794 new_env = cpu_copy(env);
pbrook6e68e072008-05-30 17:22:15 +00002795 /* Init regs that differ from the parent. */
2796 cpu_clone_regs(new_env, newsp);
bellard5cd43932003-03-29 16:54:36 +00002797 new_env->opaque = ts;
pbrookd865bab2008-06-07 22:12:17 +00002798#if defined(USE_NPTL)
2799 nptl_flags = flags;
2800 flags &= ~CLONE_NPTL_FLAGS2;
2801
2802 /* TODO: Implement CLONE_CHILD_CLEARTID. */
2803 if (nptl_flags & CLONE_SETTLS)
2804 cpu_set_tls (new_env, newtls);
2805
2806 /* Grab a mutex so that thread setup appears atomic. */
2807 pthread_mutex_lock(&clone_lock);
2808
2809 memset(&info, 0, sizeof(info));
2810 pthread_mutex_init(&info.mutex, NULL);
2811 pthread_mutex_lock(&info.mutex);
2812 pthread_cond_init(&info.cond, NULL);
2813 info.env = new_env;
2814 if (nptl_flags & CLONE_CHILD_SETTID)
2815 info.child_tidptr = child_tidptr;
2816 if (nptl_flags & CLONE_PARENT_SETTID)
2817 info.parent_tidptr = parent_tidptr;
2818
2819 ret = pthread_attr_init(&attr);
2820 ret = pthread_attr_setstack(&attr, new_stack, NEW_STACK_SIZE);
2821 /* It is not safe to deliver signals until the child has finished
2822 initializing, so temporarily block all signals. */
2823 sigfillset(&sigmask);
2824 sigprocmask(SIG_BLOCK, &sigmask, &info.sigmask);
2825
2826 ret = pthread_create(&info.thread, &attr, clone_func, &info);
2827
2828 sigprocmask(SIG_SETMASK, &info.sigmask, NULL);
2829 pthread_attr_destroy(&attr);
2830 if (ret == 0) {
2831 /* Wait for the child to initialize. */
2832 pthread_cond_wait(&info.cond, &info.mutex);
2833 ret = info.tid;
2834 if (flags & CLONE_PARENT_SETTID)
2835 put_user_u32(ret, parent_tidptr);
2836 } else {
2837 ret = -1;
2838 }
2839 pthread_mutex_unlock(&info.mutex);
2840 pthread_cond_destroy(&info.cond);
2841 pthread_mutex_destroy(&info.mutex);
2842 pthread_mutex_unlock(&clone_lock);
2843#else
2844 if (flags & CLONE_NPTL_FLAGS2)
2845 return -EINVAL;
2846 /* This is probably going to die very quickly, but do it anyway. */
bellard27725c12003-04-29 21:08:18 +00002847#ifdef __ia64__
bellardfd4a43e2006-04-24 20:32:17 +00002848 ret = __clone2(clone_func, new_stack + NEW_STACK_SIZE, flags, new_env);
bellard27725c12003-04-29 21:08:18 +00002849#else
2850 ret = clone(clone_func, new_stack + NEW_STACK_SIZE, flags, new_env);
2851#endif
pbrookd865bab2008-06-07 22:12:17 +00002852#endif
bellard1b6b0292003-03-22 17:31:38 +00002853 } else {
2854 /* if no CLONE_VM, we consider it is a fork */
pbrookd865bab2008-06-07 22:12:17 +00002855 if ((flags & ~(CSIGNAL | CLONE_NPTL_FLAGS2)) != 0)
bellard1b6b0292003-03-22 17:31:38 +00002856 return -EINVAL;
pbrookd865bab2008-06-07 22:12:17 +00002857 fork_start();
bellard1b6b0292003-03-22 17:31:38 +00002858 ret = fork();
pbrookd865bab2008-06-07 22:12:17 +00002859#if defined(USE_NPTL)
2860 /* There is a race condition here. The parent process could
2861 theoretically read the TID in the child process before the child
2862 tid is set. This would require using either ptrace
2863 (not implemented) or having *_tidptr to point at a shared memory
2864 mapping. We can't repeat the spinlock hack used above because
2865 the child process gets its own copy of the lock. */
2866 if (ret == 0) {
2867 cpu_clone_regs(env, newsp);
2868 fork_end(1);
2869 /* Child Process. */
2870 if (flags & CLONE_CHILD_SETTID)
2871 put_user_u32(gettid(), child_tidptr);
2872 if (flags & CLONE_PARENT_SETTID)
2873 put_user_u32(gettid(), parent_tidptr);
2874 ts = (TaskState *)env->opaque;
2875 if (flags & CLONE_SETTLS)
2876 cpu_set_tls (env, newtls);
2877 /* TODO: Implement CLONE_CHILD_CLEARTID. */
2878 } else {
2879 fork_end(0);
2880 }
2881#else
pbrook6e68e072008-05-30 17:22:15 +00002882 if (ret == 0) {
2883 cpu_clone_regs(env, newsp);
2884 }
pbrookd865bab2008-06-07 22:12:17 +00002885#endif
bellard1b6b0292003-03-22 17:31:38 +00002886 }
2887 return ret;
2888}
2889
blueswir1992f48a2007-10-14 16:27:31 +00002890static abi_long do_fcntl(int fd, int cmd, abi_ulong arg)
bellard7775e9e2003-05-14 22:46:48 +00002891{
2892 struct flock fl;
pbrook53a59602006-03-25 19:31:22 +00002893 struct target_flock *target_fl;
ths43f238d2007-01-05 20:55:49 +00002894 struct flock64 fl64;
2895 struct target_flock64 *target_fl64;
blueswir1992f48a2007-10-14 16:27:31 +00002896 abi_long ret;
pbrook53a59602006-03-25 19:31:22 +00002897
bellard7775e9e2003-05-14 22:46:48 +00002898 switch(cmd) {
2899 case TARGET_F_GETLK:
bellard579a97f2007-11-11 14:26:47 +00002900 if (!lock_user_struct(VERIFY_READ, target_fl, arg, 1))
2901 return -TARGET_EFAULT;
ths58134272007-03-31 18:59:32 +00002902 fl.l_type = tswap16(target_fl->l_type);
2903 fl.l_whence = tswap16(target_fl->l_whence);
2904 fl.l_start = tswapl(target_fl->l_start);
2905 fl.l_len = tswapl(target_fl->l_len);
2906 fl.l_pid = tswapl(target_fl->l_pid);
2907 unlock_user_struct(target_fl, arg, 0);
bellard9ee1fa22007-11-11 15:11:19 +00002908 ret = get_errno(fcntl(fd, cmd, &fl));
bellard7775e9e2003-05-14 22:46:48 +00002909 if (ret == 0) {
bellard579a97f2007-11-11 14:26:47 +00002910 if (!lock_user_struct(VERIFY_WRITE, target_fl, arg, 0))
2911 return -TARGET_EFAULT;
bellard7775e9e2003-05-14 22:46:48 +00002912 target_fl->l_type = tswap16(fl.l_type);
2913 target_fl->l_whence = tswap16(fl.l_whence);
2914 target_fl->l_start = tswapl(fl.l_start);
2915 target_fl->l_len = tswapl(fl.l_len);
2916 target_fl->l_pid = tswapl(fl.l_pid);
pbrook53a59602006-03-25 19:31:22 +00002917 unlock_user_struct(target_fl, arg, 1);
bellard7775e9e2003-05-14 22:46:48 +00002918 }
2919 break;
ths3b46e622007-09-17 08:09:54 +00002920
bellard7775e9e2003-05-14 22:46:48 +00002921 case TARGET_F_SETLK:
2922 case TARGET_F_SETLKW:
bellard579a97f2007-11-11 14:26:47 +00002923 if (!lock_user_struct(VERIFY_READ, target_fl, arg, 1))
2924 return -TARGET_EFAULT;
bellard7775e9e2003-05-14 22:46:48 +00002925 fl.l_type = tswap16(target_fl->l_type);
2926 fl.l_whence = tswap16(target_fl->l_whence);
2927 fl.l_start = tswapl(target_fl->l_start);
2928 fl.l_len = tswapl(target_fl->l_len);
2929 fl.l_pid = tswapl(target_fl->l_pid);
pbrook53a59602006-03-25 19:31:22 +00002930 unlock_user_struct(target_fl, arg, 0);
bellard9ee1fa22007-11-11 15:11:19 +00002931 ret = get_errno(fcntl(fd, cmd, &fl));
bellard7775e9e2003-05-14 22:46:48 +00002932 break;
ths3b46e622007-09-17 08:09:54 +00002933
bellard7775e9e2003-05-14 22:46:48 +00002934 case TARGET_F_GETLK64:
bellard579a97f2007-11-11 14:26:47 +00002935 if (!lock_user_struct(VERIFY_READ, target_fl64, arg, 1))
2936 return -TARGET_EFAULT;
ths58134272007-03-31 18:59:32 +00002937 fl64.l_type = tswap16(target_fl64->l_type) >> 1;
2938 fl64.l_whence = tswap16(target_fl64->l_whence);
2939 fl64.l_start = tswapl(target_fl64->l_start);
2940 fl64.l_len = tswapl(target_fl64->l_len);
2941 fl64.l_pid = tswap16(target_fl64->l_pid);
2942 unlock_user_struct(target_fl64, arg, 0);
bellard9ee1fa22007-11-11 15:11:19 +00002943 ret = get_errno(fcntl(fd, cmd >> 1, &fl64));
ths43f238d2007-01-05 20:55:49 +00002944 if (ret == 0) {
bellard579a97f2007-11-11 14:26:47 +00002945 if (!lock_user_struct(VERIFY_WRITE, target_fl64, arg, 0))
2946 return -TARGET_EFAULT;
ths43f238d2007-01-05 20:55:49 +00002947 target_fl64->l_type = tswap16(fl64.l_type) >> 1;
2948 target_fl64->l_whence = tswap16(fl64.l_whence);
2949 target_fl64->l_start = tswapl(fl64.l_start);
2950 target_fl64->l_len = tswapl(fl64.l_len);
2951 target_fl64->l_pid = tswapl(fl64.l_pid);
2952 unlock_user_struct(target_fl64, arg, 1);
2953 }
bellard9ee1fa22007-11-11 15:11:19 +00002954 break;
bellard7775e9e2003-05-14 22:46:48 +00002955 case TARGET_F_SETLK64:
2956 case TARGET_F_SETLKW64:
bellard579a97f2007-11-11 14:26:47 +00002957 if (!lock_user_struct(VERIFY_READ, target_fl64, arg, 1))
2958 return -TARGET_EFAULT;
ths43f238d2007-01-05 20:55:49 +00002959 fl64.l_type = tswap16(target_fl64->l_type) >> 1;
2960 fl64.l_whence = tswap16(target_fl64->l_whence);
2961 fl64.l_start = tswapl(target_fl64->l_start);
2962 fl64.l_len = tswapl(target_fl64->l_len);
2963 fl64.l_pid = tswap16(target_fl64->l_pid);
2964 unlock_user_struct(target_fl64, arg, 0);
bellard9ee1fa22007-11-11 15:11:19 +00002965 ret = get_errno(fcntl(fd, cmd >> 1, &fl64));
bellard7775e9e2003-05-14 22:46:48 +00002966 break;
2967
bellardffa65c32004-01-04 23:57:22 +00002968 case F_GETFL:
bellard9ee1fa22007-11-11 15:11:19 +00002969 ret = get_errno(fcntl(fd, cmd, arg));
2970 if (ret >= 0) {
2971 ret = host_to_target_bitmask(ret, fcntl_flags_tbl);
2972 }
bellardffa65c32004-01-04 23:57:22 +00002973 break;
2974
2975 case F_SETFL:
bellard9ee1fa22007-11-11 15:11:19 +00002976 ret = get_errno(fcntl(fd, cmd, target_to_host_bitmask(arg, fcntl_flags_tbl)));
bellardffa65c32004-01-04 23:57:22 +00002977 break;
2978
bellard7775e9e2003-05-14 22:46:48 +00002979 default:
bellard9ee1fa22007-11-11 15:11:19 +00002980 ret = get_errno(fcntl(fd, cmd, arg));
bellard7775e9e2003-05-14 22:46:48 +00002981 break;
2982 }
2983 return ret;
2984}
2985
bellard67867302003-11-23 17:05:30 +00002986#ifdef USE_UID16
bellard7775e9e2003-05-14 22:46:48 +00002987
bellard67867302003-11-23 17:05:30 +00002988static inline int high2lowuid(int uid)
2989{
2990 if (uid > 65535)
2991 return 65534;
2992 else
2993 return uid;
2994}
2995
2996static inline int high2lowgid(int gid)
2997{
2998 if (gid > 65535)
2999 return 65534;
3000 else
3001 return gid;
3002}
3003
3004static inline int low2highuid(int uid)
3005{
3006 if ((int16_t)uid == -1)
3007 return -1;
3008 else
3009 return uid;
3010}
3011
3012static inline int low2highgid(int gid)
3013{
3014 if ((int16_t)gid == -1)
3015 return -1;
3016 else
3017 return gid;
3018}
3019
3020#endif /* USE_UID16 */
bellard1b6b0292003-03-22 17:31:38 +00003021
bellard31e31b82003-02-18 22:55:36 +00003022void syscall_init(void)
3023{
bellard2ab83ea2003-06-15 19:56:46 +00003024 IOCTLEntry *ie;
3025 const argtype *arg_type;
3026 int size;
thsb92c47c2007-11-01 00:07:38 +00003027 int i;
bellard2ab83ea2003-06-15 19:56:46 +00003028
ths5fafdf22007-09-16 21:08:06 +00003029#define STRUCT(name, list...) thunk_register_struct(STRUCT_ ## name, #name, struct_ ## name ## _def);
3030#define STRUCT_SPECIAL(name) thunk_register_struct_direct(STRUCT_ ## name, #name, &struct_ ## name ## _def);
bellard31e31b82003-02-18 22:55:36 +00003031#include "syscall_types.h"
3032#undef STRUCT
3033#undef STRUCT_SPECIAL
bellard2ab83ea2003-06-15 19:56:46 +00003034
3035 /* we patch the ioctl size if necessary. We rely on the fact that
3036 no ioctl has all the bits at '1' in the size field */
3037 ie = ioctl_entries;
3038 while (ie->target_cmd != 0) {
3039 if (((ie->target_cmd >> TARGET_IOC_SIZESHIFT) & TARGET_IOC_SIZEMASK) ==
3040 TARGET_IOC_SIZEMASK) {
3041 arg_type = ie->arg_type;
3042 if (arg_type[0] != TYPE_PTR) {
ths5fafdf22007-09-16 21:08:06 +00003043 fprintf(stderr, "cannot patch size for ioctl 0x%x\n",
bellard2ab83ea2003-06-15 19:56:46 +00003044 ie->target_cmd);
3045 exit(1);
3046 }
3047 arg_type++;
3048 size = thunk_type_size(arg_type, 0);
ths5fafdf22007-09-16 21:08:06 +00003049 ie->target_cmd = (ie->target_cmd &
bellard2ab83ea2003-06-15 19:56:46 +00003050 ~(TARGET_IOC_SIZEMASK << TARGET_IOC_SIZESHIFT)) |
3051 (size << TARGET_IOC_SIZESHIFT);
3052 }
thsb92c47c2007-11-01 00:07:38 +00003053
3054 /* Build target_to_host_errno_table[] table from
3055 * host_to_target_errno_table[]. */
3056 for (i=0; i < ERRNO_TABLE_SIZE; i++)
3057 target_to_host_errno_table[host_to_target_errno_table[i]] = i;
3058
bellard2ab83ea2003-06-15 19:56:46 +00003059 /* automatic consistency check if same arch */
bellardd2fd1af2007-11-14 18:08:56 +00003060#if defined(__i386__) && defined(TARGET_I386) && defined(TARGET_ABI32)
bellard2ab83ea2003-06-15 19:56:46 +00003061 if (ie->target_cmd != ie->host_cmd) {
ths5fafdf22007-09-16 21:08:06 +00003062 fprintf(stderr, "ERROR: ioctl: target=0x%x host=0x%x\n",
bellard2ab83ea2003-06-15 19:56:46 +00003063 ie->target_cmd, ie->host_cmd);
3064 }
3065#endif
3066 ie++;
3067 }
bellard31e31b82003-02-18 22:55:36 +00003068}
bellardc573ff62004-01-04 15:51:36 +00003069
blueswir1992f48a2007-10-14 16:27:31 +00003070#if TARGET_ABI_BITS == 32
pbrookce4defa2006-02-09 16:49:55 +00003071static inline uint64_t target_offset64(uint32_t word0, uint32_t word1)
3072{
thsaf325d32008-06-10 15:29:15 +00003073#ifdef TARGET_WORDS_BIGENDIAN
pbrookce4defa2006-02-09 16:49:55 +00003074 return ((uint64_t)word0 << 32) | word1;
3075#else
3076 return ((uint64_t)word1 << 32) | word0;
3077#endif
3078}
blueswir1992f48a2007-10-14 16:27:31 +00003079#else /* TARGET_ABI_BITS == 32 */
j_mayer32407102007-09-26 23:01:49 +00003080static inline uint64_t target_offset64(uint64_t word0, uint64_t word1)
3081{
3082 return word0;
3083}
blueswir1992f48a2007-10-14 16:27:31 +00003084#endif /* TARGET_ABI_BITS != 32 */
pbrookce4defa2006-02-09 16:49:55 +00003085
3086#ifdef TARGET_NR_truncate64
blueswir1992f48a2007-10-14 16:27:31 +00003087static inline abi_long target_truncate64(void *cpu_env, const char *arg1,
3088 abi_long arg2,
3089 abi_long arg3,
3090 abi_long arg4)
pbrookce4defa2006-02-09 16:49:55 +00003091{
3092#ifdef TARGET_ARM
3093 if (((CPUARMState *)cpu_env)->eabi)
3094 {
3095 arg2 = arg3;
3096 arg3 = arg4;
3097 }
3098#endif
3099 return get_errno(truncate64(arg1, target_offset64(arg2, arg3)));
3100}
3101#endif
3102
3103#ifdef TARGET_NR_ftruncate64
blueswir1992f48a2007-10-14 16:27:31 +00003104static inline abi_long target_ftruncate64(void *cpu_env, abi_long arg1,
3105 abi_long arg2,
3106 abi_long arg3,
3107 abi_long arg4)
pbrookce4defa2006-02-09 16:49:55 +00003108{
3109#ifdef TARGET_ARM
3110 if (((CPUARMState *)cpu_env)->eabi)
3111 {
3112 arg2 = arg3;
3113 arg3 = arg4;
3114 }
3115#endif
3116 return get_errno(ftruncate64(arg1, target_offset64(arg2, arg3)));
3117}
3118#endif
3119
bellard579a97f2007-11-11 14:26:47 +00003120static inline abi_long target_to_host_timespec(struct timespec *host_ts,
3121 abi_ulong target_addr)
pbrook53a59602006-03-25 19:31:22 +00003122{
3123 struct target_timespec *target_ts;
3124
bellard579a97f2007-11-11 14:26:47 +00003125 if (!lock_user_struct(VERIFY_READ, target_ts, target_addr, 1))
3126 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00003127 host_ts->tv_sec = tswapl(target_ts->tv_sec);
3128 host_ts->tv_nsec = tswapl(target_ts->tv_nsec);
3129 unlock_user_struct(target_ts, target_addr, 0);
bellardb255bfa2008-05-10 21:51:02 +00003130 return 0;
pbrook53a59602006-03-25 19:31:22 +00003131}
3132
bellard579a97f2007-11-11 14:26:47 +00003133static inline abi_long host_to_target_timespec(abi_ulong target_addr,
3134 struct timespec *host_ts)
pbrook53a59602006-03-25 19:31:22 +00003135{
3136 struct target_timespec *target_ts;
3137
bellard579a97f2007-11-11 14:26:47 +00003138 if (!lock_user_struct(VERIFY_WRITE, target_ts, target_addr, 0))
3139 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00003140 target_ts->tv_sec = tswapl(host_ts->tv_sec);
3141 target_ts->tv_nsec = tswapl(host_ts->tv_nsec);
3142 unlock_user_struct(target_ts, target_addr, 1);
bellardb255bfa2008-05-10 21:51:02 +00003143 return 0;
pbrook53a59602006-03-25 19:31:22 +00003144}
3145
pbrookbd0c5662008-05-29 14:34:11 +00003146#if defined(USE_NPTL)
3147/* ??? Using host futex calls even when target atomic operations
3148 are not really atomic probably breaks things. However implementing
3149 futexes locally would make futexes shared between multiple processes
3150 tricky. However they're probably useless because guest atomic
3151 operations won't work either. */
3152int do_futex(target_ulong uaddr, int op, int val, target_ulong timeout,
3153 target_ulong uaddr2, int val3)
3154{
3155 struct timespec ts, *pts;
3156
3157 /* ??? We assume FUTEX_* constants are the same on both host
3158 and target. */
3159 switch (op) {
3160 case FUTEX_WAIT:
3161 if (timeout) {
3162 pts = &ts;
3163 target_to_host_timespec(pts, timeout);
3164 } else {
3165 pts = NULL;
3166 }
3167 return get_errno(sys_futex(g2h(uaddr), FUTEX_WAIT, tswap32(val),
3168 pts, NULL, 0));
3169 case FUTEX_WAKE:
3170 return get_errno(sys_futex(g2h(uaddr), FUTEX_WAKE, val, NULL, NULL, 0));
3171 case FUTEX_FD:
3172 return get_errno(sys_futex(g2h(uaddr), FUTEX_FD, val, NULL, NULL, 0));
3173 case FUTEX_REQUEUE:
3174 return get_errno(sys_futex(g2h(uaddr), FUTEX_REQUEUE, val,
3175 NULL, g2h(uaddr2), 0));
3176 case FUTEX_CMP_REQUEUE:
3177 return get_errno(sys_futex(g2h(uaddr), FUTEX_CMP_REQUEUE, val,
3178 NULL, g2h(uaddr2), tswap32(val3)));
3179 default:
3180 return -TARGET_ENOSYS;
3181 }
3182}
3183#endif
3184
pbrooka745ec62008-05-06 15:36:17 +00003185int get_osversion(void)
3186{
3187 static int osversion;
3188 struct new_utsname buf;
3189 const char *s;
3190 int i, n, tmp;
3191 if (osversion)
3192 return osversion;
3193 if (qemu_uname_release && *qemu_uname_release) {
3194 s = qemu_uname_release;
3195 } else {
3196 if (sys_uname(&buf))
3197 return 0;
3198 s = buf.release;
3199 }
3200 tmp = 0;
3201 for (i = 0; i < 3; i++) {
3202 n = 0;
3203 while (*s >= '0' && *s <= '9') {
3204 n *= 10;
3205 n += *s - '0';
3206 s++;
3207 }
3208 tmp = (tmp << 8) + n;
3209 if (*s == '.')
3210 s++;
3211 }
3212 osversion = tmp;
3213 return osversion;
3214}
3215
ths0da46a62007-10-20 20:23:07 +00003216/* do_syscall() should always have a single exit point at the end so
3217 that actions, such as logging of syscall results, can be performed.
3218 All errnos that do_syscall() returns must be -TARGET_<errcode>. */
blueswir1992f48a2007-10-14 16:27:31 +00003219abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
3220 abi_long arg2, abi_long arg3, abi_long arg4,
3221 abi_long arg5, abi_long arg6)
bellard31e31b82003-02-18 22:55:36 +00003222{
blueswir1992f48a2007-10-14 16:27:31 +00003223 abi_long ret;
bellard31e31b82003-02-18 22:55:36 +00003224 struct stat st;
bellard56c8f682005-11-28 22:28:41 +00003225 struct statfs stfs;
pbrook53a59602006-03-25 19:31:22 +00003226 void *p;
ths3b46e622007-09-17 08:09:54 +00003227
bellard72f03902003-02-18 23:33:18 +00003228#ifdef DEBUG
bellardc573ff62004-01-04 15:51:36 +00003229 gemu_log("syscall %d", num);
bellard72f03902003-02-18 23:33:18 +00003230#endif
thsb92c47c2007-11-01 00:07:38 +00003231 if(do_strace)
3232 print_syscall(num, arg1, arg2, arg3, arg4, arg5, arg6);
3233
bellard31e31b82003-02-18 22:55:36 +00003234 switch(num) {
3235 case TARGET_NR_exit:
bellard7d132992003-03-06 23:23:54 +00003236#ifdef HAVE_GPROF
3237 _mcleanup();
3238#endif
bellarde9009672005-04-26 20:42:36 +00003239 gdb_exit(cpu_env, arg1);
bellard1b6b0292003-03-22 17:31:38 +00003240 /* XXX: should free thread stack and CPU env */
bellard31e31b82003-02-18 22:55:36 +00003241 _exit(arg1);
3242 ret = 0; /* avoid warning */
3243 break;
3244 case TARGET_NR_read:
bellard579a97f2007-11-11 14:26:47 +00003245 if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
3246 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003247 ret = get_errno(read(arg1, p, arg3));
3248 unlock_user(p, arg2, ret);
bellard31e31b82003-02-18 22:55:36 +00003249 break;
3250 case TARGET_NR_write:
bellard579a97f2007-11-11 14:26:47 +00003251 if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
3252 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003253 ret = get_errno(write(arg1, p, arg3));
3254 unlock_user(p, arg2, 0);
bellard31e31b82003-02-18 22:55:36 +00003255 break;
3256 case TARGET_NR_open:
bellard2f619692007-11-16 10:46:05 +00003257 if (!(p = lock_user_string(arg1)))
3258 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003259 ret = get_errno(open(path(p),
bellardffa65c32004-01-04 23:57:22 +00003260 target_to_host_bitmask(arg2, fcntl_flags_tbl),
3261 arg3));
pbrook53a59602006-03-25 19:31:22 +00003262 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003263 break;
ths82424832007-09-24 09:21:55 +00003264#if defined(TARGET_NR_openat) && defined(__NR_openat)
3265 case TARGET_NR_openat:
bellard579a97f2007-11-11 14:26:47 +00003266 if (!(p = lock_user_string(arg2)))
3267 goto efault;
3268 ret = get_errno(sys_openat(arg1,
3269 path(p),
3270 target_to_host_bitmask(arg3, fcntl_flags_tbl),
3271 arg4));
3272 unlock_user(p, arg2, 0);
ths82424832007-09-24 09:21:55 +00003273 break;
3274#endif
bellard31e31b82003-02-18 22:55:36 +00003275 case TARGET_NR_close:
3276 ret = get_errno(close(arg1));
3277 break;
3278 case TARGET_NR_brk:
pbrook53a59602006-03-25 19:31:22 +00003279 ret = do_brk(arg1);
bellard31e31b82003-02-18 22:55:36 +00003280 break;
3281 case TARGET_NR_fork:
pbrookd865bab2008-06-07 22:12:17 +00003282 ret = get_errno(do_fork(cpu_env, SIGCHLD, 0, 0, 0, 0));
bellard31e31b82003-02-18 22:55:36 +00003283 break;
thse5febef2007-04-01 18:31:35 +00003284#ifdef TARGET_NR_waitpid
bellard31e31b82003-02-18 22:55:36 +00003285 case TARGET_NR_waitpid:
3286 {
pbrook53a59602006-03-25 19:31:22 +00003287 int status;
3288 ret = get_errno(waitpid(arg1, &status, arg3));
bellard2f619692007-11-16 10:46:05 +00003289 if (!is_error(ret) && arg2
3290 && put_user_s32(status, arg2))
3291 goto efault;
bellard31e31b82003-02-18 22:55:36 +00003292 }
3293 break;
thse5febef2007-04-01 18:31:35 +00003294#endif
pbrookf0cbb612008-05-30 18:20:05 +00003295#ifdef TARGET_NR_waitid
3296 case TARGET_NR_waitid:
3297 {
3298 siginfo_t info;
3299 info.si_pid = 0;
3300 ret = get_errno(waitid(arg1, arg2, &info, arg4));
3301 if (!is_error(ret) && arg3 && info.si_pid != 0) {
3302 if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_siginfo_t), 0)))
3303 goto efault;
3304 host_to_target_siginfo(p, &info);
3305 unlock_user(p, arg3, sizeof(target_siginfo_t));
3306 }
3307 }
3308 break;
3309#endif
j_mayer7a3148a2007-04-05 07:13:51 +00003310#ifdef TARGET_NR_creat /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00003311 case TARGET_NR_creat:
bellard579a97f2007-11-11 14:26:47 +00003312 if (!(p = lock_user_string(arg1)))
3313 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003314 ret = get_errno(creat(p, arg2));
3315 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003316 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003317#endif
bellard31e31b82003-02-18 22:55:36 +00003318 case TARGET_NR_link:
pbrook53a59602006-03-25 19:31:22 +00003319 {
3320 void * p2;
3321 p = lock_user_string(arg1);
3322 p2 = lock_user_string(arg2);
bellard579a97f2007-11-11 14:26:47 +00003323 if (!p || !p2)
3324 ret = -TARGET_EFAULT;
3325 else
3326 ret = get_errno(link(p, p2));
pbrook53a59602006-03-25 19:31:22 +00003327 unlock_user(p2, arg2, 0);
3328 unlock_user(p, arg1, 0);
3329 }
bellard31e31b82003-02-18 22:55:36 +00003330 break;
ths64f0ce42007-09-24 09:25:06 +00003331#if defined(TARGET_NR_linkat) && defined(__NR_linkat)
3332 case TARGET_NR_linkat:
ths64f0ce42007-09-24 09:25:06 +00003333 {
3334 void * p2 = NULL;
bellard579a97f2007-11-11 14:26:47 +00003335 if (!arg2 || !arg4)
3336 goto efault;
ths64f0ce42007-09-24 09:25:06 +00003337 p = lock_user_string(arg2);
3338 p2 = lock_user_string(arg4);
bellard579a97f2007-11-11 14:26:47 +00003339 if (!p || !p2)
ths0da46a62007-10-20 20:23:07 +00003340 ret = -TARGET_EFAULT;
ths64f0ce42007-09-24 09:25:06 +00003341 else
3342 ret = get_errno(sys_linkat(arg1, p, arg3, p2, arg5));
bellard579a97f2007-11-11 14:26:47 +00003343 unlock_user(p, arg2, 0);
3344 unlock_user(p2, arg4, 0);
ths64f0ce42007-09-24 09:25:06 +00003345 }
3346 break;
3347#endif
bellard31e31b82003-02-18 22:55:36 +00003348 case TARGET_NR_unlink:
bellard579a97f2007-11-11 14:26:47 +00003349 if (!(p = lock_user_string(arg1)))
3350 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003351 ret = get_errno(unlink(p));
3352 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003353 break;
ths8170f562007-09-24 09:24:11 +00003354#if defined(TARGET_NR_unlinkat) && defined(__NR_unlinkat)
3355 case TARGET_NR_unlinkat:
bellard579a97f2007-11-11 14:26:47 +00003356 if (!(p = lock_user_string(arg2)))
3357 goto efault;
3358 ret = get_errno(sys_unlinkat(arg1, p, arg3));
3359 unlock_user(p, arg2, 0);
balroged494d82007-12-11 23:23:52 +00003360 break;
balrogb7d35e62007-12-12 00:40:24 +00003361#endif
bellard31e31b82003-02-18 22:55:36 +00003362 case TARGET_NR_execve:
bellard7854b052003-03-29 17:22:23 +00003363 {
3364 char **argp, **envp;
bellardf7341ff2003-03-30 21:00:25 +00003365 int argc, envc;
blueswir1992f48a2007-10-14 16:27:31 +00003366 abi_ulong gp;
3367 abi_ulong guest_argp;
3368 abi_ulong guest_envp;
3369 abi_ulong addr;
bellard7854b052003-03-29 17:22:23 +00003370 char **q;
3371
bellardf7341ff2003-03-30 21:00:25 +00003372 argc = 0;
pbrook53a59602006-03-25 19:31:22 +00003373 guest_argp = arg2;
pbrookda94d262008-05-30 18:24:00 +00003374 for (gp = guest_argp; gp; gp += sizeof(abi_ulong)) {
ths03aa1972007-12-02 06:28:08 +00003375 if (get_user_ual(addr, gp))
bellard2f619692007-11-16 10:46:05 +00003376 goto efault;
ths03aa1972007-12-02 06:28:08 +00003377 if (!addr)
bellard2f619692007-11-16 10:46:05 +00003378 break;
bellard7854b052003-03-29 17:22:23 +00003379 argc++;
bellard2f619692007-11-16 10:46:05 +00003380 }
bellardf7341ff2003-03-30 21:00:25 +00003381 envc = 0;
pbrook53a59602006-03-25 19:31:22 +00003382 guest_envp = arg3;
pbrookda94d262008-05-30 18:24:00 +00003383 for (gp = guest_envp; gp; gp += sizeof(abi_ulong)) {
ths03aa1972007-12-02 06:28:08 +00003384 if (get_user_ual(addr, gp))
bellard2f619692007-11-16 10:46:05 +00003385 goto efault;
ths03aa1972007-12-02 06:28:08 +00003386 if (!addr)
bellard2f619692007-11-16 10:46:05 +00003387 break;
bellard7854b052003-03-29 17:22:23 +00003388 envc++;
bellard2f619692007-11-16 10:46:05 +00003389 }
bellard7854b052003-03-29 17:22:23 +00003390
bellardf7341ff2003-03-30 21:00:25 +00003391 argp = alloca((argc + 1) * sizeof(void *));
3392 envp = alloca((envc + 1) * sizeof(void *));
bellard7854b052003-03-29 17:22:23 +00003393
pbrookda94d262008-05-30 18:24:00 +00003394 for (gp = guest_argp, q = argp; gp;
blueswir1992f48a2007-10-14 16:27:31 +00003395 gp += sizeof(abi_ulong), q++) {
bellard2f619692007-11-16 10:46:05 +00003396 if (get_user_ual(addr, gp))
3397 goto execve_efault;
pbrook53a59602006-03-25 19:31:22 +00003398 if (!addr)
3399 break;
bellard2f619692007-11-16 10:46:05 +00003400 if (!(*q = lock_user_string(addr)))
3401 goto execve_efault;
pbrook53a59602006-03-25 19:31:22 +00003402 }
bellardf7341ff2003-03-30 21:00:25 +00003403 *q = NULL;
3404
pbrookda94d262008-05-30 18:24:00 +00003405 for (gp = guest_envp, q = envp; gp;
blueswir1992f48a2007-10-14 16:27:31 +00003406 gp += sizeof(abi_ulong), q++) {
bellard2f619692007-11-16 10:46:05 +00003407 if (get_user_ual(addr, gp))
3408 goto execve_efault;
pbrook53a59602006-03-25 19:31:22 +00003409 if (!addr)
3410 break;
bellard2f619692007-11-16 10:46:05 +00003411 if (!(*q = lock_user_string(addr)))
3412 goto execve_efault;
pbrook53a59602006-03-25 19:31:22 +00003413 }
bellardf7341ff2003-03-30 21:00:25 +00003414 *q = NULL;
bellard7854b052003-03-29 17:22:23 +00003415
bellard2f619692007-11-16 10:46:05 +00003416 if (!(p = lock_user_string(arg1)))
3417 goto execve_efault;
pbrook53a59602006-03-25 19:31:22 +00003418 ret = get_errno(execve(p, argp, envp));
3419 unlock_user(p, arg1, 0);
3420
bellard2f619692007-11-16 10:46:05 +00003421 goto execve_end;
3422
3423 execve_efault:
3424 ret = -TARGET_EFAULT;
3425
3426 execve_end:
pbrook53a59602006-03-25 19:31:22 +00003427 for (gp = guest_argp, q = argp; *q;
blueswir1992f48a2007-10-14 16:27:31 +00003428 gp += sizeof(abi_ulong), q++) {
bellard2f619692007-11-16 10:46:05 +00003429 if (get_user_ual(addr, gp)
3430 || !addr)
3431 break;
pbrook53a59602006-03-25 19:31:22 +00003432 unlock_user(*q, addr, 0);
3433 }
3434 for (gp = guest_envp, q = envp; *q;
blueswir1992f48a2007-10-14 16:27:31 +00003435 gp += sizeof(abi_ulong), q++) {
bellard2f619692007-11-16 10:46:05 +00003436 if (get_user_ual(addr, gp)
3437 || !addr)
3438 break;
pbrook53a59602006-03-25 19:31:22 +00003439 unlock_user(*q, addr, 0);
3440 }
bellard7854b052003-03-29 17:22:23 +00003441 }
bellard31e31b82003-02-18 22:55:36 +00003442 break;
3443 case TARGET_NR_chdir:
bellard579a97f2007-11-11 14:26:47 +00003444 if (!(p = lock_user_string(arg1)))
3445 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003446 ret = get_errno(chdir(p));
3447 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003448 break;
bellarda315a142005-01-30 22:59:18 +00003449#ifdef TARGET_NR_time
bellard31e31b82003-02-18 22:55:36 +00003450 case TARGET_NR_time:
3451 {
pbrook53a59602006-03-25 19:31:22 +00003452 time_t host_time;
3453 ret = get_errno(time(&host_time));
bellard2f619692007-11-16 10:46:05 +00003454 if (!is_error(ret)
3455 && arg1
3456 && put_user_sal(host_time, arg1))
3457 goto efault;
bellard31e31b82003-02-18 22:55:36 +00003458 }
3459 break;
bellarda315a142005-01-30 22:59:18 +00003460#endif
bellard31e31b82003-02-18 22:55:36 +00003461 case TARGET_NR_mknod:
bellard579a97f2007-11-11 14:26:47 +00003462 if (!(p = lock_user_string(arg1)))
3463 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003464 ret = get_errno(mknod(p, arg2, arg3));
3465 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003466 break;
ths75ac37a2007-09-24 09:23:05 +00003467#if defined(TARGET_NR_mknodat) && defined(__NR_mknodat)
3468 case TARGET_NR_mknodat:
bellard579a97f2007-11-11 14:26:47 +00003469 if (!(p = lock_user_string(arg2)))
3470 goto efault;
3471 ret = get_errno(sys_mknodat(arg1, p, arg3, arg4));
3472 unlock_user(p, arg2, 0);
ths75ac37a2007-09-24 09:23:05 +00003473 break;
3474#endif
bellard31e31b82003-02-18 22:55:36 +00003475 case TARGET_NR_chmod:
bellard579a97f2007-11-11 14:26:47 +00003476 if (!(p = lock_user_string(arg1)))
3477 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003478 ret = get_errno(chmod(p, arg2));
3479 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003480 break;
bellardebc05482003-09-30 21:08:41 +00003481#ifdef TARGET_NR_break
bellard31e31b82003-02-18 22:55:36 +00003482 case TARGET_NR_break:
3483 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00003484#endif
3485#ifdef TARGET_NR_oldstat
bellard31e31b82003-02-18 22:55:36 +00003486 case TARGET_NR_oldstat:
3487 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00003488#endif
bellard31e31b82003-02-18 22:55:36 +00003489 case TARGET_NR_lseek:
3490 ret = get_errno(lseek(arg1, arg2, arg3));
3491 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003492#ifdef TARGET_NR_getxpid
3493 case TARGET_NR_getxpid:
3494#else
bellard31e31b82003-02-18 22:55:36 +00003495 case TARGET_NR_getpid:
j_mayer7a3148a2007-04-05 07:13:51 +00003496#endif
bellard31e31b82003-02-18 22:55:36 +00003497 ret = get_errno(getpid());
3498 break;
3499 case TARGET_NR_mount:
ths80265912007-02-17 22:25:41 +00003500 {
3501 /* need to look at the data field */
3502 void *p2, *p3;
3503 p = lock_user_string(arg1);
3504 p2 = lock_user_string(arg2);
3505 p3 = lock_user_string(arg3);
bellard579a97f2007-11-11 14:26:47 +00003506 if (!p || !p2 || !p3)
3507 ret = -TARGET_EFAULT;
3508 else
3509 /* FIXME - arg5 should be locked, but it isn't clear how to
3510 * do that since it's not guaranteed to be a NULL-terminated
3511 * string.
3512 */
3513 ret = get_errno(mount(p, p2, p3, (unsigned long)arg4, g2h(arg5)));
3514 unlock_user(p, arg1, 0);
3515 unlock_user(p2, arg2, 0);
3516 unlock_user(p3, arg3, 0);
ths80265912007-02-17 22:25:41 +00003517 break;
3518 }
thse5febef2007-04-01 18:31:35 +00003519#ifdef TARGET_NR_umount
bellard31e31b82003-02-18 22:55:36 +00003520 case TARGET_NR_umount:
bellard579a97f2007-11-11 14:26:47 +00003521 if (!(p = lock_user_string(arg1)))
3522 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003523 ret = get_errno(umount(p));
3524 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003525 break;
thse5febef2007-04-01 18:31:35 +00003526#endif
j_mayer7a3148a2007-04-05 07:13:51 +00003527#ifdef TARGET_NR_stime /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00003528 case TARGET_NR_stime:
3529 {
pbrook53a59602006-03-25 19:31:22 +00003530 time_t host_time;
bellard2f619692007-11-16 10:46:05 +00003531 if (get_user_sal(host_time, arg1))
3532 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003533 ret = get_errno(stime(&host_time));
bellard31e31b82003-02-18 22:55:36 +00003534 }
3535 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003536#endif
bellard31e31b82003-02-18 22:55:36 +00003537 case TARGET_NR_ptrace:
3538 goto unimplemented;
j_mayer7a3148a2007-04-05 07:13:51 +00003539#ifdef TARGET_NR_alarm /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00003540 case TARGET_NR_alarm:
3541 ret = alarm(arg1);
3542 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003543#endif
bellardebc05482003-09-30 21:08:41 +00003544#ifdef TARGET_NR_oldfstat
bellard31e31b82003-02-18 22:55:36 +00003545 case TARGET_NR_oldfstat:
3546 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00003547#endif
j_mayer7a3148a2007-04-05 07:13:51 +00003548#ifdef TARGET_NR_pause /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00003549 case TARGET_NR_pause:
3550 ret = get_errno(pause());
3551 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003552#endif
thse5febef2007-04-01 18:31:35 +00003553#ifdef TARGET_NR_utime
bellard31e31b82003-02-18 22:55:36 +00003554 case TARGET_NR_utime:
bellardebc05482003-09-30 21:08:41 +00003555 {
pbrook53a59602006-03-25 19:31:22 +00003556 struct utimbuf tbuf, *host_tbuf;
3557 struct target_utimbuf *target_tbuf;
3558 if (arg2) {
bellard579a97f2007-11-11 14:26:47 +00003559 if (!lock_user_struct(VERIFY_READ, target_tbuf, arg2, 1))
3560 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003561 tbuf.actime = tswapl(target_tbuf->actime);
3562 tbuf.modtime = tswapl(target_tbuf->modtime);
3563 unlock_user_struct(target_tbuf, arg2, 0);
3564 host_tbuf = &tbuf;
bellardf72e8ff2004-05-03 19:23:07 +00003565 } else {
pbrook53a59602006-03-25 19:31:22 +00003566 host_tbuf = NULL;
bellardf72e8ff2004-05-03 19:23:07 +00003567 }
bellard579a97f2007-11-11 14:26:47 +00003568 if (!(p = lock_user_string(arg1)))
3569 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003570 ret = get_errno(utime(p, host_tbuf));
3571 unlock_user(p, arg1, 0);
bellardebc05482003-09-30 21:08:41 +00003572 }
3573 break;
thse5febef2007-04-01 18:31:35 +00003574#endif
bellard978a66f2004-12-06 22:58:05 +00003575 case TARGET_NR_utimes:
3576 {
bellard978a66f2004-12-06 22:58:05 +00003577 struct timeval *tvp, tv[2];
pbrook53a59602006-03-25 19:31:22 +00003578 if (arg2) {
ths788f5ec2007-12-09 02:37:05 +00003579 if (copy_from_user_timeval(&tv[0], arg2)
3580 || copy_from_user_timeval(&tv[1],
3581 arg2 + sizeof(struct target_timeval)))
3582 goto efault;
bellard978a66f2004-12-06 22:58:05 +00003583 tvp = tv;
3584 } else {
3585 tvp = NULL;
3586 }
bellard579a97f2007-11-11 14:26:47 +00003587 if (!(p = lock_user_string(arg1)))
3588 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003589 ret = get_errno(utimes(p, tvp));
3590 unlock_user(p, arg1, 0);
bellard978a66f2004-12-06 22:58:05 +00003591 }
3592 break;
bellardebc05482003-09-30 21:08:41 +00003593#ifdef TARGET_NR_stty
bellard31e31b82003-02-18 22:55:36 +00003594 case TARGET_NR_stty:
3595 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00003596#endif
3597#ifdef TARGET_NR_gtty
bellard31e31b82003-02-18 22:55:36 +00003598 case TARGET_NR_gtty:
3599 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00003600#endif
bellard31e31b82003-02-18 22:55:36 +00003601 case TARGET_NR_access:
bellard579a97f2007-11-11 14:26:47 +00003602 if (!(p = lock_user_string(arg1)))
3603 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003604 ret = get_errno(access(p, arg2));
3605 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003606 break;
ths92a34c12007-09-24 09:27:49 +00003607#if defined(TARGET_NR_faccessat) && defined(__NR_faccessat)
3608 case TARGET_NR_faccessat:
bellard579a97f2007-11-11 14:26:47 +00003609 if (!(p = lock_user_string(arg2)))
3610 goto efault;
3611 ret = get_errno(sys_faccessat(arg1, p, arg3, arg4));
3612 unlock_user(p, arg2, 0);
ths92a34c12007-09-24 09:27:49 +00003613 break;
3614#endif
j_mayer7a3148a2007-04-05 07:13:51 +00003615#ifdef TARGET_NR_nice /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00003616 case TARGET_NR_nice:
3617 ret = get_errno(nice(arg1));
3618 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003619#endif
bellardebc05482003-09-30 21:08:41 +00003620#ifdef TARGET_NR_ftime
bellard31e31b82003-02-18 22:55:36 +00003621 case TARGET_NR_ftime:
3622 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00003623#endif
bellard31e31b82003-02-18 22:55:36 +00003624 case TARGET_NR_sync:
bellard04369ff2003-03-20 22:33:23 +00003625 sync();
3626 ret = 0;
bellard31e31b82003-02-18 22:55:36 +00003627 break;
3628 case TARGET_NR_kill:
pbrook4cb05962008-05-30 18:05:19 +00003629 ret = get_errno(kill(arg1, target_to_host_signal(arg2)));
bellard31e31b82003-02-18 22:55:36 +00003630 break;
3631 case TARGET_NR_rename:
pbrook53a59602006-03-25 19:31:22 +00003632 {
3633 void *p2;
3634 p = lock_user_string(arg1);
3635 p2 = lock_user_string(arg2);
bellard579a97f2007-11-11 14:26:47 +00003636 if (!p || !p2)
3637 ret = -TARGET_EFAULT;
3638 else
3639 ret = get_errno(rename(p, p2));
pbrook53a59602006-03-25 19:31:22 +00003640 unlock_user(p2, arg2, 0);
3641 unlock_user(p, arg1, 0);
3642 }
bellard31e31b82003-02-18 22:55:36 +00003643 break;
ths722183f2007-09-24 09:24:37 +00003644#if defined(TARGET_NR_renameat) && defined(__NR_renameat)
3645 case TARGET_NR_renameat:
ths722183f2007-09-24 09:24:37 +00003646 {
bellard579a97f2007-11-11 14:26:47 +00003647 void *p2;
ths722183f2007-09-24 09:24:37 +00003648 p = lock_user_string(arg2);
3649 p2 = lock_user_string(arg4);
bellard579a97f2007-11-11 14:26:47 +00003650 if (!p || !p2)
ths0da46a62007-10-20 20:23:07 +00003651 ret = -TARGET_EFAULT;
ths722183f2007-09-24 09:24:37 +00003652 else
3653 ret = get_errno(sys_renameat(arg1, p, arg3, p2));
bellard579a97f2007-11-11 14:26:47 +00003654 unlock_user(p2, arg4, 0);
3655 unlock_user(p, arg2, 0);
ths722183f2007-09-24 09:24:37 +00003656 }
3657 break;
3658#endif
bellard31e31b82003-02-18 22:55:36 +00003659 case TARGET_NR_mkdir:
bellard579a97f2007-11-11 14:26:47 +00003660 if (!(p = lock_user_string(arg1)))
3661 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003662 ret = get_errno(mkdir(p, arg2));
3663 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003664 break;
ths4472ad02007-09-24 09:22:32 +00003665#if defined(TARGET_NR_mkdirat) && defined(__NR_mkdirat)
3666 case TARGET_NR_mkdirat:
bellard579a97f2007-11-11 14:26:47 +00003667 if (!(p = lock_user_string(arg2)))
3668 goto efault;
3669 ret = get_errno(sys_mkdirat(arg1, p, arg3));
3670 unlock_user(p, arg2, 0);
ths4472ad02007-09-24 09:22:32 +00003671 break;
3672#endif
bellard31e31b82003-02-18 22:55:36 +00003673 case TARGET_NR_rmdir:
bellard579a97f2007-11-11 14:26:47 +00003674 if (!(p = lock_user_string(arg1)))
3675 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003676 ret = get_errno(rmdir(p));
3677 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003678 break;
3679 case TARGET_NR_dup:
3680 ret = get_errno(dup(arg1));
3681 break;
3682 case TARGET_NR_pipe:
3683 {
pbrook53a59602006-03-25 19:31:22 +00003684 int host_pipe[2];
3685 ret = get_errno(pipe(host_pipe));
bellard31e31b82003-02-18 22:55:36 +00003686 if (!is_error(ret)) {
thsc12ab052007-06-01 11:50:36 +00003687#if defined(TARGET_MIPS)
thsead93602007-09-06 00:18:15 +00003688 CPUMIPSState *env = (CPUMIPSState*)cpu_env;
thsd0dc7dc2008-02-12 21:01:26 +00003689 env->gpr[env->current_tc][3] = host_pipe[1];
thsc12ab052007-06-01 11:50:36 +00003690 ret = host_pipe[0];
aurel32b5eff352008-03-11 23:30:22 +00003691#elif defined(TARGET_SH4)
3692 ((CPUSH4State*)cpu_env)->gregs[1] = host_pipe[1];
3693 ret = host_pipe[0];
thsc12ab052007-06-01 11:50:36 +00003694#else
bellard2f619692007-11-16 10:46:05 +00003695 if (put_user_s32(host_pipe[0], arg1)
3696 || put_user_s32(host_pipe[1], arg1 + sizeof(host_pipe[0])))
3697 goto efault;
thsc12ab052007-06-01 11:50:36 +00003698#endif
bellard31e31b82003-02-18 22:55:36 +00003699 }
3700 }
3701 break;
3702 case TARGET_NR_times:
bellard32f36bc2003-03-30 21:29:48 +00003703 {
pbrook53a59602006-03-25 19:31:22 +00003704 struct target_tms *tmsp;
bellard32f36bc2003-03-30 21:29:48 +00003705 struct tms tms;
3706 ret = get_errno(times(&tms));
pbrook53a59602006-03-25 19:31:22 +00003707 if (arg1) {
bellard579a97f2007-11-11 14:26:47 +00003708 tmsp = lock_user(VERIFY_WRITE, arg1, sizeof(struct target_tms), 0);
3709 if (!tmsp)
3710 goto efault;
bellardc596ed12003-07-13 17:32:31 +00003711 tmsp->tms_utime = tswapl(host_to_target_clock_t(tms.tms_utime));
3712 tmsp->tms_stime = tswapl(host_to_target_clock_t(tms.tms_stime));
3713 tmsp->tms_cutime = tswapl(host_to_target_clock_t(tms.tms_cutime));
3714 tmsp->tms_cstime = tswapl(host_to_target_clock_t(tms.tms_cstime));
bellard32f36bc2003-03-30 21:29:48 +00003715 }
bellardc596ed12003-07-13 17:32:31 +00003716 if (!is_error(ret))
3717 ret = host_to_target_clock_t(ret);
bellard32f36bc2003-03-30 21:29:48 +00003718 }
3719 break;
bellardebc05482003-09-30 21:08:41 +00003720#ifdef TARGET_NR_prof
bellard31e31b82003-02-18 22:55:36 +00003721 case TARGET_NR_prof:
3722 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00003723#endif
thse5febef2007-04-01 18:31:35 +00003724#ifdef TARGET_NR_signal
bellard31e31b82003-02-18 22:55:36 +00003725 case TARGET_NR_signal:
3726 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00003727#endif
bellard31e31b82003-02-18 22:55:36 +00003728 case TARGET_NR_acct:
bellard579a97f2007-11-11 14:26:47 +00003729 if (!(p = lock_user_string(arg1)))
3730 goto efault;
pbrook24836682006-04-16 14:14:53 +00003731 ret = get_errno(acct(path(p)));
3732 unlock_user(p, arg1, 0);
3733 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003734#ifdef TARGET_NR_umount2 /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00003735 case TARGET_NR_umount2:
bellard579a97f2007-11-11 14:26:47 +00003736 if (!(p = lock_user_string(arg1)))
3737 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003738 ret = get_errno(umount2(p, arg2));
3739 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003740 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003741#endif
bellardebc05482003-09-30 21:08:41 +00003742#ifdef TARGET_NR_lock
bellard31e31b82003-02-18 22:55:36 +00003743 case TARGET_NR_lock:
3744 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00003745#endif
bellard31e31b82003-02-18 22:55:36 +00003746 case TARGET_NR_ioctl:
3747 ret = do_ioctl(arg1, arg2, arg3);
3748 break;
3749 case TARGET_NR_fcntl:
bellard9ee1fa22007-11-11 15:11:19 +00003750 ret = do_fcntl(arg1, arg2, arg3);
bellard31e31b82003-02-18 22:55:36 +00003751 break;
bellardebc05482003-09-30 21:08:41 +00003752#ifdef TARGET_NR_mpx
bellard31e31b82003-02-18 22:55:36 +00003753 case TARGET_NR_mpx:
3754 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00003755#endif
bellard31e31b82003-02-18 22:55:36 +00003756 case TARGET_NR_setpgid:
3757 ret = get_errno(setpgid(arg1, arg2));
3758 break;
bellardebc05482003-09-30 21:08:41 +00003759#ifdef TARGET_NR_ulimit
bellard31e31b82003-02-18 22:55:36 +00003760 case TARGET_NR_ulimit:
3761 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00003762#endif
3763#ifdef TARGET_NR_oldolduname
bellard31e31b82003-02-18 22:55:36 +00003764 case TARGET_NR_oldolduname:
3765 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00003766#endif
bellard31e31b82003-02-18 22:55:36 +00003767 case TARGET_NR_umask:
3768 ret = get_errno(umask(arg1));
3769 break;
3770 case TARGET_NR_chroot:
bellard579a97f2007-11-11 14:26:47 +00003771 if (!(p = lock_user_string(arg1)))
3772 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003773 ret = get_errno(chroot(p));
3774 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003775 break;
3776 case TARGET_NR_ustat:
3777 goto unimplemented;
3778 case TARGET_NR_dup2:
3779 ret = get_errno(dup2(arg1, arg2));
3780 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003781#ifdef TARGET_NR_getppid /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00003782 case TARGET_NR_getppid:
3783 ret = get_errno(getppid());
3784 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003785#endif
bellard31e31b82003-02-18 22:55:36 +00003786 case TARGET_NR_getpgrp:
3787 ret = get_errno(getpgrp());
3788 break;
3789 case TARGET_NR_setsid:
3790 ret = get_errno(setsid());
3791 break;
thse5febef2007-04-01 18:31:35 +00003792#ifdef TARGET_NR_sigaction
bellard31e31b82003-02-18 22:55:36 +00003793 case TARGET_NR_sigaction:
bellard31e31b82003-02-18 22:55:36 +00003794 {
ths388bb212007-05-13 13:58:00 +00003795#if !defined(TARGET_MIPS)
pbrook53a59602006-03-25 19:31:22 +00003796 struct target_old_sigaction *old_act;
bellard66fb9762003-03-23 01:06:05 +00003797 struct target_sigaction act, oact, *pact;
pbrook53a59602006-03-25 19:31:22 +00003798 if (arg2) {
bellard579a97f2007-11-11 14:26:47 +00003799 if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1))
3800 goto efault;
bellard66fb9762003-03-23 01:06:05 +00003801 act._sa_handler = old_act->_sa_handler;
3802 target_siginitset(&act.sa_mask, old_act->sa_mask);
3803 act.sa_flags = old_act->sa_flags;
3804 act.sa_restorer = old_act->sa_restorer;
pbrook53a59602006-03-25 19:31:22 +00003805 unlock_user_struct(old_act, arg2, 0);
bellard66fb9762003-03-23 01:06:05 +00003806 pact = &act;
3807 } else {
3808 pact = NULL;
3809 }
3810 ret = get_errno(do_sigaction(arg1, pact, &oact));
pbrook53a59602006-03-25 19:31:22 +00003811 if (!is_error(ret) && arg3) {
bellard579a97f2007-11-11 14:26:47 +00003812 if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0))
3813 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003814 old_act->_sa_handler = oact._sa_handler;
3815 old_act->sa_mask = oact.sa_mask.sig[0];
3816 old_act->sa_flags = oact.sa_flags;
3817 old_act->sa_restorer = oact.sa_restorer;
3818 unlock_user_struct(old_act, arg3, 1);
bellard66fb9762003-03-23 01:06:05 +00003819 }
ths388bb212007-05-13 13:58:00 +00003820#else
bellard106ec872006-06-27 21:08:10 +00003821 struct target_sigaction act, oact, *pact, *old_act;
3822
3823 if (arg2) {
bellard579a97f2007-11-11 14:26:47 +00003824 if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1))
3825 goto efault;
bellard106ec872006-06-27 21:08:10 +00003826 act._sa_handler = old_act->_sa_handler;
3827 target_siginitset(&act.sa_mask, old_act->sa_mask.sig[0]);
3828 act.sa_flags = old_act->sa_flags;
3829 unlock_user_struct(old_act, arg2, 0);
3830 pact = &act;
3831 } else {
3832 pact = NULL;
3833 }
3834
3835 ret = get_errno(do_sigaction(arg1, pact, &oact));
3836
3837 if (!is_error(ret) && arg3) {
bellard579a97f2007-11-11 14:26:47 +00003838 if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0))
3839 goto efault;
bellard106ec872006-06-27 21:08:10 +00003840 old_act->_sa_handler = oact._sa_handler;
3841 old_act->sa_flags = oact.sa_flags;
3842 old_act->sa_mask.sig[0] = oact.sa_mask.sig[0];
3843 old_act->sa_mask.sig[1] = 0;
3844 old_act->sa_mask.sig[2] = 0;
3845 old_act->sa_mask.sig[3] = 0;
3846 unlock_user_struct(old_act, arg3, 1);
3847 }
ths388bb212007-05-13 13:58:00 +00003848#endif
bellard31e31b82003-02-18 22:55:36 +00003849 }
3850 break;
thse5febef2007-04-01 18:31:35 +00003851#endif
bellard66fb9762003-03-23 01:06:05 +00003852 case TARGET_NR_rt_sigaction:
pbrook53a59602006-03-25 19:31:22 +00003853 {
3854 struct target_sigaction *act;
3855 struct target_sigaction *oact;
3856
bellard579a97f2007-11-11 14:26:47 +00003857 if (arg2) {
3858 if (!lock_user_struct(VERIFY_READ, act, arg2, 1))
3859 goto efault;
3860 } else
pbrook53a59602006-03-25 19:31:22 +00003861 act = NULL;
bellard579a97f2007-11-11 14:26:47 +00003862 if (arg3) {
3863 if (!lock_user_struct(VERIFY_WRITE, oact, arg3, 0)) {
3864 ret = -TARGET_EFAULT;
3865 goto rt_sigaction_fail;
3866 }
3867 } else
pbrook53a59602006-03-25 19:31:22 +00003868 oact = NULL;
3869 ret = get_errno(do_sigaction(arg1, act, oact));
bellard579a97f2007-11-11 14:26:47 +00003870 rt_sigaction_fail:
3871 if (act)
pbrook53a59602006-03-25 19:31:22 +00003872 unlock_user_struct(act, arg2, 0);
bellard579a97f2007-11-11 14:26:47 +00003873 if (oact)
pbrook53a59602006-03-25 19:31:22 +00003874 unlock_user_struct(oact, arg3, 1);
3875 }
bellard66fb9762003-03-23 01:06:05 +00003876 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003877#ifdef TARGET_NR_sgetmask /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00003878 case TARGET_NR_sgetmask:
bellard66fb9762003-03-23 01:06:05 +00003879 {
3880 sigset_t cur_set;
blueswir1992f48a2007-10-14 16:27:31 +00003881 abi_ulong target_set;
bellard66fb9762003-03-23 01:06:05 +00003882 sigprocmask(0, NULL, &cur_set);
3883 host_to_target_old_sigset(&target_set, &cur_set);
3884 ret = target_set;
3885 }
3886 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003887#endif
3888#ifdef TARGET_NR_ssetmask /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00003889 case TARGET_NR_ssetmask:
bellard66fb9762003-03-23 01:06:05 +00003890 {
3891 sigset_t set, oset, cur_set;
blueswir1992f48a2007-10-14 16:27:31 +00003892 abi_ulong target_set = arg1;
bellard66fb9762003-03-23 01:06:05 +00003893 sigprocmask(0, NULL, &cur_set);
3894 target_to_host_old_sigset(&set, &target_set);
3895 sigorset(&set, &set, &cur_set);
3896 sigprocmask(SIG_SETMASK, &set, &oset);
3897 host_to_target_old_sigset(&target_set, &oset);
3898 ret = target_set;
3899 }
3900 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003901#endif
thse5febef2007-04-01 18:31:35 +00003902#ifdef TARGET_NR_sigprocmask
bellard66fb9762003-03-23 01:06:05 +00003903 case TARGET_NR_sigprocmask:
3904 {
3905 int how = arg1;
3906 sigset_t set, oldset, *set_ptr;
ths3b46e622007-09-17 08:09:54 +00003907
pbrook53a59602006-03-25 19:31:22 +00003908 if (arg2) {
bellard66fb9762003-03-23 01:06:05 +00003909 switch(how) {
3910 case TARGET_SIG_BLOCK:
3911 how = SIG_BLOCK;
3912 break;
3913 case TARGET_SIG_UNBLOCK:
3914 how = SIG_UNBLOCK;
3915 break;
3916 case TARGET_SIG_SETMASK:
3917 how = SIG_SETMASK;
3918 break;
3919 default:
ths0da46a62007-10-20 20:23:07 +00003920 ret = -TARGET_EINVAL;
bellard66fb9762003-03-23 01:06:05 +00003921 goto fail;
3922 }
bellard579a97f2007-11-11 14:26:47 +00003923 if (!(p = lock_user(VERIFY_READ, arg2, sizeof(target_sigset_t), 1)))
3924 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003925 target_to_host_old_sigset(&set, p);
3926 unlock_user(p, arg2, 0);
bellard66fb9762003-03-23 01:06:05 +00003927 set_ptr = &set;
3928 } else {
3929 how = 0;
3930 set_ptr = NULL;
3931 }
3932 ret = get_errno(sigprocmask(arg1, set_ptr, &oldset));
pbrook53a59602006-03-25 19:31:22 +00003933 if (!is_error(ret) && arg3) {
bellard579a97f2007-11-11 14:26:47 +00003934 if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0)))
3935 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003936 host_to_target_old_sigset(p, &oldset);
3937 unlock_user(p, arg3, sizeof(target_sigset_t));
bellard66fb9762003-03-23 01:06:05 +00003938 }
3939 }
3940 break;
thse5febef2007-04-01 18:31:35 +00003941#endif
bellard66fb9762003-03-23 01:06:05 +00003942 case TARGET_NR_rt_sigprocmask:
3943 {
3944 int how = arg1;
3945 sigset_t set, oldset, *set_ptr;
ths3b46e622007-09-17 08:09:54 +00003946
pbrook53a59602006-03-25 19:31:22 +00003947 if (arg2) {
bellard66fb9762003-03-23 01:06:05 +00003948 switch(how) {
3949 case TARGET_SIG_BLOCK:
3950 how = SIG_BLOCK;
3951 break;
3952 case TARGET_SIG_UNBLOCK:
3953 how = SIG_UNBLOCK;
3954 break;
3955 case TARGET_SIG_SETMASK:
3956 how = SIG_SETMASK;
3957 break;
3958 default:
ths0da46a62007-10-20 20:23:07 +00003959 ret = -TARGET_EINVAL;
bellard66fb9762003-03-23 01:06:05 +00003960 goto fail;
3961 }
bellard579a97f2007-11-11 14:26:47 +00003962 if (!(p = lock_user(VERIFY_READ, arg2, sizeof(target_sigset_t), 1)))
3963 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003964 target_to_host_sigset(&set, p);
3965 unlock_user(p, arg2, 0);
bellard66fb9762003-03-23 01:06:05 +00003966 set_ptr = &set;
3967 } else {
3968 how = 0;
3969 set_ptr = NULL;
3970 }
3971 ret = get_errno(sigprocmask(how, set_ptr, &oldset));
pbrook53a59602006-03-25 19:31:22 +00003972 if (!is_error(ret) && arg3) {
bellard579a97f2007-11-11 14:26:47 +00003973 if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0)))
3974 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003975 host_to_target_sigset(p, &oldset);
3976 unlock_user(p, arg3, sizeof(target_sigset_t));
bellard66fb9762003-03-23 01:06:05 +00003977 }
3978 }
3979 break;
thse5febef2007-04-01 18:31:35 +00003980#ifdef TARGET_NR_sigpending
bellard66fb9762003-03-23 01:06:05 +00003981 case TARGET_NR_sigpending:
3982 {
3983 sigset_t set;
3984 ret = get_errno(sigpending(&set));
3985 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00003986 if (!(p = lock_user(VERIFY_WRITE, arg1, sizeof(target_sigset_t), 0)))
3987 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003988 host_to_target_old_sigset(p, &set);
3989 unlock_user(p, arg1, sizeof(target_sigset_t));
bellard66fb9762003-03-23 01:06:05 +00003990 }
3991 }
3992 break;
thse5febef2007-04-01 18:31:35 +00003993#endif
bellard66fb9762003-03-23 01:06:05 +00003994 case TARGET_NR_rt_sigpending:
3995 {
3996 sigset_t set;
3997 ret = get_errno(sigpending(&set));
3998 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00003999 if (!(p = lock_user(VERIFY_WRITE, arg1, sizeof(target_sigset_t), 0)))
4000 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004001 host_to_target_sigset(p, &set);
4002 unlock_user(p, arg1, sizeof(target_sigset_t));
bellard66fb9762003-03-23 01:06:05 +00004003 }
4004 }
4005 break;
thse5febef2007-04-01 18:31:35 +00004006#ifdef TARGET_NR_sigsuspend
bellard66fb9762003-03-23 01:06:05 +00004007 case TARGET_NR_sigsuspend:
4008 {
4009 sigset_t set;
bellard579a97f2007-11-11 14:26:47 +00004010 if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
4011 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004012 target_to_host_old_sigset(&set, p);
4013 unlock_user(p, arg1, 0);
bellard66fb9762003-03-23 01:06:05 +00004014 ret = get_errno(sigsuspend(&set));
4015 }
4016 break;
thse5febef2007-04-01 18:31:35 +00004017#endif
bellard66fb9762003-03-23 01:06:05 +00004018 case TARGET_NR_rt_sigsuspend:
4019 {
4020 sigset_t set;
bellard579a97f2007-11-11 14:26:47 +00004021 if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
4022 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004023 target_to_host_sigset(&set, p);
4024 unlock_user(p, arg1, 0);
bellard66fb9762003-03-23 01:06:05 +00004025 ret = get_errno(sigsuspend(&set));
4026 }
4027 break;
4028 case TARGET_NR_rt_sigtimedwait:
4029 {
bellard66fb9762003-03-23 01:06:05 +00004030 sigset_t set;
4031 struct timespec uts, *puts;
4032 siginfo_t uinfo;
ths3b46e622007-09-17 08:09:54 +00004033
bellard579a97f2007-11-11 14:26:47 +00004034 if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
4035 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004036 target_to_host_sigset(&set, p);
4037 unlock_user(p, arg1, 0);
4038 if (arg3) {
bellard66fb9762003-03-23 01:06:05 +00004039 puts = &uts;
pbrook53a59602006-03-25 19:31:22 +00004040 target_to_host_timespec(puts, arg3);
bellard66fb9762003-03-23 01:06:05 +00004041 } else {
4042 puts = NULL;
4043 }
4044 ret = get_errno(sigtimedwait(&set, &uinfo, puts));
pbrook53a59602006-03-25 19:31:22 +00004045 if (!is_error(ret) && arg2) {
pbrooke1e3f302008-05-30 21:53:38 +00004046 if (!(p = lock_user(VERIFY_WRITE, arg2, sizeof(target_siginfo_t), 0)))
bellard579a97f2007-11-11 14:26:47 +00004047 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004048 host_to_target_siginfo(p, &uinfo);
pbrooke1e3f302008-05-30 21:53:38 +00004049 unlock_user(p, arg2, sizeof(target_siginfo_t));
bellard66fb9762003-03-23 01:06:05 +00004050 }
4051 }
4052 break;
4053 case TARGET_NR_rt_sigqueueinfo:
4054 {
4055 siginfo_t uinfo;
bellard579a97f2007-11-11 14:26:47 +00004056 if (!(p = lock_user(VERIFY_READ, arg3, sizeof(target_sigset_t), 1)))
4057 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004058 target_to_host_siginfo(&uinfo, p);
4059 unlock_user(p, arg1, 0);
bellard66fb9762003-03-23 01:06:05 +00004060 ret = get_errno(sys_rt_sigqueueinfo(arg1, arg2, &uinfo));
4061 }
4062 break;
thse5febef2007-04-01 18:31:35 +00004063#ifdef TARGET_NR_sigreturn
bellard66fb9762003-03-23 01:06:05 +00004064 case TARGET_NR_sigreturn:
4065 /* NOTE: ret is eax, so not transcoding must be done */
4066 ret = do_sigreturn(cpu_env);
4067 break;
thse5febef2007-04-01 18:31:35 +00004068#endif
bellard66fb9762003-03-23 01:06:05 +00004069 case TARGET_NR_rt_sigreturn:
4070 /* NOTE: ret is eax, so not transcoding must be done */
4071 ret = do_rt_sigreturn(cpu_env);
4072 break;
bellard31e31b82003-02-18 22:55:36 +00004073 case TARGET_NR_sethostname:
bellard579a97f2007-11-11 14:26:47 +00004074 if (!(p = lock_user_string(arg1)))
4075 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004076 ret = get_errno(sethostname(p, arg2));
4077 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004078 break;
4079 case TARGET_NR_setrlimit:
bellard9de5e442003-03-23 16:49:39 +00004080 {
4081 /* XXX: convert resource ? */
4082 int resource = arg1;
pbrook53a59602006-03-25 19:31:22 +00004083 struct target_rlimit *target_rlim;
bellard9de5e442003-03-23 16:49:39 +00004084 struct rlimit rlim;
bellard579a97f2007-11-11 14:26:47 +00004085 if (!lock_user_struct(VERIFY_READ, target_rlim, arg2, 1))
4086 goto efault;
bellard9de5e442003-03-23 16:49:39 +00004087 rlim.rlim_cur = tswapl(target_rlim->rlim_cur);
4088 rlim.rlim_max = tswapl(target_rlim->rlim_max);
pbrook53a59602006-03-25 19:31:22 +00004089 unlock_user_struct(target_rlim, arg2, 0);
bellard9de5e442003-03-23 16:49:39 +00004090 ret = get_errno(setrlimit(resource, &rlim));
4091 }
4092 break;
bellard31e31b82003-02-18 22:55:36 +00004093 case TARGET_NR_getrlimit:
bellard9de5e442003-03-23 16:49:39 +00004094 {
4095 /* XXX: convert resource ? */
4096 int resource = arg1;
pbrook53a59602006-03-25 19:31:22 +00004097 struct target_rlimit *target_rlim;
bellard9de5e442003-03-23 16:49:39 +00004098 struct rlimit rlim;
ths3b46e622007-09-17 08:09:54 +00004099
bellard9de5e442003-03-23 16:49:39 +00004100 ret = get_errno(getrlimit(resource, &rlim));
4101 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00004102 if (!lock_user_struct(VERIFY_WRITE, target_rlim, arg2, 0))
4103 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004104 rlim.rlim_cur = tswapl(target_rlim->rlim_cur);
4105 rlim.rlim_max = tswapl(target_rlim->rlim_max);
4106 unlock_user_struct(target_rlim, arg2, 1);
bellard9de5e442003-03-23 16:49:39 +00004107 }
4108 }
4109 break;
bellard31e31b82003-02-18 22:55:36 +00004110 case TARGET_NR_getrusage:
bellardb4091862003-05-16 15:39:34 +00004111 {
4112 struct rusage rusage;
bellardb4091862003-05-16 15:39:34 +00004113 ret = get_errno(getrusage(arg1, &rusage));
4114 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00004115 host_to_target_rusage(arg2, &rusage);
bellardb4091862003-05-16 15:39:34 +00004116 }
4117 }
4118 break;
bellard31e31b82003-02-18 22:55:36 +00004119 case TARGET_NR_gettimeofday:
4120 {
bellard31e31b82003-02-18 22:55:36 +00004121 struct timeval tv;
4122 ret = get_errno(gettimeofday(&tv, NULL));
4123 if (!is_error(ret)) {
ths788f5ec2007-12-09 02:37:05 +00004124 if (copy_to_user_timeval(arg1, &tv))
4125 goto efault;
bellard31e31b82003-02-18 22:55:36 +00004126 }
4127 }
4128 break;
4129 case TARGET_NR_settimeofday:
4130 {
bellard31e31b82003-02-18 22:55:36 +00004131 struct timeval tv;
ths788f5ec2007-12-09 02:37:05 +00004132 if (copy_from_user_timeval(&tv, arg1))
4133 goto efault;
bellard31e31b82003-02-18 22:55:36 +00004134 ret = get_errno(settimeofday(&tv, NULL));
4135 }
4136 break;
bellard048f6b42005-11-26 18:47:20 +00004137#ifdef TARGET_NR_select
bellard31e31b82003-02-18 22:55:36 +00004138 case TARGET_NR_select:
bellardf2674e32003-07-09 12:26:09 +00004139 {
pbrook53a59602006-03-25 19:31:22 +00004140 struct target_sel_arg_struct *sel;
blueswir1992f48a2007-10-14 16:27:31 +00004141 abi_ulong inp, outp, exp, tvp;
pbrook53a59602006-03-25 19:31:22 +00004142 long nsel;
4143
bellard579a97f2007-11-11 14:26:47 +00004144 if (!lock_user_struct(VERIFY_READ, sel, arg1, 1))
4145 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004146 nsel = tswapl(sel->n);
4147 inp = tswapl(sel->inp);
4148 outp = tswapl(sel->outp);
4149 exp = tswapl(sel->exp);
4150 tvp = tswapl(sel->tvp);
4151 unlock_user_struct(sel, arg1, 0);
4152 ret = do_select(nsel, inp, outp, exp, tvp);
bellardf2674e32003-07-09 12:26:09 +00004153 }
4154 break;
bellard048f6b42005-11-26 18:47:20 +00004155#endif
bellard31e31b82003-02-18 22:55:36 +00004156 case TARGET_NR_symlink:
pbrook53a59602006-03-25 19:31:22 +00004157 {
4158 void *p2;
4159 p = lock_user_string(arg1);
4160 p2 = lock_user_string(arg2);
bellard579a97f2007-11-11 14:26:47 +00004161 if (!p || !p2)
4162 ret = -TARGET_EFAULT;
4163 else
4164 ret = get_errno(symlink(p, p2));
pbrook53a59602006-03-25 19:31:22 +00004165 unlock_user(p2, arg2, 0);
4166 unlock_user(p, arg1, 0);
4167 }
bellard31e31b82003-02-18 22:55:36 +00004168 break;
thsf0b62432007-09-24 09:25:40 +00004169#if defined(TARGET_NR_symlinkat) && defined(__NR_symlinkat)
4170 case TARGET_NR_symlinkat:
thsf0b62432007-09-24 09:25:40 +00004171 {
bellard579a97f2007-11-11 14:26:47 +00004172 void *p2;
thsf0b62432007-09-24 09:25:40 +00004173 p = lock_user_string(arg1);
4174 p2 = lock_user_string(arg3);
bellard579a97f2007-11-11 14:26:47 +00004175 if (!p || !p2)
ths0da46a62007-10-20 20:23:07 +00004176 ret = -TARGET_EFAULT;
thsf0b62432007-09-24 09:25:40 +00004177 else
4178 ret = get_errno(sys_symlinkat(p, arg2, p2));
bellard579a97f2007-11-11 14:26:47 +00004179 unlock_user(p2, arg3, 0);
4180 unlock_user(p, arg1, 0);
thsf0b62432007-09-24 09:25:40 +00004181 }
4182 break;
4183#endif
bellardebc05482003-09-30 21:08:41 +00004184#ifdef TARGET_NR_oldlstat
bellard31e31b82003-02-18 22:55:36 +00004185 case TARGET_NR_oldlstat:
4186 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004187#endif
bellard31e31b82003-02-18 22:55:36 +00004188 case TARGET_NR_readlink:
pbrook53a59602006-03-25 19:31:22 +00004189 {
4190 void *p2;
4191 p = lock_user_string(arg1);
bellard579a97f2007-11-11 14:26:47 +00004192 p2 = lock_user(VERIFY_WRITE, arg2, arg3, 0);
4193 if (!p || !p2)
4194 ret = -TARGET_EFAULT;
4195 else
4196 ret = get_errno(readlink(path(p), p2, arg3));
pbrook53a59602006-03-25 19:31:22 +00004197 unlock_user(p2, arg2, ret);
4198 unlock_user(p, arg1, 0);
4199 }
bellard31e31b82003-02-18 22:55:36 +00004200 break;
ths5e0ccb12007-09-24 09:26:10 +00004201#if defined(TARGET_NR_readlinkat) && defined(__NR_readlinkat)
4202 case TARGET_NR_readlinkat:
ths5e0ccb12007-09-24 09:26:10 +00004203 {
bellard579a97f2007-11-11 14:26:47 +00004204 void *p2;
ths5e0ccb12007-09-24 09:26:10 +00004205 p = lock_user_string(arg2);
bellard579a97f2007-11-11 14:26:47 +00004206 p2 = lock_user(VERIFY_WRITE, arg3, arg4, 0);
4207 if (!p || !p2)
ths0da46a62007-10-20 20:23:07 +00004208 ret = -TARGET_EFAULT;
ths5e0ccb12007-09-24 09:26:10 +00004209 else
4210 ret = get_errno(sys_readlinkat(arg1, path(p), p2, arg4));
bellard579a97f2007-11-11 14:26:47 +00004211 unlock_user(p2, arg3, ret);
4212 unlock_user(p, arg2, 0);
ths5e0ccb12007-09-24 09:26:10 +00004213 }
4214 break;
4215#endif
thse5febef2007-04-01 18:31:35 +00004216#ifdef TARGET_NR_uselib
bellard31e31b82003-02-18 22:55:36 +00004217 case TARGET_NR_uselib:
4218 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00004219#endif
4220#ifdef TARGET_NR_swapon
bellard31e31b82003-02-18 22:55:36 +00004221 case TARGET_NR_swapon:
bellard579a97f2007-11-11 14:26:47 +00004222 if (!(p = lock_user_string(arg1)))
4223 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004224 ret = get_errno(swapon(p, arg2));
4225 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004226 break;
thse5febef2007-04-01 18:31:35 +00004227#endif
bellard31e31b82003-02-18 22:55:36 +00004228 case TARGET_NR_reboot:
4229 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00004230#ifdef TARGET_NR_readdir
bellard31e31b82003-02-18 22:55:36 +00004231 case TARGET_NR_readdir:
4232 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00004233#endif
4234#ifdef TARGET_NR_mmap
bellard31e31b82003-02-18 22:55:36 +00004235 case TARGET_NR_mmap:
bellardd2fd1af2007-11-14 18:08:56 +00004236#if (defined(TARGET_I386) && defined(TARGET_ABI32)) || defined(TARGET_ARM) || defined(TARGET_M68K) || defined(TARGET_CRIS)
bellard31e31b82003-02-18 22:55:36 +00004237 {
blueswir1992f48a2007-10-14 16:27:31 +00004238 abi_ulong *v;
4239 abi_ulong v1, v2, v3, v4, v5, v6;
bellard579a97f2007-11-11 14:26:47 +00004240 if (!(v = lock_user(VERIFY_READ, arg1, 6 * sizeof(abi_ulong), 1)))
4241 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004242 v1 = tswapl(v[0]);
4243 v2 = tswapl(v[1]);
4244 v3 = tswapl(v[2]);
4245 v4 = tswapl(v[3]);
4246 v5 = tswapl(v[4]);
4247 v6 = tswapl(v[5]);
4248 unlock_user(v, arg1, 0);
ths5fafdf22007-09-16 21:08:06 +00004249 ret = get_errno(target_mmap(v1, v2, v3,
bellard5286db72003-06-05 00:57:30 +00004250 target_to_host_bitmask(v4, mmap_flags_tbl),
4251 v5, v6));
bellard31e31b82003-02-18 22:55:36 +00004252 }
bellard31e31b82003-02-18 22:55:36 +00004253#else
ths5fafdf22007-09-16 21:08:06 +00004254 ret = get_errno(target_mmap(arg1, arg2, arg3,
4255 target_to_host_bitmask(arg4, mmap_flags_tbl),
bellard6fb883e2003-07-09 17:12:39 +00004256 arg5,
4257 arg6));
bellard31e31b82003-02-18 22:55:36 +00004258#endif
bellard6fb883e2003-07-09 17:12:39 +00004259 break;
thse5febef2007-04-01 18:31:35 +00004260#endif
bellarda315a142005-01-30 22:59:18 +00004261#ifdef TARGET_NR_mmap2
bellard6fb883e2003-07-09 17:12:39 +00004262 case TARGET_NR_mmap2:
pbrookbb7ec042008-03-25 22:28:25 +00004263#ifndef MMAP_SHIFT
bellardc573ff62004-01-04 15:51:36 +00004264#define MMAP_SHIFT 12
bellardc573ff62004-01-04 15:51:36 +00004265#endif
ths5fafdf22007-09-16 21:08:06 +00004266 ret = get_errno(target_mmap(arg1, arg2, arg3,
4267 target_to_host_bitmask(arg4, mmap_flags_tbl),
bellard5286db72003-06-05 00:57:30 +00004268 arg5,
bellardc573ff62004-01-04 15:51:36 +00004269 arg6 << MMAP_SHIFT));
bellard31e31b82003-02-18 22:55:36 +00004270 break;
bellarda315a142005-01-30 22:59:18 +00004271#endif
bellard31e31b82003-02-18 22:55:36 +00004272 case TARGET_NR_munmap:
bellard54936002003-05-13 00:25:15 +00004273 ret = get_errno(target_munmap(arg1, arg2));
bellard31e31b82003-02-18 22:55:36 +00004274 break;
bellard9de5e442003-03-23 16:49:39 +00004275 case TARGET_NR_mprotect:
bellard54936002003-05-13 00:25:15 +00004276 ret = get_errno(target_mprotect(arg1, arg2, arg3));
bellard9de5e442003-03-23 16:49:39 +00004277 break;
thse5febef2007-04-01 18:31:35 +00004278#ifdef TARGET_NR_mremap
bellard9de5e442003-03-23 16:49:39 +00004279 case TARGET_NR_mremap:
bellard54936002003-05-13 00:25:15 +00004280 ret = get_errno(target_mremap(arg1, arg2, arg3, arg4, arg5));
bellard9de5e442003-03-23 16:49:39 +00004281 break;
thse5febef2007-04-01 18:31:35 +00004282#endif
pbrook53a59602006-03-25 19:31:22 +00004283 /* ??? msync/mlock/munlock are broken for softmmu. */
thse5febef2007-04-01 18:31:35 +00004284#ifdef TARGET_NR_msync
bellard9de5e442003-03-23 16:49:39 +00004285 case TARGET_NR_msync:
pbrook53a59602006-03-25 19:31:22 +00004286 ret = get_errno(msync(g2h(arg1), arg2, arg3));
bellard9de5e442003-03-23 16:49:39 +00004287 break;
thse5febef2007-04-01 18:31:35 +00004288#endif
4289#ifdef TARGET_NR_mlock
bellard9de5e442003-03-23 16:49:39 +00004290 case TARGET_NR_mlock:
pbrook53a59602006-03-25 19:31:22 +00004291 ret = get_errno(mlock(g2h(arg1), arg2));
bellard9de5e442003-03-23 16:49:39 +00004292 break;
thse5febef2007-04-01 18:31:35 +00004293#endif
4294#ifdef TARGET_NR_munlock
bellard9de5e442003-03-23 16:49:39 +00004295 case TARGET_NR_munlock:
pbrook53a59602006-03-25 19:31:22 +00004296 ret = get_errno(munlock(g2h(arg1), arg2));
bellard9de5e442003-03-23 16:49:39 +00004297 break;
thse5febef2007-04-01 18:31:35 +00004298#endif
4299#ifdef TARGET_NR_mlockall
bellard9de5e442003-03-23 16:49:39 +00004300 case TARGET_NR_mlockall:
4301 ret = get_errno(mlockall(arg1));
4302 break;
thse5febef2007-04-01 18:31:35 +00004303#endif
4304#ifdef TARGET_NR_munlockall
bellard9de5e442003-03-23 16:49:39 +00004305 case TARGET_NR_munlockall:
4306 ret = get_errno(munlockall());
4307 break;
thse5febef2007-04-01 18:31:35 +00004308#endif
bellard31e31b82003-02-18 22:55:36 +00004309 case TARGET_NR_truncate:
bellard579a97f2007-11-11 14:26:47 +00004310 if (!(p = lock_user_string(arg1)))
4311 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004312 ret = get_errno(truncate(p, arg2));
4313 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004314 break;
4315 case TARGET_NR_ftruncate:
4316 ret = get_errno(ftruncate(arg1, arg2));
4317 break;
4318 case TARGET_NR_fchmod:
4319 ret = get_errno(fchmod(arg1, arg2));
4320 break;
ths814d7972007-09-24 09:26:51 +00004321#if defined(TARGET_NR_fchmodat) && defined(__NR_fchmodat)
4322 case TARGET_NR_fchmodat:
bellard579a97f2007-11-11 14:26:47 +00004323 if (!(p = lock_user_string(arg2)))
4324 goto efault;
4325 ret = get_errno(sys_fchmodat(arg1, p, arg3, arg4));
4326 unlock_user(p, arg2, 0);
ths814d7972007-09-24 09:26:51 +00004327 break;
4328#endif
bellard31e31b82003-02-18 22:55:36 +00004329 case TARGET_NR_getpriority:
thsc6cda172007-10-09 03:42:34 +00004330 /* libc does special remapping of the return value of
4331 * sys_getpriority() so it's just easiest to call
4332 * sys_getpriority() directly rather than through libc. */
4333 ret = sys_getpriority(arg1, arg2);
bellard31e31b82003-02-18 22:55:36 +00004334 break;
4335 case TARGET_NR_setpriority:
4336 ret = get_errno(setpriority(arg1, arg2, arg3));
4337 break;
bellardebc05482003-09-30 21:08:41 +00004338#ifdef TARGET_NR_profil
bellard31e31b82003-02-18 22:55:36 +00004339 case TARGET_NR_profil:
4340 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004341#endif
bellard31e31b82003-02-18 22:55:36 +00004342 case TARGET_NR_statfs:
bellard579a97f2007-11-11 14:26:47 +00004343 if (!(p = lock_user_string(arg1)))
4344 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004345 ret = get_errno(statfs(path(p), &stfs));
4346 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004347 convert_statfs:
4348 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00004349 struct target_statfs *target_stfs;
ths3b46e622007-09-17 08:09:54 +00004350
bellard579a97f2007-11-11 14:26:47 +00004351 if (!lock_user_struct(VERIFY_WRITE, target_stfs, arg2, 0))
4352 goto efault;
4353 __put_user(stfs.f_type, &target_stfs->f_type);
4354 __put_user(stfs.f_bsize, &target_stfs->f_bsize);
4355 __put_user(stfs.f_blocks, &target_stfs->f_blocks);
4356 __put_user(stfs.f_bfree, &target_stfs->f_bfree);
4357 __put_user(stfs.f_bavail, &target_stfs->f_bavail);
4358 __put_user(stfs.f_files, &target_stfs->f_files);
4359 __put_user(stfs.f_ffree, &target_stfs->f_ffree);
4360 __put_user(stfs.f_fsid.__val[0], &target_stfs->f_fsid.val[0]);
4361 __put_user(stfs.f_fsid.__val[1], &target_stfs->f_fsid.val[1]);
4362 __put_user(stfs.f_namelen, &target_stfs->f_namelen);
pbrook53a59602006-03-25 19:31:22 +00004363 unlock_user_struct(target_stfs, arg2, 1);
bellard31e31b82003-02-18 22:55:36 +00004364 }
4365 break;
4366 case TARGET_NR_fstatfs:
bellard56c8f682005-11-28 22:28:41 +00004367 ret = get_errno(fstatfs(arg1, &stfs));
bellard31e31b82003-02-18 22:55:36 +00004368 goto convert_statfs;
bellard56c8f682005-11-28 22:28:41 +00004369#ifdef TARGET_NR_statfs64
4370 case TARGET_NR_statfs64:
bellard579a97f2007-11-11 14:26:47 +00004371 if (!(p = lock_user_string(arg1)))
4372 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004373 ret = get_errno(statfs(path(p), &stfs));
4374 unlock_user(p, arg1, 0);
bellard56c8f682005-11-28 22:28:41 +00004375 convert_statfs64:
4376 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00004377 struct target_statfs64 *target_stfs;
ths3b46e622007-09-17 08:09:54 +00004378
bellard579a97f2007-11-11 14:26:47 +00004379 if (!lock_user_struct(VERIFY_WRITE, target_stfs, arg3, 0))
4380 goto efault;
4381 __put_user(stfs.f_type, &target_stfs->f_type);
4382 __put_user(stfs.f_bsize, &target_stfs->f_bsize);
4383 __put_user(stfs.f_blocks, &target_stfs->f_blocks);
4384 __put_user(stfs.f_bfree, &target_stfs->f_bfree);
4385 __put_user(stfs.f_bavail, &target_stfs->f_bavail);
4386 __put_user(stfs.f_files, &target_stfs->f_files);
4387 __put_user(stfs.f_ffree, &target_stfs->f_ffree);
4388 __put_user(stfs.f_fsid.__val[0], &target_stfs->f_fsid.val[0]);
4389 __put_user(stfs.f_fsid.__val[1], &target_stfs->f_fsid.val[1]);
4390 __put_user(stfs.f_namelen, &target_stfs->f_namelen);
4391 unlock_user_struct(target_stfs, arg3, 1);
bellard56c8f682005-11-28 22:28:41 +00004392 }
4393 break;
4394 case TARGET_NR_fstatfs64:
4395 ret = get_errno(fstatfs(arg1, &stfs));
4396 goto convert_statfs64;
4397#endif
bellardebc05482003-09-30 21:08:41 +00004398#ifdef TARGET_NR_ioperm
bellard31e31b82003-02-18 22:55:36 +00004399 case TARGET_NR_ioperm:
4400 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004401#endif
thse5febef2007-04-01 18:31:35 +00004402#ifdef TARGET_NR_socketcall
bellard31e31b82003-02-18 22:55:36 +00004403 case TARGET_NR_socketcall:
pbrook53a59602006-03-25 19:31:22 +00004404 ret = do_socketcall(arg1, arg2);
bellard31e31b82003-02-18 22:55:36 +00004405 break;
thse5febef2007-04-01 18:31:35 +00004406#endif
bellard3532fa72006-06-24 15:06:03 +00004407#ifdef TARGET_NR_accept
4408 case TARGET_NR_accept:
pbrook1be9e1d2006-11-19 15:26:04 +00004409 ret = do_accept(arg1, arg2, arg3);
bellard3532fa72006-06-24 15:06:03 +00004410 break;
4411#endif
4412#ifdef TARGET_NR_bind
4413 case TARGET_NR_bind:
4414 ret = do_bind(arg1, arg2, arg3);
4415 break;
4416#endif
4417#ifdef TARGET_NR_connect
4418 case TARGET_NR_connect:
4419 ret = do_connect(arg1, arg2, arg3);
4420 break;
4421#endif
4422#ifdef TARGET_NR_getpeername
4423 case TARGET_NR_getpeername:
pbrook1be9e1d2006-11-19 15:26:04 +00004424 ret = do_getpeername(arg1, arg2, arg3);
bellard3532fa72006-06-24 15:06:03 +00004425 break;
4426#endif
4427#ifdef TARGET_NR_getsockname
4428 case TARGET_NR_getsockname:
pbrook1be9e1d2006-11-19 15:26:04 +00004429 ret = do_getsockname(arg1, arg2, arg3);
bellard3532fa72006-06-24 15:06:03 +00004430 break;
4431#endif
4432#ifdef TARGET_NR_getsockopt
4433 case TARGET_NR_getsockopt:
4434 ret = do_getsockopt(arg1, arg2, arg3, arg4, arg5);
4435 break;
4436#endif
4437#ifdef TARGET_NR_listen
4438 case TARGET_NR_listen:
pbrook1be9e1d2006-11-19 15:26:04 +00004439 ret = get_errno(listen(arg1, arg2));
bellard3532fa72006-06-24 15:06:03 +00004440 break;
4441#endif
4442#ifdef TARGET_NR_recv
4443 case TARGET_NR_recv:
pbrook214201b2007-03-17 01:27:24 +00004444 ret = do_recvfrom(arg1, arg2, arg3, arg4, 0, 0);
bellard3532fa72006-06-24 15:06:03 +00004445 break;
4446#endif
4447#ifdef TARGET_NR_recvfrom
4448 case TARGET_NR_recvfrom:
pbrook214201b2007-03-17 01:27:24 +00004449 ret = do_recvfrom(arg1, arg2, arg3, arg4, arg5, arg6);
bellard3532fa72006-06-24 15:06:03 +00004450 break;
4451#endif
4452#ifdef TARGET_NR_recvmsg
4453 case TARGET_NR_recvmsg:
4454 ret = do_sendrecvmsg(arg1, arg2, arg3, 0);
4455 break;
4456#endif
4457#ifdef TARGET_NR_send
4458 case TARGET_NR_send:
pbrook1be9e1d2006-11-19 15:26:04 +00004459 ret = do_sendto(arg1, arg2, arg3, arg4, 0, 0);
bellard3532fa72006-06-24 15:06:03 +00004460 break;
4461#endif
4462#ifdef TARGET_NR_sendmsg
4463 case TARGET_NR_sendmsg:
4464 ret = do_sendrecvmsg(arg1, arg2, arg3, 1);
4465 break;
4466#endif
4467#ifdef TARGET_NR_sendto
4468 case TARGET_NR_sendto:
pbrook1be9e1d2006-11-19 15:26:04 +00004469 ret = do_sendto(arg1, arg2, arg3, arg4, arg5, arg6);
bellard3532fa72006-06-24 15:06:03 +00004470 break;
4471#endif
4472#ifdef TARGET_NR_shutdown
4473 case TARGET_NR_shutdown:
pbrook1be9e1d2006-11-19 15:26:04 +00004474 ret = get_errno(shutdown(arg1, arg2));
bellard3532fa72006-06-24 15:06:03 +00004475 break;
4476#endif
4477#ifdef TARGET_NR_socket
4478 case TARGET_NR_socket:
4479 ret = do_socket(arg1, arg2, arg3);
4480 break;
4481#endif
4482#ifdef TARGET_NR_socketpair
4483 case TARGET_NR_socketpair:
pbrook1be9e1d2006-11-19 15:26:04 +00004484 ret = do_socketpair(arg1, arg2, arg3, arg4);
bellard3532fa72006-06-24 15:06:03 +00004485 break;
4486#endif
4487#ifdef TARGET_NR_setsockopt
4488 case TARGET_NR_setsockopt:
4489 ret = do_setsockopt(arg1, arg2, arg3, arg4, (socklen_t) arg5);
4490 break;
4491#endif
ths7494b0f2007-02-11 18:26:53 +00004492
bellard31e31b82003-02-18 22:55:36 +00004493 case TARGET_NR_syslog:
bellard579a97f2007-11-11 14:26:47 +00004494 if (!(p = lock_user_string(arg2)))
4495 goto efault;
thse5574482007-02-11 20:03:13 +00004496 ret = get_errno(sys_syslog((int)arg1, p, (int)arg3));
4497 unlock_user(p, arg2, 0);
ths7494b0f2007-02-11 18:26:53 +00004498 break;
4499
bellard31e31b82003-02-18 22:55:36 +00004500 case TARGET_NR_setitimer:
bellard66fb9762003-03-23 01:06:05 +00004501 {
bellard66fb9762003-03-23 01:06:05 +00004502 struct itimerval value, ovalue, *pvalue;
4503
pbrook53a59602006-03-25 19:31:22 +00004504 if (arg2) {
bellard66fb9762003-03-23 01:06:05 +00004505 pvalue = &value;
ths788f5ec2007-12-09 02:37:05 +00004506 if (copy_from_user_timeval(&pvalue->it_interval, arg2)
4507 || copy_from_user_timeval(&pvalue->it_value,
4508 arg2 + sizeof(struct target_timeval)))
4509 goto efault;
bellard66fb9762003-03-23 01:06:05 +00004510 } else {
4511 pvalue = NULL;
4512 }
4513 ret = get_errno(setitimer(arg1, pvalue, &ovalue));
pbrook53a59602006-03-25 19:31:22 +00004514 if (!is_error(ret) && arg3) {
ths788f5ec2007-12-09 02:37:05 +00004515 if (copy_to_user_timeval(arg3,
4516 &ovalue.it_interval)
4517 || copy_to_user_timeval(arg3 + sizeof(struct target_timeval),
4518 &ovalue.it_value))
4519 goto efault;
bellard66fb9762003-03-23 01:06:05 +00004520 }
4521 }
4522 break;
bellard31e31b82003-02-18 22:55:36 +00004523 case TARGET_NR_getitimer:
bellard66fb9762003-03-23 01:06:05 +00004524 {
bellard66fb9762003-03-23 01:06:05 +00004525 struct itimerval value;
ths3b46e622007-09-17 08:09:54 +00004526
bellard66fb9762003-03-23 01:06:05 +00004527 ret = get_errno(getitimer(arg1, &value));
pbrook53a59602006-03-25 19:31:22 +00004528 if (!is_error(ret) && arg2) {
ths788f5ec2007-12-09 02:37:05 +00004529 if (copy_to_user_timeval(arg2,
4530 &value.it_interval)
4531 || copy_to_user_timeval(arg2 + sizeof(struct target_timeval),
4532 &value.it_value))
4533 goto efault;
bellard66fb9762003-03-23 01:06:05 +00004534 }
4535 }
4536 break;
bellard31e31b82003-02-18 22:55:36 +00004537 case TARGET_NR_stat:
bellard579a97f2007-11-11 14:26:47 +00004538 if (!(p = lock_user_string(arg1)))
4539 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004540 ret = get_errno(stat(path(p), &st));
4541 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004542 goto do_stat;
4543 case TARGET_NR_lstat:
bellard579a97f2007-11-11 14:26:47 +00004544 if (!(p = lock_user_string(arg1)))
4545 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004546 ret = get_errno(lstat(path(p), &st));
4547 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004548 goto do_stat;
4549 case TARGET_NR_fstat:
4550 {
4551 ret = get_errno(fstat(arg1, &st));
4552 do_stat:
4553 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00004554 struct target_stat *target_st;
thse3584652007-06-01 11:49:38 +00004555
bellard579a97f2007-11-11 14:26:47 +00004556 if (!lock_user_struct(VERIFY_WRITE, target_st, arg2, 0))
4557 goto efault;
bellardd2fd1af2007-11-14 18:08:56 +00004558 __put_user(st.st_dev, &target_st->st_dev);
4559 __put_user(st.st_ino, &target_st->st_ino);
4560 __put_user(st.st_mode, &target_st->st_mode);
4561 __put_user(st.st_uid, &target_st->st_uid);
4562 __put_user(st.st_gid, &target_st->st_gid);
4563 __put_user(st.st_nlink, &target_st->st_nlink);
4564 __put_user(st.st_rdev, &target_st->st_rdev);
4565 __put_user(st.st_size, &target_st->st_size);
4566 __put_user(st.st_blksize, &target_st->st_blksize);
4567 __put_user(st.st_blocks, &target_st->st_blocks);
4568 __put_user(st.st_atime, &target_st->target_st_atime);
4569 __put_user(st.st_mtime, &target_st->target_st_mtime);
4570 __put_user(st.st_ctime, &target_st->target_st_ctime);
pbrook53a59602006-03-25 19:31:22 +00004571 unlock_user_struct(target_st, arg2, 1);
bellard31e31b82003-02-18 22:55:36 +00004572 }
4573 }
4574 break;
bellardebc05482003-09-30 21:08:41 +00004575#ifdef TARGET_NR_olduname
bellard31e31b82003-02-18 22:55:36 +00004576 case TARGET_NR_olduname:
4577 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004578#endif
4579#ifdef TARGET_NR_iopl
bellard31e31b82003-02-18 22:55:36 +00004580 case TARGET_NR_iopl:
4581 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004582#endif
bellard31e31b82003-02-18 22:55:36 +00004583 case TARGET_NR_vhangup:
4584 ret = get_errno(vhangup());
4585 break;
bellardebc05482003-09-30 21:08:41 +00004586#ifdef TARGET_NR_idle
bellard31e31b82003-02-18 22:55:36 +00004587 case TARGET_NR_idle:
4588 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004589#endif
bellard42ad6ae2005-01-03 22:48:11 +00004590#ifdef TARGET_NR_syscall
4591 case TARGET_NR_syscall:
4592 ret = do_syscall(cpu_env,arg1 & 0xffff,arg2,arg3,arg4,arg5,arg6,0);
4593 break;
4594#endif
bellard31e31b82003-02-18 22:55:36 +00004595 case TARGET_NR_wait4:
4596 {
4597 int status;
blueswir1992f48a2007-10-14 16:27:31 +00004598 abi_long status_ptr = arg2;
bellard31e31b82003-02-18 22:55:36 +00004599 struct rusage rusage, *rusage_ptr;
blueswir1992f48a2007-10-14 16:27:31 +00004600 abi_ulong target_rusage = arg4;
bellard31e31b82003-02-18 22:55:36 +00004601 if (target_rusage)
4602 rusage_ptr = &rusage;
4603 else
4604 rusage_ptr = NULL;
4605 ret = get_errno(wait4(arg1, &status, arg3, rusage_ptr));
4606 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +00004607 if (status_ptr) {
4608 if (put_user_s32(status, status_ptr))
4609 goto efault;
bellard31e31b82003-02-18 22:55:36 +00004610 }
bellard2f619692007-11-16 10:46:05 +00004611 if (target_rusage)
4612 host_to_target_rusage(target_rusage, &rusage);
bellard31e31b82003-02-18 22:55:36 +00004613 }
4614 }
4615 break;
thse5febef2007-04-01 18:31:35 +00004616#ifdef TARGET_NR_swapoff
bellard31e31b82003-02-18 22:55:36 +00004617 case TARGET_NR_swapoff:
bellard579a97f2007-11-11 14:26:47 +00004618 if (!(p = lock_user_string(arg1)))
4619 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004620 ret = get_errno(swapoff(p));
4621 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004622 break;
thse5febef2007-04-01 18:31:35 +00004623#endif
bellard31e31b82003-02-18 22:55:36 +00004624 case TARGET_NR_sysinfo:
bellarda5448a72004-06-19 16:59:03 +00004625 {
pbrook53a59602006-03-25 19:31:22 +00004626 struct target_sysinfo *target_value;
bellarda5448a72004-06-19 16:59:03 +00004627 struct sysinfo value;
4628 ret = get_errno(sysinfo(&value));
pbrook53a59602006-03-25 19:31:22 +00004629 if (!is_error(ret) && arg1)
bellarda5448a72004-06-19 16:59:03 +00004630 {
bellard579a97f2007-11-11 14:26:47 +00004631 if (!lock_user_struct(VERIFY_WRITE, target_value, arg1, 0))
4632 goto efault;
bellarda5448a72004-06-19 16:59:03 +00004633 __put_user(value.uptime, &target_value->uptime);
4634 __put_user(value.loads[0], &target_value->loads[0]);
4635 __put_user(value.loads[1], &target_value->loads[1]);
4636 __put_user(value.loads[2], &target_value->loads[2]);
4637 __put_user(value.totalram, &target_value->totalram);
4638 __put_user(value.freeram, &target_value->freeram);
4639 __put_user(value.sharedram, &target_value->sharedram);
4640 __put_user(value.bufferram, &target_value->bufferram);
4641 __put_user(value.totalswap, &target_value->totalswap);
4642 __put_user(value.freeswap, &target_value->freeswap);
4643 __put_user(value.procs, &target_value->procs);
4644 __put_user(value.totalhigh, &target_value->totalhigh);
4645 __put_user(value.freehigh, &target_value->freehigh);
4646 __put_user(value.mem_unit, &target_value->mem_unit);
pbrook53a59602006-03-25 19:31:22 +00004647 unlock_user_struct(target_value, arg1, 1);
bellarda5448a72004-06-19 16:59:03 +00004648 }
4649 }
4650 break;
thse5febef2007-04-01 18:31:35 +00004651#ifdef TARGET_NR_ipc
bellard31e31b82003-02-18 22:55:36 +00004652 case TARGET_NR_ipc:
bellard8853f862004-02-22 14:57:26 +00004653 ret = do_ipc(arg1, arg2, arg3, arg4, arg5, arg6);
4654 break;
thse5febef2007-04-01 18:31:35 +00004655#endif
bellard31e31b82003-02-18 22:55:36 +00004656 case TARGET_NR_fsync:
4657 ret = get_errno(fsync(arg1));
4658 break;
bellard31e31b82003-02-18 22:55:36 +00004659 case TARGET_NR_clone:
pbrookd865bab2008-06-07 22:12:17 +00004660 ret = get_errno(do_fork(cpu_env, arg1, arg2, arg3, arg4, arg5));
bellard1b6b0292003-03-22 17:31:38 +00004661 break;
bellardec86b0f2003-04-11 00:15:04 +00004662#ifdef __NR_exit_group
4663 /* new thread calls */
4664 case TARGET_NR_exit_group:
bellarde9009672005-04-26 20:42:36 +00004665 gdb_exit(cpu_env, arg1);
bellardec86b0f2003-04-11 00:15:04 +00004666 ret = get_errno(exit_group(arg1));
4667 break;
4668#endif
bellard31e31b82003-02-18 22:55:36 +00004669 case TARGET_NR_setdomainname:
bellard579a97f2007-11-11 14:26:47 +00004670 if (!(p = lock_user_string(arg1)))
4671 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004672 ret = get_errno(setdomainname(p, arg2));
4673 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004674 break;
4675 case TARGET_NR_uname:
4676 /* no need to transcode because we use the linux syscall */
bellard29e619b2004-09-13 21:41:04 +00004677 {
4678 struct new_utsname * buf;
ths3b46e622007-09-17 08:09:54 +00004679
bellard579a97f2007-11-11 14:26:47 +00004680 if (!lock_user_struct(VERIFY_WRITE, buf, arg1, 0))
4681 goto efault;
bellard29e619b2004-09-13 21:41:04 +00004682 ret = get_errno(sys_uname(buf));
4683 if (!is_error(ret)) {
4684 /* Overrite the native machine name with whatever is being
4685 emulated. */
4686 strcpy (buf->machine, UNAME_MACHINE);
pbrookc5937222006-05-14 11:30:38 +00004687 /* Allow the user to override the reported release. */
4688 if (qemu_uname_release && *qemu_uname_release)
4689 strcpy (buf->release, qemu_uname_release);
bellard29e619b2004-09-13 21:41:04 +00004690 }
pbrook53a59602006-03-25 19:31:22 +00004691 unlock_user_struct(buf, arg1, 1);
bellard29e619b2004-09-13 21:41:04 +00004692 }
bellard31e31b82003-02-18 22:55:36 +00004693 break;
bellard6dbad632003-03-16 18:05:05 +00004694#ifdef TARGET_I386
bellard31e31b82003-02-18 22:55:36 +00004695 case TARGET_NR_modify_ldt:
bellard03acab62007-11-11 14:57:14 +00004696 ret = do_modify_ldt(cpu_env, arg1, arg2, arg3);
bellard5cd43932003-03-29 16:54:36 +00004697 break;
j_mayer84409dd2007-04-06 08:56:50 +00004698#if !defined(TARGET_X86_64)
bellard5cd43932003-03-29 16:54:36 +00004699 case TARGET_NR_vm86old:
4700 goto unimplemented;
4701 case TARGET_NR_vm86:
pbrook53a59602006-03-25 19:31:22 +00004702 ret = do_vm86(cpu_env, arg1, arg2);
bellard6dbad632003-03-16 18:05:05 +00004703 break;
4704#endif
j_mayer84409dd2007-04-06 08:56:50 +00004705#endif
bellard31e31b82003-02-18 22:55:36 +00004706 case TARGET_NR_adjtimex:
4707 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00004708#ifdef TARGET_NR_create_module
bellard31e31b82003-02-18 22:55:36 +00004709 case TARGET_NR_create_module:
thse5febef2007-04-01 18:31:35 +00004710#endif
bellard31e31b82003-02-18 22:55:36 +00004711 case TARGET_NR_init_module:
4712 case TARGET_NR_delete_module:
thse5febef2007-04-01 18:31:35 +00004713#ifdef TARGET_NR_get_kernel_syms
bellard31e31b82003-02-18 22:55:36 +00004714 case TARGET_NR_get_kernel_syms:
thse5febef2007-04-01 18:31:35 +00004715#endif
bellard31e31b82003-02-18 22:55:36 +00004716 goto unimplemented;
4717 case TARGET_NR_quotactl:
4718 goto unimplemented;
4719 case TARGET_NR_getpgid:
4720 ret = get_errno(getpgid(arg1));
4721 break;
4722 case TARGET_NR_fchdir:
4723 ret = get_errno(fchdir(arg1));
4724 break;
j_mayer84409dd2007-04-06 08:56:50 +00004725#ifdef TARGET_NR_bdflush /* not on x86_64 */
bellard31e31b82003-02-18 22:55:36 +00004726 case TARGET_NR_bdflush:
4727 goto unimplemented;
j_mayer84409dd2007-04-06 08:56:50 +00004728#endif
thse5febef2007-04-01 18:31:35 +00004729#ifdef TARGET_NR_sysfs
bellard31e31b82003-02-18 22:55:36 +00004730 case TARGET_NR_sysfs:
4731 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00004732#endif
bellard31e31b82003-02-18 22:55:36 +00004733 case TARGET_NR_personality:
bellard1b6b0292003-03-22 17:31:38 +00004734 ret = get_errno(personality(arg1));
bellard31e31b82003-02-18 22:55:36 +00004735 break;
thse5febef2007-04-01 18:31:35 +00004736#ifdef TARGET_NR_afs_syscall
bellard31e31b82003-02-18 22:55:36 +00004737 case TARGET_NR_afs_syscall:
4738 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00004739#endif
j_mayer7a3148a2007-04-05 07:13:51 +00004740#ifdef TARGET_NR__llseek /* Not on alpha */
bellard31e31b82003-02-18 22:55:36 +00004741 case TARGET_NR__llseek:
4742 {
bellard4f2ac232004-04-26 19:44:02 +00004743#if defined (__x86_64__)
4744 ret = get_errno(lseek(arg1, ((uint64_t )arg2 << 32) | arg3, arg5));
bellard2f619692007-11-16 10:46:05 +00004745 if (put_user_s64(ret, arg4))
4746 goto efault;
bellard4f2ac232004-04-26 19:44:02 +00004747#else
bellard31e31b82003-02-18 22:55:36 +00004748 int64_t res;
4749 ret = get_errno(_llseek(arg1, arg2, arg3, &res, arg5));
bellard2f619692007-11-16 10:46:05 +00004750 if (put_user_s64(res, arg4))
4751 goto efault;
bellard4f2ac232004-04-26 19:44:02 +00004752#endif
bellard31e31b82003-02-18 22:55:36 +00004753 }
4754 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004755#endif
bellard31e31b82003-02-18 22:55:36 +00004756 case TARGET_NR_getdents:
blueswir1992f48a2007-10-14 16:27:31 +00004757#if TARGET_ABI_BITS != 32
pbrook53a59602006-03-25 19:31:22 +00004758 goto unimplemented;
blueswir1992f48a2007-10-14 16:27:31 +00004759#elif TARGET_ABI_BITS == 32 && HOST_LONG_BITS == 64
bellard4add45b2003-06-05 01:52:59 +00004760 {
pbrook53a59602006-03-25 19:31:22 +00004761 struct target_dirent *target_dirp;
bellard4add45b2003-06-05 01:52:59 +00004762 struct dirent *dirp;
blueswir1992f48a2007-10-14 16:27:31 +00004763 abi_long count = arg3;
bellard4add45b2003-06-05 01:52:59 +00004764
4765 dirp = malloc(count);
ths0da46a62007-10-20 20:23:07 +00004766 if (!dirp) {
bellard579a97f2007-11-11 14:26:47 +00004767 ret = -TARGET_ENOMEM;
ths0da46a62007-10-20 20:23:07 +00004768 goto fail;
4769 }
ths3b46e622007-09-17 08:09:54 +00004770
bellard4add45b2003-06-05 01:52:59 +00004771 ret = get_errno(sys_getdents(arg1, dirp, count));
4772 if (!is_error(ret)) {
4773 struct dirent *de;
4774 struct target_dirent *tde;
4775 int len = ret;
4776 int reclen, treclen;
4777 int count1, tnamelen;
4778
4779 count1 = 0;
4780 de = dirp;
bellard579a97f2007-11-11 14:26:47 +00004781 if (!(target_dirp = lock_user(VERIFY_WRITE, arg2, count, 0)))
4782 goto efault;
bellard4add45b2003-06-05 01:52:59 +00004783 tde = target_dirp;
4784 while (len > 0) {
4785 reclen = de->d_reclen;
blueswir1992f48a2007-10-14 16:27:31 +00004786 treclen = reclen - (2 * (sizeof(long) - sizeof(abi_long)));
bellard4add45b2003-06-05 01:52:59 +00004787 tde->d_reclen = tswap16(treclen);
4788 tde->d_ino = tswapl(de->d_ino);
4789 tde->d_off = tswapl(de->d_off);
blueswir1992f48a2007-10-14 16:27:31 +00004790 tnamelen = treclen - (2 * sizeof(abi_long) + 2);
bellard4add45b2003-06-05 01:52:59 +00004791 if (tnamelen > 256)
4792 tnamelen = 256;
bellard80a9d032005-01-03 23:31:27 +00004793 /* XXX: may not be correct */
bellard4add45b2003-06-05 01:52:59 +00004794 strncpy(tde->d_name, de->d_name, tnamelen);
4795 de = (struct dirent *)((char *)de + reclen);
4796 len -= reclen;
j_mayer1c5bf3b2007-04-14 12:17:59 +00004797 tde = (struct target_dirent *)((char *)tde + treclen);
bellard4add45b2003-06-05 01:52:59 +00004798 count1 += treclen;
4799 }
4800 ret = count1;
bellard579a97f2007-11-11 14:26:47 +00004801 unlock_user(target_dirp, arg2, ret);
bellard4add45b2003-06-05 01:52:59 +00004802 }
4803 free(dirp);
4804 }
4805#else
bellard31e31b82003-02-18 22:55:36 +00004806 {
pbrook53a59602006-03-25 19:31:22 +00004807 struct dirent *dirp;
blueswir1992f48a2007-10-14 16:27:31 +00004808 abi_long count = arg3;
bellarddab2ed92003-03-22 15:23:14 +00004809
bellard579a97f2007-11-11 14:26:47 +00004810 if (!(dirp = lock_user(VERIFY_WRITE, arg2, count, 0)))
4811 goto efault;
bellard72f03902003-02-18 23:33:18 +00004812 ret = get_errno(sys_getdents(arg1, dirp, count));
bellard31e31b82003-02-18 22:55:36 +00004813 if (!is_error(ret)) {
4814 struct dirent *de;
4815 int len = ret;
4816 int reclen;
4817 de = dirp;
4818 while (len > 0) {
bellard8083a3e2003-03-24 23:12:16 +00004819 reclen = de->d_reclen;
bellard31e31b82003-02-18 22:55:36 +00004820 if (reclen > len)
4821 break;
bellard8083a3e2003-03-24 23:12:16 +00004822 de->d_reclen = tswap16(reclen);
bellard31e31b82003-02-18 22:55:36 +00004823 tswapls(&de->d_ino);
4824 tswapls(&de->d_off);
4825 de = (struct dirent *)((char *)de + reclen);
4826 len -= reclen;
4827 }
4828 }
pbrook53a59602006-03-25 19:31:22 +00004829 unlock_user(dirp, arg2, ret);
bellard31e31b82003-02-18 22:55:36 +00004830 }
bellard4add45b2003-06-05 01:52:59 +00004831#endif
bellard31e31b82003-02-18 22:55:36 +00004832 break;
ths3ae43202007-09-16 21:39:48 +00004833#if defined(TARGET_NR_getdents64) && defined(__NR_getdents64)
bellarddab2ed92003-03-22 15:23:14 +00004834 case TARGET_NR_getdents64:
4835 {
pbrook53a59602006-03-25 19:31:22 +00004836 struct dirent64 *dirp;
blueswir1992f48a2007-10-14 16:27:31 +00004837 abi_long count = arg3;
bellard579a97f2007-11-11 14:26:47 +00004838 if (!(dirp = lock_user(VERIFY_WRITE, arg2, count, 0)))
4839 goto efault;
bellarddab2ed92003-03-22 15:23:14 +00004840 ret = get_errno(sys_getdents64(arg1, dirp, count));
4841 if (!is_error(ret)) {
4842 struct dirent64 *de;
4843 int len = ret;
4844 int reclen;
4845 de = dirp;
4846 while (len > 0) {
bellard8083a3e2003-03-24 23:12:16 +00004847 reclen = de->d_reclen;
bellarddab2ed92003-03-22 15:23:14 +00004848 if (reclen > len)
4849 break;
bellard8083a3e2003-03-24 23:12:16 +00004850 de->d_reclen = tswap16(reclen);
bellard8582a532007-11-11 23:11:36 +00004851 tswap64s((uint64_t *)&de->d_ino);
4852 tswap64s((uint64_t *)&de->d_off);
bellarddab2ed92003-03-22 15:23:14 +00004853 de = (struct dirent64 *)((char *)de + reclen);
4854 len -= reclen;
4855 }
4856 }
pbrook53a59602006-03-25 19:31:22 +00004857 unlock_user(dirp, arg2, ret);
bellarddab2ed92003-03-22 15:23:14 +00004858 }
4859 break;
bellarda541f292004-04-12 20:39:29 +00004860#endif /* TARGET_NR_getdents64 */
thse5febef2007-04-01 18:31:35 +00004861#ifdef TARGET_NR__newselect
bellard31e31b82003-02-18 22:55:36 +00004862 case TARGET_NR__newselect:
pbrook53a59602006-03-25 19:31:22 +00004863 ret = do_select(arg1, arg2, arg3, arg4, arg5);
bellard31e31b82003-02-18 22:55:36 +00004864 break;
thse5febef2007-04-01 18:31:35 +00004865#endif
4866#ifdef TARGET_NR_poll
bellard9de5e442003-03-23 16:49:39 +00004867 case TARGET_NR_poll:
4868 {
pbrook53a59602006-03-25 19:31:22 +00004869 struct target_pollfd *target_pfd;
bellard9de5e442003-03-23 16:49:39 +00004870 unsigned int nfds = arg2;
4871 int timeout = arg3;
4872 struct pollfd *pfd;
bellard7854b052003-03-29 17:22:23 +00004873 unsigned int i;
bellard9de5e442003-03-23 16:49:39 +00004874
bellard579a97f2007-11-11 14:26:47 +00004875 target_pfd = lock_user(VERIFY_WRITE, arg1, sizeof(struct target_pollfd) * nfds, 1);
4876 if (!target_pfd)
4877 goto efault;
bellard9de5e442003-03-23 16:49:39 +00004878 pfd = alloca(sizeof(struct pollfd) * nfds);
4879 for(i = 0; i < nfds; i++) {
bellard5cd43932003-03-29 16:54:36 +00004880 pfd[i].fd = tswap32(target_pfd[i].fd);
4881 pfd[i].events = tswap16(target_pfd[i].events);
bellard9de5e442003-03-23 16:49:39 +00004882 }
4883 ret = get_errno(poll(pfd, nfds, timeout));
4884 if (!is_error(ret)) {
4885 for(i = 0; i < nfds; i++) {
bellard5cd43932003-03-29 16:54:36 +00004886 target_pfd[i].revents = tswap16(pfd[i].revents);
bellard9de5e442003-03-23 16:49:39 +00004887 }
pbrook53a59602006-03-25 19:31:22 +00004888 ret += nfds * (sizeof(struct target_pollfd)
4889 - sizeof(struct pollfd));
bellard9de5e442003-03-23 16:49:39 +00004890 }
pbrook53a59602006-03-25 19:31:22 +00004891 unlock_user(target_pfd, arg1, ret);
bellard9de5e442003-03-23 16:49:39 +00004892 }
4893 break;
thse5febef2007-04-01 18:31:35 +00004894#endif
bellard31e31b82003-02-18 22:55:36 +00004895 case TARGET_NR_flock:
bellard9de5e442003-03-23 16:49:39 +00004896 /* NOTE: the flock constant seems to be the same for every
4897 Linux platform */
4898 ret = get_errno(flock(arg1, arg2));
bellard31e31b82003-02-18 22:55:36 +00004899 break;
4900 case TARGET_NR_readv:
4901 {
4902 int count = arg3;
bellard31e31b82003-02-18 22:55:36 +00004903 struct iovec *vec;
bellard31e31b82003-02-18 22:55:36 +00004904
4905 vec = alloca(count * sizeof(struct iovec));
bellard41df8412008-02-04 22:26:57 +00004906 if (lock_iovec(VERIFY_WRITE, vec, arg2, count, 0) < 0)
4907 goto efault;
bellard31e31b82003-02-18 22:55:36 +00004908 ret = get_errno(readv(arg1, vec, count));
pbrook53a59602006-03-25 19:31:22 +00004909 unlock_iovec(vec, arg2, count, 1);
bellard31e31b82003-02-18 22:55:36 +00004910 }
4911 break;
4912 case TARGET_NR_writev:
4913 {
4914 int count = arg3;
bellard31e31b82003-02-18 22:55:36 +00004915 struct iovec *vec;
bellard31e31b82003-02-18 22:55:36 +00004916
4917 vec = alloca(count * sizeof(struct iovec));
bellard41df8412008-02-04 22:26:57 +00004918 if (lock_iovec(VERIFY_READ, vec, arg2, count, 1) < 0)
4919 goto efault;
bellard31e31b82003-02-18 22:55:36 +00004920 ret = get_errno(writev(arg1, vec, count));
pbrook53a59602006-03-25 19:31:22 +00004921 unlock_iovec(vec, arg2, count, 0);
bellard31e31b82003-02-18 22:55:36 +00004922 }
4923 break;
4924 case TARGET_NR_getsid:
4925 ret = get_errno(getsid(arg1));
4926 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004927#if defined(TARGET_NR_fdatasync) /* Not on alpha (osf_datasync ?) */
bellard31e31b82003-02-18 22:55:36 +00004928 case TARGET_NR_fdatasync:
bellard5cd43932003-03-29 16:54:36 +00004929 ret = get_errno(fdatasync(arg1));
4930 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004931#endif
bellard31e31b82003-02-18 22:55:36 +00004932 case TARGET_NR__sysctl:
ths0da46a62007-10-20 20:23:07 +00004933 /* We don't implement this, but ENOTDIR is always a safe
bellard29e619b2004-09-13 21:41:04 +00004934 return value. */
ths0da46a62007-10-20 20:23:07 +00004935 ret = -TARGET_ENOTDIR;
4936 break;
bellard31e31b82003-02-18 22:55:36 +00004937 case TARGET_NR_sched_setparam:
bellard5cd43932003-03-29 16:54:36 +00004938 {
pbrook53a59602006-03-25 19:31:22 +00004939 struct sched_param *target_schp;
bellard5cd43932003-03-29 16:54:36 +00004940 struct sched_param schp;
pbrook53a59602006-03-25 19:31:22 +00004941
bellard579a97f2007-11-11 14:26:47 +00004942 if (!lock_user_struct(VERIFY_READ, target_schp, arg2, 1))
4943 goto efault;
bellard5cd43932003-03-29 16:54:36 +00004944 schp.sched_priority = tswap32(target_schp->sched_priority);
pbrook53a59602006-03-25 19:31:22 +00004945 unlock_user_struct(target_schp, arg2, 0);
bellard5cd43932003-03-29 16:54:36 +00004946 ret = get_errno(sched_setparam(arg1, &schp));
4947 }
4948 break;
bellard31e31b82003-02-18 22:55:36 +00004949 case TARGET_NR_sched_getparam:
bellard5cd43932003-03-29 16:54:36 +00004950 {
pbrook53a59602006-03-25 19:31:22 +00004951 struct sched_param *target_schp;
bellard5cd43932003-03-29 16:54:36 +00004952 struct sched_param schp;
4953 ret = get_errno(sched_getparam(arg1, &schp));
4954 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00004955 if (!lock_user_struct(VERIFY_WRITE, target_schp, arg2, 0))
4956 goto efault;
bellard5cd43932003-03-29 16:54:36 +00004957 target_schp->sched_priority = tswap32(schp.sched_priority);
pbrook53a59602006-03-25 19:31:22 +00004958 unlock_user_struct(target_schp, arg2, 1);
bellard5cd43932003-03-29 16:54:36 +00004959 }
4960 }
4961 break;
bellard31e31b82003-02-18 22:55:36 +00004962 case TARGET_NR_sched_setscheduler:
bellard5cd43932003-03-29 16:54:36 +00004963 {
pbrook53a59602006-03-25 19:31:22 +00004964 struct sched_param *target_schp;
bellard5cd43932003-03-29 16:54:36 +00004965 struct sched_param schp;
bellard579a97f2007-11-11 14:26:47 +00004966 if (!lock_user_struct(VERIFY_READ, target_schp, arg3, 1))
4967 goto efault;
bellard5cd43932003-03-29 16:54:36 +00004968 schp.sched_priority = tswap32(target_schp->sched_priority);
pbrook53a59602006-03-25 19:31:22 +00004969 unlock_user_struct(target_schp, arg3, 0);
bellard5cd43932003-03-29 16:54:36 +00004970 ret = get_errno(sched_setscheduler(arg1, arg2, &schp));
4971 }
4972 break;
bellard31e31b82003-02-18 22:55:36 +00004973 case TARGET_NR_sched_getscheduler:
bellard5cd43932003-03-29 16:54:36 +00004974 ret = get_errno(sched_getscheduler(arg1));
4975 break;
bellard31e31b82003-02-18 22:55:36 +00004976 case TARGET_NR_sched_yield:
4977 ret = get_errno(sched_yield());
4978 break;
4979 case TARGET_NR_sched_get_priority_max:
bellard5cd43932003-03-29 16:54:36 +00004980 ret = get_errno(sched_get_priority_max(arg1));
4981 break;
bellard31e31b82003-02-18 22:55:36 +00004982 case TARGET_NR_sched_get_priority_min:
bellard5cd43932003-03-29 16:54:36 +00004983 ret = get_errno(sched_get_priority_min(arg1));
4984 break;
bellard31e31b82003-02-18 22:55:36 +00004985 case TARGET_NR_sched_rr_get_interval:
bellard5cd43932003-03-29 16:54:36 +00004986 {
bellard5cd43932003-03-29 16:54:36 +00004987 struct timespec ts;
4988 ret = get_errno(sched_rr_get_interval(arg1, &ts));
4989 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00004990 host_to_target_timespec(arg2, &ts);
bellard5cd43932003-03-29 16:54:36 +00004991 }
4992 }
4993 break;
bellard31e31b82003-02-18 22:55:36 +00004994 case TARGET_NR_nanosleep:
bellard1b6b0292003-03-22 17:31:38 +00004995 {
bellard1b6b0292003-03-22 17:31:38 +00004996 struct timespec req, rem;
pbrook53a59602006-03-25 19:31:22 +00004997 target_to_host_timespec(&req, arg1);
bellard1b6b0292003-03-22 17:31:38 +00004998 ret = get_errno(nanosleep(&req, &rem));
pbrook53a59602006-03-25 19:31:22 +00004999 if (is_error(ret) && arg2) {
5000 host_to_target_timespec(arg2, &rem);
bellard1b6b0292003-03-22 17:31:38 +00005001 }
5002 }
5003 break;
thse5febef2007-04-01 18:31:35 +00005004#ifdef TARGET_NR_query_module
bellard31e31b82003-02-18 22:55:36 +00005005 case TARGET_NR_query_module:
bellard5cd43932003-03-29 16:54:36 +00005006 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00005007#endif
5008#ifdef TARGET_NR_nfsservctl
bellard31e31b82003-02-18 22:55:36 +00005009 case TARGET_NR_nfsservctl:
bellard5cd43932003-03-29 16:54:36 +00005010 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00005011#endif
bellard31e31b82003-02-18 22:55:36 +00005012 case TARGET_NR_prctl:
thse5574482007-02-11 20:03:13 +00005013 switch (arg1)
5014 {
5015 case PR_GET_PDEATHSIG:
5016 {
5017 int deathsig;
5018 ret = get_errno(prctl(arg1, &deathsig, arg3, arg4, arg5));
bellard2f619692007-11-16 10:46:05 +00005019 if (!is_error(ret) && arg2
5020 && put_user_ual(deathsig, arg2))
5021 goto efault;
thse5574482007-02-11 20:03:13 +00005022 }
5023 break;
5024 default:
5025 ret = get_errno(prctl(arg1, arg2, arg3, arg4, arg5));
5026 break;
5027 }
ths39b9aae2007-02-11 18:36:44 +00005028 break;
bellardd2fd1af2007-11-14 18:08:56 +00005029#ifdef TARGET_NR_arch_prctl
5030 case TARGET_NR_arch_prctl:
5031#if defined(TARGET_I386) && !defined(TARGET_ABI32)
5032 ret = do_arch_prctl(cpu_env, arg1, arg2);
5033 break;
5034#else
5035 goto unimplemented;
5036#endif
5037#endif
bellard67867302003-11-23 17:05:30 +00005038#ifdef TARGET_NR_pread
bellard31e31b82003-02-18 22:55:36 +00005039 case TARGET_NR_pread:
bellard579a97f2007-11-11 14:26:47 +00005040 if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
5041 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005042 ret = get_errno(pread(arg1, p, arg3, arg4));
5043 unlock_user(p, arg2, ret);
bellard206f0fa2003-05-14 19:01:56 +00005044 break;
bellard31e31b82003-02-18 22:55:36 +00005045 case TARGET_NR_pwrite:
bellard579a97f2007-11-11 14:26:47 +00005046 if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
5047 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005048 ret = get_errno(pwrite(arg1, p, arg3, arg4));
5049 unlock_user(p, arg2, 0);
bellard206f0fa2003-05-14 19:01:56 +00005050 break;
bellard67867302003-11-23 17:05:30 +00005051#endif
aurel32f2c7ba12008-03-28 22:32:06 +00005052#ifdef TARGET_NR_pread64
5053 case TARGET_NR_pread64:
5054 if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
5055 goto efault;
5056 ret = get_errno(pread64(arg1, p, arg3, target_offset64(arg4, arg5)));
5057 unlock_user(p, arg2, ret);
5058 break;
5059 case TARGET_NR_pwrite64:
5060 if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
5061 goto efault;
5062 ret = get_errno(pwrite64(arg1, p, arg3, target_offset64(arg4, arg5)));
5063 unlock_user(p, arg2, 0);
5064 break;
5065#endif
bellard31e31b82003-02-18 22:55:36 +00005066 case TARGET_NR_getcwd:
bellard579a97f2007-11-11 14:26:47 +00005067 if (!(p = lock_user(VERIFY_WRITE, arg1, arg2, 0)))
5068 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005069 ret = get_errno(sys_getcwd1(p, arg2));
5070 unlock_user(p, arg1, ret);
bellard31e31b82003-02-18 22:55:36 +00005071 break;
5072 case TARGET_NR_capget:
bellard5cd43932003-03-29 16:54:36 +00005073 goto unimplemented;
bellard31e31b82003-02-18 22:55:36 +00005074 case TARGET_NR_capset:
bellard5cd43932003-03-29 16:54:36 +00005075 goto unimplemented;
bellard31e31b82003-02-18 22:55:36 +00005076 case TARGET_NR_sigaltstack:
ths198a74d2007-09-27 16:44:32 +00005077#if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_MIPS) || \
5078 defined(TARGET_SPARC) || defined(TARGET_PPC) || defined(TARGET_ALPHA)
bellard579a97f2007-11-11 14:26:47 +00005079 ret = do_sigaltstack(arg1, arg2, get_sp_from_cpustate((CPUState *)cpu_env));
thsa04e1342007-09-27 13:57:58 +00005080 break;
5081#else
bellard5cd43932003-03-29 16:54:36 +00005082 goto unimplemented;
thsa04e1342007-09-27 13:57:58 +00005083#endif
bellard31e31b82003-02-18 22:55:36 +00005084 case TARGET_NR_sendfile:
bellard5cd43932003-03-29 16:54:36 +00005085 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00005086#ifdef TARGET_NR_getpmsg
bellard31e31b82003-02-18 22:55:36 +00005087 case TARGET_NR_getpmsg:
bellard5cd43932003-03-29 16:54:36 +00005088 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00005089#endif
5090#ifdef TARGET_NR_putpmsg
bellard31e31b82003-02-18 22:55:36 +00005091 case TARGET_NR_putpmsg:
bellard5cd43932003-03-29 16:54:36 +00005092 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00005093#endif
bellard048f6b42005-11-26 18:47:20 +00005094#ifdef TARGET_NR_vfork
bellard31e31b82003-02-18 22:55:36 +00005095 case TARGET_NR_vfork:
pbrookd865bab2008-06-07 22:12:17 +00005096 ret = get_errno(do_fork(cpu_env, CLONE_VFORK | CLONE_VM | SIGCHLD,
5097 0, 0, 0, 0));
bellard31e31b82003-02-18 22:55:36 +00005098 break;
bellard048f6b42005-11-26 18:47:20 +00005099#endif
bellardebc05482003-09-30 21:08:41 +00005100#ifdef TARGET_NR_ugetrlimit
bellard31e31b82003-02-18 22:55:36 +00005101 case TARGET_NR_ugetrlimit:
bellard728584b2003-04-29 20:43:36 +00005102 {
5103 struct rlimit rlim;
5104 ret = get_errno(getrlimit(arg1, &rlim));
5105 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00005106 struct target_rlimit *target_rlim;
bellard579a97f2007-11-11 14:26:47 +00005107 if (!lock_user_struct(VERIFY_WRITE, target_rlim, arg2, 0))
5108 goto efault;
bellard728584b2003-04-29 20:43:36 +00005109 target_rlim->rlim_cur = tswapl(rlim.rlim_cur);
5110 target_rlim->rlim_max = tswapl(rlim.rlim_max);
pbrook53a59602006-03-25 19:31:22 +00005111 unlock_user_struct(target_rlim, arg2, 1);
bellard728584b2003-04-29 20:43:36 +00005112 }
5113 break;
5114 }
bellardebc05482003-09-30 21:08:41 +00005115#endif
bellarda315a142005-01-30 22:59:18 +00005116#ifdef TARGET_NR_truncate64
bellard31e31b82003-02-18 22:55:36 +00005117 case TARGET_NR_truncate64:
bellard579a97f2007-11-11 14:26:47 +00005118 if (!(p = lock_user_string(arg1)))
5119 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005120 ret = target_truncate64(cpu_env, p, arg2, arg3, arg4);
5121 unlock_user(p, arg1, 0);
bellard667f38b2005-07-23 14:46:27 +00005122 break;
bellarda315a142005-01-30 22:59:18 +00005123#endif
5124#ifdef TARGET_NR_ftruncate64
bellard31e31b82003-02-18 22:55:36 +00005125 case TARGET_NR_ftruncate64:
pbrookce4defa2006-02-09 16:49:55 +00005126 ret = target_ftruncate64(cpu_env, arg1, arg2, arg3, arg4);
bellard667f38b2005-07-23 14:46:27 +00005127 break;
bellarda315a142005-01-30 22:59:18 +00005128#endif
5129#ifdef TARGET_NR_stat64
bellard31e31b82003-02-18 22:55:36 +00005130 case TARGET_NR_stat64:
bellard579a97f2007-11-11 14:26:47 +00005131 if (!(p = lock_user_string(arg1)))
5132 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005133 ret = get_errno(stat(path(p), &st));
5134 unlock_user(p, arg1, 0);
bellard60cd49d2003-03-16 22:53:56 +00005135 goto do_stat64;
bellarda315a142005-01-30 22:59:18 +00005136#endif
5137#ifdef TARGET_NR_lstat64
bellard31e31b82003-02-18 22:55:36 +00005138 case TARGET_NR_lstat64:
bellard579a97f2007-11-11 14:26:47 +00005139 if (!(p = lock_user_string(arg1)))
5140 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005141 ret = get_errno(lstat(path(p), &st));
5142 unlock_user(p, arg1, 0);
bellard60cd49d2003-03-16 22:53:56 +00005143 goto do_stat64;
bellarda315a142005-01-30 22:59:18 +00005144#endif
5145#ifdef TARGET_NR_fstat64
bellard31e31b82003-02-18 22:55:36 +00005146 case TARGET_NR_fstat64:
bellard60cd49d2003-03-16 22:53:56 +00005147 {
5148 ret = get_errno(fstat(arg1, &st));
5149 do_stat64:
5150 if (!is_error(ret)) {
pbrookce4defa2006-02-09 16:49:55 +00005151#ifdef TARGET_ARM
5152 if (((CPUARMState *)cpu_env)->eabi) {
pbrook53a59602006-03-25 19:31:22 +00005153 struct target_eabi_stat64 *target_st;
bellard579a97f2007-11-11 14:26:47 +00005154
5155 if (!lock_user_struct(VERIFY_WRITE, target_st, arg2, 0))
5156 goto efault;
pbrookce4defa2006-02-09 16:49:55 +00005157 memset(target_st, 0, sizeof(struct target_eabi_stat64));
bellard579a97f2007-11-11 14:26:47 +00005158 __put_user(st.st_dev, &target_st->st_dev);
5159 __put_user(st.st_ino, &target_st->st_ino);
bellardec86b0f2003-04-11 00:15:04 +00005160#ifdef TARGET_STAT64_HAS_BROKEN_ST_INO
bellard579a97f2007-11-11 14:26:47 +00005161 __put_user(st.st_ino, &target_st->__st_ino);
bellardec86b0f2003-04-11 00:15:04 +00005162#endif
bellard579a97f2007-11-11 14:26:47 +00005163 __put_user(st.st_mode, &target_st->st_mode);
5164 __put_user(st.st_nlink, &target_st->st_nlink);
5165 __put_user(st.st_uid, &target_st->st_uid);
5166 __put_user(st.st_gid, &target_st->st_gid);
5167 __put_user(st.st_rdev, &target_st->st_rdev);
5168 __put_user(st.st_size, &target_st->st_size);
5169 __put_user(st.st_blksize, &target_st->st_blksize);
5170 __put_user(st.st_blocks, &target_st->st_blocks);
5171 __put_user(st.st_atime, &target_st->target_st_atime);
5172 __put_user(st.st_mtime, &target_st->target_st_mtime);
5173 __put_user(st.st_ctime, &target_st->target_st_ctime);
5174 unlock_user_struct(target_st, arg2, 1);
pbrookce4defa2006-02-09 16:49:55 +00005175 } else
5176#endif
5177 {
pbrook53a59602006-03-25 19:31:22 +00005178 struct target_stat64 *target_st;
bellard579a97f2007-11-11 14:26:47 +00005179
5180 if (!lock_user_struct(VERIFY_WRITE, target_st, arg2, 0))
5181 goto efault;
pbrookce4defa2006-02-09 16:49:55 +00005182 memset(target_st, 0, sizeof(struct target_stat64));
bellard579a97f2007-11-11 14:26:47 +00005183 __put_user(st.st_dev, &target_st->st_dev);
5184 __put_user(st.st_ino, &target_st->st_ino);
pbrookce4defa2006-02-09 16:49:55 +00005185#ifdef TARGET_STAT64_HAS_BROKEN_ST_INO
bellard579a97f2007-11-11 14:26:47 +00005186 __put_user(st.st_ino, &target_st->__st_ino);
pbrookce4defa2006-02-09 16:49:55 +00005187#endif
bellard579a97f2007-11-11 14:26:47 +00005188 __put_user(st.st_mode, &target_st->st_mode);
5189 __put_user(st.st_nlink, &target_st->st_nlink);
5190 __put_user(st.st_uid, &target_st->st_uid);
5191 __put_user(st.st_gid, &target_st->st_gid);
5192 __put_user(st.st_rdev, &target_st->st_rdev);
pbrookce4defa2006-02-09 16:49:55 +00005193 /* XXX: better use of kernel struct */
bellard579a97f2007-11-11 14:26:47 +00005194 __put_user(st.st_size, &target_st->st_size);
5195 __put_user(st.st_blksize, &target_st->st_blksize);
5196 __put_user(st.st_blocks, &target_st->st_blocks);
5197 __put_user(st.st_atime, &target_st->target_st_atime);
5198 __put_user(st.st_mtime, &target_st->target_st_mtime);
5199 __put_user(st.st_ctime, &target_st->target_st_ctime);
5200 unlock_user_struct(target_st, arg2, 1);
pbrookce4defa2006-02-09 16:49:55 +00005201 }
bellard60cd49d2003-03-16 22:53:56 +00005202 }
5203 }
5204 break;
bellarda315a142005-01-30 22:59:18 +00005205#endif
bellard67867302003-11-23 17:05:30 +00005206#ifdef USE_UID16
5207 case TARGET_NR_lchown:
bellard579a97f2007-11-11 14:26:47 +00005208 if (!(p = lock_user_string(arg1)))
5209 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005210 ret = get_errno(lchown(p, low2highuid(arg2), low2highgid(arg3)));
5211 unlock_user(p, arg1, 0);
bellard67867302003-11-23 17:05:30 +00005212 break;
5213 case TARGET_NR_getuid:
5214 ret = get_errno(high2lowuid(getuid()));
5215 break;
5216 case TARGET_NR_getgid:
5217 ret = get_errno(high2lowgid(getgid()));
5218 break;
5219 case TARGET_NR_geteuid:
5220 ret = get_errno(high2lowuid(geteuid()));
5221 break;
5222 case TARGET_NR_getegid:
5223 ret = get_errno(high2lowgid(getegid()));
5224 break;
5225 case TARGET_NR_setreuid:
5226 ret = get_errno(setreuid(low2highuid(arg1), low2highuid(arg2)));
5227 break;
5228 case TARGET_NR_setregid:
5229 ret = get_errno(setregid(low2highgid(arg1), low2highgid(arg2)));
5230 break;
5231 case TARGET_NR_getgroups:
5232 {
5233 int gidsetsize = arg1;
pbrook53a59602006-03-25 19:31:22 +00005234 uint16_t *target_grouplist;
bellard67867302003-11-23 17:05:30 +00005235 gid_t *grouplist;
5236 int i;
5237
5238 grouplist = alloca(gidsetsize * sizeof(gid_t));
5239 ret = get_errno(getgroups(gidsetsize, grouplist));
5240 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00005241 target_grouplist = lock_user(VERIFY_WRITE, arg2, gidsetsize * 2, 0);
5242 if (!target_grouplist)
5243 goto efault;
bellard67867302003-11-23 17:05:30 +00005244 for(i = 0;i < gidsetsize; i++)
5245 target_grouplist[i] = tswap16(grouplist[i]);
pbrook53a59602006-03-25 19:31:22 +00005246 unlock_user(target_grouplist, arg2, gidsetsize * 2);
bellard67867302003-11-23 17:05:30 +00005247 }
5248 }
5249 break;
5250 case TARGET_NR_setgroups:
5251 {
5252 int gidsetsize = arg1;
pbrook53a59602006-03-25 19:31:22 +00005253 uint16_t *target_grouplist;
bellard67867302003-11-23 17:05:30 +00005254 gid_t *grouplist;
5255 int i;
5256
5257 grouplist = alloca(gidsetsize * sizeof(gid_t));
bellard579a97f2007-11-11 14:26:47 +00005258 target_grouplist = lock_user(VERIFY_READ, arg2, gidsetsize * 2, 1);
5259 if (!target_grouplist) {
5260 ret = -TARGET_EFAULT;
5261 goto fail;
5262 }
bellard67867302003-11-23 17:05:30 +00005263 for(i = 0;i < gidsetsize; i++)
5264 grouplist[i] = tswap16(target_grouplist[i]);
pbrook53a59602006-03-25 19:31:22 +00005265 unlock_user(target_grouplist, arg2, 0);
bellard67867302003-11-23 17:05:30 +00005266 ret = get_errno(setgroups(gidsetsize, grouplist));
5267 }
5268 break;
5269 case TARGET_NR_fchown:
5270 ret = get_errno(fchown(arg1, low2highuid(arg2), low2highgid(arg3)));
5271 break;
thsccfa72b2007-09-24 09:23:34 +00005272#if defined(TARGET_NR_fchownat) && defined(__NR_fchownat)
5273 case TARGET_NR_fchownat:
bellard579a97f2007-11-11 14:26:47 +00005274 if (!(p = lock_user_string(arg2)))
5275 goto efault;
5276 ret = get_errno(sys_fchownat(arg1, p, low2highuid(arg3), low2highgid(arg4), arg5));
5277 unlock_user(p, arg2, 0);
thsccfa72b2007-09-24 09:23:34 +00005278 break;
5279#endif
bellard67867302003-11-23 17:05:30 +00005280#ifdef TARGET_NR_setresuid
5281 case TARGET_NR_setresuid:
ths5fafdf22007-09-16 21:08:06 +00005282 ret = get_errno(setresuid(low2highuid(arg1),
5283 low2highuid(arg2),
bellard67867302003-11-23 17:05:30 +00005284 low2highuid(arg3)));
5285 break;
5286#endif
5287#ifdef TARGET_NR_getresuid
5288 case TARGET_NR_getresuid:
5289 {
pbrook53a59602006-03-25 19:31:22 +00005290 uid_t ruid, euid, suid;
bellard67867302003-11-23 17:05:30 +00005291 ret = get_errno(getresuid(&ruid, &euid, &suid));
5292 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +00005293 if (put_user_u16(high2lowuid(ruid), arg1)
5294 || put_user_u16(high2lowuid(euid), arg2)
5295 || put_user_u16(high2lowuid(suid), arg3))
5296 goto efault;
bellard67867302003-11-23 17:05:30 +00005297 }
5298 }
5299 break;
5300#endif
5301#ifdef TARGET_NR_getresgid
5302 case TARGET_NR_setresgid:
ths5fafdf22007-09-16 21:08:06 +00005303 ret = get_errno(setresgid(low2highgid(arg1),
5304 low2highgid(arg2),
bellard67867302003-11-23 17:05:30 +00005305 low2highgid(arg3)));
5306 break;
5307#endif
5308#ifdef TARGET_NR_getresgid
5309 case TARGET_NR_getresgid:
5310 {
pbrook53a59602006-03-25 19:31:22 +00005311 gid_t rgid, egid, sgid;
bellard67867302003-11-23 17:05:30 +00005312 ret = get_errno(getresgid(&rgid, &egid, &sgid));
5313 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +00005314 if (put_user_u16(high2lowgid(rgid), arg1)
5315 || put_user_u16(high2lowgid(egid), arg2)
5316 || put_user_u16(high2lowgid(sgid), arg3))
5317 goto efault;
bellard67867302003-11-23 17:05:30 +00005318 }
5319 }
5320 break;
5321#endif
5322 case TARGET_NR_chown:
bellard579a97f2007-11-11 14:26:47 +00005323 if (!(p = lock_user_string(arg1)))
5324 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005325 ret = get_errno(chown(p, low2highuid(arg2), low2highgid(arg3)));
5326 unlock_user(p, arg1, 0);
bellard67867302003-11-23 17:05:30 +00005327 break;
5328 case TARGET_NR_setuid:
5329 ret = get_errno(setuid(low2highuid(arg1)));
5330 break;
5331 case TARGET_NR_setgid:
5332 ret = get_errno(setgid(low2highgid(arg1)));
5333 break;
5334 case TARGET_NR_setfsuid:
5335 ret = get_errno(setfsuid(arg1));
5336 break;
5337 case TARGET_NR_setfsgid:
5338 ret = get_errno(setfsgid(arg1));
5339 break;
5340#endif /* USE_UID16 */
5341
bellarda315a142005-01-30 22:59:18 +00005342#ifdef TARGET_NR_lchown32
bellard31e31b82003-02-18 22:55:36 +00005343 case TARGET_NR_lchown32:
bellard579a97f2007-11-11 14:26:47 +00005344 if (!(p = lock_user_string(arg1)))
5345 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005346 ret = get_errno(lchown(p, arg2, arg3));
5347 unlock_user(p, arg1, 0);
bellardb03c60f2003-03-23 17:19:56 +00005348 break;
bellarda315a142005-01-30 22:59:18 +00005349#endif
5350#ifdef TARGET_NR_getuid32
bellard31e31b82003-02-18 22:55:36 +00005351 case TARGET_NR_getuid32:
bellardb03c60f2003-03-23 17:19:56 +00005352 ret = get_errno(getuid());
5353 break;
bellarda315a142005-01-30 22:59:18 +00005354#endif
5355#ifdef TARGET_NR_getgid32
bellard31e31b82003-02-18 22:55:36 +00005356 case TARGET_NR_getgid32:
bellardb03c60f2003-03-23 17:19:56 +00005357 ret = get_errno(getgid());
5358 break;
bellarda315a142005-01-30 22:59:18 +00005359#endif
5360#ifdef TARGET_NR_geteuid32
bellard31e31b82003-02-18 22:55:36 +00005361 case TARGET_NR_geteuid32:
bellardb03c60f2003-03-23 17:19:56 +00005362 ret = get_errno(geteuid());
5363 break;
bellarda315a142005-01-30 22:59:18 +00005364#endif
5365#ifdef TARGET_NR_getegid32
bellard31e31b82003-02-18 22:55:36 +00005366 case TARGET_NR_getegid32:
bellardb03c60f2003-03-23 17:19:56 +00005367 ret = get_errno(getegid());
5368 break;
bellarda315a142005-01-30 22:59:18 +00005369#endif
5370#ifdef TARGET_NR_setreuid32
bellard31e31b82003-02-18 22:55:36 +00005371 case TARGET_NR_setreuid32:
bellardb03c60f2003-03-23 17:19:56 +00005372 ret = get_errno(setreuid(arg1, arg2));
5373 break;
bellarda315a142005-01-30 22:59:18 +00005374#endif
5375#ifdef TARGET_NR_setregid32
bellard31e31b82003-02-18 22:55:36 +00005376 case TARGET_NR_setregid32:
bellardb03c60f2003-03-23 17:19:56 +00005377 ret = get_errno(setregid(arg1, arg2));
5378 break;
bellarda315a142005-01-30 22:59:18 +00005379#endif
5380#ifdef TARGET_NR_getgroups32
bellard31e31b82003-02-18 22:55:36 +00005381 case TARGET_NR_getgroups32:
bellard99c475a2005-01-31 20:45:13 +00005382 {
5383 int gidsetsize = arg1;
pbrook53a59602006-03-25 19:31:22 +00005384 uint32_t *target_grouplist;
bellard99c475a2005-01-31 20:45:13 +00005385 gid_t *grouplist;
5386 int i;
5387
5388 grouplist = alloca(gidsetsize * sizeof(gid_t));
5389 ret = get_errno(getgroups(gidsetsize, grouplist));
5390 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00005391 target_grouplist = lock_user(VERIFY_WRITE, arg2, gidsetsize * 4, 0);
5392 if (!target_grouplist) {
5393 ret = -TARGET_EFAULT;
5394 goto fail;
5395 }
bellard99c475a2005-01-31 20:45:13 +00005396 for(i = 0;i < gidsetsize; i++)
pbrook53a59602006-03-25 19:31:22 +00005397 target_grouplist[i] = tswap32(grouplist[i]);
5398 unlock_user(target_grouplist, arg2, gidsetsize * 4);
bellard99c475a2005-01-31 20:45:13 +00005399 }
5400 }
5401 break;
bellarda315a142005-01-30 22:59:18 +00005402#endif
5403#ifdef TARGET_NR_setgroups32
bellard31e31b82003-02-18 22:55:36 +00005404 case TARGET_NR_setgroups32:
bellard99c475a2005-01-31 20:45:13 +00005405 {
5406 int gidsetsize = arg1;
pbrook53a59602006-03-25 19:31:22 +00005407 uint32_t *target_grouplist;
bellard99c475a2005-01-31 20:45:13 +00005408 gid_t *grouplist;
5409 int i;
ths3b46e622007-09-17 08:09:54 +00005410
bellard99c475a2005-01-31 20:45:13 +00005411 grouplist = alloca(gidsetsize * sizeof(gid_t));
bellard579a97f2007-11-11 14:26:47 +00005412 target_grouplist = lock_user(VERIFY_READ, arg2, gidsetsize * 4, 1);
5413 if (!target_grouplist) {
5414 ret = -TARGET_EFAULT;
5415 goto fail;
5416 }
bellard99c475a2005-01-31 20:45:13 +00005417 for(i = 0;i < gidsetsize; i++)
pbrook53a59602006-03-25 19:31:22 +00005418 grouplist[i] = tswap32(target_grouplist[i]);
5419 unlock_user(target_grouplist, arg2, 0);
bellard99c475a2005-01-31 20:45:13 +00005420 ret = get_errno(setgroups(gidsetsize, grouplist));
5421 }
5422 break;
bellarda315a142005-01-30 22:59:18 +00005423#endif
5424#ifdef TARGET_NR_fchown32
bellard31e31b82003-02-18 22:55:36 +00005425 case TARGET_NR_fchown32:
bellardb03c60f2003-03-23 17:19:56 +00005426 ret = get_errno(fchown(arg1, arg2, arg3));
5427 break;
bellarda315a142005-01-30 22:59:18 +00005428#endif
5429#ifdef TARGET_NR_setresuid32
bellard31e31b82003-02-18 22:55:36 +00005430 case TARGET_NR_setresuid32:
bellardb03c60f2003-03-23 17:19:56 +00005431 ret = get_errno(setresuid(arg1, arg2, arg3));
5432 break;
bellarda315a142005-01-30 22:59:18 +00005433#endif
5434#ifdef TARGET_NR_getresuid32
bellard31e31b82003-02-18 22:55:36 +00005435 case TARGET_NR_getresuid32:
bellardb03c60f2003-03-23 17:19:56 +00005436 {
pbrook53a59602006-03-25 19:31:22 +00005437 uid_t ruid, euid, suid;
bellardb03c60f2003-03-23 17:19:56 +00005438 ret = get_errno(getresuid(&ruid, &euid, &suid));
5439 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +00005440 if (put_user_u32(ruid, arg1)
5441 || put_user_u32(euid, arg2)
5442 || put_user_u32(suid, arg3))
5443 goto efault;
bellardb03c60f2003-03-23 17:19:56 +00005444 }
5445 }
5446 break;
bellarda315a142005-01-30 22:59:18 +00005447#endif
5448#ifdef TARGET_NR_setresgid32
bellard31e31b82003-02-18 22:55:36 +00005449 case TARGET_NR_setresgid32:
bellardb03c60f2003-03-23 17:19:56 +00005450 ret = get_errno(setresgid(arg1, arg2, arg3));
5451 break;
bellarda315a142005-01-30 22:59:18 +00005452#endif
5453#ifdef TARGET_NR_getresgid32
bellard31e31b82003-02-18 22:55:36 +00005454 case TARGET_NR_getresgid32:
bellardb03c60f2003-03-23 17:19:56 +00005455 {
pbrook53a59602006-03-25 19:31:22 +00005456 gid_t rgid, egid, sgid;
bellardb03c60f2003-03-23 17:19:56 +00005457 ret = get_errno(getresgid(&rgid, &egid, &sgid));
5458 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +00005459 if (put_user_u32(rgid, arg1)
5460 || put_user_u32(egid, arg2)
5461 || put_user_u32(sgid, arg3))
5462 goto efault;
bellardb03c60f2003-03-23 17:19:56 +00005463 }
5464 }
5465 break;
bellarda315a142005-01-30 22:59:18 +00005466#endif
5467#ifdef TARGET_NR_chown32
bellard31e31b82003-02-18 22:55:36 +00005468 case TARGET_NR_chown32:
bellard579a97f2007-11-11 14:26:47 +00005469 if (!(p = lock_user_string(arg1)))
5470 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005471 ret = get_errno(chown(p, arg2, arg3));
5472 unlock_user(p, arg1, 0);
bellardb03c60f2003-03-23 17:19:56 +00005473 break;
bellarda315a142005-01-30 22:59:18 +00005474#endif
5475#ifdef TARGET_NR_setuid32
bellard31e31b82003-02-18 22:55:36 +00005476 case TARGET_NR_setuid32:
bellardb03c60f2003-03-23 17:19:56 +00005477 ret = get_errno(setuid(arg1));
5478 break;
bellarda315a142005-01-30 22:59:18 +00005479#endif
5480#ifdef TARGET_NR_setgid32
bellard31e31b82003-02-18 22:55:36 +00005481 case TARGET_NR_setgid32:
bellardb03c60f2003-03-23 17:19:56 +00005482 ret = get_errno(setgid(arg1));
5483 break;
bellarda315a142005-01-30 22:59:18 +00005484#endif
5485#ifdef TARGET_NR_setfsuid32
bellard31e31b82003-02-18 22:55:36 +00005486 case TARGET_NR_setfsuid32:
bellardb03c60f2003-03-23 17:19:56 +00005487 ret = get_errno(setfsuid(arg1));
5488 break;
bellarda315a142005-01-30 22:59:18 +00005489#endif
5490#ifdef TARGET_NR_setfsgid32
bellard31e31b82003-02-18 22:55:36 +00005491 case TARGET_NR_setfsgid32:
bellardb03c60f2003-03-23 17:19:56 +00005492 ret = get_errno(setfsgid(arg1));
5493 break;
bellarda315a142005-01-30 22:59:18 +00005494#endif
bellard67867302003-11-23 17:05:30 +00005495
bellard31e31b82003-02-18 22:55:36 +00005496 case TARGET_NR_pivot_root:
bellardb03c60f2003-03-23 17:19:56 +00005497 goto unimplemented;
bellardffa65c32004-01-04 23:57:22 +00005498#ifdef TARGET_NR_mincore
bellard31e31b82003-02-18 22:55:36 +00005499 case TARGET_NR_mincore:
bellardb03c60f2003-03-23 17:19:56 +00005500 goto unimplemented;
bellardffa65c32004-01-04 23:57:22 +00005501#endif
5502#ifdef TARGET_NR_madvise
bellard31e31b82003-02-18 22:55:36 +00005503 case TARGET_NR_madvise:
pbrook24836682006-04-16 14:14:53 +00005504 /* A straight passthrough may not be safe because qemu sometimes
5505 turns private flie-backed mappings into anonymous mappings.
5506 This will break MADV_DONTNEED.
5507 This is a hint, so ignoring and returning success is ok. */
5508 ret = get_errno(0);
5509 break;
bellardffa65c32004-01-04 23:57:22 +00005510#endif
blueswir1992f48a2007-10-14 16:27:31 +00005511#if TARGET_ABI_BITS == 32
bellard31e31b82003-02-18 22:55:36 +00005512 case TARGET_NR_fcntl64:
bellard77e46722003-04-29 20:39:06 +00005513 {
thsb1e341e2007-03-20 21:50:52 +00005514 int cmd;
bellard77e46722003-04-29 20:39:06 +00005515 struct flock64 fl;
pbrook53a59602006-03-25 19:31:22 +00005516 struct target_flock64 *target_fl;
pbrookce4defa2006-02-09 16:49:55 +00005517#ifdef TARGET_ARM
pbrook53a59602006-03-25 19:31:22 +00005518 struct target_eabi_flock64 *target_efl;
pbrookce4defa2006-02-09 16:49:55 +00005519#endif
bellard77e46722003-04-29 20:39:06 +00005520
thsb1e341e2007-03-20 21:50:52 +00005521 switch(arg2){
5522 case TARGET_F_GETLK64:
5523 cmd = F_GETLK64;
thsa7222582007-03-22 15:08:55 +00005524 break;
thsb1e341e2007-03-20 21:50:52 +00005525 case TARGET_F_SETLK64:
5526 cmd = F_SETLK64;
thsa7222582007-03-22 15:08:55 +00005527 break;
thsb1e341e2007-03-20 21:50:52 +00005528 case TARGET_F_SETLKW64:
5529 cmd = F_SETLK64;
thsa7222582007-03-22 15:08:55 +00005530 break;
thsb1e341e2007-03-20 21:50:52 +00005531 default:
5532 cmd = arg2;
thsa7222582007-03-22 15:08:55 +00005533 break;
thsb1e341e2007-03-20 21:50:52 +00005534 }
5535
bellard60cd49d2003-03-16 22:53:56 +00005536 switch(arg2) {
thsb1e341e2007-03-20 21:50:52 +00005537 case TARGET_F_GETLK64:
ths58134272007-03-31 18:59:32 +00005538#ifdef TARGET_ARM
5539 if (((CPUARMState *)cpu_env)->eabi) {
bellard9ee1fa22007-11-11 15:11:19 +00005540 if (!lock_user_struct(VERIFY_READ, target_efl, arg3, 1))
5541 goto efault;
ths58134272007-03-31 18:59:32 +00005542 fl.l_type = tswap16(target_efl->l_type);
5543 fl.l_whence = tswap16(target_efl->l_whence);
5544 fl.l_start = tswap64(target_efl->l_start);
5545 fl.l_len = tswap64(target_efl->l_len);
5546 fl.l_pid = tswapl(target_efl->l_pid);
5547 unlock_user_struct(target_efl, arg3, 0);
5548 } else
5549#endif
5550 {
bellard9ee1fa22007-11-11 15:11:19 +00005551 if (!lock_user_struct(VERIFY_READ, target_fl, arg3, 1))
5552 goto efault;
ths58134272007-03-31 18:59:32 +00005553 fl.l_type = tswap16(target_fl->l_type);
5554 fl.l_whence = tswap16(target_fl->l_whence);
5555 fl.l_start = tswap64(target_fl->l_start);
5556 fl.l_len = tswap64(target_fl->l_len);
5557 fl.l_pid = tswapl(target_fl->l_pid);
5558 unlock_user_struct(target_fl, arg3, 0);
5559 }
thsb1e341e2007-03-20 21:50:52 +00005560 ret = get_errno(fcntl(arg1, cmd, &fl));
bellard77e46722003-04-29 20:39:06 +00005561 if (ret == 0) {
pbrookce4defa2006-02-09 16:49:55 +00005562#ifdef TARGET_ARM
5563 if (((CPUARMState *)cpu_env)->eabi) {
bellard9ee1fa22007-11-11 15:11:19 +00005564 if (!lock_user_struct(VERIFY_WRITE, target_efl, arg3, 0))
5565 goto efault;
pbrookce4defa2006-02-09 16:49:55 +00005566 target_efl->l_type = tswap16(fl.l_type);
5567 target_efl->l_whence = tswap16(fl.l_whence);
5568 target_efl->l_start = tswap64(fl.l_start);
5569 target_efl->l_len = tswap64(fl.l_len);
5570 target_efl->l_pid = tswapl(fl.l_pid);
pbrook53a59602006-03-25 19:31:22 +00005571 unlock_user_struct(target_efl, arg3, 1);
pbrookce4defa2006-02-09 16:49:55 +00005572 } else
5573#endif
5574 {
bellard9ee1fa22007-11-11 15:11:19 +00005575 if (!lock_user_struct(VERIFY_WRITE, target_fl, arg3, 0))
5576 goto efault;
pbrookce4defa2006-02-09 16:49:55 +00005577 target_fl->l_type = tswap16(fl.l_type);
5578 target_fl->l_whence = tswap16(fl.l_whence);
5579 target_fl->l_start = tswap64(fl.l_start);
5580 target_fl->l_len = tswap64(fl.l_len);
5581 target_fl->l_pid = tswapl(fl.l_pid);
pbrook53a59602006-03-25 19:31:22 +00005582 unlock_user_struct(target_fl, arg3, 1);
pbrookce4defa2006-02-09 16:49:55 +00005583 }
bellard77e46722003-04-29 20:39:06 +00005584 }
5585 break;
5586
thsb1e341e2007-03-20 21:50:52 +00005587 case TARGET_F_SETLK64:
5588 case TARGET_F_SETLKW64:
pbrookce4defa2006-02-09 16:49:55 +00005589#ifdef TARGET_ARM
5590 if (((CPUARMState *)cpu_env)->eabi) {
bellard9ee1fa22007-11-11 15:11:19 +00005591 if (!lock_user_struct(VERIFY_READ, target_efl, arg3, 1))
5592 goto efault;
pbrookce4defa2006-02-09 16:49:55 +00005593 fl.l_type = tswap16(target_efl->l_type);
5594 fl.l_whence = tswap16(target_efl->l_whence);
5595 fl.l_start = tswap64(target_efl->l_start);
5596 fl.l_len = tswap64(target_efl->l_len);
5597 fl.l_pid = tswapl(target_efl->l_pid);
pbrook53a59602006-03-25 19:31:22 +00005598 unlock_user_struct(target_efl, arg3, 0);
pbrookce4defa2006-02-09 16:49:55 +00005599 } else
5600#endif
5601 {
bellard9ee1fa22007-11-11 15:11:19 +00005602 if (!lock_user_struct(VERIFY_READ, target_fl, arg3, 1))
5603 goto efault;
pbrookce4defa2006-02-09 16:49:55 +00005604 fl.l_type = tswap16(target_fl->l_type);
5605 fl.l_whence = tswap16(target_fl->l_whence);
5606 fl.l_start = tswap64(target_fl->l_start);
5607 fl.l_len = tswap64(target_fl->l_len);
5608 fl.l_pid = tswapl(target_fl->l_pid);
pbrook53a59602006-03-25 19:31:22 +00005609 unlock_user_struct(target_fl, arg3, 0);
pbrookce4defa2006-02-09 16:49:55 +00005610 }
thsb1e341e2007-03-20 21:50:52 +00005611 ret = get_errno(fcntl(arg1, cmd, &fl));
bellard77e46722003-04-29 20:39:06 +00005612 break;
bellard60cd49d2003-03-16 22:53:56 +00005613 default:
bellard9ee1fa22007-11-11 15:11:19 +00005614 ret = do_fcntl(arg1, cmd, arg3);
bellard60cd49d2003-03-16 22:53:56 +00005615 break;
5616 }
bellard77e46722003-04-29 20:39:06 +00005617 break;
5618 }
bellard60cd49d2003-03-16 22:53:56 +00005619#endif
ths7d600c82006-12-08 01:32:58 +00005620#ifdef TARGET_NR_cacheflush
5621 case TARGET_NR_cacheflush:
5622 /* self-modifying code is handled automatically, so nothing needed */
5623 ret = 0;
5624 break;
5625#endif
bellardebc05482003-09-30 21:08:41 +00005626#ifdef TARGET_NR_security
bellard31e31b82003-02-18 22:55:36 +00005627 case TARGET_NR_security:
5628 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00005629#endif
bellardc573ff62004-01-04 15:51:36 +00005630#ifdef TARGET_NR_getpagesize
5631 case TARGET_NR_getpagesize:
5632 ret = TARGET_PAGE_SIZE;
5633 break;
5634#endif
bellard31e31b82003-02-18 22:55:36 +00005635 case TARGET_NR_gettid:
5636 ret = get_errno(gettid());
5637 break;
thse5febef2007-04-01 18:31:35 +00005638#ifdef TARGET_NR_readahead
bellard31e31b82003-02-18 22:55:36 +00005639 case TARGET_NR_readahead:
bellard5cd43932003-03-29 16:54:36 +00005640 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00005641#endif
bellardebc05482003-09-30 21:08:41 +00005642#ifdef TARGET_NR_setxattr
bellard31e31b82003-02-18 22:55:36 +00005643 case TARGET_NR_setxattr:
5644 case TARGET_NR_lsetxattr:
5645 case TARGET_NR_fsetxattr:
5646 case TARGET_NR_getxattr:
5647 case TARGET_NR_lgetxattr:
5648 case TARGET_NR_fgetxattr:
5649 case TARGET_NR_listxattr:
5650 case TARGET_NR_llistxattr:
5651 case TARGET_NR_flistxattr:
5652 case TARGET_NR_removexattr:
5653 case TARGET_NR_lremovexattr:
5654 case TARGET_NR_fremovexattr:
bellard5cd43932003-03-29 16:54:36 +00005655 goto unimplemented_nowarn;
bellardebc05482003-09-30 21:08:41 +00005656#endif
5657#ifdef TARGET_NR_set_thread_area
bellard5cd43932003-03-29 16:54:36 +00005658 case TARGET_NR_set_thread_area:
bellard8d18e892007-11-14 15:18:40 +00005659#if defined(TARGET_MIPS)
ths6f5b89a2007-03-02 20:48:00 +00005660 ((CPUMIPSState *) cpu_env)->tls_value = arg1;
5661 ret = 0;
5662 break;
bellard8d18e892007-11-14 15:18:40 +00005663#elif defined(TARGET_I386) && defined(TARGET_ABI32)
5664 ret = do_set_thread_area(cpu_env, arg1);
5665 break;
ths6f5b89a2007-03-02 20:48:00 +00005666#else
5667 goto unimplemented_nowarn;
5668#endif
5669#endif
5670#ifdef TARGET_NR_get_thread_area
bellard5cd43932003-03-29 16:54:36 +00005671 case TARGET_NR_get_thread_area:
bellard8d18e892007-11-14 15:18:40 +00005672#if defined(TARGET_I386) && defined(TARGET_ABI32)
5673 ret = do_get_thread_area(cpu_env, arg1);
5674#else
bellard5cd43932003-03-29 16:54:36 +00005675 goto unimplemented_nowarn;
bellardebc05482003-09-30 21:08:41 +00005676#endif
bellard8d18e892007-11-14 15:18:40 +00005677#endif
bellard48dc41e2006-06-21 18:15:50 +00005678#ifdef TARGET_NR_getdomainname
5679 case TARGET_NR_getdomainname:
5680 goto unimplemented_nowarn;
5681#endif
ths6f5b89a2007-03-02 20:48:00 +00005682
thsb5906f92007-03-19 13:32:45 +00005683#ifdef TARGET_NR_clock_gettime
5684 case TARGET_NR_clock_gettime:
5685 {
5686 struct timespec ts;
5687 ret = get_errno(clock_gettime(arg1, &ts));
5688 if (!is_error(ret)) {
5689 host_to_target_timespec(arg2, &ts);
5690 }
5691 break;
5692 }
5693#endif
5694#ifdef TARGET_NR_clock_getres
5695 case TARGET_NR_clock_getres:
5696 {
5697 struct timespec ts;
5698 ret = get_errno(clock_getres(arg1, &ts));
5699 if (!is_error(ret)) {
5700 host_to_target_timespec(arg2, &ts);
5701 }
5702 break;
5703 }
5704#endif
pbrook63d76512008-05-29 13:43:29 +00005705#ifdef TARGET_NR_clock_nanosleep
5706 case TARGET_NR_clock_nanosleep:
5707 {
5708 struct timespec ts;
5709 target_to_host_timespec(&ts, arg3);
5710 ret = get_errno(clock_nanosleep(arg1, arg2, &ts, arg4 ? &ts : NULL));
5711 if (arg4)
5712 host_to_target_timespec(arg4, &ts);
5713 break;
5714 }
5715#endif
thsb5906f92007-03-19 13:32:45 +00005716
ths6f5b89a2007-03-02 20:48:00 +00005717#if defined(TARGET_NR_set_tid_address) && defined(__NR_set_tid_address)
5718 case TARGET_NR_set_tid_address:
bellard579a97f2007-11-11 14:26:47 +00005719 ret = get_errno(set_tid_address((int *)g2h(arg1)));
5720 break;
ths6f5b89a2007-03-02 20:48:00 +00005721#endif
5722
ths3ae43202007-09-16 21:39:48 +00005723#if defined(TARGET_NR_tkill) && defined(__NR_tkill)
ths4cae1d12007-07-12 11:06:53 +00005724 case TARGET_NR_tkill:
pbrook4cb05962008-05-30 18:05:19 +00005725 ret = get_errno(sys_tkill((int)arg1, target_to_host_signal(arg2)));
ths4cae1d12007-07-12 11:06:53 +00005726 break;
5727#endif
5728
ths3ae43202007-09-16 21:39:48 +00005729#if defined(TARGET_NR_tgkill) && defined(__NR_tgkill)
ths71455572007-06-21 21:45:30 +00005730 case TARGET_NR_tgkill:
pbrook4cb05962008-05-30 18:05:19 +00005731 ret = get_errno(sys_tgkill((int)arg1, (int)arg2,
5732 target_to_host_signal(arg3)));
ths71455572007-06-21 21:45:30 +00005733 break;
5734#endif
5735
ths4f2b1fe2007-06-21 21:57:12 +00005736#ifdef TARGET_NR_set_robust_list
5737 case TARGET_NR_set_robust_list:
5738 goto unimplemented_nowarn;
5739#endif
5740
ths9007f0e2007-09-25 17:50:37 +00005741#if defined(TARGET_NR_utimensat) && defined(__NR_utimensat)
5742 case TARGET_NR_utimensat:
5743 {
5744 struct timespec ts[2];
5745 target_to_host_timespec(ts, arg3);
5746 target_to_host_timespec(ts+1, arg3+sizeof(struct target_timespec));
5747 if (!arg2)
5748 ret = get_errno(sys_utimensat(arg1, NULL, ts, arg4));
5749 else {
bellard579a97f2007-11-11 14:26:47 +00005750 if (!(p = lock_user_string(arg2))) {
ths0da46a62007-10-20 20:23:07 +00005751 ret = -TARGET_EFAULT;
bellard579a97f2007-11-11 14:26:47 +00005752 goto fail;
5753 }
5754 ret = get_errno(sys_utimensat(arg1, path(p), ts, arg4));
5755 unlock_user(p, arg2, 0);
ths9007f0e2007-09-25 17:50:37 +00005756 }
5757 }
5758 break;
5759#endif
pbrookbd0c5662008-05-29 14:34:11 +00005760#if defined(USE_NPTL)
5761 case TARGET_NR_futex:
5762 ret = do_futex(arg1, arg2, arg3, arg4, arg5, arg6);
5763 break;
5764#endif
ths9007f0e2007-09-25 17:50:37 +00005765
bellard31e31b82003-02-18 22:55:36 +00005766 default:
5767 unimplemented:
bellard5cd43932003-03-29 16:54:36 +00005768 gemu_log("qemu: Unsupported syscall: %d\n", num);
ths4f2b1fe2007-06-21 21:57:12 +00005769#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 +00005770 unimplemented_nowarn:
bellard80a9d032005-01-03 23:31:27 +00005771#endif
ths0da46a62007-10-20 20:23:07 +00005772 ret = -TARGET_ENOSYS;
bellard31e31b82003-02-18 22:55:36 +00005773 break;
5774 }
bellard579a97f2007-11-11 14:26:47 +00005775fail:
bellardc573ff62004-01-04 15:51:36 +00005776#ifdef DEBUG
5777 gemu_log(" = %ld\n", ret);
5778#endif
thsb92c47c2007-11-01 00:07:38 +00005779 if(do_strace)
5780 print_syscall_ret(num, ret);
bellard31e31b82003-02-18 22:55:36 +00005781 return ret;
bellard579a97f2007-11-11 14:26:47 +00005782efault:
5783 ret = -TARGET_EFAULT;
5784 goto fail;
bellard31e31b82003-02-18 22:55:36 +00005785}