blob: bb0999d1abe73b337570478ae94dfc572bbe8511 [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
Blue Swirl8167ee82009-07-16 20:47:01 +000017 * along with this program; if not, see <http://www.gnu.org/licenses/>.
bellard31e31b82003-02-18 22:55:36 +000018 */
Eduardo Habkostd5b3a9b2009-06-09 18:26:31 -030019#define _ATFILE_SOURCE
bellard31e31b82003-02-18 22:55:36 +000020#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>
Aurelien Jarno60e99242010-03-29 02:12:51 +020044#ifdef __ia64__
45int __clone2(int (*fn)(void *), void *child_stack_base,
46 size_t stack_size, int flags, void *arg, ...);
47#endif
bellard31e31b82003-02-18 22:55:36 +000048#include <sys/socket.h>
aurel32607175e2009-04-15 16:11:59 +000049#include <sys/un.h>
bellard31e31b82003-02-18 22:55:36 +000050#include <sys/uio.h>
bellard9de5e442003-03-23 16:49:39 +000051#include <sys/poll.h>
bellard32f36bc2003-03-30 21:29:48 +000052#include <sys/times.h>
bellard8853f862004-02-22 14:57:26 +000053#include <sys/shm.h>
thsfa294812007-02-02 22:05:00 +000054#include <sys/sem.h>
bellard56c8f682005-11-28 22:28:41 +000055#include <sys/statfs.h>
bellardebc05482003-09-30 21:08:41 +000056#include <utime.h>
bellarda5448a72004-06-19 16:59:03 +000057#include <sys/sysinfo.h>
aurel323b3f24a2009-04-15 16:12:13 +000058#include <sys/utsname.h>
bellard72f03902003-02-18 23:33:18 +000059//#include <sys/user.h>
bellard8853f862004-02-22 14:57:26 +000060#include <netinet/ip.h>
bellard7854b052003-03-29 17:22:23 +000061#include <netinet/tcp.h>
aurel320b6d3ae2008-09-15 07:43:43 +000062#include <qemu-common.h>
Juan Quintela9788c9c2009-07-27 16:13:02 +020063#ifdef TARGET_GPROF
aurel326d946cd2008-11-06 16:15:18 +000064#include <sys/gmon.h>
65#endif
Riku Voipioc2882b92009-08-12 15:08:24 +030066#ifdef CONFIG_EVENTFD
67#include <sys/eventfd.h>
68#endif
Peter Maydell3b6edd12011-02-15 18:35:05 +000069#ifdef CONFIG_EPOLL
70#include <sys/epoll.h>
71#endif
bellard31e31b82003-02-18 22:55:36 +000072
73#define termios host_termios
74#define winsize host_winsize
75#define termio host_termio
bellard04369ff2003-03-20 22:33:23 +000076#define sgttyb host_sgttyb /* same as target */
77#define tchars host_tchars /* same as target */
78#define ltchars host_ltchars /* same as target */
bellard31e31b82003-02-18 22:55:36 +000079
80#include <linux/termios.h>
81#include <linux/unistd.h>
82#include <linux/utsname.h>
83#include <linux/cdrom.h>
84#include <linux/hdreg.h>
85#include <linux/soundcard.h>
bellard19b84f32003-05-08 15:41:49 +000086#include <linux/kd.h>
balrog8fbd6b52008-09-20 03:03:09 +000087#include <linux/mtio.h>
Martin Mohring350d1772009-05-04 21:21:41 +030088#include <linux/fs.h>
Peter Maydelldace20d2011-01-10 13:11:24 +000089#if defined(CONFIG_FIEMAP)
Peter Maydell285da2b2011-01-06 15:04:18 +000090#include <linux/fiemap.h>
Peter Maydelldace20d2011-01-10 13:11:24 +000091#endif
Ulrich Hechtf7680a52009-10-16 17:00:44 +020092#include <linux/fb.h>
93#include <linux/vt.h>
pbrookd7e40362008-05-23 16:06:43 +000094#include "linux_loop.h"
Loïc Minierda790302009-12-29 22:06:13 +010095#include "cpu-uname.h"
bellard31e31b82003-02-18 22:55:36 +000096
bellard3ef693a2003-03-23 20:17:16 +000097#include "qemu.h"
balrog526ccb72008-07-16 12:13:52 +000098#include "qemu-common.h"
bellard31e31b82003-02-18 22:55:36 +000099
Juan Quintela2f7bb872009-07-27 16:13:24 +0200100#if defined(CONFIG_USE_NPTL)
pbrookd865bab2008-06-07 22:12:17 +0000101#define CLONE_NPTL_FLAGS2 (CLONE_SETTLS | \
102 CLONE_PARENT_SETTID | CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID)
103#else
104/* XXX: Hardcode the above values. */
105#define CLONE_NPTL_FLAGS2 0
pbrook30813ce2008-06-02 15:45:44 +0000106#endif
107
bellard72f03902003-02-18 23:33:18 +0000108//#define DEBUG
bellard31e31b82003-02-18 22:55:36 +0000109
bellard1a9353d2003-03-16 20:28:50 +0000110//#include <linux/msdos_fs.h>
aurel326556a832008-10-13 21:08:17 +0000111#define VFAT_IOCTL_READDIR_BOTH _IOR('r', 1, struct linux_dirent [2])
112#define VFAT_IOCTL_READDIR_SHORT _IOR('r', 2, struct linux_dirent [2])
bellard1a9353d2003-03-16 20:28:50 +0000113
bellard70a194b2003-08-11 22:20:16 +0000114
bellard70a194b2003-08-11 22:20:16 +0000115#undef _syscall0
116#undef _syscall1
117#undef _syscall2
118#undef _syscall3
119#undef _syscall4
120#undef _syscall5
bellard83fcb512006-06-14 13:37:16 +0000121#undef _syscall6
bellard70a194b2003-08-11 22:20:16 +0000122
bellard83fcb512006-06-14 13:37:16 +0000123#define _syscall0(type,name) \
blueswir18fcd3692008-08-17 20:26:25 +0000124static type name (void) \
bellard83fcb512006-06-14 13:37:16 +0000125{ \
126 return syscall(__NR_##name); \
bellard70a194b2003-08-11 22:20:16 +0000127}
128
bellard83fcb512006-06-14 13:37:16 +0000129#define _syscall1(type,name,type1,arg1) \
blueswir18fcd3692008-08-17 20:26:25 +0000130static type name (type1 arg1) \
bellard83fcb512006-06-14 13:37:16 +0000131{ \
132 return syscall(__NR_##name, arg1); \
bellard70a194b2003-08-11 22:20:16 +0000133}
134
bellard83fcb512006-06-14 13:37:16 +0000135#define _syscall2(type,name,type1,arg1,type2,arg2) \
blueswir18fcd3692008-08-17 20:26:25 +0000136static type name (type1 arg1,type2 arg2) \
bellard83fcb512006-06-14 13:37:16 +0000137{ \
138 return syscall(__NR_##name, arg1, arg2); \
bellard70a194b2003-08-11 22:20:16 +0000139}
140
bellard83fcb512006-06-14 13:37:16 +0000141#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \
blueswir18fcd3692008-08-17 20:26:25 +0000142static type name (type1 arg1,type2 arg2,type3 arg3) \
bellard83fcb512006-06-14 13:37:16 +0000143{ \
144 return syscall(__NR_##name, arg1, arg2, arg3); \
bellard70a194b2003-08-11 22:20:16 +0000145}
146
bellard83fcb512006-06-14 13:37:16 +0000147#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \
blueswir18fcd3692008-08-17 20:26:25 +0000148static type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4) \
bellard83fcb512006-06-14 13:37:16 +0000149{ \
150 return syscall(__NR_##name, arg1, arg2, arg3, arg4); \
bellard70a194b2003-08-11 22:20:16 +0000151}
152
bellard83fcb512006-06-14 13:37:16 +0000153#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
154 type5,arg5) \
blueswir18fcd3692008-08-17 20:26:25 +0000155static type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \
bellard83fcb512006-06-14 13:37:16 +0000156{ \
157 return syscall(__NR_##name, arg1, arg2, arg3, arg4, arg5); \
bellard70a194b2003-08-11 22:20:16 +0000158}
bellard83fcb512006-06-14 13:37:16 +0000159
160
161#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
162 type5,arg5,type6,arg6) \
blueswir18fcd3692008-08-17 20:26:25 +0000163static type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5, \
164 type6 arg6) \
bellard83fcb512006-06-14 13:37:16 +0000165{ \
166 return syscall(__NR_##name, arg1, arg2, arg3, arg4, arg5, arg6); \
167}
168
bellard70a194b2003-08-11 22:20:16 +0000169
bellard31e31b82003-02-18 22:55:36 +0000170#define __NR_sys_uname __NR_uname
ths92a34c12007-09-24 09:27:49 +0000171#define __NR_sys_faccessat __NR_faccessat
ths814d7972007-09-24 09:26:51 +0000172#define __NR_sys_fchmodat __NR_fchmodat
thsccfa72b2007-09-24 09:23:34 +0000173#define __NR_sys_fchownat __NR_fchownat
balrog6a24a772008-09-20 02:23:36 +0000174#define __NR_sys_fstatat64 __NR_fstatat64
balrogac8a6552008-09-20 02:25:39 +0000175#define __NR_sys_futimesat __NR_futimesat
bellard72f03902003-02-18 23:33:18 +0000176#define __NR_sys_getcwd1 __NR_getcwd
bellard72f03902003-02-18 23:33:18 +0000177#define __NR_sys_getdents __NR_getdents
bellarddab2ed92003-03-22 15:23:14 +0000178#define __NR_sys_getdents64 __NR_getdents64
thsc6cda172007-10-09 03:42:34 +0000179#define __NR_sys_getpriority __NR_getpriority
ths64f0ce42007-09-24 09:25:06 +0000180#define __NR_sys_linkat __NR_linkat
ths4472ad02007-09-24 09:22:32 +0000181#define __NR_sys_mkdirat __NR_mkdirat
ths75ac37a2007-09-24 09:23:05 +0000182#define __NR_sys_mknodat __NR_mknodat
aurel329d33b762009-04-08 23:07:05 +0000183#define __NR_sys_newfstatat __NR_newfstatat
ths82424832007-09-24 09:21:55 +0000184#define __NR_sys_openat __NR_openat
ths5e0ccb12007-09-24 09:26:10 +0000185#define __NR_sys_readlinkat __NR_readlinkat
ths722183f2007-09-24 09:24:37 +0000186#define __NR_sys_renameat __NR_renameat
bellard66fb9762003-03-23 01:06:05 +0000187#define __NR_sys_rt_sigqueueinfo __NR_rt_sigqueueinfo
thsf0b62432007-09-24 09:25:40 +0000188#define __NR_sys_symlinkat __NR_symlinkat
ths7494b0f2007-02-11 18:26:53 +0000189#define __NR_sys_syslog __NR_syslog
ths71455572007-06-21 21:45:30 +0000190#define __NR_sys_tgkill __NR_tgkill
ths4cae1d12007-07-12 11:06:53 +0000191#define __NR_sys_tkill __NR_tkill
ths8170f562007-09-24 09:24:11 +0000192#define __NR_sys_unlinkat __NR_unlinkat
ths9007f0e2007-09-25 17:50:37 +0000193#define __NR_sys_utimensat __NR_utimensat
pbrookbd0c5662008-05-29 14:34:11 +0000194#define __NR_sys_futex __NR_futex
aurel3239b59762008-10-01 21:46:50 +0000195#define __NR_sys_inotify_init __NR_inotify_init
196#define __NR_sys_inotify_add_watch __NR_inotify_add_watch
197#define __NR_sys_inotify_rm_watch __NR_inotify_rm_watch
bellard31e31b82003-02-18 22:55:36 +0000198
bellardbc51c5c2004-03-17 23:46:04 +0000199#if defined(__alpha__) || defined (__ia64__) || defined(__x86_64__)
bellard9af9eaa2003-04-07 21:34:41 +0000200#define __NR__llseek __NR_lseek
201#endif
202
bellard72f03902003-02-18 23:33:18 +0000203#ifdef __NR_gettid
bellard31e31b82003-02-18 22:55:36 +0000204_syscall0(int, gettid)
bellard72f03902003-02-18 23:33:18 +0000205#else
ths0da46a62007-10-20 20:23:07 +0000206/* This is a replacement for the host gettid() and must return a host
207 errno. */
bellard72f03902003-02-18 23:33:18 +0000208static int gettid(void) {
209 return -ENOSYS;
210}
211#endif
aurel323b3f24a2009-04-15 16:12:13 +0000212_syscall3(int, sys_getdents, uint, fd, struct linux_dirent *, dirp, uint, count);
aurel323b3f24a2009-04-15 16:12:13 +0000213#if defined(TARGET_NR_getdents64) && defined(__NR_getdents64)
214_syscall3(int, sys_getdents64, uint, fd, struct linux_dirent64 *, dirp, uint, count);
215#endif
216_syscall2(int, sys_getpriority, int, which, int, who);
Richard Hendersond35b2612010-06-04 12:14:10 -0700217#if defined(TARGET_NR__llseek) && defined(__NR_llseek)
aurel323b3f24a2009-04-15 16:12:13 +0000218_syscall5(int, _llseek, uint, fd, ulong, hi, ulong, lo,
219 loff_t *, res, uint, wh);
220#endif
221_syscall3(int,sys_rt_sigqueueinfo,int,pid,int,sig,siginfo_t *,uinfo)
222_syscall3(int,sys_syslog,int,type,char*,bufp,int,len)
223#if defined(TARGET_NR_tgkill) && defined(__NR_tgkill)
224_syscall3(int,sys_tgkill,int,tgid,int,pid,int,sig)
225#endif
226#if defined(TARGET_NR_tkill) && defined(__NR_tkill)
227_syscall2(int,sys_tkill,int,tid,int,sig)
228#endif
229#ifdef __NR_exit_group
230_syscall1(int,exit_group,int,error_code)
231#endif
232#if defined(TARGET_NR_set_tid_address) && defined(__NR_set_tid_address)
233_syscall1(int,set_tid_address,int *,tidptr)
234#endif
Juan Quintela2f7bb872009-07-27 16:13:24 +0200235#if defined(CONFIG_USE_NPTL)
aurel323b3f24a2009-04-15 16:12:13 +0000236#if defined(TARGET_NR_futex) && defined(__NR_futex)
237_syscall6(int,sys_futex,int *,uaddr,int,op,int,val,
238 const struct timespec *,timeout,int *,uaddr2,int,val3)
239#endif
240#endif
Mike Frysinger737de1d2011-02-07 01:05:55 -0500241#define __NR_sys_sched_getaffinity __NR_sched_getaffinity
242_syscall3(int, sys_sched_getaffinity, pid_t, pid, unsigned int, len,
243 unsigned long *, user_mask_ptr);
244#define __NR_sys_sched_setaffinity __NR_sched_setaffinity
245_syscall3(int, sys_sched_setaffinity, pid_t, pid, unsigned int, len,
246 unsigned long *, user_mask_ptr);
aurel323b3f24a2009-04-15 16:12:13 +0000247
248static bitmask_transtbl fcntl_flags_tbl[] = {
249 { TARGET_O_ACCMODE, TARGET_O_WRONLY, O_ACCMODE, O_WRONLY, },
250 { TARGET_O_ACCMODE, TARGET_O_RDWR, O_ACCMODE, O_RDWR, },
251 { TARGET_O_CREAT, TARGET_O_CREAT, O_CREAT, O_CREAT, },
252 { TARGET_O_EXCL, TARGET_O_EXCL, O_EXCL, O_EXCL, },
253 { TARGET_O_NOCTTY, TARGET_O_NOCTTY, O_NOCTTY, O_NOCTTY, },
254 { TARGET_O_TRUNC, TARGET_O_TRUNC, O_TRUNC, O_TRUNC, },
255 { TARGET_O_APPEND, TARGET_O_APPEND, O_APPEND, O_APPEND, },
256 { TARGET_O_NONBLOCK, TARGET_O_NONBLOCK, O_NONBLOCK, O_NONBLOCK, },
257 { TARGET_O_SYNC, TARGET_O_SYNC, O_SYNC, O_SYNC, },
258 { TARGET_FASYNC, TARGET_FASYNC, FASYNC, FASYNC, },
259 { TARGET_O_DIRECTORY, TARGET_O_DIRECTORY, O_DIRECTORY, O_DIRECTORY, },
260 { TARGET_O_NOFOLLOW, TARGET_O_NOFOLLOW, O_NOFOLLOW, O_NOFOLLOW, },
261 { TARGET_O_LARGEFILE, TARGET_O_LARGEFILE, O_LARGEFILE, O_LARGEFILE, },
262#if defined(O_DIRECT)
263 { TARGET_O_DIRECT, TARGET_O_DIRECT, O_DIRECT, O_DIRECT, },
264#endif
265 { 0, 0, 0, 0 }
266};
267
268#define COPY_UTSNAME_FIELD(dest, src) \
269 do { \
270 /* __NEW_UTS_LEN doesn't include terminating null */ \
271 (void) strncpy((dest), (src), __NEW_UTS_LEN); \
272 (dest)[__NEW_UTS_LEN] = '\0'; \
273 } while (0)
274
275static int sys_uname(struct new_utsname *buf)
276{
277 struct utsname uts_buf;
278
279 if (uname(&uts_buf) < 0)
280 return (-1);
281
282 /*
283 * Just in case these have some differences, we
284 * translate utsname to new_utsname (which is the
285 * struct linux kernel uses).
286 */
287
288 bzero(buf, sizeof (*buf));
289 COPY_UTSNAME_FIELD(buf->sysname, uts_buf.sysname);
290 COPY_UTSNAME_FIELD(buf->nodename, uts_buf.nodename);
291 COPY_UTSNAME_FIELD(buf->release, uts_buf.release);
292 COPY_UTSNAME_FIELD(buf->version, uts_buf.version);
293 COPY_UTSNAME_FIELD(buf->machine, uts_buf.machine);
294#ifdef _GNU_SOURCE
295 COPY_UTSNAME_FIELD(buf->domainname, uts_buf.domainname);
296#endif
297 return (0);
298
299#undef COPY_UTSNAME_FIELD
300}
301
302static int sys_getcwd1(char *buf, size_t size)
303{
304 if (getcwd(buf, size) == NULL) {
305 /* getcwd() sets errno */
306 return (-1);
307 }
aurel32aaf4ad32009-04-16 14:17:14 +0000308 return strlen(buf)+1;
aurel323b3f24a2009-04-15 16:12:13 +0000309}
310
311#ifdef CONFIG_ATFILE
312/*
313 * Host system seems to have atfile syscall stubs available. We
314 * now enable them one by one as specified by target syscall_nr.h.
315 */
316
317#ifdef TARGET_NR_faccessat
aurel32465c9f02009-04-19 08:52:17 +0000318static int sys_faccessat(int dirfd, const char *pathname, int mode)
aurel323b3f24a2009-04-15 16:12:13 +0000319{
aurel32465c9f02009-04-19 08:52:17 +0000320 return (faccessat(dirfd, pathname, mode, 0));
aurel323b3f24a2009-04-15 16:12:13 +0000321}
322#endif
323#ifdef TARGET_NR_fchmodat
aurel32465c9f02009-04-19 08:52:17 +0000324static int sys_fchmodat(int dirfd, const char *pathname, mode_t mode)
aurel323b3f24a2009-04-15 16:12:13 +0000325{
aurel32465c9f02009-04-19 08:52:17 +0000326 return (fchmodat(dirfd, pathname, mode, 0));
aurel323b3f24a2009-04-15 16:12:13 +0000327}
328#endif
aurel32fda33742009-04-15 17:12:01 +0000329#if defined(TARGET_NR_fchownat) && defined(USE_UID16)
aurel323b3f24a2009-04-15 16:12:13 +0000330static int sys_fchownat(int dirfd, const char *pathname, uid_t owner,
331 gid_t group, int flags)
332{
333 return (fchownat(dirfd, pathname, owner, group, flags));
334}
335#endif
336#ifdef __NR_fstatat64
337static int sys_fstatat64(int dirfd, const char *pathname, struct stat *buf,
338 int flags)
339{
340 return (fstatat(dirfd, pathname, buf, flags));
341}
342#endif
343#ifdef __NR_newfstatat
344static int sys_newfstatat(int dirfd, const char *pathname, struct stat *buf,
345 int flags)
346{
347 return (fstatat(dirfd, pathname, buf, flags));
348}
349#endif
350#ifdef TARGET_NR_futimesat
351static int sys_futimesat(int dirfd, const char *pathname,
352 const struct timeval times[2])
353{
354 return (futimesat(dirfd, pathname, times));
355}
356#endif
357#ifdef TARGET_NR_linkat
358static int sys_linkat(int olddirfd, const char *oldpath,
359 int newdirfd, const char *newpath, int flags)
360{
361 return (linkat(olddirfd, oldpath, newdirfd, newpath, flags));
362}
363#endif
364#ifdef TARGET_NR_mkdirat
365static int sys_mkdirat(int dirfd, const char *pathname, mode_t mode)
366{
367 return (mkdirat(dirfd, pathname, mode));
368}
369#endif
370#ifdef TARGET_NR_mknodat
371static int sys_mknodat(int dirfd, const char *pathname, mode_t mode,
372 dev_t dev)
373{
374 return (mknodat(dirfd, pathname, mode, dev));
375}
376#endif
377#ifdef TARGET_NR_openat
378static int sys_openat(int dirfd, const char *pathname, int flags, ...)
379{
380 /*
381 * open(2) has extra parameter 'mode' when called with
382 * flag O_CREAT.
383 */
384 if ((flags & O_CREAT) != 0) {
385 va_list ap;
386 mode_t mode;
387
388 /*
389 * Get the 'mode' parameter and translate it to
390 * host bits.
391 */
392 va_start(ap, flags);
393 mode = va_arg(ap, mode_t);
394 mode = target_to_host_bitmask(mode, fcntl_flags_tbl);
395 va_end(ap);
396
397 return (openat(dirfd, pathname, flags, mode));
398 }
399 return (openat(dirfd, pathname, flags));
400}
401#endif
402#ifdef TARGET_NR_readlinkat
403static int sys_readlinkat(int dirfd, const char *pathname, char *buf, size_t bufsiz)
404{
405 return (readlinkat(dirfd, pathname, buf, bufsiz));
406}
407#endif
408#ifdef TARGET_NR_renameat
409static int sys_renameat(int olddirfd, const char *oldpath,
410 int newdirfd, const char *newpath)
411{
412 return (renameat(olddirfd, oldpath, newdirfd, newpath));
413}
414#endif
415#ifdef TARGET_NR_symlinkat
416static int sys_symlinkat(const char *oldpath, int newdirfd, const char *newpath)
417{
418 return (symlinkat(oldpath, newdirfd, newpath));
419}
420#endif
421#ifdef TARGET_NR_unlinkat
422static int sys_unlinkat(int dirfd, const char *pathname, int flags)
423{
424 return (unlinkat(dirfd, pathname, flags));
425}
426#endif
aurel323b3f24a2009-04-15 16:12:13 +0000427#else /* !CONFIG_ATFILE */
428
429/*
430 * Try direct syscalls instead
431 */
ths92a34c12007-09-24 09:27:49 +0000432#if defined(TARGET_NR_faccessat) && defined(__NR_faccessat)
aurel32465c9f02009-04-19 08:52:17 +0000433_syscall3(int,sys_faccessat,int,dirfd,const char *,pathname,int,mode)
ths92a34c12007-09-24 09:27:49 +0000434#endif
ths814d7972007-09-24 09:26:51 +0000435#if defined(TARGET_NR_fchmodat) && defined(__NR_fchmodat)
aurel32465c9f02009-04-19 08:52:17 +0000436_syscall3(int,sys_fchmodat,int,dirfd,const char *,pathname, mode_t,mode)
ths814d7972007-09-24 09:26:51 +0000437#endif
blueswir14583f582008-08-24 10:35:55 +0000438#if defined(TARGET_NR_fchownat) && defined(__NR_fchownat) && defined(USE_UID16)
thsccfa72b2007-09-24 09:23:34 +0000439_syscall5(int,sys_fchownat,int,dirfd,const char *,pathname,
440 uid_t,owner,gid_t,group,int,flags)
441#endif
aurel329d33b762009-04-08 23:07:05 +0000442#if (defined(TARGET_NR_fstatat64) || defined(TARGET_NR_newfstatat)) && \
443 defined(__NR_fstatat64)
balrog6a24a772008-09-20 02:23:36 +0000444_syscall4(int,sys_fstatat64,int,dirfd,const char *,pathname,
445 struct stat *,buf,int,flags)
446#endif
balrogac8a6552008-09-20 02:25:39 +0000447#if defined(TARGET_NR_futimesat) && defined(__NR_futimesat)
448_syscall3(int,sys_futimesat,int,dirfd,const char *,pathname,
449 const struct timeval *,times)
450#endif
aurel323b3f24a2009-04-15 16:12:13 +0000451#if (defined(TARGET_NR_newfstatat) || defined(TARGET_NR_fstatat64) ) && \
452 defined(__NR_newfstatat)
453_syscall4(int,sys_newfstatat,int,dirfd,const char *,pathname,
454 struct stat *,buf,int,flags)
blueswir18fcd3692008-08-17 20:26:25 +0000455#endif
ths64f0ce42007-09-24 09:25:06 +0000456#if defined(TARGET_NR_linkat) && defined(__NR_linkat)
457_syscall5(int,sys_linkat,int,olddirfd,const char *,oldpath,
aurel323b3f24a2009-04-15 16:12:13 +0000458 int,newdirfd,const char *,newpath,int,flags)
ths64f0ce42007-09-24 09:25:06 +0000459#endif
ths4472ad02007-09-24 09:22:32 +0000460#if defined(TARGET_NR_mkdirat) && defined(__NR_mkdirat)
461_syscall3(int,sys_mkdirat,int,dirfd,const char *,pathname,mode_t,mode)
462#endif
ths75ac37a2007-09-24 09:23:05 +0000463#if defined(TARGET_NR_mknodat) && defined(__NR_mknodat)
464_syscall4(int,sys_mknodat,int,dirfd,const char *,pathname,
465 mode_t,mode,dev_t,dev)
466#endif
ths82424832007-09-24 09:21:55 +0000467#if defined(TARGET_NR_openat) && defined(__NR_openat)
468_syscall4(int,sys_openat,int,dirfd,const char *,pathname,int,flags,mode_t,mode)
469#endif
ths5e0ccb12007-09-24 09:26:10 +0000470#if defined(TARGET_NR_readlinkat) && defined(__NR_readlinkat)
471_syscall4(int,sys_readlinkat,int,dirfd,const char *,pathname,
472 char *,buf,size_t,bufsize)
473#endif
ths722183f2007-09-24 09:24:37 +0000474#if defined(TARGET_NR_renameat) && defined(__NR_renameat)
475_syscall4(int,sys_renameat,int,olddirfd,const char *,oldpath,
476 int,newdirfd,const char *,newpath)
477#endif
thsb51eaa82007-09-25 16:09:22 +0000478#if defined(TARGET_NR_symlinkat) && defined(__NR_symlinkat)
thsf0b62432007-09-24 09:25:40 +0000479_syscall3(int,sys_symlinkat,const char *,oldpath,
480 int,newdirfd,const char *,newpath)
481#endif
ths8170f562007-09-24 09:24:11 +0000482#if defined(TARGET_NR_unlinkat) && defined(__NR_unlinkat)
483_syscall3(int,sys_unlinkat,int,dirfd,const char *,pathname,int,flags)
484#endif
Riku Voipioebc996f2009-04-21 15:01:51 +0300485
486#endif /* CONFIG_ATFILE */
487
488#ifdef CONFIG_UTIMENSAT
489static int sys_utimensat(int dirfd, const char *pathname,
490 const struct timespec times[2], int flags)
491{
492 if (pathname == NULL)
493 return futimens(dirfd, times);
494 else
495 return utimensat(dirfd, pathname, times, flags);
496}
497#else
ths9007f0e2007-09-25 17:50:37 +0000498#if defined(TARGET_NR_utimensat) && defined(__NR_utimensat)
499_syscall4(int,sys_utimensat,int,dirfd,const char *,pathname,
500 const struct timespec *,tsp,int,flags)
501#endif
Riku Voipioebc996f2009-04-21 15:01:51 +0300502#endif /* CONFIG_UTIMENSAT */
aurel323b3f24a2009-04-15 16:12:13 +0000503
504#ifdef CONFIG_INOTIFY
aurel328690e422009-04-17 13:50:32 +0000505#include <sys/inotify.h>
aurel323b3f24a2009-04-15 16:12:13 +0000506
aurel3239b59762008-10-01 21:46:50 +0000507#if defined(TARGET_NR_inotify_init) && defined(__NR_inotify_init)
aurel323b3f24a2009-04-15 16:12:13 +0000508static int sys_inotify_init(void)
509{
510 return (inotify_init());
511}
aurel3239b59762008-10-01 21:46:50 +0000512#endif
513#if defined(TARGET_NR_inotify_add_watch) && defined(__NR_inotify_add_watch)
aurel323b3f24a2009-04-15 16:12:13 +0000514static int sys_inotify_add_watch(int fd,const char *pathname, int32_t mask)
515{
516 return (inotify_add_watch(fd, pathname, mask));
517}
aurel3239b59762008-10-01 21:46:50 +0000518#endif
519#if defined(TARGET_NR_inotify_rm_watch) && defined(__NR_inotify_rm_watch)
aurel323b3f24a2009-04-15 16:12:13 +0000520static int sys_inotify_rm_watch(int fd, int32_t wd)
521{
aurel328690e422009-04-17 13:50:32 +0000522 return (inotify_rm_watch(fd, wd));
aurel323b3f24a2009-04-15 16:12:13 +0000523}
aurel3239b59762008-10-01 21:46:50 +0000524#endif
Riku Voipioc05c7a72010-03-26 15:25:11 +0000525#ifdef CONFIG_INOTIFY1
526#if defined(TARGET_NR_inotify_init1) && defined(__NR_inotify_init1)
527static int sys_inotify_init1(int flags)
528{
529 return (inotify_init1(flags));
530}
531#endif
532#endif
aurel323b3f24a2009-04-15 16:12:13 +0000533#else
534/* Userspace can usually survive runtime without inotify */
535#undef TARGET_NR_inotify_init
Riku Voipioc05c7a72010-03-26 15:25:11 +0000536#undef TARGET_NR_inotify_init1
aurel323b3f24a2009-04-15 16:12:13 +0000537#undef TARGET_NR_inotify_add_watch
538#undef TARGET_NR_inotify_rm_watch
539#endif /* CONFIG_INOTIFY */
540
Mike Frysingerd8035d42011-02-07 01:05:51 -0500541#if defined(TARGET_NR_ppoll)
542#ifndef __NR_ppoll
543# define __NR_ppoll -1
544#endif
545#define __NR_sys_ppoll __NR_ppoll
546_syscall5(int, sys_ppoll, struct pollfd *, fds, nfds_t, nfds,
547 struct timespec *, timeout, const __sigset_t *, sigmask,
548 size_t, sigsetsize)
549#endif
bellard66fb9762003-03-23 01:06:05 +0000550
551extern int personality(int);
bellard9de5e442003-03-23 16:49:39 +0000552extern int flock(int, int);
553extern int setfsuid(int);
554extern int setfsgid(int);
bellard19b84f32003-05-08 15:41:49 +0000555extern int setgroups(int, gid_t *);
bellard31e31b82003-02-18 22:55:36 +0000556
thsb92c47c2007-11-01 00:07:38 +0000557#define ERRNO_TABLE_SIZE 1200
558
559/* target_to_host_errno_table[] is initialized from
560 * host_to_target_errno_table[] in syscall_init(). */
561static uint16_t target_to_host_errno_table[ERRNO_TABLE_SIZE] = {
562};
563
ths637947f2007-06-01 12:09:19 +0000564/*
thsfe8f0962007-07-12 10:59:21 +0000565 * This list is the union of errno values overridden in asm-<arch>/errno.h
ths637947f2007-06-01 12:09:19 +0000566 * minus the errnos that are not actually generic to all archs.
567 */
thsb92c47c2007-11-01 00:07:38 +0000568static uint16_t host_to_target_errno_table[ERRNO_TABLE_SIZE] = {
ths637947f2007-06-01 12:09:19 +0000569 [EIDRM] = TARGET_EIDRM,
570 [ECHRNG] = TARGET_ECHRNG,
571 [EL2NSYNC] = TARGET_EL2NSYNC,
572 [EL3HLT] = TARGET_EL3HLT,
573 [EL3RST] = TARGET_EL3RST,
574 [ELNRNG] = TARGET_ELNRNG,
575 [EUNATCH] = TARGET_EUNATCH,
576 [ENOCSI] = TARGET_ENOCSI,
577 [EL2HLT] = TARGET_EL2HLT,
578 [EDEADLK] = TARGET_EDEADLK,
579 [ENOLCK] = TARGET_ENOLCK,
580 [EBADE] = TARGET_EBADE,
581 [EBADR] = TARGET_EBADR,
582 [EXFULL] = TARGET_EXFULL,
583 [ENOANO] = TARGET_ENOANO,
584 [EBADRQC] = TARGET_EBADRQC,
585 [EBADSLT] = TARGET_EBADSLT,
586 [EBFONT] = TARGET_EBFONT,
587 [ENOSTR] = TARGET_ENOSTR,
588 [ENODATA] = TARGET_ENODATA,
589 [ETIME] = TARGET_ETIME,
590 [ENOSR] = TARGET_ENOSR,
591 [ENONET] = TARGET_ENONET,
592 [ENOPKG] = TARGET_ENOPKG,
593 [EREMOTE] = TARGET_EREMOTE,
594 [ENOLINK] = TARGET_ENOLINK,
595 [EADV] = TARGET_EADV,
596 [ESRMNT] = TARGET_ESRMNT,
597 [ECOMM] = TARGET_ECOMM,
598 [EPROTO] = TARGET_EPROTO,
599 [EDOTDOT] = TARGET_EDOTDOT,
600 [EMULTIHOP] = TARGET_EMULTIHOP,
601 [EBADMSG] = TARGET_EBADMSG,
602 [ENAMETOOLONG] = TARGET_ENAMETOOLONG,
603 [EOVERFLOW] = TARGET_EOVERFLOW,
604 [ENOTUNIQ] = TARGET_ENOTUNIQ,
605 [EBADFD] = TARGET_EBADFD,
606 [EREMCHG] = TARGET_EREMCHG,
607 [ELIBACC] = TARGET_ELIBACC,
608 [ELIBBAD] = TARGET_ELIBBAD,
609 [ELIBSCN] = TARGET_ELIBSCN,
610 [ELIBMAX] = TARGET_ELIBMAX,
611 [ELIBEXEC] = TARGET_ELIBEXEC,
612 [EILSEQ] = TARGET_EILSEQ,
613 [ENOSYS] = TARGET_ENOSYS,
614 [ELOOP] = TARGET_ELOOP,
615 [ERESTART] = TARGET_ERESTART,
616 [ESTRPIPE] = TARGET_ESTRPIPE,
617 [ENOTEMPTY] = TARGET_ENOTEMPTY,
618 [EUSERS] = TARGET_EUSERS,
619 [ENOTSOCK] = TARGET_ENOTSOCK,
620 [EDESTADDRREQ] = TARGET_EDESTADDRREQ,
621 [EMSGSIZE] = TARGET_EMSGSIZE,
622 [EPROTOTYPE] = TARGET_EPROTOTYPE,
623 [ENOPROTOOPT] = TARGET_ENOPROTOOPT,
624 [EPROTONOSUPPORT] = TARGET_EPROTONOSUPPORT,
625 [ESOCKTNOSUPPORT] = TARGET_ESOCKTNOSUPPORT,
626 [EOPNOTSUPP] = TARGET_EOPNOTSUPP,
627 [EPFNOSUPPORT] = TARGET_EPFNOSUPPORT,
628 [EAFNOSUPPORT] = TARGET_EAFNOSUPPORT,
629 [EADDRINUSE] = TARGET_EADDRINUSE,
630 [EADDRNOTAVAIL] = TARGET_EADDRNOTAVAIL,
631 [ENETDOWN] = TARGET_ENETDOWN,
632 [ENETUNREACH] = TARGET_ENETUNREACH,
633 [ENETRESET] = TARGET_ENETRESET,
634 [ECONNABORTED] = TARGET_ECONNABORTED,
635 [ECONNRESET] = TARGET_ECONNRESET,
636 [ENOBUFS] = TARGET_ENOBUFS,
637 [EISCONN] = TARGET_EISCONN,
638 [ENOTCONN] = TARGET_ENOTCONN,
639 [EUCLEAN] = TARGET_EUCLEAN,
640 [ENOTNAM] = TARGET_ENOTNAM,
641 [ENAVAIL] = TARGET_ENAVAIL,
642 [EISNAM] = TARGET_EISNAM,
643 [EREMOTEIO] = TARGET_EREMOTEIO,
644 [ESHUTDOWN] = TARGET_ESHUTDOWN,
645 [ETOOMANYREFS] = TARGET_ETOOMANYREFS,
646 [ETIMEDOUT] = TARGET_ETIMEDOUT,
647 [ECONNREFUSED] = TARGET_ECONNREFUSED,
648 [EHOSTDOWN] = TARGET_EHOSTDOWN,
649 [EHOSTUNREACH] = TARGET_EHOSTUNREACH,
650 [EALREADY] = TARGET_EALREADY,
651 [EINPROGRESS] = TARGET_EINPROGRESS,
652 [ESTALE] = TARGET_ESTALE,
653 [ECANCELED] = TARGET_ECANCELED,
654 [ENOMEDIUM] = TARGET_ENOMEDIUM,
655 [EMEDIUMTYPE] = TARGET_EMEDIUMTYPE,
thsb7fe5db2007-07-23 15:37:46 +0000656#ifdef ENOKEY
ths637947f2007-06-01 12:09:19 +0000657 [ENOKEY] = TARGET_ENOKEY,
thsb7fe5db2007-07-23 15:37:46 +0000658#endif
659#ifdef EKEYEXPIRED
ths637947f2007-06-01 12:09:19 +0000660 [EKEYEXPIRED] = TARGET_EKEYEXPIRED,
thsb7fe5db2007-07-23 15:37:46 +0000661#endif
662#ifdef EKEYREVOKED
ths637947f2007-06-01 12:09:19 +0000663 [EKEYREVOKED] = TARGET_EKEYREVOKED,
thsb7fe5db2007-07-23 15:37:46 +0000664#endif
665#ifdef EKEYREJECTED
ths637947f2007-06-01 12:09:19 +0000666 [EKEYREJECTED] = TARGET_EKEYREJECTED,
thsb7fe5db2007-07-23 15:37:46 +0000667#endif
668#ifdef EOWNERDEAD
ths637947f2007-06-01 12:09:19 +0000669 [EOWNERDEAD] = TARGET_EOWNERDEAD,
thsb7fe5db2007-07-23 15:37:46 +0000670#endif
671#ifdef ENOTRECOVERABLE
ths637947f2007-06-01 12:09:19 +0000672 [ENOTRECOVERABLE] = TARGET_ENOTRECOVERABLE,
thsb7fe5db2007-07-23 15:37:46 +0000673#endif
thsb92c47c2007-11-01 00:07:38 +0000674};
ths637947f2007-06-01 12:09:19 +0000675
676static inline int host_to_target_errno(int err)
677{
678 if(host_to_target_errno_table[err])
679 return host_to_target_errno_table[err];
680 return err;
681}
682
thsb92c47c2007-11-01 00:07:38 +0000683static inline int target_to_host_errno(int err)
684{
685 if (target_to_host_errno_table[err])
686 return target_to_host_errno_table[err];
687 return err;
688}
689
blueswir1992f48a2007-10-14 16:27:31 +0000690static inline abi_long get_errno(abi_long ret)
bellard31e31b82003-02-18 22:55:36 +0000691{
692 if (ret == -1)
ths637947f2007-06-01 12:09:19 +0000693 return -host_to_target_errno(errno);
bellard31e31b82003-02-18 22:55:36 +0000694 else
695 return ret;
696}
697
blueswir1992f48a2007-10-14 16:27:31 +0000698static inline int is_error(abi_long ret)
bellard31e31b82003-02-18 22:55:36 +0000699{
blueswir1992f48a2007-10-14 16:27:31 +0000700 return (abi_ulong)ret >= (abi_ulong)(-4096);
bellard31e31b82003-02-18 22:55:36 +0000701}
702
thsb92c47c2007-11-01 00:07:38 +0000703char *target_strerror(int err)
704{
705 return strerror(target_to_host_errno(err));
706}
707
blueswir1992f48a2007-10-14 16:27:31 +0000708static abi_ulong target_brk;
709static abi_ulong target_original_brk;
bellard31e31b82003-02-18 22:55:36 +0000710
blueswir1992f48a2007-10-14 16:27:31 +0000711void target_set_brk(abi_ulong new_brk)
bellard31e31b82003-02-18 22:55:36 +0000712{
blueswir14c1de732007-07-07 20:45:44 +0000713 target_original_brk = target_brk = HOST_PAGE_ALIGN(new_brk);
bellard31e31b82003-02-18 22:55:36 +0000714}
715
ths0da46a62007-10-20 20:23:07 +0000716/* do_brk() must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +0000717abi_long do_brk(abi_ulong new_brk)
bellard31e31b82003-02-18 22:55:36 +0000718{
blueswir1992f48a2007-10-14 16:27:31 +0000719 abi_ulong brk_page;
720 abi_long mapped_addr;
bellard31e31b82003-02-18 22:55:36 +0000721 int new_alloc_size;
722
723 if (!new_brk)
pbrook53a59602006-03-25 19:31:22 +0000724 return target_brk;
bellard31e31b82003-02-18 22:55:36 +0000725 if (new_brk < target_original_brk)
balrog7ab240a2008-04-26 12:17:34 +0000726 return target_brk;
ths3b46e622007-09-17 08:09:54 +0000727
pbrook53a59602006-03-25 19:31:22 +0000728 brk_page = HOST_PAGE_ALIGN(target_brk);
bellard31e31b82003-02-18 22:55:36 +0000729
730 /* If the new brk is less than this, set it and we're done... */
731 if (new_brk < brk_page) {
732 target_brk = new_brk;
pbrook53a59602006-03-25 19:31:22 +0000733 return target_brk;
bellard31e31b82003-02-18 22:55:36 +0000734 }
735
736 /* We need to allocate more memory after the brk... */
bellard54936002003-05-13 00:25:15 +0000737 new_alloc_size = HOST_PAGE_ALIGN(new_brk - brk_page + 1);
ths5fafdf22007-09-16 21:08:06 +0000738 mapped_addr = get_errno(target_mmap(brk_page, new_alloc_size,
bellard54936002003-05-13 00:25:15 +0000739 PROT_READ|PROT_WRITE,
740 MAP_ANON|MAP_FIXED|MAP_PRIVATE, 0, 0));
balrog7ab240a2008-04-26 12:17:34 +0000741
Richard Henderson7dd46c02010-05-03 10:07:49 -0700742#if defined(TARGET_ALPHA)
743 /* We (partially) emulate OSF/1 on Alpha, which requires we
744 return a proper errno, not an unchanged brk value. */
745 if (is_error(mapped_addr)) {
746 return -TARGET_ENOMEM;
747 }
748#endif
749
750 if (!is_error(mapped_addr)) {
bellard31e31b82003-02-18 22:55:36 +0000751 target_brk = new_brk;
Richard Henderson7dd46c02010-05-03 10:07:49 -0700752 }
balrog7ab240a2008-04-26 12:17:34 +0000753 return target_brk;
bellard31e31b82003-02-18 22:55:36 +0000754}
755
ths26edcf42007-12-09 02:25:24 +0000756static inline abi_long copy_from_user_fdset(fd_set *fds,
757 abi_ulong target_fds_addr,
758 int n)
bellard31e31b82003-02-18 22:55:36 +0000759{
ths26edcf42007-12-09 02:25:24 +0000760 int i, nw, j, k;
761 abi_ulong b, *target_fds;
762
763 nw = (n + TARGET_ABI_BITS - 1) / TARGET_ABI_BITS;
764 if (!(target_fds = lock_user(VERIFY_READ,
765 target_fds_addr,
766 sizeof(abi_ulong) * nw,
767 1)))
768 return -TARGET_EFAULT;
769
770 FD_ZERO(fds);
771 k = 0;
772 for (i = 0; i < nw; i++) {
773 /* grab the abi_ulong */
774 __get_user(b, &target_fds[i]);
775 for (j = 0; j < TARGET_ABI_BITS; j++) {
776 /* check the bit inside the abi_ulong */
777 if ((b >> j) & 1)
778 FD_SET(k, fds);
779 k++;
bellard31e31b82003-02-18 22:55:36 +0000780 }
bellard31e31b82003-02-18 22:55:36 +0000781 }
ths26edcf42007-12-09 02:25:24 +0000782
783 unlock_user(target_fds, target_fds_addr, 0);
784
785 return 0;
bellard31e31b82003-02-18 22:55:36 +0000786}
787
ths26edcf42007-12-09 02:25:24 +0000788static inline abi_long copy_to_user_fdset(abi_ulong target_fds_addr,
789 const fd_set *fds,
790 int n)
bellard31e31b82003-02-18 22:55:36 +0000791{
bellard31e31b82003-02-18 22:55:36 +0000792 int i, nw, j, k;
blueswir1992f48a2007-10-14 16:27:31 +0000793 abi_long v;
ths26edcf42007-12-09 02:25:24 +0000794 abi_ulong *target_fds;
bellard31e31b82003-02-18 22:55:36 +0000795
ths26edcf42007-12-09 02:25:24 +0000796 nw = (n + TARGET_ABI_BITS - 1) / TARGET_ABI_BITS;
797 if (!(target_fds = lock_user(VERIFY_WRITE,
798 target_fds_addr,
799 sizeof(abi_ulong) * nw,
800 0)))
801 return -TARGET_EFAULT;
802
803 k = 0;
804 for (i = 0; i < nw; i++) {
805 v = 0;
806 for (j = 0; j < TARGET_ABI_BITS; j++) {
807 v |= ((FD_ISSET(k, fds) != 0) << j);
808 k++;
bellard31e31b82003-02-18 22:55:36 +0000809 }
ths26edcf42007-12-09 02:25:24 +0000810 __put_user(v, &target_fds[i]);
bellard31e31b82003-02-18 22:55:36 +0000811 }
ths26edcf42007-12-09 02:25:24 +0000812
813 unlock_user(target_fds, target_fds_addr, sizeof(abi_ulong) * nw);
814
815 return 0;
bellard31e31b82003-02-18 22:55:36 +0000816}
817
bellardc596ed12003-07-13 17:32:31 +0000818#if defined(__alpha__)
819#define HOST_HZ 1024
820#else
821#define HOST_HZ 100
822#endif
823
blueswir1992f48a2007-10-14 16:27:31 +0000824static inline abi_long host_to_target_clock_t(long ticks)
bellardc596ed12003-07-13 17:32:31 +0000825{
826#if HOST_HZ == TARGET_HZ
827 return ticks;
828#else
829 return ((int64_t)ticks * TARGET_HZ) / HOST_HZ;
830#endif
831}
832
bellard579a97f2007-11-11 14:26:47 +0000833static inline abi_long host_to_target_rusage(abi_ulong target_addr,
834 const struct rusage *rusage)
bellardb4091862003-05-16 15:39:34 +0000835{
pbrook53a59602006-03-25 19:31:22 +0000836 struct target_rusage *target_rusage;
837
bellard579a97f2007-11-11 14:26:47 +0000838 if (!lock_user_struct(VERIFY_WRITE, target_rusage, target_addr, 0))
839 return -TARGET_EFAULT;
bellardb4091862003-05-16 15:39:34 +0000840 target_rusage->ru_utime.tv_sec = tswapl(rusage->ru_utime.tv_sec);
841 target_rusage->ru_utime.tv_usec = tswapl(rusage->ru_utime.tv_usec);
842 target_rusage->ru_stime.tv_sec = tswapl(rusage->ru_stime.tv_sec);
843 target_rusage->ru_stime.tv_usec = tswapl(rusage->ru_stime.tv_usec);
844 target_rusage->ru_maxrss = tswapl(rusage->ru_maxrss);
845 target_rusage->ru_ixrss = tswapl(rusage->ru_ixrss);
846 target_rusage->ru_idrss = tswapl(rusage->ru_idrss);
847 target_rusage->ru_isrss = tswapl(rusage->ru_isrss);
848 target_rusage->ru_minflt = tswapl(rusage->ru_minflt);
849 target_rusage->ru_majflt = tswapl(rusage->ru_majflt);
850 target_rusage->ru_nswap = tswapl(rusage->ru_nswap);
851 target_rusage->ru_inblock = tswapl(rusage->ru_inblock);
852 target_rusage->ru_oublock = tswapl(rusage->ru_oublock);
853 target_rusage->ru_msgsnd = tswapl(rusage->ru_msgsnd);
854 target_rusage->ru_msgrcv = tswapl(rusage->ru_msgrcv);
855 target_rusage->ru_nsignals = tswapl(rusage->ru_nsignals);
856 target_rusage->ru_nvcsw = tswapl(rusage->ru_nvcsw);
857 target_rusage->ru_nivcsw = tswapl(rusage->ru_nivcsw);
pbrook53a59602006-03-25 19:31:22 +0000858 unlock_user_struct(target_rusage, target_addr, 1);
bellard579a97f2007-11-11 14:26:47 +0000859
860 return 0;
bellardb4091862003-05-16 15:39:34 +0000861}
862
takasi-y@ops.dti.ne.jp81bbe902010-04-12 04:07:35 +0900863static inline rlim_t target_to_host_rlim(target_ulong target_rlim)
864{
865 if (target_rlim == TARGET_RLIM_INFINITY)
866 return RLIM_INFINITY;
867 else
868 return tswapl(target_rlim);
869}
870
871static inline target_ulong host_to_target_rlim(rlim_t rlim)
872{
873 if (rlim == RLIM_INFINITY || rlim != (target_long)rlim)
874 return TARGET_RLIM_INFINITY;
875 else
876 return tswapl(rlim);
877}
878
ths788f5ec2007-12-09 02:37:05 +0000879static inline abi_long copy_from_user_timeval(struct timeval *tv,
880 abi_ulong target_tv_addr)
bellard31e31b82003-02-18 22:55:36 +0000881{
pbrook53a59602006-03-25 19:31:22 +0000882 struct target_timeval *target_tv;
883
ths788f5ec2007-12-09 02:37:05 +0000884 if (!lock_user_struct(VERIFY_READ, target_tv, target_tv_addr, 1))
bellard579a97f2007-11-11 14:26:47 +0000885 return -TARGET_EFAULT;
ths788f5ec2007-12-09 02:37:05 +0000886
887 __get_user(tv->tv_sec, &target_tv->tv_sec);
888 __get_user(tv->tv_usec, &target_tv->tv_usec);
889
890 unlock_user_struct(target_tv, target_tv_addr, 0);
bellard579a97f2007-11-11 14:26:47 +0000891
892 return 0;
bellard31e31b82003-02-18 22:55:36 +0000893}
894
ths788f5ec2007-12-09 02:37:05 +0000895static inline abi_long copy_to_user_timeval(abi_ulong target_tv_addr,
896 const struct timeval *tv)
bellard31e31b82003-02-18 22:55:36 +0000897{
pbrook53a59602006-03-25 19:31:22 +0000898 struct target_timeval *target_tv;
899
ths788f5ec2007-12-09 02:37:05 +0000900 if (!lock_user_struct(VERIFY_WRITE, target_tv, target_tv_addr, 0))
bellard579a97f2007-11-11 14:26:47 +0000901 return -TARGET_EFAULT;
ths788f5ec2007-12-09 02:37:05 +0000902
903 __put_user(tv->tv_sec, &target_tv->tv_sec);
904 __put_user(tv->tv_usec, &target_tv->tv_usec);
905
906 unlock_user_struct(target_tv, target_tv_addr, 1);
bellard579a97f2007-11-11 14:26:47 +0000907
908 return 0;
bellard31e31b82003-02-18 22:55:36 +0000909}
910
Nathan Froyd8ec9cf82009-07-22 09:14:36 -0700911#if defined(TARGET_NR_mq_open) && defined(__NR_mq_open)
912#include <mqueue.h>
913
aurel3224e10032009-04-15 16:11:43 +0000914static inline abi_long copy_from_user_mq_attr(struct mq_attr *attr,
915 abi_ulong target_mq_attr_addr)
916{
917 struct target_mq_attr *target_mq_attr;
918
919 if (!lock_user_struct(VERIFY_READ, target_mq_attr,
920 target_mq_attr_addr, 1))
921 return -TARGET_EFAULT;
922
923 __get_user(attr->mq_flags, &target_mq_attr->mq_flags);
924 __get_user(attr->mq_maxmsg, &target_mq_attr->mq_maxmsg);
925 __get_user(attr->mq_msgsize, &target_mq_attr->mq_msgsize);
926 __get_user(attr->mq_curmsgs, &target_mq_attr->mq_curmsgs);
927
928 unlock_user_struct(target_mq_attr, target_mq_attr_addr, 0);
929
930 return 0;
931}
932
933static inline abi_long copy_to_user_mq_attr(abi_ulong target_mq_attr_addr,
934 const struct mq_attr *attr)
935{
936 struct target_mq_attr *target_mq_attr;
937
938 if (!lock_user_struct(VERIFY_WRITE, target_mq_attr,
939 target_mq_attr_addr, 0))
940 return -TARGET_EFAULT;
941
942 __put_user(attr->mq_flags, &target_mq_attr->mq_flags);
943 __put_user(attr->mq_maxmsg, &target_mq_attr->mq_maxmsg);
944 __put_user(attr->mq_msgsize, &target_mq_attr->mq_msgsize);
945 __put_user(attr->mq_curmsgs, &target_mq_attr->mq_curmsgs);
946
947 unlock_user_struct(target_mq_attr, target_mq_attr_addr, 1);
948
949 return 0;
950}
Nathan Froyd8ec9cf82009-07-22 09:14:36 -0700951#endif
bellard31e31b82003-02-18 22:55:36 +0000952
ths0da46a62007-10-20 20:23:07 +0000953/* do_select() must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +0000954static abi_long do_select(int n,
ths26edcf42007-12-09 02:25:24 +0000955 abi_ulong rfd_addr, abi_ulong wfd_addr,
956 abi_ulong efd_addr, abi_ulong target_tv_addr)
bellard31e31b82003-02-18 22:55:36 +0000957{
958 fd_set rfds, wfds, efds;
959 fd_set *rfds_ptr, *wfds_ptr, *efds_ptr;
960 struct timeval tv, *tv_ptr;
blueswir1992f48a2007-10-14 16:27:31 +0000961 abi_long ret;
bellard31e31b82003-02-18 22:55:36 +0000962
ths26edcf42007-12-09 02:25:24 +0000963 if (rfd_addr) {
964 if (copy_from_user_fdset(&rfds, rfd_addr, n))
965 return -TARGET_EFAULT;
966 rfds_ptr = &rfds;
pbrook53a59602006-03-25 19:31:22 +0000967 } else {
pbrook53a59602006-03-25 19:31:22 +0000968 rfds_ptr = NULL;
969 }
ths26edcf42007-12-09 02:25:24 +0000970 if (wfd_addr) {
971 if (copy_from_user_fdset(&wfds, wfd_addr, n))
972 return -TARGET_EFAULT;
973 wfds_ptr = &wfds;
pbrook53a59602006-03-25 19:31:22 +0000974 } else {
pbrook53a59602006-03-25 19:31:22 +0000975 wfds_ptr = NULL;
976 }
ths26edcf42007-12-09 02:25:24 +0000977 if (efd_addr) {
978 if (copy_from_user_fdset(&efds, efd_addr, n))
979 return -TARGET_EFAULT;
980 efds_ptr = &efds;
pbrook53a59602006-03-25 19:31:22 +0000981 } else {
pbrook53a59602006-03-25 19:31:22 +0000982 efds_ptr = NULL;
983 }
ths3b46e622007-09-17 08:09:54 +0000984
ths26edcf42007-12-09 02:25:24 +0000985 if (target_tv_addr) {
ths788f5ec2007-12-09 02:37:05 +0000986 if (copy_from_user_timeval(&tv, target_tv_addr))
987 return -TARGET_EFAULT;
bellard31e31b82003-02-18 22:55:36 +0000988 tv_ptr = &tv;
989 } else {
990 tv_ptr = NULL;
991 }
ths26edcf42007-12-09 02:25:24 +0000992
bellard31e31b82003-02-18 22:55:36 +0000993 ret = get_errno(select(n, rfds_ptr, wfds_ptr, efds_ptr, tv_ptr));
pbrook53a59602006-03-25 19:31:22 +0000994
ths26edcf42007-12-09 02:25:24 +0000995 if (!is_error(ret)) {
996 if (rfd_addr && copy_to_user_fdset(rfd_addr, &rfds, n))
997 return -TARGET_EFAULT;
998 if (wfd_addr && copy_to_user_fdset(wfd_addr, &wfds, n))
999 return -TARGET_EFAULT;
1000 if (efd_addr && copy_to_user_fdset(efd_addr, &efds, n))
1001 return -TARGET_EFAULT;
bellard31e31b82003-02-18 22:55:36 +00001002
ths788f5ec2007-12-09 02:37:05 +00001003 if (target_tv_addr && copy_to_user_timeval(target_tv_addr, &tv))
1004 return -TARGET_EFAULT;
bellard31e31b82003-02-18 22:55:36 +00001005 }
bellard579a97f2007-11-11 14:26:47 +00001006
bellard31e31b82003-02-18 22:55:36 +00001007 return ret;
1008}
1009
Riku Voipio099d6b02009-05-05 12:10:04 +03001010static abi_long do_pipe2(int host_pipe[], int flags)
1011{
1012#ifdef CONFIG_PIPE2
1013 return pipe2(host_pipe, flags);
1014#else
1015 return -ENOSYS;
1016#endif
1017}
1018
Richard Hendersonfb41a662010-05-03 10:07:52 -07001019static abi_long do_pipe(void *cpu_env, abi_ulong pipedes,
1020 int flags, int is_pipe2)
Riku Voipio099d6b02009-05-05 12:10:04 +03001021{
1022 int host_pipe[2];
1023 abi_long ret;
1024 ret = flags ? do_pipe2(host_pipe, flags) : pipe(host_pipe);
1025
1026 if (is_error(ret))
1027 return get_errno(ret);
Richard Hendersonfb41a662010-05-03 10:07:52 -07001028
1029 /* Several targets have special calling conventions for the original
1030 pipe syscall, but didn't replicate this into the pipe2 syscall. */
1031 if (!is_pipe2) {
1032#if defined(TARGET_ALPHA)
1033 ((CPUAlphaState *)cpu_env)->ir[IR_A4] = host_pipe[1];
1034 return host_pipe[0];
1035#elif defined(TARGET_MIPS)
1036 ((CPUMIPSState*)cpu_env)->active_tc.gpr[3] = host_pipe[1];
1037 return host_pipe[0];
1038#elif defined(TARGET_SH4)
takasi-y@ops.dti.ne.jp597c0212010-02-18 00:35:03 +09001039 ((CPUSH4State*)cpu_env)->gregs[1] = host_pipe[1];
Richard Hendersonfb41a662010-05-03 10:07:52 -07001040 return host_pipe[0];
takasi-y@ops.dti.ne.jp597c0212010-02-18 00:35:03 +09001041#endif
Richard Hendersonfb41a662010-05-03 10:07:52 -07001042 }
1043
Riku Voipio099d6b02009-05-05 12:10:04 +03001044 if (put_user_s32(host_pipe[0], pipedes)
1045 || put_user_s32(host_pipe[1], pipedes + sizeof(host_pipe[0])))
1046 return -TARGET_EFAULT;
Riku Voipio099d6b02009-05-05 12:10:04 +03001047 return get_errno(ret);
1048}
1049
Lionel Landwerlinb975b832009-04-25 23:30:19 +02001050static inline abi_long target_to_host_ip_mreq(struct ip_mreqn *mreqn,
1051 abi_ulong target_addr,
1052 socklen_t len)
1053{
1054 struct target_ip_mreqn *target_smreqn;
1055
1056 target_smreqn = lock_user(VERIFY_READ, target_addr, len, 1);
1057 if (!target_smreqn)
1058 return -TARGET_EFAULT;
1059 mreqn->imr_multiaddr.s_addr = target_smreqn->imr_multiaddr.s_addr;
1060 mreqn->imr_address.s_addr = target_smreqn->imr_address.s_addr;
1061 if (len == sizeof(struct target_ip_mreqn))
1062 mreqn->imr_ifindex = tswapl(target_smreqn->imr_ifindex);
1063 unlock_user(target_smreqn, target_addr, 0);
1064
1065 return 0;
1066}
1067
bellard579a97f2007-11-11 14:26:47 +00001068static inline abi_long target_to_host_sockaddr(struct sockaddr *addr,
1069 abi_ulong target_addr,
1070 socklen_t len)
bellard7854b052003-03-29 17:22:23 +00001071{
aurel32607175e2009-04-15 16:11:59 +00001072 const socklen_t unix_maxlen = sizeof (struct sockaddr_un);
1073 sa_family_t sa_family;
pbrook53a59602006-03-25 19:31:22 +00001074 struct target_sockaddr *target_saddr;
1075
bellard579a97f2007-11-11 14:26:47 +00001076 target_saddr = lock_user(VERIFY_READ, target_addr, len, 1);
1077 if (!target_saddr)
1078 return -TARGET_EFAULT;
aurel32607175e2009-04-15 16:11:59 +00001079
1080 sa_family = tswap16(target_saddr->sa_family);
1081
1082 /* Oops. The caller might send a incomplete sun_path; sun_path
1083 * must be terminated by \0 (see the manual page), but
1084 * unfortunately it is quite common to specify sockaddr_un
1085 * length as "strlen(x->sun_path)" while it should be
1086 * "strlen(...) + 1". We'll fix that here if needed.
1087 * Linux kernel has a similar feature.
1088 */
1089
1090 if (sa_family == AF_UNIX) {
1091 if (len < unix_maxlen && len > 0) {
1092 char *cp = (char*)target_saddr;
1093
1094 if ( cp[len-1] && !cp[len] )
1095 len++;
1096 }
1097 if (len > unix_maxlen)
1098 len = unix_maxlen;
1099 }
1100
pbrook53a59602006-03-25 19:31:22 +00001101 memcpy(addr, target_saddr, len);
aurel32607175e2009-04-15 16:11:59 +00001102 addr->sa_family = sa_family;
pbrook53a59602006-03-25 19:31:22 +00001103 unlock_user(target_saddr, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00001104
1105 return 0;
bellard7854b052003-03-29 17:22:23 +00001106}
1107
bellard579a97f2007-11-11 14:26:47 +00001108static inline abi_long host_to_target_sockaddr(abi_ulong target_addr,
1109 struct sockaddr *addr,
1110 socklen_t len)
bellard7854b052003-03-29 17:22:23 +00001111{
pbrook53a59602006-03-25 19:31:22 +00001112 struct target_sockaddr *target_saddr;
1113
bellard579a97f2007-11-11 14:26:47 +00001114 target_saddr = lock_user(VERIFY_WRITE, target_addr, len, 0);
1115 if (!target_saddr)
1116 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00001117 memcpy(target_saddr, addr, len);
1118 target_saddr->sa_family = tswap16(addr->sa_family);
1119 unlock_user(target_saddr, target_addr, len);
bellard579a97f2007-11-11 14:26:47 +00001120
1121 return 0;
bellard7854b052003-03-29 17:22:23 +00001122}
1123
pbrook53a59602006-03-25 19:31:22 +00001124/* ??? Should this also swap msgh->name? */
bellard5a4a8982007-11-11 17:39:18 +00001125static inline abi_long target_to_host_cmsg(struct msghdr *msgh,
1126 struct target_msghdr *target_msgh)
bellard7854b052003-03-29 17:22:23 +00001127{
1128 struct cmsghdr *cmsg = CMSG_FIRSTHDR(msgh);
bellard5a4a8982007-11-11 17:39:18 +00001129 abi_long msg_controllen;
1130 abi_ulong target_cmsg_addr;
1131 struct target_cmsghdr *target_cmsg;
bellard7854b052003-03-29 17:22:23 +00001132 socklen_t space = 0;
bellard5a4a8982007-11-11 17:39:18 +00001133
1134 msg_controllen = tswapl(target_msgh->msg_controllen);
1135 if (msg_controllen < sizeof (struct target_cmsghdr))
1136 goto the_end;
1137 target_cmsg_addr = tswapl(target_msgh->msg_control);
1138 target_cmsg = lock_user(VERIFY_READ, target_cmsg_addr, msg_controllen, 1);
1139 if (!target_cmsg)
1140 return -TARGET_EFAULT;
bellard7854b052003-03-29 17:22:23 +00001141
1142 while (cmsg && target_cmsg) {
1143 void *data = CMSG_DATA(cmsg);
1144 void *target_data = TARGET_CMSG_DATA(target_cmsg);
1145
ths5fafdf22007-09-16 21:08:06 +00001146 int len = tswapl(target_cmsg->cmsg_len)
bellard7854b052003-03-29 17:22:23 +00001147 - TARGET_CMSG_ALIGN(sizeof (struct target_cmsghdr));
1148
1149 space += CMSG_SPACE(len);
1150 if (space > msgh->msg_controllen) {
1151 space -= CMSG_SPACE(len);
bellard31febb72005-12-18 20:03:27 +00001152 gemu_log("Host cmsg overflow\n");
bellard7854b052003-03-29 17:22:23 +00001153 break;
1154 }
1155
1156 cmsg->cmsg_level = tswap32(target_cmsg->cmsg_level);
1157 cmsg->cmsg_type = tswap32(target_cmsg->cmsg_type);
1158 cmsg->cmsg_len = CMSG_LEN(len);
1159
bellard3532fa72006-06-24 15:06:03 +00001160 if (cmsg->cmsg_level != TARGET_SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS) {
bellard7854b052003-03-29 17:22:23 +00001161 gemu_log("Unsupported ancillary data: %d/%d\n", cmsg->cmsg_level, cmsg->cmsg_type);
1162 memcpy(data, target_data, len);
1163 } else {
1164 int *fd = (int *)data;
1165 int *target_fd = (int *)target_data;
1166 int i, numfds = len / sizeof(int);
1167
1168 for (i = 0; i < numfds; i++)
1169 fd[i] = tswap32(target_fd[i]);
1170 }
1171
1172 cmsg = CMSG_NXTHDR(msgh, cmsg);
1173 target_cmsg = TARGET_CMSG_NXTHDR(target_msgh, target_cmsg);
1174 }
bellard5a4a8982007-11-11 17:39:18 +00001175 unlock_user(target_cmsg, target_cmsg_addr, 0);
1176 the_end:
bellard7854b052003-03-29 17:22:23 +00001177 msgh->msg_controllen = space;
bellard5a4a8982007-11-11 17:39:18 +00001178 return 0;
bellard7854b052003-03-29 17:22:23 +00001179}
1180
pbrook53a59602006-03-25 19:31:22 +00001181/* ??? Should this also swap msgh->name? */
bellard5a4a8982007-11-11 17:39:18 +00001182static inline abi_long host_to_target_cmsg(struct target_msghdr *target_msgh,
1183 struct msghdr *msgh)
bellard7854b052003-03-29 17:22:23 +00001184{
1185 struct cmsghdr *cmsg = CMSG_FIRSTHDR(msgh);
bellard5a4a8982007-11-11 17:39:18 +00001186 abi_long msg_controllen;
1187 abi_ulong target_cmsg_addr;
1188 struct target_cmsghdr *target_cmsg;
bellard7854b052003-03-29 17:22:23 +00001189 socklen_t space = 0;
1190
bellard5a4a8982007-11-11 17:39:18 +00001191 msg_controllen = tswapl(target_msgh->msg_controllen);
1192 if (msg_controllen < sizeof (struct target_cmsghdr))
1193 goto the_end;
1194 target_cmsg_addr = tswapl(target_msgh->msg_control);
1195 target_cmsg = lock_user(VERIFY_WRITE, target_cmsg_addr, msg_controllen, 0);
1196 if (!target_cmsg)
1197 return -TARGET_EFAULT;
1198
bellard7854b052003-03-29 17:22:23 +00001199 while (cmsg && target_cmsg) {
1200 void *data = CMSG_DATA(cmsg);
1201 void *target_data = TARGET_CMSG_DATA(target_cmsg);
1202
1203 int len = cmsg->cmsg_len - CMSG_ALIGN(sizeof (struct cmsghdr));
1204
1205 space += TARGET_CMSG_SPACE(len);
bellard5a4a8982007-11-11 17:39:18 +00001206 if (space > msg_controllen) {
bellard7854b052003-03-29 17:22:23 +00001207 space -= TARGET_CMSG_SPACE(len);
bellard31febb72005-12-18 20:03:27 +00001208 gemu_log("Target cmsg overflow\n");
bellard7854b052003-03-29 17:22:23 +00001209 break;
1210 }
1211
1212 target_cmsg->cmsg_level = tswap32(cmsg->cmsg_level);
1213 target_cmsg->cmsg_type = tswap32(cmsg->cmsg_type);
1214 target_cmsg->cmsg_len = tswapl(TARGET_CMSG_LEN(len));
1215
bellard3532fa72006-06-24 15:06:03 +00001216 if (cmsg->cmsg_level != TARGET_SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS) {
bellard7854b052003-03-29 17:22:23 +00001217 gemu_log("Unsupported ancillary data: %d/%d\n", cmsg->cmsg_level, cmsg->cmsg_type);
1218 memcpy(target_data, data, len);
1219 } else {
1220 int *fd = (int *)data;
1221 int *target_fd = (int *)target_data;
1222 int i, numfds = len / sizeof(int);
1223
1224 for (i = 0; i < numfds; i++)
1225 target_fd[i] = tswap32(fd[i]);
1226 }
1227
1228 cmsg = CMSG_NXTHDR(msgh, cmsg);
1229 target_cmsg = TARGET_CMSG_NXTHDR(target_msgh, target_cmsg);
1230 }
bellard5a4a8982007-11-11 17:39:18 +00001231 unlock_user(target_cmsg, target_cmsg_addr, space);
1232 the_end:
1233 target_msgh->msg_controllen = tswapl(space);
1234 return 0;
bellard7854b052003-03-29 17:22:23 +00001235}
1236
ths0da46a62007-10-20 20:23:07 +00001237/* do_setsockopt() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001238static abi_long do_setsockopt(int sockfd, int level, int optname,
bellard2f619692007-11-16 10:46:05 +00001239 abi_ulong optval_addr, socklen_t optlen)
bellard7854b052003-03-29 17:22:23 +00001240{
blueswir1992f48a2007-10-14 16:27:31 +00001241 abi_long ret;
j_mayer32407102007-09-26 23:01:49 +00001242 int val;
Lionel Landwerlinb975b832009-04-25 23:30:19 +02001243 struct ip_mreqn *ip_mreq;
Lionel Landwerlin6e3cb582009-04-25 23:31:18 +02001244 struct ip_mreq_source *ip_mreq_source;
ths3b46e622007-09-17 08:09:54 +00001245
bellard8853f862004-02-22 14:57:26 +00001246 switch(level) {
1247 case SOL_TCP:
bellard7854b052003-03-29 17:22:23 +00001248 /* TCP options all take an 'int' value. */
bellard7854b052003-03-29 17:22:23 +00001249 if (optlen < sizeof(uint32_t))
ths0da46a62007-10-20 20:23:07 +00001250 return -TARGET_EINVAL;
ths3b46e622007-09-17 08:09:54 +00001251
bellard2f619692007-11-16 10:46:05 +00001252 if (get_user_u32(val, optval_addr))
1253 return -TARGET_EFAULT;
bellard8853f862004-02-22 14:57:26 +00001254 ret = get_errno(setsockopt(sockfd, level, optname, &val, sizeof(val)));
1255 break;
1256 case SOL_IP:
1257 switch(optname) {
bellard2efbe912005-07-23 15:10:20 +00001258 case IP_TOS:
1259 case IP_TTL:
bellard8853f862004-02-22 14:57:26 +00001260 case IP_HDRINCL:
bellard2efbe912005-07-23 15:10:20 +00001261 case IP_ROUTER_ALERT:
1262 case IP_RECVOPTS:
1263 case IP_RETOPTS:
1264 case IP_PKTINFO:
1265 case IP_MTU_DISCOVER:
1266 case IP_RECVERR:
1267 case IP_RECVTOS:
1268#ifdef IP_FREEBIND
1269 case IP_FREEBIND:
1270#endif
1271 case IP_MULTICAST_TTL:
1272 case IP_MULTICAST_LOOP:
bellard8853f862004-02-22 14:57:26 +00001273 val = 0;
1274 if (optlen >= sizeof(uint32_t)) {
bellard2f619692007-11-16 10:46:05 +00001275 if (get_user_u32(val, optval_addr))
1276 return -TARGET_EFAULT;
bellard8853f862004-02-22 14:57:26 +00001277 } else if (optlen >= 1) {
bellard2f619692007-11-16 10:46:05 +00001278 if (get_user_u8(val, optval_addr))
1279 return -TARGET_EFAULT;
bellard8853f862004-02-22 14:57:26 +00001280 }
1281 ret = get_errno(setsockopt(sockfd, level, optname, &val, sizeof(val)));
1282 break;
Lionel Landwerlinb975b832009-04-25 23:30:19 +02001283 case IP_ADD_MEMBERSHIP:
1284 case IP_DROP_MEMBERSHIP:
1285 if (optlen < sizeof (struct target_ip_mreq) ||
1286 optlen > sizeof (struct target_ip_mreqn))
1287 return -TARGET_EINVAL;
1288
1289 ip_mreq = (struct ip_mreqn *) alloca(optlen);
1290 target_to_host_ip_mreq(ip_mreq, optval_addr, optlen);
1291 ret = get_errno(setsockopt(sockfd, level, optname, ip_mreq, optlen));
1292 break;
1293
Lionel Landwerlin6e3cb582009-04-25 23:31:18 +02001294 case IP_BLOCK_SOURCE:
1295 case IP_UNBLOCK_SOURCE:
1296 case IP_ADD_SOURCE_MEMBERSHIP:
1297 case IP_DROP_SOURCE_MEMBERSHIP:
1298 if (optlen != sizeof (struct target_ip_mreq_source))
1299 return -TARGET_EINVAL;
1300
1301 ip_mreq_source = lock_user(VERIFY_READ, optval_addr, optlen, 1);
1302 ret = get_errno(setsockopt(sockfd, level, optname, ip_mreq_source, optlen));
1303 unlock_user (ip_mreq_source, optval_addr, 0);
1304 break;
1305
bellard8853f862004-02-22 14:57:26 +00001306 default:
1307 goto unimplemented;
1308 }
1309 break;
bellard3532fa72006-06-24 15:06:03 +00001310 case TARGET_SOL_SOCKET:
bellard8853f862004-02-22 14:57:26 +00001311 switch (optname) {
1312 /* Options with 'int' argument. */
bellard3532fa72006-06-24 15:06:03 +00001313 case TARGET_SO_DEBUG:
1314 optname = SO_DEBUG;
1315 break;
1316 case TARGET_SO_REUSEADDR:
1317 optname = SO_REUSEADDR;
1318 break;
1319 case TARGET_SO_TYPE:
1320 optname = SO_TYPE;
1321 break;
1322 case TARGET_SO_ERROR:
1323 optname = SO_ERROR;
1324 break;
1325 case TARGET_SO_DONTROUTE:
1326 optname = SO_DONTROUTE;
1327 break;
1328 case TARGET_SO_BROADCAST:
1329 optname = SO_BROADCAST;
1330 break;
1331 case TARGET_SO_SNDBUF:
1332 optname = SO_SNDBUF;
1333 break;
1334 case TARGET_SO_RCVBUF:
1335 optname = SO_RCVBUF;
1336 break;
1337 case TARGET_SO_KEEPALIVE:
1338 optname = SO_KEEPALIVE;
1339 break;
1340 case TARGET_SO_OOBINLINE:
1341 optname = SO_OOBINLINE;
1342 break;
1343 case TARGET_SO_NO_CHECK:
1344 optname = SO_NO_CHECK;
1345 break;
1346 case TARGET_SO_PRIORITY:
1347 optname = SO_PRIORITY;
1348 break;
bellard5e83e8e2005-03-01 22:32:06 +00001349#ifdef SO_BSDCOMPAT
bellard3532fa72006-06-24 15:06:03 +00001350 case TARGET_SO_BSDCOMPAT:
1351 optname = SO_BSDCOMPAT;
1352 break;
bellard5e83e8e2005-03-01 22:32:06 +00001353#endif
bellard3532fa72006-06-24 15:06:03 +00001354 case TARGET_SO_PASSCRED:
1355 optname = SO_PASSCRED;
1356 break;
1357 case TARGET_SO_TIMESTAMP:
1358 optname = SO_TIMESTAMP;
1359 break;
1360 case TARGET_SO_RCVLOWAT:
1361 optname = SO_RCVLOWAT;
1362 break;
1363 case TARGET_SO_RCVTIMEO:
1364 optname = SO_RCVTIMEO;
1365 break;
1366 case TARGET_SO_SNDTIMEO:
1367 optname = SO_SNDTIMEO;
1368 break;
bellard8853f862004-02-22 14:57:26 +00001369 break;
1370 default:
1371 goto unimplemented;
1372 }
bellard3532fa72006-06-24 15:06:03 +00001373 if (optlen < sizeof(uint32_t))
bellard2f619692007-11-16 10:46:05 +00001374 return -TARGET_EINVAL;
bellard3532fa72006-06-24 15:06:03 +00001375
bellard2f619692007-11-16 10:46:05 +00001376 if (get_user_u32(val, optval_addr))
1377 return -TARGET_EFAULT;
bellard3532fa72006-06-24 15:06:03 +00001378 ret = get_errno(setsockopt(sockfd, SOL_SOCKET, optname, &val, sizeof(val)));
bellard8853f862004-02-22 14:57:26 +00001379 break;
bellard7854b052003-03-29 17:22:23 +00001380 default:
bellard8853f862004-02-22 14:57:26 +00001381 unimplemented:
1382 gemu_log("Unsupported setsockopt level=%d optname=%d \n", level, optname);
ths6fa13c12007-12-18 02:41:04 +00001383 ret = -TARGET_ENOPROTOOPT;
bellard7854b052003-03-29 17:22:23 +00001384 }
bellard8853f862004-02-22 14:57:26 +00001385 return ret;
bellard7854b052003-03-29 17:22:23 +00001386}
1387
ths0da46a62007-10-20 20:23:07 +00001388/* do_getsockopt() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001389static abi_long do_getsockopt(int sockfd, int level, int optname,
bellard2f619692007-11-16 10:46:05 +00001390 abi_ulong optval_addr, abi_ulong optlen)
bellard7854b052003-03-29 17:22:23 +00001391{
blueswir1992f48a2007-10-14 16:27:31 +00001392 abi_long ret;
blueswir1b55266b2008-09-20 08:07:15 +00001393 int len, val;
1394 socklen_t lv;
bellard8853f862004-02-22 14:57:26 +00001395
1396 switch(level) {
bellard3532fa72006-06-24 15:06:03 +00001397 case TARGET_SOL_SOCKET:
Jamie Lentinf3b974c2010-11-26 15:04:08 +02001398 level = SOL_SOCKET;
1399 switch (optname) {
1400 /* These don't just return a single integer */
1401 case TARGET_SO_LINGER:
1402 case TARGET_SO_RCVTIMEO:
1403 case TARGET_SO_SNDTIMEO:
1404 case TARGET_SO_PEERCRED:
1405 case TARGET_SO_PEERNAME:
1406 goto unimplemented;
1407 /* Options with 'int' argument. */
1408 case TARGET_SO_DEBUG:
1409 optname = SO_DEBUG;
1410 goto int_case;
1411 case TARGET_SO_REUSEADDR:
1412 optname = SO_REUSEADDR;
1413 goto int_case;
1414 case TARGET_SO_TYPE:
1415 optname = SO_TYPE;
1416 goto int_case;
1417 case TARGET_SO_ERROR:
1418 optname = SO_ERROR;
1419 goto int_case;
1420 case TARGET_SO_DONTROUTE:
1421 optname = SO_DONTROUTE;
1422 goto int_case;
1423 case TARGET_SO_BROADCAST:
1424 optname = SO_BROADCAST;
1425 goto int_case;
1426 case TARGET_SO_SNDBUF:
1427 optname = SO_SNDBUF;
1428 goto int_case;
1429 case TARGET_SO_RCVBUF:
1430 optname = SO_RCVBUF;
1431 goto int_case;
1432 case TARGET_SO_KEEPALIVE:
1433 optname = SO_KEEPALIVE;
1434 goto int_case;
1435 case TARGET_SO_OOBINLINE:
1436 optname = SO_OOBINLINE;
1437 goto int_case;
1438 case TARGET_SO_NO_CHECK:
1439 optname = SO_NO_CHECK;
1440 goto int_case;
1441 case TARGET_SO_PRIORITY:
1442 optname = SO_PRIORITY;
1443 goto int_case;
1444#ifdef SO_BSDCOMPAT
1445 case TARGET_SO_BSDCOMPAT:
1446 optname = SO_BSDCOMPAT;
1447 goto int_case;
1448#endif
1449 case TARGET_SO_PASSCRED:
1450 optname = SO_PASSCRED;
1451 goto int_case;
1452 case TARGET_SO_TIMESTAMP:
1453 optname = SO_TIMESTAMP;
1454 goto int_case;
1455 case TARGET_SO_RCVLOWAT:
1456 optname = SO_RCVLOWAT;
1457 goto int_case;
bellard8853f862004-02-22 14:57:26 +00001458 default:
bellard2efbe912005-07-23 15:10:20 +00001459 goto int_case;
1460 }
1461 break;
1462 case SOL_TCP:
1463 /* TCP options all take an 'int' value. */
1464 int_case:
bellard2f619692007-11-16 10:46:05 +00001465 if (get_user_u32(len, optlen))
1466 return -TARGET_EFAULT;
bellard2efbe912005-07-23 15:10:20 +00001467 if (len < 0)
ths0da46a62007-10-20 20:23:07 +00001468 return -TARGET_EINVAL;
Mike Frysinger73160d92011-02-07 01:05:49 -05001469 lv = sizeof(lv);
bellard2efbe912005-07-23 15:10:20 +00001470 ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
1471 if (ret < 0)
1472 return ret;
bellard2efbe912005-07-23 15:10:20 +00001473 if (len > lv)
1474 len = lv;
bellard2f619692007-11-16 10:46:05 +00001475 if (len == 4) {
1476 if (put_user_u32(val, optval_addr))
1477 return -TARGET_EFAULT;
1478 } else {
1479 if (put_user_u8(val, optval_addr))
1480 return -TARGET_EFAULT;
Jamie Lentinf3b974c2010-11-26 15:04:08 +02001481 }
bellard2f619692007-11-16 10:46:05 +00001482 if (put_user_u32(len, optlen))
1483 return -TARGET_EFAULT;
bellard2efbe912005-07-23 15:10:20 +00001484 break;
1485 case SOL_IP:
1486 switch(optname) {
1487 case IP_TOS:
1488 case IP_TTL:
1489 case IP_HDRINCL:
1490 case IP_ROUTER_ALERT:
1491 case IP_RECVOPTS:
1492 case IP_RETOPTS:
1493 case IP_PKTINFO:
1494 case IP_MTU_DISCOVER:
1495 case IP_RECVERR:
1496 case IP_RECVTOS:
1497#ifdef IP_FREEBIND
1498 case IP_FREEBIND:
1499#endif
1500 case IP_MULTICAST_TTL:
1501 case IP_MULTICAST_LOOP:
bellard2f619692007-11-16 10:46:05 +00001502 if (get_user_u32(len, optlen))
1503 return -TARGET_EFAULT;
bellard8853f862004-02-22 14:57:26 +00001504 if (len < 0)
ths0da46a62007-10-20 20:23:07 +00001505 return -TARGET_EINVAL;
Mike Frysinger73160d92011-02-07 01:05:49 -05001506 lv = sizeof(lv);
bellard8853f862004-02-22 14:57:26 +00001507 ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
1508 if (ret < 0)
1509 return ret;
bellard2efbe912005-07-23 15:10:20 +00001510 if (len < sizeof(int) && len > 0 && val >= 0 && val < 255) {
bellard2efbe912005-07-23 15:10:20 +00001511 len = 1;
bellard2f619692007-11-16 10:46:05 +00001512 if (put_user_u32(len, optlen)
1513 || put_user_u8(val, optval_addr))
1514 return -TARGET_EFAULT;
bellard2efbe912005-07-23 15:10:20 +00001515 } else {
bellard2efbe912005-07-23 15:10:20 +00001516 if (len > sizeof(int))
1517 len = sizeof(int);
bellard2f619692007-11-16 10:46:05 +00001518 if (put_user_u32(len, optlen)
1519 || put_user_u32(val, optval_addr))
1520 return -TARGET_EFAULT;
bellard2efbe912005-07-23 15:10:20 +00001521 }
bellard8853f862004-02-22 14:57:26 +00001522 break;
bellard2efbe912005-07-23 15:10:20 +00001523 default:
thsc02f4992007-12-18 02:39:59 +00001524 ret = -TARGET_ENOPROTOOPT;
1525 break;
bellard8853f862004-02-22 14:57:26 +00001526 }
1527 break;
1528 default:
1529 unimplemented:
1530 gemu_log("getsockopt level=%d optname=%d not yet supported\n",
1531 level, optname);
thsc02f4992007-12-18 02:39:59 +00001532 ret = -TARGET_EOPNOTSUPP;
bellard8853f862004-02-22 14:57:26 +00001533 break;
1534 }
1535 return ret;
bellard7854b052003-03-29 17:22:23 +00001536}
1537
bellard579a97f2007-11-11 14:26:47 +00001538/* FIXME
1539 * lock_iovec()/unlock_iovec() have a return code of 0 for success where
1540 * other lock functions have a return code of 0 for failure.
1541 */
1542static abi_long lock_iovec(int type, struct iovec *vec, abi_ulong target_addr,
1543 int count, int copy)
pbrook53a59602006-03-25 19:31:22 +00001544{
1545 struct target_iovec *target_vec;
blueswir1992f48a2007-10-14 16:27:31 +00001546 abi_ulong base;
balrogd732dcb2008-10-28 10:21:03 +00001547 int i;
pbrook53a59602006-03-25 19:31:22 +00001548
bellard579a97f2007-11-11 14:26:47 +00001549 target_vec = lock_user(VERIFY_READ, target_addr, count * sizeof(struct target_iovec), 1);
1550 if (!target_vec)
1551 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00001552 for(i = 0;i < count; i++) {
1553 base = tswapl(target_vec[i].iov_base);
1554 vec[i].iov_len = tswapl(target_vec[i].iov_len);
bellard41df8412008-02-04 22:26:57 +00001555 if (vec[i].iov_len != 0) {
1556 vec[i].iov_base = lock_user(type, base, vec[i].iov_len, copy);
balrogd732dcb2008-10-28 10:21:03 +00001557 /* Don't check lock_user return value. We must call writev even
1558 if a element has invalid base address. */
bellard41df8412008-02-04 22:26:57 +00001559 } else {
1560 /* zero length pointer is ignored */
1561 vec[i].iov_base = NULL;
1562 }
pbrook53a59602006-03-25 19:31:22 +00001563 }
1564 unlock_user (target_vec, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00001565 return 0;
pbrook53a59602006-03-25 19:31:22 +00001566}
1567
bellard579a97f2007-11-11 14:26:47 +00001568static abi_long unlock_iovec(struct iovec *vec, abi_ulong target_addr,
1569 int count, int copy)
pbrook53a59602006-03-25 19:31:22 +00001570{
1571 struct target_iovec *target_vec;
blueswir1992f48a2007-10-14 16:27:31 +00001572 abi_ulong base;
pbrook53a59602006-03-25 19:31:22 +00001573 int i;
1574
bellard579a97f2007-11-11 14:26:47 +00001575 target_vec = lock_user(VERIFY_READ, target_addr, count * sizeof(struct target_iovec), 1);
1576 if (!target_vec)
1577 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00001578 for(i = 0;i < count; i++) {
balrogd732dcb2008-10-28 10:21:03 +00001579 if (target_vec[i].iov_base) {
1580 base = tswapl(target_vec[i].iov_base);
1581 unlock_user(vec[i].iov_base, base, copy ? vec[i].iov_len : 0);
1582 }
pbrook53a59602006-03-25 19:31:22 +00001583 }
1584 unlock_user (target_vec, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00001585
1586 return 0;
pbrook53a59602006-03-25 19:31:22 +00001587}
1588
ths0da46a62007-10-20 20:23:07 +00001589/* do_socket() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001590static abi_long do_socket(int domain, int type, int protocol)
bellard3532fa72006-06-24 15:06:03 +00001591{
1592#if defined(TARGET_MIPS)
1593 switch(type) {
1594 case TARGET_SOCK_DGRAM:
1595 type = SOCK_DGRAM;
1596 break;
1597 case TARGET_SOCK_STREAM:
1598 type = SOCK_STREAM;
1599 break;
1600 case TARGET_SOCK_RAW:
1601 type = SOCK_RAW;
1602 break;
1603 case TARGET_SOCK_RDM:
1604 type = SOCK_RDM;
1605 break;
1606 case TARGET_SOCK_SEQPACKET:
1607 type = SOCK_SEQPACKET;
1608 break;
1609 case TARGET_SOCK_PACKET:
1610 type = SOCK_PACKET;
1611 break;
1612 }
1613#endif
balrog12bc92a2007-10-30 21:06:14 +00001614 if (domain == PF_NETLINK)
1615 return -EAFNOSUPPORT; /* do not NETLINK socket connections possible */
bellard3532fa72006-06-24 15:06:03 +00001616 return get_errno(socket(domain, type, protocol));
1617}
1618
ths0da46a62007-10-20 20:23:07 +00001619/* do_bind() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001620static abi_long do_bind(int sockfd, abi_ulong target_addr,
1621 socklen_t addrlen)
bellard3532fa72006-06-24 15:06:03 +00001622{
aurel328f7aeaf2009-01-30 19:47:57 +00001623 void *addr;
Arnaud Patard917507b2009-06-19 10:44:45 +03001624 abi_long ret;
aurel328f7aeaf2009-01-30 19:47:57 +00001625
Blue Swirl38724252010-09-18 05:53:14 +00001626 if ((int)addrlen < 0) {
aurel328f7aeaf2009-01-30 19:47:57 +00001627 return -TARGET_EINVAL;
Blue Swirl38724252010-09-18 05:53:14 +00001628 }
aurel328f7aeaf2009-01-30 19:47:57 +00001629
aurel32607175e2009-04-15 16:11:59 +00001630 addr = alloca(addrlen+1);
ths3b46e622007-09-17 08:09:54 +00001631
Arnaud Patard917507b2009-06-19 10:44:45 +03001632 ret = target_to_host_sockaddr(addr, target_addr, addrlen);
1633 if (ret)
1634 return ret;
1635
bellard3532fa72006-06-24 15:06:03 +00001636 return get_errno(bind(sockfd, addr, addrlen));
1637}
1638
ths0da46a62007-10-20 20:23:07 +00001639/* do_connect() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001640static abi_long do_connect(int sockfd, abi_ulong target_addr,
1641 socklen_t addrlen)
bellard3532fa72006-06-24 15:06:03 +00001642{
aurel328f7aeaf2009-01-30 19:47:57 +00001643 void *addr;
Arnaud Patard917507b2009-06-19 10:44:45 +03001644 abi_long ret;
aurel328f7aeaf2009-01-30 19:47:57 +00001645
Blue Swirl38724252010-09-18 05:53:14 +00001646 if ((int)addrlen < 0) {
aurel328f7aeaf2009-01-30 19:47:57 +00001647 return -TARGET_EINVAL;
Blue Swirl38724252010-09-18 05:53:14 +00001648 }
aurel328f7aeaf2009-01-30 19:47:57 +00001649
1650 addr = alloca(addrlen);
ths3b46e622007-09-17 08:09:54 +00001651
Arnaud Patard917507b2009-06-19 10:44:45 +03001652 ret = target_to_host_sockaddr(addr, target_addr, addrlen);
1653 if (ret)
1654 return ret;
1655
bellard3532fa72006-06-24 15:06:03 +00001656 return get_errno(connect(sockfd, addr, addrlen));
1657}
1658
ths0da46a62007-10-20 20:23:07 +00001659/* do_sendrecvmsg() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001660static abi_long do_sendrecvmsg(int fd, abi_ulong target_msg,
1661 int flags, int send)
bellard3532fa72006-06-24 15:06:03 +00001662{
balrog6de645c2008-10-28 10:26:29 +00001663 abi_long ret, len;
bellard3532fa72006-06-24 15:06:03 +00001664 struct target_msghdr *msgp;
1665 struct msghdr msg;
1666 int count;
1667 struct iovec *vec;
blueswir1992f48a2007-10-14 16:27:31 +00001668 abi_ulong target_vec;
bellard3532fa72006-06-24 15:06:03 +00001669
bellard579a97f2007-11-11 14:26:47 +00001670 /* FIXME */
1671 if (!lock_user_struct(send ? VERIFY_READ : VERIFY_WRITE,
1672 msgp,
1673 target_msg,
1674 send ? 1 : 0))
1675 return -TARGET_EFAULT;
bellard3532fa72006-06-24 15:06:03 +00001676 if (msgp->msg_name) {
1677 msg.msg_namelen = tswap32(msgp->msg_namelen);
1678 msg.msg_name = alloca(msg.msg_namelen);
Arnaud Patard917507b2009-06-19 10:44:45 +03001679 ret = target_to_host_sockaddr(msg.msg_name, tswapl(msgp->msg_name),
bellard3532fa72006-06-24 15:06:03 +00001680 msg.msg_namelen);
Arnaud Patard917507b2009-06-19 10:44:45 +03001681 if (ret) {
1682 unlock_user_struct(msgp, target_msg, send ? 0 : 1);
1683 return ret;
1684 }
bellard3532fa72006-06-24 15:06:03 +00001685 } else {
1686 msg.msg_name = NULL;
1687 msg.msg_namelen = 0;
1688 }
1689 msg.msg_controllen = 2 * tswapl(msgp->msg_controllen);
1690 msg.msg_control = alloca(msg.msg_controllen);
1691 msg.msg_flags = tswap32(msgp->msg_flags);
ths3b46e622007-09-17 08:09:54 +00001692
bellard3532fa72006-06-24 15:06:03 +00001693 count = tswapl(msgp->msg_iovlen);
1694 vec = alloca(count * sizeof(struct iovec));
1695 target_vec = tswapl(msgp->msg_iov);
bellard579a97f2007-11-11 14:26:47 +00001696 lock_iovec(send ? VERIFY_READ : VERIFY_WRITE, vec, target_vec, count, send);
bellard3532fa72006-06-24 15:06:03 +00001697 msg.msg_iovlen = count;
1698 msg.msg_iov = vec;
ths3b46e622007-09-17 08:09:54 +00001699
bellard3532fa72006-06-24 15:06:03 +00001700 if (send) {
bellard5a4a8982007-11-11 17:39:18 +00001701 ret = target_to_host_cmsg(&msg, msgp);
1702 if (ret == 0)
1703 ret = get_errno(sendmsg(fd, &msg, flags));
bellard3532fa72006-06-24 15:06:03 +00001704 } else {
1705 ret = get_errno(recvmsg(fd, &msg, flags));
balrog6de645c2008-10-28 10:26:29 +00001706 if (!is_error(ret)) {
1707 len = ret;
bellard5a4a8982007-11-11 17:39:18 +00001708 ret = host_to_target_cmsg(msgp, &msg);
balrog6de645c2008-10-28 10:26:29 +00001709 if (!is_error(ret))
1710 ret = len;
1711 }
bellard3532fa72006-06-24 15:06:03 +00001712 }
1713 unlock_iovec(vec, target_vec, count, !send);
bellard579a97f2007-11-11 14:26:47 +00001714 unlock_user_struct(msgp, target_msg, send ? 0 : 1);
bellard3532fa72006-06-24 15:06:03 +00001715 return ret;
1716}
1717
ths0da46a62007-10-20 20:23:07 +00001718/* do_accept() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001719static abi_long do_accept(int fd, abi_ulong target_addr,
bellard2f619692007-11-16 10:46:05 +00001720 abi_ulong target_addrlen_addr)
pbrook1be9e1d2006-11-19 15:26:04 +00001721{
bellard2f619692007-11-16 10:46:05 +00001722 socklen_t addrlen;
1723 void *addr;
blueswir1992f48a2007-10-14 16:27:31 +00001724 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00001725
Arnaud Patard917507b2009-06-19 10:44:45 +03001726 if (target_addr == 0)
1727 return get_errno(accept(fd, NULL, NULL));
1728
1729 /* linux returns EINVAL if addrlen pointer is invalid */
bellard2f619692007-11-16 10:46:05 +00001730 if (get_user_u32(addrlen, target_addrlen_addr))
Arnaud Patard917507b2009-06-19 10:44:45 +03001731 return -TARGET_EINVAL;
bellard2f619692007-11-16 10:46:05 +00001732
Blue Swirl38724252010-09-18 05:53:14 +00001733 if ((int)addrlen < 0) {
aurel328f7aeaf2009-01-30 19:47:57 +00001734 return -TARGET_EINVAL;
Blue Swirl38724252010-09-18 05:53:14 +00001735 }
aurel328f7aeaf2009-01-30 19:47:57 +00001736
Arnaud Patard917507b2009-06-19 10:44:45 +03001737 if (!access_ok(VERIFY_WRITE, target_addr, addrlen))
1738 return -TARGET_EINVAL;
1739
bellard2f619692007-11-16 10:46:05 +00001740 addr = alloca(addrlen);
1741
pbrook1be9e1d2006-11-19 15:26:04 +00001742 ret = get_errno(accept(fd, addr, &addrlen));
1743 if (!is_error(ret)) {
1744 host_to_target_sockaddr(target_addr, addr, addrlen);
bellard2f619692007-11-16 10:46:05 +00001745 if (put_user_u32(addrlen, target_addrlen_addr))
1746 ret = -TARGET_EFAULT;
pbrook1be9e1d2006-11-19 15:26:04 +00001747 }
1748 return ret;
1749}
1750
ths0da46a62007-10-20 20:23:07 +00001751/* do_getpeername() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001752static abi_long do_getpeername(int fd, abi_ulong target_addr,
bellard2f619692007-11-16 10:46:05 +00001753 abi_ulong target_addrlen_addr)
pbrook1be9e1d2006-11-19 15:26:04 +00001754{
bellard2f619692007-11-16 10:46:05 +00001755 socklen_t addrlen;
1756 void *addr;
blueswir1992f48a2007-10-14 16:27:31 +00001757 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00001758
bellard2f619692007-11-16 10:46:05 +00001759 if (get_user_u32(addrlen, target_addrlen_addr))
1760 return -TARGET_EFAULT;
1761
Blue Swirl38724252010-09-18 05:53:14 +00001762 if ((int)addrlen < 0) {
aurel328f7aeaf2009-01-30 19:47:57 +00001763 return -TARGET_EINVAL;
Blue Swirl38724252010-09-18 05:53:14 +00001764 }
aurel328f7aeaf2009-01-30 19:47:57 +00001765
Arnaud Patard917507b2009-06-19 10:44:45 +03001766 if (!access_ok(VERIFY_WRITE, target_addr, addrlen))
1767 return -TARGET_EFAULT;
1768
bellard2f619692007-11-16 10:46:05 +00001769 addr = alloca(addrlen);
1770
pbrook1be9e1d2006-11-19 15:26:04 +00001771 ret = get_errno(getpeername(fd, addr, &addrlen));
1772 if (!is_error(ret)) {
1773 host_to_target_sockaddr(target_addr, addr, addrlen);
bellard2f619692007-11-16 10:46:05 +00001774 if (put_user_u32(addrlen, target_addrlen_addr))
1775 ret = -TARGET_EFAULT;
pbrook1be9e1d2006-11-19 15:26:04 +00001776 }
1777 return ret;
1778}
1779
ths0da46a62007-10-20 20:23:07 +00001780/* do_getsockname() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001781static abi_long do_getsockname(int fd, abi_ulong target_addr,
bellard2f619692007-11-16 10:46:05 +00001782 abi_ulong target_addrlen_addr)
pbrook1be9e1d2006-11-19 15:26:04 +00001783{
bellard2f619692007-11-16 10:46:05 +00001784 socklen_t addrlen;
1785 void *addr;
blueswir1992f48a2007-10-14 16:27:31 +00001786 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00001787
bellard2f619692007-11-16 10:46:05 +00001788 if (get_user_u32(addrlen, target_addrlen_addr))
1789 return -TARGET_EFAULT;
1790
Blue Swirl38724252010-09-18 05:53:14 +00001791 if ((int)addrlen < 0) {
aurel328f7aeaf2009-01-30 19:47:57 +00001792 return -TARGET_EINVAL;
Blue Swirl38724252010-09-18 05:53:14 +00001793 }
aurel328f7aeaf2009-01-30 19:47:57 +00001794
Arnaud Patard917507b2009-06-19 10:44:45 +03001795 if (!access_ok(VERIFY_WRITE, target_addr, addrlen))
1796 return -TARGET_EFAULT;
1797
bellard2f619692007-11-16 10:46:05 +00001798 addr = alloca(addrlen);
1799
pbrook1be9e1d2006-11-19 15:26:04 +00001800 ret = get_errno(getsockname(fd, addr, &addrlen));
1801 if (!is_error(ret)) {
1802 host_to_target_sockaddr(target_addr, addr, addrlen);
bellard2f619692007-11-16 10:46:05 +00001803 if (put_user_u32(addrlen, target_addrlen_addr))
1804 ret = -TARGET_EFAULT;
pbrook1be9e1d2006-11-19 15:26:04 +00001805 }
1806 return ret;
1807}
1808
ths0da46a62007-10-20 20:23:07 +00001809/* do_socketpair() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001810static abi_long do_socketpair(int domain, int type, int protocol,
bellard2f619692007-11-16 10:46:05 +00001811 abi_ulong target_tab_addr)
pbrook1be9e1d2006-11-19 15:26:04 +00001812{
1813 int tab[2];
blueswir1992f48a2007-10-14 16:27:31 +00001814 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00001815
1816 ret = get_errno(socketpair(domain, type, protocol, tab));
1817 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +00001818 if (put_user_s32(tab[0], target_tab_addr)
1819 || put_user_s32(tab[1], target_tab_addr + sizeof(tab[0])))
1820 ret = -TARGET_EFAULT;
pbrook1be9e1d2006-11-19 15:26:04 +00001821 }
1822 return ret;
1823}
1824
ths0da46a62007-10-20 20:23:07 +00001825/* do_sendto() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001826static abi_long do_sendto(int fd, abi_ulong msg, size_t len, int flags,
1827 abi_ulong target_addr, socklen_t addrlen)
pbrook1be9e1d2006-11-19 15:26:04 +00001828{
1829 void *addr;
1830 void *host_msg;
blueswir1992f48a2007-10-14 16:27:31 +00001831 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00001832
Blue Swirl38724252010-09-18 05:53:14 +00001833 if ((int)addrlen < 0) {
aurel328f7aeaf2009-01-30 19:47:57 +00001834 return -TARGET_EINVAL;
Blue Swirl38724252010-09-18 05:53:14 +00001835 }
aurel328f7aeaf2009-01-30 19:47:57 +00001836
bellard579a97f2007-11-11 14:26:47 +00001837 host_msg = lock_user(VERIFY_READ, msg, len, 1);
1838 if (!host_msg)
1839 return -TARGET_EFAULT;
pbrook1be9e1d2006-11-19 15:26:04 +00001840 if (target_addr) {
1841 addr = alloca(addrlen);
Arnaud Patard917507b2009-06-19 10:44:45 +03001842 ret = target_to_host_sockaddr(addr, target_addr, addrlen);
1843 if (ret) {
1844 unlock_user(host_msg, msg, 0);
1845 return ret;
1846 }
pbrook1be9e1d2006-11-19 15:26:04 +00001847 ret = get_errno(sendto(fd, host_msg, len, flags, addr, addrlen));
1848 } else {
1849 ret = get_errno(send(fd, host_msg, len, flags));
1850 }
1851 unlock_user(host_msg, msg, 0);
1852 return ret;
1853}
1854
ths0da46a62007-10-20 20:23:07 +00001855/* do_recvfrom() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001856static abi_long do_recvfrom(int fd, abi_ulong msg, size_t len, int flags,
1857 abi_ulong target_addr,
1858 abi_ulong target_addrlen)
pbrook1be9e1d2006-11-19 15:26:04 +00001859{
1860 socklen_t addrlen;
1861 void *addr;
1862 void *host_msg;
blueswir1992f48a2007-10-14 16:27:31 +00001863 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00001864
bellard579a97f2007-11-11 14:26:47 +00001865 host_msg = lock_user(VERIFY_WRITE, msg, len, 0);
1866 if (!host_msg)
1867 return -TARGET_EFAULT;
pbrook1be9e1d2006-11-19 15:26:04 +00001868 if (target_addr) {
bellard2f619692007-11-16 10:46:05 +00001869 if (get_user_u32(addrlen, target_addrlen)) {
1870 ret = -TARGET_EFAULT;
1871 goto fail;
1872 }
Blue Swirl38724252010-09-18 05:53:14 +00001873 if ((int)addrlen < 0) {
aurel328f7aeaf2009-01-30 19:47:57 +00001874 ret = -TARGET_EINVAL;
1875 goto fail;
1876 }
pbrook1be9e1d2006-11-19 15:26:04 +00001877 addr = alloca(addrlen);
1878 ret = get_errno(recvfrom(fd, host_msg, len, flags, addr, &addrlen));
1879 } else {
1880 addr = NULL; /* To keep compiler quiet. */
1881 ret = get_errno(recv(fd, host_msg, len, flags));
1882 }
1883 if (!is_error(ret)) {
1884 if (target_addr) {
1885 host_to_target_sockaddr(target_addr, addr, addrlen);
bellard2f619692007-11-16 10:46:05 +00001886 if (put_user_u32(addrlen, target_addrlen)) {
1887 ret = -TARGET_EFAULT;
1888 goto fail;
1889 }
pbrook1be9e1d2006-11-19 15:26:04 +00001890 }
1891 unlock_user(host_msg, msg, len);
1892 } else {
bellard2f619692007-11-16 10:46:05 +00001893fail:
pbrook1be9e1d2006-11-19 15:26:04 +00001894 unlock_user(host_msg, msg, 0);
1895 }
1896 return ret;
1897}
1898
j_mayer32407102007-09-26 23:01:49 +00001899#ifdef TARGET_NR_socketcall
ths0da46a62007-10-20 20:23:07 +00001900/* do_socketcall() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001901static abi_long do_socketcall(int num, abi_ulong vptr)
bellard31e31b82003-02-18 22:55:36 +00001902{
blueswir1992f48a2007-10-14 16:27:31 +00001903 abi_long ret;
1904 const int n = sizeof(abi_ulong);
bellard31e31b82003-02-18 22:55:36 +00001905
1906 switch(num) {
1907 case SOCKOP_socket:
bellard7854b052003-03-29 17:22:23 +00001908 {
Ulrich Hecht98818182009-07-03 17:09:28 +02001909 abi_ulong domain, type, protocol;
bellard2f619692007-11-16 10:46:05 +00001910
Ulrich Hecht98818182009-07-03 17:09:28 +02001911 if (get_user_ual(domain, vptr)
1912 || get_user_ual(type, vptr + n)
1913 || get_user_ual(protocol, vptr + 2 * n))
bellard2f619692007-11-16 10:46:05 +00001914 return -TARGET_EFAULT;
1915
bellard3532fa72006-06-24 15:06:03 +00001916 ret = do_socket(domain, type, protocol);
bellard7854b052003-03-29 17:22:23 +00001917 }
bellard31e31b82003-02-18 22:55:36 +00001918 break;
1919 case SOCKOP_bind:
bellard7854b052003-03-29 17:22:23 +00001920 {
Ulrich Hecht98818182009-07-03 17:09:28 +02001921 abi_ulong sockfd;
bellard2f619692007-11-16 10:46:05 +00001922 abi_ulong target_addr;
1923 socklen_t addrlen;
1924
Ulrich Hecht98818182009-07-03 17:09:28 +02001925 if (get_user_ual(sockfd, vptr)
bellard2f619692007-11-16 10:46:05 +00001926 || get_user_ual(target_addr, vptr + n)
Ulrich Hecht98818182009-07-03 17:09:28 +02001927 || get_user_ual(addrlen, vptr + 2 * n))
bellard2f619692007-11-16 10:46:05 +00001928 return -TARGET_EFAULT;
1929
bellard3532fa72006-06-24 15:06:03 +00001930 ret = do_bind(sockfd, target_addr, addrlen);
bellard7854b052003-03-29 17:22:23 +00001931 }
bellard31e31b82003-02-18 22:55:36 +00001932 break;
1933 case SOCKOP_connect:
bellard7854b052003-03-29 17:22:23 +00001934 {
Ulrich Hecht98818182009-07-03 17:09:28 +02001935 abi_ulong sockfd;
bellard2f619692007-11-16 10:46:05 +00001936 abi_ulong target_addr;
1937 socklen_t addrlen;
1938
Ulrich Hecht98818182009-07-03 17:09:28 +02001939 if (get_user_ual(sockfd, vptr)
bellard2f619692007-11-16 10:46:05 +00001940 || get_user_ual(target_addr, vptr + n)
Ulrich Hecht98818182009-07-03 17:09:28 +02001941 || get_user_ual(addrlen, vptr + 2 * n))
bellard2f619692007-11-16 10:46:05 +00001942 return -TARGET_EFAULT;
1943
bellard3532fa72006-06-24 15:06:03 +00001944 ret = do_connect(sockfd, target_addr, addrlen);
bellard7854b052003-03-29 17:22:23 +00001945 }
bellard31e31b82003-02-18 22:55:36 +00001946 break;
1947 case SOCKOP_listen:
bellard7854b052003-03-29 17:22:23 +00001948 {
Ulrich Hecht98818182009-07-03 17:09:28 +02001949 abi_ulong sockfd, backlog;
bellard2f619692007-11-16 10:46:05 +00001950
Ulrich Hecht98818182009-07-03 17:09:28 +02001951 if (get_user_ual(sockfd, vptr)
1952 || get_user_ual(backlog, vptr + n))
bellard2f619692007-11-16 10:46:05 +00001953 return -TARGET_EFAULT;
1954
bellard7854b052003-03-29 17:22:23 +00001955 ret = get_errno(listen(sockfd, backlog));
1956 }
bellard31e31b82003-02-18 22:55:36 +00001957 break;
1958 case SOCKOP_accept:
1959 {
Ulrich Hecht98818182009-07-03 17:09:28 +02001960 abi_ulong sockfd;
bellard2f619692007-11-16 10:46:05 +00001961 abi_ulong target_addr, target_addrlen;
1962
Ulrich Hecht98818182009-07-03 17:09:28 +02001963 if (get_user_ual(sockfd, vptr)
bellard2f619692007-11-16 10:46:05 +00001964 || get_user_ual(target_addr, vptr + n)
Ulrich Hecht98818182009-07-03 17:09:28 +02001965 || get_user_ual(target_addrlen, vptr + 2 * n))
bellard2f619692007-11-16 10:46:05 +00001966 return -TARGET_EFAULT;
1967
pbrook1be9e1d2006-11-19 15:26:04 +00001968 ret = do_accept(sockfd, target_addr, target_addrlen);
bellard31e31b82003-02-18 22:55:36 +00001969 }
1970 break;
1971 case SOCKOP_getsockname:
1972 {
Ulrich Hecht98818182009-07-03 17:09:28 +02001973 abi_ulong sockfd;
bellard2f619692007-11-16 10:46:05 +00001974 abi_ulong target_addr, target_addrlen;
1975
Ulrich Hecht98818182009-07-03 17:09:28 +02001976 if (get_user_ual(sockfd, vptr)
bellard2f619692007-11-16 10:46:05 +00001977 || get_user_ual(target_addr, vptr + n)
Ulrich Hecht98818182009-07-03 17:09:28 +02001978 || get_user_ual(target_addrlen, vptr + 2 * n))
bellard2f619692007-11-16 10:46:05 +00001979 return -TARGET_EFAULT;
1980
pbrook1be9e1d2006-11-19 15:26:04 +00001981 ret = do_getsockname(sockfd, target_addr, target_addrlen);
bellard31e31b82003-02-18 22:55:36 +00001982 }
1983 break;
1984 case SOCKOP_getpeername:
1985 {
Ulrich Hecht98818182009-07-03 17:09:28 +02001986 abi_ulong sockfd;
bellard2f619692007-11-16 10:46:05 +00001987 abi_ulong target_addr, target_addrlen;
1988
Ulrich Hecht98818182009-07-03 17:09:28 +02001989 if (get_user_ual(sockfd, vptr)
bellard2f619692007-11-16 10:46:05 +00001990 || get_user_ual(target_addr, vptr + n)
Ulrich Hecht98818182009-07-03 17:09:28 +02001991 || get_user_ual(target_addrlen, vptr + 2 * n))
bellard2f619692007-11-16 10:46:05 +00001992 return -TARGET_EFAULT;
1993
pbrook1be9e1d2006-11-19 15:26:04 +00001994 ret = do_getpeername(sockfd, target_addr, target_addrlen);
bellard31e31b82003-02-18 22:55:36 +00001995 }
1996 break;
1997 case SOCKOP_socketpair:
1998 {
Ulrich Hecht98818182009-07-03 17:09:28 +02001999 abi_ulong domain, type, protocol;
bellard2f619692007-11-16 10:46:05 +00002000 abi_ulong tab;
2001
Ulrich Hecht98818182009-07-03 17:09:28 +02002002 if (get_user_ual(domain, vptr)
2003 || get_user_ual(type, vptr + n)
2004 || get_user_ual(protocol, vptr + 2 * n)
bellard2f619692007-11-16 10:46:05 +00002005 || get_user_ual(tab, vptr + 3 * n))
2006 return -TARGET_EFAULT;
2007
pbrook1be9e1d2006-11-19 15:26:04 +00002008 ret = do_socketpair(domain, type, protocol, tab);
bellard31e31b82003-02-18 22:55:36 +00002009 }
2010 break;
2011 case SOCKOP_send:
bellard7854b052003-03-29 17:22:23 +00002012 {
Ulrich Hecht98818182009-07-03 17:09:28 +02002013 abi_ulong sockfd;
bellard2f619692007-11-16 10:46:05 +00002014 abi_ulong msg;
2015 size_t len;
Ulrich Hecht98818182009-07-03 17:09:28 +02002016 abi_ulong flags;
bellard2f619692007-11-16 10:46:05 +00002017
Ulrich Hecht98818182009-07-03 17:09:28 +02002018 if (get_user_ual(sockfd, vptr)
bellard2f619692007-11-16 10:46:05 +00002019 || get_user_ual(msg, vptr + n)
2020 || get_user_ual(len, vptr + 2 * n)
Ulrich Hecht98818182009-07-03 17:09:28 +02002021 || get_user_ual(flags, vptr + 3 * n))
bellard2f619692007-11-16 10:46:05 +00002022 return -TARGET_EFAULT;
2023
pbrook1be9e1d2006-11-19 15:26:04 +00002024 ret = do_sendto(sockfd, msg, len, flags, 0, 0);
bellard7854b052003-03-29 17:22:23 +00002025 }
bellard31e31b82003-02-18 22:55:36 +00002026 break;
2027 case SOCKOP_recv:
bellard7854b052003-03-29 17:22:23 +00002028 {
Ulrich Hecht98818182009-07-03 17:09:28 +02002029 abi_ulong sockfd;
bellard2f619692007-11-16 10:46:05 +00002030 abi_ulong msg;
2031 size_t len;
Ulrich Hecht98818182009-07-03 17:09:28 +02002032 abi_ulong flags;
bellard2f619692007-11-16 10:46:05 +00002033
Ulrich Hecht98818182009-07-03 17:09:28 +02002034 if (get_user_ual(sockfd, vptr)
bellard2f619692007-11-16 10:46:05 +00002035 || get_user_ual(msg, vptr + n)
2036 || get_user_ual(len, vptr + 2 * n)
Ulrich Hecht98818182009-07-03 17:09:28 +02002037 || get_user_ual(flags, vptr + 3 * n))
bellard2f619692007-11-16 10:46:05 +00002038 return -TARGET_EFAULT;
2039
pbrook1be9e1d2006-11-19 15:26:04 +00002040 ret = do_recvfrom(sockfd, msg, len, flags, 0, 0);
bellard7854b052003-03-29 17:22:23 +00002041 }
bellard31e31b82003-02-18 22:55:36 +00002042 break;
2043 case SOCKOP_sendto:
bellard7854b052003-03-29 17:22:23 +00002044 {
Ulrich Hecht98818182009-07-03 17:09:28 +02002045 abi_ulong sockfd;
bellard2f619692007-11-16 10:46:05 +00002046 abi_ulong msg;
2047 size_t len;
Ulrich Hecht98818182009-07-03 17:09:28 +02002048 abi_ulong flags;
bellard2f619692007-11-16 10:46:05 +00002049 abi_ulong addr;
2050 socklen_t addrlen;
2051
Ulrich Hecht98818182009-07-03 17:09:28 +02002052 if (get_user_ual(sockfd, vptr)
bellard2f619692007-11-16 10:46:05 +00002053 || get_user_ual(msg, vptr + n)
2054 || get_user_ual(len, vptr + 2 * n)
Ulrich Hecht98818182009-07-03 17:09:28 +02002055 || get_user_ual(flags, vptr + 3 * n)
bellard2f619692007-11-16 10:46:05 +00002056 || get_user_ual(addr, vptr + 4 * n)
Ulrich Hecht98818182009-07-03 17:09:28 +02002057 || get_user_ual(addrlen, vptr + 5 * n))
bellard2f619692007-11-16 10:46:05 +00002058 return -TARGET_EFAULT;
2059
pbrook1be9e1d2006-11-19 15:26:04 +00002060 ret = do_sendto(sockfd, msg, len, flags, addr, addrlen);
bellard7854b052003-03-29 17:22:23 +00002061 }
bellard31e31b82003-02-18 22:55:36 +00002062 break;
2063 case SOCKOP_recvfrom:
2064 {
Ulrich Hecht98818182009-07-03 17:09:28 +02002065 abi_ulong sockfd;
bellard2f619692007-11-16 10:46:05 +00002066 abi_ulong msg;
2067 size_t len;
Ulrich Hecht98818182009-07-03 17:09:28 +02002068 abi_ulong flags;
bellard2f619692007-11-16 10:46:05 +00002069 abi_ulong addr;
2070 socklen_t addrlen;
2071
Ulrich Hecht98818182009-07-03 17:09:28 +02002072 if (get_user_ual(sockfd, vptr)
bellard2f619692007-11-16 10:46:05 +00002073 || get_user_ual(msg, vptr + n)
2074 || get_user_ual(len, vptr + 2 * n)
Ulrich Hecht98818182009-07-03 17:09:28 +02002075 || get_user_ual(flags, vptr + 3 * n)
bellard2f619692007-11-16 10:46:05 +00002076 || get_user_ual(addr, vptr + 4 * n)
Ulrich Hecht98818182009-07-03 17:09:28 +02002077 || get_user_ual(addrlen, vptr + 5 * n))
bellard2f619692007-11-16 10:46:05 +00002078 return -TARGET_EFAULT;
2079
pbrook1be9e1d2006-11-19 15:26:04 +00002080 ret = do_recvfrom(sockfd, msg, len, flags, addr, addrlen);
bellard31e31b82003-02-18 22:55:36 +00002081 }
2082 break;
2083 case SOCKOP_shutdown:
bellard7854b052003-03-29 17:22:23 +00002084 {
Ulrich Hecht98818182009-07-03 17:09:28 +02002085 abi_ulong sockfd, how;
bellard2f619692007-11-16 10:46:05 +00002086
Ulrich Hecht98818182009-07-03 17:09:28 +02002087 if (get_user_ual(sockfd, vptr)
2088 || get_user_ual(how, vptr + n))
bellard2f619692007-11-16 10:46:05 +00002089 return -TARGET_EFAULT;
bellard7854b052003-03-29 17:22:23 +00002090
2091 ret = get_errno(shutdown(sockfd, how));
2092 }
bellard31e31b82003-02-18 22:55:36 +00002093 break;
2094 case SOCKOP_sendmsg:
2095 case SOCKOP_recvmsg:
bellard1a9353d2003-03-16 20:28:50 +00002096 {
Ulrich Hecht98818182009-07-03 17:09:28 +02002097 abi_ulong fd;
blueswir1992f48a2007-10-14 16:27:31 +00002098 abi_ulong target_msg;
Ulrich Hecht98818182009-07-03 17:09:28 +02002099 abi_ulong flags;
bellard1a9353d2003-03-16 20:28:50 +00002100
Ulrich Hecht98818182009-07-03 17:09:28 +02002101 if (get_user_ual(fd, vptr)
bellard2f619692007-11-16 10:46:05 +00002102 || get_user_ual(target_msg, vptr + n)
Ulrich Hecht98818182009-07-03 17:09:28 +02002103 || get_user_ual(flags, vptr + 2 * n))
bellard2f619692007-11-16 10:46:05 +00002104 return -TARGET_EFAULT;
bellard3532fa72006-06-24 15:06:03 +00002105
ths5fafdf22007-09-16 21:08:06 +00002106 ret = do_sendrecvmsg(fd, target_msg, flags,
bellard3532fa72006-06-24 15:06:03 +00002107 (num == SOCKOP_sendmsg));
bellard1a9353d2003-03-16 20:28:50 +00002108 }
2109 break;
bellard31e31b82003-02-18 22:55:36 +00002110 case SOCKOP_setsockopt:
bellard7854b052003-03-29 17:22:23 +00002111 {
Ulrich Hecht98818182009-07-03 17:09:28 +02002112 abi_ulong sockfd;
2113 abi_ulong level;
2114 abi_ulong optname;
bellard2f619692007-11-16 10:46:05 +00002115 abi_ulong optval;
2116 socklen_t optlen;
2117
Ulrich Hecht98818182009-07-03 17:09:28 +02002118 if (get_user_ual(sockfd, vptr)
2119 || get_user_ual(level, vptr + n)
2120 || get_user_ual(optname, vptr + 2 * n)
bellard2f619692007-11-16 10:46:05 +00002121 || get_user_ual(optval, vptr + 3 * n)
Ulrich Hecht98818182009-07-03 17:09:28 +02002122 || get_user_ual(optlen, vptr + 4 * n))
bellard2f619692007-11-16 10:46:05 +00002123 return -TARGET_EFAULT;
bellard7854b052003-03-29 17:22:23 +00002124
2125 ret = do_setsockopt(sockfd, level, optname, optval, optlen);
2126 }
2127 break;
bellard31e31b82003-02-18 22:55:36 +00002128 case SOCKOP_getsockopt:
bellard7854b052003-03-29 17:22:23 +00002129 {
Ulrich Hecht98818182009-07-03 17:09:28 +02002130 abi_ulong sockfd;
2131 abi_ulong level;
2132 abi_ulong optname;
bellard2f619692007-11-16 10:46:05 +00002133 abi_ulong optval;
2134 socklen_t optlen;
bellard7854b052003-03-29 17:22:23 +00002135
Ulrich Hecht98818182009-07-03 17:09:28 +02002136 if (get_user_ual(sockfd, vptr)
2137 || get_user_ual(level, vptr + n)
2138 || get_user_ual(optname, vptr + 2 * n)
bellard2f619692007-11-16 10:46:05 +00002139 || get_user_ual(optval, vptr + 3 * n)
Ulrich Hecht98818182009-07-03 17:09:28 +02002140 || get_user_ual(optlen, vptr + 4 * n))
bellard2f619692007-11-16 10:46:05 +00002141 return -TARGET_EFAULT;
2142
2143 ret = do_getsockopt(sockfd, level, optname, optval, optlen);
bellard7854b052003-03-29 17:22:23 +00002144 }
2145 break;
bellard31e31b82003-02-18 22:55:36 +00002146 default:
2147 gemu_log("Unsupported socketcall: %d\n", num);
ths0da46a62007-10-20 20:23:07 +00002148 ret = -TARGET_ENOSYS;
bellard31e31b82003-02-18 22:55:36 +00002149 break;
2150 }
2151 return ret;
2152}
j_mayer32407102007-09-26 23:01:49 +00002153#endif
bellard31e31b82003-02-18 22:55:36 +00002154
bellard8853f862004-02-22 14:57:26 +00002155#define N_SHM_REGIONS 32
2156
2157static struct shm_region {
bellard5a4a8982007-11-11 17:39:18 +00002158 abi_ulong start;
2159 abi_ulong size;
bellard8853f862004-02-22 14:57:26 +00002160} shm_regions[N_SHM_REGIONS];
2161
ths3eb6b042007-06-03 14:26:27 +00002162struct target_ipc_perm
2163{
blueswir1992f48a2007-10-14 16:27:31 +00002164 abi_long __key;
2165 abi_ulong uid;
2166 abi_ulong gid;
2167 abi_ulong cuid;
2168 abi_ulong cgid;
ths3eb6b042007-06-03 14:26:27 +00002169 unsigned short int mode;
2170 unsigned short int __pad1;
2171 unsigned short int __seq;
2172 unsigned short int __pad2;
blueswir1992f48a2007-10-14 16:27:31 +00002173 abi_ulong __unused1;
2174 abi_ulong __unused2;
ths3eb6b042007-06-03 14:26:27 +00002175};
2176
2177struct target_semid_ds
2178{
2179 struct target_ipc_perm sem_perm;
blueswir1992f48a2007-10-14 16:27:31 +00002180 abi_ulong sem_otime;
2181 abi_ulong __unused1;
2182 abi_ulong sem_ctime;
2183 abi_ulong __unused2;
2184 abi_ulong sem_nsems;
2185 abi_ulong __unused3;
2186 abi_ulong __unused4;
ths3eb6b042007-06-03 14:26:27 +00002187};
2188
bellard579a97f2007-11-11 14:26:47 +00002189static inline abi_long target_to_host_ipc_perm(struct ipc_perm *host_ip,
2190 abi_ulong target_addr)
ths3eb6b042007-06-03 14:26:27 +00002191{
2192 struct target_ipc_perm *target_ip;
2193 struct target_semid_ds *target_sd;
2194
bellard579a97f2007-11-11 14:26:47 +00002195 if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
2196 return -TARGET_EFAULT;
Michael S. Tsirkine8bbe362009-09-30 18:56:44 +00002197 target_ip = &(target_sd->sem_perm);
ths3eb6b042007-06-03 14:26:27 +00002198 host_ip->__key = tswapl(target_ip->__key);
2199 host_ip->uid = tswapl(target_ip->uid);
2200 host_ip->gid = tswapl(target_ip->gid);
2201 host_ip->cuid = tswapl(target_ip->cuid);
2202 host_ip->cgid = tswapl(target_ip->cgid);
2203 host_ip->mode = tswapl(target_ip->mode);
2204 unlock_user_struct(target_sd, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00002205 return 0;
ths3eb6b042007-06-03 14:26:27 +00002206}
2207
bellard579a97f2007-11-11 14:26:47 +00002208static inline abi_long host_to_target_ipc_perm(abi_ulong target_addr,
2209 struct ipc_perm *host_ip)
ths3eb6b042007-06-03 14:26:27 +00002210{
2211 struct target_ipc_perm *target_ip;
2212 struct target_semid_ds *target_sd;
2213
bellard579a97f2007-11-11 14:26:47 +00002214 if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
2215 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00002216 target_ip = &(target_sd->sem_perm);
2217 target_ip->__key = tswapl(host_ip->__key);
2218 target_ip->uid = tswapl(host_ip->uid);
2219 target_ip->gid = tswapl(host_ip->gid);
2220 target_ip->cuid = tswapl(host_ip->cuid);
2221 target_ip->cgid = tswapl(host_ip->cgid);
2222 target_ip->mode = tswapl(host_ip->mode);
2223 unlock_user_struct(target_sd, target_addr, 1);
bellard579a97f2007-11-11 14:26:47 +00002224 return 0;
ths3eb6b042007-06-03 14:26:27 +00002225}
2226
bellard579a97f2007-11-11 14:26:47 +00002227static inline abi_long target_to_host_semid_ds(struct semid_ds *host_sd,
2228 abi_ulong target_addr)
ths3eb6b042007-06-03 14:26:27 +00002229{
2230 struct target_semid_ds *target_sd;
2231
bellard579a97f2007-11-11 14:26:47 +00002232 if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
2233 return -TARGET_EFAULT;
aurel32e5289082009-04-18 16:16:12 +00002234 if (target_to_host_ipc_perm(&(host_sd->sem_perm),target_addr))
2235 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00002236 host_sd->sem_nsems = tswapl(target_sd->sem_nsems);
2237 host_sd->sem_otime = tswapl(target_sd->sem_otime);
2238 host_sd->sem_ctime = tswapl(target_sd->sem_ctime);
2239 unlock_user_struct(target_sd, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00002240 return 0;
ths3eb6b042007-06-03 14:26:27 +00002241}
2242
bellard579a97f2007-11-11 14:26:47 +00002243static inline abi_long host_to_target_semid_ds(abi_ulong target_addr,
2244 struct semid_ds *host_sd)
ths3eb6b042007-06-03 14:26:27 +00002245{
2246 struct target_semid_ds *target_sd;
2247
bellard579a97f2007-11-11 14:26:47 +00002248 if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
2249 return -TARGET_EFAULT;
aurel32e5289082009-04-18 16:16:12 +00002250 if (host_to_target_ipc_perm(target_addr,&(host_sd->sem_perm)))
2251 return -TARGET_EFAULT;;
ths3eb6b042007-06-03 14:26:27 +00002252 target_sd->sem_nsems = tswapl(host_sd->sem_nsems);
2253 target_sd->sem_otime = tswapl(host_sd->sem_otime);
2254 target_sd->sem_ctime = tswapl(host_sd->sem_ctime);
2255 unlock_user_struct(target_sd, target_addr, 1);
bellard579a97f2007-11-11 14:26:47 +00002256 return 0;
ths3eb6b042007-06-03 14:26:27 +00002257}
2258
aurel32e5289082009-04-18 16:16:12 +00002259struct target_seminfo {
2260 int semmap;
2261 int semmni;
2262 int semmns;
2263 int semmnu;
2264 int semmsl;
2265 int semopm;
2266 int semume;
2267 int semusz;
2268 int semvmx;
2269 int semaem;
2270};
2271
2272static inline abi_long host_to_target_seminfo(abi_ulong target_addr,
2273 struct seminfo *host_seminfo)
2274{
2275 struct target_seminfo *target_seminfo;
2276 if (!lock_user_struct(VERIFY_WRITE, target_seminfo, target_addr, 0))
2277 return -TARGET_EFAULT;
2278 __put_user(host_seminfo->semmap, &target_seminfo->semmap);
2279 __put_user(host_seminfo->semmni, &target_seminfo->semmni);
2280 __put_user(host_seminfo->semmns, &target_seminfo->semmns);
2281 __put_user(host_seminfo->semmnu, &target_seminfo->semmnu);
2282 __put_user(host_seminfo->semmsl, &target_seminfo->semmsl);
2283 __put_user(host_seminfo->semopm, &target_seminfo->semopm);
2284 __put_user(host_seminfo->semume, &target_seminfo->semume);
2285 __put_user(host_seminfo->semusz, &target_seminfo->semusz);
2286 __put_user(host_seminfo->semvmx, &target_seminfo->semvmx);
2287 __put_user(host_seminfo->semaem, &target_seminfo->semaem);
2288 unlock_user_struct(target_seminfo, target_addr, 1);
2289 return 0;
2290}
2291
thsfa294812007-02-02 22:05:00 +00002292union semun {
2293 int val;
ths3eb6b042007-06-03 14:26:27 +00002294 struct semid_ds *buf;
thsfa294812007-02-02 22:05:00 +00002295 unsigned short *array;
aurel32e5289082009-04-18 16:16:12 +00002296 struct seminfo *__buf;
thsfa294812007-02-02 22:05:00 +00002297};
2298
ths3eb6b042007-06-03 14:26:27 +00002299union target_semun {
2300 int val;
aurel32e5289082009-04-18 16:16:12 +00002301 abi_ulong buf;
2302 abi_ulong array;
2303 abi_ulong __buf;
ths3eb6b042007-06-03 14:26:27 +00002304};
2305
aurel32e5289082009-04-18 16:16:12 +00002306static inline abi_long target_to_host_semarray(int semid, unsigned short **host_array,
2307 abi_ulong target_addr)
ths3eb6b042007-06-03 14:26:27 +00002308{
aurel32e5289082009-04-18 16:16:12 +00002309 int nsems;
2310 unsigned short *array;
2311 union semun semun;
2312 struct semid_ds semid_ds;
2313 int i, ret;
ths3eb6b042007-06-03 14:26:27 +00002314
aurel32e5289082009-04-18 16:16:12 +00002315 semun.buf = &semid_ds;
2316
2317 ret = semctl(semid, 0, IPC_STAT, semun);
2318 if (ret == -1)
2319 return get_errno(ret);
2320
2321 nsems = semid_ds.sem_nsems;
2322
2323 *host_array = malloc(nsems*sizeof(unsigned short));
2324 array = lock_user(VERIFY_READ, target_addr,
2325 nsems*sizeof(unsigned short), 1);
2326 if (!array)
2327 return -TARGET_EFAULT;
2328
2329 for(i=0; i<nsems; i++) {
2330 __get_user((*host_array)[i], &array[i]);
ths3eb6b042007-06-03 14:26:27 +00002331 }
aurel32e5289082009-04-18 16:16:12 +00002332 unlock_user(array, target_addr, 0);
2333
bellard579a97f2007-11-11 14:26:47 +00002334 return 0;
ths3eb6b042007-06-03 14:26:27 +00002335}
2336
aurel32e5289082009-04-18 16:16:12 +00002337static inline abi_long host_to_target_semarray(int semid, abi_ulong target_addr,
2338 unsigned short **host_array)
ths3eb6b042007-06-03 14:26:27 +00002339{
aurel32e5289082009-04-18 16:16:12 +00002340 int nsems;
2341 unsigned short *array;
2342 union semun semun;
2343 struct semid_ds semid_ds;
2344 int i, ret;
ths3eb6b042007-06-03 14:26:27 +00002345
aurel32e5289082009-04-18 16:16:12 +00002346 semun.buf = &semid_ds;
2347
2348 ret = semctl(semid, 0, IPC_STAT, semun);
2349 if (ret == -1)
2350 return get_errno(ret);
2351
2352 nsems = semid_ds.sem_nsems;
2353
2354 array = lock_user(VERIFY_WRITE, target_addr,
2355 nsems*sizeof(unsigned short), 0);
2356 if (!array)
2357 return -TARGET_EFAULT;
2358
2359 for(i=0; i<nsems; i++) {
2360 __put_user((*host_array)[i], &array[i]);
ths3eb6b042007-06-03 14:26:27 +00002361 }
aurel32e5289082009-04-18 16:16:12 +00002362 free(*host_array);
2363 unlock_user(array, target_addr, 1);
2364
bellard579a97f2007-11-11 14:26:47 +00002365 return 0;
ths3eb6b042007-06-03 14:26:27 +00002366}
2367
aurel32e5289082009-04-18 16:16:12 +00002368static inline abi_long do_semctl(int semid, int semnum, int cmd,
2369 union target_semun target_su)
ths3eb6b042007-06-03 14:26:27 +00002370{
2371 union semun arg;
2372 struct semid_ds dsarg;
vibi sreenivasan7b8118e2009-06-19 13:34:39 +05302373 unsigned short *array = NULL;
aurel32e5289082009-04-18 16:16:12 +00002374 struct seminfo seminfo;
2375 abi_long ret = -TARGET_EINVAL;
2376 abi_long err;
2377 cmd &= 0xff;
ths3eb6b042007-06-03 14:26:27 +00002378
2379 switch( cmd ) {
2380 case GETVAL:
ths3eb6b042007-06-03 14:26:27 +00002381 case SETVAL:
aurel32e5289082009-04-18 16:16:12 +00002382 arg.val = tswapl(target_su.val);
2383 ret = get_errno(semctl(semid, semnum, cmd, arg));
2384 target_su.val = tswapl(arg.val);
ths3eb6b042007-06-03 14:26:27 +00002385 break;
2386 case GETALL:
ths3eb6b042007-06-03 14:26:27 +00002387 case SETALL:
aurel32e5289082009-04-18 16:16:12 +00002388 err = target_to_host_semarray(semid, &array, target_su.array);
2389 if (err)
2390 return err;
2391 arg.array = array;
2392 ret = get_errno(semctl(semid, semnum, cmd, arg));
2393 err = host_to_target_semarray(semid, target_su.array, &array);
2394 if (err)
2395 return err;
ths3eb6b042007-06-03 14:26:27 +00002396 break;
2397 case IPC_STAT:
ths3eb6b042007-06-03 14:26:27 +00002398 case IPC_SET:
aurel32e5289082009-04-18 16:16:12 +00002399 case SEM_STAT:
2400 err = target_to_host_semid_ds(&dsarg, target_su.buf);
2401 if (err)
2402 return err;
2403 arg.buf = &dsarg;
2404 ret = get_errno(semctl(semid, semnum, cmd, arg));
2405 err = host_to_target_semid_ds(target_su.buf, &dsarg);
2406 if (err)
2407 return err;
ths3eb6b042007-06-03 14:26:27 +00002408 break;
aurel32e5289082009-04-18 16:16:12 +00002409 case IPC_INFO:
2410 case SEM_INFO:
2411 arg.__buf = &seminfo;
2412 ret = get_errno(semctl(semid, semnum, cmd, arg));
2413 err = host_to_target_seminfo(target_su.__buf, &seminfo);
2414 if (err)
2415 return err;
2416 break;
2417 case IPC_RMID:
2418 case GETPID:
2419 case GETNCNT:
2420 case GETZCNT:
2421 ret = get_errno(semctl(semid, semnum, cmd, NULL));
2422 break;
ths3eb6b042007-06-03 14:26:27 +00002423 }
2424
2425 return ret;
2426}
2427
aurel32e5289082009-04-18 16:16:12 +00002428struct target_sembuf {
2429 unsigned short sem_num;
2430 short sem_op;
2431 short sem_flg;
2432};
2433
2434static inline abi_long target_to_host_sembuf(struct sembuf *host_sembuf,
2435 abi_ulong target_addr,
2436 unsigned nsops)
2437{
2438 struct target_sembuf *target_sembuf;
2439 int i;
2440
2441 target_sembuf = lock_user(VERIFY_READ, target_addr,
2442 nsops*sizeof(struct target_sembuf), 1);
2443 if (!target_sembuf)
2444 return -TARGET_EFAULT;
2445
2446 for(i=0; i<nsops; i++) {
2447 __get_user(host_sembuf[i].sem_num, &target_sembuf[i].sem_num);
2448 __get_user(host_sembuf[i].sem_op, &target_sembuf[i].sem_op);
2449 __get_user(host_sembuf[i].sem_flg, &target_sembuf[i].sem_flg);
2450 }
2451
2452 unlock_user(target_sembuf, target_addr, 0);
2453
2454 return 0;
2455}
2456
2457static inline abi_long do_semop(int semid, abi_long ptr, unsigned nsops)
2458{
2459 struct sembuf sops[nsops];
2460
2461 if (target_to_host_sembuf(sops, ptr, nsops))
2462 return -TARGET_EFAULT;
2463
2464 return semop(semid, sops, nsops);
2465}
2466
ths1bc012f2007-06-03 14:27:49 +00002467struct target_msqid_ds
2468{
aurel321c54ff92008-10-13 21:08:44 +00002469 struct target_ipc_perm msg_perm;
2470 abi_ulong msg_stime;
2471#if TARGET_ABI_BITS == 32
2472 abi_ulong __unused1;
2473#endif
2474 abi_ulong msg_rtime;
2475#if TARGET_ABI_BITS == 32
2476 abi_ulong __unused2;
2477#endif
2478 abi_ulong msg_ctime;
2479#if TARGET_ABI_BITS == 32
2480 abi_ulong __unused3;
2481#endif
2482 abi_ulong __msg_cbytes;
2483 abi_ulong msg_qnum;
2484 abi_ulong msg_qbytes;
2485 abi_ulong msg_lspid;
2486 abi_ulong msg_lrpid;
2487 abi_ulong __unused4;
2488 abi_ulong __unused5;
ths1bc012f2007-06-03 14:27:49 +00002489};
2490
bellard579a97f2007-11-11 14:26:47 +00002491static inline abi_long target_to_host_msqid_ds(struct msqid_ds *host_md,
2492 abi_ulong target_addr)
ths1bc012f2007-06-03 14:27:49 +00002493{
2494 struct target_msqid_ds *target_md;
2495
bellard579a97f2007-11-11 14:26:47 +00002496 if (!lock_user_struct(VERIFY_READ, target_md, target_addr, 1))
2497 return -TARGET_EFAULT;
aurel321c54ff92008-10-13 21:08:44 +00002498 if (target_to_host_ipc_perm(&(host_md->msg_perm),target_addr))
2499 return -TARGET_EFAULT;
ths1bc012f2007-06-03 14:27:49 +00002500 host_md->msg_stime = tswapl(target_md->msg_stime);
2501 host_md->msg_rtime = tswapl(target_md->msg_rtime);
2502 host_md->msg_ctime = tswapl(target_md->msg_ctime);
2503 host_md->__msg_cbytes = tswapl(target_md->__msg_cbytes);
2504 host_md->msg_qnum = tswapl(target_md->msg_qnum);
2505 host_md->msg_qbytes = tswapl(target_md->msg_qbytes);
2506 host_md->msg_lspid = tswapl(target_md->msg_lspid);
2507 host_md->msg_lrpid = tswapl(target_md->msg_lrpid);
2508 unlock_user_struct(target_md, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00002509 return 0;
ths1bc012f2007-06-03 14:27:49 +00002510}
2511
bellard579a97f2007-11-11 14:26:47 +00002512static inline abi_long host_to_target_msqid_ds(abi_ulong target_addr,
2513 struct msqid_ds *host_md)
ths1bc012f2007-06-03 14:27:49 +00002514{
2515 struct target_msqid_ds *target_md;
2516
bellard579a97f2007-11-11 14:26:47 +00002517 if (!lock_user_struct(VERIFY_WRITE, target_md, target_addr, 0))
2518 return -TARGET_EFAULT;
aurel321c54ff92008-10-13 21:08:44 +00002519 if (host_to_target_ipc_perm(target_addr,&(host_md->msg_perm)))
2520 return -TARGET_EFAULT;
ths1bc012f2007-06-03 14:27:49 +00002521 target_md->msg_stime = tswapl(host_md->msg_stime);
2522 target_md->msg_rtime = tswapl(host_md->msg_rtime);
2523 target_md->msg_ctime = tswapl(host_md->msg_ctime);
2524 target_md->__msg_cbytes = tswapl(host_md->__msg_cbytes);
2525 target_md->msg_qnum = tswapl(host_md->msg_qnum);
2526 target_md->msg_qbytes = tswapl(host_md->msg_qbytes);
2527 target_md->msg_lspid = tswapl(host_md->msg_lspid);
2528 target_md->msg_lrpid = tswapl(host_md->msg_lrpid);
2529 unlock_user_struct(target_md, target_addr, 1);
bellard579a97f2007-11-11 14:26:47 +00002530 return 0;
ths1bc012f2007-06-03 14:27:49 +00002531}
2532
aurel321c54ff92008-10-13 21:08:44 +00002533struct target_msginfo {
2534 int msgpool;
2535 int msgmap;
2536 int msgmax;
2537 int msgmnb;
2538 int msgmni;
2539 int msgssz;
2540 int msgtql;
2541 unsigned short int msgseg;
2542};
2543
2544static inline abi_long host_to_target_msginfo(abi_ulong target_addr,
2545 struct msginfo *host_msginfo)
2546{
2547 struct target_msginfo *target_msginfo;
2548 if (!lock_user_struct(VERIFY_WRITE, target_msginfo, target_addr, 0))
2549 return -TARGET_EFAULT;
2550 __put_user(host_msginfo->msgpool, &target_msginfo->msgpool);
2551 __put_user(host_msginfo->msgmap, &target_msginfo->msgmap);
2552 __put_user(host_msginfo->msgmax, &target_msginfo->msgmax);
2553 __put_user(host_msginfo->msgmnb, &target_msginfo->msgmnb);
2554 __put_user(host_msginfo->msgmni, &target_msginfo->msgmni);
2555 __put_user(host_msginfo->msgssz, &target_msginfo->msgssz);
2556 __put_user(host_msginfo->msgtql, &target_msginfo->msgtql);
2557 __put_user(host_msginfo->msgseg, &target_msginfo->msgseg);
2558 unlock_user_struct(target_msginfo, target_addr, 1);
aurel3200b229a2008-10-24 13:12:52 +00002559 return 0;
aurel321c54ff92008-10-13 21:08:44 +00002560}
2561
2562static inline abi_long do_msgctl(int msgid, int cmd, abi_long ptr)
ths1bc012f2007-06-03 14:27:49 +00002563{
2564 struct msqid_ds dsarg;
aurel321c54ff92008-10-13 21:08:44 +00002565 struct msginfo msginfo;
2566 abi_long ret = -TARGET_EINVAL;
2567
2568 cmd &= 0xff;
2569
2570 switch (cmd) {
ths1bc012f2007-06-03 14:27:49 +00002571 case IPC_STAT:
2572 case IPC_SET:
aurel321c54ff92008-10-13 21:08:44 +00002573 case MSG_STAT:
2574 if (target_to_host_msqid_ds(&dsarg,ptr))
2575 return -TARGET_EFAULT;
2576 ret = get_errno(msgctl(msgid, cmd, &dsarg));
2577 if (host_to_target_msqid_ds(ptr,&dsarg))
2578 return -TARGET_EFAULT;
2579 break;
2580 case IPC_RMID:
2581 ret = get_errno(msgctl(msgid, cmd, NULL));
2582 break;
2583 case IPC_INFO:
2584 case MSG_INFO:
2585 ret = get_errno(msgctl(msgid, cmd, (struct msqid_ds *)&msginfo));
2586 if (host_to_target_msginfo(ptr, &msginfo))
2587 return -TARGET_EFAULT;
2588 break;
ths1bc012f2007-06-03 14:27:49 +00002589 }
aurel321c54ff92008-10-13 21:08:44 +00002590
ths1bc012f2007-06-03 14:27:49 +00002591 return ret;
2592}
2593
2594struct target_msgbuf {
aurel321c54ff92008-10-13 21:08:44 +00002595 abi_long mtype;
2596 char mtext[1];
ths1bc012f2007-06-03 14:27:49 +00002597};
2598
blueswir1992f48a2007-10-14 16:27:31 +00002599static inline abi_long do_msgsnd(int msqid, abi_long msgp,
2600 unsigned int msgsz, int msgflg)
ths1bc012f2007-06-03 14:27:49 +00002601{
2602 struct target_msgbuf *target_mb;
2603 struct msgbuf *host_mb;
blueswir1992f48a2007-10-14 16:27:31 +00002604 abi_long ret = 0;
ths1bc012f2007-06-03 14:27:49 +00002605
bellard579a97f2007-11-11 14:26:47 +00002606 if (!lock_user_struct(VERIFY_READ, target_mb, msgp, 0))
2607 return -TARGET_EFAULT;
ths1bc012f2007-06-03 14:27:49 +00002608 host_mb = malloc(msgsz+sizeof(long));
aurel321c54ff92008-10-13 21:08:44 +00002609 host_mb->mtype = (abi_long) tswapl(target_mb->mtype);
2610 memcpy(host_mb->mtext, target_mb->mtext, msgsz);
ths1bc012f2007-06-03 14:27:49 +00002611 ret = get_errno(msgsnd(msqid, host_mb, msgsz, msgflg));
2612 free(host_mb);
2613 unlock_user_struct(target_mb, msgp, 0);
2614
2615 return ret;
2616}
2617
blueswir1992f48a2007-10-14 16:27:31 +00002618static inline abi_long do_msgrcv(int msqid, abi_long msgp,
aurel321c54ff92008-10-13 21:08:44 +00002619 unsigned int msgsz, abi_long msgtyp,
blueswir1992f48a2007-10-14 16:27:31 +00002620 int msgflg)
ths1bc012f2007-06-03 14:27:49 +00002621{
2622 struct target_msgbuf *target_mb;
bellard579a97f2007-11-11 14:26:47 +00002623 char *target_mtext;
ths1bc012f2007-06-03 14:27:49 +00002624 struct msgbuf *host_mb;
blueswir1992f48a2007-10-14 16:27:31 +00002625 abi_long ret = 0;
ths1bc012f2007-06-03 14:27:49 +00002626
bellard579a97f2007-11-11 14:26:47 +00002627 if (!lock_user_struct(VERIFY_WRITE, target_mb, msgp, 0))
2628 return -TARGET_EFAULT;
aurel321c54ff92008-10-13 21:08:44 +00002629
ths1bc012f2007-06-03 14:27:49 +00002630 host_mb = malloc(msgsz+sizeof(long));
aurel321c54ff92008-10-13 21:08:44 +00002631 ret = get_errno(msgrcv(msqid, host_mb, msgsz, tswapl(msgtyp), msgflg));
2632
bellard579a97f2007-11-11 14:26:47 +00002633 if (ret > 0) {
2634 abi_ulong target_mtext_addr = msgp + sizeof(abi_ulong);
2635 target_mtext = lock_user(VERIFY_WRITE, target_mtext_addr, ret, 0);
2636 if (!target_mtext) {
2637 ret = -TARGET_EFAULT;
2638 goto end;
2639 }
aurel321c54ff92008-10-13 21:08:44 +00002640 memcpy(target_mb->mtext, host_mb->mtext, ret);
bellard579a97f2007-11-11 14:26:47 +00002641 unlock_user(target_mtext, target_mtext_addr, ret);
2642 }
aurel321c54ff92008-10-13 21:08:44 +00002643
ths1bc012f2007-06-03 14:27:49 +00002644 target_mb->mtype = tswapl(host_mb->mtype);
2645 free(host_mb);
ths1bc012f2007-06-03 14:27:49 +00002646
bellard579a97f2007-11-11 14:26:47 +00002647end:
2648 if (target_mb)
2649 unlock_user_struct(target_mb, msgp, 1);
ths1bc012f2007-06-03 14:27:49 +00002650 return ret;
2651}
2652
Riku Voipio88a8c982009-04-03 10:42:00 +03002653struct target_shmid_ds
2654{
2655 struct target_ipc_perm shm_perm;
2656 abi_ulong shm_segsz;
2657 abi_ulong shm_atime;
2658#if TARGET_ABI_BITS == 32
2659 abi_ulong __unused1;
2660#endif
2661 abi_ulong shm_dtime;
2662#if TARGET_ABI_BITS == 32
2663 abi_ulong __unused2;
2664#endif
2665 abi_ulong shm_ctime;
2666#if TARGET_ABI_BITS == 32
2667 abi_ulong __unused3;
2668#endif
2669 int shm_cpid;
2670 int shm_lpid;
2671 abi_ulong shm_nattch;
2672 unsigned long int __unused4;
2673 unsigned long int __unused5;
2674};
2675
2676static inline abi_long target_to_host_shmid_ds(struct shmid_ds *host_sd,
2677 abi_ulong target_addr)
2678{
2679 struct target_shmid_ds *target_sd;
2680
2681 if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
2682 return -TARGET_EFAULT;
2683 if (target_to_host_ipc_perm(&(host_sd->shm_perm), target_addr))
2684 return -TARGET_EFAULT;
2685 __get_user(host_sd->shm_segsz, &target_sd->shm_segsz);
2686 __get_user(host_sd->shm_atime, &target_sd->shm_atime);
2687 __get_user(host_sd->shm_dtime, &target_sd->shm_dtime);
2688 __get_user(host_sd->shm_ctime, &target_sd->shm_ctime);
2689 __get_user(host_sd->shm_cpid, &target_sd->shm_cpid);
2690 __get_user(host_sd->shm_lpid, &target_sd->shm_lpid);
2691 __get_user(host_sd->shm_nattch, &target_sd->shm_nattch);
2692 unlock_user_struct(target_sd, target_addr, 0);
2693 return 0;
2694}
2695
2696static inline abi_long host_to_target_shmid_ds(abi_ulong target_addr,
2697 struct shmid_ds *host_sd)
2698{
2699 struct target_shmid_ds *target_sd;
2700
2701 if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
2702 return -TARGET_EFAULT;
2703 if (host_to_target_ipc_perm(target_addr, &(host_sd->shm_perm)))
2704 return -TARGET_EFAULT;
2705 __put_user(host_sd->shm_segsz, &target_sd->shm_segsz);
2706 __put_user(host_sd->shm_atime, &target_sd->shm_atime);
2707 __put_user(host_sd->shm_dtime, &target_sd->shm_dtime);
2708 __put_user(host_sd->shm_ctime, &target_sd->shm_ctime);
2709 __put_user(host_sd->shm_cpid, &target_sd->shm_cpid);
2710 __put_user(host_sd->shm_lpid, &target_sd->shm_lpid);
2711 __put_user(host_sd->shm_nattch, &target_sd->shm_nattch);
2712 unlock_user_struct(target_sd, target_addr, 1);
2713 return 0;
2714}
2715
2716struct target_shminfo {
2717 abi_ulong shmmax;
2718 abi_ulong shmmin;
2719 abi_ulong shmmni;
2720 abi_ulong shmseg;
2721 abi_ulong shmall;
2722};
2723
2724static inline abi_long host_to_target_shminfo(abi_ulong target_addr,
2725 struct shminfo *host_shminfo)
2726{
2727 struct target_shminfo *target_shminfo;
2728 if (!lock_user_struct(VERIFY_WRITE, target_shminfo, target_addr, 0))
2729 return -TARGET_EFAULT;
2730 __put_user(host_shminfo->shmmax, &target_shminfo->shmmax);
2731 __put_user(host_shminfo->shmmin, &target_shminfo->shmmin);
2732 __put_user(host_shminfo->shmmni, &target_shminfo->shmmni);
2733 __put_user(host_shminfo->shmseg, &target_shminfo->shmseg);
2734 __put_user(host_shminfo->shmall, &target_shminfo->shmall);
2735 unlock_user_struct(target_shminfo, target_addr, 1);
2736 return 0;
2737}
2738
2739struct target_shm_info {
2740 int used_ids;
2741 abi_ulong shm_tot;
2742 abi_ulong shm_rss;
2743 abi_ulong shm_swp;
2744 abi_ulong swap_attempts;
2745 abi_ulong swap_successes;
2746};
2747
2748static inline abi_long host_to_target_shm_info(abi_ulong target_addr,
2749 struct shm_info *host_shm_info)
2750{
2751 struct target_shm_info *target_shm_info;
2752 if (!lock_user_struct(VERIFY_WRITE, target_shm_info, target_addr, 0))
2753 return -TARGET_EFAULT;
2754 __put_user(host_shm_info->used_ids, &target_shm_info->used_ids);
2755 __put_user(host_shm_info->shm_tot, &target_shm_info->shm_tot);
2756 __put_user(host_shm_info->shm_rss, &target_shm_info->shm_rss);
2757 __put_user(host_shm_info->shm_swp, &target_shm_info->shm_swp);
2758 __put_user(host_shm_info->swap_attempts, &target_shm_info->swap_attempts);
2759 __put_user(host_shm_info->swap_successes, &target_shm_info->swap_successes);
2760 unlock_user_struct(target_shm_info, target_addr, 1);
2761 return 0;
2762}
2763
2764static inline abi_long do_shmctl(int shmid, int cmd, abi_long buf)
2765{
2766 struct shmid_ds dsarg;
2767 struct shminfo shminfo;
2768 struct shm_info shm_info;
2769 abi_long ret = -TARGET_EINVAL;
2770
2771 cmd &= 0xff;
2772
2773 switch(cmd) {
2774 case IPC_STAT:
2775 case IPC_SET:
2776 case SHM_STAT:
2777 if (target_to_host_shmid_ds(&dsarg, buf))
2778 return -TARGET_EFAULT;
2779 ret = get_errno(shmctl(shmid, cmd, &dsarg));
2780 if (host_to_target_shmid_ds(buf, &dsarg))
2781 return -TARGET_EFAULT;
2782 break;
2783 case IPC_INFO:
2784 ret = get_errno(shmctl(shmid, cmd, (struct shmid_ds *)&shminfo));
2785 if (host_to_target_shminfo(buf, &shminfo))
2786 return -TARGET_EFAULT;
2787 break;
2788 case SHM_INFO:
2789 ret = get_errno(shmctl(shmid, cmd, (struct shmid_ds *)&shm_info));
2790 if (host_to_target_shm_info(buf, &shm_info))
2791 return -TARGET_EFAULT;
2792 break;
2793 case IPC_RMID:
2794 case SHM_LOCK:
2795 case SHM_UNLOCK:
2796 ret = get_errno(shmctl(shmid, cmd, NULL));
2797 break;
2798 }
2799
2800 return ret;
2801}
2802
2803static inline abi_ulong do_shmat(int shmid, abi_ulong shmaddr, int shmflg)
2804{
2805 abi_long raddr;
2806 void *host_raddr;
2807 struct shmid_ds shm_info;
2808 int i,ret;
2809
2810 /* find out the length of the shared memory segment */
2811 ret = get_errno(shmctl(shmid, IPC_STAT, &shm_info));
2812 if (is_error(ret)) {
2813 /* can't get length, bail out */
2814 return ret;
2815 }
2816
2817 mmap_lock();
2818
2819 if (shmaddr)
2820 host_raddr = shmat(shmid, (void *)g2h(shmaddr), shmflg);
2821 else {
2822 abi_ulong mmap_start;
2823
2824 mmap_start = mmap_find_vma(0, shm_info.shm_segsz);
2825
2826 if (mmap_start == -1) {
2827 errno = ENOMEM;
2828 host_raddr = (void *)-1;
2829 } else
2830 host_raddr = shmat(shmid, g2h(mmap_start), shmflg | SHM_REMAP);
2831 }
2832
2833 if (host_raddr == (void *)-1) {
2834 mmap_unlock();
2835 return get_errno((long)host_raddr);
2836 }
2837 raddr=h2g((unsigned long)host_raddr);
2838
2839 page_set_flags(raddr, raddr + shm_info.shm_segsz,
2840 PAGE_VALID | PAGE_READ |
2841 ((shmflg & SHM_RDONLY)? 0 : PAGE_WRITE));
2842
2843 for (i = 0; i < N_SHM_REGIONS; i++) {
2844 if (shm_regions[i].start == 0) {
2845 shm_regions[i].start = raddr;
2846 shm_regions[i].size = shm_info.shm_segsz;
2847 break;
2848 }
2849 }
2850
2851 mmap_unlock();
2852 return raddr;
2853
2854}
2855
2856static inline abi_long do_shmdt(abi_ulong shmaddr)
2857{
2858 int i;
2859
2860 for (i = 0; i < N_SHM_REGIONS; ++i) {
2861 if (shm_regions[i].start == shmaddr) {
2862 shm_regions[i].start = 0;
takasi-y@ops.dti.ne.jpe00ac242010-04-11 02:09:57 +09002863 page_set_flags(shmaddr, shmaddr + shm_regions[i].size, 0);
Riku Voipio88a8c982009-04-03 10:42:00 +03002864 break;
2865 }
2866 }
2867
2868 return get_errno(shmdt(g2h(shmaddr)));
2869}
2870
aurel321c54ff92008-10-13 21:08:44 +00002871#ifdef TARGET_NR_ipc
pbrook53a59602006-03-25 19:31:22 +00002872/* ??? This only works with linear mappings. */
ths0da46a62007-10-20 20:23:07 +00002873/* do_ipc() must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00002874static abi_long do_ipc(unsigned int call, int first,
2875 int second, int third,
2876 abi_long ptr, abi_long fifth)
bellard8853f862004-02-22 14:57:26 +00002877{
2878 int version;
blueswir1992f48a2007-10-14 16:27:31 +00002879 abi_long ret = 0;
bellard8853f862004-02-22 14:57:26 +00002880
2881 version = call >> 16;
2882 call &= 0xffff;
2883
2884 switch (call) {
thsfa294812007-02-02 22:05:00 +00002885 case IPCOP_semop:
aurel32e5289082009-04-18 16:16:12 +00002886 ret = do_semop(first, ptr, second);
thsfa294812007-02-02 22:05:00 +00002887 break;
2888
2889 case IPCOP_semget:
2890 ret = get_errno(semget(first, second, third));
2891 break;
2892
2893 case IPCOP_semctl:
aurel32e5289082009-04-18 16:16:12 +00002894 ret = do_semctl(first, second, third, (union target_semun)(abi_ulong) ptr);
thsfa294812007-02-02 22:05:00 +00002895 break;
thsd96372e2007-02-02 22:05:44 +00002896
aurel321c54ff92008-10-13 21:08:44 +00002897 case IPCOP_msgget:
2898 ret = get_errno(msgget(first, second));
2899 break;
thsd96372e2007-02-02 22:05:44 +00002900
aurel321c54ff92008-10-13 21:08:44 +00002901 case IPCOP_msgsnd:
2902 ret = do_msgsnd(first, ptr, second, third);
2903 break;
thsd96372e2007-02-02 22:05:44 +00002904
aurel321c54ff92008-10-13 21:08:44 +00002905 case IPCOP_msgctl:
2906 ret = do_msgctl(first, second, ptr);
2907 break;
thsd96372e2007-02-02 22:05:44 +00002908
aurel321c54ff92008-10-13 21:08:44 +00002909 case IPCOP_msgrcv:
2910 switch (version) {
2911 case 0:
2912 {
2913 struct target_ipc_kludge {
2914 abi_long msgp;
2915 abi_long msgtyp;
2916 } *tmp;
thsd96372e2007-02-02 22:05:44 +00002917
aurel321c54ff92008-10-13 21:08:44 +00002918 if (!lock_user_struct(VERIFY_READ, tmp, ptr, 1)) {
2919 ret = -TARGET_EFAULT;
2920 break;
ths1bc012f2007-06-03 14:27:49 +00002921 }
aurel321c54ff92008-10-13 21:08:44 +00002922
2923 ret = do_msgrcv(first, tmp->msgp, second, tmp->msgtyp, third);
2924
2925 unlock_user_struct(tmp, ptr, 0);
2926 break;
2927 }
2928 default:
2929 ret = do_msgrcv(first, ptr, second, fifth, third);
2930 }
2931 break;
thsd96372e2007-02-02 22:05:44 +00002932
bellard8853f862004-02-22 14:57:26 +00002933 case IPCOP_shmat:
Riku Voipio88a8c982009-04-03 10:42:00 +03002934 switch (version) {
2935 default:
bellard5a4a8982007-11-11 17:39:18 +00002936 {
2937 abi_ulong raddr;
Riku Voipio88a8c982009-04-03 10:42:00 +03002938 raddr = do_shmat(first, ptr, second);
2939 if (is_error(raddr))
2940 return get_errno(raddr);
bellard2f619692007-11-16 10:46:05 +00002941 if (put_user_ual(raddr, third))
bellard5a4a8982007-11-11 17:39:18 +00002942 return -TARGET_EFAULT;
Riku Voipio88a8c982009-04-03 10:42:00 +03002943 break;
2944 }
2945 case 1:
2946 ret = -TARGET_EINVAL;
2947 break;
bellard5a4a8982007-11-11 17:39:18 +00002948 }
bellard8853f862004-02-22 14:57:26 +00002949 break;
2950 case IPCOP_shmdt:
Riku Voipio88a8c982009-04-03 10:42:00 +03002951 ret = do_shmdt(ptr);
bellard8853f862004-02-22 14:57:26 +00002952 break;
2953
2954 case IPCOP_shmget:
2955 /* IPC_* flag values are the same on all linux platforms */
2956 ret = get_errno(shmget(first, second, third));
2957 break;
2958
2959 /* IPC_* and SHM_* command values are the same on all linux platforms */
2960 case IPCOP_shmctl:
Riku Voipio88a8c982009-04-03 10:42:00 +03002961 ret = do_shmctl(first, second, third);
bellard8853f862004-02-22 14:57:26 +00002962 break;
2963 default:
j_mayer32407102007-09-26 23:01:49 +00002964 gemu_log("Unsupported ipc call: %d (version %d)\n", call, version);
ths0da46a62007-10-20 20:23:07 +00002965 ret = -TARGET_ENOSYS;
bellard8853f862004-02-22 14:57:26 +00002966 break;
2967 }
2968 return ret;
2969}
j_mayer32407102007-09-26 23:01:49 +00002970#endif
bellard8853f862004-02-22 14:57:26 +00002971
bellard31e31b82003-02-18 22:55:36 +00002972/* kernel structure types definitions */
2973#define IFNAMSIZ 16
2974
Blue Swirl001faf32009-05-13 17:53:17 +00002975#define STRUCT(name, ...) STRUCT_ ## name,
bellard31e31b82003-02-18 22:55:36 +00002976#define STRUCT_SPECIAL(name) STRUCT_ ## name,
2977enum {
2978#include "syscall_types.h"
2979};
2980#undef STRUCT
2981#undef STRUCT_SPECIAL
2982
Blue Swirl001faf32009-05-13 17:53:17 +00002983#define STRUCT(name, ...) static const argtype struct_ ## name ## _def[] = { __VA_ARGS__, TYPE_NULL };
bellard31e31b82003-02-18 22:55:36 +00002984#define STRUCT_SPECIAL(name)
2985#include "syscall_types.h"
2986#undef STRUCT
2987#undef STRUCT_SPECIAL
2988
Peter Maydelld2ef05b2011-01-06 15:04:17 +00002989typedef struct IOCTLEntry IOCTLEntry;
2990
2991typedef abi_long do_ioctl_fn(const IOCTLEntry *ie, uint8_t *buf_temp,
2992 int fd, abi_long cmd, abi_long arg);
2993
2994struct IOCTLEntry {
bellard2ab83ea2003-06-15 19:56:46 +00002995 unsigned int target_cmd;
2996 unsigned int host_cmd;
bellard31e31b82003-02-18 22:55:36 +00002997 const char *name;
2998 int access;
Peter Maydelld2ef05b2011-01-06 15:04:17 +00002999 do_ioctl_fn *do_ioctl;
bellard1a9353d2003-03-16 20:28:50 +00003000 const argtype arg_type[5];
Peter Maydelld2ef05b2011-01-06 15:04:17 +00003001};
bellard31e31b82003-02-18 22:55:36 +00003002
3003#define IOC_R 0x0001
3004#define IOC_W 0x0002
3005#define IOC_RW (IOC_R | IOC_W)
3006
3007#define MAX_STRUCT_SIZE 4096
3008
Peter Maydelldace20d2011-01-10 13:11:24 +00003009#ifdef CONFIG_FIEMAP
Peter Maydell285da2b2011-01-06 15:04:18 +00003010/* So fiemap access checks don't overflow on 32 bit systems.
3011 * This is very slightly smaller than the limit imposed by
3012 * the underlying kernel.
3013 */
3014#define FIEMAP_MAX_EXTENTS ((UINT_MAX - sizeof(struct fiemap)) \
3015 / sizeof(struct fiemap_extent))
3016
3017static abi_long do_ioctl_fs_ioc_fiemap(const IOCTLEntry *ie, uint8_t *buf_temp,
3018 int fd, abi_long cmd, abi_long arg)
3019{
3020 /* The parameter for this ioctl is a struct fiemap followed
3021 * by an array of struct fiemap_extent whose size is set
3022 * in fiemap->fm_extent_count. The array is filled in by the
3023 * ioctl.
3024 */
3025 int target_size_in, target_size_out;
3026 struct fiemap *fm;
3027 const argtype *arg_type = ie->arg_type;
3028 const argtype extent_arg_type[] = { MK_STRUCT(STRUCT_fiemap_extent) };
3029 void *argptr, *p;
3030 abi_long ret;
3031 int i, extent_size = thunk_type_size(extent_arg_type, 0);
3032 uint32_t outbufsz;
3033 int free_fm = 0;
3034
3035 assert(arg_type[0] == TYPE_PTR);
3036 assert(ie->access == IOC_RW);
3037 arg_type++;
3038 target_size_in = thunk_type_size(arg_type, 0);
3039 argptr = lock_user(VERIFY_READ, arg, target_size_in, 1);
3040 if (!argptr) {
3041 return -TARGET_EFAULT;
3042 }
3043 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
3044 unlock_user(argptr, arg, 0);
3045 fm = (struct fiemap *)buf_temp;
3046 if (fm->fm_extent_count > FIEMAP_MAX_EXTENTS) {
3047 return -TARGET_EINVAL;
3048 }
3049
3050 outbufsz = sizeof (*fm) +
3051 (sizeof(struct fiemap_extent) * fm->fm_extent_count);
3052
3053 if (outbufsz > MAX_STRUCT_SIZE) {
3054 /* We can't fit all the extents into the fixed size buffer.
3055 * Allocate one that is large enough and use it instead.
3056 */
3057 fm = malloc(outbufsz);
3058 if (!fm) {
3059 return -TARGET_ENOMEM;
3060 }
3061 memcpy(fm, buf_temp, sizeof(struct fiemap));
3062 free_fm = 1;
3063 }
3064 ret = get_errno(ioctl(fd, ie->host_cmd, fm));
3065 if (!is_error(ret)) {
3066 target_size_out = target_size_in;
3067 /* An extent_count of 0 means we were only counting the extents
3068 * so there are no structs to copy
3069 */
3070 if (fm->fm_extent_count != 0) {
3071 target_size_out += fm->fm_mapped_extents * extent_size;
3072 }
3073 argptr = lock_user(VERIFY_WRITE, arg, target_size_out, 0);
3074 if (!argptr) {
3075 ret = -TARGET_EFAULT;
3076 } else {
3077 /* Convert the struct fiemap */
3078 thunk_convert(argptr, fm, arg_type, THUNK_TARGET);
3079 if (fm->fm_extent_count != 0) {
3080 p = argptr + target_size_in;
3081 /* ...and then all the struct fiemap_extents */
3082 for (i = 0; i < fm->fm_mapped_extents; i++) {
3083 thunk_convert(p, &fm->fm_extents[i], extent_arg_type,
3084 THUNK_TARGET);
3085 p += extent_size;
3086 }
3087 }
3088 unlock_user(argptr, arg, target_size_out);
3089 }
3090 }
3091 if (free_fm) {
3092 free(fm);
3093 }
3094 return ret;
3095}
Peter Maydelldace20d2011-01-10 13:11:24 +00003096#endif
Peter Maydell285da2b2011-01-06 15:04:18 +00003097
blueswir19f106a72008-10-05 10:52:52 +00003098static IOCTLEntry ioctl_entries[] = {
Blue Swirl001faf32009-05-13 17:53:17 +00003099#define IOCTL(cmd, access, ...) \
Peter Maydelld2ef05b2011-01-06 15:04:17 +00003100 { TARGET_ ## cmd, cmd, #cmd, access, 0, { __VA_ARGS__ } },
3101#define IOCTL_SPECIAL(cmd, access, dofn, ...) \
3102 { TARGET_ ## cmd, cmd, #cmd, access, dofn, { __VA_ARGS__ } },
bellard31e31b82003-02-18 22:55:36 +00003103#include "ioctls.h"
3104 { 0, 0, },
3105};
3106
pbrook53a59602006-03-25 19:31:22 +00003107/* ??? Implement proper locking for ioctls. */
ths0da46a62007-10-20 20:23:07 +00003108/* do_ioctl() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00003109static abi_long do_ioctl(int fd, abi_long cmd, abi_long arg)
bellard31e31b82003-02-18 22:55:36 +00003110{
3111 const IOCTLEntry *ie;
3112 const argtype *arg_type;
blueswir1992f48a2007-10-14 16:27:31 +00003113 abi_long ret;
bellard31e31b82003-02-18 22:55:36 +00003114 uint8_t buf_temp[MAX_STRUCT_SIZE];
pbrook53a59602006-03-25 19:31:22 +00003115 int target_size;
3116 void *argptr;
bellard31e31b82003-02-18 22:55:36 +00003117
3118 ie = ioctl_entries;
3119 for(;;) {
3120 if (ie->target_cmd == 0) {
j_mayer32407102007-09-26 23:01:49 +00003121 gemu_log("Unsupported ioctl: cmd=0x%04lx\n", (long)cmd);
ths0da46a62007-10-20 20:23:07 +00003122 return -TARGET_ENOSYS;
bellard31e31b82003-02-18 22:55:36 +00003123 }
3124 if (ie->target_cmd == cmd)
3125 break;
3126 ie++;
3127 }
3128 arg_type = ie->arg_type;
bellard9de5e442003-03-23 16:49:39 +00003129#if defined(DEBUG)
j_mayer32407102007-09-26 23:01:49 +00003130 gemu_log("ioctl: cmd=0x%04lx (%s)\n", (long)cmd, ie->name);
bellard72f03902003-02-18 23:33:18 +00003131#endif
Peter Maydelld2ef05b2011-01-06 15:04:17 +00003132 if (ie->do_ioctl) {
3133 return ie->do_ioctl(ie, buf_temp, fd, cmd, arg);
3134 }
3135
bellard31e31b82003-02-18 22:55:36 +00003136 switch(arg_type[0]) {
3137 case TYPE_NULL:
3138 /* no argument */
3139 ret = get_errno(ioctl(fd, ie->host_cmd));
3140 break;
3141 case TYPE_PTRVOID:
3142 case TYPE_INT:
3143 /* int argment */
3144 ret = get_errno(ioctl(fd, ie->host_cmd, arg));
3145 break;
3146 case TYPE_PTR:
3147 arg_type++;
pbrook53a59602006-03-25 19:31:22 +00003148 target_size = thunk_type_size(arg_type, 0);
bellard31e31b82003-02-18 22:55:36 +00003149 switch(ie->access) {
3150 case IOC_R:
3151 ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
3152 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00003153 argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
3154 if (!argptr)
3155 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00003156 thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
3157 unlock_user(argptr, arg, target_size);
bellard31e31b82003-02-18 22:55:36 +00003158 }
3159 break;
3160 case IOC_W:
bellard579a97f2007-11-11 14:26:47 +00003161 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
3162 if (!argptr)
3163 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00003164 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
3165 unlock_user(argptr, arg, 0);
bellard31e31b82003-02-18 22:55:36 +00003166 ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
3167 break;
3168 default:
3169 case IOC_RW:
bellard579a97f2007-11-11 14:26:47 +00003170 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
3171 if (!argptr)
3172 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00003173 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
3174 unlock_user(argptr, arg, 0);
bellard31e31b82003-02-18 22:55:36 +00003175 ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
3176 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00003177 argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
3178 if (!argptr)
3179 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00003180 thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
3181 unlock_user(argptr, arg, target_size);
bellard31e31b82003-02-18 22:55:36 +00003182 }
3183 break;
3184 }
3185 break;
3186 default:
j_mayer32407102007-09-26 23:01:49 +00003187 gemu_log("Unsupported ioctl type: cmd=0x%04lx type=%d\n",
3188 (long)cmd, arg_type[0]);
ths0da46a62007-10-20 20:23:07 +00003189 ret = -TARGET_ENOSYS;
bellard31e31b82003-02-18 22:55:36 +00003190 break;
3191 }
3192 return ret;
3193}
3194
blueswir1b39bc502008-10-05 10:51:10 +00003195static const bitmask_transtbl iflag_tbl[] = {
bellard31e31b82003-02-18 22:55:36 +00003196 { TARGET_IGNBRK, TARGET_IGNBRK, IGNBRK, IGNBRK },
3197 { TARGET_BRKINT, TARGET_BRKINT, BRKINT, BRKINT },
3198 { TARGET_IGNPAR, TARGET_IGNPAR, IGNPAR, IGNPAR },
3199 { TARGET_PARMRK, TARGET_PARMRK, PARMRK, PARMRK },
3200 { TARGET_INPCK, TARGET_INPCK, INPCK, INPCK },
3201 { TARGET_ISTRIP, TARGET_ISTRIP, ISTRIP, ISTRIP },
3202 { TARGET_INLCR, TARGET_INLCR, INLCR, INLCR },
3203 { TARGET_IGNCR, TARGET_IGNCR, IGNCR, IGNCR },
3204 { TARGET_ICRNL, TARGET_ICRNL, ICRNL, ICRNL },
3205 { TARGET_IUCLC, TARGET_IUCLC, IUCLC, IUCLC },
3206 { TARGET_IXON, TARGET_IXON, IXON, IXON },
3207 { TARGET_IXANY, TARGET_IXANY, IXANY, IXANY },
3208 { TARGET_IXOFF, TARGET_IXOFF, IXOFF, IXOFF },
3209 { TARGET_IMAXBEL, TARGET_IMAXBEL, IMAXBEL, IMAXBEL },
3210 { 0, 0, 0, 0 }
3211};
3212
blueswir1b39bc502008-10-05 10:51:10 +00003213static const bitmask_transtbl oflag_tbl[] = {
bellard31e31b82003-02-18 22:55:36 +00003214 { TARGET_OPOST, TARGET_OPOST, OPOST, OPOST },
3215 { TARGET_OLCUC, TARGET_OLCUC, OLCUC, OLCUC },
3216 { TARGET_ONLCR, TARGET_ONLCR, ONLCR, ONLCR },
3217 { TARGET_OCRNL, TARGET_OCRNL, OCRNL, OCRNL },
3218 { TARGET_ONOCR, TARGET_ONOCR, ONOCR, ONOCR },
3219 { TARGET_ONLRET, TARGET_ONLRET, ONLRET, ONLRET },
3220 { TARGET_OFILL, TARGET_OFILL, OFILL, OFILL },
3221 { TARGET_OFDEL, TARGET_OFDEL, OFDEL, OFDEL },
3222 { TARGET_NLDLY, TARGET_NL0, NLDLY, NL0 },
3223 { TARGET_NLDLY, TARGET_NL1, NLDLY, NL1 },
3224 { TARGET_CRDLY, TARGET_CR0, CRDLY, CR0 },
3225 { TARGET_CRDLY, TARGET_CR1, CRDLY, CR1 },
3226 { TARGET_CRDLY, TARGET_CR2, CRDLY, CR2 },
3227 { TARGET_CRDLY, TARGET_CR3, CRDLY, CR3 },
3228 { TARGET_TABDLY, TARGET_TAB0, TABDLY, TAB0 },
3229 { TARGET_TABDLY, TARGET_TAB1, TABDLY, TAB1 },
3230 { TARGET_TABDLY, TARGET_TAB2, TABDLY, TAB2 },
3231 { TARGET_TABDLY, TARGET_TAB3, TABDLY, TAB3 },
3232 { TARGET_BSDLY, TARGET_BS0, BSDLY, BS0 },
3233 { TARGET_BSDLY, TARGET_BS1, BSDLY, BS1 },
3234 { TARGET_VTDLY, TARGET_VT0, VTDLY, VT0 },
3235 { TARGET_VTDLY, TARGET_VT1, VTDLY, VT1 },
3236 { TARGET_FFDLY, TARGET_FF0, FFDLY, FF0 },
3237 { TARGET_FFDLY, TARGET_FF1, FFDLY, FF1 },
3238 { 0, 0, 0, 0 }
3239};
3240
blueswir1b39bc502008-10-05 10:51:10 +00003241static const bitmask_transtbl cflag_tbl[] = {
bellard31e31b82003-02-18 22:55:36 +00003242 { TARGET_CBAUD, TARGET_B0, CBAUD, B0 },
3243 { TARGET_CBAUD, TARGET_B50, CBAUD, B50 },
3244 { TARGET_CBAUD, TARGET_B75, CBAUD, B75 },
3245 { TARGET_CBAUD, TARGET_B110, CBAUD, B110 },
3246 { TARGET_CBAUD, TARGET_B134, CBAUD, B134 },
3247 { TARGET_CBAUD, TARGET_B150, CBAUD, B150 },
3248 { TARGET_CBAUD, TARGET_B200, CBAUD, B200 },
3249 { TARGET_CBAUD, TARGET_B300, CBAUD, B300 },
3250 { TARGET_CBAUD, TARGET_B600, CBAUD, B600 },
3251 { TARGET_CBAUD, TARGET_B1200, CBAUD, B1200 },
3252 { TARGET_CBAUD, TARGET_B1800, CBAUD, B1800 },
3253 { TARGET_CBAUD, TARGET_B2400, CBAUD, B2400 },
3254 { TARGET_CBAUD, TARGET_B4800, CBAUD, B4800 },
3255 { TARGET_CBAUD, TARGET_B9600, CBAUD, B9600 },
3256 { TARGET_CBAUD, TARGET_B19200, CBAUD, B19200 },
3257 { TARGET_CBAUD, TARGET_B38400, CBAUD, B38400 },
3258 { TARGET_CBAUD, TARGET_B57600, CBAUD, B57600 },
3259 { TARGET_CBAUD, TARGET_B115200, CBAUD, B115200 },
3260 { TARGET_CBAUD, TARGET_B230400, CBAUD, B230400 },
3261 { TARGET_CBAUD, TARGET_B460800, CBAUD, B460800 },
3262 { TARGET_CSIZE, TARGET_CS5, CSIZE, CS5 },
3263 { TARGET_CSIZE, TARGET_CS6, CSIZE, CS6 },
3264 { TARGET_CSIZE, TARGET_CS7, CSIZE, CS7 },
3265 { TARGET_CSIZE, TARGET_CS8, CSIZE, CS8 },
3266 { TARGET_CSTOPB, TARGET_CSTOPB, CSTOPB, CSTOPB },
3267 { TARGET_CREAD, TARGET_CREAD, CREAD, CREAD },
3268 { TARGET_PARENB, TARGET_PARENB, PARENB, PARENB },
3269 { TARGET_PARODD, TARGET_PARODD, PARODD, PARODD },
3270 { TARGET_HUPCL, TARGET_HUPCL, HUPCL, HUPCL },
3271 { TARGET_CLOCAL, TARGET_CLOCAL, CLOCAL, CLOCAL },
3272 { TARGET_CRTSCTS, TARGET_CRTSCTS, CRTSCTS, CRTSCTS },
3273 { 0, 0, 0, 0 }
3274};
3275
blueswir1b39bc502008-10-05 10:51:10 +00003276static const bitmask_transtbl lflag_tbl[] = {
bellard31e31b82003-02-18 22:55:36 +00003277 { TARGET_ISIG, TARGET_ISIG, ISIG, ISIG },
3278 { TARGET_ICANON, TARGET_ICANON, ICANON, ICANON },
3279 { TARGET_XCASE, TARGET_XCASE, XCASE, XCASE },
3280 { TARGET_ECHO, TARGET_ECHO, ECHO, ECHO },
3281 { TARGET_ECHOE, TARGET_ECHOE, ECHOE, ECHOE },
3282 { TARGET_ECHOK, TARGET_ECHOK, ECHOK, ECHOK },
3283 { TARGET_ECHONL, TARGET_ECHONL, ECHONL, ECHONL },
3284 { TARGET_NOFLSH, TARGET_NOFLSH, NOFLSH, NOFLSH },
3285 { TARGET_TOSTOP, TARGET_TOSTOP, TOSTOP, TOSTOP },
3286 { TARGET_ECHOCTL, TARGET_ECHOCTL, ECHOCTL, ECHOCTL },
3287 { TARGET_ECHOPRT, TARGET_ECHOPRT, ECHOPRT, ECHOPRT },
3288 { TARGET_ECHOKE, TARGET_ECHOKE, ECHOKE, ECHOKE },
3289 { TARGET_FLUSHO, TARGET_FLUSHO, FLUSHO, FLUSHO },
3290 { TARGET_PENDIN, TARGET_PENDIN, PENDIN, PENDIN },
3291 { TARGET_IEXTEN, TARGET_IEXTEN, IEXTEN, IEXTEN },
3292 { 0, 0, 0, 0 }
3293};
3294
3295static void target_to_host_termios (void *dst, const void *src)
3296{
3297 struct host_termios *host = dst;
3298 const struct target_termios *target = src;
ths3b46e622007-09-17 08:09:54 +00003299
ths5fafdf22007-09-16 21:08:06 +00003300 host->c_iflag =
bellard31e31b82003-02-18 22:55:36 +00003301 target_to_host_bitmask(tswap32(target->c_iflag), iflag_tbl);
ths5fafdf22007-09-16 21:08:06 +00003302 host->c_oflag =
bellard31e31b82003-02-18 22:55:36 +00003303 target_to_host_bitmask(tswap32(target->c_oflag), oflag_tbl);
ths5fafdf22007-09-16 21:08:06 +00003304 host->c_cflag =
bellard31e31b82003-02-18 22:55:36 +00003305 target_to_host_bitmask(tswap32(target->c_cflag), cflag_tbl);
ths5fafdf22007-09-16 21:08:06 +00003306 host->c_lflag =
bellard31e31b82003-02-18 22:55:36 +00003307 target_to_host_bitmask(tswap32(target->c_lflag), lflag_tbl);
3308 host->c_line = target->c_line;
ths3b46e622007-09-17 08:09:54 +00003309
Arnaud Patard44607122009-04-21 17:39:08 +03003310 memset(host->c_cc, 0, sizeof(host->c_cc));
ths5fafdf22007-09-16 21:08:06 +00003311 host->c_cc[VINTR] = target->c_cc[TARGET_VINTR];
3312 host->c_cc[VQUIT] = target->c_cc[TARGET_VQUIT];
ths3b46e622007-09-17 08:09:54 +00003313 host->c_cc[VERASE] = target->c_cc[TARGET_VERASE];
ths5fafdf22007-09-16 21:08:06 +00003314 host->c_cc[VKILL] = target->c_cc[TARGET_VKILL];
ths3b46e622007-09-17 08:09:54 +00003315 host->c_cc[VEOF] = target->c_cc[TARGET_VEOF];
ths5fafdf22007-09-16 21:08:06 +00003316 host->c_cc[VTIME] = target->c_cc[TARGET_VTIME];
ths3b46e622007-09-17 08:09:54 +00003317 host->c_cc[VMIN] = target->c_cc[TARGET_VMIN];
ths5fafdf22007-09-16 21:08:06 +00003318 host->c_cc[VSWTC] = target->c_cc[TARGET_VSWTC];
ths3b46e622007-09-17 08:09:54 +00003319 host->c_cc[VSTART] = target->c_cc[TARGET_VSTART];
ths5fafdf22007-09-16 21:08:06 +00003320 host->c_cc[VSTOP] = target->c_cc[TARGET_VSTOP];
3321 host->c_cc[VSUSP] = target->c_cc[TARGET_VSUSP];
ths3b46e622007-09-17 08:09:54 +00003322 host->c_cc[VEOL] = target->c_cc[TARGET_VEOL];
3323 host->c_cc[VREPRINT] = target->c_cc[TARGET_VREPRINT];
3324 host->c_cc[VDISCARD] = target->c_cc[TARGET_VDISCARD];
3325 host->c_cc[VWERASE] = target->c_cc[TARGET_VWERASE];
3326 host->c_cc[VLNEXT] = target->c_cc[TARGET_VLNEXT];
ths5fafdf22007-09-16 21:08:06 +00003327 host->c_cc[VEOL2] = target->c_cc[TARGET_VEOL2];
bellard31e31b82003-02-18 22:55:36 +00003328}
ths3b46e622007-09-17 08:09:54 +00003329
bellard31e31b82003-02-18 22:55:36 +00003330static void host_to_target_termios (void *dst, const void *src)
3331{
3332 struct target_termios *target = dst;
3333 const struct host_termios *host = src;
3334
ths5fafdf22007-09-16 21:08:06 +00003335 target->c_iflag =
bellard31e31b82003-02-18 22:55:36 +00003336 tswap32(host_to_target_bitmask(host->c_iflag, iflag_tbl));
ths5fafdf22007-09-16 21:08:06 +00003337 target->c_oflag =
bellard31e31b82003-02-18 22:55:36 +00003338 tswap32(host_to_target_bitmask(host->c_oflag, oflag_tbl));
ths5fafdf22007-09-16 21:08:06 +00003339 target->c_cflag =
bellard31e31b82003-02-18 22:55:36 +00003340 tswap32(host_to_target_bitmask(host->c_cflag, cflag_tbl));
ths5fafdf22007-09-16 21:08:06 +00003341 target->c_lflag =
bellard31e31b82003-02-18 22:55:36 +00003342 tswap32(host_to_target_bitmask(host->c_lflag, lflag_tbl));
3343 target->c_line = host->c_line;
ths3b46e622007-09-17 08:09:54 +00003344
Arnaud Patard44607122009-04-21 17:39:08 +03003345 memset(target->c_cc, 0, sizeof(target->c_cc));
bellard31e31b82003-02-18 22:55:36 +00003346 target->c_cc[TARGET_VINTR] = host->c_cc[VINTR];
3347 target->c_cc[TARGET_VQUIT] = host->c_cc[VQUIT];
3348 target->c_cc[TARGET_VERASE] = host->c_cc[VERASE];
3349 target->c_cc[TARGET_VKILL] = host->c_cc[VKILL];
3350 target->c_cc[TARGET_VEOF] = host->c_cc[VEOF];
3351 target->c_cc[TARGET_VTIME] = host->c_cc[VTIME];
3352 target->c_cc[TARGET_VMIN] = host->c_cc[VMIN];
3353 target->c_cc[TARGET_VSWTC] = host->c_cc[VSWTC];
3354 target->c_cc[TARGET_VSTART] = host->c_cc[VSTART];
3355 target->c_cc[TARGET_VSTOP] = host->c_cc[VSTOP];
3356 target->c_cc[TARGET_VSUSP] = host->c_cc[VSUSP];
3357 target->c_cc[TARGET_VEOL] = host->c_cc[VEOL];
3358 target->c_cc[TARGET_VREPRINT] = host->c_cc[VREPRINT];
3359 target->c_cc[TARGET_VDISCARD] = host->c_cc[VDISCARD];
3360 target->c_cc[TARGET_VWERASE] = host->c_cc[VWERASE];
3361 target->c_cc[TARGET_VLNEXT] = host->c_cc[VLNEXT];
3362 target->c_cc[TARGET_VEOL2] = host->c_cc[VEOL2];
3363}
3364
blueswir18e853dc2008-10-05 10:49:32 +00003365static const StructEntry struct_termios_def = {
bellard31e31b82003-02-18 22:55:36 +00003366 .convert = { host_to_target_termios, target_to_host_termios },
3367 .size = { sizeof(struct target_termios), sizeof(struct host_termios) },
3368 .align = { __alignof__(struct target_termios), __alignof__(struct host_termios) },
3369};
3370
bellard5286db72003-06-05 00:57:30 +00003371static bitmask_transtbl mmap_flags_tbl[] = {
3372 { TARGET_MAP_SHARED, TARGET_MAP_SHARED, MAP_SHARED, MAP_SHARED },
3373 { TARGET_MAP_PRIVATE, TARGET_MAP_PRIVATE, MAP_PRIVATE, MAP_PRIVATE },
3374 { TARGET_MAP_FIXED, TARGET_MAP_FIXED, MAP_FIXED, MAP_FIXED },
3375 { TARGET_MAP_ANONYMOUS, TARGET_MAP_ANONYMOUS, MAP_ANONYMOUS, MAP_ANONYMOUS },
3376 { TARGET_MAP_GROWSDOWN, TARGET_MAP_GROWSDOWN, MAP_GROWSDOWN, MAP_GROWSDOWN },
3377 { TARGET_MAP_DENYWRITE, TARGET_MAP_DENYWRITE, MAP_DENYWRITE, MAP_DENYWRITE },
3378 { TARGET_MAP_EXECUTABLE, TARGET_MAP_EXECUTABLE, MAP_EXECUTABLE, MAP_EXECUTABLE },
3379 { TARGET_MAP_LOCKED, TARGET_MAP_LOCKED, MAP_LOCKED, MAP_LOCKED },
3380 { 0, 0, 0, 0 }
3381};
3382
bellard2ab83ea2003-06-15 19:56:46 +00003383#if defined(TARGET_I386)
bellard6dbad632003-03-16 18:05:05 +00003384
3385/* NOTE: there is really one LDT for all the threads */
blueswir1b1d8e522008-10-26 13:43:07 +00003386static uint8_t *ldt_table;
bellard6dbad632003-03-16 18:05:05 +00003387
bellard03acab62007-11-11 14:57:14 +00003388static abi_long read_ldt(abi_ulong ptr, unsigned long bytecount)
bellard6dbad632003-03-16 18:05:05 +00003389{
3390 int size;
pbrook53a59602006-03-25 19:31:22 +00003391 void *p;
bellard6dbad632003-03-16 18:05:05 +00003392
3393 if (!ldt_table)
3394 return 0;
3395 size = TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE;
3396 if (size > bytecount)
3397 size = bytecount;
bellard579a97f2007-11-11 14:26:47 +00003398 p = lock_user(VERIFY_WRITE, ptr, size, 0);
3399 if (!p)
bellard03acab62007-11-11 14:57:14 +00003400 return -TARGET_EFAULT;
bellard579a97f2007-11-11 14:26:47 +00003401 /* ??? Should this by byteswapped? */
pbrook53a59602006-03-25 19:31:22 +00003402 memcpy(p, ldt_table, size);
3403 unlock_user(p, ptr, size);
bellard6dbad632003-03-16 18:05:05 +00003404 return size;
3405}
3406
3407/* XXX: add locking support */
bellard03acab62007-11-11 14:57:14 +00003408static abi_long write_ldt(CPUX86State *env,
3409 abi_ulong ptr, unsigned long bytecount, int oldmode)
bellard6dbad632003-03-16 18:05:05 +00003410{
3411 struct target_modify_ldt_ldt_s ldt_info;
pbrook53a59602006-03-25 19:31:22 +00003412 struct target_modify_ldt_ldt_s *target_ldt_info;
bellard6dbad632003-03-16 18:05:05 +00003413 int seg_32bit, contents, read_exec_only, limit_in_pages;
bellard8d18e892007-11-14 15:18:40 +00003414 int seg_not_present, useable, lm;
bellard6dbad632003-03-16 18:05:05 +00003415 uint32_t *lp, entry_1, entry_2;
3416
3417 if (bytecount != sizeof(ldt_info))
bellard03acab62007-11-11 14:57:14 +00003418 return -TARGET_EINVAL;
bellard579a97f2007-11-11 14:26:47 +00003419 if (!lock_user_struct(VERIFY_READ, target_ldt_info, ptr, 1))
bellard03acab62007-11-11 14:57:14 +00003420 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00003421 ldt_info.entry_number = tswap32(target_ldt_info->entry_number);
3422 ldt_info.base_addr = tswapl(target_ldt_info->base_addr);
3423 ldt_info.limit = tswap32(target_ldt_info->limit);
3424 ldt_info.flags = tswap32(target_ldt_info->flags);
3425 unlock_user_struct(target_ldt_info, ptr, 0);
ths3b46e622007-09-17 08:09:54 +00003426
bellard6dbad632003-03-16 18:05:05 +00003427 if (ldt_info.entry_number >= TARGET_LDT_ENTRIES)
bellard03acab62007-11-11 14:57:14 +00003428 return -TARGET_EINVAL;
bellard6dbad632003-03-16 18:05:05 +00003429 seg_32bit = ldt_info.flags & 1;
3430 contents = (ldt_info.flags >> 1) & 3;
3431 read_exec_only = (ldt_info.flags >> 3) & 1;
3432 limit_in_pages = (ldt_info.flags >> 4) & 1;
3433 seg_not_present = (ldt_info.flags >> 5) & 1;
3434 useable = (ldt_info.flags >> 6) & 1;
bellard8d18e892007-11-14 15:18:40 +00003435#ifdef TARGET_ABI32
3436 lm = 0;
3437#else
3438 lm = (ldt_info.flags >> 7) & 1;
3439#endif
bellard6dbad632003-03-16 18:05:05 +00003440 if (contents == 3) {
3441 if (oldmode)
bellard03acab62007-11-11 14:57:14 +00003442 return -TARGET_EINVAL;
bellard6dbad632003-03-16 18:05:05 +00003443 if (seg_not_present == 0)
bellard03acab62007-11-11 14:57:14 +00003444 return -TARGET_EINVAL;
bellard6dbad632003-03-16 18:05:05 +00003445 }
3446 /* allocate the LDT */
3447 if (!ldt_table) {
balroge4415702008-11-10 02:55:33 +00003448 env->ldt.base = target_mmap(0,
3449 TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE,
3450 PROT_READ|PROT_WRITE,
3451 MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
3452 if (env->ldt.base == -1)
bellard03acab62007-11-11 14:57:14 +00003453 return -TARGET_ENOMEM;
balroge4415702008-11-10 02:55:33 +00003454 memset(g2h(env->ldt.base), 0,
3455 TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE);
bellard6dbad632003-03-16 18:05:05 +00003456 env->ldt.limit = 0xffff;
balroge4415702008-11-10 02:55:33 +00003457 ldt_table = g2h(env->ldt.base);
bellard6dbad632003-03-16 18:05:05 +00003458 }
3459
3460 /* NOTE: same code as Linux kernel */
3461 /* Allow LDTs to be cleared by the user. */
3462 if (ldt_info.base_addr == 0 && ldt_info.limit == 0) {
3463 if (oldmode ||
3464 (contents == 0 &&
3465 read_exec_only == 1 &&
3466 seg_32bit == 0 &&
3467 limit_in_pages == 0 &&
3468 seg_not_present == 1 &&
3469 useable == 0 )) {
3470 entry_1 = 0;
3471 entry_2 = 0;
3472 goto install;
3473 }
3474 }
ths3b46e622007-09-17 08:09:54 +00003475
bellard6dbad632003-03-16 18:05:05 +00003476 entry_1 = ((ldt_info.base_addr & 0x0000ffff) << 16) |
3477 (ldt_info.limit & 0x0ffff);
3478 entry_2 = (ldt_info.base_addr & 0xff000000) |
3479 ((ldt_info.base_addr & 0x00ff0000) >> 16) |
3480 (ldt_info.limit & 0xf0000) |
3481 ((read_exec_only ^ 1) << 9) |
3482 (contents << 10) |
3483 ((seg_not_present ^ 1) << 15) |
3484 (seg_32bit << 22) |
3485 (limit_in_pages << 23) |
bellard8d18e892007-11-14 15:18:40 +00003486 (lm << 21) |
bellard6dbad632003-03-16 18:05:05 +00003487 0x7000;
3488 if (!oldmode)
3489 entry_2 |= (useable << 20);
bellard14ae3ba2003-05-27 23:25:06 +00003490
bellard6dbad632003-03-16 18:05:05 +00003491 /* Install the new entry ... */
3492install:
3493 lp = (uint32_t *)(ldt_table + (ldt_info.entry_number << 3));
3494 lp[0] = tswap32(entry_1);
3495 lp[1] = tswap32(entry_2);
3496 return 0;
3497}
3498
3499/* specific and weird i386 syscalls */
blueswir18fcd3692008-08-17 20:26:25 +00003500static abi_long do_modify_ldt(CPUX86State *env, int func, abi_ulong ptr,
3501 unsigned long bytecount)
bellard6dbad632003-03-16 18:05:05 +00003502{
bellard03acab62007-11-11 14:57:14 +00003503 abi_long ret;
ths3b46e622007-09-17 08:09:54 +00003504
bellard6dbad632003-03-16 18:05:05 +00003505 switch (func) {
3506 case 0:
3507 ret = read_ldt(ptr, bytecount);
3508 break;
3509 case 1:
3510 ret = write_ldt(env, ptr, bytecount, 1);
3511 break;
3512 case 0x11:
3513 ret = write_ldt(env, ptr, bytecount, 0);
3514 break;
bellard03acab62007-11-11 14:57:14 +00003515 default:
3516 ret = -TARGET_ENOSYS;
3517 break;
bellard6dbad632003-03-16 18:05:05 +00003518 }
3519 return ret;
3520}
bellard1b6b0292003-03-22 17:31:38 +00003521
blueswir14583f582008-08-24 10:35:55 +00003522#if defined(TARGET_I386) && defined(TARGET_ABI32)
blueswir18fcd3692008-08-17 20:26:25 +00003523static abi_long do_set_thread_area(CPUX86State *env, abi_ulong ptr)
bellard8d18e892007-11-14 15:18:40 +00003524{
3525 uint64_t *gdt_table = g2h(env->gdt.base);
3526 struct target_modify_ldt_ldt_s ldt_info;
3527 struct target_modify_ldt_ldt_s *target_ldt_info;
3528 int seg_32bit, contents, read_exec_only, limit_in_pages;
3529 int seg_not_present, useable, lm;
3530 uint32_t *lp, entry_1, entry_2;
3531 int i;
3532
3533 lock_user_struct(VERIFY_WRITE, target_ldt_info, ptr, 1);
3534 if (!target_ldt_info)
3535 return -TARGET_EFAULT;
3536 ldt_info.entry_number = tswap32(target_ldt_info->entry_number);
3537 ldt_info.base_addr = tswapl(target_ldt_info->base_addr);
3538 ldt_info.limit = tswap32(target_ldt_info->limit);
3539 ldt_info.flags = tswap32(target_ldt_info->flags);
3540 if (ldt_info.entry_number == -1) {
3541 for (i=TARGET_GDT_ENTRY_TLS_MIN; i<=TARGET_GDT_ENTRY_TLS_MAX; i++) {
3542 if (gdt_table[i] == 0) {
3543 ldt_info.entry_number = i;
3544 target_ldt_info->entry_number = tswap32(i);
3545 break;
3546 }
3547 }
3548 }
3549 unlock_user_struct(target_ldt_info, ptr, 1);
3550
3551 if (ldt_info.entry_number < TARGET_GDT_ENTRY_TLS_MIN ||
3552 ldt_info.entry_number > TARGET_GDT_ENTRY_TLS_MAX)
3553 return -TARGET_EINVAL;
3554 seg_32bit = ldt_info.flags & 1;
3555 contents = (ldt_info.flags >> 1) & 3;
3556 read_exec_only = (ldt_info.flags >> 3) & 1;
3557 limit_in_pages = (ldt_info.flags >> 4) & 1;
3558 seg_not_present = (ldt_info.flags >> 5) & 1;
3559 useable = (ldt_info.flags >> 6) & 1;
3560#ifdef TARGET_ABI32
3561 lm = 0;
3562#else
3563 lm = (ldt_info.flags >> 7) & 1;
3564#endif
3565
3566 if (contents == 3) {
3567 if (seg_not_present == 0)
3568 return -TARGET_EINVAL;
3569 }
3570
3571 /* NOTE: same code as Linux kernel */
3572 /* Allow LDTs to be cleared by the user. */
3573 if (ldt_info.base_addr == 0 && ldt_info.limit == 0) {
3574 if ((contents == 0 &&
3575 read_exec_only == 1 &&
3576 seg_32bit == 0 &&
3577 limit_in_pages == 0 &&
3578 seg_not_present == 1 &&
3579 useable == 0 )) {
3580 entry_1 = 0;
3581 entry_2 = 0;
3582 goto install;
3583 }
3584 }
3585
3586 entry_1 = ((ldt_info.base_addr & 0x0000ffff) << 16) |
3587 (ldt_info.limit & 0x0ffff);
3588 entry_2 = (ldt_info.base_addr & 0xff000000) |
3589 ((ldt_info.base_addr & 0x00ff0000) >> 16) |
3590 (ldt_info.limit & 0xf0000) |
3591 ((read_exec_only ^ 1) << 9) |
3592 (contents << 10) |
3593 ((seg_not_present ^ 1) << 15) |
3594 (seg_32bit << 22) |
3595 (limit_in_pages << 23) |
3596 (useable << 20) |
3597 (lm << 21) |
3598 0x7000;
3599
3600 /* Install the new entry ... */
3601install:
3602 lp = (uint32_t *)(gdt_table + ldt_info.entry_number);
3603 lp[0] = tswap32(entry_1);
3604 lp[1] = tswap32(entry_2);
3605 return 0;
3606}
3607
blueswir18fcd3692008-08-17 20:26:25 +00003608static abi_long do_get_thread_area(CPUX86State *env, abi_ulong ptr)
bellard8d18e892007-11-14 15:18:40 +00003609{
3610 struct target_modify_ldt_ldt_s *target_ldt_info;
3611 uint64_t *gdt_table = g2h(env->gdt.base);
3612 uint32_t base_addr, limit, flags;
3613 int seg_32bit, contents, read_exec_only, limit_in_pages, idx;
3614 int seg_not_present, useable, lm;
3615 uint32_t *lp, entry_1, entry_2;
3616
3617 lock_user_struct(VERIFY_WRITE, target_ldt_info, ptr, 1);
3618 if (!target_ldt_info)
3619 return -TARGET_EFAULT;
3620 idx = tswap32(target_ldt_info->entry_number);
3621 if (idx < TARGET_GDT_ENTRY_TLS_MIN ||
3622 idx > TARGET_GDT_ENTRY_TLS_MAX) {
3623 unlock_user_struct(target_ldt_info, ptr, 1);
3624 return -TARGET_EINVAL;
3625 }
3626 lp = (uint32_t *)(gdt_table + idx);
3627 entry_1 = tswap32(lp[0]);
3628 entry_2 = tswap32(lp[1]);
3629
3630 read_exec_only = ((entry_2 >> 9) & 1) ^ 1;
3631 contents = (entry_2 >> 10) & 3;
3632 seg_not_present = ((entry_2 >> 15) & 1) ^ 1;
3633 seg_32bit = (entry_2 >> 22) & 1;
3634 limit_in_pages = (entry_2 >> 23) & 1;
3635 useable = (entry_2 >> 20) & 1;
3636#ifdef TARGET_ABI32
3637 lm = 0;
3638#else
3639 lm = (entry_2 >> 21) & 1;
3640#endif
3641 flags = (seg_32bit << 0) | (contents << 1) |
3642 (read_exec_only << 3) | (limit_in_pages << 4) |
3643 (seg_not_present << 5) | (useable << 6) | (lm << 7);
3644 limit = (entry_1 & 0xffff) | (entry_2 & 0xf0000);
3645 base_addr = (entry_1 >> 16) |
3646 (entry_2 & 0xff000000) |
3647 ((entry_2 & 0xff) << 16);
3648 target_ldt_info->base_addr = tswapl(base_addr);
3649 target_ldt_info->limit = tswap32(limit);
3650 target_ldt_info->flags = tswap32(flags);
3651 unlock_user_struct(target_ldt_info, ptr, 1);
3652 return 0;
3653}
blueswir14583f582008-08-24 10:35:55 +00003654#endif /* TARGET_I386 && TARGET_ABI32 */
bellard8d18e892007-11-14 15:18:40 +00003655
bellardd2fd1af2007-11-14 18:08:56 +00003656#ifndef TARGET_ABI32
blueswir18fcd3692008-08-17 20:26:25 +00003657static abi_long do_arch_prctl(CPUX86State *env, int code, abi_ulong addr)
bellardd2fd1af2007-11-14 18:08:56 +00003658{
3659 abi_long ret;
3660 abi_ulong val;
3661 int idx;
3662
3663 switch(code) {
3664 case TARGET_ARCH_SET_GS:
3665 case TARGET_ARCH_SET_FS:
3666 if (code == TARGET_ARCH_SET_GS)
3667 idx = R_GS;
3668 else
3669 idx = R_FS;
3670 cpu_x86_load_seg(env, idx, 0);
3671 env->segs[idx].base = addr;
3672 break;
3673 case TARGET_ARCH_GET_GS:
3674 case TARGET_ARCH_GET_FS:
3675 if (code == TARGET_ARCH_GET_GS)
3676 idx = R_GS;
3677 else
3678 idx = R_FS;
3679 val = env->segs[idx].base;
3680 if (put_user(val, addr, abi_ulong))
3681 return -TARGET_EFAULT;
3682 break;
3683 default:
3684 ret = -TARGET_EINVAL;
3685 break;
3686 }
3687 return 0;
3688}
3689#endif
3690
bellard2ab83ea2003-06-15 19:56:46 +00003691#endif /* defined(TARGET_I386) */
3692
Juan Quintela2f7bb872009-07-27 16:13:24 +02003693#if defined(CONFIG_USE_NPTL)
pbrookd865bab2008-06-07 22:12:17 +00003694
3695#define NEW_STACK_SIZE PTHREAD_STACK_MIN
3696
3697static pthread_mutex_t clone_lock = PTHREAD_MUTEX_INITIALIZER;
3698typedef struct {
3699 CPUState *env;
3700 pthread_mutex_t mutex;
3701 pthread_cond_t cond;
3702 pthread_t thread;
3703 uint32_t tid;
3704 abi_ulong child_tidptr;
3705 abi_ulong parent_tidptr;
3706 sigset_t sigmask;
3707} new_thread_info;
3708
3709static void *clone_func(void *arg)
3710{
3711 new_thread_info *info = arg;
3712 CPUState *env;
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03003713 TaskState *ts;
pbrookd865bab2008-06-07 22:12:17 +00003714
3715 env = info->env;
3716 thread_env = env;
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03003717 ts = (TaskState *)thread_env->opaque;
pbrookd865bab2008-06-07 22:12:17 +00003718 info->tid = gettid();
Nathan Froyd1e9fa732009-06-03 11:33:08 -07003719 env->host_tid = info->tid;
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03003720 task_settid(ts);
pbrookd865bab2008-06-07 22:12:17 +00003721 if (info->child_tidptr)
3722 put_user_u32(info->tid, info->child_tidptr);
3723 if (info->parent_tidptr)
3724 put_user_u32(info->tid, info->parent_tidptr);
3725 /* Enable signals. */
3726 sigprocmask(SIG_SETMASK, &info->sigmask, NULL);
3727 /* Signal to the parent that we're ready. */
3728 pthread_mutex_lock(&info->mutex);
3729 pthread_cond_broadcast(&info->cond);
3730 pthread_mutex_unlock(&info->mutex);
3731 /* Wait until the parent has finshed initializing the tls state. */
3732 pthread_mutex_lock(&clone_lock);
3733 pthread_mutex_unlock(&clone_lock);
3734 cpu_loop(env);
3735 /* never exits */
3736 return NULL;
3737}
3738#else
bellard1b6b0292003-03-22 17:31:38 +00003739/* this stack is the equivalent of the kernel stack associated with a
3740 thread/process */
3741#define NEW_STACK_SIZE 8192
3742
3743static int clone_func(void *arg)
3744{
bellard2ab83ea2003-06-15 19:56:46 +00003745 CPUState *env = arg;
bellard1b6b0292003-03-22 17:31:38 +00003746 cpu_loop(env);
3747 /* never exits */
3748 return 0;
3749}
pbrookd865bab2008-06-07 22:12:17 +00003750#endif
bellard1b6b0292003-03-22 17:31:38 +00003751
ths0da46a62007-10-20 20:23:07 +00003752/* do_fork() Must return host values and target errnos (unlike most
3753 do_*() functions). */
pbrookd865bab2008-06-07 22:12:17 +00003754static int do_fork(CPUState *env, unsigned int flags, abi_ulong newsp,
3755 abi_ulong parent_tidptr, target_ulong newtls,
3756 abi_ulong child_tidptr)
bellard1b6b0292003-03-22 17:31:38 +00003757{
3758 int ret;
bellard5cd43932003-03-29 16:54:36 +00003759 TaskState *ts;
bellard2ab83ea2003-06-15 19:56:46 +00003760 CPUState *new_env;
Juan Quintela2f7bb872009-07-27 16:13:24 +02003761#if defined(CONFIG_USE_NPTL)
pbrookd865bab2008-06-07 22:12:17 +00003762 unsigned int nptl_flags;
3763 sigset_t sigmask;
Riku Voipio91907492010-11-26 16:21:34 +02003764#else
3765 uint8_t *new_stack;
pbrookd865bab2008-06-07 22:12:17 +00003766#endif
ths3b46e622007-09-17 08:09:54 +00003767
balrog436d1242008-09-21 02:39:45 +00003768 /* Emulate vfork() with fork() */
3769 if (flags & CLONE_VFORK)
3770 flags &= ~(CLONE_VFORK | CLONE_VM);
3771
bellard1b6b0292003-03-22 17:31:38 +00003772 if (flags & CLONE_VM) {
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03003773 TaskState *parent_ts = (TaskState *)env->opaque;
Juan Quintela2f7bb872009-07-27 16:13:24 +02003774#if defined(CONFIG_USE_NPTL)
pbrookd865bab2008-06-07 22:12:17 +00003775 new_thread_info info;
3776 pthread_attr_t attr;
pbrookbd0c5662008-05-29 14:34:11 +00003777#endif
Nathan Froyd48e15fc2010-10-29 07:48:57 -07003778 ts = qemu_mallocz(sizeof(TaskState));
pbrook624f7972008-05-31 16:11:38 +00003779 init_task_state(ts);
bellard1b6b0292003-03-22 17:31:38 +00003780 /* we create a new CPU instance. */
thsc5be9f02007-02-28 20:20:53 +00003781 new_env = cpu_copy(env);
Blue Swirlb4558d72009-11-07 16:34:12 +00003782#if defined(TARGET_I386) || defined(TARGET_SPARC) || defined(TARGET_PPC)
3783 cpu_reset(new_env);
3784#endif
pbrook6e68e072008-05-30 17:22:15 +00003785 /* Init regs that differ from the parent. */
3786 cpu_clone_regs(new_env, newsp);
bellard5cd43932003-03-29 16:54:36 +00003787 new_env->opaque = ts;
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03003788 ts->bprm = parent_ts->bprm;
3789 ts->info = parent_ts->info;
Juan Quintela2f7bb872009-07-27 16:13:24 +02003790#if defined(CONFIG_USE_NPTL)
pbrookd865bab2008-06-07 22:12:17 +00003791 nptl_flags = flags;
3792 flags &= ~CLONE_NPTL_FLAGS2;
3793
pbrookc2764712009-03-07 15:24:59 +00003794 if (nptl_flags & CLONE_CHILD_CLEARTID) {
3795 ts->child_tidptr = child_tidptr;
3796 }
3797
pbrookd865bab2008-06-07 22:12:17 +00003798 if (nptl_flags & CLONE_SETTLS)
3799 cpu_set_tls (new_env, newtls);
3800
3801 /* Grab a mutex so that thread setup appears atomic. */
3802 pthread_mutex_lock(&clone_lock);
3803
3804 memset(&info, 0, sizeof(info));
3805 pthread_mutex_init(&info.mutex, NULL);
3806 pthread_mutex_lock(&info.mutex);
3807 pthread_cond_init(&info.cond, NULL);
3808 info.env = new_env;
3809 if (nptl_flags & CLONE_CHILD_SETTID)
3810 info.child_tidptr = child_tidptr;
3811 if (nptl_flags & CLONE_PARENT_SETTID)
3812 info.parent_tidptr = parent_tidptr;
3813
3814 ret = pthread_attr_init(&attr);
Nathan Froyd48e15fc2010-10-29 07:48:57 -07003815 ret = pthread_attr_setstacksize(&attr, NEW_STACK_SIZE);
3816 ret = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
pbrookd865bab2008-06-07 22:12:17 +00003817 /* It is not safe to deliver signals until the child has finished
3818 initializing, so temporarily block all signals. */
3819 sigfillset(&sigmask);
3820 sigprocmask(SIG_BLOCK, &sigmask, &info.sigmask);
3821
3822 ret = pthread_create(&info.thread, &attr, clone_func, &info);
pbrookc2764712009-03-07 15:24:59 +00003823 /* TODO: Free new CPU state if thread creation failed. */
pbrookd865bab2008-06-07 22:12:17 +00003824
3825 sigprocmask(SIG_SETMASK, &info.sigmask, NULL);
3826 pthread_attr_destroy(&attr);
3827 if (ret == 0) {
3828 /* Wait for the child to initialize. */
3829 pthread_cond_wait(&info.cond, &info.mutex);
3830 ret = info.tid;
3831 if (flags & CLONE_PARENT_SETTID)
3832 put_user_u32(ret, parent_tidptr);
3833 } else {
3834 ret = -1;
3835 }
3836 pthread_mutex_unlock(&info.mutex);
3837 pthread_cond_destroy(&info.cond);
3838 pthread_mutex_destroy(&info.mutex);
3839 pthread_mutex_unlock(&clone_lock);
3840#else
3841 if (flags & CLONE_NPTL_FLAGS2)
3842 return -EINVAL;
3843 /* This is probably going to die very quickly, but do it anyway. */
Nathan Froyd48e15fc2010-10-29 07:48:57 -07003844 new_stack = qemu_mallocz (NEW_STACK_SIZE);
bellard27725c12003-04-29 21:08:18 +00003845#ifdef __ia64__
Aurelien Jarno60e99242010-03-29 02:12:51 +02003846 ret = __clone2(clone_func, new_stack, NEW_STACK_SIZE, flags, new_env);
bellard27725c12003-04-29 21:08:18 +00003847#else
3848 ret = clone(clone_func, new_stack + NEW_STACK_SIZE, flags, new_env);
3849#endif
pbrookd865bab2008-06-07 22:12:17 +00003850#endif
bellard1b6b0292003-03-22 17:31:38 +00003851 } else {
3852 /* if no CLONE_VM, we consider it is a fork */
pbrookd865bab2008-06-07 22:12:17 +00003853 if ((flags & ~(CSIGNAL | CLONE_NPTL_FLAGS2)) != 0)
bellard1b6b0292003-03-22 17:31:38 +00003854 return -EINVAL;
pbrookd865bab2008-06-07 22:12:17 +00003855 fork_start();
bellard1b6b0292003-03-22 17:31:38 +00003856 ret = fork();
pbrookd865bab2008-06-07 22:12:17 +00003857 if (ret == 0) {
aurel322b1319c2008-12-18 22:44:04 +00003858 /* Child Process. */
pbrookd865bab2008-06-07 22:12:17 +00003859 cpu_clone_regs(env, newsp);
3860 fork_end(1);
Juan Quintela2f7bb872009-07-27 16:13:24 +02003861#if defined(CONFIG_USE_NPTL)
aurel322b1319c2008-12-18 22:44:04 +00003862 /* There is a race condition here. The parent process could
3863 theoretically read the TID in the child process before the child
3864 tid is set. This would require using either ptrace
3865 (not implemented) or having *_tidptr to point at a shared memory
3866 mapping. We can't repeat the spinlock hack used above because
3867 the child process gets its own copy of the lock. */
pbrookd865bab2008-06-07 22:12:17 +00003868 if (flags & CLONE_CHILD_SETTID)
3869 put_user_u32(gettid(), child_tidptr);
3870 if (flags & CLONE_PARENT_SETTID)
3871 put_user_u32(gettid(), parent_tidptr);
3872 ts = (TaskState *)env->opaque;
3873 if (flags & CLONE_SETTLS)
3874 cpu_set_tls (env, newtls);
pbrookc2764712009-03-07 15:24:59 +00003875 if (flags & CLONE_CHILD_CLEARTID)
3876 ts->child_tidptr = child_tidptr;
aurel322b1319c2008-12-18 22:44:04 +00003877#endif
pbrookd865bab2008-06-07 22:12:17 +00003878 } else {
3879 fork_end(0);
3880 }
bellard1b6b0292003-03-22 17:31:38 +00003881 }
3882 return ret;
3883}
3884
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02003885/* warning : doesn't handle linux specific flags... */
3886static int target_to_host_fcntl_cmd(int cmd)
3887{
3888 switch(cmd) {
3889 case TARGET_F_DUPFD:
3890 case TARGET_F_GETFD:
3891 case TARGET_F_SETFD:
3892 case TARGET_F_GETFL:
3893 case TARGET_F_SETFL:
3894 return cmd;
3895 case TARGET_F_GETLK:
3896 return F_GETLK;
3897 case TARGET_F_SETLK:
3898 return F_SETLK;
3899 case TARGET_F_SETLKW:
3900 return F_SETLKW;
3901 case TARGET_F_GETOWN:
3902 return F_GETOWN;
3903 case TARGET_F_SETOWN:
3904 return F_SETOWN;
3905 case TARGET_F_GETSIG:
3906 return F_GETSIG;
3907 case TARGET_F_SETSIG:
3908 return F_SETSIG;
3909#if TARGET_ABI_BITS == 32
3910 case TARGET_F_GETLK64:
3911 return F_GETLK64;
3912 case TARGET_F_SETLK64:
3913 return F_SETLK64;
3914 case TARGET_F_SETLKW64:
3915 return F_SETLKW64;
3916#endif
Ulrich Hecht7e22e542009-07-24 19:10:27 +02003917 case TARGET_F_SETLEASE:
3918 return F_SETLEASE;
3919 case TARGET_F_GETLEASE:
3920 return F_GETLEASE;
malcfbd5de92009-09-06 06:31:59 +04003921#ifdef F_DUPFD_CLOEXEC
Ulrich Hecht7e22e542009-07-24 19:10:27 +02003922 case TARGET_F_DUPFD_CLOEXEC:
3923 return F_DUPFD_CLOEXEC;
malcfbd5de92009-09-06 06:31:59 +04003924#endif
Ulrich Hecht7e22e542009-07-24 19:10:27 +02003925 case TARGET_F_NOTIFY:
3926 return F_NOTIFY;
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02003927 default:
3928 return -TARGET_EINVAL;
3929 }
3930 return -TARGET_EINVAL;
3931}
3932
blueswir1992f48a2007-10-14 16:27:31 +00003933static abi_long do_fcntl(int fd, int cmd, abi_ulong arg)
bellard7775e9e2003-05-14 22:46:48 +00003934{
3935 struct flock fl;
pbrook53a59602006-03-25 19:31:22 +00003936 struct target_flock *target_fl;
ths43f238d2007-01-05 20:55:49 +00003937 struct flock64 fl64;
3938 struct target_flock64 *target_fl64;
blueswir1992f48a2007-10-14 16:27:31 +00003939 abi_long ret;
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02003940 int host_cmd = target_to_host_fcntl_cmd(cmd);
3941
3942 if (host_cmd == -TARGET_EINVAL)
3943 return host_cmd;
pbrook53a59602006-03-25 19:31:22 +00003944
bellard7775e9e2003-05-14 22:46:48 +00003945 switch(cmd) {
3946 case TARGET_F_GETLK:
bellard579a97f2007-11-11 14:26:47 +00003947 if (!lock_user_struct(VERIFY_READ, target_fl, arg, 1))
3948 return -TARGET_EFAULT;
ths58134272007-03-31 18:59:32 +00003949 fl.l_type = tswap16(target_fl->l_type);
3950 fl.l_whence = tswap16(target_fl->l_whence);
3951 fl.l_start = tswapl(target_fl->l_start);
3952 fl.l_len = tswapl(target_fl->l_len);
Ulrich Hecht7e22e542009-07-24 19:10:27 +02003953 fl.l_pid = tswap32(target_fl->l_pid);
ths58134272007-03-31 18:59:32 +00003954 unlock_user_struct(target_fl, arg, 0);
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02003955 ret = get_errno(fcntl(fd, host_cmd, &fl));
bellard7775e9e2003-05-14 22:46:48 +00003956 if (ret == 0) {
bellard579a97f2007-11-11 14:26:47 +00003957 if (!lock_user_struct(VERIFY_WRITE, target_fl, arg, 0))
3958 return -TARGET_EFAULT;
bellard7775e9e2003-05-14 22:46:48 +00003959 target_fl->l_type = tswap16(fl.l_type);
3960 target_fl->l_whence = tswap16(fl.l_whence);
3961 target_fl->l_start = tswapl(fl.l_start);
3962 target_fl->l_len = tswapl(fl.l_len);
Ulrich Hecht7e22e542009-07-24 19:10:27 +02003963 target_fl->l_pid = tswap32(fl.l_pid);
pbrook53a59602006-03-25 19:31:22 +00003964 unlock_user_struct(target_fl, arg, 1);
bellard7775e9e2003-05-14 22:46:48 +00003965 }
3966 break;
ths3b46e622007-09-17 08:09:54 +00003967
bellard7775e9e2003-05-14 22:46:48 +00003968 case TARGET_F_SETLK:
3969 case TARGET_F_SETLKW:
bellard579a97f2007-11-11 14:26:47 +00003970 if (!lock_user_struct(VERIFY_READ, target_fl, arg, 1))
3971 return -TARGET_EFAULT;
bellard7775e9e2003-05-14 22:46:48 +00003972 fl.l_type = tswap16(target_fl->l_type);
3973 fl.l_whence = tswap16(target_fl->l_whence);
3974 fl.l_start = tswapl(target_fl->l_start);
3975 fl.l_len = tswapl(target_fl->l_len);
Ulrich Hecht7e22e542009-07-24 19:10:27 +02003976 fl.l_pid = tswap32(target_fl->l_pid);
pbrook53a59602006-03-25 19:31:22 +00003977 unlock_user_struct(target_fl, arg, 0);
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02003978 ret = get_errno(fcntl(fd, host_cmd, &fl));
bellard7775e9e2003-05-14 22:46:48 +00003979 break;
ths3b46e622007-09-17 08:09:54 +00003980
bellard7775e9e2003-05-14 22:46:48 +00003981 case TARGET_F_GETLK64:
bellard579a97f2007-11-11 14:26:47 +00003982 if (!lock_user_struct(VERIFY_READ, target_fl64, arg, 1))
3983 return -TARGET_EFAULT;
ths58134272007-03-31 18:59:32 +00003984 fl64.l_type = tswap16(target_fl64->l_type) >> 1;
3985 fl64.l_whence = tswap16(target_fl64->l_whence);
3986 fl64.l_start = tswapl(target_fl64->l_start);
3987 fl64.l_len = tswapl(target_fl64->l_len);
Ulrich Hecht7e22e542009-07-24 19:10:27 +02003988 fl64.l_pid = tswap32(target_fl64->l_pid);
ths58134272007-03-31 18:59:32 +00003989 unlock_user_struct(target_fl64, arg, 0);
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02003990 ret = get_errno(fcntl(fd, host_cmd, &fl64));
ths43f238d2007-01-05 20:55:49 +00003991 if (ret == 0) {
bellard579a97f2007-11-11 14:26:47 +00003992 if (!lock_user_struct(VERIFY_WRITE, target_fl64, arg, 0))
3993 return -TARGET_EFAULT;
ths43f238d2007-01-05 20:55:49 +00003994 target_fl64->l_type = tswap16(fl64.l_type) >> 1;
3995 target_fl64->l_whence = tswap16(fl64.l_whence);
3996 target_fl64->l_start = tswapl(fl64.l_start);
3997 target_fl64->l_len = tswapl(fl64.l_len);
Ulrich Hecht7e22e542009-07-24 19:10:27 +02003998 target_fl64->l_pid = tswap32(fl64.l_pid);
ths43f238d2007-01-05 20:55:49 +00003999 unlock_user_struct(target_fl64, arg, 1);
4000 }
bellard9ee1fa22007-11-11 15:11:19 +00004001 break;
bellard7775e9e2003-05-14 22:46:48 +00004002 case TARGET_F_SETLK64:
4003 case TARGET_F_SETLKW64:
bellard579a97f2007-11-11 14:26:47 +00004004 if (!lock_user_struct(VERIFY_READ, target_fl64, arg, 1))
4005 return -TARGET_EFAULT;
ths43f238d2007-01-05 20:55:49 +00004006 fl64.l_type = tswap16(target_fl64->l_type) >> 1;
4007 fl64.l_whence = tswap16(target_fl64->l_whence);
4008 fl64.l_start = tswapl(target_fl64->l_start);
4009 fl64.l_len = tswapl(target_fl64->l_len);
Ulrich Hecht7e22e542009-07-24 19:10:27 +02004010 fl64.l_pid = tswap32(target_fl64->l_pid);
ths43f238d2007-01-05 20:55:49 +00004011 unlock_user_struct(target_fl64, arg, 0);
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02004012 ret = get_errno(fcntl(fd, host_cmd, &fl64));
bellard7775e9e2003-05-14 22:46:48 +00004013 break;
4014
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02004015 case TARGET_F_GETFL:
4016 ret = get_errno(fcntl(fd, host_cmd, arg));
bellard9ee1fa22007-11-11 15:11:19 +00004017 if (ret >= 0) {
4018 ret = host_to_target_bitmask(ret, fcntl_flags_tbl);
4019 }
bellardffa65c32004-01-04 23:57:22 +00004020 break;
4021
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02004022 case TARGET_F_SETFL:
4023 ret = get_errno(fcntl(fd, host_cmd, target_to_host_bitmask(arg, fcntl_flags_tbl)));
4024 break;
4025
4026 case TARGET_F_SETOWN:
4027 case TARGET_F_GETOWN:
4028 case TARGET_F_SETSIG:
4029 case TARGET_F_GETSIG:
Ulrich Hecht7e22e542009-07-24 19:10:27 +02004030 case TARGET_F_SETLEASE:
4031 case TARGET_F_GETLEASE:
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02004032 ret = get_errno(fcntl(fd, host_cmd, arg));
bellardffa65c32004-01-04 23:57:22 +00004033 break;
4034
bellard7775e9e2003-05-14 22:46:48 +00004035 default:
bellard9ee1fa22007-11-11 15:11:19 +00004036 ret = get_errno(fcntl(fd, cmd, arg));
bellard7775e9e2003-05-14 22:46:48 +00004037 break;
4038 }
4039 return ret;
4040}
4041
bellard67867302003-11-23 17:05:30 +00004042#ifdef USE_UID16
bellard7775e9e2003-05-14 22:46:48 +00004043
bellard67867302003-11-23 17:05:30 +00004044static inline int high2lowuid(int uid)
4045{
4046 if (uid > 65535)
4047 return 65534;
4048 else
4049 return uid;
4050}
4051
4052static inline int high2lowgid(int gid)
4053{
4054 if (gid > 65535)
4055 return 65534;
4056 else
4057 return gid;
4058}
4059
4060static inline int low2highuid(int uid)
4061{
4062 if ((int16_t)uid == -1)
4063 return -1;
4064 else
4065 return uid;
4066}
4067
4068static inline int low2highgid(int gid)
4069{
4070 if ((int16_t)gid == -1)
4071 return -1;
4072 else
4073 return gid;
4074}
4075
4076#endif /* USE_UID16 */
bellard1b6b0292003-03-22 17:31:38 +00004077
bellard31e31b82003-02-18 22:55:36 +00004078void syscall_init(void)
4079{
bellard2ab83ea2003-06-15 19:56:46 +00004080 IOCTLEntry *ie;
4081 const argtype *arg_type;
4082 int size;
thsb92c47c2007-11-01 00:07:38 +00004083 int i;
bellard2ab83ea2003-06-15 19:56:46 +00004084
Blue Swirl001faf32009-05-13 17:53:17 +00004085#define STRUCT(name, ...) thunk_register_struct(STRUCT_ ## name, #name, struct_ ## name ## _def);
ths5fafdf22007-09-16 21:08:06 +00004086#define STRUCT_SPECIAL(name) thunk_register_struct_direct(STRUCT_ ## name, #name, &struct_ ## name ## _def);
bellard31e31b82003-02-18 22:55:36 +00004087#include "syscall_types.h"
4088#undef STRUCT
4089#undef STRUCT_SPECIAL
bellard2ab83ea2003-06-15 19:56:46 +00004090
4091 /* we patch the ioctl size if necessary. We rely on the fact that
4092 no ioctl has all the bits at '1' in the size field */
4093 ie = ioctl_entries;
4094 while (ie->target_cmd != 0) {
4095 if (((ie->target_cmd >> TARGET_IOC_SIZESHIFT) & TARGET_IOC_SIZEMASK) ==
4096 TARGET_IOC_SIZEMASK) {
4097 arg_type = ie->arg_type;
4098 if (arg_type[0] != TYPE_PTR) {
ths5fafdf22007-09-16 21:08:06 +00004099 fprintf(stderr, "cannot patch size for ioctl 0x%x\n",
bellard2ab83ea2003-06-15 19:56:46 +00004100 ie->target_cmd);
4101 exit(1);
4102 }
4103 arg_type++;
4104 size = thunk_type_size(arg_type, 0);
ths5fafdf22007-09-16 21:08:06 +00004105 ie->target_cmd = (ie->target_cmd &
bellard2ab83ea2003-06-15 19:56:46 +00004106 ~(TARGET_IOC_SIZEMASK << TARGET_IOC_SIZESHIFT)) |
4107 (size << TARGET_IOC_SIZESHIFT);
4108 }
thsb92c47c2007-11-01 00:07:38 +00004109
4110 /* Build target_to_host_errno_table[] table from
4111 * host_to_target_errno_table[]. */
4112 for (i=0; i < ERRNO_TABLE_SIZE; i++)
4113 target_to_host_errno_table[host_to_target_errno_table[i]] = i;
4114
bellard2ab83ea2003-06-15 19:56:46 +00004115 /* automatic consistency check if same arch */
balrog872ea0c2008-09-21 02:31:19 +00004116#if (defined(__i386__) && defined(TARGET_I386) && defined(TARGET_ABI32)) || \
4117 (defined(__x86_64__) && defined(TARGET_X86_64))
4118 if (unlikely(ie->target_cmd != ie->host_cmd)) {
4119 fprintf(stderr, "ERROR: ioctl(%s): target=0x%x host=0x%x\n",
4120 ie->name, ie->target_cmd, ie->host_cmd);
bellard2ab83ea2003-06-15 19:56:46 +00004121 }
4122#endif
4123 ie++;
4124 }
bellard31e31b82003-02-18 22:55:36 +00004125}
bellardc573ff62004-01-04 15:51:36 +00004126
blueswir1992f48a2007-10-14 16:27:31 +00004127#if TARGET_ABI_BITS == 32
pbrookce4defa2006-02-09 16:49:55 +00004128static inline uint64_t target_offset64(uint32_t word0, uint32_t word1)
4129{
thsaf325d32008-06-10 15:29:15 +00004130#ifdef TARGET_WORDS_BIGENDIAN
pbrookce4defa2006-02-09 16:49:55 +00004131 return ((uint64_t)word0 << 32) | word1;
4132#else
4133 return ((uint64_t)word1 << 32) | word0;
4134#endif
4135}
blueswir1992f48a2007-10-14 16:27:31 +00004136#else /* TARGET_ABI_BITS == 32 */
j_mayer32407102007-09-26 23:01:49 +00004137static inline uint64_t target_offset64(uint64_t word0, uint64_t word1)
4138{
4139 return word0;
4140}
blueswir1992f48a2007-10-14 16:27:31 +00004141#endif /* TARGET_ABI_BITS != 32 */
pbrookce4defa2006-02-09 16:49:55 +00004142
4143#ifdef TARGET_NR_truncate64
blueswir1992f48a2007-10-14 16:27:31 +00004144static inline abi_long target_truncate64(void *cpu_env, const char *arg1,
4145 abi_long arg2,
4146 abi_long arg3,
4147 abi_long arg4)
pbrookce4defa2006-02-09 16:49:55 +00004148{
4149#ifdef TARGET_ARM
4150 if (((CPUARMState *)cpu_env)->eabi)
4151 {
4152 arg2 = arg3;
4153 arg3 = arg4;
4154 }
4155#endif
4156 return get_errno(truncate64(arg1, target_offset64(arg2, arg3)));
4157}
4158#endif
4159
4160#ifdef TARGET_NR_ftruncate64
blueswir1992f48a2007-10-14 16:27:31 +00004161static inline abi_long target_ftruncate64(void *cpu_env, abi_long arg1,
4162 abi_long arg2,
4163 abi_long arg3,
4164 abi_long arg4)
pbrookce4defa2006-02-09 16:49:55 +00004165{
4166#ifdef TARGET_ARM
4167 if (((CPUARMState *)cpu_env)->eabi)
4168 {
4169 arg2 = arg3;
4170 arg3 = arg4;
4171 }
4172#endif
4173 return get_errno(ftruncate64(arg1, target_offset64(arg2, arg3)));
4174}
4175#endif
4176
bellard579a97f2007-11-11 14:26:47 +00004177static inline abi_long target_to_host_timespec(struct timespec *host_ts,
4178 abi_ulong target_addr)
pbrook53a59602006-03-25 19:31:22 +00004179{
4180 struct target_timespec *target_ts;
4181
bellard579a97f2007-11-11 14:26:47 +00004182 if (!lock_user_struct(VERIFY_READ, target_ts, target_addr, 1))
4183 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00004184 host_ts->tv_sec = tswapl(target_ts->tv_sec);
4185 host_ts->tv_nsec = tswapl(target_ts->tv_nsec);
4186 unlock_user_struct(target_ts, target_addr, 0);
bellardb255bfa2008-05-10 21:51:02 +00004187 return 0;
pbrook53a59602006-03-25 19:31:22 +00004188}
4189
bellard579a97f2007-11-11 14:26:47 +00004190static inline abi_long host_to_target_timespec(abi_ulong target_addr,
4191 struct timespec *host_ts)
pbrook53a59602006-03-25 19:31:22 +00004192{
4193 struct target_timespec *target_ts;
4194
bellard579a97f2007-11-11 14:26:47 +00004195 if (!lock_user_struct(VERIFY_WRITE, target_ts, target_addr, 0))
4196 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00004197 target_ts->tv_sec = tswapl(host_ts->tv_sec);
4198 target_ts->tv_nsec = tswapl(host_ts->tv_nsec);
4199 unlock_user_struct(target_ts, target_addr, 1);
bellardb255bfa2008-05-10 21:51:02 +00004200 return 0;
pbrook53a59602006-03-25 19:31:22 +00004201}
4202
aurel329d33b762009-04-08 23:07:05 +00004203#if defined(TARGET_NR_stat64) || defined(TARGET_NR_newfstatat)
balrog6a24a772008-09-20 02:23:36 +00004204static inline abi_long host_to_target_stat64(void *cpu_env,
4205 abi_ulong target_addr,
4206 struct stat *host_st)
4207{
4208#ifdef TARGET_ARM
4209 if (((CPUARMState *)cpu_env)->eabi) {
4210 struct target_eabi_stat64 *target_st;
4211
4212 if (!lock_user_struct(VERIFY_WRITE, target_st, target_addr, 0))
4213 return -TARGET_EFAULT;
4214 memset(target_st, 0, sizeof(struct target_eabi_stat64));
4215 __put_user(host_st->st_dev, &target_st->st_dev);
4216 __put_user(host_st->st_ino, &target_st->st_ino);
4217#ifdef TARGET_STAT64_HAS_BROKEN_ST_INO
4218 __put_user(host_st->st_ino, &target_st->__st_ino);
4219#endif
4220 __put_user(host_st->st_mode, &target_st->st_mode);
4221 __put_user(host_st->st_nlink, &target_st->st_nlink);
4222 __put_user(host_st->st_uid, &target_st->st_uid);
4223 __put_user(host_st->st_gid, &target_st->st_gid);
4224 __put_user(host_st->st_rdev, &target_st->st_rdev);
4225 __put_user(host_st->st_size, &target_st->st_size);
4226 __put_user(host_st->st_blksize, &target_st->st_blksize);
4227 __put_user(host_st->st_blocks, &target_st->st_blocks);
4228 __put_user(host_st->st_atime, &target_st->target_st_atime);
4229 __put_user(host_st->st_mtime, &target_st->target_st_mtime);
4230 __put_user(host_st->st_ctime, &target_st->target_st_ctime);
4231 unlock_user_struct(target_st, target_addr, 1);
4232 } else
4233#endif
4234 {
Richard Hendersoned18c5c2010-04-26 10:27:22 -07004235#if TARGET_ABI_BITS == 64 && !defined(TARGET_ALPHA)
aurel329d33b762009-04-08 23:07:05 +00004236 struct target_stat *target_st;
4237#else
balrog6a24a772008-09-20 02:23:36 +00004238 struct target_stat64 *target_st;
aurel329d33b762009-04-08 23:07:05 +00004239#endif
balrog6a24a772008-09-20 02:23:36 +00004240
4241 if (!lock_user_struct(VERIFY_WRITE, target_st, target_addr, 0))
4242 return -TARGET_EFAULT;
aurel329d33b762009-04-08 23:07:05 +00004243 memset(target_st, 0, sizeof(*target_st));
balrog6a24a772008-09-20 02:23:36 +00004244 __put_user(host_st->st_dev, &target_st->st_dev);
4245 __put_user(host_st->st_ino, &target_st->st_ino);
4246#ifdef TARGET_STAT64_HAS_BROKEN_ST_INO
4247 __put_user(host_st->st_ino, &target_st->__st_ino);
4248#endif
4249 __put_user(host_st->st_mode, &target_st->st_mode);
4250 __put_user(host_st->st_nlink, &target_st->st_nlink);
4251 __put_user(host_st->st_uid, &target_st->st_uid);
4252 __put_user(host_st->st_gid, &target_st->st_gid);
4253 __put_user(host_st->st_rdev, &target_st->st_rdev);
4254 /* XXX: better use of kernel struct */
4255 __put_user(host_st->st_size, &target_st->st_size);
4256 __put_user(host_st->st_blksize, &target_st->st_blksize);
4257 __put_user(host_st->st_blocks, &target_st->st_blocks);
4258 __put_user(host_st->st_atime, &target_st->target_st_atime);
4259 __put_user(host_st->st_mtime, &target_st->target_st_mtime);
4260 __put_user(host_st->st_ctime, &target_st->target_st_ctime);
4261 unlock_user_struct(target_st, target_addr, 1);
4262 }
4263
4264 return 0;
4265}
4266#endif
4267
Juan Quintela2f7bb872009-07-27 16:13:24 +02004268#if defined(CONFIG_USE_NPTL)
pbrookbd0c5662008-05-29 14:34:11 +00004269/* ??? Using host futex calls even when target atomic operations
4270 are not really atomic probably breaks things. However implementing
4271 futexes locally would make futexes shared between multiple processes
4272 tricky. However they're probably useless because guest atomic
4273 operations won't work either. */
blueswir18fcd3692008-08-17 20:26:25 +00004274static int do_futex(target_ulong uaddr, int op, int val, target_ulong timeout,
4275 target_ulong uaddr2, int val3)
pbrookbd0c5662008-05-29 14:34:11 +00004276{
4277 struct timespec ts, *pts;
Nathan Froyda16aae02009-08-03 08:43:29 -07004278 int base_op;
pbrookbd0c5662008-05-29 14:34:11 +00004279
4280 /* ??? We assume FUTEX_* constants are the same on both host
4281 and target. */
Martin Mohringa29ccd62009-05-04 21:34:56 +03004282#ifdef FUTEX_CMD_MASK
Nathan Froyda16aae02009-08-03 08:43:29 -07004283 base_op = op & FUTEX_CMD_MASK;
Martin Mohringa29ccd62009-05-04 21:34:56 +03004284#else
Nathan Froyda16aae02009-08-03 08:43:29 -07004285 base_op = op;
Martin Mohringa29ccd62009-05-04 21:34:56 +03004286#endif
Nathan Froyda16aae02009-08-03 08:43:29 -07004287 switch (base_op) {
pbrookbd0c5662008-05-29 14:34:11 +00004288 case FUTEX_WAIT:
4289 if (timeout) {
4290 pts = &ts;
4291 target_to_host_timespec(pts, timeout);
4292 } else {
4293 pts = NULL;
4294 }
Martin Mohringa29ccd62009-05-04 21:34:56 +03004295 return get_errno(sys_futex(g2h(uaddr), op, tswap32(val),
pbrookbd0c5662008-05-29 14:34:11 +00004296 pts, NULL, 0));
4297 case FUTEX_WAKE:
Martin Mohringa29ccd62009-05-04 21:34:56 +03004298 return get_errno(sys_futex(g2h(uaddr), op, val, NULL, NULL, 0));
pbrookbd0c5662008-05-29 14:34:11 +00004299 case FUTEX_FD:
Martin Mohringa29ccd62009-05-04 21:34:56 +03004300 return get_errno(sys_futex(g2h(uaddr), op, val, NULL, NULL, 0));
pbrookbd0c5662008-05-29 14:34:11 +00004301 case FUTEX_REQUEUE:
pbrookbd0c5662008-05-29 14:34:11 +00004302 case FUTEX_CMP_REQUEUE:
Nathan Froyda16aae02009-08-03 08:43:29 -07004303 case FUTEX_WAKE_OP:
4304 /* For FUTEX_REQUEUE, FUTEX_CMP_REQUEUE, and FUTEX_WAKE_OP, the
4305 TIMEOUT parameter is interpreted as a uint32_t by the kernel.
4306 But the prototype takes a `struct timespec *'; insert casts
4307 to satisfy the compiler. We do not need to tswap TIMEOUT
4308 since it's not compared to guest memory. */
4309 pts = (struct timespec *)(uintptr_t) timeout;
4310 return get_errno(sys_futex(g2h(uaddr), op, val, pts,
4311 g2h(uaddr2),
4312 (base_op == FUTEX_CMP_REQUEUE
4313 ? tswap32(val3)
4314 : val3)));
pbrookbd0c5662008-05-29 14:34:11 +00004315 default:
4316 return -TARGET_ENOSYS;
4317 }
4318}
4319#endif
4320
pbrook1d9d8b52009-04-16 15:17:02 +00004321/* Map host to target signal numbers for the wait family of syscalls.
4322 Assume all other status bits are the same. */
4323static int host_to_target_waitstatus(int status)
4324{
4325 if (WIFSIGNALED(status)) {
4326 return host_to_target_signal(WTERMSIG(status)) | (status & ~0x7f);
4327 }
4328 if (WIFSTOPPED(status)) {
4329 return (host_to_target_signal(WSTOPSIG(status)) << 8)
4330 | (status & 0xff);
4331 }
4332 return status;
4333}
4334
pbrooka745ec62008-05-06 15:36:17 +00004335int get_osversion(void)
4336{
4337 static int osversion;
4338 struct new_utsname buf;
4339 const char *s;
4340 int i, n, tmp;
4341 if (osversion)
4342 return osversion;
4343 if (qemu_uname_release && *qemu_uname_release) {
4344 s = qemu_uname_release;
4345 } else {
4346 if (sys_uname(&buf))
4347 return 0;
4348 s = buf.release;
4349 }
4350 tmp = 0;
4351 for (i = 0; i < 3; i++) {
4352 n = 0;
4353 while (*s >= '0' && *s <= '9') {
4354 n *= 10;
4355 n += *s - '0';
4356 s++;
4357 }
4358 tmp = (tmp << 8) + n;
4359 if (*s == '.')
4360 s++;
4361 }
4362 osversion = tmp;
4363 return osversion;
4364}
4365
ths0da46a62007-10-20 20:23:07 +00004366/* do_syscall() should always have a single exit point at the end so
4367 that actions, such as logging of syscall results, can be performed.
4368 All errnos that do_syscall() returns must be -TARGET_<errcode>. */
blueswir1992f48a2007-10-14 16:27:31 +00004369abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
4370 abi_long arg2, abi_long arg3, abi_long arg4,
4371 abi_long arg5, abi_long arg6)
bellard31e31b82003-02-18 22:55:36 +00004372{
blueswir1992f48a2007-10-14 16:27:31 +00004373 abi_long ret;
bellard31e31b82003-02-18 22:55:36 +00004374 struct stat st;
bellard56c8f682005-11-28 22:28:41 +00004375 struct statfs stfs;
pbrook53a59602006-03-25 19:31:22 +00004376 void *p;
ths3b46e622007-09-17 08:09:54 +00004377
bellard72f03902003-02-18 23:33:18 +00004378#ifdef DEBUG
bellardc573ff62004-01-04 15:51:36 +00004379 gemu_log("syscall %d", num);
bellard72f03902003-02-18 23:33:18 +00004380#endif
thsb92c47c2007-11-01 00:07:38 +00004381 if(do_strace)
4382 print_syscall(num, arg1, arg2, arg3, arg4, arg5, arg6);
4383
bellard31e31b82003-02-18 22:55:36 +00004384 switch(num) {
4385 case TARGET_NR_exit:
Juan Quintela2f7bb872009-07-27 16:13:24 +02004386#ifdef CONFIG_USE_NPTL
pbrookc2764712009-03-07 15:24:59 +00004387 /* In old applications this may be used to implement _exit(2).
4388 However in threaded applictions it is used for thread termination,
4389 and _exit_group is used for application termination.
4390 Do thread termination if we have more then one thread. */
4391 /* FIXME: This probably breaks if a signal arrives. We should probably
4392 be disabling signals. */
4393 if (first_cpu->next_cpu) {
Nathan Froyd1e9fa732009-06-03 11:33:08 -07004394 TaskState *ts;
pbrookc2764712009-03-07 15:24:59 +00004395 CPUState **lastp;
4396 CPUState *p;
4397
4398 cpu_list_lock();
4399 lastp = &first_cpu;
4400 p = first_cpu;
4401 while (p && p != (CPUState *)cpu_env) {
4402 lastp = &p->next_cpu;
4403 p = p->next_cpu;
4404 }
4405 /* If we didn't find the CPU for this thread then something is
4406 horribly wrong. */
4407 if (!p)
4408 abort();
4409 /* Remove the CPU from the list. */
4410 *lastp = p->next_cpu;
4411 cpu_list_unlock();
Nathan Froyd1e9fa732009-06-03 11:33:08 -07004412 ts = ((CPUState *)cpu_env)->opaque;
pbrookc2764712009-03-07 15:24:59 +00004413 if (ts->child_tidptr) {
4414 put_user_u32(0, ts->child_tidptr);
4415 sys_futex(g2h(ts->child_tidptr), FUTEX_WAKE, INT_MAX,
4416 NULL, NULL, 0);
4417 }
Nathan Froyd48e15fc2010-10-29 07:48:57 -07004418 thread_env = NULL;
4419 qemu_free(cpu_env);
4420 qemu_free(ts);
pbrookc2764712009-03-07 15:24:59 +00004421 pthread_exit(NULL);
4422 }
4423#endif
Juan Quintela9788c9c2009-07-27 16:13:02 +02004424#ifdef TARGET_GPROF
bellard7d132992003-03-06 23:23:54 +00004425 _mcleanup();
4426#endif
bellarde9009672005-04-26 20:42:36 +00004427 gdb_exit(cpu_env, arg1);
pbrookc2764712009-03-07 15:24:59 +00004428 _exit(arg1);
bellard31e31b82003-02-18 22:55:36 +00004429 ret = 0; /* avoid warning */
4430 break;
4431 case TARGET_NR_read:
aurel3238d840e2009-01-30 19:48:17 +00004432 if (arg3 == 0)
4433 ret = 0;
4434 else {
4435 if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
4436 goto efault;
4437 ret = get_errno(read(arg1, p, arg3));
4438 unlock_user(p, arg2, ret);
4439 }
bellard31e31b82003-02-18 22:55:36 +00004440 break;
4441 case TARGET_NR_write:
bellard579a97f2007-11-11 14:26:47 +00004442 if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
4443 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004444 ret = get_errno(write(arg1, p, arg3));
4445 unlock_user(p, arg2, 0);
bellard31e31b82003-02-18 22:55:36 +00004446 break;
4447 case TARGET_NR_open:
bellard2f619692007-11-16 10:46:05 +00004448 if (!(p = lock_user_string(arg1)))
4449 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004450 ret = get_errno(open(path(p),
bellardffa65c32004-01-04 23:57:22 +00004451 target_to_host_bitmask(arg2, fcntl_flags_tbl),
4452 arg3));
pbrook53a59602006-03-25 19:31:22 +00004453 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004454 break;
ths82424832007-09-24 09:21:55 +00004455#if defined(TARGET_NR_openat) && defined(__NR_openat)
4456 case TARGET_NR_openat:
bellard579a97f2007-11-11 14:26:47 +00004457 if (!(p = lock_user_string(arg2)))
4458 goto efault;
4459 ret = get_errno(sys_openat(arg1,
4460 path(p),
4461 target_to_host_bitmask(arg3, fcntl_flags_tbl),
4462 arg4));
4463 unlock_user(p, arg2, 0);
ths82424832007-09-24 09:21:55 +00004464 break;
4465#endif
bellard31e31b82003-02-18 22:55:36 +00004466 case TARGET_NR_close:
4467 ret = get_errno(close(arg1));
4468 break;
4469 case TARGET_NR_brk:
pbrook53a59602006-03-25 19:31:22 +00004470 ret = do_brk(arg1);
bellard31e31b82003-02-18 22:55:36 +00004471 break;
4472 case TARGET_NR_fork:
pbrookd865bab2008-06-07 22:12:17 +00004473 ret = get_errno(do_fork(cpu_env, SIGCHLD, 0, 0, 0, 0));
bellard31e31b82003-02-18 22:55:36 +00004474 break;
thse5febef2007-04-01 18:31:35 +00004475#ifdef TARGET_NR_waitpid
bellard31e31b82003-02-18 22:55:36 +00004476 case TARGET_NR_waitpid:
4477 {
pbrook53a59602006-03-25 19:31:22 +00004478 int status;
4479 ret = get_errno(waitpid(arg1, &status, arg3));
bellard2f619692007-11-16 10:46:05 +00004480 if (!is_error(ret) && arg2
pbrook1d9d8b52009-04-16 15:17:02 +00004481 && put_user_s32(host_to_target_waitstatus(status), arg2))
bellard2f619692007-11-16 10:46:05 +00004482 goto efault;
bellard31e31b82003-02-18 22:55:36 +00004483 }
4484 break;
thse5febef2007-04-01 18:31:35 +00004485#endif
pbrookf0cbb612008-05-30 18:20:05 +00004486#ifdef TARGET_NR_waitid
4487 case TARGET_NR_waitid:
4488 {
4489 siginfo_t info;
4490 info.si_pid = 0;
4491 ret = get_errno(waitid(arg1, arg2, &info, arg4));
4492 if (!is_error(ret) && arg3 && info.si_pid != 0) {
Anthony Liguoric227f092009-10-01 16:12:16 -05004493 if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_siginfo_t), 0)))
pbrookf0cbb612008-05-30 18:20:05 +00004494 goto efault;
4495 host_to_target_siginfo(p, &info);
Anthony Liguoric227f092009-10-01 16:12:16 -05004496 unlock_user(p, arg3, sizeof(target_siginfo_t));
pbrookf0cbb612008-05-30 18:20:05 +00004497 }
4498 }
4499 break;
4500#endif
j_mayer7a3148a2007-04-05 07:13:51 +00004501#ifdef TARGET_NR_creat /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00004502 case TARGET_NR_creat:
bellard579a97f2007-11-11 14:26:47 +00004503 if (!(p = lock_user_string(arg1)))
4504 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004505 ret = get_errno(creat(p, arg2));
4506 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004507 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004508#endif
bellard31e31b82003-02-18 22:55:36 +00004509 case TARGET_NR_link:
pbrook53a59602006-03-25 19:31:22 +00004510 {
4511 void * p2;
4512 p = lock_user_string(arg1);
4513 p2 = lock_user_string(arg2);
bellard579a97f2007-11-11 14:26:47 +00004514 if (!p || !p2)
4515 ret = -TARGET_EFAULT;
4516 else
4517 ret = get_errno(link(p, p2));
pbrook53a59602006-03-25 19:31:22 +00004518 unlock_user(p2, arg2, 0);
4519 unlock_user(p, arg1, 0);
4520 }
bellard31e31b82003-02-18 22:55:36 +00004521 break;
ths64f0ce42007-09-24 09:25:06 +00004522#if defined(TARGET_NR_linkat) && defined(__NR_linkat)
4523 case TARGET_NR_linkat:
ths64f0ce42007-09-24 09:25:06 +00004524 {
4525 void * p2 = NULL;
bellard579a97f2007-11-11 14:26:47 +00004526 if (!arg2 || !arg4)
4527 goto efault;
ths64f0ce42007-09-24 09:25:06 +00004528 p = lock_user_string(arg2);
4529 p2 = lock_user_string(arg4);
bellard579a97f2007-11-11 14:26:47 +00004530 if (!p || !p2)
ths0da46a62007-10-20 20:23:07 +00004531 ret = -TARGET_EFAULT;
ths64f0ce42007-09-24 09:25:06 +00004532 else
4533 ret = get_errno(sys_linkat(arg1, p, arg3, p2, arg5));
bellard579a97f2007-11-11 14:26:47 +00004534 unlock_user(p, arg2, 0);
4535 unlock_user(p2, arg4, 0);
ths64f0ce42007-09-24 09:25:06 +00004536 }
4537 break;
4538#endif
bellard31e31b82003-02-18 22:55:36 +00004539 case TARGET_NR_unlink:
bellard579a97f2007-11-11 14:26:47 +00004540 if (!(p = lock_user_string(arg1)))
4541 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004542 ret = get_errno(unlink(p));
4543 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004544 break;
ths8170f562007-09-24 09:24:11 +00004545#if defined(TARGET_NR_unlinkat) && defined(__NR_unlinkat)
4546 case TARGET_NR_unlinkat:
bellard579a97f2007-11-11 14:26:47 +00004547 if (!(p = lock_user_string(arg2)))
4548 goto efault;
4549 ret = get_errno(sys_unlinkat(arg1, p, arg3));
4550 unlock_user(p, arg2, 0);
balroged494d82007-12-11 23:23:52 +00004551 break;
balrogb7d35e62007-12-12 00:40:24 +00004552#endif
bellard31e31b82003-02-18 22:55:36 +00004553 case TARGET_NR_execve:
bellard7854b052003-03-29 17:22:23 +00004554 {
4555 char **argp, **envp;
bellardf7341ff2003-03-30 21:00:25 +00004556 int argc, envc;
blueswir1992f48a2007-10-14 16:27:31 +00004557 abi_ulong gp;
4558 abi_ulong guest_argp;
4559 abi_ulong guest_envp;
4560 abi_ulong addr;
bellard7854b052003-03-29 17:22:23 +00004561 char **q;
4562
bellardf7341ff2003-03-30 21:00:25 +00004563 argc = 0;
pbrook53a59602006-03-25 19:31:22 +00004564 guest_argp = arg2;
pbrookda94d262008-05-30 18:24:00 +00004565 for (gp = guest_argp; gp; gp += sizeof(abi_ulong)) {
ths03aa1972007-12-02 06:28:08 +00004566 if (get_user_ual(addr, gp))
bellard2f619692007-11-16 10:46:05 +00004567 goto efault;
ths03aa1972007-12-02 06:28:08 +00004568 if (!addr)
bellard2f619692007-11-16 10:46:05 +00004569 break;
bellard7854b052003-03-29 17:22:23 +00004570 argc++;
bellard2f619692007-11-16 10:46:05 +00004571 }
bellardf7341ff2003-03-30 21:00:25 +00004572 envc = 0;
pbrook53a59602006-03-25 19:31:22 +00004573 guest_envp = arg3;
pbrookda94d262008-05-30 18:24:00 +00004574 for (gp = guest_envp; gp; gp += sizeof(abi_ulong)) {
ths03aa1972007-12-02 06:28:08 +00004575 if (get_user_ual(addr, gp))
bellard2f619692007-11-16 10:46:05 +00004576 goto efault;
ths03aa1972007-12-02 06:28:08 +00004577 if (!addr)
bellard2f619692007-11-16 10:46:05 +00004578 break;
bellard7854b052003-03-29 17:22:23 +00004579 envc++;
bellard2f619692007-11-16 10:46:05 +00004580 }
bellard7854b052003-03-29 17:22:23 +00004581
bellardf7341ff2003-03-30 21:00:25 +00004582 argp = alloca((argc + 1) * sizeof(void *));
4583 envp = alloca((envc + 1) * sizeof(void *));
bellard7854b052003-03-29 17:22:23 +00004584
pbrookda94d262008-05-30 18:24:00 +00004585 for (gp = guest_argp, q = argp; gp;
blueswir1992f48a2007-10-14 16:27:31 +00004586 gp += sizeof(abi_ulong), q++) {
bellard2f619692007-11-16 10:46:05 +00004587 if (get_user_ual(addr, gp))
4588 goto execve_efault;
pbrook53a59602006-03-25 19:31:22 +00004589 if (!addr)
4590 break;
bellard2f619692007-11-16 10:46:05 +00004591 if (!(*q = lock_user_string(addr)))
4592 goto execve_efault;
pbrook53a59602006-03-25 19:31:22 +00004593 }
bellardf7341ff2003-03-30 21:00:25 +00004594 *q = NULL;
4595
pbrookda94d262008-05-30 18:24:00 +00004596 for (gp = guest_envp, q = envp; gp;
blueswir1992f48a2007-10-14 16:27:31 +00004597 gp += sizeof(abi_ulong), q++) {
bellard2f619692007-11-16 10:46:05 +00004598 if (get_user_ual(addr, gp))
4599 goto execve_efault;
pbrook53a59602006-03-25 19:31:22 +00004600 if (!addr)
4601 break;
bellard2f619692007-11-16 10:46:05 +00004602 if (!(*q = lock_user_string(addr)))
4603 goto execve_efault;
pbrook53a59602006-03-25 19:31:22 +00004604 }
bellardf7341ff2003-03-30 21:00:25 +00004605 *q = NULL;
bellard7854b052003-03-29 17:22:23 +00004606
bellard2f619692007-11-16 10:46:05 +00004607 if (!(p = lock_user_string(arg1)))
4608 goto execve_efault;
pbrook53a59602006-03-25 19:31:22 +00004609 ret = get_errno(execve(p, argp, envp));
4610 unlock_user(p, arg1, 0);
4611
bellard2f619692007-11-16 10:46:05 +00004612 goto execve_end;
4613
4614 execve_efault:
4615 ret = -TARGET_EFAULT;
4616
4617 execve_end:
pbrook53a59602006-03-25 19:31:22 +00004618 for (gp = guest_argp, q = argp; *q;
blueswir1992f48a2007-10-14 16:27:31 +00004619 gp += sizeof(abi_ulong), q++) {
bellard2f619692007-11-16 10:46:05 +00004620 if (get_user_ual(addr, gp)
4621 || !addr)
4622 break;
pbrook53a59602006-03-25 19:31:22 +00004623 unlock_user(*q, addr, 0);
4624 }
4625 for (gp = guest_envp, q = envp; *q;
blueswir1992f48a2007-10-14 16:27:31 +00004626 gp += sizeof(abi_ulong), q++) {
bellard2f619692007-11-16 10:46:05 +00004627 if (get_user_ual(addr, gp)
4628 || !addr)
4629 break;
pbrook53a59602006-03-25 19:31:22 +00004630 unlock_user(*q, addr, 0);
4631 }
bellard7854b052003-03-29 17:22:23 +00004632 }
bellard31e31b82003-02-18 22:55:36 +00004633 break;
4634 case TARGET_NR_chdir:
bellard579a97f2007-11-11 14:26:47 +00004635 if (!(p = lock_user_string(arg1)))
4636 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004637 ret = get_errno(chdir(p));
4638 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004639 break;
bellarda315a142005-01-30 22:59:18 +00004640#ifdef TARGET_NR_time
bellard31e31b82003-02-18 22:55:36 +00004641 case TARGET_NR_time:
4642 {
pbrook53a59602006-03-25 19:31:22 +00004643 time_t host_time;
4644 ret = get_errno(time(&host_time));
bellard2f619692007-11-16 10:46:05 +00004645 if (!is_error(ret)
4646 && arg1
4647 && put_user_sal(host_time, arg1))
4648 goto efault;
bellard31e31b82003-02-18 22:55:36 +00004649 }
4650 break;
bellarda315a142005-01-30 22:59:18 +00004651#endif
bellard31e31b82003-02-18 22:55:36 +00004652 case TARGET_NR_mknod:
bellard579a97f2007-11-11 14:26:47 +00004653 if (!(p = lock_user_string(arg1)))
4654 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004655 ret = get_errno(mknod(p, arg2, arg3));
4656 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004657 break;
ths75ac37a2007-09-24 09:23:05 +00004658#if defined(TARGET_NR_mknodat) && defined(__NR_mknodat)
4659 case TARGET_NR_mknodat:
bellard579a97f2007-11-11 14:26:47 +00004660 if (!(p = lock_user_string(arg2)))
4661 goto efault;
4662 ret = get_errno(sys_mknodat(arg1, p, arg3, arg4));
4663 unlock_user(p, arg2, 0);
ths75ac37a2007-09-24 09:23:05 +00004664 break;
4665#endif
bellard31e31b82003-02-18 22:55:36 +00004666 case TARGET_NR_chmod:
bellard579a97f2007-11-11 14:26:47 +00004667 if (!(p = lock_user_string(arg1)))
4668 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004669 ret = get_errno(chmod(p, arg2));
4670 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004671 break;
bellardebc05482003-09-30 21:08:41 +00004672#ifdef TARGET_NR_break
bellard31e31b82003-02-18 22:55:36 +00004673 case TARGET_NR_break:
4674 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004675#endif
4676#ifdef TARGET_NR_oldstat
bellard31e31b82003-02-18 22:55:36 +00004677 case TARGET_NR_oldstat:
4678 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004679#endif
bellard31e31b82003-02-18 22:55:36 +00004680 case TARGET_NR_lseek:
4681 ret = get_errno(lseek(arg1, arg2, arg3));
4682 break;
Richard Henderson92317332010-05-03 10:07:53 -07004683#if defined(TARGET_NR_getxpid) && defined(TARGET_ALPHA)
4684 /* Alpha specific */
j_mayer7a3148a2007-04-05 07:13:51 +00004685 case TARGET_NR_getxpid:
Richard Henderson92317332010-05-03 10:07:53 -07004686 ((CPUAlphaState *)cpu_env)->ir[IR_A4] = getppid();
bellard31e31b82003-02-18 22:55:36 +00004687 ret = get_errno(getpid());
4688 break;
Richard Henderson92317332010-05-03 10:07:53 -07004689#endif
4690#ifdef TARGET_NR_getpid
4691 case TARGET_NR_getpid:
4692 ret = get_errno(getpid());
4693 break;
4694#endif
bellard31e31b82003-02-18 22:55:36 +00004695 case TARGET_NR_mount:
ths80265912007-02-17 22:25:41 +00004696 {
4697 /* need to look at the data field */
4698 void *p2, *p3;
4699 p = lock_user_string(arg1);
4700 p2 = lock_user_string(arg2);
4701 p3 = lock_user_string(arg3);
bellard579a97f2007-11-11 14:26:47 +00004702 if (!p || !p2 || !p3)
4703 ret = -TARGET_EFAULT;
Jan-Simon Möllerdab46402009-10-17 21:52:43 +03004704 else {
bellard579a97f2007-11-11 14:26:47 +00004705 /* FIXME - arg5 should be locked, but it isn't clear how to
4706 * do that since it's not guaranteed to be a NULL-terminated
4707 * string.
4708 */
Jan-Simon Möllerdab46402009-10-17 21:52:43 +03004709 if ( ! arg5 )
4710 ret = get_errno(mount(p, p2, p3, (unsigned long)arg4, NULL));
4711 else
4712 ret = get_errno(mount(p, p2, p3, (unsigned long)arg4, g2h(arg5)));
4713 }
bellard579a97f2007-11-11 14:26:47 +00004714 unlock_user(p, arg1, 0);
4715 unlock_user(p2, arg2, 0);
4716 unlock_user(p3, arg3, 0);
ths80265912007-02-17 22:25:41 +00004717 break;
4718 }
thse5febef2007-04-01 18:31:35 +00004719#ifdef TARGET_NR_umount
bellard31e31b82003-02-18 22:55:36 +00004720 case TARGET_NR_umount:
bellard579a97f2007-11-11 14:26:47 +00004721 if (!(p = lock_user_string(arg1)))
4722 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004723 ret = get_errno(umount(p));
4724 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004725 break;
thse5febef2007-04-01 18:31:35 +00004726#endif
j_mayer7a3148a2007-04-05 07:13:51 +00004727#ifdef TARGET_NR_stime /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00004728 case TARGET_NR_stime:
4729 {
pbrook53a59602006-03-25 19:31:22 +00004730 time_t host_time;
bellard2f619692007-11-16 10:46:05 +00004731 if (get_user_sal(host_time, arg1))
4732 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004733 ret = get_errno(stime(&host_time));
bellard31e31b82003-02-18 22:55:36 +00004734 }
4735 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004736#endif
bellard31e31b82003-02-18 22:55:36 +00004737 case TARGET_NR_ptrace:
4738 goto unimplemented;
j_mayer7a3148a2007-04-05 07:13:51 +00004739#ifdef TARGET_NR_alarm /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00004740 case TARGET_NR_alarm:
4741 ret = alarm(arg1);
4742 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004743#endif
bellardebc05482003-09-30 21:08:41 +00004744#ifdef TARGET_NR_oldfstat
bellard31e31b82003-02-18 22:55:36 +00004745 case TARGET_NR_oldfstat:
4746 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004747#endif
j_mayer7a3148a2007-04-05 07:13:51 +00004748#ifdef TARGET_NR_pause /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00004749 case TARGET_NR_pause:
4750 ret = get_errno(pause());
4751 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004752#endif
thse5febef2007-04-01 18:31:35 +00004753#ifdef TARGET_NR_utime
bellard31e31b82003-02-18 22:55:36 +00004754 case TARGET_NR_utime:
bellardebc05482003-09-30 21:08:41 +00004755 {
pbrook53a59602006-03-25 19:31:22 +00004756 struct utimbuf tbuf, *host_tbuf;
4757 struct target_utimbuf *target_tbuf;
4758 if (arg2) {
bellard579a97f2007-11-11 14:26:47 +00004759 if (!lock_user_struct(VERIFY_READ, target_tbuf, arg2, 1))
4760 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004761 tbuf.actime = tswapl(target_tbuf->actime);
4762 tbuf.modtime = tswapl(target_tbuf->modtime);
4763 unlock_user_struct(target_tbuf, arg2, 0);
4764 host_tbuf = &tbuf;
bellardf72e8ff2004-05-03 19:23:07 +00004765 } else {
pbrook53a59602006-03-25 19:31:22 +00004766 host_tbuf = NULL;
bellardf72e8ff2004-05-03 19:23:07 +00004767 }
bellard579a97f2007-11-11 14:26:47 +00004768 if (!(p = lock_user_string(arg1)))
4769 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004770 ret = get_errno(utime(p, host_tbuf));
4771 unlock_user(p, arg1, 0);
bellardebc05482003-09-30 21:08:41 +00004772 }
4773 break;
thse5febef2007-04-01 18:31:35 +00004774#endif
bellard978a66f2004-12-06 22:58:05 +00004775 case TARGET_NR_utimes:
4776 {
bellard978a66f2004-12-06 22:58:05 +00004777 struct timeval *tvp, tv[2];
pbrook53a59602006-03-25 19:31:22 +00004778 if (arg2) {
ths788f5ec2007-12-09 02:37:05 +00004779 if (copy_from_user_timeval(&tv[0], arg2)
4780 || copy_from_user_timeval(&tv[1],
4781 arg2 + sizeof(struct target_timeval)))
4782 goto efault;
bellard978a66f2004-12-06 22:58:05 +00004783 tvp = tv;
4784 } else {
4785 tvp = NULL;
4786 }
bellard579a97f2007-11-11 14:26:47 +00004787 if (!(p = lock_user_string(arg1)))
4788 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004789 ret = get_errno(utimes(p, tvp));
4790 unlock_user(p, arg1, 0);
bellard978a66f2004-12-06 22:58:05 +00004791 }
4792 break;
balrogac8a6552008-09-20 02:25:39 +00004793#if defined(TARGET_NR_futimesat) && defined(__NR_futimesat)
4794 case TARGET_NR_futimesat:
4795 {
4796 struct timeval *tvp, tv[2];
4797 if (arg3) {
4798 if (copy_from_user_timeval(&tv[0], arg3)
4799 || copy_from_user_timeval(&tv[1],
4800 arg3 + sizeof(struct target_timeval)))
4801 goto efault;
4802 tvp = tv;
4803 } else {
4804 tvp = NULL;
4805 }
4806 if (!(p = lock_user_string(arg2)))
4807 goto efault;
4808 ret = get_errno(sys_futimesat(arg1, path(p), tvp));
4809 unlock_user(p, arg2, 0);
4810 }
4811 break;
4812#endif
bellardebc05482003-09-30 21:08:41 +00004813#ifdef TARGET_NR_stty
bellard31e31b82003-02-18 22:55:36 +00004814 case TARGET_NR_stty:
4815 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004816#endif
4817#ifdef TARGET_NR_gtty
bellard31e31b82003-02-18 22:55:36 +00004818 case TARGET_NR_gtty:
4819 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004820#endif
bellard31e31b82003-02-18 22:55:36 +00004821 case TARGET_NR_access:
bellard579a97f2007-11-11 14:26:47 +00004822 if (!(p = lock_user_string(arg1)))
4823 goto efault;
Ulrich Hecht719f9082009-07-03 17:09:29 +02004824 ret = get_errno(access(path(p), arg2));
pbrook53a59602006-03-25 19:31:22 +00004825 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004826 break;
ths92a34c12007-09-24 09:27:49 +00004827#if defined(TARGET_NR_faccessat) && defined(__NR_faccessat)
4828 case TARGET_NR_faccessat:
bellard579a97f2007-11-11 14:26:47 +00004829 if (!(p = lock_user_string(arg2)))
4830 goto efault;
aurel32465c9f02009-04-19 08:52:17 +00004831 ret = get_errno(sys_faccessat(arg1, p, arg3));
bellard579a97f2007-11-11 14:26:47 +00004832 unlock_user(p, arg2, 0);
ths92a34c12007-09-24 09:27:49 +00004833 break;
4834#endif
j_mayer7a3148a2007-04-05 07:13:51 +00004835#ifdef TARGET_NR_nice /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00004836 case TARGET_NR_nice:
4837 ret = get_errno(nice(arg1));
4838 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004839#endif
bellardebc05482003-09-30 21:08:41 +00004840#ifdef TARGET_NR_ftime
bellard31e31b82003-02-18 22:55:36 +00004841 case TARGET_NR_ftime:
4842 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004843#endif
bellard31e31b82003-02-18 22:55:36 +00004844 case TARGET_NR_sync:
bellard04369ff2003-03-20 22:33:23 +00004845 sync();
4846 ret = 0;
bellard31e31b82003-02-18 22:55:36 +00004847 break;
4848 case TARGET_NR_kill:
pbrook4cb05962008-05-30 18:05:19 +00004849 ret = get_errno(kill(arg1, target_to_host_signal(arg2)));
bellard31e31b82003-02-18 22:55:36 +00004850 break;
4851 case TARGET_NR_rename:
pbrook53a59602006-03-25 19:31:22 +00004852 {
4853 void *p2;
4854 p = lock_user_string(arg1);
4855 p2 = lock_user_string(arg2);
bellard579a97f2007-11-11 14:26:47 +00004856 if (!p || !p2)
4857 ret = -TARGET_EFAULT;
4858 else
4859 ret = get_errno(rename(p, p2));
pbrook53a59602006-03-25 19:31:22 +00004860 unlock_user(p2, arg2, 0);
4861 unlock_user(p, arg1, 0);
4862 }
bellard31e31b82003-02-18 22:55:36 +00004863 break;
ths722183f2007-09-24 09:24:37 +00004864#if defined(TARGET_NR_renameat) && defined(__NR_renameat)
4865 case TARGET_NR_renameat:
ths722183f2007-09-24 09:24:37 +00004866 {
bellard579a97f2007-11-11 14:26:47 +00004867 void *p2;
ths722183f2007-09-24 09:24:37 +00004868 p = lock_user_string(arg2);
4869 p2 = lock_user_string(arg4);
bellard579a97f2007-11-11 14:26:47 +00004870 if (!p || !p2)
ths0da46a62007-10-20 20:23:07 +00004871 ret = -TARGET_EFAULT;
ths722183f2007-09-24 09:24:37 +00004872 else
4873 ret = get_errno(sys_renameat(arg1, p, arg3, p2));
bellard579a97f2007-11-11 14:26:47 +00004874 unlock_user(p2, arg4, 0);
4875 unlock_user(p, arg2, 0);
ths722183f2007-09-24 09:24:37 +00004876 }
4877 break;
4878#endif
bellard31e31b82003-02-18 22:55:36 +00004879 case TARGET_NR_mkdir:
bellard579a97f2007-11-11 14:26:47 +00004880 if (!(p = lock_user_string(arg1)))
4881 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004882 ret = get_errno(mkdir(p, arg2));
4883 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004884 break;
ths4472ad02007-09-24 09:22:32 +00004885#if defined(TARGET_NR_mkdirat) && defined(__NR_mkdirat)
4886 case TARGET_NR_mkdirat:
bellard579a97f2007-11-11 14:26:47 +00004887 if (!(p = lock_user_string(arg2)))
4888 goto efault;
4889 ret = get_errno(sys_mkdirat(arg1, p, arg3));
4890 unlock_user(p, arg2, 0);
ths4472ad02007-09-24 09:22:32 +00004891 break;
4892#endif
bellard31e31b82003-02-18 22:55:36 +00004893 case TARGET_NR_rmdir:
bellard579a97f2007-11-11 14:26:47 +00004894 if (!(p = lock_user_string(arg1)))
4895 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004896 ret = get_errno(rmdir(p));
4897 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004898 break;
4899 case TARGET_NR_dup:
4900 ret = get_errno(dup(arg1));
4901 break;
4902 case TARGET_NR_pipe:
Richard Hendersonfb41a662010-05-03 10:07:52 -07004903 ret = do_pipe(cpu_env, arg1, 0, 0);
bellard31e31b82003-02-18 22:55:36 +00004904 break;
Riku Voipio099d6b02009-05-05 12:10:04 +03004905#ifdef TARGET_NR_pipe2
4906 case TARGET_NR_pipe2:
Richard Hendersonfb41a662010-05-03 10:07:52 -07004907 ret = do_pipe(cpu_env, arg1, arg2, 1);
Riku Voipio099d6b02009-05-05 12:10:04 +03004908 break;
4909#endif
bellard31e31b82003-02-18 22:55:36 +00004910 case TARGET_NR_times:
bellard32f36bc2003-03-30 21:29:48 +00004911 {
pbrook53a59602006-03-25 19:31:22 +00004912 struct target_tms *tmsp;
bellard32f36bc2003-03-30 21:29:48 +00004913 struct tms tms;
4914 ret = get_errno(times(&tms));
pbrook53a59602006-03-25 19:31:22 +00004915 if (arg1) {
bellard579a97f2007-11-11 14:26:47 +00004916 tmsp = lock_user(VERIFY_WRITE, arg1, sizeof(struct target_tms), 0);
4917 if (!tmsp)
4918 goto efault;
bellardc596ed12003-07-13 17:32:31 +00004919 tmsp->tms_utime = tswapl(host_to_target_clock_t(tms.tms_utime));
4920 tmsp->tms_stime = tswapl(host_to_target_clock_t(tms.tms_stime));
4921 tmsp->tms_cutime = tswapl(host_to_target_clock_t(tms.tms_cutime));
4922 tmsp->tms_cstime = tswapl(host_to_target_clock_t(tms.tms_cstime));
bellard32f36bc2003-03-30 21:29:48 +00004923 }
bellardc596ed12003-07-13 17:32:31 +00004924 if (!is_error(ret))
4925 ret = host_to_target_clock_t(ret);
bellard32f36bc2003-03-30 21:29:48 +00004926 }
4927 break;
bellardebc05482003-09-30 21:08:41 +00004928#ifdef TARGET_NR_prof
bellard31e31b82003-02-18 22:55:36 +00004929 case TARGET_NR_prof:
4930 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004931#endif
thse5febef2007-04-01 18:31:35 +00004932#ifdef TARGET_NR_signal
bellard31e31b82003-02-18 22:55:36 +00004933 case TARGET_NR_signal:
4934 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00004935#endif
bellard31e31b82003-02-18 22:55:36 +00004936 case TARGET_NR_acct:
aurel3238d840e2009-01-30 19:48:17 +00004937 if (arg1 == 0) {
4938 ret = get_errno(acct(NULL));
4939 } else {
4940 if (!(p = lock_user_string(arg1)))
4941 goto efault;
4942 ret = get_errno(acct(path(p)));
4943 unlock_user(p, arg1, 0);
4944 }
pbrook24836682006-04-16 14:14:53 +00004945 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004946#ifdef TARGET_NR_umount2 /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00004947 case TARGET_NR_umount2:
bellard579a97f2007-11-11 14:26:47 +00004948 if (!(p = lock_user_string(arg1)))
4949 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004950 ret = get_errno(umount2(p, arg2));
4951 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004952 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004953#endif
bellardebc05482003-09-30 21:08:41 +00004954#ifdef TARGET_NR_lock
bellard31e31b82003-02-18 22:55:36 +00004955 case TARGET_NR_lock:
4956 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004957#endif
bellard31e31b82003-02-18 22:55:36 +00004958 case TARGET_NR_ioctl:
4959 ret = do_ioctl(arg1, arg2, arg3);
4960 break;
4961 case TARGET_NR_fcntl:
bellard9ee1fa22007-11-11 15:11:19 +00004962 ret = do_fcntl(arg1, arg2, arg3);
bellard31e31b82003-02-18 22:55:36 +00004963 break;
bellardebc05482003-09-30 21:08:41 +00004964#ifdef TARGET_NR_mpx
bellard31e31b82003-02-18 22:55:36 +00004965 case TARGET_NR_mpx:
4966 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004967#endif
bellard31e31b82003-02-18 22:55:36 +00004968 case TARGET_NR_setpgid:
4969 ret = get_errno(setpgid(arg1, arg2));
4970 break;
bellardebc05482003-09-30 21:08:41 +00004971#ifdef TARGET_NR_ulimit
bellard31e31b82003-02-18 22:55:36 +00004972 case TARGET_NR_ulimit:
4973 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004974#endif
4975#ifdef TARGET_NR_oldolduname
bellard31e31b82003-02-18 22:55:36 +00004976 case TARGET_NR_oldolduname:
4977 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004978#endif
bellard31e31b82003-02-18 22:55:36 +00004979 case TARGET_NR_umask:
4980 ret = get_errno(umask(arg1));
4981 break;
4982 case TARGET_NR_chroot:
bellard579a97f2007-11-11 14:26:47 +00004983 if (!(p = lock_user_string(arg1)))
4984 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004985 ret = get_errno(chroot(p));
4986 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004987 break;
4988 case TARGET_NR_ustat:
4989 goto unimplemented;
4990 case TARGET_NR_dup2:
4991 ret = get_errno(dup2(arg1, arg2));
4992 break;
Ulrich Hechtd0927932009-09-17 20:22:14 +03004993#if defined(CONFIG_DUP3) && defined(TARGET_NR_dup3)
4994 case TARGET_NR_dup3:
4995 ret = get_errno(dup3(arg1, arg2, arg3));
4996 break;
4997#endif
j_mayer7a3148a2007-04-05 07:13:51 +00004998#ifdef TARGET_NR_getppid /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00004999 case TARGET_NR_getppid:
5000 ret = get_errno(getppid());
5001 break;
j_mayer7a3148a2007-04-05 07:13:51 +00005002#endif
bellard31e31b82003-02-18 22:55:36 +00005003 case TARGET_NR_getpgrp:
5004 ret = get_errno(getpgrp());
5005 break;
5006 case TARGET_NR_setsid:
5007 ret = get_errno(setsid());
5008 break;
thse5febef2007-04-01 18:31:35 +00005009#ifdef TARGET_NR_sigaction
bellard31e31b82003-02-18 22:55:36 +00005010 case TARGET_NR_sigaction:
bellard31e31b82003-02-18 22:55:36 +00005011 {
Richard Henderson6049f4f2009-12-27 18:30:03 -08005012#if defined(TARGET_ALPHA)
5013 struct target_sigaction act, oact, *pact = 0;
pbrook53a59602006-03-25 19:31:22 +00005014 struct target_old_sigaction *old_act;
pbrook53a59602006-03-25 19:31:22 +00005015 if (arg2) {
bellard579a97f2007-11-11 14:26:47 +00005016 if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1))
5017 goto efault;
bellard66fb9762003-03-23 01:06:05 +00005018 act._sa_handler = old_act->_sa_handler;
5019 target_siginitset(&act.sa_mask, old_act->sa_mask);
5020 act.sa_flags = old_act->sa_flags;
Richard Henderson6049f4f2009-12-27 18:30:03 -08005021 act.sa_restorer = 0;
pbrook53a59602006-03-25 19:31:22 +00005022 unlock_user_struct(old_act, arg2, 0);
bellard66fb9762003-03-23 01:06:05 +00005023 pact = &act;
bellard66fb9762003-03-23 01:06:05 +00005024 }
5025 ret = get_errno(do_sigaction(arg1, pact, &oact));
pbrook53a59602006-03-25 19:31:22 +00005026 if (!is_error(ret) && arg3) {
bellard579a97f2007-11-11 14:26:47 +00005027 if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0))
5028 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005029 old_act->_sa_handler = oact._sa_handler;
5030 old_act->sa_mask = oact.sa_mask.sig[0];
5031 old_act->sa_flags = oact.sa_flags;
pbrook53a59602006-03-25 19:31:22 +00005032 unlock_user_struct(old_act, arg3, 1);
bellard66fb9762003-03-23 01:06:05 +00005033 }
Richard Henderson6049f4f2009-12-27 18:30:03 -08005034#elif defined(TARGET_MIPS)
bellard106ec872006-06-27 21:08:10 +00005035 struct target_sigaction act, oact, *pact, *old_act;
5036
5037 if (arg2) {
bellard579a97f2007-11-11 14:26:47 +00005038 if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1))
5039 goto efault;
bellard106ec872006-06-27 21:08:10 +00005040 act._sa_handler = old_act->_sa_handler;
5041 target_siginitset(&act.sa_mask, old_act->sa_mask.sig[0]);
5042 act.sa_flags = old_act->sa_flags;
5043 unlock_user_struct(old_act, arg2, 0);
5044 pact = &act;
5045 } else {
5046 pact = NULL;
5047 }
5048
5049 ret = get_errno(do_sigaction(arg1, pact, &oact));
5050
5051 if (!is_error(ret) && arg3) {
bellard579a97f2007-11-11 14:26:47 +00005052 if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0))
5053 goto efault;
bellard106ec872006-06-27 21:08:10 +00005054 old_act->_sa_handler = oact._sa_handler;
5055 old_act->sa_flags = oact.sa_flags;
5056 old_act->sa_mask.sig[0] = oact.sa_mask.sig[0];
5057 old_act->sa_mask.sig[1] = 0;
5058 old_act->sa_mask.sig[2] = 0;
5059 old_act->sa_mask.sig[3] = 0;
5060 unlock_user_struct(old_act, arg3, 1);
5061 }
Richard Henderson6049f4f2009-12-27 18:30:03 -08005062#else
5063 struct target_old_sigaction *old_act;
5064 struct target_sigaction act, oact, *pact;
5065 if (arg2) {
5066 if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1))
5067 goto efault;
5068 act._sa_handler = old_act->_sa_handler;
5069 target_siginitset(&act.sa_mask, old_act->sa_mask);
5070 act.sa_flags = old_act->sa_flags;
5071 act.sa_restorer = old_act->sa_restorer;
5072 unlock_user_struct(old_act, arg2, 0);
5073 pact = &act;
5074 } else {
5075 pact = NULL;
5076 }
5077 ret = get_errno(do_sigaction(arg1, pact, &oact));
5078 if (!is_error(ret) && arg3) {
5079 if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0))
5080 goto efault;
5081 old_act->_sa_handler = oact._sa_handler;
5082 old_act->sa_mask = oact.sa_mask.sig[0];
5083 old_act->sa_flags = oact.sa_flags;
5084 old_act->sa_restorer = oact.sa_restorer;
5085 unlock_user_struct(old_act, arg3, 1);
5086 }
ths388bb212007-05-13 13:58:00 +00005087#endif
bellard31e31b82003-02-18 22:55:36 +00005088 }
5089 break;
thse5febef2007-04-01 18:31:35 +00005090#endif
bellard66fb9762003-03-23 01:06:05 +00005091 case TARGET_NR_rt_sigaction:
pbrook53a59602006-03-25 19:31:22 +00005092 {
Richard Henderson6049f4f2009-12-27 18:30:03 -08005093#if defined(TARGET_ALPHA)
5094 struct target_sigaction act, oact, *pact = 0;
5095 struct target_rt_sigaction *rt_act;
5096 /* ??? arg4 == sizeof(sigset_t). */
5097 if (arg2) {
5098 if (!lock_user_struct(VERIFY_READ, rt_act, arg2, 1))
5099 goto efault;
5100 act._sa_handler = rt_act->_sa_handler;
5101 act.sa_mask = rt_act->sa_mask;
5102 act.sa_flags = rt_act->sa_flags;
5103 act.sa_restorer = arg5;
5104 unlock_user_struct(rt_act, arg2, 0);
5105 pact = &act;
5106 }
5107 ret = get_errno(do_sigaction(arg1, pact, &oact));
5108 if (!is_error(ret) && arg3) {
5109 if (!lock_user_struct(VERIFY_WRITE, rt_act, arg3, 0))
5110 goto efault;
5111 rt_act->_sa_handler = oact._sa_handler;
5112 rt_act->sa_mask = oact.sa_mask;
5113 rt_act->sa_flags = oact.sa_flags;
5114 unlock_user_struct(rt_act, arg3, 1);
5115 }
5116#else
pbrook53a59602006-03-25 19:31:22 +00005117 struct target_sigaction *act;
5118 struct target_sigaction *oact;
5119
bellard579a97f2007-11-11 14:26:47 +00005120 if (arg2) {
5121 if (!lock_user_struct(VERIFY_READ, act, arg2, 1))
5122 goto efault;
5123 } else
pbrook53a59602006-03-25 19:31:22 +00005124 act = NULL;
bellard579a97f2007-11-11 14:26:47 +00005125 if (arg3) {
5126 if (!lock_user_struct(VERIFY_WRITE, oact, arg3, 0)) {
5127 ret = -TARGET_EFAULT;
5128 goto rt_sigaction_fail;
5129 }
5130 } else
pbrook53a59602006-03-25 19:31:22 +00005131 oact = NULL;
5132 ret = get_errno(do_sigaction(arg1, act, oact));
bellard579a97f2007-11-11 14:26:47 +00005133 rt_sigaction_fail:
5134 if (act)
pbrook53a59602006-03-25 19:31:22 +00005135 unlock_user_struct(act, arg2, 0);
bellard579a97f2007-11-11 14:26:47 +00005136 if (oact)
pbrook53a59602006-03-25 19:31:22 +00005137 unlock_user_struct(oact, arg3, 1);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005138#endif
pbrook53a59602006-03-25 19:31:22 +00005139 }
bellard66fb9762003-03-23 01:06:05 +00005140 break;
j_mayer7a3148a2007-04-05 07:13:51 +00005141#ifdef TARGET_NR_sgetmask /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00005142 case TARGET_NR_sgetmask:
bellard66fb9762003-03-23 01:06:05 +00005143 {
5144 sigset_t cur_set;
blueswir1992f48a2007-10-14 16:27:31 +00005145 abi_ulong target_set;
bellard66fb9762003-03-23 01:06:05 +00005146 sigprocmask(0, NULL, &cur_set);
5147 host_to_target_old_sigset(&target_set, &cur_set);
5148 ret = target_set;
5149 }
5150 break;
j_mayer7a3148a2007-04-05 07:13:51 +00005151#endif
5152#ifdef TARGET_NR_ssetmask /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00005153 case TARGET_NR_ssetmask:
bellard66fb9762003-03-23 01:06:05 +00005154 {
5155 sigset_t set, oset, cur_set;
blueswir1992f48a2007-10-14 16:27:31 +00005156 abi_ulong target_set = arg1;
bellard66fb9762003-03-23 01:06:05 +00005157 sigprocmask(0, NULL, &cur_set);
5158 target_to_host_old_sigset(&set, &target_set);
5159 sigorset(&set, &set, &cur_set);
5160 sigprocmask(SIG_SETMASK, &set, &oset);
5161 host_to_target_old_sigset(&target_set, &oset);
5162 ret = target_set;
5163 }
5164 break;
j_mayer7a3148a2007-04-05 07:13:51 +00005165#endif
thse5febef2007-04-01 18:31:35 +00005166#ifdef TARGET_NR_sigprocmask
bellard66fb9762003-03-23 01:06:05 +00005167 case TARGET_NR_sigprocmask:
5168 {
Richard Hendersona5b3b132010-05-03 10:07:55 -07005169#if defined(TARGET_ALPHA)
5170 sigset_t set, oldset;
5171 abi_ulong mask;
5172 int how;
5173
5174 switch (arg1) {
5175 case TARGET_SIG_BLOCK:
5176 how = SIG_BLOCK;
5177 break;
5178 case TARGET_SIG_UNBLOCK:
5179 how = SIG_UNBLOCK;
5180 break;
5181 case TARGET_SIG_SETMASK:
5182 how = SIG_SETMASK;
5183 break;
5184 default:
5185 ret = -TARGET_EINVAL;
5186 goto fail;
5187 }
5188 mask = arg2;
5189 target_to_host_old_sigset(&set, &mask);
5190
5191 ret = get_errno(sigprocmask(how, &set, &oldset));
5192
5193 if (!is_error(ret)) {
5194 host_to_target_old_sigset(&mask, &oldset);
5195 ret = mask;
5196 ((CPUAlphaState *)cpu_env)->[IR_V0] = 0; /* force no error */
5197 }
5198#else
bellard66fb9762003-03-23 01:06:05 +00005199 sigset_t set, oldset, *set_ptr;
Richard Hendersona5b3b132010-05-03 10:07:55 -07005200 int how;
ths3b46e622007-09-17 08:09:54 +00005201
pbrook53a59602006-03-25 19:31:22 +00005202 if (arg2) {
Richard Hendersona5b3b132010-05-03 10:07:55 -07005203 switch (arg1) {
bellard66fb9762003-03-23 01:06:05 +00005204 case TARGET_SIG_BLOCK:
5205 how = SIG_BLOCK;
5206 break;
5207 case TARGET_SIG_UNBLOCK:
5208 how = SIG_UNBLOCK;
5209 break;
5210 case TARGET_SIG_SETMASK:
5211 how = SIG_SETMASK;
5212 break;
5213 default:
ths0da46a62007-10-20 20:23:07 +00005214 ret = -TARGET_EINVAL;
bellard66fb9762003-03-23 01:06:05 +00005215 goto fail;
5216 }
Anthony Liguoric227f092009-10-01 16:12:16 -05005217 if (!(p = lock_user(VERIFY_READ, arg2, sizeof(target_sigset_t), 1)))
bellard579a97f2007-11-11 14:26:47 +00005218 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005219 target_to_host_old_sigset(&set, p);
5220 unlock_user(p, arg2, 0);
bellard66fb9762003-03-23 01:06:05 +00005221 set_ptr = &set;
5222 } else {
5223 how = 0;
5224 set_ptr = NULL;
5225 }
Richard Hendersona5b3b132010-05-03 10:07:55 -07005226 ret = get_errno(sigprocmask(how, set_ptr, &oldset));
pbrook53a59602006-03-25 19:31:22 +00005227 if (!is_error(ret) && arg3) {
Anthony Liguoric227f092009-10-01 16:12:16 -05005228 if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0)))
bellard579a97f2007-11-11 14:26:47 +00005229 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005230 host_to_target_old_sigset(p, &oldset);
Anthony Liguoric227f092009-10-01 16:12:16 -05005231 unlock_user(p, arg3, sizeof(target_sigset_t));
bellard66fb9762003-03-23 01:06:05 +00005232 }
Richard Hendersona5b3b132010-05-03 10:07:55 -07005233#endif
bellard66fb9762003-03-23 01:06:05 +00005234 }
5235 break;
thse5febef2007-04-01 18:31:35 +00005236#endif
bellard66fb9762003-03-23 01:06:05 +00005237 case TARGET_NR_rt_sigprocmask:
5238 {
5239 int how = arg1;
5240 sigset_t set, oldset, *set_ptr;
ths3b46e622007-09-17 08:09:54 +00005241
pbrook53a59602006-03-25 19:31:22 +00005242 if (arg2) {
bellard66fb9762003-03-23 01:06:05 +00005243 switch(how) {
5244 case TARGET_SIG_BLOCK:
5245 how = SIG_BLOCK;
5246 break;
5247 case TARGET_SIG_UNBLOCK:
5248 how = SIG_UNBLOCK;
5249 break;
5250 case TARGET_SIG_SETMASK:
5251 how = SIG_SETMASK;
5252 break;
5253 default:
ths0da46a62007-10-20 20:23:07 +00005254 ret = -TARGET_EINVAL;
bellard66fb9762003-03-23 01:06:05 +00005255 goto fail;
5256 }
Anthony Liguoric227f092009-10-01 16:12:16 -05005257 if (!(p = lock_user(VERIFY_READ, arg2, sizeof(target_sigset_t), 1)))
bellard579a97f2007-11-11 14:26:47 +00005258 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005259 target_to_host_sigset(&set, p);
5260 unlock_user(p, arg2, 0);
bellard66fb9762003-03-23 01:06:05 +00005261 set_ptr = &set;
5262 } else {
5263 how = 0;
5264 set_ptr = NULL;
5265 }
5266 ret = get_errno(sigprocmask(how, set_ptr, &oldset));
pbrook53a59602006-03-25 19:31:22 +00005267 if (!is_error(ret) && arg3) {
Anthony Liguoric227f092009-10-01 16:12:16 -05005268 if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0)))
bellard579a97f2007-11-11 14:26:47 +00005269 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005270 host_to_target_sigset(p, &oldset);
Anthony Liguoric227f092009-10-01 16:12:16 -05005271 unlock_user(p, arg3, sizeof(target_sigset_t));
bellard66fb9762003-03-23 01:06:05 +00005272 }
5273 }
5274 break;
thse5febef2007-04-01 18:31:35 +00005275#ifdef TARGET_NR_sigpending
bellard66fb9762003-03-23 01:06:05 +00005276 case TARGET_NR_sigpending:
5277 {
5278 sigset_t set;
5279 ret = get_errno(sigpending(&set));
5280 if (!is_error(ret)) {
Anthony Liguoric227f092009-10-01 16:12:16 -05005281 if (!(p = lock_user(VERIFY_WRITE, arg1, sizeof(target_sigset_t), 0)))
bellard579a97f2007-11-11 14:26:47 +00005282 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005283 host_to_target_old_sigset(p, &set);
Anthony Liguoric227f092009-10-01 16:12:16 -05005284 unlock_user(p, arg1, sizeof(target_sigset_t));
bellard66fb9762003-03-23 01:06:05 +00005285 }
5286 }
5287 break;
thse5febef2007-04-01 18:31:35 +00005288#endif
bellard66fb9762003-03-23 01:06:05 +00005289 case TARGET_NR_rt_sigpending:
5290 {
5291 sigset_t set;
5292 ret = get_errno(sigpending(&set));
5293 if (!is_error(ret)) {
Anthony Liguoric227f092009-10-01 16:12:16 -05005294 if (!(p = lock_user(VERIFY_WRITE, arg1, sizeof(target_sigset_t), 0)))
bellard579a97f2007-11-11 14:26:47 +00005295 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005296 host_to_target_sigset(p, &set);
Anthony Liguoric227f092009-10-01 16:12:16 -05005297 unlock_user(p, arg1, sizeof(target_sigset_t));
bellard66fb9762003-03-23 01:06:05 +00005298 }
5299 }
5300 break;
thse5febef2007-04-01 18:31:35 +00005301#ifdef TARGET_NR_sigsuspend
bellard66fb9762003-03-23 01:06:05 +00005302 case TARGET_NR_sigsuspend:
5303 {
5304 sigset_t set;
Richard Hendersonf43ce122010-05-03 10:07:54 -07005305#if defined(TARGET_ALPHA)
5306 abi_ulong mask = arg1;
5307 target_to_host_old_sigset(&set, &mask);
5308#else
Anthony Liguoric227f092009-10-01 16:12:16 -05005309 if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
bellard579a97f2007-11-11 14:26:47 +00005310 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005311 target_to_host_old_sigset(&set, p);
5312 unlock_user(p, arg1, 0);
Richard Hendersonf43ce122010-05-03 10:07:54 -07005313#endif
bellard66fb9762003-03-23 01:06:05 +00005314 ret = get_errno(sigsuspend(&set));
5315 }
5316 break;
thse5febef2007-04-01 18:31:35 +00005317#endif
bellard66fb9762003-03-23 01:06:05 +00005318 case TARGET_NR_rt_sigsuspend:
5319 {
5320 sigset_t set;
Anthony Liguoric227f092009-10-01 16:12:16 -05005321 if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
bellard579a97f2007-11-11 14:26:47 +00005322 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005323 target_to_host_sigset(&set, p);
5324 unlock_user(p, arg1, 0);
bellard66fb9762003-03-23 01:06:05 +00005325 ret = get_errno(sigsuspend(&set));
5326 }
5327 break;
5328 case TARGET_NR_rt_sigtimedwait:
5329 {
bellard66fb9762003-03-23 01:06:05 +00005330 sigset_t set;
5331 struct timespec uts, *puts;
5332 siginfo_t uinfo;
ths3b46e622007-09-17 08:09:54 +00005333
Anthony Liguoric227f092009-10-01 16:12:16 -05005334 if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
bellard579a97f2007-11-11 14:26:47 +00005335 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005336 target_to_host_sigset(&set, p);
5337 unlock_user(p, arg1, 0);
5338 if (arg3) {
bellard66fb9762003-03-23 01:06:05 +00005339 puts = &uts;
pbrook53a59602006-03-25 19:31:22 +00005340 target_to_host_timespec(puts, arg3);
bellard66fb9762003-03-23 01:06:05 +00005341 } else {
5342 puts = NULL;
5343 }
5344 ret = get_errno(sigtimedwait(&set, &uinfo, puts));
pbrook53a59602006-03-25 19:31:22 +00005345 if (!is_error(ret) && arg2) {
Anthony Liguoric227f092009-10-01 16:12:16 -05005346 if (!(p = lock_user(VERIFY_WRITE, arg2, sizeof(target_siginfo_t), 0)))
bellard579a97f2007-11-11 14:26:47 +00005347 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005348 host_to_target_siginfo(p, &uinfo);
Anthony Liguoric227f092009-10-01 16:12:16 -05005349 unlock_user(p, arg2, sizeof(target_siginfo_t));
bellard66fb9762003-03-23 01:06:05 +00005350 }
5351 }
5352 break;
5353 case TARGET_NR_rt_sigqueueinfo:
5354 {
5355 siginfo_t uinfo;
Anthony Liguoric227f092009-10-01 16:12:16 -05005356 if (!(p = lock_user(VERIFY_READ, arg3, sizeof(target_sigset_t), 1)))
bellard579a97f2007-11-11 14:26:47 +00005357 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005358 target_to_host_siginfo(&uinfo, p);
5359 unlock_user(p, arg1, 0);
bellard66fb9762003-03-23 01:06:05 +00005360 ret = get_errno(sys_rt_sigqueueinfo(arg1, arg2, &uinfo));
5361 }
5362 break;
thse5febef2007-04-01 18:31:35 +00005363#ifdef TARGET_NR_sigreturn
bellard66fb9762003-03-23 01:06:05 +00005364 case TARGET_NR_sigreturn:
5365 /* NOTE: ret is eax, so not transcoding must be done */
5366 ret = do_sigreturn(cpu_env);
5367 break;
thse5febef2007-04-01 18:31:35 +00005368#endif
bellard66fb9762003-03-23 01:06:05 +00005369 case TARGET_NR_rt_sigreturn:
5370 /* NOTE: ret is eax, so not transcoding must be done */
5371 ret = do_rt_sigreturn(cpu_env);
5372 break;
bellard31e31b82003-02-18 22:55:36 +00005373 case TARGET_NR_sethostname:
bellard579a97f2007-11-11 14:26:47 +00005374 if (!(p = lock_user_string(arg1)))
5375 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005376 ret = get_errno(sethostname(p, arg2));
5377 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00005378 break;
5379 case TARGET_NR_setrlimit:
bellard9de5e442003-03-23 16:49:39 +00005380 {
bellard9de5e442003-03-23 16:49:39 +00005381 int resource = arg1;
pbrook53a59602006-03-25 19:31:22 +00005382 struct target_rlimit *target_rlim;
bellard9de5e442003-03-23 16:49:39 +00005383 struct rlimit rlim;
bellard579a97f2007-11-11 14:26:47 +00005384 if (!lock_user_struct(VERIFY_READ, target_rlim, arg2, 1))
5385 goto efault;
takasi-y@ops.dti.ne.jp81bbe902010-04-12 04:07:35 +09005386 rlim.rlim_cur = target_to_host_rlim(target_rlim->rlim_cur);
5387 rlim.rlim_max = target_to_host_rlim(target_rlim->rlim_max);
pbrook53a59602006-03-25 19:31:22 +00005388 unlock_user_struct(target_rlim, arg2, 0);
bellard9de5e442003-03-23 16:49:39 +00005389 ret = get_errno(setrlimit(resource, &rlim));
5390 }
5391 break;
bellard31e31b82003-02-18 22:55:36 +00005392 case TARGET_NR_getrlimit:
bellard9de5e442003-03-23 16:49:39 +00005393 {
bellard9de5e442003-03-23 16:49:39 +00005394 int resource = arg1;
pbrook53a59602006-03-25 19:31:22 +00005395 struct target_rlimit *target_rlim;
bellard9de5e442003-03-23 16:49:39 +00005396 struct rlimit rlim;
ths3b46e622007-09-17 08:09:54 +00005397
bellard9de5e442003-03-23 16:49:39 +00005398 ret = get_errno(getrlimit(resource, &rlim));
5399 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00005400 if (!lock_user_struct(VERIFY_WRITE, target_rlim, arg2, 0))
5401 goto efault;
takasi-y@ops.dti.ne.jp81bbe902010-04-12 04:07:35 +09005402 target_rlim->rlim_cur = host_to_target_rlim(rlim.rlim_cur);
5403 target_rlim->rlim_max = host_to_target_rlim(rlim.rlim_max);
pbrook53a59602006-03-25 19:31:22 +00005404 unlock_user_struct(target_rlim, arg2, 1);
bellard9de5e442003-03-23 16:49:39 +00005405 }
5406 }
5407 break;
bellard31e31b82003-02-18 22:55:36 +00005408 case TARGET_NR_getrusage:
bellardb4091862003-05-16 15:39:34 +00005409 {
5410 struct rusage rusage;
bellardb4091862003-05-16 15:39:34 +00005411 ret = get_errno(getrusage(arg1, &rusage));
5412 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00005413 host_to_target_rusage(arg2, &rusage);
bellardb4091862003-05-16 15:39:34 +00005414 }
5415 }
5416 break;
bellard31e31b82003-02-18 22:55:36 +00005417 case TARGET_NR_gettimeofday:
5418 {
bellard31e31b82003-02-18 22:55:36 +00005419 struct timeval tv;
5420 ret = get_errno(gettimeofday(&tv, NULL));
5421 if (!is_error(ret)) {
ths788f5ec2007-12-09 02:37:05 +00005422 if (copy_to_user_timeval(arg1, &tv))
5423 goto efault;
bellard31e31b82003-02-18 22:55:36 +00005424 }
5425 }
5426 break;
5427 case TARGET_NR_settimeofday:
5428 {
bellard31e31b82003-02-18 22:55:36 +00005429 struct timeval tv;
ths788f5ec2007-12-09 02:37:05 +00005430 if (copy_from_user_timeval(&tv, arg1))
5431 goto efault;
bellard31e31b82003-02-18 22:55:36 +00005432 ret = get_errno(settimeofday(&tv, NULL));
5433 }
5434 break;
bellard048f6b42005-11-26 18:47:20 +00005435#ifdef TARGET_NR_select
bellard31e31b82003-02-18 22:55:36 +00005436 case TARGET_NR_select:
bellardf2674e32003-07-09 12:26:09 +00005437 {
pbrook53a59602006-03-25 19:31:22 +00005438 struct target_sel_arg_struct *sel;
blueswir1992f48a2007-10-14 16:27:31 +00005439 abi_ulong inp, outp, exp, tvp;
pbrook53a59602006-03-25 19:31:22 +00005440 long nsel;
5441
bellard579a97f2007-11-11 14:26:47 +00005442 if (!lock_user_struct(VERIFY_READ, sel, arg1, 1))
5443 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005444 nsel = tswapl(sel->n);
5445 inp = tswapl(sel->inp);
5446 outp = tswapl(sel->outp);
5447 exp = tswapl(sel->exp);
5448 tvp = tswapl(sel->tvp);
5449 unlock_user_struct(sel, arg1, 0);
5450 ret = do_select(nsel, inp, outp, exp, tvp);
bellardf2674e32003-07-09 12:26:09 +00005451 }
5452 break;
bellard048f6b42005-11-26 18:47:20 +00005453#endif
Riku Voipio9e423822010-05-07 12:28:05 +00005454#ifdef TARGET_NR_pselect6
5455 case TARGET_NR_pselect6:
5456 goto unimplemented_nowarn;
5457#endif
bellard31e31b82003-02-18 22:55:36 +00005458 case TARGET_NR_symlink:
pbrook53a59602006-03-25 19:31:22 +00005459 {
5460 void *p2;
5461 p = lock_user_string(arg1);
5462 p2 = lock_user_string(arg2);
bellard579a97f2007-11-11 14:26:47 +00005463 if (!p || !p2)
5464 ret = -TARGET_EFAULT;
5465 else
5466 ret = get_errno(symlink(p, p2));
pbrook53a59602006-03-25 19:31:22 +00005467 unlock_user(p2, arg2, 0);
5468 unlock_user(p, arg1, 0);
5469 }
bellard31e31b82003-02-18 22:55:36 +00005470 break;
thsf0b62432007-09-24 09:25:40 +00005471#if defined(TARGET_NR_symlinkat) && defined(__NR_symlinkat)
5472 case TARGET_NR_symlinkat:
thsf0b62432007-09-24 09:25:40 +00005473 {
bellard579a97f2007-11-11 14:26:47 +00005474 void *p2;
thsf0b62432007-09-24 09:25:40 +00005475 p = lock_user_string(arg1);
5476 p2 = lock_user_string(arg3);
bellard579a97f2007-11-11 14:26:47 +00005477 if (!p || !p2)
ths0da46a62007-10-20 20:23:07 +00005478 ret = -TARGET_EFAULT;
thsf0b62432007-09-24 09:25:40 +00005479 else
5480 ret = get_errno(sys_symlinkat(p, arg2, p2));
bellard579a97f2007-11-11 14:26:47 +00005481 unlock_user(p2, arg3, 0);
5482 unlock_user(p, arg1, 0);
thsf0b62432007-09-24 09:25:40 +00005483 }
5484 break;
5485#endif
bellardebc05482003-09-30 21:08:41 +00005486#ifdef TARGET_NR_oldlstat
bellard31e31b82003-02-18 22:55:36 +00005487 case TARGET_NR_oldlstat:
5488 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00005489#endif
bellard31e31b82003-02-18 22:55:36 +00005490 case TARGET_NR_readlink:
pbrook53a59602006-03-25 19:31:22 +00005491 {
aurel32d088d662009-01-30 20:09:01 +00005492 void *p2, *temp;
pbrook53a59602006-03-25 19:31:22 +00005493 p = lock_user_string(arg1);
bellard579a97f2007-11-11 14:26:47 +00005494 p2 = lock_user(VERIFY_WRITE, arg2, arg3, 0);
5495 if (!p || !p2)
5496 ret = -TARGET_EFAULT;
aurel32d088d662009-01-30 20:09:01 +00005497 else {
5498 if (strncmp((const char *)p, "/proc/self/exe", 14) == 0) {
5499 char real[PATH_MAX];
5500 temp = realpath(exec_path,real);
5501 ret = (temp==NULL) ? get_errno(-1) : strlen(real) ;
5502 snprintf((char *)p2, arg3, "%s", real);
5503 }
5504 else
5505 ret = get_errno(readlink(path(p), p2, arg3));
aurel32d088d662009-01-30 20:09:01 +00005506 }
pbrook53a59602006-03-25 19:31:22 +00005507 unlock_user(p2, arg2, ret);
5508 unlock_user(p, arg1, 0);
5509 }
bellard31e31b82003-02-18 22:55:36 +00005510 break;
ths5e0ccb12007-09-24 09:26:10 +00005511#if defined(TARGET_NR_readlinkat) && defined(__NR_readlinkat)
5512 case TARGET_NR_readlinkat:
ths5e0ccb12007-09-24 09:26:10 +00005513 {
bellard579a97f2007-11-11 14:26:47 +00005514 void *p2;
ths5e0ccb12007-09-24 09:26:10 +00005515 p = lock_user_string(arg2);
bellard579a97f2007-11-11 14:26:47 +00005516 p2 = lock_user(VERIFY_WRITE, arg3, arg4, 0);
5517 if (!p || !p2)
ths0da46a62007-10-20 20:23:07 +00005518 ret = -TARGET_EFAULT;
ths5e0ccb12007-09-24 09:26:10 +00005519 else
5520 ret = get_errno(sys_readlinkat(arg1, path(p), p2, arg4));
bellard579a97f2007-11-11 14:26:47 +00005521 unlock_user(p2, arg3, ret);
5522 unlock_user(p, arg2, 0);
ths5e0ccb12007-09-24 09:26:10 +00005523 }
5524 break;
5525#endif
thse5febef2007-04-01 18:31:35 +00005526#ifdef TARGET_NR_uselib
bellard31e31b82003-02-18 22:55:36 +00005527 case TARGET_NR_uselib:
5528 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00005529#endif
5530#ifdef TARGET_NR_swapon
bellard31e31b82003-02-18 22:55:36 +00005531 case TARGET_NR_swapon:
bellard579a97f2007-11-11 14:26:47 +00005532 if (!(p = lock_user_string(arg1)))
5533 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005534 ret = get_errno(swapon(p, arg2));
5535 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00005536 break;
thse5febef2007-04-01 18:31:35 +00005537#endif
bellard31e31b82003-02-18 22:55:36 +00005538 case TARGET_NR_reboot:
5539 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00005540#ifdef TARGET_NR_readdir
bellard31e31b82003-02-18 22:55:36 +00005541 case TARGET_NR_readdir:
5542 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00005543#endif
5544#ifdef TARGET_NR_mmap
bellard31e31b82003-02-18 22:55:36 +00005545 case TARGET_NR_mmap:
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02005546#if (defined(TARGET_I386) && defined(TARGET_ABI32)) || defined(TARGET_ARM) || defined(TARGET_M68K) || defined(TARGET_CRIS) || defined(TARGET_MICROBLAZE)
bellard31e31b82003-02-18 22:55:36 +00005547 {
blueswir1992f48a2007-10-14 16:27:31 +00005548 abi_ulong *v;
5549 abi_ulong v1, v2, v3, v4, v5, v6;
bellard579a97f2007-11-11 14:26:47 +00005550 if (!(v = lock_user(VERIFY_READ, arg1, 6 * sizeof(abi_ulong), 1)))
5551 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005552 v1 = tswapl(v[0]);
5553 v2 = tswapl(v[1]);
5554 v3 = tswapl(v[2]);
5555 v4 = tswapl(v[3]);
5556 v5 = tswapl(v[4]);
5557 v6 = tswapl(v[5]);
5558 unlock_user(v, arg1, 0);
ths5fafdf22007-09-16 21:08:06 +00005559 ret = get_errno(target_mmap(v1, v2, v3,
bellard5286db72003-06-05 00:57:30 +00005560 target_to_host_bitmask(v4, mmap_flags_tbl),
5561 v5, v6));
bellard31e31b82003-02-18 22:55:36 +00005562 }
bellard31e31b82003-02-18 22:55:36 +00005563#else
ths5fafdf22007-09-16 21:08:06 +00005564 ret = get_errno(target_mmap(arg1, arg2, arg3,
5565 target_to_host_bitmask(arg4, mmap_flags_tbl),
bellard6fb883e2003-07-09 17:12:39 +00005566 arg5,
5567 arg6));
bellard31e31b82003-02-18 22:55:36 +00005568#endif
bellard6fb883e2003-07-09 17:12:39 +00005569 break;
thse5febef2007-04-01 18:31:35 +00005570#endif
bellarda315a142005-01-30 22:59:18 +00005571#ifdef TARGET_NR_mmap2
bellard6fb883e2003-07-09 17:12:39 +00005572 case TARGET_NR_mmap2:
pbrookbb7ec042008-03-25 22:28:25 +00005573#ifndef MMAP_SHIFT
bellardc573ff62004-01-04 15:51:36 +00005574#define MMAP_SHIFT 12
bellardc573ff62004-01-04 15:51:36 +00005575#endif
ths5fafdf22007-09-16 21:08:06 +00005576 ret = get_errno(target_mmap(arg1, arg2, arg3,
5577 target_to_host_bitmask(arg4, mmap_flags_tbl),
bellard5286db72003-06-05 00:57:30 +00005578 arg5,
bellardc573ff62004-01-04 15:51:36 +00005579 arg6 << MMAP_SHIFT));
bellard31e31b82003-02-18 22:55:36 +00005580 break;
bellarda315a142005-01-30 22:59:18 +00005581#endif
bellard31e31b82003-02-18 22:55:36 +00005582 case TARGET_NR_munmap:
bellard54936002003-05-13 00:25:15 +00005583 ret = get_errno(target_munmap(arg1, arg2));
bellard31e31b82003-02-18 22:55:36 +00005584 break;
bellard9de5e442003-03-23 16:49:39 +00005585 case TARGET_NR_mprotect:
Paul Brook97374d32010-06-16 13:03:51 +01005586 {
5587 TaskState *ts = ((CPUState *)cpu_env)->opaque;
5588 /* Special hack to detect libc making the stack executable. */
5589 if ((arg3 & PROT_GROWSDOWN)
5590 && arg1 >= ts->info->stack_limit
5591 && arg1 <= ts->info->start_stack) {
5592 arg3 &= ~PROT_GROWSDOWN;
5593 arg2 = arg2 + arg1 - ts->info->stack_limit;
5594 arg1 = ts->info->stack_limit;
5595 }
5596 }
bellard54936002003-05-13 00:25:15 +00005597 ret = get_errno(target_mprotect(arg1, arg2, arg3));
bellard9de5e442003-03-23 16:49:39 +00005598 break;
thse5febef2007-04-01 18:31:35 +00005599#ifdef TARGET_NR_mremap
bellard9de5e442003-03-23 16:49:39 +00005600 case TARGET_NR_mremap:
bellard54936002003-05-13 00:25:15 +00005601 ret = get_errno(target_mremap(arg1, arg2, arg3, arg4, arg5));
bellard9de5e442003-03-23 16:49:39 +00005602 break;
thse5febef2007-04-01 18:31:35 +00005603#endif
pbrook53a59602006-03-25 19:31:22 +00005604 /* ??? msync/mlock/munlock are broken for softmmu. */
thse5febef2007-04-01 18:31:35 +00005605#ifdef TARGET_NR_msync
bellard9de5e442003-03-23 16:49:39 +00005606 case TARGET_NR_msync:
pbrook53a59602006-03-25 19:31:22 +00005607 ret = get_errno(msync(g2h(arg1), arg2, arg3));
bellard9de5e442003-03-23 16:49:39 +00005608 break;
thse5febef2007-04-01 18:31:35 +00005609#endif
5610#ifdef TARGET_NR_mlock
bellard9de5e442003-03-23 16:49:39 +00005611 case TARGET_NR_mlock:
pbrook53a59602006-03-25 19:31:22 +00005612 ret = get_errno(mlock(g2h(arg1), arg2));
bellard9de5e442003-03-23 16:49:39 +00005613 break;
thse5febef2007-04-01 18:31:35 +00005614#endif
5615#ifdef TARGET_NR_munlock
bellard9de5e442003-03-23 16:49:39 +00005616 case TARGET_NR_munlock:
pbrook53a59602006-03-25 19:31:22 +00005617 ret = get_errno(munlock(g2h(arg1), arg2));
bellard9de5e442003-03-23 16:49:39 +00005618 break;
thse5febef2007-04-01 18:31:35 +00005619#endif
5620#ifdef TARGET_NR_mlockall
bellard9de5e442003-03-23 16:49:39 +00005621 case TARGET_NR_mlockall:
5622 ret = get_errno(mlockall(arg1));
5623 break;
thse5febef2007-04-01 18:31:35 +00005624#endif
5625#ifdef TARGET_NR_munlockall
bellard9de5e442003-03-23 16:49:39 +00005626 case TARGET_NR_munlockall:
5627 ret = get_errno(munlockall());
5628 break;
thse5febef2007-04-01 18:31:35 +00005629#endif
bellard31e31b82003-02-18 22:55:36 +00005630 case TARGET_NR_truncate:
bellard579a97f2007-11-11 14:26:47 +00005631 if (!(p = lock_user_string(arg1)))
5632 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005633 ret = get_errno(truncate(p, arg2));
5634 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00005635 break;
5636 case TARGET_NR_ftruncate:
5637 ret = get_errno(ftruncate(arg1, arg2));
5638 break;
5639 case TARGET_NR_fchmod:
5640 ret = get_errno(fchmod(arg1, arg2));
5641 break;
ths814d7972007-09-24 09:26:51 +00005642#if defined(TARGET_NR_fchmodat) && defined(__NR_fchmodat)
5643 case TARGET_NR_fchmodat:
bellard579a97f2007-11-11 14:26:47 +00005644 if (!(p = lock_user_string(arg2)))
5645 goto efault;
aurel32465c9f02009-04-19 08:52:17 +00005646 ret = get_errno(sys_fchmodat(arg1, p, arg3));
bellard579a97f2007-11-11 14:26:47 +00005647 unlock_user(p, arg2, 0);
ths814d7972007-09-24 09:26:51 +00005648 break;
5649#endif
bellard31e31b82003-02-18 22:55:36 +00005650 case TARGET_NR_getpriority:
thsc6cda172007-10-09 03:42:34 +00005651 /* libc does special remapping of the return value of
5652 * sys_getpriority() so it's just easiest to call
5653 * sys_getpriority() directly rather than through libc. */
Ulrich Hecht69137202009-09-17 21:08:37 +03005654 ret = get_errno(sys_getpriority(arg1, arg2));
bellard31e31b82003-02-18 22:55:36 +00005655 break;
5656 case TARGET_NR_setpriority:
5657 ret = get_errno(setpriority(arg1, arg2, arg3));
5658 break;
bellardebc05482003-09-30 21:08:41 +00005659#ifdef TARGET_NR_profil
bellard31e31b82003-02-18 22:55:36 +00005660 case TARGET_NR_profil:
5661 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00005662#endif
bellard31e31b82003-02-18 22:55:36 +00005663 case TARGET_NR_statfs:
bellard579a97f2007-11-11 14:26:47 +00005664 if (!(p = lock_user_string(arg1)))
5665 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005666 ret = get_errno(statfs(path(p), &stfs));
5667 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00005668 convert_statfs:
5669 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00005670 struct target_statfs *target_stfs;
ths3b46e622007-09-17 08:09:54 +00005671
bellard579a97f2007-11-11 14:26:47 +00005672 if (!lock_user_struct(VERIFY_WRITE, target_stfs, arg2, 0))
5673 goto efault;
5674 __put_user(stfs.f_type, &target_stfs->f_type);
5675 __put_user(stfs.f_bsize, &target_stfs->f_bsize);
5676 __put_user(stfs.f_blocks, &target_stfs->f_blocks);
5677 __put_user(stfs.f_bfree, &target_stfs->f_bfree);
5678 __put_user(stfs.f_bavail, &target_stfs->f_bavail);
5679 __put_user(stfs.f_files, &target_stfs->f_files);
5680 __put_user(stfs.f_ffree, &target_stfs->f_ffree);
5681 __put_user(stfs.f_fsid.__val[0], &target_stfs->f_fsid.val[0]);
5682 __put_user(stfs.f_fsid.__val[1], &target_stfs->f_fsid.val[1]);
5683 __put_user(stfs.f_namelen, &target_stfs->f_namelen);
pbrook53a59602006-03-25 19:31:22 +00005684 unlock_user_struct(target_stfs, arg2, 1);
bellard31e31b82003-02-18 22:55:36 +00005685 }
5686 break;
5687 case TARGET_NR_fstatfs:
bellard56c8f682005-11-28 22:28:41 +00005688 ret = get_errno(fstatfs(arg1, &stfs));
bellard31e31b82003-02-18 22:55:36 +00005689 goto convert_statfs;
bellard56c8f682005-11-28 22:28:41 +00005690#ifdef TARGET_NR_statfs64
5691 case TARGET_NR_statfs64:
bellard579a97f2007-11-11 14:26:47 +00005692 if (!(p = lock_user_string(arg1)))
5693 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005694 ret = get_errno(statfs(path(p), &stfs));
5695 unlock_user(p, arg1, 0);
bellard56c8f682005-11-28 22:28:41 +00005696 convert_statfs64:
5697 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00005698 struct target_statfs64 *target_stfs;
ths3b46e622007-09-17 08:09:54 +00005699
bellard579a97f2007-11-11 14:26:47 +00005700 if (!lock_user_struct(VERIFY_WRITE, target_stfs, arg3, 0))
5701 goto efault;
5702 __put_user(stfs.f_type, &target_stfs->f_type);
5703 __put_user(stfs.f_bsize, &target_stfs->f_bsize);
5704 __put_user(stfs.f_blocks, &target_stfs->f_blocks);
5705 __put_user(stfs.f_bfree, &target_stfs->f_bfree);
5706 __put_user(stfs.f_bavail, &target_stfs->f_bavail);
5707 __put_user(stfs.f_files, &target_stfs->f_files);
5708 __put_user(stfs.f_ffree, &target_stfs->f_ffree);
5709 __put_user(stfs.f_fsid.__val[0], &target_stfs->f_fsid.val[0]);
5710 __put_user(stfs.f_fsid.__val[1], &target_stfs->f_fsid.val[1]);
5711 __put_user(stfs.f_namelen, &target_stfs->f_namelen);
5712 unlock_user_struct(target_stfs, arg3, 1);
bellard56c8f682005-11-28 22:28:41 +00005713 }
5714 break;
5715 case TARGET_NR_fstatfs64:
5716 ret = get_errno(fstatfs(arg1, &stfs));
5717 goto convert_statfs64;
5718#endif
bellardebc05482003-09-30 21:08:41 +00005719#ifdef TARGET_NR_ioperm
bellard31e31b82003-02-18 22:55:36 +00005720 case TARGET_NR_ioperm:
5721 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00005722#endif
thse5febef2007-04-01 18:31:35 +00005723#ifdef TARGET_NR_socketcall
bellard31e31b82003-02-18 22:55:36 +00005724 case TARGET_NR_socketcall:
pbrook53a59602006-03-25 19:31:22 +00005725 ret = do_socketcall(arg1, arg2);
bellard31e31b82003-02-18 22:55:36 +00005726 break;
thse5febef2007-04-01 18:31:35 +00005727#endif
bellard3532fa72006-06-24 15:06:03 +00005728#ifdef TARGET_NR_accept
5729 case TARGET_NR_accept:
pbrook1be9e1d2006-11-19 15:26:04 +00005730 ret = do_accept(arg1, arg2, arg3);
bellard3532fa72006-06-24 15:06:03 +00005731 break;
5732#endif
5733#ifdef TARGET_NR_bind
5734 case TARGET_NR_bind:
5735 ret = do_bind(arg1, arg2, arg3);
5736 break;
5737#endif
5738#ifdef TARGET_NR_connect
5739 case TARGET_NR_connect:
5740 ret = do_connect(arg1, arg2, arg3);
5741 break;
5742#endif
5743#ifdef TARGET_NR_getpeername
5744 case TARGET_NR_getpeername:
pbrook1be9e1d2006-11-19 15:26:04 +00005745 ret = do_getpeername(arg1, arg2, arg3);
bellard3532fa72006-06-24 15:06:03 +00005746 break;
5747#endif
5748#ifdef TARGET_NR_getsockname
5749 case TARGET_NR_getsockname:
pbrook1be9e1d2006-11-19 15:26:04 +00005750 ret = do_getsockname(arg1, arg2, arg3);
bellard3532fa72006-06-24 15:06:03 +00005751 break;
5752#endif
5753#ifdef TARGET_NR_getsockopt
5754 case TARGET_NR_getsockopt:
5755 ret = do_getsockopt(arg1, arg2, arg3, arg4, arg5);
5756 break;
5757#endif
5758#ifdef TARGET_NR_listen
5759 case TARGET_NR_listen:
pbrook1be9e1d2006-11-19 15:26:04 +00005760 ret = get_errno(listen(arg1, arg2));
bellard3532fa72006-06-24 15:06:03 +00005761 break;
5762#endif
5763#ifdef TARGET_NR_recv
5764 case TARGET_NR_recv:
pbrook214201b2007-03-17 01:27:24 +00005765 ret = do_recvfrom(arg1, arg2, arg3, arg4, 0, 0);
bellard3532fa72006-06-24 15:06:03 +00005766 break;
5767#endif
5768#ifdef TARGET_NR_recvfrom
5769 case TARGET_NR_recvfrom:
pbrook214201b2007-03-17 01:27:24 +00005770 ret = do_recvfrom(arg1, arg2, arg3, arg4, arg5, arg6);
bellard3532fa72006-06-24 15:06:03 +00005771 break;
5772#endif
5773#ifdef TARGET_NR_recvmsg
5774 case TARGET_NR_recvmsg:
5775 ret = do_sendrecvmsg(arg1, arg2, arg3, 0);
5776 break;
5777#endif
5778#ifdef TARGET_NR_send
5779 case TARGET_NR_send:
pbrook1be9e1d2006-11-19 15:26:04 +00005780 ret = do_sendto(arg1, arg2, arg3, arg4, 0, 0);
bellard3532fa72006-06-24 15:06:03 +00005781 break;
5782#endif
5783#ifdef TARGET_NR_sendmsg
5784 case TARGET_NR_sendmsg:
5785 ret = do_sendrecvmsg(arg1, arg2, arg3, 1);
5786 break;
5787#endif
5788#ifdef TARGET_NR_sendto
5789 case TARGET_NR_sendto:
pbrook1be9e1d2006-11-19 15:26:04 +00005790 ret = do_sendto(arg1, arg2, arg3, arg4, arg5, arg6);
bellard3532fa72006-06-24 15:06:03 +00005791 break;
5792#endif
5793#ifdef TARGET_NR_shutdown
5794 case TARGET_NR_shutdown:
pbrook1be9e1d2006-11-19 15:26:04 +00005795 ret = get_errno(shutdown(arg1, arg2));
bellard3532fa72006-06-24 15:06:03 +00005796 break;
5797#endif
5798#ifdef TARGET_NR_socket
5799 case TARGET_NR_socket:
5800 ret = do_socket(arg1, arg2, arg3);
5801 break;
5802#endif
5803#ifdef TARGET_NR_socketpair
5804 case TARGET_NR_socketpair:
pbrook1be9e1d2006-11-19 15:26:04 +00005805 ret = do_socketpair(arg1, arg2, arg3, arg4);
bellard3532fa72006-06-24 15:06:03 +00005806 break;
5807#endif
5808#ifdef TARGET_NR_setsockopt
5809 case TARGET_NR_setsockopt:
5810 ret = do_setsockopt(arg1, arg2, arg3, arg4, (socklen_t) arg5);
5811 break;
5812#endif
ths7494b0f2007-02-11 18:26:53 +00005813
bellard31e31b82003-02-18 22:55:36 +00005814 case TARGET_NR_syslog:
bellard579a97f2007-11-11 14:26:47 +00005815 if (!(p = lock_user_string(arg2)))
5816 goto efault;
thse5574482007-02-11 20:03:13 +00005817 ret = get_errno(sys_syslog((int)arg1, p, (int)arg3));
5818 unlock_user(p, arg2, 0);
ths7494b0f2007-02-11 18:26:53 +00005819 break;
5820
bellard31e31b82003-02-18 22:55:36 +00005821 case TARGET_NR_setitimer:
bellard66fb9762003-03-23 01:06:05 +00005822 {
bellard66fb9762003-03-23 01:06:05 +00005823 struct itimerval value, ovalue, *pvalue;
5824
pbrook53a59602006-03-25 19:31:22 +00005825 if (arg2) {
bellard66fb9762003-03-23 01:06:05 +00005826 pvalue = &value;
ths788f5ec2007-12-09 02:37:05 +00005827 if (copy_from_user_timeval(&pvalue->it_interval, arg2)
5828 || copy_from_user_timeval(&pvalue->it_value,
5829 arg2 + sizeof(struct target_timeval)))
5830 goto efault;
bellard66fb9762003-03-23 01:06:05 +00005831 } else {
5832 pvalue = NULL;
5833 }
5834 ret = get_errno(setitimer(arg1, pvalue, &ovalue));
pbrook53a59602006-03-25 19:31:22 +00005835 if (!is_error(ret) && arg3) {
ths788f5ec2007-12-09 02:37:05 +00005836 if (copy_to_user_timeval(arg3,
5837 &ovalue.it_interval)
5838 || copy_to_user_timeval(arg3 + sizeof(struct target_timeval),
5839 &ovalue.it_value))
5840 goto efault;
bellard66fb9762003-03-23 01:06:05 +00005841 }
5842 }
5843 break;
bellard31e31b82003-02-18 22:55:36 +00005844 case TARGET_NR_getitimer:
bellard66fb9762003-03-23 01:06:05 +00005845 {
bellard66fb9762003-03-23 01:06:05 +00005846 struct itimerval value;
ths3b46e622007-09-17 08:09:54 +00005847
bellard66fb9762003-03-23 01:06:05 +00005848 ret = get_errno(getitimer(arg1, &value));
pbrook53a59602006-03-25 19:31:22 +00005849 if (!is_error(ret) && arg2) {
ths788f5ec2007-12-09 02:37:05 +00005850 if (copy_to_user_timeval(arg2,
5851 &value.it_interval)
5852 || copy_to_user_timeval(arg2 + sizeof(struct target_timeval),
5853 &value.it_value))
5854 goto efault;
bellard66fb9762003-03-23 01:06:05 +00005855 }
5856 }
5857 break;
bellard31e31b82003-02-18 22:55:36 +00005858 case TARGET_NR_stat:
bellard579a97f2007-11-11 14:26:47 +00005859 if (!(p = lock_user_string(arg1)))
5860 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005861 ret = get_errno(stat(path(p), &st));
5862 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00005863 goto do_stat;
5864 case TARGET_NR_lstat:
bellard579a97f2007-11-11 14:26:47 +00005865 if (!(p = lock_user_string(arg1)))
5866 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005867 ret = get_errno(lstat(path(p), &st));
5868 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00005869 goto do_stat;
5870 case TARGET_NR_fstat:
5871 {
5872 ret = get_errno(fstat(arg1, &st));
5873 do_stat:
5874 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00005875 struct target_stat *target_st;
thse3584652007-06-01 11:49:38 +00005876
bellard579a97f2007-11-11 14:26:47 +00005877 if (!lock_user_struct(VERIFY_WRITE, target_st, arg2, 0))
5878 goto efault;
Ulrich Hecht12727912009-07-24 19:10:32 +02005879 memset(target_st, 0, sizeof(*target_st));
bellardd2fd1af2007-11-14 18:08:56 +00005880 __put_user(st.st_dev, &target_st->st_dev);
5881 __put_user(st.st_ino, &target_st->st_ino);
5882 __put_user(st.st_mode, &target_st->st_mode);
5883 __put_user(st.st_uid, &target_st->st_uid);
5884 __put_user(st.st_gid, &target_st->st_gid);
5885 __put_user(st.st_nlink, &target_st->st_nlink);
5886 __put_user(st.st_rdev, &target_st->st_rdev);
5887 __put_user(st.st_size, &target_st->st_size);
5888 __put_user(st.st_blksize, &target_st->st_blksize);
5889 __put_user(st.st_blocks, &target_st->st_blocks);
5890 __put_user(st.st_atime, &target_st->target_st_atime);
5891 __put_user(st.st_mtime, &target_st->target_st_mtime);
5892 __put_user(st.st_ctime, &target_st->target_st_ctime);
pbrook53a59602006-03-25 19:31:22 +00005893 unlock_user_struct(target_st, arg2, 1);
bellard31e31b82003-02-18 22:55:36 +00005894 }
5895 }
5896 break;
bellardebc05482003-09-30 21:08:41 +00005897#ifdef TARGET_NR_olduname
bellard31e31b82003-02-18 22:55:36 +00005898 case TARGET_NR_olduname:
5899 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00005900#endif
5901#ifdef TARGET_NR_iopl
bellard31e31b82003-02-18 22:55:36 +00005902 case TARGET_NR_iopl:
5903 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00005904#endif
bellard31e31b82003-02-18 22:55:36 +00005905 case TARGET_NR_vhangup:
5906 ret = get_errno(vhangup());
5907 break;
bellardebc05482003-09-30 21:08:41 +00005908#ifdef TARGET_NR_idle
bellard31e31b82003-02-18 22:55:36 +00005909 case TARGET_NR_idle:
5910 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00005911#endif
bellard42ad6ae2005-01-03 22:48:11 +00005912#ifdef TARGET_NR_syscall
5913 case TARGET_NR_syscall:
5914 ret = do_syscall(cpu_env,arg1 & 0xffff,arg2,arg3,arg4,arg5,arg6,0);
5915 break;
5916#endif
bellard31e31b82003-02-18 22:55:36 +00005917 case TARGET_NR_wait4:
5918 {
5919 int status;
blueswir1992f48a2007-10-14 16:27:31 +00005920 abi_long status_ptr = arg2;
bellard31e31b82003-02-18 22:55:36 +00005921 struct rusage rusage, *rusage_ptr;
blueswir1992f48a2007-10-14 16:27:31 +00005922 abi_ulong target_rusage = arg4;
bellard31e31b82003-02-18 22:55:36 +00005923 if (target_rusage)
5924 rusage_ptr = &rusage;
5925 else
5926 rusage_ptr = NULL;
5927 ret = get_errno(wait4(arg1, &status, arg3, rusage_ptr));
5928 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +00005929 if (status_ptr) {
pbrook1d9d8b52009-04-16 15:17:02 +00005930 status = host_to_target_waitstatus(status);
bellard2f619692007-11-16 10:46:05 +00005931 if (put_user_s32(status, status_ptr))
5932 goto efault;
bellard31e31b82003-02-18 22:55:36 +00005933 }
bellard2f619692007-11-16 10:46:05 +00005934 if (target_rusage)
5935 host_to_target_rusage(target_rusage, &rusage);
bellard31e31b82003-02-18 22:55:36 +00005936 }
5937 }
5938 break;
thse5febef2007-04-01 18:31:35 +00005939#ifdef TARGET_NR_swapoff
bellard31e31b82003-02-18 22:55:36 +00005940 case TARGET_NR_swapoff:
bellard579a97f2007-11-11 14:26:47 +00005941 if (!(p = lock_user_string(arg1)))
5942 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005943 ret = get_errno(swapoff(p));
5944 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00005945 break;
thse5febef2007-04-01 18:31:35 +00005946#endif
bellard31e31b82003-02-18 22:55:36 +00005947 case TARGET_NR_sysinfo:
bellarda5448a72004-06-19 16:59:03 +00005948 {
pbrook53a59602006-03-25 19:31:22 +00005949 struct target_sysinfo *target_value;
bellarda5448a72004-06-19 16:59:03 +00005950 struct sysinfo value;
5951 ret = get_errno(sysinfo(&value));
pbrook53a59602006-03-25 19:31:22 +00005952 if (!is_error(ret) && arg1)
bellarda5448a72004-06-19 16:59:03 +00005953 {
bellard579a97f2007-11-11 14:26:47 +00005954 if (!lock_user_struct(VERIFY_WRITE, target_value, arg1, 0))
5955 goto efault;
bellarda5448a72004-06-19 16:59:03 +00005956 __put_user(value.uptime, &target_value->uptime);
5957 __put_user(value.loads[0], &target_value->loads[0]);
5958 __put_user(value.loads[1], &target_value->loads[1]);
5959 __put_user(value.loads[2], &target_value->loads[2]);
5960 __put_user(value.totalram, &target_value->totalram);
5961 __put_user(value.freeram, &target_value->freeram);
5962 __put_user(value.sharedram, &target_value->sharedram);
5963 __put_user(value.bufferram, &target_value->bufferram);
5964 __put_user(value.totalswap, &target_value->totalswap);
5965 __put_user(value.freeswap, &target_value->freeswap);
5966 __put_user(value.procs, &target_value->procs);
5967 __put_user(value.totalhigh, &target_value->totalhigh);
5968 __put_user(value.freehigh, &target_value->freehigh);
5969 __put_user(value.mem_unit, &target_value->mem_unit);
pbrook53a59602006-03-25 19:31:22 +00005970 unlock_user_struct(target_value, arg1, 1);
bellarda5448a72004-06-19 16:59:03 +00005971 }
5972 }
5973 break;
thse5febef2007-04-01 18:31:35 +00005974#ifdef TARGET_NR_ipc
bellard31e31b82003-02-18 22:55:36 +00005975 case TARGET_NR_ipc:
bellard8853f862004-02-22 14:57:26 +00005976 ret = do_ipc(arg1, arg2, arg3, arg4, arg5, arg6);
5977 break;
thse5febef2007-04-01 18:31:35 +00005978#endif
aurel32e5289082009-04-18 16:16:12 +00005979#ifdef TARGET_NR_semget
5980 case TARGET_NR_semget:
5981 ret = get_errno(semget(arg1, arg2, arg3));
5982 break;
5983#endif
5984#ifdef TARGET_NR_semop
5985 case TARGET_NR_semop:
5986 ret = get_errno(do_semop(arg1, arg2, arg3));
5987 break;
5988#endif
5989#ifdef TARGET_NR_semctl
5990 case TARGET_NR_semctl:
5991 ret = do_semctl(arg1, arg2, arg3, (union target_semun)(abi_ulong)arg4);
5992 break;
5993#endif
aurel32eeb438c2008-10-13 21:08:55 +00005994#ifdef TARGET_NR_msgctl
5995 case TARGET_NR_msgctl:
5996 ret = do_msgctl(arg1, arg2, arg3);
5997 break;
5998#endif
5999#ifdef TARGET_NR_msgget
6000 case TARGET_NR_msgget:
6001 ret = get_errno(msgget(arg1, arg2));
6002 break;
6003#endif
6004#ifdef TARGET_NR_msgrcv
6005 case TARGET_NR_msgrcv:
6006 ret = do_msgrcv(arg1, arg2, arg3, arg4, arg5);
6007 break;
6008#endif
6009#ifdef TARGET_NR_msgsnd
6010 case TARGET_NR_msgsnd:
6011 ret = do_msgsnd(arg1, arg2, arg3, arg4);
6012 break;
6013#endif
Riku Voipio88a8c982009-04-03 10:42:00 +03006014#ifdef TARGET_NR_shmget
6015 case TARGET_NR_shmget:
6016 ret = get_errno(shmget(arg1, arg2, arg3));
6017 break;
6018#endif
6019#ifdef TARGET_NR_shmctl
6020 case TARGET_NR_shmctl:
6021 ret = do_shmctl(arg1, arg2, arg3);
6022 break;
6023#endif
6024#ifdef TARGET_NR_shmat
6025 case TARGET_NR_shmat:
6026 ret = do_shmat(arg1, arg2, arg3);
6027 break;
6028#endif
6029#ifdef TARGET_NR_shmdt
6030 case TARGET_NR_shmdt:
6031 ret = do_shmdt(arg1);
6032 break;
6033#endif
bellard31e31b82003-02-18 22:55:36 +00006034 case TARGET_NR_fsync:
6035 ret = get_errno(fsync(arg1));
6036 break;
bellard31e31b82003-02-18 22:55:36 +00006037 case TARGET_NR_clone:
Richard Hendersona4b388f2010-04-12 16:17:22 -07006038#if defined(TARGET_SH4) || defined(TARGET_ALPHA)
aurel320b6d3ae2008-09-15 07:43:43 +00006039 ret = get_errno(do_fork(cpu_env, arg1, arg2, arg3, arg5, arg4));
edgar_iglb15ad612009-01-07 19:43:47 +00006040#elif defined(TARGET_CRIS)
6041 ret = get_errno(do_fork(cpu_env, arg2, arg1, arg3, arg4, arg5));
aurel320b6d3ae2008-09-15 07:43:43 +00006042#else
pbrookd865bab2008-06-07 22:12:17 +00006043 ret = get_errno(do_fork(cpu_env, arg1, arg2, arg3, arg4, arg5));
aurel320b6d3ae2008-09-15 07:43:43 +00006044#endif
bellard1b6b0292003-03-22 17:31:38 +00006045 break;
bellardec86b0f2003-04-11 00:15:04 +00006046#ifdef __NR_exit_group
6047 /* new thread calls */
6048 case TARGET_NR_exit_group:
Juan Quintela9788c9c2009-07-27 16:13:02 +02006049#ifdef TARGET_GPROF
aurel326d946cd2008-11-06 16:15:18 +00006050 _mcleanup();
6051#endif
bellarde9009672005-04-26 20:42:36 +00006052 gdb_exit(cpu_env, arg1);
bellardec86b0f2003-04-11 00:15:04 +00006053 ret = get_errno(exit_group(arg1));
6054 break;
6055#endif
bellard31e31b82003-02-18 22:55:36 +00006056 case TARGET_NR_setdomainname:
bellard579a97f2007-11-11 14:26:47 +00006057 if (!(p = lock_user_string(arg1)))
6058 goto efault;
pbrook53a59602006-03-25 19:31:22 +00006059 ret = get_errno(setdomainname(p, arg2));
6060 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00006061 break;
6062 case TARGET_NR_uname:
6063 /* no need to transcode because we use the linux syscall */
bellard29e619b2004-09-13 21:41:04 +00006064 {
6065 struct new_utsname * buf;
ths3b46e622007-09-17 08:09:54 +00006066
bellard579a97f2007-11-11 14:26:47 +00006067 if (!lock_user_struct(VERIFY_WRITE, buf, arg1, 0))
6068 goto efault;
bellard29e619b2004-09-13 21:41:04 +00006069 ret = get_errno(sys_uname(buf));
6070 if (!is_error(ret)) {
6071 /* Overrite the native machine name with whatever is being
6072 emulated. */
Loïc Minierda790302009-12-29 22:06:13 +01006073 strcpy (buf->machine, cpu_to_uname_machine(cpu_env));
pbrookc5937222006-05-14 11:30:38 +00006074 /* Allow the user to override the reported release. */
6075 if (qemu_uname_release && *qemu_uname_release)
6076 strcpy (buf->release, qemu_uname_release);
bellard29e619b2004-09-13 21:41:04 +00006077 }
pbrook53a59602006-03-25 19:31:22 +00006078 unlock_user_struct(buf, arg1, 1);
bellard29e619b2004-09-13 21:41:04 +00006079 }
bellard31e31b82003-02-18 22:55:36 +00006080 break;
bellard6dbad632003-03-16 18:05:05 +00006081#ifdef TARGET_I386
bellard31e31b82003-02-18 22:55:36 +00006082 case TARGET_NR_modify_ldt:
bellard03acab62007-11-11 14:57:14 +00006083 ret = do_modify_ldt(cpu_env, arg1, arg2, arg3);
bellard5cd43932003-03-29 16:54:36 +00006084 break;
j_mayer84409dd2007-04-06 08:56:50 +00006085#if !defined(TARGET_X86_64)
bellard5cd43932003-03-29 16:54:36 +00006086 case TARGET_NR_vm86old:
6087 goto unimplemented;
6088 case TARGET_NR_vm86:
pbrook53a59602006-03-25 19:31:22 +00006089 ret = do_vm86(cpu_env, arg1, arg2);
bellard6dbad632003-03-16 18:05:05 +00006090 break;
6091#endif
j_mayer84409dd2007-04-06 08:56:50 +00006092#endif
bellard31e31b82003-02-18 22:55:36 +00006093 case TARGET_NR_adjtimex:
6094 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00006095#ifdef TARGET_NR_create_module
bellard31e31b82003-02-18 22:55:36 +00006096 case TARGET_NR_create_module:
thse5febef2007-04-01 18:31:35 +00006097#endif
bellard31e31b82003-02-18 22:55:36 +00006098 case TARGET_NR_init_module:
6099 case TARGET_NR_delete_module:
thse5febef2007-04-01 18:31:35 +00006100#ifdef TARGET_NR_get_kernel_syms
bellard31e31b82003-02-18 22:55:36 +00006101 case TARGET_NR_get_kernel_syms:
thse5febef2007-04-01 18:31:35 +00006102#endif
bellard31e31b82003-02-18 22:55:36 +00006103 goto unimplemented;
6104 case TARGET_NR_quotactl:
6105 goto unimplemented;
6106 case TARGET_NR_getpgid:
6107 ret = get_errno(getpgid(arg1));
6108 break;
6109 case TARGET_NR_fchdir:
6110 ret = get_errno(fchdir(arg1));
6111 break;
j_mayer84409dd2007-04-06 08:56:50 +00006112#ifdef TARGET_NR_bdflush /* not on x86_64 */
bellard31e31b82003-02-18 22:55:36 +00006113 case TARGET_NR_bdflush:
6114 goto unimplemented;
j_mayer84409dd2007-04-06 08:56:50 +00006115#endif
thse5febef2007-04-01 18:31:35 +00006116#ifdef TARGET_NR_sysfs
bellard31e31b82003-02-18 22:55:36 +00006117 case TARGET_NR_sysfs:
6118 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00006119#endif
bellard31e31b82003-02-18 22:55:36 +00006120 case TARGET_NR_personality:
bellard1b6b0292003-03-22 17:31:38 +00006121 ret = get_errno(personality(arg1));
bellard31e31b82003-02-18 22:55:36 +00006122 break;
thse5febef2007-04-01 18:31:35 +00006123#ifdef TARGET_NR_afs_syscall
bellard31e31b82003-02-18 22:55:36 +00006124 case TARGET_NR_afs_syscall:
6125 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00006126#endif
j_mayer7a3148a2007-04-05 07:13:51 +00006127#ifdef TARGET_NR__llseek /* Not on alpha */
bellard31e31b82003-02-18 22:55:36 +00006128 case TARGET_NR__llseek:
6129 {
6130 int64_t res;
Peter Maydell0c1592d2011-02-22 13:02:26 +00006131#if !defined(__NR_llseek)
6132 res = lseek(arg1, ((uint64_t)arg2 << 32) | arg3, arg5);
6133 if (res == -1) {
6134 ret = get_errno(res);
6135 } else {
6136 ret = 0;
6137 }
6138#else
bellard31e31b82003-02-18 22:55:36 +00006139 ret = get_errno(_llseek(arg1, arg2, arg3, &res, arg5));
bellard4f2ac232004-04-26 19:44:02 +00006140#endif
Peter Maydell0c1592d2011-02-22 13:02:26 +00006141 if ((ret == 0) && put_user_s64(res, arg4)) {
6142 goto efault;
6143 }
bellard31e31b82003-02-18 22:55:36 +00006144 }
6145 break;
j_mayer7a3148a2007-04-05 07:13:51 +00006146#endif
bellard31e31b82003-02-18 22:55:36 +00006147 case TARGET_NR_getdents:
Ulrich Hechtd83c8732009-07-24 19:10:28 +02006148#if TARGET_ABI_BITS == 32 && HOST_LONG_BITS == 64
bellard4add45b2003-06-05 01:52:59 +00006149 {
pbrook53a59602006-03-25 19:31:22 +00006150 struct target_dirent *target_dirp;
aurel326556a832008-10-13 21:08:17 +00006151 struct linux_dirent *dirp;
blueswir1992f48a2007-10-14 16:27:31 +00006152 abi_long count = arg3;
bellard4add45b2003-06-05 01:52:59 +00006153
6154 dirp = malloc(count);
ths0da46a62007-10-20 20:23:07 +00006155 if (!dirp) {
bellard579a97f2007-11-11 14:26:47 +00006156 ret = -TARGET_ENOMEM;
ths0da46a62007-10-20 20:23:07 +00006157 goto fail;
6158 }
ths3b46e622007-09-17 08:09:54 +00006159
bellard4add45b2003-06-05 01:52:59 +00006160 ret = get_errno(sys_getdents(arg1, dirp, count));
6161 if (!is_error(ret)) {
aurel326556a832008-10-13 21:08:17 +00006162 struct linux_dirent *de;
bellard4add45b2003-06-05 01:52:59 +00006163 struct target_dirent *tde;
6164 int len = ret;
6165 int reclen, treclen;
6166 int count1, tnamelen;
6167
6168 count1 = 0;
6169 de = dirp;
bellard579a97f2007-11-11 14:26:47 +00006170 if (!(target_dirp = lock_user(VERIFY_WRITE, arg2, count, 0)))
6171 goto efault;
bellard4add45b2003-06-05 01:52:59 +00006172 tde = target_dirp;
6173 while (len > 0) {
6174 reclen = de->d_reclen;
blueswir1992f48a2007-10-14 16:27:31 +00006175 treclen = reclen - (2 * (sizeof(long) - sizeof(abi_long)));
bellard4add45b2003-06-05 01:52:59 +00006176 tde->d_reclen = tswap16(treclen);
6177 tde->d_ino = tswapl(de->d_ino);
6178 tde->d_off = tswapl(de->d_off);
blueswir1992f48a2007-10-14 16:27:31 +00006179 tnamelen = treclen - (2 * sizeof(abi_long) + 2);
bellard4add45b2003-06-05 01:52:59 +00006180 if (tnamelen > 256)
6181 tnamelen = 256;
bellard80a9d032005-01-03 23:31:27 +00006182 /* XXX: may not be correct */
blueswir1be15b142008-10-25 11:21:28 +00006183 pstrcpy(tde->d_name, tnamelen, de->d_name);
aurel326556a832008-10-13 21:08:17 +00006184 de = (struct linux_dirent *)((char *)de + reclen);
bellard4add45b2003-06-05 01:52:59 +00006185 len -= reclen;
j_mayer1c5bf3b2007-04-14 12:17:59 +00006186 tde = (struct target_dirent *)((char *)tde + treclen);
bellard4add45b2003-06-05 01:52:59 +00006187 count1 += treclen;
6188 }
6189 ret = count1;
bellard579a97f2007-11-11 14:26:47 +00006190 unlock_user(target_dirp, arg2, ret);
bellard4add45b2003-06-05 01:52:59 +00006191 }
6192 free(dirp);
6193 }
6194#else
bellard31e31b82003-02-18 22:55:36 +00006195 {
aurel326556a832008-10-13 21:08:17 +00006196 struct linux_dirent *dirp;
blueswir1992f48a2007-10-14 16:27:31 +00006197 abi_long count = arg3;
bellarddab2ed92003-03-22 15:23:14 +00006198
bellard579a97f2007-11-11 14:26:47 +00006199 if (!(dirp = lock_user(VERIFY_WRITE, arg2, count, 0)))
6200 goto efault;
bellard72f03902003-02-18 23:33:18 +00006201 ret = get_errno(sys_getdents(arg1, dirp, count));
bellard31e31b82003-02-18 22:55:36 +00006202 if (!is_error(ret)) {
aurel326556a832008-10-13 21:08:17 +00006203 struct linux_dirent *de;
bellard31e31b82003-02-18 22:55:36 +00006204 int len = ret;
6205 int reclen;
6206 de = dirp;
6207 while (len > 0) {
bellard8083a3e2003-03-24 23:12:16 +00006208 reclen = de->d_reclen;
bellard31e31b82003-02-18 22:55:36 +00006209 if (reclen > len)
6210 break;
bellard8083a3e2003-03-24 23:12:16 +00006211 de->d_reclen = tswap16(reclen);
bellard31e31b82003-02-18 22:55:36 +00006212 tswapls(&de->d_ino);
6213 tswapls(&de->d_off);
aurel326556a832008-10-13 21:08:17 +00006214 de = (struct linux_dirent *)((char *)de + reclen);
bellard31e31b82003-02-18 22:55:36 +00006215 len -= reclen;
6216 }
6217 }
pbrook53a59602006-03-25 19:31:22 +00006218 unlock_user(dirp, arg2, ret);
bellard31e31b82003-02-18 22:55:36 +00006219 }
bellard4add45b2003-06-05 01:52:59 +00006220#endif
bellard31e31b82003-02-18 22:55:36 +00006221 break;
ths3ae43202007-09-16 21:39:48 +00006222#if defined(TARGET_NR_getdents64) && defined(__NR_getdents64)
bellarddab2ed92003-03-22 15:23:14 +00006223 case TARGET_NR_getdents64:
6224 {
aurel326556a832008-10-13 21:08:17 +00006225 struct linux_dirent64 *dirp;
blueswir1992f48a2007-10-14 16:27:31 +00006226 abi_long count = arg3;
bellard579a97f2007-11-11 14:26:47 +00006227 if (!(dirp = lock_user(VERIFY_WRITE, arg2, count, 0)))
6228 goto efault;
bellarddab2ed92003-03-22 15:23:14 +00006229 ret = get_errno(sys_getdents64(arg1, dirp, count));
6230 if (!is_error(ret)) {
aurel326556a832008-10-13 21:08:17 +00006231 struct linux_dirent64 *de;
bellarddab2ed92003-03-22 15:23:14 +00006232 int len = ret;
6233 int reclen;
6234 de = dirp;
6235 while (len > 0) {
bellard8083a3e2003-03-24 23:12:16 +00006236 reclen = de->d_reclen;
bellarddab2ed92003-03-22 15:23:14 +00006237 if (reclen > len)
6238 break;
bellard8083a3e2003-03-24 23:12:16 +00006239 de->d_reclen = tswap16(reclen);
bellard8582a532007-11-11 23:11:36 +00006240 tswap64s((uint64_t *)&de->d_ino);
6241 tswap64s((uint64_t *)&de->d_off);
aurel326556a832008-10-13 21:08:17 +00006242 de = (struct linux_dirent64 *)((char *)de + reclen);
bellarddab2ed92003-03-22 15:23:14 +00006243 len -= reclen;
6244 }
6245 }
pbrook53a59602006-03-25 19:31:22 +00006246 unlock_user(dirp, arg2, ret);
bellarddab2ed92003-03-22 15:23:14 +00006247 }
6248 break;
bellarda541f292004-04-12 20:39:29 +00006249#endif /* TARGET_NR_getdents64 */
thse5febef2007-04-01 18:31:35 +00006250#ifdef TARGET_NR__newselect
bellard31e31b82003-02-18 22:55:36 +00006251 case TARGET_NR__newselect:
pbrook53a59602006-03-25 19:31:22 +00006252 ret = do_select(arg1, arg2, arg3, arg4, arg5);
bellard31e31b82003-02-18 22:55:36 +00006253 break;
thse5febef2007-04-01 18:31:35 +00006254#endif
Mike Frysingerd8035d42011-02-07 01:05:51 -05006255#if defined(TARGET_NR_poll) || defined(TARGET_NR_ppoll)
6256# ifdef TARGET_NR_poll
bellard9de5e442003-03-23 16:49:39 +00006257 case TARGET_NR_poll:
Mike Frysingerd8035d42011-02-07 01:05:51 -05006258# endif
6259# ifdef TARGET_NR_ppoll
6260 case TARGET_NR_ppoll:
6261# endif
bellard9de5e442003-03-23 16:49:39 +00006262 {
pbrook53a59602006-03-25 19:31:22 +00006263 struct target_pollfd *target_pfd;
bellard9de5e442003-03-23 16:49:39 +00006264 unsigned int nfds = arg2;
6265 int timeout = arg3;
6266 struct pollfd *pfd;
bellard7854b052003-03-29 17:22:23 +00006267 unsigned int i;
bellard9de5e442003-03-23 16:49:39 +00006268
bellard579a97f2007-11-11 14:26:47 +00006269 target_pfd = lock_user(VERIFY_WRITE, arg1, sizeof(struct target_pollfd) * nfds, 1);
6270 if (!target_pfd)
6271 goto efault;
Mike Frysingerd8035d42011-02-07 01:05:51 -05006272
bellard9de5e442003-03-23 16:49:39 +00006273 pfd = alloca(sizeof(struct pollfd) * nfds);
6274 for(i = 0; i < nfds; i++) {
bellard5cd43932003-03-29 16:54:36 +00006275 pfd[i].fd = tswap32(target_pfd[i].fd);
6276 pfd[i].events = tswap16(target_pfd[i].events);
bellard9de5e442003-03-23 16:49:39 +00006277 }
Mike Frysingerd8035d42011-02-07 01:05:51 -05006278
6279# ifdef TARGET_NR_ppoll
6280 if (num == TARGET_NR_ppoll) {
6281 struct timespec _timeout_ts, *timeout_ts = &_timeout_ts;
6282 target_sigset_t *target_set;
6283 sigset_t _set, *set = &_set;
6284
6285 if (arg3) {
6286 if (target_to_host_timespec(timeout_ts, arg3)) {
6287 unlock_user(target_pfd, arg1, 0);
6288 goto efault;
6289 }
6290 } else {
6291 timeout_ts = NULL;
6292 }
6293
6294 if (arg4) {
6295 target_set = lock_user(VERIFY_READ, arg4, sizeof(target_sigset_t), 1);
6296 if (!target_set) {
6297 unlock_user(target_pfd, arg1, 0);
6298 goto efault;
6299 }
6300 target_to_host_sigset(set, target_set);
6301 } else {
6302 set = NULL;
6303 }
6304
6305 ret = get_errno(sys_ppoll(pfd, nfds, timeout_ts, set, _NSIG/8));
6306
6307 if (!is_error(ret) && arg3) {
6308 host_to_target_timespec(arg3, timeout_ts);
6309 }
6310 if (arg4) {
6311 unlock_user(target_set, arg4, 0);
6312 }
6313 } else
6314# endif
6315 ret = get_errno(poll(pfd, nfds, timeout));
6316
bellard9de5e442003-03-23 16:49:39 +00006317 if (!is_error(ret)) {
6318 for(i = 0; i < nfds; i++) {
bellard5cd43932003-03-29 16:54:36 +00006319 target_pfd[i].revents = tswap16(pfd[i].revents);
bellard9de5e442003-03-23 16:49:39 +00006320 }
6321 }
Peter Maydell30cb4cd2011-02-25 10:27:40 +00006322 unlock_user(target_pfd, arg1, sizeof(struct target_pollfd) * nfds);
bellard9de5e442003-03-23 16:49:39 +00006323 }
6324 break;
thse5febef2007-04-01 18:31:35 +00006325#endif
bellard31e31b82003-02-18 22:55:36 +00006326 case TARGET_NR_flock:
bellard9de5e442003-03-23 16:49:39 +00006327 /* NOTE: the flock constant seems to be the same for every
6328 Linux platform */
6329 ret = get_errno(flock(arg1, arg2));
bellard31e31b82003-02-18 22:55:36 +00006330 break;
6331 case TARGET_NR_readv:
6332 {
6333 int count = arg3;
bellard31e31b82003-02-18 22:55:36 +00006334 struct iovec *vec;
bellard31e31b82003-02-18 22:55:36 +00006335
6336 vec = alloca(count * sizeof(struct iovec));
bellard41df8412008-02-04 22:26:57 +00006337 if (lock_iovec(VERIFY_WRITE, vec, arg2, count, 0) < 0)
6338 goto efault;
bellard31e31b82003-02-18 22:55:36 +00006339 ret = get_errno(readv(arg1, vec, count));
pbrook53a59602006-03-25 19:31:22 +00006340 unlock_iovec(vec, arg2, count, 1);
bellard31e31b82003-02-18 22:55:36 +00006341 }
6342 break;
6343 case TARGET_NR_writev:
6344 {
6345 int count = arg3;
bellard31e31b82003-02-18 22:55:36 +00006346 struct iovec *vec;
bellard31e31b82003-02-18 22:55:36 +00006347
6348 vec = alloca(count * sizeof(struct iovec));
bellard41df8412008-02-04 22:26:57 +00006349 if (lock_iovec(VERIFY_READ, vec, arg2, count, 1) < 0)
6350 goto efault;
bellard31e31b82003-02-18 22:55:36 +00006351 ret = get_errno(writev(arg1, vec, count));
pbrook53a59602006-03-25 19:31:22 +00006352 unlock_iovec(vec, arg2, count, 0);
bellard31e31b82003-02-18 22:55:36 +00006353 }
6354 break;
6355 case TARGET_NR_getsid:
6356 ret = get_errno(getsid(arg1));
6357 break;
j_mayer7a3148a2007-04-05 07:13:51 +00006358#if defined(TARGET_NR_fdatasync) /* Not on alpha (osf_datasync ?) */
bellard31e31b82003-02-18 22:55:36 +00006359 case TARGET_NR_fdatasync:
bellard5cd43932003-03-29 16:54:36 +00006360 ret = get_errno(fdatasync(arg1));
6361 break;
j_mayer7a3148a2007-04-05 07:13:51 +00006362#endif
bellard31e31b82003-02-18 22:55:36 +00006363 case TARGET_NR__sysctl:
ths0da46a62007-10-20 20:23:07 +00006364 /* We don't implement this, but ENOTDIR is always a safe
bellard29e619b2004-09-13 21:41:04 +00006365 return value. */
ths0da46a62007-10-20 20:23:07 +00006366 ret = -TARGET_ENOTDIR;
6367 break;
Mike Frysinger737de1d2011-02-07 01:05:55 -05006368 case TARGET_NR_sched_getaffinity:
6369 {
6370 unsigned int mask_size;
6371 unsigned long *mask;
6372
6373 /*
6374 * sched_getaffinity needs multiples of ulong, so need to take
6375 * care of mismatches between target ulong and host ulong sizes.
6376 */
6377 if (arg2 & (sizeof(abi_ulong) - 1)) {
6378 ret = -TARGET_EINVAL;
6379 break;
6380 }
6381 mask_size = (arg2 + (sizeof(*mask) - 1)) & ~(sizeof(*mask) - 1);
6382
6383 mask = alloca(mask_size);
6384 ret = get_errno(sys_sched_getaffinity(arg1, mask_size, mask));
6385
6386 if (!is_error(ret)) {
6387 if (arg2 > ret) {
6388 /* Zero out any extra space kernel didn't fill */
6389 unsigned long zero = arg2 - ret;
6390 p = alloca(zero);
6391 memset(p, 0, zero);
6392 if (copy_to_user(arg3 + zero, p, zero)) {
6393 goto efault;
6394 }
6395 arg2 = ret;
6396 }
6397 if (copy_to_user(arg3, mask, arg2)) {
6398 goto efault;
6399 }
6400 ret = arg2;
6401 }
6402 }
6403 break;
6404 case TARGET_NR_sched_setaffinity:
6405 {
6406 unsigned int mask_size;
6407 unsigned long *mask;
6408
6409 /*
6410 * sched_setaffinity needs multiples of ulong, so need to take
6411 * care of mismatches between target ulong and host ulong sizes.
6412 */
6413 if (arg2 & (sizeof(abi_ulong) - 1)) {
6414 ret = -TARGET_EINVAL;
6415 break;
6416 }
6417 mask_size = (arg2 + (sizeof(*mask) - 1)) & ~(sizeof(*mask) - 1);
6418
6419 mask = alloca(mask_size);
6420 if (!lock_user_struct(VERIFY_READ, p, arg3, 1)) {
6421 goto efault;
6422 }
6423 memcpy(mask, p, arg2);
6424 unlock_user_struct(p, arg2, 0);
6425
6426 ret = get_errno(sys_sched_setaffinity(arg1, mask_size, mask));
6427 }
6428 break;
bellard31e31b82003-02-18 22:55:36 +00006429 case TARGET_NR_sched_setparam:
bellard5cd43932003-03-29 16:54:36 +00006430 {
pbrook53a59602006-03-25 19:31:22 +00006431 struct sched_param *target_schp;
bellard5cd43932003-03-29 16:54:36 +00006432 struct sched_param schp;
pbrook53a59602006-03-25 19:31:22 +00006433
bellard579a97f2007-11-11 14:26:47 +00006434 if (!lock_user_struct(VERIFY_READ, target_schp, arg2, 1))
6435 goto efault;
bellard5cd43932003-03-29 16:54:36 +00006436 schp.sched_priority = tswap32(target_schp->sched_priority);
pbrook53a59602006-03-25 19:31:22 +00006437 unlock_user_struct(target_schp, arg2, 0);
bellard5cd43932003-03-29 16:54:36 +00006438 ret = get_errno(sched_setparam(arg1, &schp));
6439 }
6440 break;
bellard31e31b82003-02-18 22:55:36 +00006441 case TARGET_NR_sched_getparam:
bellard5cd43932003-03-29 16:54:36 +00006442 {
pbrook53a59602006-03-25 19:31:22 +00006443 struct sched_param *target_schp;
bellard5cd43932003-03-29 16:54:36 +00006444 struct sched_param schp;
6445 ret = get_errno(sched_getparam(arg1, &schp));
6446 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00006447 if (!lock_user_struct(VERIFY_WRITE, target_schp, arg2, 0))
6448 goto efault;
bellard5cd43932003-03-29 16:54:36 +00006449 target_schp->sched_priority = tswap32(schp.sched_priority);
pbrook53a59602006-03-25 19:31:22 +00006450 unlock_user_struct(target_schp, arg2, 1);
bellard5cd43932003-03-29 16:54:36 +00006451 }
6452 }
6453 break;
bellard31e31b82003-02-18 22:55:36 +00006454 case TARGET_NR_sched_setscheduler:
bellard5cd43932003-03-29 16:54:36 +00006455 {
pbrook53a59602006-03-25 19:31:22 +00006456 struct sched_param *target_schp;
bellard5cd43932003-03-29 16:54:36 +00006457 struct sched_param schp;
bellard579a97f2007-11-11 14:26:47 +00006458 if (!lock_user_struct(VERIFY_READ, target_schp, arg3, 1))
6459 goto efault;
bellard5cd43932003-03-29 16:54:36 +00006460 schp.sched_priority = tswap32(target_schp->sched_priority);
pbrook53a59602006-03-25 19:31:22 +00006461 unlock_user_struct(target_schp, arg3, 0);
bellard5cd43932003-03-29 16:54:36 +00006462 ret = get_errno(sched_setscheduler(arg1, arg2, &schp));
6463 }
6464 break;
bellard31e31b82003-02-18 22:55:36 +00006465 case TARGET_NR_sched_getscheduler:
bellard5cd43932003-03-29 16:54:36 +00006466 ret = get_errno(sched_getscheduler(arg1));
6467 break;
bellard31e31b82003-02-18 22:55:36 +00006468 case TARGET_NR_sched_yield:
6469 ret = get_errno(sched_yield());
6470 break;
6471 case TARGET_NR_sched_get_priority_max:
bellard5cd43932003-03-29 16:54:36 +00006472 ret = get_errno(sched_get_priority_max(arg1));
6473 break;
bellard31e31b82003-02-18 22:55:36 +00006474 case TARGET_NR_sched_get_priority_min:
bellard5cd43932003-03-29 16:54:36 +00006475 ret = get_errno(sched_get_priority_min(arg1));
6476 break;
bellard31e31b82003-02-18 22:55:36 +00006477 case TARGET_NR_sched_rr_get_interval:
bellard5cd43932003-03-29 16:54:36 +00006478 {
bellard5cd43932003-03-29 16:54:36 +00006479 struct timespec ts;
6480 ret = get_errno(sched_rr_get_interval(arg1, &ts));
6481 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00006482 host_to_target_timespec(arg2, &ts);
bellard5cd43932003-03-29 16:54:36 +00006483 }
6484 }
6485 break;
bellard31e31b82003-02-18 22:55:36 +00006486 case TARGET_NR_nanosleep:
bellard1b6b0292003-03-22 17:31:38 +00006487 {
bellard1b6b0292003-03-22 17:31:38 +00006488 struct timespec req, rem;
pbrook53a59602006-03-25 19:31:22 +00006489 target_to_host_timespec(&req, arg1);
bellard1b6b0292003-03-22 17:31:38 +00006490 ret = get_errno(nanosleep(&req, &rem));
pbrook53a59602006-03-25 19:31:22 +00006491 if (is_error(ret) && arg2) {
6492 host_to_target_timespec(arg2, &rem);
bellard1b6b0292003-03-22 17:31:38 +00006493 }
6494 }
6495 break;
thse5febef2007-04-01 18:31:35 +00006496#ifdef TARGET_NR_query_module
bellard31e31b82003-02-18 22:55:36 +00006497 case TARGET_NR_query_module:
bellard5cd43932003-03-29 16:54:36 +00006498 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00006499#endif
6500#ifdef TARGET_NR_nfsservctl
bellard31e31b82003-02-18 22:55:36 +00006501 case TARGET_NR_nfsservctl:
bellard5cd43932003-03-29 16:54:36 +00006502 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00006503#endif
bellard31e31b82003-02-18 22:55:36 +00006504 case TARGET_NR_prctl:
thse5574482007-02-11 20:03:13 +00006505 switch (arg1)
6506 {
6507 case PR_GET_PDEATHSIG:
6508 {
6509 int deathsig;
6510 ret = get_errno(prctl(arg1, &deathsig, arg3, arg4, arg5));
bellard2f619692007-11-16 10:46:05 +00006511 if (!is_error(ret) && arg2
6512 && put_user_ual(deathsig, arg2))
6513 goto efault;
thse5574482007-02-11 20:03:13 +00006514 }
6515 break;
6516 default:
6517 ret = get_errno(prctl(arg1, arg2, arg3, arg4, arg5));
6518 break;
6519 }
ths39b9aae2007-02-11 18:36:44 +00006520 break;
bellardd2fd1af2007-11-14 18:08:56 +00006521#ifdef TARGET_NR_arch_prctl
6522 case TARGET_NR_arch_prctl:
6523#if defined(TARGET_I386) && !defined(TARGET_ABI32)
6524 ret = do_arch_prctl(cpu_env, arg1, arg2);
6525 break;
6526#else
6527 goto unimplemented;
6528#endif
6529#endif
bellard67867302003-11-23 17:05:30 +00006530#ifdef TARGET_NR_pread
bellard31e31b82003-02-18 22:55:36 +00006531 case TARGET_NR_pread:
balroga4ae00b2008-09-20 03:14:14 +00006532#ifdef TARGET_ARM
6533 if (((CPUARMState *)cpu_env)->eabi)
6534 arg4 = arg5;
6535#endif
bellard579a97f2007-11-11 14:26:47 +00006536 if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
6537 goto efault;
pbrook53a59602006-03-25 19:31:22 +00006538 ret = get_errno(pread(arg1, p, arg3, arg4));
6539 unlock_user(p, arg2, ret);
bellard206f0fa2003-05-14 19:01:56 +00006540 break;
bellard31e31b82003-02-18 22:55:36 +00006541 case TARGET_NR_pwrite:
balroga4ae00b2008-09-20 03:14:14 +00006542#ifdef TARGET_ARM
6543 if (((CPUARMState *)cpu_env)->eabi)
6544 arg4 = arg5;
6545#endif
bellard579a97f2007-11-11 14:26:47 +00006546 if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
6547 goto efault;
pbrook53a59602006-03-25 19:31:22 +00006548 ret = get_errno(pwrite(arg1, p, arg3, arg4));
6549 unlock_user(p, arg2, 0);
bellard206f0fa2003-05-14 19:01:56 +00006550 break;
bellard67867302003-11-23 17:05:30 +00006551#endif
aurel32f2c7ba12008-03-28 22:32:06 +00006552#ifdef TARGET_NR_pread64
6553 case TARGET_NR_pread64:
6554 if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
6555 goto efault;
6556 ret = get_errno(pread64(arg1, p, arg3, target_offset64(arg4, arg5)));
6557 unlock_user(p, arg2, ret);
6558 break;
6559 case TARGET_NR_pwrite64:
6560 if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
6561 goto efault;
6562 ret = get_errno(pwrite64(arg1, p, arg3, target_offset64(arg4, arg5)));
6563 unlock_user(p, arg2, 0);
6564 break;
6565#endif
bellard31e31b82003-02-18 22:55:36 +00006566 case TARGET_NR_getcwd:
bellard579a97f2007-11-11 14:26:47 +00006567 if (!(p = lock_user(VERIFY_WRITE, arg1, arg2, 0)))
6568 goto efault;
pbrook53a59602006-03-25 19:31:22 +00006569 ret = get_errno(sys_getcwd1(p, arg2));
6570 unlock_user(p, arg1, ret);
bellard31e31b82003-02-18 22:55:36 +00006571 break;
6572 case TARGET_NR_capget:
bellard5cd43932003-03-29 16:54:36 +00006573 goto unimplemented;
bellard31e31b82003-02-18 22:55:36 +00006574 case TARGET_NR_capset:
bellard5cd43932003-03-29 16:54:36 +00006575 goto unimplemented;
bellard31e31b82003-02-18 22:55:36 +00006576 case TARGET_NR_sigaltstack:
ths198a74d2007-09-27 16:44:32 +00006577#if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_MIPS) || \
Laurent Vivierc761c152009-08-03 16:12:19 +02006578 defined(TARGET_SPARC) || defined(TARGET_PPC) || defined(TARGET_ALPHA) || \
6579 defined(TARGET_M68K)
bellard579a97f2007-11-11 14:26:47 +00006580 ret = do_sigaltstack(arg1, arg2, get_sp_from_cpustate((CPUState *)cpu_env));
thsa04e1342007-09-27 13:57:58 +00006581 break;
6582#else
bellard5cd43932003-03-29 16:54:36 +00006583 goto unimplemented;
thsa04e1342007-09-27 13:57:58 +00006584#endif
bellard31e31b82003-02-18 22:55:36 +00006585 case TARGET_NR_sendfile:
bellard5cd43932003-03-29 16:54:36 +00006586 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00006587#ifdef TARGET_NR_getpmsg
bellard31e31b82003-02-18 22:55:36 +00006588 case TARGET_NR_getpmsg:
bellard5cd43932003-03-29 16:54:36 +00006589 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00006590#endif
6591#ifdef TARGET_NR_putpmsg
bellard31e31b82003-02-18 22:55:36 +00006592 case TARGET_NR_putpmsg:
bellard5cd43932003-03-29 16:54:36 +00006593 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00006594#endif
bellard048f6b42005-11-26 18:47:20 +00006595#ifdef TARGET_NR_vfork
bellard31e31b82003-02-18 22:55:36 +00006596 case TARGET_NR_vfork:
pbrookd865bab2008-06-07 22:12:17 +00006597 ret = get_errno(do_fork(cpu_env, CLONE_VFORK | CLONE_VM | SIGCHLD,
6598 0, 0, 0, 0));
bellard31e31b82003-02-18 22:55:36 +00006599 break;
bellard048f6b42005-11-26 18:47:20 +00006600#endif
bellardebc05482003-09-30 21:08:41 +00006601#ifdef TARGET_NR_ugetrlimit
bellard31e31b82003-02-18 22:55:36 +00006602 case TARGET_NR_ugetrlimit:
bellard728584b2003-04-29 20:43:36 +00006603 {
6604 struct rlimit rlim;
6605 ret = get_errno(getrlimit(arg1, &rlim));
6606 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00006607 struct target_rlimit *target_rlim;
bellard579a97f2007-11-11 14:26:47 +00006608 if (!lock_user_struct(VERIFY_WRITE, target_rlim, arg2, 0))
6609 goto efault;
takasi-y@ops.dti.ne.jp81bbe902010-04-12 04:07:35 +09006610 target_rlim->rlim_cur = host_to_target_rlim(rlim.rlim_cur);
6611 target_rlim->rlim_max = host_to_target_rlim(rlim.rlim_max);
pbrook53a59602006-03-25 19:31:22 +00006612 unlock_user_struct(target_rlim, arg2, 1);
bellard728584b2003-04-29 20:43:36 +00006613 }
6614 break;
6615 }
bellardebc05482003-09-30 21:08:41 +00006616#endif
bellarda315a142005-01-30 22:59:18 +00006617#ifdef TARGET_NR_truncate64
bellard31e31b82003-02-18 22:55:36 +00006618 case TARGET_NR_truncate64:
bellard579a97f2007-11-11 14:26:47 +00006619 if (!(p = lock_user_string(arg1)))
6620 goto efault;
pbrook53a59602006-03-25 19:31:22 +00006621 ret = target_truncate64(cpu_env, p, arg2, arg3, arg4);
6622 unlock_user(p, arg1, 0);
bellard667f38b2005-07-23 14:46:27 +00006623 break;
bellarda315a142005-01-30 22:59:18 +00006624#endif
6625#ifdef TARGET_NR_ftruncate64
bellard31e31b82003-02-18 22:55:36 +00006626 case TARGET_NR_ftruncate64:
pbrookce4defa2006-02-09 16:49:55 +00006627 ret = target_ftruncate64(cpu_env, arg1, arg2, arg3, arg4);
bellard667f38b2005-07-23 14:46:27 +00006628 break;
bellarda315a142005-01-30 22:59:18 +00006629#endif
6630#ifdef TARGET_NR_stat64
bellard31e31b82003-02-18 22:55:36 +00006631 case TARGET_NR_stat64:
bellard579a97f2007-11-11 14:26:47 +00006632 if (!(p = lock_user_string(arg1)))
6633 goto efault;
pbrook53a59602006-03-25 19:31:22 +00006634 ret = get_errno(stat(path(p), &st));
6635 unlock_user(p, arg1, 0);
balrog6a24a772008-09-20 02:23:36 +00006636 if (!is_error(ret))
6637 ret = host_to_target_stat64(cpu_env, arg2, &st);
6638 break;
bellarda315a142005-01-30 22:59:18 +00006639#endif
6640#ifdef TARGET_NR_lstat64
bellard31e31b82003-02-18 22:55:36 +00006641 case TARGET_NR_lstat64:
bellard579a97f2007-11-11 14:26:47 +00006642 if (!(p = lock_user_string(arg1)))
6643 goto efault;
pbrook53a59602006-03-25 19:31:22 +00006644 ret = get_errno(lstat(path(p), &st));
6645 unlock_user(p, arg1, 0);
balrog6a24a772008-09-20 02:23:36 +00006646 if (!is_error(ret))
6647 ret = host_to_target_stat64(cpu_env, arg2, &st);
6648 break;
bellarda315a142005-01-30 22:59:18 +00006649#endif
6650#ifdef TARGET_NR_fstat64
bellard31e31b82003-02-18 22:55:36 +00006651 case TARGET_NR_fstat64:
balrog6a24a772008-09-20 02:23:36 +00006652 ret = get_errno(fstat(arg1, &st));
6653 if (!is_error(ret))
6654 ret = host_to_target_stat64(cpu_env, arg2, &st);
6655 break;
bellardec86b0f2003-04-11 00:15:04 +00006656#endif
aurel329d33b762009-04-08 23:07:05 +00006657#if (defined(TARGET_NR_fstatat64) || defined(TARGET_NR_newfstatat)) && \
6658 (defined(__NR_fstatat64) || defined(__NR_newfstatat))
6659#ifdef TARGET_NR_fstatat64
balrog6a24a772008-09-20 02:23:36 +00006660 case TARGET_NR_fstatat64:
aurel329d33b762009-04-08 23:07:05 +00006661#endif
6662#ifdef TARGET_NR_newfstatat
6663 case TARGET_NR_newfstatat:
6664#endif
balrog6a24a772008-09-20 02:23:36 +00006665 if (!(p = lock_user_string(arg2)))
6666 goto efault;
aurel329d33b762009-04-08 23:07:05 +00006667#ifdef __NR_fstatat64
balrog6a24a772008-09-20 02:23:36 +00006668 ret = get_errno(sys_fstatat64(arg1, path(p), &st, arg4));
aurel329d33b762009-04-08 23:07:05 +00006669#else
6670 ret = get_errno(sys_newfstatat(arg1, path(p), &st, arg4));
6671#endif
balrog6a24a772008-09-20 02:23:36 +00006672 if (!is_error(ret))
6673 ret = host_to_target_stat64(cpu_env, arg3, &st);
bellard60cd49d2003-03-16 22:53:56 +00006674 break;
bellarda315a142005-01-30 22:59:18 +00006675#endif
bellard67867302003-11-23 17:05:30 +00006676#ifdef USE_UID16
6677 case TARGET_NR_lchown:
bellard579a97f2007-11-11 14:26:47 +00006678 if (!(p = lock_user_string(arg1)))
6679 goto efault;
pbrook53a59602006-03-25 19:31:22 +00006680 ret = get_errno(lchown(p, low2highuid(arg2), low2highgid(arg3)));
6681 unlock_user(p, arg1, 0);
bellard67867302003-11-23 17:05:30 +00006682 break;
6683 case TARGET_NR_getuid:
6684 ret = get_errno(high2lowuid(getuid()));
6685 break;
6686 case TARGET_NR_getgid:
6687 ret = get_errno(high2lowgid(getgid()));
6688 break;
6689 case TARGET_NR_geteuid:
6690 ret = get_errno(high2lowuid(geteuid()));
6691 break;
6692 case TARGET_NR_getegid:
6693 ret = get_errno(high2lowgid(getegid()));
6694 break;
6695 case TARGET_NR_setreuid:
6696 ret = get_errno(setreuid(low2highuid(arg1), low2highuid(arg2)));
6697 break;
6698 case TARGET_NR_setregid:
6699 ret = get_errno(setregid(low2highgid(arg1), low2highgid(arg2)));
6700 break;
6701 case TARGET_NR_getgroups:
6702 {
6703 int gidsetsize = arg1;
pbrook53a59602006-03-25 19:31:22 +00006704 uint16_t *target_grouplist;
bellard67867302003-11-23 17:05:30 +00006705 gid_t *grouplist;
6706 int i;
6707
6708 grouplist = alloca(gidsetsize * sizeof(gid_t));
6709 ret = get_errno(getgroups(gidsetsize, grouplist));
balrogcb3bc232008-09-20 02:08:13 +00006710 if (gidsetsize == 0)
6711 break;
bellard67867302003-11-23 17:05:30 +00006712 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00006713 target_grouplist = lock_user(VERIFY_WRITE, arg2, gidsetsize * 2, 0);
6714 if (!target_grouplist)
6715 goto efault;
balroga2155fc2008-09-20 02:12:08 +00006716 for(i = 0;i < ret; i++)
bellard67867302003-11-23 17:05:30 +00006717 target_grouplist[i] = tswap16(grouplist[i]);
pbrook53a59602006-03-25 19:31:22 +00006718 unlock_user(target_grouplist, arg2, gidsetsize * 2);
bellard67867302003-11-23 17:05:30 +00006719 }
6720 }
6721 break;
6722 case TARGET_NR_setgroups:
6723 {
6724 int gidsetsize = arg1;
pbrook53a59602006-03-25 19:31:22 +00006725 uint16_t *target_grouplist;
bellard67867302003-11-23 17:05:30 +00006726 gid_t *grouplist;
6727 int i;
6728
6729 grouplist = alloca(gidsetsize * sizeof(gid_t));
bellard579a97f2007-11-11 14:26:47 +00006730 target_grouplist = lock_user(VERIFY_READ, arg2, gidsetsize * 2, 1);
6731 if (!target_grouplist) {
6732 ret = -TARGET_EFAULT;
6733 goto fail;
6734 }
bellard67867302003-11-23 17:05:30 +00006735 for(i = 0;i < gidsetsize; i++)
6736 grouplist[i] = tswap16(target_grouplist[i]);
pbrook53a59602006-03-25 19:31:22 +00006737 unlock_user(target_grouplist, arg2, 0);
bellard67867302003-11-23 17:05:30 +00006738 ret = get_errno(setgroups(gidsetsize, grouplist));
6739 }
6740 break;
6741 case TARGET_NR_fchown:
6742 ret = get_errno(fchown(arg1, low2highuid(arg2), low2highgid(arg3)));
6743 break;
thsccfa72b2007-09-24 09:23:34 +00006744#if defined(TARGET_NR_fchownat) && defined(__NR_fchownat)
6745 case TARGET_NR_fchownat:
bellard579a97f2007-11-11 14:26:47 +00006746 if (!(p = lock_user_string(arg2)))
6747 goto efault;
6748 ret = get_errno(sys_fchownat(arg1, p, low2highuid(arg3), low2highgid(arg4), arg5));
6749 unlock_user(p, arg2, 0);
thsccfa72b2007-09-24 09:23:34 +00006750 break;
6751#endif
bellard67867302003-11-23 17:05:30 +00006752#ifdef TARGET_NR_setresuid
6753 case TARGET_NR_setresuid:
ths5fafdf22007-09-16 21:08:06 +00006754 ret = get_errno(setresuid(low2highuid(arg1),
6755 low2highuid(arg2),
bellard67867302003-11-23 17:05:30 +00006756 low2highuid(arg3)));
6757 break;
6758#endif
6759#ifdef TARGET_NR_getresuid
6760 case TARGET_NR_getresuid:
6761 {
pbrook53a59602006-03-25 19:31:22 +00006762 uid_t ruid, euid, suid;
bellard67867302003-11-23 17:05:30 +00006763 ret = get_errno(getresuid(&ruid, &euid, &suid));
6764 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +00006765 if (put_user_u16(high2lowuid(ruid), arg1)
6766 || put_user_u16(high2lowuid(euid), arg2)
6767 || put_user_u16(high2lowuid(suid), arg3))
6768 goto efault;
bellard67867302003-11-23 17:05:30 +00006769 }
6770 }
6771 break;
6772#endif
6773#ifdef TARGET_NR_getresgid
6774 case TARGET_NR_setresgid:
ths5fafdf22007-09-16 21:08:06 +00006775 ret = get_errno(setresgid(low2highgid(arg1),
6776 low2highgid(arg2),
bellard67867302003-11-23 17:05:30 +00006777 low2highgid(arg3)));
6778 break;
6779#endif
6780#ifdef TARGET_NR_getresgid
6781 case TARGET_NR_getresgid:
6782 {
pbrook53a59602006-03-25 19:31:22 +00006783 gid_t rgid, egid, sgid;
bellard67867302003-11-23 17:05:30 +00006784 ret = get_errno(getresgid(&rgid, &egid, &sgid));
6785 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +00006786 if (put_user_u16(high2lowgid(rgid), arg1)
6787 || put_user_u16(high2lowgid(egid), arg2)
6788 || put_user_u16(high2lowgid(sgid), arg3))
6789 goto efault;
bellard67867302003-11-23 17:05:30 +00006790 }
6791 }
6792 break;
6793#endif
6794 case TARGET_NR_chown:
bellard579a97f2007-11-11 14:26:47 +00006795 if (!(p = lock_user_string(arg1)))
6796 goto efault;
pbrook53a59602006-03-25 19:31:22 +00006797 ret = get_errno(chown(p, low2highuid(arg2), low2highgid(arg3)));
6798 unlock_user(p, arg1, 0);
bellard67867302003-11-23 17:05:30 +00006799 break;
6800 case TARGET_NR_setuid:
6801 ret = get_errno(setuid(low2highuid(arg1)));
6802 break;
6803 case TARGET_NR_setgid:
6804 ret = get_errno(setgid(low2highgid(arg1)));
6805 break;
6806 case TARGET_NR_setfsuid:
6807 ret = get_errno(setfsuid(arg1));
6808 break;
6809 case TARGET_NR_setfsgid:
6810 ret = get_errno(setfsgid(arg1));
6811 break;
6812#endif /* USE_UID16 */
6813
bellarda315a142005-01-30 22:59:18 +00006814#ifdef TARGET_NR_lchown32
bellard31e31b82003-02-18 22:55:36 +00006815 case TARGET_NR_lchown32:
bellard579a97f2007-11-11 14:26:47 +00006816 if (!(p = lock_user_string(arg1)))
6817 goto efault;
pbrook53a59602006-03-25 19:31:22 +00006818 ret = get_errno(lchown(p, arg2, arg3));
6819 unlock_user(p, arg1, 0);
bellardb03c60f2003-03-23 17:19:56 +00006820 break;
bellarda315a142005-01-30 22:59:18 +00006821#endif
6822#ifdef TARGET_NR_getuid32
bellard31e31b82003-02-18 22:55:36 +00006823 case TARGET_NR_getuid32:
bellardb03c60f2003-03-23 17:19:56 +00006824 ret = get_errno(getuid());
6825 break;
bellarda315a142005-01-30 22:59:18 +00006826#endif
aurel3264b4d282008-11-14 17:20:15 +00006827
6828#if defined(TARGET_NR_getxuid) && defined(TARGET_ALPHA)
6829 /* Alpha specific */
6830 case TARGET_NR_getxuid:
Richard Hendersonba0e2762009-12-09 15:56:29 -08006831 {
6832 uid_t euid;
6833 euid=geteuid();
6834 ((CPUAlphaState *)cpu_env)->ir[IR_A4]=euid;
6835 }
aurel3264b4d282008-11-14 17:20:15 +00006836 ret = get_errno(getuid());
6837 break;
6838#endif
6839#if defined(TARGET_NR_getxgid) && defined(TARGET_ALPHA)
6840 /* Alpha specific */
6841 case TARGET_NR_getxgid:
Richard Hendersonba0e2762009-12-09 15:56:29 -08006842 {
6843 uid_t egid;
6844 egid=getegid();
6845 ((CPUAlphaState *)cpu_env)->ir[IR_A4]=egid;
6846 }
aurel3264b4d282008-11-14 17:20:15 +00006847 ret = get_errno(getgid());
6848 break;
6849#endif
Richard Hendersonba0e2762009-12-09 15:56:29 -08006850#if defined(TARGET_NR_osf_getsysinfo) && defined(TARGET_ALPHA)
6851 /* Alpha specific */
6852 case TARGET_NR_osf_getsysinfo:
6853 ret = -TARGET_EOPNOTSUPP;
6854 switch (arg1) {
6855 case TARGET_GSI_IEEE_FP_CONTROL:
6856 {
6857 uint64_t swcr, fpcr = cpu_alpha_load_fpcr (cpu_env);
6858
6859 /* Copied from linux ieee_fpcr_to_swcr. */
6860 swcr = (fpcr >> 35) & SWCR_STATUS_MASK;
6861 swcr |= (fpcr >> 36) & SWCR_MAP_DMZ;
6862 swcr |= (~fpcr >> 48) & (SWCR_TRAP_ENABLE_INV
6863 | SWCR_TRAP_ENABLE_DZE
6864 | SWCR_TRAP_ENABLE_OVF);
6865 swcr |= (~fpcr >> 57) & (SWCR_TRAP_ENABLE_UNF
6866 | SWCR_TRAP_ENABLE_INE);
6867 swcr |= (fpcr >> 47) & SWCR_MAP_UMZ;
6868 swcr |= (~fpcr >> 41) & SWCR_TRAP_ENABLE_DNO;
6869
6870 if (put_user_u64 (swcr, arg2))
6871 goto efault;
6872 ret = 0;
6873 }
6874 break;
6875
6876 /* case GSI_IEEE_STATE_AT_SIGNAL:
6877 -- Not implemented in linux kernel.
6878 case GSI_UACPROC:
6879 -- Retrieves current unaligned access state; not much used.
6880 case GSI_PROC_TYPE:
6881 -- Retrieves implver information; surely not used.
6882 case GSI_GET_HWRPB:
6883 -- Grabs a copy of the HWRPB; surely not used.
6884 */
6885 }
6886 break;
6887#endif
6888#if defined(TARGET_NR_osf_setsysinfo) && defined(TARGET_ALPHA)
6889 /* Alpha specific */
6890 case TARGET_NR_osf_setsysinfo:
6891 ret = -TARGET_EOPNOTSUPP;
6892 switch (arg1) {
6893 case TARGET_SSI_IEEE_FP_CONTROL:
6894 case TARGET_SSI_IEEE_RAISE_EXCEPTION:
6895 {
6896 uint64_t swcr, fpcr, orig_fpcr;
6897
6898 if (get_user_u64 (swcr, arg2))
6899 goto efault;
6900 orig_fpcr = cpu_alpha_load_fpcr (cpu_env);
6901 fpcr = orig_fpcr & FPCR_DYN_MASK;
6902
6903 /* Copied from linux ieee_swcr_to_fpcr. */
6904 fpcr |= (swcr & SWCR_STATUS_MASK) << 35;
6905 fpcr |= (swcr & SWCR_MAP_DMZ) << 36;
6906 fpcr |= (~swcr & (SWCR_TRAP_ENABLE_INV
6907 | SWCR_TRAP_ENABLE_DZE
6908 | SWCR_TRAP_ENABLE_OVF)) << 48;
6909 fpcr |= (~swcr & (SWCR_TRAP_ENABLE_UNF
6910 | SWCR_TRAP_ENABLE_INE)) << 57;
6911 fpcr |= (swcr & SWCR_MAP_UMZ ? FPCR_UNDZ | FPCR_UNFD : 0);
6912 fpcr |= (~swcr & SWCR_TRAP_ENABLE_DNO) << 41;
6913
6914 cpu_alpha_store_fpcr (cpu_env, fpcr);
6915 ret = 0;
6916
6917 if (arg1 == TARGET_SSI_IEEE_RAISE_EXCEPTION) {
6918 /* Old exceptions are not signaled. */
6919 fpcr &= ~(orig_fpcr & FPCR_STATUS_MASK);
6920
6921 /* If any exceptions set by this call, and are unmasked,
6922 send a signal. */
6923 /* ??? FIXME */
6924 }
6925 }
6926 break;
6927
6928 /* case SSI_NVPAIRS:
6929 -- Used with SSIN_UACPROC to enable unaligned accesses.
6930 case SSI_IEEE_STATE_AT_SIGNAL:
6931 case SSI_IEEE_IGNORE_STATE_AT_SIGNAL:
6932 -- Not implemented in linux kernel
6933 */
6934 }
6935 break;
6936#endif
6937#ifdef TARGET_NR_osf_sigprocmask
6938 /* Alpha specific. */
6939 case TARGET_NR_osf_sigprocmask:
6940 {
6941 abi_ulong mask;
6942 int how = arg1;
6943 sigset_t set, oldset;
6944
6945 switch(arg1) {
6946 case TARGET_SIG_BLOCK:
6947 how = SIG_BLOCK;
6948 break;
6949 case TARGET_SIG_UNBLOCK:
6950 how = SIG_UNBLOCK;
6951 break;
6952 case TARGET_SIG_SETMASK:
6953 how = SIG_SETMASK;
6954 break;
6955 default:
6956 ret = -TARGET_EINVAL;
6957 goto fail;
6958 }
6959 mask = arg2;
6960 target_to_host_old_sigset(&set, &mask);
6961 sigprocmask(arg1, &set, &oldset);
6962 host_to_target_old_sigset(&mask, &oldset);
6963 ret = mask;
6964 }
6965 break;
6966#endif
aurel3264b4d282008-11-14 17:20:15 +00006967
bellarda315a142005-01-30 22:59:18 +00006968#ifdef TARGET_NR_getgid32
bellard31e31b82003-02-18 22:55:36 +00006969 case TARGET_NR_getgid32:
bellardb03c60f2003-03-23 17:19:56 +00006970 ret = get_errno(getgid());
6971 break;
bellarda315a142005-01-30 22:59:18 +00006972#endif
6973#ifdef TARGET_NR_geteuid32
bellard31e31b82003-02-18 22:55:36 +00006974 case TARGET_NR_geteuid32:
bellardb03c60f2003-03-23 17:19:56 +00006975 ret = get_errno(geteuid());
6976 break;
bellarda315a142005-01-30 22:59:18 +00006977#endif
6978#ifdef TARGET_NR_getegid32
bellard31e31b82003-02-18 22:55:36 +00006979 case TARGET_NR_getegid32:
bellardb03c60f2003-03-23 17:19:56 +00006980 ret = get_errno(getegid());
6981 break;
bellarda315a142005-01-30 22:59:18 +00006982#endif
6983#ifdef TARGET_NR_setreuid32
bellard31e31b82003-02-18 22:55:36 +00006984 case TARGET_NR_setreuid32:
bellardb03c60f2003-03-23 17:19:56 +00006985 ret = get_errno(setreuid(arg1, arg2));
6986 break;
bellarda315a142005-01-30 22:59:18 +00006987#endif
6988#ifdef TARGET_NR_setregid32
bellard31e31b82003-02-18 22:55:36 +00006989 case TARGET_NR_setregid32:
bellardb03c60f2003-03-23 17:19:56 +00006990 ret = get_errno(setregid(arg1, arg2));
6991 break;
bellarda315a142005-01-30 22:59:18 +00006992#endif
6993#ifdef TARGET_NR_getgroups32
bellard31e31b82003-02-18 22:55:36 +00006994 case TARGET_NR_getgroups32:
bellard99c475a2005-01-31 20:45:13 +00006995 {
6996 int gidsetsize = arg1;
pbrook53a59602006-03-25 19:31:22 +00006997 uint32_t *target_grouplist;
bellard99c475a2005-01-31 20:45:13 +00006998 gid_t *grouplist;
6999 int i;
7000
7001 grouplist = alloca(gidsetsize * sizeof(gid_t));
7002 ret = get_errno(getgroups(gidsetsize, grouplist));
balrogcb3bc232008-09-20 02:08:13 +00007003 if (gidsetsize == 0)
7004 break;
bellard99c475a2005-01-31 20:45:13 +00007005 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00007006 target_grouplist = lock_user(VERIFY_WRITE, arg2, gidsetsize * 4, 0);
7007 if (!target_grouplist) {
7008 ret = -TARGET_EFAULT;
7009 goto fail;
7010 }
balroga2155fc2008-09-20 02:12:08 +00007011 for(i = 0;i < ret; i++)
pbrook53a59602006-03-25 19:31:22 +00007012 target_grouplist[i] = tswap32(grouplist[i]);
7013 unlock_user(target_grouplist, arg2, gidsetsize * 4);
bellard99c475a2005-01-31 20:45:13 +00007014 }
7015 }
7016 break;
bellarda315a142005-01-30 22:59:18 +00007017#endif
7018#ifdef TARGET_NR_setgroups32
bellard31e31b82003-02-18 22:55:36 +00007019 case TARGET_NR_setgroups32:
bellard99c475a2005-01-31 20:45:13 +00007020 {
7021 int gidsetsize = arg1;
pbrook53a59602006-03-25 19:31:22 +00007022 uint32_t *target_grouplist;
bellard99c475a2005-01-31 20:45:13 +00007023 gid_t *grouplist;
7024 int i;
ths3b46e622007-09-17 08:09:54 +00007025
bellard99c475a2005-01-31 20:45:13 +00007026 grouplist = alloca(gidsetsize * sizeof(gid_t));
bellard579a97f2007-11-11 14:26:47 +00007027 target_grouplist = lock_user(VERIFY_READ, arg2, gidsetsize * 4, 1);
7028 if (!target_grouplist) {
7029 ret = -TARGET_EFAULT;
7030 goto fail;
7031 }
bellard99c475a2005-01-31 20:45:13 +00007032 for(i = 0;i < gidsetsize; i++)
pbrook53a59602006-03-25 19:31:22 +00007033 grouplist[i] = tswap32(target_grouplist[i]);
7034 unlock_user(target_grouplist, arg2, 0);
bellard99c475a2005-01-31 20:45:13 +00007035 ret = get_errno(setgroups(gidsetsize, grouplist));
7036 }
7037 break;
bellarda315a142005-01-30 22:59:18 +00007038#endif
7039#ifdef TARGET_NR_fchown32
bellard31e31b82003-02-18 22:55:36 +00007040 case TARGET_NR_fchown32:
bellardb03c60f2003-03-23 17:19:56 +00007041 ret = get_errno(fchown(arg1, arg2, arg3));
7042 break;
bellarda315a142005-01-30 22:59:18 +00007043#endif
7044#ifdef TARGET_NR_setresuid32
bellard31e31b82003-02-18 22:55:36 +00007045 case TARGET_NR_setresuid32:
bellardb03c60f2003-03-23 17:19:56 +00007046 ret = get_errno(setresuid(arg1, arg2, arg3));
7047 break;
bellarda315a142005-01-30 22:59:18 +00007048#endif
7049#ifdef TARGET_NR_getresuid32
bellard31e31b82003-02-18 22:55:36 +00007050 case TARGET_NR_getresuid32:
bellardb03c60f2003-03-23 17:19:56 +00007051 {
pbrook53a59602006-03-25 19:31:22 +00007052 uid_t ruid, euid, suid;
bellardb03c60f2003-03-23 17:19:56 +00007053 ret = get_errno(getresuid(&ruid, &euid, &suid));
7054 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +00007055 if (put_user_u32(ruid, arg1)
7056 || put_user_u32(euid, arg2)
7057 || put_user_u32(suid, arg3))
7058 goto efault;
bellardb03c60f2003-03-23 17:19:56 +00007059 }
7060 }
7061 break;
bellarda315a142005-01-30 22:59:18 +00007062#endif
7063#ifdef TARGET_NR_setresgid32
bellard31e31b82003-02-18 22:55:36 +00007064 case TARGET_NR_setresgid32:
bellardb03c60f2003-03-23 17:19:56 +00007065 ret = get_errno(setresgid(arg1, arg2, arg3));
7066 break;
bellarda315a142005-01-30 22:59:18 +00007067#endif
7068#ifdef TARGET_NR_getresgid32
bellard31e31b82003-02-18 22:55:36 +00007069 case TARGET_NR_getresgid32:
bellardb03c60f2003-03-23 17:19:56 +00007070 {
pbrook53a59602006-03-25 19:31:22 +00007071 gid_t rgid, egid, sgid;
bellardb03c60f2003-03-23 17:19:56 +00007072 ret = get_errno(getresgid(&rgid, &egid, &sgid));
7073 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +00007074 if (put_user_u32(rgid, arg1)
7075 || put_user_u32(egid, arg2)
7076 || put_user_u32(sgid, arg3))
7077 goto efault;
bellardb03c60f2003-03-23 17:19:56 +00007078 }
7079 }
7080 break;
bellarda315a142005-01-30 22:59:18 +00007081#endif
7082#ifdef TARGET_NR_chown32
bellard31e31b82003-02-18 22:55:36 +00007083 case TARGET_NR_chown32:
bellard579a97f2007-11-11 14:26:47 +00007084 if (!(p = lock_user_string(arg1)))
7085 goto efault;
pbrook53a59602006-03-25 19:31:22 +00007086 ret = get_errno(chown(p, arg2, arg3));
7087 unlock_user(p, arg1, 0);
bellardb03c60f2003-03-23 17:19:56 +00007088 break;
bellarda315a142005-01-30 22:59:18 +00007089#endif
7090#ifdef TARGET_NR_setuid32
bellard31e31b82003-02-18 22:55:36 +00007091 case TARGET_NR_setuid32:
bellardb03c60f2003-03-23 17:19:56 +00007092 ret = get_errno(setuid(arg1));
7093 break;
bellarda315a142005-01-30 22:59:18 +00007094#endif
7095#ifdef TARGET_NR_setgid32
bellard31e31b82003-02-18 22:55:36 +00007096 case TARGET_NR_setgid32:
bellardb03c60f2003-03-23 17:19:56 +00007097 ret = get_errno(setgid(arg1));
7098 break;
bellarda315a142005-01-30 22:59:18 +00007099#endif
7100#ifdef TARGET_NR_setfsuid32
bellard31e31b82003-02-18 22:55:36 +00007101 case TARGET_NR_setfsuid32:
bellardb03c60f2003-03-23 17:19:56 +00007102 ret = get_errno(setfsuid(arg1));
7103 break;
bellarda315a142005-01-30 22:59:18 +00007104#endif
7105#ifdef TARGET_NR_setfsgid32
bellard31e31b82003-02-18 22:55:36 +00007106 case TARGET_NR_setfsgid32:
bellardb03c60f2003-03-23 17:19:56 +00007107 ret = get_errno(setfsgid(arg1));
7108 break;
bellarda315a142005-01-30 22:59:18 +00007109#endif
bellard67867302003-11-23 17:05:30 +00007110
bellard31e31b82003-02-18 22:55:36 +00007111 case TARGET_NR_pivot_root:
bellardb03c60f2003-03-23 17:19:56 +00007112 goto unimplemented;
bellardffa65c32004-01-04 23:57:22 +00007113#ifdef TARGET_NR_mincore
bellard31e31b82003-02-18 22:55:36 +00007114 case TARGET_NR_mincore:
aurel3204bb9ac2008-10-01 21:46:41 +00007115 {
7116 void *a;
7117 ret = -TARGET_EFAULT;
7118 if (!(a = lock_user(VERIFY_READ, arg1,arg2, 0)))
7119 goto efault;
7120 if (!(p = lock_user_string(arg3)))
7121 goto mincore_fail;
7122 ret = get_errno(mincore(a, arg2, p));
7123 unlock_user(p, arg3, ret);
7124 mincore_fail:
7125 unlock_user(a, arg1, 0);
7126 }
7127 break;
bellardffa65c32004-01-04 23:57:22 +00007128#endif
aurel32408321b2008-10-01 21:46:32 +00007129#ifdef TARGET_NR_arm_fadvise64_64
7130 case TARGET_NR_arm_fadvise64_64:
7131 {
7132 /*
7133 * arm_fadvise64_64 looks like fadvise64_64 but
7134 * with different argument order
7135 */
7136 abi_long temp;
7137 temp = arg3;
7138 arg3 = arg4;
7139 arg4 = temp;
7140 }
7141#endif
Ulrich Hechte72d2cc2009-07-24 19:10:31 +02007142#if defined(TARGET_NR_fadvise64_64) || defined(TARGET_NR_arm_fadvise64_64) || defined(TARGET_NR_fadvise64)
aurel32408321b2008-10-01 21:46:32 +00007143#ifdef TARGET_NR_fadvise64_64
7144 case TARGET_NR_fadvise64_64:
7145#endif
Ulrich Hechte72d2cc2009-07-24 19:10:31 +02007146#ifdef TARGET_NR_fadvise64
7147 case TARGET_NR_fadvise64:
7148#endif
7149#ifdef TARGET_S390X
7150 switch (arg4) {
7151 case 4: arg4 = POSIX_FADV_NOREUSE + 1; break; /* make sure it's an invalid value */
7152 case 5: arg4 = POSIX_FADV_NOREUSE + 2; break; /* ditto */
7153 case 6: arg4 = POSIX_FADV_DONTNEED; break;
7154 case 7: arg4 = POSIX_FADV_NOREUSE; break;
7155 default: break;
7156 }
7157#endif
7158 ret = -posix_fadvise(arg1, arg2, arg3, arg4);
aurel32408321b2008-10-01 21:46:32 +00007159 break;
7160#endif
bellardffa65c32004-01-04 23:57:22 +00007161#ifdef TARGET_NR_madvise
bellard31e31b82003-02-18 22:55:36 +00007162 case TARGET_NR_madvise:
pbrook24836682006-04-16 14:14:53 +00007163 /* A straight passthrough may not be safe because qemu sometimes
7164 turns private flie-backed mappings into anonymous mappings.
7165 This will break MADV_DONTNEED.
7166 This is a hint, so ignoring and returning success is ok. */
7167 ret = get_errno(0);
7168 break;
bellardffa65c32004-01-04 23:57:22 +00007169#endif
blueswir1992f48a2007-10-14 16:27:31 +00007170#if TARGET_ABI_BITS == 32
bellard31e31b82003-02-18 22:55:36 +00007171 case TARGET_NR_fcntl64:
bellard77e46722003-04-29 20:39:06 +00007172 {
thsb1e341e2007-03-20 21:50:52 +00007173 int cmd;
bellard77e46722003-04-29 20:39:06 +00007174 struct flock64 fl;
pbrook53a59602006-03-25 19:31:22 +00007175 struct target_flock64 *target_fl;
pbrookce4defa2006-02-09 16:49:55 +00007176#ifdef TARGET_ARM
pbrook53a59602006-03-25 19:31:22 +00007177 struct target_eabi_flock64 *target_efl;
pbrookce4defa2006-02-09 16:49:55 +00007178#endif
bellard77e46722003-04-29 20:39:06 +00007179
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02007180 cmd = target_to_host_fcntl_cmd(arg2);
7181 if (cmd == -TARGET_EINVAL)
7182 return cmd;
thsb1e341e2007-03-20 21:50:52 +00007183
bellard60cd49d2003-03-16 22:53:56 +00007184 switch(arg2) {
thsb1e341e2007-03-20 21:50:52 +00007185 case TARGET_F_GETLK64:
ths58134272007-03-31 18:59:32 +00007186#ifdef TARGET_ARM
7187 if (((CPUARMState *)cpu_env)->eabi) {
bellard9ee1fa22007-11-11 15:11:19 +00007188 if (!lock_user_struct(VERIFY_READ, target_efl, arg3, 1))
7189 goto efault;
ths58134272007-03-31 18:59:32 +00007190 fl.l_type = tswap16(target_efl->l_type);
7191 fl.l_whence = tswap16(target_efl->l_whence);
7192 fl.l_start = tswap64(target_efl->l_start);
7193 fl.l_len = tswap64(target_efl->l_len);
Ulrich Hecht7e22e542009-07-24 19:10:27 +02007194 fl.l_pid = tswap32(target_efl->l_pid);
ths58134272007-03-31 18:59:32 +00007195 unlock_user_struct(target_efl, arg3, 0);
7196 } else
7197#endif
7198 {
bellard9ee1fa22007-11-11 15:11:19 +00007199 if (!lock_user_struct(VERIFY_READ, target_fl, arg3, 1))
7200 goto efault;
ths58134272007-03-31 18:59:32 +00007201 fl.l_type = tswap16(target_fl->l_type);
7202 fl.l_whence = tswap16(target_fl->l_whence);
7203 fl.l_start = tswap64(target_fl->l_start);
7204 fl.l_len = tswap64(target_fl->l_len);
Ulrich Hecht7e22e542009-07-24 19:10:27 +02007205 fl.l_pid = tswap32(target_fl->l_pid);
ths58134272007-03-31 18:59:32 +00007206 unlock_user_struct(target_fl, arg3, 0);
7207 }
thsb1e341e2007-03-20 21:50:52 +00007208 ret = get_errno(fcntl(arg1, cmd, &fl));
bellard77e46722003-04-29 20:39:06 +00007209 if (ret == 0) {
pbrookce4defa2006-02-09 16:49:55 +00007210#ifdef TARGET_ARM
7211 if (((CPUARMState *)cpu_env)->eabi) {
bellard9ee1fa22007-11-11 15:11:19 +00007212 if (!lock_user_struct(VERIFY_WRITE, target_efl, arg3, 0))
7213 goto efault;
pbrookce4defa2006-02-09 16:49:55 +00007214 target_efl->l_type = tswap16(fl.l_type);
7215 target_efl->l_whence = tswap16(fl.l_whence);
7216 target_efl->l_start = tswap64(fl.l_start);
7217 target_efl->l_len = tswap64(fl.l_len);
Ulrich Hecht7e22e542009-07-24 19:10:27 +02007218 target_efl->l_pid = tswap32(fl.l_pid);
pbrook53a59602006-03-25 19:31:22 +00007219 unlock_user_struct(target_efl, arg3, 1);
pbrookce4defa2006-02-09 16:49:55 +00007220 } else
7221#endif
7222 {
bellard9ee1fa22007-11-11 15:11:19 +00007223 if (!lock_user_struct(VERIFY_WRITE, target_fl, arg3, 0))
7224 goto efault;
pbrookce4defa2006-02-09 16:49:55 +00007225 target_fl->l_type = tswap16(fl.l_type);
7226 target_fl->l_whence = tswap16(fl.l_whence);
7227 target_fl->l_start = tswap64(fl.l_start);
7228 target_fl->l_len = tswap64(fl.l_len);
Ulrich Hecht7e22e542009-07-24 19:10:27 +02007229 target_fl->l_pid = tswap32(fl.l_pid);
pbrook53a59602006-03-25 19:31:22 +00007230 unlock_user_struct(target_fl, arg3, 1);
pbrookce4defa2006-02-09 16:49:55 +00007231 }
bellard77e46722003-04-29 20:39:06 +00007232 }
7233 break;
7234
thsb1e341e2007-03-20 21:50:52 +00007235 case TARGET_F_SETLK64:
7236 case TARGET_F_SETLKW64:
pbrookce4defa2006-02-09 16:49:55 +00007237#ifdef TARGET_ARM
7238 if (((CPUARMState *)cpu_env)->eabi) {
bellard9ee1fa22007-11-11 15:11:19 +00007239 if (!lock_user_struct(VERIFY_READ, target_efl, arg3, 1))
7240 goto efault;
pbrookce4defa2006-02-09 16:49:55 +00007241 fl.l_type = tswap16(target_efl->l_type);
7242 fl.l_whence = tswap16(target_efl->l_whence);
7243 fl.l_start = tswap64(target_efl->l_start);
7244 fl.l_len = tswap64(target_efl->l_len);
Ulrich Hecht7e22e542009-07-24 19:10:27 +02007245 fl.l_pid = tswap32(target_efl->l_pid);
pbrook53a59602006-03-25 19:31:22 +00007246 unlock_user_struct(target_efl, arg3, 0);
pbrookce4defa2006-02-09 16:49:55 +00007247 } else
7248#endif
7249 {
bellard9ee1fa22007-11-11 15:11:19 +00007250 if (!lock_user_struct(VERIFY_READ, target_fl, arg3, 1))
7251 goto efault;
pbrookce4defa2006-02-09 16:49:55 +00007252 fl.l_type = tswap16(target_fl->l_type);
7253 fl.l_whence = tswap16(target_fl->l_whence);
7254 fl.l_start = tswap64(target_fl->l_start);
7255 fl.l_len = tswap64(target_fl->l_len);
Ulrich Hecht7e22e542009-07-24 19:10:27 +02007256 fl.l_pid = tswap32(target_fl->l_pid);
pbrook53a59602006-03-25 19:31:22 +00007257 unlock_user_struct(target_fl, arg3, 0);
pbrookce4defa2006-02-09 16:49:55 +00007258 }
thsb1e341e2007-03-20 21:50:52 +00007259 ret = get_errno(fcntl(arg1, cmd, &fl));
bellard77e46722003-04-29 20:39:06 +00007260 break;
bellard60cd49d2003-03-16 22:53:56 +00007261 default:
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02007262 ret = do_fcntl(arg1, arg2, arg3);
bellard60cd49d2003-03-16 22:53:56 +00007263 break;
7264 }
bellard77e46722003-04-29 20:39:06 +00007265 break;
7266 }
bellard60cd49d2003-03-16 22:53:56 +00007267#endif
ths7d600c82006-12-08 01:32:58 +00007268#ifdef TARGET_NR_cacheflush
7269 case TARGET_NR_cacheflush:
7270 /* self-modifying code is handled automatically, so nothing needed */
7271 ret = 0;
7272 break;
7273#endif
bellardebc05482003-09-30 21:08:41 +00007274#ifdef TARGET_NR_security
bellard31e31b82003-02-18 22:55:36 +00007275 case TARGET_NR_security:
7276 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00007277#endif
bellardc573ff62004-01-04 15:51:36 +00007278#ifdef TARGET_NR_getpagesize
7279 case TARGET_NR_getpagesize:
7280 ret = TARGET_PAGE_SIZE;
7281 break;
7282#endif
bellard31e31b82003-02-18 22:55:36 +00007283 case TARGET_NR_gettid:
7284 ret = get_errno(gettid());
7285 break;
thse5febef2007-04-01 18:31:35 +00007286#ifdef TARGET_NR_readahead
bellard31e31b82003-02-18 22:55:36 +00007287 case TARGET_NR_readahead:
aurel322054ac92008-10-13 21:08:07 +00007288#if TARGET_ABI_BITS == 32
7289#ifdef TARGET_ARM
7290 if (((CPUARMState *)cpu_env)->eabi)
7291 {
7292 arg2 = arg3;
7293 arg3 = arg4;
7294 arg4 = arg5;
7295 }
7296#endif
7297 ret = get_errno(readahead(arg1, ((off64_t)arg3 << 32) | arg2, arg4));
7298#else
7299 ret = get_errno(readahead(arg1, arg2, arg3));
7300#endif
7301 break;
thse5febef2007-04-01 18:31:35 +00007302#endif
bellardebc05482003-09-30 21:08:41 +00007303#ifdef TARGET_NR_setxattr
bellard31e31b82003-02-18 22:55:36 +00007304 case TARGET_NR_setxattr:
7305 case TARGET_NR_lsetxattr:
7306 case TARGET_NR_fsetxattr:
7307 case TARGET_NR_getxattr:
7308 case TARGET_NR_lgetxattr:
7309 case TARGET_NR_fgetxattr:
7310 case TARGET_NR_listxattr:
7311 case TARGET_NR_llistxattr:
7312 case TARGET_NR_flistxattr:
7313 case TARGET_NR_removexattr:
7314 case TARGET_NR_lremovexattr:
7315 case TARGET_NR_fremovexattr:
Arnaud Patard6f932f92009-04-21 21:04:18 +03007316 ret = -TARGET_EOPNOTSUPP;
7317 break;
bellardebc05482003-09-30 21:08:41 +00007318#endif
7319#ifdef TARGET_NR_set_thread_area
bellard5cd43932003-03-29 16:54:36 +00007320 case TARGET_NR_set_thread_area:
bellard8d18e892007-11-14 15:18:40 +00007321#if defined(TARGET_MIPS)
ths6f5b89a2007-03-02 20:48:00 +00007322 ((CPUMIPSState *) cpu_env)->tls_value = arg1;
7323 ret = 0;
7324 break;
edgar_iglef967792009-01-07 14:19:38 +00007325#elif defined(TARGET_CRIS)
7326 if (arg1 & 0xff)
7327 ret = -TARGET_EINVAL;
7328 else {
7329 ((CPUCRISState *) cpu_env)->pregs[PR_PID] = arg1;
7330 ret = 0;
7331 }
7332 break;
bellard8d18e892007-11-14 15:18:40 +00007333#elif defined(TARGET_I386) && defined(TARGET_ABI32)
7334 ret = do_set_thread_area(cpu_env, arg1);
7335 break;
ths6f5b89a2007-03-02 20:48:00 +00007336#else
7337 goto unimplemented_nowarn;
7338#endif
7339#endif
7340#ifdef TARGET_NR_get_thread_area
bellard5cd43932003-03-29 16:54:36 +00007341 case TARGET_NR_get_thread_area:
bellard8d18e892007-11-14 15:18:40 +00007342#if defined(TARGET_I386) && defined(TARGET_ABI32)
7343 ret = do_get_thread_area(cpu_env, arg1);
7344#else
bellard5cd43932003-03-29 16:54:36 +00007345 goto unimplemented_nowarn;
bellardebc05482003-09-30 21:08:41 +00007346#endif
bellard8d18e892007-11-14 15:18:40 +00007347#endif
bellard48dc41e2006-06-21 18:15:50 +00007348#ifdef TARGET_NR_getdomainname
7349 case TARGET_NR_getdomainname:
7350 goto unimplemented_nowarn;
7351#endif
ths6f5b89a2007-03-02 20:48:00 +00007352
thsb5906f92007-03-19 13:32:45 +00007353#ifdef TARGET_NR_clock_gettime
7354 case TARGET_NR_clock_gettime:
7355 {
7356 struct timespec ts;
7357 ret = get_errno(clock_gettime(arg1, &ts));
7358 if (!is_error(ret)) {
7359 host_to_target_timespec(arg2, &ts);
7360 }
7361 break;
7362 }
7363#endif
7364#ifdef TARGET_NR_clock_getres
7365 case TARGET_NR_clock_getres:
7366 {
7367 struct timespec ts;
7368 ret = get_errno(clock_getres(arg1, &ts));
7369 if (!is_error(ret)) {
7370 host_to_target_timespec(arg2, &ts);
7371 }
7372 break;
7373 }
7374#endif
pbrook63d76512008-05-29 13:43:29 +00007375#ifdef TARGET_NR_clock_nanosleep
7376 case TARGET_NR_clock_nanosleep:
7377 {
7378 struct timespec ts;
7379 target_to_host_timespec(&ts, arg3);
7380 ret = get_errno(clock_nanosleep(arg1, arg2, &ts, arg4 ? &ts : NULL));
7381 if (arg4)
7382 host_to_target_timespec(arg4, &ts);
7383 break;
7384 }
7385#endif
thsb5906f92007-03-19 13:32:45 +00007386
ths6f5b89a2007-03-02 20:48:00 +00007387#if defined(TARGET_NR_set_tid_address) && defined(__NR_set_tid_address)
7388 case TARGET_NR_set_tid_address:
bellard579a97f2007-11-11 14:26:47 +00007389 ret = get_errno(set_tid_address((int *)g2h(arg1)));
7390 break;
ths6f5b89a2007-03-02 20:48:00 +00007391#endif
7392
ths3ae43202007-09-16 21:39:48 +00007393#if defined(TARGET_NR_tkill) && defined(__NR_tkill)
ths4cae1d12007-07-12 11:06:53 +00007394 case TARGET_NR_tkill:
pbrook4cb05962008-05-30 18:05:19 +00007395 ret = get_errno(sys_tkill((int)arg1, target_to_host_signal(arg2)));
ths4cae1d12007-07-12 11:06:53 +00007396 break;
7397#endif
7398
ths3ae43202007-09-16 21:39:48 +00007399#if defined(TARGET_NR_tgkill) && defined(__NR_tgkill)
ths71455572007-06-21 21:45:30 +00007400 case TARGET_NR_tgkill:
pbrook4cb05962008-05-30 18:05:19 +00007401 ret = get_errno(sys_tgkill((int)arg1, (int)arg2,
7402 target_to_host_signal(arg3)));
ths71455572007-06-21 21:45:30 +00007403 break;
7404#endif
7405
ths4f2b1fe2007-06-21 21:57:12 +00007406#ifdef TARGET_NR_set_robust_list
7407 case TARGET_NR_set_robust_list:
7408 goto unimplemented_nowarn;
7409#endif
7410
ths9007f0e2007-09-25 17:50:37 +00007411#if defined(TARGET_NR_utimensat) && defined(__NR_utimensat)
7412 case TARGET_NR_utimensat:
7413 {
Riku Voipioebc996f2009-04-21 15:01:51 +03007414 struct timespec *tsp, ts[2];
7415 if (!arg3) {
7416 tsp = NULL;
7417 } else {
7418 target_to_host_timespec(ts, arg3);
7419 target_to_host_timespec(ts+1, arg3+sizeof(struct target_timespec));
7420 tsp = ts;
7421 }
ths9007f0e2007-09-25 17:50:37 +00007422 if (!arg2)
Riku Voipioebc996f2009-04-21 15:01:51 +03007423 ret = get_errno(sys_utimensat(arg1, NULL, tsp, arg4));
ths9007f0e2007-09-25 17:50:37 +00007424 else {
bellard579a97f2007-11-11 14:26:47 +00007425 if (!(p = lock_user_string(arg2))) {
ths0da46a62007-10-20 20:23:07 +00007426 ret = -TARGET_EFAULT;
bellard579a97f2007-11-11 14:26:47 +00007427 goto fail;
7428 }
Riku Voipioebc996f2009-04-21 15:01:51 +03007429 ret = get_errno(sys_utimensat(arg1, path(p), tsp, arg4));
bellard579a97f2007-11-11 14:26:47 +00007430 unlock_user(p, arg2, 0);
ths9007f0e2007-09-25 17:50:37 +00007431 }
7432 }
7433 break;
7434#endif
Juan Quintela2f7bb872009-07-27 16:13:24 +02007435#if defined(CONFIG_USE_NPTL)
pbrookbd0c5662008-05-29 14:34:11 +00007436 case TARGET_NR_futex:
7437 ret = do_futex(arg1, arg2, arg3, arg4, arg5, arg6);
7438 break;
7439#endif
aurel32dbfe4c32009-04-08 21:29:30 +00007440#if defined(TARGET_NR_inotify_init) && defined(__NR_inotify_init)
aurel3239b59762008-10-01 21:46:50 +00007441 case TARGET_NR_inotify_init:
7442 ret = get_errno(sys_inotify_init());
7443 break;
7444#endif
Stefan Weila1606b02010-03-28 11:44:41 +02007445#ifdef CONFIG_INOTIFY1
Riku Voipioc05c7a72010-03-26 15:25:11 +00007446#if defined(TARGET_NR_inotify_init1) && defined(__NR_inotify_init1)
7447 case TARGET_NR_inotify_init1:
7448 ret = get_errno(sys_inotify_init1(arg1));
7449 break;
7450#endif
Stefan Weila1606b02010-03-28 11:44:41 +02007451#endif
aurel32dbfe4c32009-04-08 21:29:30 +00007452#if defined(TARGET_NR_inotify_add_watch) && defined(__NR_inotify_add_watch)
aurel3239b59762008-10-01 21:46:50 +00007453 case TARGET_NR_inotify_add_watch:
7454 p = lock_user_string(arg2);
7455 ret = get_errno(sys_inotify_add_watch(arg1, path(p), arg3));
7456 unlock_user(p, arg2, 0);
7457 break;
7458#endif
aurel32dbfe4c32009-04-08 21:29:30 +00007459#if defined(TARGET_NR_inotify_rm_watch) && defined(__NR_inotify_rm_watch)
aurel3239b59762008-10-01 21:46:50 +00007460 case TARGET_NR_inotify_rm_watch:
7461 ret = get_errno(sys_inotify_rm_watch(arg1, arg2));
7462 break;
7463#endif
ths9007f0e2007-09-25 17:50:37 +00007464
Nathan Froyd8ec9cf82009-07-22 09:14:36 -07007465#if defined(TARGET_NR_mq_open) && defined(__NR_mq_open)
aurel3224e10032009-04-15 16:11:43 +00007466 case TARGET_NR_mq_open:
7467 {
7468 struct mq_attr posix_mq_attr;
7469
7470 p = lock_user_string(arg1 - 1);
7471 if (arg4 != 0)
7472 copy_from_user_mq_attr (&posix_mq_attr, arg4);
7473 ret = get_errno(mq_open(p, arg2, arg3, &posix_mq_attr));
7474 unlock_user (p, arg1, 0);
7475 }
7476 break;
7477
7478 case TARGET_NR_mq_unlink:
7479 p = lock_user_string(arg1 - 1);
7480 ret = get_errno(mq_unlink(p));
7481 unlock_user (p, arg1, 0);
7482 break;
7483
7484 case TARGET_NR_mq_timedsend:
7485 {
7486 struct timespec ts;
7487
7488 p = lock_user (VERIFY_READ, arg2, arg3, 1);
7489 if (arg5 != 0) {
7490 target_to_host_timespec(&ts, arg5);
7491 ret = get_errno(mq_timedsend(arg1, p, arg3, arg4, &ts));
7492 host_to_target_timespec(arg5, &ts);
7493 }
7494 else
7495 ret = get_errno(mq_send(arg1, p, arg3, arg4));
7496 unlock_user (p, arg2, arg3);
7497 }
7498 break;
7499
7500 case TARGET_NR_mq_timedreceive:
7501 {
7502 struct timespec ts;
7503 unsigned int prio;
7504
7505 p = lock_user (VERIFY_READ, arg2, arg3, 1);
7506 if (arg5 != 0) {
7507 target_to_host_timespec(&ts, arg5);
7508 ret = get_errno(mq_timedreceive(arg1, p, arg3, &prio, &ts));
7509 host_to_target_timespec(arg5, &ts);
7510 }
7511 else
7512 ret = get_errno(mq_receive(arg1, p, arg3, &prio));
7513 unlock_user (p, arg2, arg3);
7514 if (arg4 != 0)
7515 put_user_u32(prio, arg4);
7516 }
7517 break;
7518
7519 /* Not implemented for now... */
7520/* case TARGET_NR_mq_notify: */
7521/* break; */
7522
7523 case TARGET_NR_mq_getsetattr:
7524 {
7525 struct mq_attr posix_mq_attr_in, posix_mq_attr_out;
7526 ret = 0;
7527 if (arg3 != 0) {
7528 ret = mq_getattr(arg1, &posix_mq_attr_out);
7529 copy_to_user_mq_attr(arg3, &posix_mq_attr_out);
7530 }
7531 if (arg2 != 0) {
7532 copy_from_user_mq_attr(&posix_mq_attr_in, arg2);
7533 ret |= mq_setattr(arg1, &posix_mq_attr_in, &posix_mq_attr_out);
7534 }
7535
7536 }
7537 break;
7538#endif
7539
vibisreenivasan3ce34df2009-05-16 18:32:41 +05307540#ifdef CONFIG_SPLICE
7541#ifdef TARGET_NR_tee
7542 case TARGET_NR_tee:
7543 {
7544 ret = get_errno(tee(arg1,arg2,arg3,arg4));
7545 }
7546 break;
7547#endif
7548#ifdef TARGET_NR_splice
7549 case TARGET_NR_splice:
7550 {
7551 loff_t loff_in, loff_out;
7552 loff_t *ploff_in = NULL, *ploff_out = NULL;
7553 if(arg2) {
7554 get_user_u64(loff_in, arg2);
7555 ploff_in = &loff_in;
7556 }
7557 if(arg4) {
7558 get_user_u64(loff_out, arg2);
7559 ploff_out = &loff_out;
7560 }
7561 ret = get_errno(splice(arg1, ploff_in, arg3, ploff_out, arg5, arg6));
7562 }
7563 break;
7564#endif
7565#ifdef TARGET_NR_vmsplice
7566 case TARGET_NR_vmsplice:
7567 {
7568 int count = arg3;
7569 struct iovec *vec;
7570
7571 vec = alloca(count * sizeof(struct iovec));
7572 if (lock_iovec(VERIFY_READ, vec, arg2, count, 1) < 0)
7573 goto efault;
7574 ret = get_errno(vmsplice(arg1, vec, count, arg4));
7575 unlock_iovec(vec, arg2, count, 0);
7576 }
7577 break;
7578#endif
7579#endif /* CONFIG_SPLICE */
Riku Voipioc2882b92009-08-12 15:08:24 +03007580#ifdef CONFIG_EVENTFD
7581#if defined(TARGET_NR_eventfd)
7582 case TARGET_NR_eventfd:
7583 ret = get_errno(eventfd(arg1, 0));
7584 break;
7585#endif
7586#if defined(TARGET_NR_eventfd2)
7587 case TARGET_NR_eventfd2:
7588 ret = get_errno(eventfd(arg1, arg2));
7589 break;
7590#endif
7591#endif /* CONFIG_EVENTFD */
Ulrich Hechtd0927932009-09-17 20:22:14 +03007592#if defined(CONFIG_FALLOCATE) && defined(TARGET_NR_fallocate)
7593 case TARGET_NR_fallocate:
7594 ret = get_errno(fallocate(arg1, arg2, arg3, arg4));
7595 break;
7596#endif
Peter Maydellc727f472011-01-06 11:05:10 +00007597#if defined(CONFIG_SYNC_FILE_RANGE)
7598#if defined(TARGET_NR_sync_file_range)
7599 case TARGET_NR_sync_file_range:
7600#if TARGET_ABI_BITS == 32
7601 ret = get_errno(sync_file_range(arg1, target_offset64(arg2, arg3),
7602 target_offset64(arg4, arg5), arg6));
7603#else
7604 ret = get_errno(sync_file_range(arg1, arg2, arg3, arg4));
7605#endif
7606 break;
7607#endif
7608#if defined(TARGET_NR_sync_file_range2)
7609 case TARGET_NR_sync_file_range2:
7610 /* This is like sync_file_range but the arguments are reordered */
7611#if TARGET_ABI_BITS == 32
7612 ret = get_errno(sync_file_range(arg1, target_offset64(arg3, arg4),
7613 target_offset64(arg5, arg6), arg2));
7614#else
7615 ret = get_errno(sync_file_range(arg1, arg3, arg4, arg2));
7616#endif
7617 break;
7618#endif
7619#endif
Peter Maydell3b6edd12011-02-15 18:35:05 +00007620#if defined(CONFIG_EPOLL)
7621#if defined(TARGET_NR_epoll_create)
7622 case TARGET_NR_epoll_create:
7623 ret = get_errno(epoll_create(arg1));
7624 break;
7625#endif
7626#if defined(TARGET_NR_epoll_create1) && defined(CONFIG_EPOLL_CREATE1)
7627 case TARGET_NR_epoll_create1:
7628 ret = get_errno(epoll_create1(arg1));
7629 break;
7630#endif
7631#if defined(TARGET_NR_epoll_ctl)
7632 case TARGET_NR_epoll_ctl:
7633 {
7634 struct epoll_event ep;
7635 struct epoll_event *epp = 0;
7636 if (arg4) {
7637 struct target_epoll_event *target_ep;
7638 if (!lock_user_struct(VERIFY_READ, target_ep, arg4, 1)) {
7639 goto efault;
7640 }
7641 ep.events = tswap32(target_ep->events);
7642 /* The epoll_data_t union is just opaque data to the kernel,
7643 * so we transfer all 64 bits across and need not worry what
7644 * actual data type it is.
7645 */
7646 ep.data.u64 = tswap64(target_ep->data.u64);
7647 unlock_user_struct(target_ep, arg4, 0);
7648 epp = &ep;
7649 }
7650 ret = get_errno(epoll_ctl(arg1, arg2, arg3, epp));
7651 break;
7652 }
7653#endif
7654
7655#if defined(TARGET_NR_epoll_pwait) && defined(CONFIG_EPOLL_PWAIT)
7656#define IMPLEMENT_EPOLL_PWAIT
7657#endif
7658#if defined(TARGET_NR_epoll_wait) || defined(IMPLEMENT_EPOLL_PWAIT)
7659#if defined(TARGET_NR_epoll_wait)
7660 case TARGET_NR_epoll_wait:
7661#endif
7662#if defined(IMPLEMENT_EPOLL_PWAIT)
7663 case TARGET_NR_epoll_pwait:
7664#endif
7665 {
7666 struct target_epoll_event *target_ep;
7667 struct epoll_event *ep;
7668 int epfd = arg1;
7669 int maxevents = arg3;
7670 int timeout = arg4;
7671
7672 target_ep = lock_user(VERIFY_WRITE, arg2,
7673 maxevents * sizeof(struct target_epoll_event), 1);
7674 if (!target_ep) {
7675 goto efault;
7676 }
7677
7678 ep = alloca(maxevents * sizeof(struct epoll_event));
7679
7680 switch (num) {
7681#if defined(IMPLEMENT_EPOLL_PWAIT)
7682 case TARGET_NR_epoll_pwait:
7683 {
7684 target_sigset_t *target_set;
7685 sigset_t _set, *set = &_set;
7686
7687 if (arg5) {
7688 target_set = lock_user(VERIFY_READ, arg5,
7689 sizeof(target_sigset_t), 1);
7690 if (!target_set) {
7691 unlock_user(target_ep, arg2, 0);
7692 goto efault;
7693 }
7694 target_to_host_sigset(set, target_set);
7695 unlock_user(target_set, arg5, 0);
7696 } else {
7697 set = NULL;
7698 }
7699
7700 ret = get_errno(epoll_pwait(epfd, ep, maxevents, timeout, set));
7701 break;
7702 }
7703#endif
7704#if defined(TARGET_NR_epoll_wait)
7705 case TARGET_NR_epoll_wait:
7706 ret = get_errno(epoll_wait(epfd, ep, maxevents, timeout));
7707 break;
7708#endif
7709 default:
7710 ret = -TARGET_ENOSYS;
7711 }
7712 if (!is_error(ret)) {
7713 int i;
7714 for (i = 0; i < ret; i++) {
7715 target_ep[i].events = tswap32(ep[i].events);
7716 target_ep[i].data.u64 = tswap64(ep[i].data.u64);
7717 }
7718 }
7719 unlock_user(target_ep, arg2, ret * sizeof(struct target_epoll_event));
7720 break;
7721 }
7722#endif
7723#endif
bellard31e31b82003-02-18 22:55:36 +00007724 default:
7725 unimplemented:
bellard5cd43932003-03-29 16:54:36 +00007726 gemu_log("qemu: Unsupported syscall: %d\n", num);
ths4f2b1fe2007-06-21 21:57:12 +00007727#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 +00007728 unimplemented_nowarn:
bellard80a9d032005-01-03 23:31:27 +00007729#endif
ths0da46a62007-10-20 20:23:07 +00007730 ret = -TARGET_ENOSYS;
bellard31e31b82003-02-18 22:55:36 +00007731 break;
7732 }
bellard579a97f2007-11-11 14:26:47 +00007733fail:
bellardc573ff62004-01-04 15:51:36 +00007734#ifdef DEBUG
Blue Swirl0bf9e312009-07-20 17:19:25 +00007735 gemu_log(" = " TARGET_ABI_FMT_ld "\n", ret);
bellardc573ff62004-01-04 15:51:36 +00007736#endif
thsb92c47c2007-11-01 00:07:38 +00007737 if(do_strace)
7738 print_syscall_ret(num, ret);
bellard31e31b82003-02-18 22:55:36 +00007739 return ret;
bellard579a97f2007-11-11 14:26:47 +00007740efault:
7741 ret = -TARGET_EFAULT;
7742 goto fail;
bellard31e31b82003-02-18 22:55:36 +00007743}