blob: 8a953492b890e58a47027b0577239ef0650fe197 [file] [log] [blame]
bellard31e31b82003-02-18 22:55:36 +00001/*
2 * Linux syscalls
ths5fafdf22007-09-16 21:08:06 +00003 *
bellard31e31b82003-02-18 22:55:36 +00004 * Copyright (c) 2003 Fabrice Bellard
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
blueswir1530e7612009-01-05 18:11:53 +000018 * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
19 * MA 02110-1301, USA.
bellard31e31b82003-02-18 22:55:36 +000020 */
21#include <stdlib.h>
22#include <stdio.h>
23#include <stdarg.h>
bellard04369ff2003-03-20 22:33:23 +000024#include <string.h>
bellard31e31b82003-02-18 22:55:36 +000025#include <elf.h>
26#include <endian.h>
27#include <errno.h>
28#include <unistd.h>
29#include <fcntl.h>
bellard7854b052003-03-29 17:22:23 +000030#include <time.h>
pbrook82e671d2008-06-09 12:10:22 +000031#include <limits.h>
aurel3224e10032009-04-15 16:11:43 +000032#include <mqueue.h>
bellard31e31b82003-02-18 22:55:36 +000033#include <sys/types.h>
thsd08d3bb2007-03-19 13:09:22 +000034#include <sys/ipc.h>
35#include <sys/msg.h>
bellard31e31b82003-02-18 22:55:36 +000036#include <sys/wait.h>
37#include <sys/time.h>
38#include <sys/stat.h>
39#include <sys/mount.h>
ths39b9aae2007-02-11 18:36:44 +000040#include <sys/prctl.h>
bellard31e31b82003-02-18 22:55:36 +000041#include <sys/resource.h>
42#include <sys/mman.h>
43#include <sys/swap.h>
44#include <signal.h>
45#include <sched.h>
46#include <sys/socket.h>
aurel32607175e2009-04-15 16:11:59 +000047#include <sys/un.h>
bellard31e31b82003-02-18 22:55:36 +000048#include <sys/uio.h>
bellard9de5e442003-03-23 16:49:39 +000049#include <sys/poll.h>
bellard32f36bc2003-03-30 21:29:48 +000050#include <sys/times.h>
bellard8853f862004-02-22 14:57:26 +000051#include <sys/shm.h>
thsfa294812007-02-02 22:05:00 +000052#include <sys/sem.h>
bellard56c8f682005-11-28 22:28:41 +000053#include <sys/statfs.h>
bellardebc05482003-09-30 21:08:41 +000054#include <utime.h>
bellarda5448a72004-06-19 16:59:03 +000055#include <sys/sysinfo.h>
aurel323b3f24a2009-04-15 16:12:13 +000056#include <sys/utsname.h>
bellard72f03902003-02-18 23:33:18 +000057//#include <sys/user.h>
bellard8853f862004-02-22 14:57:26 +000058#include <netinet/ip.h>
bellard7854b052003-03-29 17:22:23 +000059#include <netinet/tcp.h>
aurel320b6d3ae2008-09-15 07:43:43 +000060#include <qemu-common.h>
aurel326d946cd2008-11-06 16:15:18 +000061#ifdef HAVE_GPROF
62#include <sys/gmon.h>
63#endif
bellard31e31b82003-02-18 22:55:36 +000064
65#define termios host_termios
66#define winsize host_winsize
67#define termio host_termio
bellard04369ff2003-03-20 22:33:23 +000068#define sgttyb host_sgttyb /* same as target */
69#define tchars host_tchars /* same as target */
70#define ltchars host_ltchars /* same as target */
bellard31e31b82003-02-18 22:55:36 +000071
72#include <linux/termios.h>
73#include <linux/unistd.h>
74#include <linux/utsname.h>
75#include <linux/cdrom.h>
76#include <linux/hdreg.h>
77#include <linux/soundcard.h>
bellard19b84f32003-05-08 15:41:49 +000078#include <linux/kd.h>
balrog8fbd6b52008-09-20 03:03:09 +000079#include <linux/mtio.h>
pbrookd7e40362008-05-23 16:06:43 +000080#include "linux_loop.h"
bellard31e31b82003-02-18 22:55:36 +000081
bellard3ef693a2003-03-23 20:17:16 +000082#include "qemu.h"
balrog526ccb72008-07-16 12:13:52 +000083#include "qemu-common.h"
bellard31e31b82003-02-18 22:55:36 +000084
pbrook30813ce2008-06-02 15:45:44 +000085#if defined(USE_NPTL)
86#include <linux/futex.h>
pbrookd865bab2008-06-07 22:12:17 +000087#define CLONE_NPTL_FLAGS2 (CLONE_SETTLS | \
88 CLONE_PARENT_SETTID | CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID)
89#else
90/* XXX: Hardcode the above values. */
91#define CLONE_NPTL_FLAGS2 0
pbrook30813ce2008-06-02 15:45:44 +000092#endif
93
bellard72f03902003-02-18 23:33:18 +000094//#define DEBUG
bellard31e31b82003-02-18 22:55:36 +000095
bellard1a9353d2003-03-16 20:28:50 +000096//#include <linux/msdos_fs.h>
aurel326556a832008-10-13 21:08:17 +000097#define VFAT_IOCTL_READDIR_BOTH _IOR('r', 1, struct linux_dirent [2])
98#define VFAT_IOCTL_READDIR_SHORT _IOR('r', 2, struct linux_dirent [2])
bellard1a9353d2003-03-16 20:28:50 +000099
bellard70a194b2003-08-11 22:20:16 +0000100
bellard70a194b2003-08-11 22:20:16 +0000101#undef _syscall0
102#undef _syscall1
103#undef _syscall2
104#undef _syscall3
105#undef _syscall4
106#undef _syscall5
bellard83fcb512006-06-14 13:37:16 +0000107#undef _syscall6
bellard70a194b2003-08-11 22:20:16 +0000108
bellard83fcb512006-06-14 13:37:16 +0000109#define _syscall0(type,name) \
blueswir18fcd3692008-08-17 20:26:25 +0000110static type name (void) \
bellard83fcb512006-06-14 13:37:16 +0000111{ \
112 return syscall(__NR_##name); \
bellard70a194b2003-08-11 22:20:16 +0000113}
114
bellard83fcb512006-06-14 13:37:16 +0000115#define _syscall1(type,name,type1,arg1) \
blueswir18fcd3692008-08-17 20:26:25 +0000116static type name (type1 arg1) \
bellard83fcb512006-06-14 13:37:16 +0000117{ \
118 return syscall(__NR_##name, arg1); \
bellard70a194b2003-08-11 22:20:16 +0000119}
120
bellard83fcb512006-06-14 13:37:16 +0000121#define _syscall2(type,name,type1,arg1,type2,arg2) \
blueswir18fcd3692008-08-17 20:26:25 +0000122static type name (type1 arg1,type2 arg2) \
bellard83fcb512006-06-14 13:37:16 +0000123{ \
124 return syscall(__NR_##name, arg1, arg2); \
bellard70a194b2003-08-11 22:20:16 +0000125}
126
bellard83fcb512006-06-14 13:37:16 +0000127#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \
blueswir18fcd3692008-08-17 20:26:25 +0000128static type name (type1 arg1,type2 arg2,type3 arg3) \
bellard83fcb512006-06-14 13:37:16 +0000129{ \
130 return syscall(__NR_##name, arg1, arg2, arg3); \
bellard70a194b2003-08-11 22:20:16 +0000131}
132
bellard83fcb512006-06-14 13:37:16 +0000133#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \
blueswir18fcd3692008-08-17 20:26:25 +0000134static type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4) \
bellard83fcb512006-06-14 13:37:16 +0000135{ \
136 return syscall(__NR_##name, arg1, arg2, arg3, arg4); \
bellard70a194b2003-08-11 22:20:16 +0000137}
138
bellard83fcb512006-06-14 13:37:16 +0000139#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
140 type5,arg5) \
blueswir18fcd3692008-08-17 20:26:25 +0000141static type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \
bellard83fcb512006-06-14 13:37:16 +0000142{ \
143 return syscall(__NR_##name, arg1, arg2, arg3, arg4, arg5); \
bellard70a194b2003-08-11 22:20:16 +0000144}
bellard83fcb512006-06-14 13:37:16 +0000145
146
147#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
148 type5,arg5,type6,arg6) \
blueswir18fcd3692008-08-17 20:26:25 +0000149static type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5, \
150 type6 arg6) \
bellard83fcb512006-06-14 13:37:16 +0000151{ \
152 return syscall(__NR_##name, arg1, arg2, arg3, arg4, arg5, arg6); \
153}
154
bellard70a194b2003-08-11 22:20:16 +0000155
bellard31e31b82003-02-18 22:55:36 +0000156#define __NR_sys_uname __NR_uname
ths92a34c12007-09-24 09:27:49 +0000157#define __NR_sys_faccessat __NR_faccessat
ths814d7972007-09-24 09:26:51 +0000158#define __NR_sys_fchmodat __NR_fchmodat
thsccfa72b2007-09-24 09:23:34 +0000159#define __NR_sys_fchownat __NR_fchownat
balrog6a24a772008-09-20 02:23:36 +0000160#define __NR_sys_fstatat64 __NR_fstatat64
balrogac8a6552008-09-20 02:25:39 +0000161#define __NR_sys_futimesat __NR_futimesat
bellard72f03902003-02-18 23:33:18 +0000162#define __NR_sys_getcwd1 __NR_getcwd
bellard72f03902003-02-18 23:33:18 +0000163#define __NR_sys_getdents __NR_getdents
bellarddab2ed92003-03-22 15:23:14 +0000164#define __NR_sys_getdents64 __NR_getdents64
thsc6cda172007-10-09 03:42:34 +0000165#define __NR_sys_getpriority __NR_getpriority
ths64f0ce42007-09-24 09:25:06 +0000166#define __NR_sys_linkat __NR_linkat
ths4472ad02007-09-24 09:22:32 +0000167#define __NR_sys_mkdirat __NR_mkdirat
ths75ac37a2007-09-24 09:23:05 +0000168#define __NR_sys_mknodat __NR_mknodat
aurel329d33b762009-04-08 23:07:05 +0000169#define __NR_sys_newfstatat __NR_newfstatat
ths82424832007-09-24 09:21:55 +0000170#define __NR_sys_openat __NR_openat
ths5e0ccb12007-09-24 09:26:10 +0000171#define __NR_sys_readlinkat __NR_readlinkat
ths722183f2007-09-24 09:24:37 +0000172#define __NR_sys_renameat __NR_renameat
bellard66fb9762003-03-23 01:06:05 +0000173#define __NR_sys_rt_sigqueueinfo __NR_rt_sigqueueinfo
thsf0b62432007-09-24 09:25:40 +0000174#define __NR_sys_symlinkat __NR_symlinkat
ths7494b0f2007-02-11 18:26:53 +0000175#define __NR_sys_syslog __NR_syslog
ths71455572007-06-21 21:45:30 +0000176#define __NR_sys_tgkill __NR_tgkill
ths4cae1d12007-07-12 11:06:53 +0000177#define __NR_sys_tkill __NR_tkill
ths8170f562007-09-24 09:24:11 +0000178#define __NR_sys_unlinkat __NR_unlinkat
ths9007f0e2007-09-25 17:50:37 +0000179#define __NR_sys_utimensat __NR_utimensat
pbrookbd0c5662008-05-29 14:34:11 +0000180#define __NR_sys_futex __NR_futex
aurel3239b59762008-10-01 21:46:50 +0000181#define __NR_sys_inotify_init __NR_inotify_init
182#define __NR_sys_inotify_add_watch __NR_inotify_add_watch
183#define __NR_sys_inotify_rm_watch __NR_inotify_rm_watch
bellard31e31b82003-02-18 22:55:36 +0000184
bellardbc51c5c2004-03-17 23:46:04 +0000185#if defined(__alpha__) || defined (__ia64__) || defined(__x86_64__)
bellard9af9eaa2003-04-07 21:34:41 +0000186#define __NR__llseek __NR_lseek
187#endif
188
bellard72f03902003-02-18 23:33:18 +0000189#ifdef __NR_gettid
bellard31e31b82003-02-18 22:55:36 +0000190_syscall0(int, gettid)
bellard72f03902003-02-18 23:33:18 +0000191#else
ths0da46a62007-10-20 20:23:07 +0000192/* This is a replacement for the host gettid() and must return a host
193 errno. */
bellard72f03902003-02-18 23:33:18 +0000194static int gettid(void) {
195 return -ENOSYS;
196}
197#endif
aurel323b3f24a2009-04-15 16:12:13 +0000198#if TARGET_ABI_BITS == 32
199_syscall3(int, sys_getdents, uint, fd, struct linux_dirent *, dirp, uint, count);
200#endif
201#if defined(TARGET_NR_getdents64) && defined(__NR_getdents64)
202_syscall3(int, sys_getdents64, uint, fd, struct linux_dirent64 *, dirp, uint, count);
203#endif
204_syscall2(int, sys_getpriority, int, which, int, who);
Paul Brook909b69c2009-05-19 15:58:52 +0100205#if defined(TARGET_NR__llseek) && !defined (__x86_64__)
aurel323b3f24a2009-04-15 16:12:13 +0000206_syscall5(int, _llseek, uint, fd, ulong, hi, ulong, lo,
207 loff_t *, res, uint, wh);
208#endif
209_syscall3(int,sys_rt_sigqueueinfo,int,pid,int,sig,siginfo_t *,uinfo)
210_syscall3(int,sys_syslog,int,type,char*,bufp,int,len)
211#if defined(TARGET_NR_tgkill) && defined(__NR_tgkill)
212_syscall3(int,sys_tgkill,int,tgid,int,pid,int,sig)
213#endif
214#if defined(TARGET_NR_tkill) && defined(__NR_tkill)
215_syscall2(int,sys_tkill,int,tid,int,sig)
216#endif
217#ifdef __NR_exit_group
218_syscall1(int,exit_group,int,error_code)
219#endif
220#if defined(TARGET_NR_set_tid_address) && defined(__NR_set_tid_address)
221_syscall1(int,set_tid_address,int *,tidptr)
222#endif
223#if defined(USE_NPTL)
224#if defined(TARGET_NR_futex) && defined(__NR_futex)
225_syscall6(int,sys_futex,int *,uaddr,int,op,int,val,
226 const struct timespec *,timeout,int *,uaddr2,int,val3)
227#endif
228#endif
229
230static bitmask_transtbl fcntl_flags_tbl[] = {
231 { TARGET_O_ACCMODE, TARGET_O_WRONLY, O_ACCMODE, O_WRONLY, },
232 { TARGET_O_ACCMODE, TARGET_O_RDWR, O_ACCMODE, O_RDWR, },
233 { TARGET_O_CREAT, TARGET_O_CREAT, O_CREAT, O_CREAT, },
234 { TARGET_O_EXCL, TARGET_O_EXCL, O_EXCL, O_EXCL, },
235 { TARGET_O_NOCTTY, TARGET_O_NOCTTY, O_NOCTTY, O_NOCTTY, },
236 { TARGET_O_TRUNC, TARGET_O_TRUNC, O_TRUNC, O_TRUNC, },
237 { TARGET_O_APPEND, TARGET_O_APPEND, O_APPEND, O_APPEND, },
238 { TARGET_O_NONBLOCK, TARGET_O_NONBLOCK, O_NONBLOCK, O_NONBLOCK, },
239 { TARGET_O_SYNC, TARGET_O_SYNC, O_SYNC, O_SYNC, },
240 { TARGET_FASYNC, TARGET_FASYNC, FASYNC, FASYNC, },
241 { TARGET_O_DIRECTORY, TARGET_O_DIRECTORY, O_DIRECTORY, O_DIRECTORY, },
242 { TARGET_O_NOFOLLOW, TARGET_O_NOFOLLOW, O_NOFOLLOW, O_NOFOLLOW, },
243 { TARGET_O_LARGEFILE, TARGET_O_LARGEFILE, O_LARGEFILE, O_LARGEFILE, },
244#if defined(O_DIRECT)
245 { TARGET_O_DIRECT, TARGET_O_DIRECT, O_DIRECT, O_DIRECT, },
246#endif
247 { 0, 0, 0, 0 }
248};
249
250#define COPY_UTSNAME_FIELD(dest, src) \
251 do { \
252 /* __NEW_UTS_LEN doesn't include terminating null */ \
253 (void) strncpy((dest), (src), __NEW_UTS_LEN); \
254 (dest)[__NEW_UTS_LEN] = '\0'; \
255 } while (0)
256
257static int sys_uname(struct new_utsname *buf)
258{
259 struct utsname uts_buf;
260
261 if (uname(&uts_buf) < 0)
262 return (-1);
263
264 /*
265 * Just in case these have some differences, we
266 * translate utsname to new_utsname (which is the
267 * struct linux kernel uses).
268 */
269
270 bzero(buf, sizeof (*buf));
271 COPY_UTSNAME_FIELD(buf->sysname, uts_buf.sysname);
272 COPY_UTSNAME_FIELD(buf->nodename, uts_buf.nodename);
273 COPY_UTSNAME_FIELD(buf->release, uts_buf.release);
274 COPY_UTSNAME_FIELD(buf->version, uts_buf.version);
275 COPY_UTSNAME_FIELD(buf->machine, uts_buf.machine);
276#ifdef _GNU_SOURCE
277 COPY_UTSNAME_FIELD(buf->domainname, uts_buf.domainname);
278#endif
279 return (0);
280
281#undef COPY_UTSNAME_FIELD
282}
283
284static int sys_getcwd1(char *buf, size_t size)
285{
286 if (getcwd(buf, size) == NULL) {
287 /* getcwd() sets errno */
288 return (-1);
289 }
aurel32aaf4ad32009-04-16 14:17:14 +0000290 return strlen(buf)+1;
aurel323b3f24a2009-04-15 16:12:13 +0000291}
292
293#ifdef CONFIG_ATFILE
294/*
295 * Host system seems to have atfile syscall stubs available. We
296 * now enable them one by one as specified by target syscall_nr.h.
297 */
298
299#ifdef TARGET_NR_faccessat
aurel32465c9f02009-04-19 08:52:17 +0000300static int sys_faccessat(int dirfd, const char *pathname, int mode)
aurel323b3f24a2009-04-15 16:12:13 +0000301{
aurel32465c9f02009-04-19 08:52:17 +0000302 return (faccessat(dirfd, pathname, mode, 0));
aurel323b3f24a2009-04-15 16:12:13 +0000303}
304#endif
305#ifdef TARGET_NR_fchmodat
aurel32465c9f02009-04-19 08:52:17 +0000306static int sys_fchmodat(int dirfd, const char *pathname, mode_t mode)
aurel323b3f24a2009-04-15 16:12:13 +0000307{
aurel32465c9f02009-04-19 08:52:17 +0000308 return (fchmodat(dirfd, pathname, mode, 0));
aurel323b3f24a2009-04-15 16:12:13 +0000309}
310#endif
aurel32fda33742009-04-15 17:12:01 +0000311#if defined(TARGET_NR_fchownat) && defined(USE_UID16)
aurel323b3f24a2009-04-15 16:12:13 +0000312static int sys_fchownat(int dirfd, const char *pathname, uid_t owner,
313 gid_t group, int flags)
314{
315 return (fchownat(dirfd, pathname, owner, group, flags));
316}
317#endif
318#ifdef __NR_fstatat64
319static int sys_fstatat64(int dirfd, const char *pathname, struct stat *buf,
320 int flags)
321{
322 return (fstatat(dirfd, pathname, buf, flags));
323}
324#endif
325#ifdef __NR_newfstatat
326static int sys_newfstatat(int dirfd, const char *pathname, struct stat *buf,
327 int flags)
328{
329 return (fstatat(dirfd, pathname, buf, flags));
330}
331#endif
332#ifdef TARGET_NR_futimesat
333static int sys_futimesat(int dirfd, const char *pathname,
334 const struct timeval times[2])
335{
336 return (futimesat(dirfd, pathname, times));
337}
338#endif
339#ifdef TARGET_NR_linkat
340static int sys_linkat(int olddirfd, const char *oldpath,
341 int newdirfd, const char *newpath, int flags)
342{
343 return (linkat(olddirfd, oldpath, newdirfd, newpath, flags));
344}
345#endif
346#ifdef TARGET_NR_mkdirat
347static int sys_mkdirat(int dirfd, const char *pathname, mode_t mode)
348{
349 return (mkdirat(dirfd, pathname, mode));
350}
351#endif
352#ifdef TARGET_NR_mknodat
353static int sys_mknodat(int dirfd, const char *pathname, mode_t mode,
354 dev_t dev)
355{
356 return (mknodat(dirfd, pathname, mode, dev));
357}
358#endif
359#ifdef TARGET_NR_openat
360static int sys_openat(int dirfd, const char *pathname, int flags, ...)
361{
362 /*
363 * open(2) has extra parameter 'mode' when called with
364 * flag O_CREAT.
365 */
366 if ((flags & O_CREAT) != 0) {
367 va_list ap;
368 mode_t mode;
369
370 /*
371 * Get the 'mode' parameter and translate it to
372 * host bits.
373 */
374 va_start(ap, flags);
375 mode = va_arg(ap, mode_t);
376 mode = target_to_host_bitmask(mode, fcntl_flags_tbl);
377 va_end(ap);
378
379 return (openat(dirfd, pathname, flags, mode));
380 }
381 return (openat(dirfd, pathname, flags));
382}
383#endif
384#ifdef TARGET_NR_readlinkat
385static int sys_readlinkat(int dirfd, const char *pathname, char *buf, size_t bufsiz)
386{
387 return (readlinkat(dirfd, pathname, buf, bufsiz));
388}
389#endif
390#ifdef TARGET_NR_renameat
391static int sys_renameat(int olddirfd, const char *oldpath,
392 int newdirfd, const char *newpath)
393{
394 return (renameat(olddirfd, oldpath, newdirfd, newpath));
395}
396#endif
397#ifdef TARGET_NR_symlinkat
398static int sys_symlinkat(const char *oldpath, int newdirfd, const char *newpath)
399{
400 return (symlinkat(oldpath, newdirfd, newpath));
401}
402#endif
403#ifdef TARGET_NR_unlinkat
404static int sys_unlinkat(int dirfd, const char *pathname, int flags)
405{
406 return (unlinkat(dirfd, pathname, flags));
407}
408#endif
aurel323b3f24a2009-04-15 16:12:13 +0000409#else /* !CONFIG_ATFILE */
410
411/*
412 * Try direct syscalls instead
413 */
ths92a34c12007-09-24 09:27:49 +0000414#if defined(TARGET_NR_faccessat) && defined(__NR_faccessat)
aurel32465c9f02009-04-19 08:52:17 +0000415_syscall3(int,sys_faccessat,int,dirfd,const char *,pathname,int,mode)
ths92a34c12007-09-24 09:27:49 +0000416#endif
ths814d7972007-09-24 09:26:51 +0000417#if defined(TARGET_NR_fchmodat) && defined(__NR_fchmodat)
aurel32465c9f02009-04-19 08:52:17 +0000418_syscall3(int,sys_fchmodat,int,dirfd,const char *,pathname, mode_t,mode)
ths814d7972007-09-24 09:26:51 +0000419#endif
blueswir14583f582008-08-24 10:35:55 +0000420#if defined(TARGET_NR_fchownat) && defined(__NR_fchownat) && defined(USE_UID16)
thsccfa72b2007-09-24 09:23:34 +0000421_syscall5(int,sys_fchownat,int,dirfd,const char *,pathname,
422 uid_t,owner,gid_t,group,int,flags)
423#endif
aurel329d33b762009-04-08 23:07:05 +0000424#if (defined(TARGET_NR_fstatat64) || defined(TARGET_NR_newfstatat)) && \
425 defined(__NR_fstatat64)
balrog6a24a772008-09-20 02:23:36 +0000426_syscall4(int,sys_fstatat64,int,dirfd,const char *,pathname,
427 struct stat *,buf,int,flags)
428#endif
balrogac8a6552008-09-20 02:25:39 +0000429#if defined(TARGET_NR_futimesat) && defined(__NR_futimesat)
430_syscall3(int,sys_futimesat,int,dirfd,const char *,pathname,
431 const struct timeval *,times)
432#endif
aurel323b3f24a2009-04-15 16:12:13 +0000433#if (defined(TARGET_NR_newfstatat) || defined(TARGET_NR_fstatat64) ) && \
434 defined(__NR_newfstatat)
435_syscall4(int,sys_newfstatat,int,dirfd,const char *,pathname,
436 struct stat *,buf,int,flags)
blueswir18fcd3692008-08-17 20:26:25 +0000437#endif
ths64f0ce42007-09-24 09:25:06 +0000438#if defined(TARGET_NR_linkat) && defined(__NR_linkat)
439_syscall5(int,sys_linkat,int,olddirfd,const char *,oldpath,
aurel323b3f24a2009-04-15 16:12:13 +0000440 int,newdirfd,const char *,newpath,int,flags)
ths64f0ce42007-09-24 09:25:06 +0000441#endif
ths4472ad02007-09-24 09:22:32 +0000442#if defined(TARGET_NR_mkdirat) && defined(__NR_mkdirat)
443_syscall3(int,sys_mkdirat,int,dirfd,const char *,pathname,mode_t,mode)
444#endif
ths75ac37a2007-09-24 09:23:05 +0000445#if defined(TARGET_NR_mknodat) && defined(__NR_mknodat)
446_syscall4(int,sys_mknodat,int,dirfd,const char *,pathname,
447 mode_t,mode,dev_t,dev)
448#endif
ths82424832007-09-24 09:21:55 +0000449#if defined(TARGET_NR_openat) && defined(__NR_openat)
450_syscall4(int,sys_openat,int,dirfd,const char *,pathname,int,flags,mode_t,mode)
451#endif
ths5e0ccb12007-09-24 09:26:10 +0000452#if defined(TARGET_NR_readlinkat) && defined(__NR_readlinkat)
453_syscall4(int,sys_readlinkat,int,dirfd,const char *,pathname,
454 char *,buf,size_t,bufsize)
455#endif
ths722183f2007-09-24 09:24:37 +0000456#if defined(TARGET_NR_renameat) && defined(__NR_renameat)
457_syscall4(int,sys_renameat,int,olddirfd,const char *,oldpath,
458 int,newdirfd,const char *,newpath)
459#endif
thsb51eaa82007-09-25 16:09:22 +0000460#if defined(TARGET_NR_symlinkat) && defined(__NR_symlinkat)
thsf0b62432007-09-24 09:25:40 +0000461_syscall3(int,sys_symlinkat,const char *,oldpath,
462 int,newdirfd,const char *,newpath)
463#endif
ths8170f562007-09-24 09:24:11 +0000464#if defined(TARGET_NR_unlinkat) && defined(__NR_unlinkat)
465_syscall3(int,sys_unlinkat,int,dirfd,const char *,pathname,int,flags)
466#endif
Riku Voipioebc996f2009-04-21 15:01:51 +0300467
468#endif /* CONFIG_ATFILE */
469
470#ifdef CONFIG_UTIMENSAT
471static int sys_utimensat(int dirfd, const char *pathname,
472 const struct timespec times[2], int flags)
473{
474 if (pathname == NULL)
475 return futimens(dirfd, times);
476 else
477 return utimensat(dirfd, pathname, times, flags);
478}
479#else
ths9007f0e2007-09-25 17:50:37 +0000480#if defined(TARGET_NR_utimensat) && defined(__NR_utimensat)
481_syscall4(int,sys_utimensat,int,dirfd,const char *,pathname,
482 const struct timespec *,tsp,int,flags)
483#endif
Riku Voipioebc996f2009-04-21 15:01:51 +0300484#endif /* CONFIG_UTIMENSAT */
aurel323b3f24a2009-04-15 16:12:13 +0000485
486#ifdef CONFIG_INOTIFY
aurel328690e422009-04-17 13:50:32 +0000487#include <sys/inotify.h>
aurel323b3f24a2009-04-15 16:12:13 +0000488
aurel3239b59762008-10-01 21:46:50 +0000489#if defined(TARGET_NR_inotify_init) && defined(__NR_inotify_init)
aurel323b3f24a2009-04-15 16:12:13 +0000490static int sys_inotify_init(void)
491{
492 return (inotify_init());
493}
aurel3239b59762008-10-01 21:46:50 +0000494#endif
495#if defined(TARGET_NR_inotify_add_watch) && defined(__NR_inotify_add_watch)
aurel323b3f24a2009-04-15 16:12:13 +0000496static int sys_inotify_add_watch(int fd,const char *pathname, int32_t mask)
497{
498 return (inotify_add_watch(fd, pathname, mask));
499}
aurel3239b59762008-10-01 21:46:50 +0000500#endif
501#if defined(TARGET_NR_inotify_rm_watch) && defined(__NR_inotify_rm_watch)
aurel323b3f24a2009-04-15 16:12:13 +0000502static int sys_inotify_rm_watch(int fd, int32_t wd)
503{
aurel328690e422009-04-17 13:50:32 +0000504 return (inotify_rm_watch(fd, wd));
aurel323b3f24a2009-04-15 16:12:13 +0000505}
aurel3239b59762008-10-01 21:46:50 +0000506#endif
aurel323b3f24a2009-04-15 16:12:13 +0000507#else
508/* Userspace can usually survive runtime without inotify */
509#undef TARGET_NR_inotify_init
510#undef TARGET_NR_inotify_add_watch
511#undef TARGET_NR_inotify_rm_watch
512#endif /* CONFIG_INOTIFY */
513
bellard66fb9762003-03-23 01:06:05 +0000514
515extern int personality(int);
bellard9de5e442003-03-23 16:49:39 +0000516extern int flock(int, int);
517extern int setfsuid(int);
518extern int setfsgid(int);
bellard19b84f32003-05-08 15:41:49 +0000519extern int setgroups(int, gid_t *);
bellard31e31b82003-02-18 22:55:36 +0000520
thsb92c47c2007-11-01 00:07:38 +0000521#define ERRNO_TABLE_SIZE 1200
522
523/* target_to_host_errno_table[] is initialized from
524 * host_to_target_errno_table[] in syscall_init(). */
525static uint16_t target_to_host_errno_table[ERRNO_TABLE_SIZE] = {
526};
527
ths637947f2007-06-01 12:09:19 +0000528/*
thsfe8f0962007-07-12 10:59:21 +0000529 * This list is the union of errno values overridden in asm-<arch>/errno.h
ths637947f2007-06-01 12:09:19 +0000530 * minus the errnos that are not actually generic to all archs.
531 */
thsb92c47c2007-11-01 00:07:38 +0000532static uint16_t host_to_target_errno_table[ERRNO_TABLE_SIZE] = {
ths637947f2007-06-01 12:09:19 +0000533 [EIDRM] = TARGET_EIDRM,
534 [ECHRNG] = TARGET_ECHRNG,
535 [EL2NSYNC] = TARGET_EL2NSYNC,
536 [EL3HLT] = TARGET_EL3HLT,
537 [EL3RST] = TARGET_EL3RST,
538 [ELNRNG] = TARGET_ELNRNG,
539 [EUNATCH] = TARGET_EUNATCH,
540 [ENOCSI] = TARGET_ENOCSI,
541 [EL2HLT] = TARGET_EL2HLT,
542 [EDEADLK] = TARGET_EDEADLK,
543 [ENOLCK] = TARGET_ENOLCK,
544 [EBADE] = TARGET_EBADE,
545 [EBADR] = TARGET_EBADR,
546 [EXFULL] = TARGET_EXFULL,
547 [ENOANO] = TARGET_ENOANO,
548 [EBADRQC] = TARGET_EBADRQC,
549 [EBADSLT] = TARGET_EBADSLT,
550 [EBFONT] = TARGET_EBFONT,
551 [ENOSTR] = TARGET_ENOSTR,
552 [ENODATA] = TARGET_ENODATA,
553 [ETIME] = TARGET_ETIME,
554 [ENOSR] = TARGET_ENOSR,
555 [ENONET] = TARGET_ENONET,
556 [ENOPKG] = TARGET_ENOPKG,
557 [EREMOTE] = TARGET_EREMOTE,
558 [ENOLINK] = TARGET_ENOLINK,
559 [EADV] = TARGET_EADV,
560 [ESRMNT] = TARGET_ESRMNT,
561 [ECOMM] = TARGET_ECOMM,
562 [EPROTO] = TARGET_EPROTO,
563 [EDOTDOT] = TARGET_EDOTDOT,
564 [EMULTIHOP] = TARGET_EMULTIHOP,
565 [EBADMSG] = TARGET_EBADMSG,
566 [ENAMETOOLONG] = TARGET_ENAMETOOLONG,
567 [EOVERFLOW] = TARGET_EOVERFLOW,
568 [ENOTUNIQ] = TARGET_ENOTUNIQ,
569 [EBADFD] = TARGET_EBADFD,
570 [EREMCHG] = TARGET_EREMCHG,
571 [ELIBACC] = TARGET_ELIBACC,
572 [ELIBBAD] = TARGET_ELIBBAD,
573 [ELIBSCN] = TARGET_ELIBSCN,
574 [ELIBMAX] = TARGET_ELIBMAX,
575 [ELIBEXEC] = TARGET_ELIBEXEC,
576 [EILSEQ] = TARGET_EILSEQ,
577 [ENOSYS] = TARGET_ENOSYS,
578 [ELOOP] = TARGET_ELOOP,
579 [ERESTART] = TARGET_ERESTART,
580 [ESTRPIPE] = TARGET_ESTRPIPE,
581 [ENOTEMPTY] = TARGET_ENOTEMPTY,
582 [EUSERS] = TARGET_EUSERS,
583 [ENOTSOCK] = TARGET_ENOTSOCK,
584 [EDESTADDRREQ] = TARGET_EDESTADDRREQ,
585 [EMSGSIZE] = TARGET_EMSGSIZE,
586 [EPROTOTYPE] = TARGET_EPROTOTYPE,
587 [ENOPROTOOPT] = TARGET_ENOPROTOOPT,
588 [EPROTONOSUPPORT] = TARGET_EPROTONOSUPPORT,
589 [ESOCKTNOSUPPORT] = TARGET_ESOCKTNOSUPPORT,
590 [EOPNOTSUPP] = TARGET_EOPNOTSUPP,
591 [EPFNOSUPPORT] = TARGET_EPFNOSUPPORT,
592 [EAFNOSUPPORT] = TARGET_EAFNOSUPPORT,
593 [EADDRINUSE] = TARGET_EADDRINUSE,
594 [EADDRNOTAVAIL] = TARGET_EADDRNOTAVAIL,
595 [ENETDOWN] = TARGET_ENETDOWN,
596 [ENETUNREACH] = TARGET_ENETUNREACH,
597 [ENETRESET] = TARGET_ENETRESET,
598 [ECONNABORTED] = TARGET_ECONNABORTED,
599 [ECONNRESET] = TARGET_ECONNRESET,
600 [ENOBUFS] = TARGET_ENOBUFS,
601 [EISCONN] = TARGET_EISCONN,
602 [ENOTCONN] = TARGET_ENOTCONN,
603 [EUCLEAN] = TARGET_EUCLEAN,
604 [ENOTNAM] = TARGET_ENOTNAM,
605 [ENAVAIL] = TARGET_ENAVAIL,
606 [EISNAM] = TARGET_EISNAM,
607 [EREMOTEIO] = TARGET_EREMOTEIO,
608 [ESHUTDOWN] = TARGET_ESHUTDOWN,
609 [ETOOMANYREFS] = TARGET_ETOOMANYREFS,
610 [ETIMEDOUT] = TARGET_ETIMEDOUT,
611 [ECONNREFUSED] = TARGET_ECONNREFUSED,
612 [EHOSTDOWN] = TARGET_EHOSTDOWN,
613 [EHOSTUNREACH] = TARGET_EHOSTUNREACH,
614 [EALREADY] = TARGET_EALREADY,
615 [EINPROGRESS] = TARGET_EINPROGRESS,
616 [ESTALE] = TARGET_ESTALE,
617 [ECANCELED] = TARGET_ECANCELED,
618 [ENOMEDIUM] = TARGET_ENOMEDIUM,
619 [EMEDIUMTYPE] = TARGET_EMEDIUMTYPE,
thsb7fe5db2007-07-23 15:37:46 +0000620#ifdef ENOKEY
ths637947f2007-06-01 12:09:19 +0000621 [ENOKEY] = TARGET_ENOKEY,
thsb7fe5db2007-07-23 15:37:46 +0000622#endif
623#ifdef EKEYEXPIRED
ths637947f2007-06-01 12:09:19 +0000624 [EKEYEXPIRED] = TARGET_EKEYEXPIRED,
thsb7fe5db2007-07-23 15:37:46 +0000625#endif
626#ifdef EKEYREVOKED
ths637947f2007-06-01 12:09:19 +0000627 [EKEYREVOKED] = TARGET_EKEYREVOKED,
thsb7fe5db2007-07-23 15:37:46 +0000628#endif
629#ifdef EKEYREJECTED
ths637947f2007-06-01 12:09:19 +0000630 [EKEYREJECTED] = TARGET_EKEYREJECTED,
thsb7fe5db2007-07-23 15:37:46 +0000631#endif
632#ifdef EOWNERDEAD
ths637947f2007-06-01 12:09:19 +0000633 [EOWNERDEAD] = TARGET_EOWNERDEAD,
thsb7fe5db2007-07-23 15:37:46 +0000634#endif
635#ifdef ENOTRECOVERABLE
ths637947f2007-06-01 12:09:19 +0000636 [ENOTRECOVERABLE] = TARGET_ENOTRECOVERABLE,
thsb7fe5db2007-07-23 15:37:46 +0000637#endif
thsb92c47c2007-11-01 00:07:38 +0000638};
ths637947f2007-06-01 12:09:19 +0000639
640static inline int host_to_target_errno(int err)
641{
642 if(host_to_target_errno_table[err])
643 return host_to_target_errno_table[err];
644 return err;
645}
646
thsb92c47c2007-11-01 00:07:38 +0000647static inline int target_to_host_errno(int err)
648{
649 if (target_to_host_errno_table[err])
650 return target_to_host_errno_table[err];
651 return err;
652}
653
blueswir1992f48a2007-10-14 16:27:31 +0000654static inline abi_long get_errno(abi_long ret)
bellard31e31b82003-02-18 22:55:36 +0000655{
656 if (ret == -1)
ths637947f2007-06-01 12:09:19 +0000657 return -host_to_target_errno(errno);
bellard31e31b82003-02-18 22:55:36 +0000658 else
659 return ret;
660}
661
blueswir1992f48a2007-10-14 16:27:31 +0000662static inline int is_error(abi_long ret)
bellard31e31b82003-02-18 22:55:36 +0000663{
blueswir1992f48a2007-10-14 16:27:31 +0000664 return (abi_ulong)ret >= (abi_ulong)(-4096);
bellard31e31b82003-02-18 22:55:36 +0000665}
666
thsb92c47c2007-11-01 00:07:38 +0000667char *target_strerror(int err)
668{
669 return strerror(target_to_host_errno(err));
670}
671
blueswir1992f48a2007-10-14 16:27:31 +0000672static abi_ulong target_brk;
673static abi_ulong target_original_brk;
bellard31e31b82003-02-18 22:55:36 +0000674
blueswir1992f48a2007-10-14 16:27:31 +0000675void target_set_brk(abi_ulong new_brk)
bellard31e31b82003-02-18 22:55:36 +0000676{
blueswir14c1de732007-07-07 20:45:44 +0000677 target_original_brk = target_brk = HOST_PAGE_ALIGN(new_brk);
bellard31e31b82003-02-18 22:55:36 +0000678}
679
ths0da46a62007-10-20 20:23:07 +0000680/* do_brk() must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +0000681abi_long do_brk(abi_ulong new_brk)
bellard31e31b82003-02-18 22:55:36 +0000682{
blueswir1992f48a2007-10-14 16:27:31 +0000683 abi_ulong brk_page;
684 abi_long mapped_addr;
bellard31e31b82003-02-18 22:55:36 +0000685 int new_alloc_size;
686
687 if (!new_brk)
pbrook53a59602006-03-25 19:31:22 +0000688 return target_brk;
bellard31e31b82003-02-18 22:55:36 +0000689 if (new_brk < target_original_brk)
balrog7ab240a2008-04-26 12:17:34 +0000690 return target_brk;
ths3b46e622007-09-17 08:09:54 +0000691
pbrook53a59602006-03-25 19:31:22 +0000692 brk_page = HOST_PAGE_ALIGN(target_brk);
bellard31e31b82003-02-18 22:55:36 +0000693
694 /* If the new brk is less than this, set it and we're done... */
695 if (new_brk < brk_page) {
696 target_brk = new_brk;
pbrook53a59602006-03-25 19:31:22 +0000697 return target_brk;
bellard31e31b82003-02-18 22:55:36 +0000698 }
699
700 /* We need to allocate more memory after the brk... */
bellard54936002003-05-13 00:25:15 +0000701 new_alloc_size = HOST_PAGE_ALIGN(new_brk - brk_page + 1);
ths5fafdf22007-09-16 21:08:06 +0000702 mapped_addr = get_errno(target_mmap(brk_page, new_alloc_size,
bellard54936002003-05-13 00:25:15 +0000703 PROT_READ|PROT_WRITE,
704 MAP_ANON|MAP_FIXED|MAP_PRIVATE, 0, 0));
balrog7ab240a2008-04-26 12:17:34 +0000705
706 if (!is_error(mapped_addr))
bellard31e31b82003-02-18 22:55:36 +0000707 target_brk = new_brk;
balrog7ab240a2008-04-26 12:17:34 +0000708
709 return target_brk;
bellard31e31b82003-02-18 22:55:36 +0000710}
711
ths26edcf42007-12-09 02:25:24 +0000712static inline abi_long copy_from_user_fdset(fd_set *fds,
713 abi_ulong target_fds_addr,
714 int n)
bellard31e31b82003-02-18 22:55:36 +0000715{
ths26edcf42007-12-09 02:25:24 +0000716 int i, nw, j, k;
717 abi_ulong b, *target_fds;
718
719 nw = (n + TARGET_ABI_BITS - 1) / TARGET_ABI_BITS;
720 if (!(target_fds = lock_user(VERIFY_READ,
721 target_fds_addr,
722 sizeof(abi_ulong) * nw,
723 1)))
724 return -TARGET_EFAULT;
725
726 FD_ZERO(fds);
727 k = 0;
728 for (i = 0; i < nw; i++) {
729 /* grab the abi_ulong */
730 __get_user(b, &target_fds[i]);
731 for (j = 0; j < TARGET_ABI_BITS; j++) {
732 /* check the bit inside the abi_ulong */
733 if ((b >> j) & 1)
734 FD_SET(k, fds);
735 k++;
bellard31e31b82003-02-18 22:55:36 +0000736 }
bellard31e31b82003-02-18 22:55:36 +0000737 }
ths26edcf42007-12-09 02:25:24 +0000738
739 unlock_user(target_fds, target_fds_addr, 0);
740
741 return 0;
bellard31e31b82003-02-18 22:55:36 +0000742}
743
ths26edcf42007-12-09 02:25:24 +0000744static inline abi_long copy_to_user_fdset(abi_ulong target_fds_addr,
745 const fd_set *fds,
746 int n)
bellard31e31b82003-02-18 22:55:36 +0000747{
bellard31e31b82003-02-18 22:55:36 +0000748 int i, nw, j, k;
blueswir1992f48a2007-10-14 16:27:31 +0000749 abi_long v;
ths26edcf42007-12-09 02:25:24 +0000750 abi_ulong *target_fds;
bellard31e31b82003-02-18 22:55:36 +0000751
ths26edcf42007-12-09 02:25:24 +0000752 nw = (n + TARGET_ABI_BITS - 1) / TARGET_ABI_BITS;
753 if (!(target_fds = lock_user(VERIFY_WRITE,
754 target_fds_addr,
755 sizeof(abi_ulong) * nw,
756 0)))
757 return -TARGET_EFAULT;
758
759 k = 0;
760 for (i = 0; i < nw; i++) {
761 v = 0;
762 for (j = 0; j < TARGET_ABI_BITS; j++) {
763 v |= ((FD_ISSET(k, fds) != 0) << j);
764 k++;
bellard31e31b82003-02-18 22:55:36 +0000765 }
ths26edcf42007-12-09 02:25:24 +0000766 __put_user(v, &target_fds[i]);
bellard31e31b82003-02-18 22:55:36 +0000767 }
ths26edcf42007-12-09 02:25:24 +0000768
769 unlock_user(target_fds, target_fds_addr, sizeof(abi_ulong) * nw);
770
771 return 0;
bellard31e31b82003-02-18 22:55:36 +0000772}
773
bellardc596ed12003-07-13 17:32:31 +0000774#if defined(__alpha__)
775#define HOST_HZ 1024
776#else
777#define HOST_HZ 100
778#endif
779
blueswir1992f48a2007-10-14 16:27:31 +0000780static inline abi_long host_to_target_clock_t(long ticks)
bellardc596ed12003-07-13 17:32:31 +0000781{
782#if HOST_HZ == TARGET_HZ
783 return ticks;
784#else
785 return ((int64_t)ticks * TARGET_HZ) / HOST_HZ;
786#endif
787}
788
bellard579a97f2007-11-11 14:26:47 +0000789static inline abi_long host_to_target_rusage(abi_ulong target_addr,
790 const struct rusage *rusage)
bellardb4091862003-05-16 15:39:34 +0000791{
pbrook53a59602006-03-25 19:31:22 +0000792 struct target_rusage *target_rusage;
793
bellard579a97f2007-11-11 14:26:47 +0000794 if (!lock_user_struct(VERIFY_WRITE, target_rusage, target_addr, 0))
795 return -TARGET_EFAULT;
bellardb4091862003-05-16 15:39:34 +0000796 target_rusage->ru_utime.tv_sec = tswapl(rusage->ru_utime.tv_sec);
797 target_rusage->ru_utime.tv_usec = tswapl(rusage->ru_utime.tv_usec);
798 target_rusage->ru_stime.tv_sec = tswapl(rusage->ru_stime.tv_sec);
799 target_rusage->ru_stime.tv_usec = tswapl(rusage->ru_stime.tv_usec);
800 target_rusage->ru_maxrss = tswapl(rusage->ru_maxrss);
801 target_rusage->ru_ixrss = tswapl(rusage->ru_ixrss);
802 target_rusage->ru_idrss = tswapl(rusage->ru_idrss);
803 target_rusage->ru_isrss = tswapl(rusage->ru_isrss);
804 target_rusage->ru_minflt = tswapl(rusage->ru_minflt);
805 target_rusage->ru_majflt = tswapl(rusage->ru_majflt);
806 target_rusage->ru_nswap = tswapl(rusage->ru_nswap);
807 target_rusage->ru_inblock = tswapl(rusage->ru_inblock);
808 target_rusage->ru_oublock = tswapl(rusage->ru_oublock);
809 target_rusage->ru_msgsnd = tswapl(rusage->ru_msgsnd);
810 target_rusage->ru_msgrcv = tswapl(rusage->ru_msgrcv);
811 target_rusage->ru_nsignals = tswapl(rusage->ru_nsignals);
812 target_rusage->ru_nvcsw = tswapl(rusage->ru_nvcsw);
813 target_rusage->ru_nivcsw = tswapl(rusage->ru_nivcsw);
pbrook53a59602006-03-25 19:31:22 +0000814 unlock_user_struct(target_rusage, target_addr, 1);
bellard579a97f2007-11-11 14:26:47 +0000815
816 return 0;
bellardb4091862003-05-16 15:39:34 +0000817}
818
ths788f5ec2007-12-09 02:37:05 +0000819static inline abi_long copy_from_user_timeval(struct timeval *tv,
820 abi_ulong target_tv_addr)
bellard31e31b82003-02-18 22:55:36 +0000821{
pbrook53a59602006-03-25 19:31:22 +0000822 struct target_timeval *target_tv;
823
ths788f5ec2007-12-09 02:37:05 +0000824 if (!lock_user_struct(VERIFY_READ, target_tv, target_tv_addr, 1))
bellard579a97f2007-11-11 14:26:47 +0000825 return -TARGET_EFAULT;
ths788f5ec2007-12-09 02:37:05 +0000826
827 __get_user(tv->tv_sec, &target_tv->tv_sec);
828 __get_user(tv->tv_usec, &target_tv->tv_usec);
829
830 unlock_user_struct(target_tv, target_tv_addr, 0);
bellard579a97f2007-11-11 14:26:47 +0000831
832 return 0;
bellard31e31b82003-02-18 22:55:36 +0000833}
834
ths788f5ec2007-12-09 02:37:05 +0000835static inline abi_long copy_to_user_timeval(abi_ulong target_tv_addr,
836 const struct timeval *tv)
bellard31e31b82003-02-18 22:55:36 +0000837{
pbrook53a59602006-03-25 19:31:22 +0000838 struct target_timeval *target_tv;
839
ths788f5ec2007-12-09 02:37:05 +0000840 if (!lock_user_struct(VERIFY_WRITE, target_tv, target_tv_addr, 0))
bellard579a97f2007-11-11 14:26:47 +0000841 return -TARGET_EFAULT;
ths788f5ec2007-12-09 02:37:05 +0000842
843 __put_user(tv->tv_sec, &target_tv->tv_sec);
844 __put_user(tv->tv_usec, &target_tv->tv_usec);
845
846 unlock_user_struct(target_tv, target_tv_addr, 1);
bellard579a97f2007-11-11 14:26:47 +0000847
848 return 0;
bellard31e31b82003-02-18 22:55:36 +0000849}
850
aurel3224e10032009-04-15 16:11:43 +0000851static inline abi_long copy_from_user_mq_attr(struct mq_attr *attr,
852 abi_ulong target_mq_attr_addr)
853{
854 struct target_mq_attr *target_mq_attr;
855
856 if (!lock_user_struct(VERIFY_READ, target_mq_attr,
857 target_mq_attr_addr, 1))
858 return -TARGET_EFAULT;
859
860 __get_user(attr->mq_flags, &target_mq_attr->mq_flags);
861 __get_user(attr->mq_maxmsg, &target_mq_attr->mq_maxmsg);
862 __get_user(attr->mq_msgsize, &target_mq_attr->mq_msgsize);
863 __get_user(attr->mq_curmsgs, &target_mq_attr->mq_curmsgs);
864
865 unlock_user_struct(target_mq_attr, target_mq_attr_addr, 0);
866
867 return 0;
868}
869
870static inline abi_long copy_to_user_mq_attr(abi_ulong target_mq_attr_addr,
871 const struct mq_attr *attr)
872{
873 struct target_mq_attr *target_mq_attr;
874
875 if (!lock_user_struct(VERIFY_WRITE, target_mq_attr,
876 target_mq_attr_addr, 0))
877 return -TARGET_EFAULT;
878
879 __put_user(attr->mq_flags, &target_mq_attr->mq_flags);
880 __put_user(attr->mq_maxmsg, &target_mq_attr->mq_maxmsg);
881 __put_user(attr->mq_msgsize, &target_mq_attr->mq_msgsize);
882 __put_user(attr->mq_curmsgs, &target_mq_attr->mq_curmsgs);
883
884 unlock_user_struct(target_mq_attr, target_mq_attr_addr, 1);
885
886 return 0;
887}
bellard31e31b82003-02-18 22:55:36 +0000888
ths0da46a62007-10-20 20:23:07 +0000889/* do_select() must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +0000890static abi_long do_select(int n,
ths26edcf42007-12-09 02:25:24 +0000891 abi_ulong rfd_addr, abi_ulong wfd_addr,
892 abi_ulong efd_addr, abi_ulong target_tv_addr)
bellard31e31b82003-02-18 22:55:36 +0000893{
894 fd_set rfds, wfds, efds;
895 fd_set *rfds_ptr, *wfds_ptr, *efds_ptr;
896 struct timeval tv, *tv_ptr;
blueswir1992f48a2007-10-14 16:27:31 +0000897 abi_long ret;
bellard31e31b82003-02-18 22:55:36 +0000898
ths26edcf42007-12-09 02:25:24 +0000899 if (rfd_addr) {
900 if (copy_from_user_fdset(&rfds, rfd_addr, n))
901 return -TARGET_EFAULT;
902 rfds_ptr = &rfds;
pbrook53a59602006-03-25 19:31:22 +0000903 } else {
pbrook53a59602006-03-25 19:31:22 +0000904 rfds_ptr = NULL;
905 }
ths26edcf42007-12-09 02:25:24 +0000906 if (wfd_addr) {
907 if (copy_from_user_fdset(&wfds, wfd_addr, n))
908 return -TARGET_EFAULT;
909 wfds_ptr = &wfds;
pbrook53a59602006-03-25 19:31:22 +0000910 } else {
pbrook53a59602006-03-25 19:31:22 +0000911 wfds_ptr = NULL;
912 }
ths26edcf42007-12-09 02:25:24 +0000913 if (efd_addr) {
914 if (copy_from_user_fdset(&efds, efd_addr, n))
915 return -TARGET_EFAULT;
916 efds_ptr = &efds;
pbrook53a59602006-03-25 19:31:22 +0000917 } else {
pbrook53a59602006-03-25 19:31:22 +0000918 efds_ptr = NULL;
919 }
ths3b46e622007-09-17 08:09:54 +0000920
ths26edcf42007-12-09 02:25:24 +0000921 if (target_tv_addr) {
ths788f5ec2007-12-09 02:37:05 +0000922 if (copy_from_user_timeval(&tv, target_tv_addr))
923 return -TARGET_EFAULT;
bellard31e31b82003-02-18 22:55:36 +0000924 tv_ptr = &tv;
925 } else {
926 tv_ptr = NULL;
927 }
ths26edcf42007-12-09 02:25:24 +0000928
bellard31e31b82003-02-18 22:55:36 +0000929 ret = get_errno(select(n, rfds_ptr, wfds_ptr, efds_ptr, tv_ptr));
pbrook53a59602006-03-25 19:31:22 +0000930
ths26edcf42007-12-09 02:25:24 +0000931 if (!is_error(ret)) {
932 if (rfd_addr && copy_to_user_fdset(rfd_addr, &rfds, n))
933 return -TARGET_EFAULT;
934 if (wfd_addr && copy_to_user_fdset(wfd_addr, &wfds, n))
935 return -TARGET_EFAULT;
936 if (efd_addr && copy_to_user_fdset(efd_addr, &efds, n))
937 return -TARGET_EFAULT;
bellard31e31b82003-02-18 22:55:36 +0000938
ths788f5ec2007-12-09 02:37:05 +0000939 if (target_tv_addr && copy_to_user_timeval(target_tv_addr, &tv))
940 return -TARGET_EFAULT;
bellard31e31b82003-02-18 22:55:36 +0000941 }
bellard579a97f2007-11-11 14:26:47 +0000942
bellard31e31b82003-02-18 22:55:36 +0000943 return ret;
944}
945
bellard579a97f2007-11-11 14:26:47 +0000946static inline abi_long target_to_host_sockaddr(struct sockaddr *addr,
947 abi_ulong target_addr,
948 socklen_t len)
bellard7854b052003-03-29 17:22:23 +0000949{
aurel32607175e2009-04-15 16:11:59 +0000950 const socklen_t unix_maxlen = sizeof (struct sockaddr_un);
951 sa_family_t sa_family;
pbrook53a59602006-03-25 19:31:22 +0000952 struct target_sockaddr *target_saddr;
953
bellard579a97f2007-11-11 14:26:47 +0000954 target_saddr = lock_user(VERIFY_READ, target_addr, len, 1);
955 if (!target_saddr)
956 return -TARGET_EFAULT;
aurel32607175e2009-04-15 16:11:59 +0000957
958 sa_family = tswap16(target_saddr->sa_family);
959
960 /* Oops. The caller might send a incomplete sun_path; sun_path
961 * must be terminated by \0 (see the manual page), but
962 * unfortunately it is quite common to specify sockaddr_un
963 * length as "strlen(x->sun_path)" while it should be
964 * "strlen(...) + 1". We'll fix that here if needed.
965 * Linux kernel has a similar feature.
966 */
967
968 if (sa_family == AF_UNIX) {
969 if (len < unix_maxlen && len > 0) {
970 char *cp = (char*)target_saddr;
971
972 if ( cp[len-1] && !cp[len] )
973 len++;
974 }
975 if (len > unix_maxlen)
976 len = unix_maxlen;
977 }
978
pbrook53a59602006-03-25 19:31:22 +0000979 memcpy(addr, target_saddr, len);
aurel32607175e2009-04-15 16:11:59 +0000980 addr->sa_family = sa_family;
pbrook53a59602006-03-25 19:31:22 +0000981 unlock_user(target_saddr, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +0000982
983 return 0;
bellard7854b052003-03-29 17:22:23 +0000984}
985
bellard579a97f2007-11-11 14:26:47 +0000986static inline abi_long host_to_target_sockaddr(abi_ulong target_addr,
987 struct sockaddr *addr,
988 socklen_t len)
bellard7854b052003-03-29 17:22:23 +0000989{
pbrook53a59602006-03-25 19:31:22 +0000990 struct target_sockaddr *target_saddr;
991
bellard579a97f2007-11-11 14:26:47 +0000992 target_saddr = lock_user(VERIFY_WRITE, target_addr, len, 0);
993 if (!target_saddr)
994 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +0000995 memcpy(target_saddr, addr, len);
996 target_saddr->sa_family = tswap16(addr->sa_family);
997 unlock_user(target_saddr, target_addr, len);
bellard579a97f2007-11-11 14:26:47 +0000998
999 return 0;
bellard7854b052003-03-29 17:22:23 +00001000}
1001
pbrook53a59602006-03-25 19:31:22 +00001002/* ??? Should this also swap msgh->name? */
bellard5a4a8982007-11-11 17:39:18 +00001003static inline abi_long target_to_host_cmsg(struct msghdr *msgh,
1004 struct target_msghdr *target_msgh)
bellard7854b052003-03-29 17:22:23 +00001005{
1006 struct cmsghdr *cmsg = CMSG_FIRSTHDR(msgh);
bellard5a4a8982007-11-11 17:39:18 +00001007 abi_long msg_controllen;
1008 abi_ulong target_cmsg_addr;
1009 struct target_cmsghdr *target_cmsg;
bellard7854b052003-03-29 17:22:23 +00001010 socklen_t space = 0;
bellard5a4a8982007-11-11 17:39:18 +00001011
1012 msg_controllen = tswapl(target_msgh->msg_controllen);
1013 if (msg_controllen < sizeof (struct target_cmsghdr))
1014 goto the_end;
1015 target_cmsg_addr = tswapl(target_msgh->msg_control);
1016 target_cmsg = lock_user(VERIFY_READ, target_cmsg_addr, msg_controllen, 1);
1017 if (!target_cmsg)
1018 return -TARGET_EFAULT;
bellard7854b052003-03-29 17:22:23 +00001019
1020 while (cmsg && target_cmsg) {
1021 void *data = CMSG_DATA(cmsg);
1022 void *target_data = TARGET_CMSG_DATA(target_cmsg);
1023
ths5fafdf22007-09-16 21:08:06 +00001024 int len = tswapl(target_cmsg->cmsg_len)
bellard7854b052003-03-29 17:22:23 +00001025 - TARGET_CMSG_ALIGN(sizeof (struct target_cmsghdr));
1026
1027 space += CMSG_SPACE(len);
1028 if (space > msgh->msg_controllen) {
1029 space -= CMSG_SPACE(len);
bellard31febb72005-12-18 20:03:27 +00001030 gemu_log("Host cmsg overflow\n");
bellard7854b052003-03-29 17:22:23 +00001031 break;
1032 }
1033
1034 cmsg->cmsg_level = tswap32(target_cmsg->cmsg_level);
1035 cmsg->cmsg_type = tswap32(target_cmsg->cmsg_type);
1036 cmsg->cmsg_len = CMSG_LEN(len);
1037
bellard3532fa72006-06-24 15:06:03 +00001038 if (cmsg->cmsg_level != TARGET_SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS) {
bellard7854b052003-03-29 17:22:23 +00001039 gemu_log("Unsupported ancillary data: %d/%d\n", cmsg->cmsg_level, cmsg->cmsg_type);
1040 memcpy(data, target_data, len);
1041 } else {
1042 int *fd = (int *)data;
1043 int *target_fd = (int *)target_data;
1044 int i, numfds = len / sizeof(int);
1045
1046 for (i = 0; i < numfds; i++)
1047 fd[i] = tswap32(target_fd[i]);
1048 }
1049
1050 cmsg = CMSG_NXTHDR(msgh, cmsg);
1051 target_cmsg = TARGET_CMSG_NXTHDR(target_msgh, target_cmsg);
1052 }
bellard5a4a8982007-11-11 17:39:18 +00001053 unlock_user(target_cmsg, target_cmsg_addr, 0);
1054 the_end:
bellard7854b052003-03-29 17:22:23 +00001055 msgh->msg_controllen = space;
bellard5a4a8982007-11-11 17:39:18 +00001056 return 0;
bellard7854b052003-03-29 17:22:23 +00001057}
1058
pbrook53a59602006-03-25 19:31:22 +00001059/* ??? Should this also swap msgh->name? */
bellard5a4a8982007-11-11 17:39:18 +00001060static inline abi_long host_to_target_cmsg(struct target_msghdr *target_msgh,
1061 struct msghdr *msgh)
bellard7854b052003-03-29 17:22:23 +00001062{
1063 struct cmsghdr *cmsg = CMSG_FIRSTHDR(msgh);
bellard5a4a8982007-11-11 17:39:18 +00001064 abi_long msg_controllen;
1065 abi_ulong target_cmsg_addr;
1066 struct target_cmsghdr *target_cmsg;
bellard7854b052003-03-29 17:22:23 +00001067 socklen_t space = 0;
1068
bellard5a4a8982007-11-11 17:39:18 +00001069 msg_controllen = tswapl(target_msgh->msg_controllen);
1070 if (msg_controllen < sizeof (struct target_cmsghdr))
1071 goto the_end;
1072 target_cmsg_addr = tswapl(target_msgh->msg_control);
1073 target_cmsg = lock_user(VERIFY_WRITE, target_cmsg_addr, msg_controllen, 0);
1074 if (!target_cmsg)
1075 return -TARGET_EFAULT;
1076
bellard7854b052003-03-29 17:22:23 +00001077 while (cmsg && target_cmsg) {
1078 void *data = CMSG_DATA(cmsg);
1079 void *target_data = TARGET_CMSG_DATA(target_cmsg);
1080
1081 int len = cmsg->cmsg_len - CMSG_ALIGN(sizeof (struct cmsghdr));
1082
1083 space += TARGET_CMSG_SPACE(len);
bellard5a4a8982007-11-11 17:39:18 +00001084 if (space > msg_controllen) {
bellard7854b052003-03-29 17:22:23 +00001085 space -= TARGET_CMSG_SPACE(len);
bellard31febb72005-12-18 20:03:27 +00001086 gemu_log("Target cmsg overflow\n");
bellard7854b052003-03-29 17:22:23 +00001087 break;
1088 }
1089
1090 target_cmsg->cmsg_level = tswap32(cmsg->cmsg_level);
1091 target_cmsg->cmsg_type = tswap32(cmsg->cmsg_type);
1092 target_cmsg->cmsg_len = tswapl(TARGET_CMSG_LEN(len));
1093
bellard3532fa72006-06-24 15:06:03 +00001094 if (cmsg->cmsg_level != TARGET_SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS) {
bellard7854b052003-03-29 17:22:23 +00001095 gemu_log("Unsupported ancillary data: %d/%d\n", cmsg->cmsg_level, cmsg->cmsg_type);
1096 memcpy(target_data, data, len);
1097 } else {
1098 int *fd = (int *)data;
1099 int *target_fd = (int *)target_data;
1100 int i, numfds = len / sizeof(int);
1101
1102 for (i = 0; i < numfds; i++)
1103 target_fd[i] = tswap32(fd[i]);
1104 }
1105
1106 cmsg = CMSG_NXTHDR(msgh, cmsg);
1107 target_cmsg = TARGET_CMSG_NXTHDR(target_msgh, target_cmsg);
1108 }
bellard5a4a8982007-11-11 17:39:18 +00001109 unlock_user(target_cmsg, target_cmsg_addr, space);
1110 the_end:
1111 target_msgh->msg_controllen = tswapl(space);
1112 return 0;
bellard7854b052003-03-29 17:22:23 +00001113}
1114
ths0da46a62007-10-20 20:23:07 +00001115/* do_setsockopt() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001116static abi_long do_setsockopt(int sockfd, int level, int optname,
bellard2f619692007-11-16 10:46:05 +00001117 abi_ulong optval_addr, socklen_t optlen)
bellard7854b052003-03-29 17:22:23 +00001118{
blueswir1992f48a2007-10-14 16:27:31 +00001119 abi_long ret;
j_mayer32407102007-09-26 23:01:49 +00001120 int val;
ths3b46e622007-09-17 08:09:54 +00001121
bellard8853f862004-02-22 14:57:26 +00001122 switch(level) {
1123 case SOL_TCP:
bellard7854b052003-03-29 17:22:23 +00001124 /* TCP options all take an 'int' value. */
bellard7854b052003-03-29 17:22:23 +00001125 if (optlen < sizeof(uint32_t))
ths0da46a62007-10-20 20:23:07 +00001126 return -TARGET_EINVAL;
ths3b46e622007-09-17 08:09:54 +00001127
bellard2f619692007-11-16 10:46:05 +00001128 if (get_user_u32(val, optval_addr))
1129 return -TARGET_EFAULT;
bellard8853f862004-02-22 14:57:26 +00001130 ret = get_errno(setsockopt(sockfd, level, optname, &val, sizeof(val)));
1131 break;
1132 case SOL_IP:
1133 switch(optname) {
bellard2efbe912005-07-23 15:10:20 +00001134 case IP_TOS:
1135 case IP_TTL:
bellard8853f862004-02-22 14:57:26 +00001136 case IP_HDRINCL:
bellard2efbe912005-07-23 15:10:20 +00001137 case IP_ROUTER_ALERT:
1138 case IP_RECVOPTS:
1139 case IP_RETOPTS:
1140 case IP_PKTINFO:
1141 case IP_MTU_DISCOVER:
1142 case IP_RECVERR:
1143 case IP_RECVTOS:
1144#ifdef IP_FREEBIND
1145 case IP_FREEBIND:
1146#endif
1147 case IP_MULTICAST_TTL:
1148 case IP_MULTICAST_LOOP:
bellard8853f862004-02-22 14:57:26 +00001149 val = 0;
1150 if (optlen >= sizeof(uint32_t)) {
bellard2f619692007-11-16 10:46:05 +00001151 if (get_user_u32(val, optval_addr))
1152 return -TARGET_EFAULT;
bellard8853f862004-02-22 14:57:26 +00001153 } else if (optlen >= 1) {
bellard2f619692007-11-16 10:46:05 +00001154 if (get_user_u8(val, optval_addr))
1155 return -TARGET_EFAULT;
bellard8853f862004-02-22 14:57:26 +00001156 }
1157 ret = get_errno(setsockopt(sockfd, level, optname, &val, sizeof(val)));
1158 break;
1159 default:
1160 goto unimplemented;
1161 }
1162 break;
bellard3532fa72006-06-24 15:06:03 +00001163 case TARGET_SOL_SOCKET:
bellard8853f862004-02-22 14:57:26 +00001164 switch (optname) {
1165 /* Options with 'int' argument. */
bellard3532fa72006-06-24 15:06:03 +00001166 case TARGET_SO_DEBUG:
1167 optname = SO_DEBUG;
1168 break;
1169 case TARGET_SO_REUSEADDR:
1170 optname = SO_REUSEADDR;
1171 break;
1172 case TARGET_SO_TYPE:
1173 optname = SO_TYPE;
1174 break;
1175 case TARGET_SO_ERROR:
1176 optname = SO_ERROR;
1177 break;
1178 case TARGET_SO_DONTROUTE:
1179 optname = SO_DONTROUTE;
1180 break;
1181 case TARGET_SO_BROADCAST:
1182 optname = SO_BROADCAST;
1183 break;
1184 case TARGET_SO_SNDBUF:
1185 optname = SO_SNDBUF;
1186 break;
1187 case TARGET_SO_RCVBUF:
1188 optname = SO_RCVBUF;
1189 break;
1190 case TARGET_SO_KEEPALIVE:
1191 optname = SO_KEEPALIVE;
1192 break;
1193 case TARGET_SO_OOBINLINE:
1194 optname = SO_OOBINLINE;
1195 break;
1196 case TARGET_SO_NO_CHECK:
1197 optname = SO_NO_CHECK;
1198 break;
1199 case TARGET_SO_PRIORITY:
1200 optname = SO_PRIORITY;
1201 break;
bellard5e83e8e2005-03-01 22:32:06 +00001202#ifdef SO_BSDCOMPAT
bellard3532fa72006-06-24 15:06:03 +00001203 case TARGET_SO_BSDCOMPAT:
1204 optname = SO_BSDCOMPAT;
1205 break;
bellard5e83e8e2005-03-01 22:32:06 +00001206#endif
bellard3532fa72006-06-24 15:06:03 +00001207 case TARGET_SO_PASSCRED:
1208 optname = SO_PASSCRED;
1209 break;
1210 case TARGET_SO_TIMESTAMP:
1211 optname = SO_TIMESTAMP;
1212 break;
1213 case TARGET_SO_RCVLOWAT:
1214 optname = SO_RCVLOWAT;
1215 break;
1216 case TARGET_SO_RCVTIMEO:
1217 optname = SO_RCVTIMEO;
1218 break;
1219 case TARGET_SO_SNDTIMEO:
1220 optname = SO_SNDTIMEO;
1221 break;
bellard8853f862004-02-22 14:57:26 +00001222 break;
1223 default:
1224 goto unimplemented;
1225 }
bellard3532fa72006-06-24 15:06:03 +00001226 if (optlen < sizeof(uint32_t))
bellard2f619692007-11-16 10:46:05 +00001227 return -TARGET_EINVAL;
bellard3532fa72006-06-24 15:06:03 +00001228
bellard2f619692007-11-16 10:46:05 +00001229 if (get_user_u32(val, optval_addr))
1230 return -TARGET_EFAULT;
bellard3532fa72006-06-24 15:06:03 +00001231 ret = get_errno(setsockopt(sockfd, SOL_SOCKET, optname, &val, sizeof(val)));
bellard8853f862004-02-22 14:57:26 +00001232 break;
bellard7854b052003-03-29 17:22:23 +00001233 default:
bellard8853f862004-02-22 14:57:26 +00001234 unimplemented:
1235 gemu_log("Unsupported setsockopt level=%d optname=%d \n", level, optname);
ths6fa13c12007-12-18 02:41:04 +00001236 ret = -TARGET_ENOPROTOOPT;
bellard7854b052003-03-29 17:22:23 +00001237 }
bellard8853f862004-02-22 14:57:26 +00001238 return ret;
bellard7854b052003-03-29 17:22:23 +00001239}
1240
ths0da46a62007-10-20 20:23:07 +00001241/* do_getsockopt() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001242static abi_long do_getsockopt(int sockfd, int level, int optname,
bellard2f619692007-11-16 10:46:05 +00001243 abi_ulong optval_addr, abi_ulong optlen)
bellard7854b052003-03-29 17:22:23 +00001244{
blueswir1992f48a2007-10-14 16:27:31 +00001245 abi_long ret;
blueswir1b55266b2008-09-20 08:07:15 +00001246 int len, val;
1247 socklen_t lv;
bellard8853f862004-02-22 14:57:26 +00001248
1249 switch(level) {
bellard3532fa72006-06-24 15:06:03 +00001250 case TARGET_SOL_SOCKET:
1251 level = SOL_SOCKET;
bellard8853f862004-02-22 14:57:26 +00001252 switch (optname) {
bellard3532fa72006-06-24 15:06:03 +00001253 case TARGET_SO_LINGER:
1254 case TARGET_SO_RCVTIMEO:
1255 case TARGET_SO_SNDTIMEO:
1256 case TARGET_SO_PEERCRED:
1257 case TARGET_SO_PEERNAME:
bellard8853f862004-02-22 14:57:26 +00001258 /* These don't just return a single integer */
1259 goto unimplemented;
1260 default:
bellard2efbe912005-07-23 15:10:20 +00001261 goto int_case;
1262 }
1263 break;
1264 case SOL_TCP:
1265 /* TCP options all take an 'int' value. */
1266 int_case:
bellard2f619692007-11-16 10:46:05 +00001267 if (get_user_u32(len, optlen))
1268 return -TARGET_EFAULT;
bellard2efbe912005-07-23 15:10:20 +00001269 if (len < 0)
ths0da46a62007-10-20 20:23:07 +00001270 return -TARGET_EINVAL;
bellard2efbe912005-07-23 15:10:20 +00001271 lv = sizeof(int);
1272 ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
1273 if (ret < 0)
1274 return ret;
1275 val = tswap32(val);
1276 if (len > lv)
1277 len = lv;
bellard2f619692007-11-16 10:46:05 +00001278 if (len == 4) {
1279 if (put_user_u32(val, optval_addr))
1280 return -TARGET_EFAULT;
1281 } else {
1282 if (put_user_u8(val, optval_addr))
1283 return -TARGET_EFAULT;
1284 }
1285 if (put_user_u32(len, optlen))
1286 return -TARGET_EFAULT;
bellard2efbe912005-07-23 15:10:20 +00001287 break;
1288 case SOL_IP:
1289 switch(optname) {
1290 case IP_TOS:
1291 case IP_TTL:
1292 case IP_HDRINCL:
1293 case IP_ROUTER_ALERT:
1294 case IP_RECVOPTS:
1295 case IP_RETOPTS:
1296 case IP_PKTINFO:
1297 case IP_MTU_DISCOVER:
1298 case IP_RECVERR:
1299 case IP_RECVTOS:
1300#ifdef IP_FREEBIND
1301 case IP_FREEBIND:
1302#endif
1303 case IP_MULTICAST_TTL:
1304 case IP_MULTICAST_LOOP:
bellard2f619692007-11-16 10:46:05 +00001305 if (get_user_u32(len, optlen))
1306 return -TARGET_EFAULT;
bellard8853f862004-02-22 14:57:26 +00001307 if (len < 0)
ths0da46a62007-10-20 20:23:07 +00001308 return -TARGET_EINVAL;
bellard8853f862004-02-22 14:57:26 +00001309 lv = sizeof(int);
1310 ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
1311 if (ret < 0)
1312 return ret;
bellard2efbe912005-07-23 15:10:20 +00001313 if (len < sizeof(int) && len > 0 && val >= 0 && val < 255) {
bellard2efbe912005-07-23 15:10:20 +00001314 len = 1;
bellard2f619692007-11-16 10:46:05 +00001315 if (put_user_u32(len, optlen)
1316 || put_user_u8(val, optval_addr))
1317 return -TARGET_EFAULT;
bellard2efbe912005-07-23 15:10:20 +00001318 } else {
bellard2efbe912005-07-23 15:10:20 +00001319 if (len > sizeof(int))
1320 len = sizeof(int);
bellard2f619692007-11-16 10:46:05 +00001321 if (put_user_u32(len, optlen)
1322 || put_user_u32(val, optval_addr))
1323 return -TARGET_EFAULT;
bellard2efbe912005-07-23 15:10:20 +00001324 }
bellard8853f862004-02-22 14:57:26 +00001325 break;
bellard2efbe912005-07-23 15:10:20 +00001326 default:
thsc02f4992007-12-18 02:39:59 +00001327 ret = -TARGET_ENOPROTOOPT;
1328 break;
bellard8853f862004-02-22 14:57:26 +00001329 }
1330 break;
1331 default:
1332 unimplemented:
1333 gemu_log("getsockopt level=%d optname=%d not yet supported\n",
1334 level, optname);
thsc02f4992007-12-18 02:39:59 +00001335 ret = -TARGET_EOPNOTSUPP;
bellard8853f862004-02-22 14:57:26 +00001336 break;
1337 }
1338 return ret;
bellard7854b052003-03-29 17:22:23 +00001339}
1340
bellard579a97f2007-11-11 14:26:47 +00001341/* FIXME
1342 * lock_iovec()/unlock_iovec() have a return code of 0 for success where
1343 * other lock functions have a return code of 0 for failure.
1344 */
1345static abi_long lock_iovec(int type, struct iovec *vec, abi_ulong target_addr,
1346 int count, int copy)
pbrook53a59602006-03-25 19:31:22 +00001347{
1348 struct target_iovec *target_vec;
blueswir1992f48a2007-10-14 16:27:31 +00001349 abi_ulong base;
balrogd732dcb2008-10-28 10:21:03 +00001350 int i;
pbrook53a59602006-03-25 19:31:22 +00001351
bellard579a97f2007-11-11 14:26:47 +00001352 target_vec = lock_user(VERIFY_READ, target_addr, count * sizeof(struct target_iovec), 1);
1353 if (!target_vec)
1354 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00001355 for(i = 0;i < count; i++) {
1356 base = tswapl(target_vec[i].iov_base);
1357 vec[i].iov_len = tswapl(target_vec[i].iov_len);
bellard41df8412008-02-04 22:26:57 +00001358 if (vec[i].iov_len != 0) {
1359 vec[i].iov_base = lock_user(type, base, vec[i].iov_len, copy);
balrogd732dcb2008-10-28 10:21:03 +00001360 /* Don't check lock_user return value. We must call writev even
1361 if a element has invalid base address. */
bellard41df8412008-02-04 22:26:57 +00001362 } else {
1363 /* zero length pointer is ignored */
1364 vec[i].iov_base = NULL;
1365 }
pbrook53a59602006-03-25 19:31:22 +00001366 }
1367 unlock_user (target_vec, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00001368 return 0;
pbrook53a59602006-03-25 19:31:22 +00001369}
1370
bellard579a97f2007-11-11 14:26:47 +00001371static abi_long unlock_iovec(struct iovec *vec, abi_ulong target_addr,
1372 int count, int copy)
pbrook53a59602006-03-25 19:31:22 +00001373{
1374 struct target_iovec *target_vec;
blueswir1992f48a2007-10-14 16:27:31 +00001375 abi_ulong base;
pbrook53a59602006-03-25 19:31:22 +00001376 int i;
1377
bellard579a97f2007-11-11 14:26:47 +00001378 target_vec = lock_user(VERIFY_READ, target_addr, count * sizeof(struct target_iovec), 1);
1379 if (!target_vec)
1380 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00001381 for(i = 0;i < count; i++) {
balrogd732dcb2008-10-28 10:21:03 +00001382 if (target_vec[i].iov_base) {
1383 base = tswapl(target_vec[i].iov_base);
1384 unlock_user(vec[i].iov_base, base, copy ? vec[i].iov_len : 0);
1385 }
pbrook53a59602006-03-25 19:31:22 +00001386 }
1387 unlock_user (target_vec, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00001388
1389 return 0;
pbrook53a59602006-03-25 19:31:22 +00001390}
1391
ths0da46a62007-10-20 20:23:07 +00001392/* do_socket() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001393static abi_long do_socket(int domain, int type, int protocol)
bellard3532fa72006-06-24 15:06:03 +00001394{
1395#if defined(TARGET_MIPS)
1396 switch(type) {
1397 case TARGET_SOCK_DGRAM:
1398 type = SOCK_DGRAM;
1399 break;
1400 case TARGET_SOCK_STREAM:
1401 type = SOCK_STREAM;
1402 break;
1403 case TARGET_SOCK_RAW:
1404 type = SOCK_RAW;
1405 break;
1406 case TARGET_SOCK_RDM:
1407 type = SOCK_RDM;
1408 break;
1409 case TARGET_SOCK_SEQPACKET:
1410 type = SOCK_SEQPACKET;
1411 break;
1412 case TARGET_SOCK_PACKET:
1413 type = SOCK_PACKET;
1414 break;
1415 }
1416#endif
balrog12bc92a2007-10-30 21:06:14 +00001417 if (domain == PF_NETLINK)
1418 return -EAFNOSUPPORT; /* do not NETLINK socket connections possible */
bellard3532fa72006-06-24 15:06:03 +00001419 return get_errno(socket(domain, type, protocol));
1420}
1421
ths0da46a62007-10-20 20:23:07 +00001422/* do_bind() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001423static abi_long do_bind(int sockfd, abi_ulong target_addr,
1424 socklen_t addrlen)
bellard3532fa72006-06-24 15:06:03 +00001425{
aurel328f7aeaf2009-01-30 19:47:57 +00001426 void *addr;
1427
aurel32be09ac42009-04-15 16:12:06 +00001428 if (addrlen < 0)
aurel328f7aeaf2009-01-30 19:47:57 +00001429 return -TARGET_EINVAL;
1430
aurel32607175e2009-04-15 16:11:59 +00001431 addr = alloca(addrlen+1);
ths3b46e622007-09-17 08:09:54 +00001432
bellard3532fa72006-06-24 15:06:03 +00001433 target_to_host_sockaddr(addr, target_addr, addrlen);
1434 return get_errno(bind(sockfd, addr, addrlen));
1435}
1436
ths0da46a62007-10-20 20:23:07 +00001437/* do_connect() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001438static abi_long do_connect(int sockfd, abi_ulong target_addr,
1439 socklen_t addrlen)
bellard3532fa72006-06-24 15:06:03 +00001440{
aurel328f7aeaf2009-01-30 19:47:57 +00001441 void *addr;
1442
aurel32be09ac42009-04-15 16:12:06 +00001443 if (addrlen < 0)
aurel328f7aeaf2009-01-30 19:47:57 +00001444 return -TARGET_EINVAL;
1445
1446 addr = alloca(addrlen);
ths3b46e622007-09-17 08:09:54 +00001447
bellard3532fa72006-06-24 15:06:03 +00001448 target_to_host_sockaddr(addr, target_addr, addrlen);
1449 return get_errno(connect(sockfd, addr, addrlen));
1450}
1451
ths0da46a62007-10-20 20:23:07 +00001452/* do_sendrecvmsg() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001453static abi_long do_sendrecvmsg(int fd, abi_ulong target_msg,
1454 int flags, int send)
bellard3532fa72006-06-24 15:06:03 +00001455{
balrog6de645c2008-10-28 10:26:29 +00001456 abi_long ret, len;
bellard3532fa72006-06-24 15:06:03 +00001457 struct target_msghdr *msgp;
1458 struct msghdr msg;
1459 int count;
1460 struct iovec *vec;
blueswir1992f48a2007-10-14 16:27:31 +00001461 abi_ulong target_vec;
bellard3532fa72006-06-24 15:06:03 +00001462
bellard579a97f2007-11-11 14:26:47 +00001463 /* FIXME */
1464 if (!lock_user_struct(send ? VERIFY_READ : VERIFY_WRITE,
1465 msgp,
1466 target_msg,
1467 send ? 1 : 0))
1468 return -TARGET_EFAULT;
bellard3532fa72006-06-24 15:06:03 +00001469 if (msgp->msg_name) {
1470 msg.msg_namelen = tswap32(msgp->msg_namelen);
1471 msg.msg_name = alloca(msg.msg_namelen);
1472 target_to_host_sockaddr(msg.msg_name, tswapl(msgp->msg_name),
1473 msg.msg_namelen);
1474 } else {
1475 msg.msg_name = NULL;
1476 msg.msg_namelen = 0;
1477 }
1478 msg.msg_controllen = 2 * tswapl(msgp->msg_controllen);
1479 msg.msg_control = alloca(msg.msg_controllen);
1480 msg.msg_flags = tswap32(msgp->msg_flags);
ths3b46e622007-09-17 08:09:54 +00001481
bellard3532fa72006-06-24 15:06:03 +00001482 count = tswapl(msgp->msg_iovlen);
1483 vec = alloca(count * sizeof(struct iovec));
1484 target_vec = tswapl(msgp->msg_iov);
bellard579a97f2007-11-11 14:26:47 +00001485 lock_iovec(send ? VERIFY_READ : VERIFY_WRITE, vec, target_vec, count, send);
bellard3532fa72006-06-24 15:06:03 +00001486 msg.msg_iovlen = count;
1487 msg.msg_iov = vec;
ths3b46e622007-09-17 08:09:54 +00001488
bellard3532fa72006-06-24 15:06:03 +00001489 if (send) {
bellard5a4a8982007-11-11 17:39:18 +00001490 ret = target_to_host_cmsg(&msg, msgp);
1491 if (ret == 0)
1492 ret = get_errno(sendmsg(fd, &msg, flags));
bellard3532fa72006-06-24 15:06:03 +00001493 } else {
1494 ret = get_errno(recvmsg(fd, &msg, flags));
balrog6de645c2008-10-28 10:26:29 +00001495 if (!is_error(ret)) {
1496 len = ret;
bellard5a4a8982007-11-11 17:39:18 +00001497 ret = host_to_target_cmsg(msgp, &msg);
balrog6de645c2008-10-28 10:26:29 +00001498 if (!is_error(ret))
1499 ret = len;
1500 }
bellard3532fa72006-06-24 15:06:03 +00001501 }
1502 unlock_iovec(vec, target_vec, count, !send);
bellard579a97f2007-11-11 14:26:47 +00001503 unlock_user_struct(msgp, target_msg, send ? 0 : 1);
bellard3532fa72006-06-24 15:06:03 +00001504 return ret;
1505}
1506
ths0da46a62007-10-20 20:23:07 +00001507/* do_accept() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001508static abi_long do_accept(int fd, abi_ulong target_addr,
bellard2f619692007-11-16 10:46:05 +00001509 abi_ulong target_addrlen_addr)
pbrook1be9e1d2006-11-19 15:26:04 +00001510{
bellard2f619692007-11-16 10:46:05 +00001511 socklen_t addrlen;
1512 void *addr;
blueswir1992f48a2007-10-14 16:27:31 +00001513 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00001514
bellard2f619692007-11-16 10:46:05 +00001515 if (get_user_u32(addrlen, target_addrlen_addr))
1516 return -TARGET_EFAULT;
1517
aurel32be09ac42009-04-15 16:12:06 +00001518 if (addrlen < 0)
aurel328f7aeaf2009-01-30 19:47:57 +00001519 return -TARGET_EINVAL;
1520
bellard2f619692007-11-16 10:46:05 +00001521 addr = alloca(addrlen);
1522
pbrook1be9e1d2006-11-19 15:26:04 +00001523 ret = get_errno(accept(fd, addr, &addrlen));
1524 if (!is_error(ret)) {
1525 host_to_target_sockaddr(target_addr, addr, addrlen);
bellard2f619692007-11-16 10:46:05 +00001526 if (put_user_u32(addrlen, target_addrlen_addr))
1527 ret = -TARGET_EFAULT;
pbrook1be9e1d2006-11-19 15:26:04 +00001528 }
1529 return ret;
1530}
1531
ths0da46a62007-10-20 20:23:07 +00001532/* do_getpeername() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001533static abi_long do_getpeername(int fd, abi_ulong target_addr,
bellard2f619692007-11-16 10:46:05 +00001534 abi_ulong target_addrlen_addr)
pbrook1be9e1d2006-11-19 15:26:04 +00001535{
bellard2f619692007-11-16 10:46:05 +00001536 socklen_t addrlen;
1537 void *addr;
blueswir1992f48a2007-10-14 16:27:31 +00001538 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00001539
bellard2f619692007-11-16 10:46:05 +00001540 if (get_user_u32(addrlen, target_addrlen_addr))
1541 return -TARGET_EFAULT;
1542
aurel32be09ac42009-04-15 16:12:06 +00001543 if (addrlen < 0)
aurel328f7aeaf2009-01-30 19:47:57 +00001544 return -TARGET_EINVAL;
1545
bellard2f619692007-11-16 10:46:05 +00001546 addr = alloca(addrlen);
1547
pbrook1be9e1d2006-11-19 15:26:04 +00001548 ret = get_errno(getpeername(fd, addr, &addrlen));
1549 if (!is_error(ret)) {
1550 host_to_target_sockaddr(target_addr, addr, addrlen);
bellard2f619692007-11-16 10:46:05 +00001551 if (put_user_u32(addrlen, target_addrlen_addr))
1552 ret = -TARGET_EFAULT;
pbrook1be9e1d2006-11-19 15:26:04 +00001553 }
1554 return ret;
1555}
1556
ths0da46a62007-10-20 20:23:07 +00001557/* do_getsockname() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001558static abi_long do_getsockname(int fd, abi_ulong target_addr,
bellard2f619692007-11-16 10:46:05 +00001559 abi_ulong target_addrlen_addr)
pbrook1be9e1d2006-11-19 15:26:04 +00001560{
bellard2f619692007-11-16 10:46:05 +00001561 socklen_t addrlen;
1562 void *addr;
blueswir1992f48a2007-10-14 16:27:31 +00001563 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00001564
aurel328fea3602009-01-30 19:47:47 +00001565 if (target_addr == 0)
1566 return get_errno(accept(fd, NULL, NULL));
1567
bellard2f619692007-11-16 10:46:05 +00001568 if (get_user_u32(addrlen, target_addrlen_addr))
1569 return -TARGET_EFAULT;
1570
aurel32be09ac42009-04-15 16:12:06 +00001571 if (addrlen < 0)
aurel328f7aeaf2009-01-30 19:47:57 +00001572 return -TARGET_EINVAL;
1573
bellard2f619692007-11-16 10:46:05 +00001574 addr = alloca(addrlen);
1575
pbrook1be9e1d2006-11-19 15:26:04 +00001576 ret = get_errno(getsockname(fd, addr, &addrlen));
1577 if (!is_error(ret)) {
1578 host_to_target_sockaddr(target_addr, addr, addrlen);
bellard2f619692007-11-16 10:46:05 +00001579 if (put_user_u32(addrlen, target_addrlen_addr))
1580 ret = -TARGET_EFAULT;
pbrook1be9e1d2006-11-19 15:26:04 +00001581 }
1582 return ret;
1583}
1584
ths0da46a62007-10-20 20:23:07 +00001585/* do_socketpair() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001586static abi_long do_socketpair(int domain, int type, int protocol,
bellard2f619692007-11-16 10:46:05 +00001587 abi_ulong target_tab_addr)
pbrook1be9e1d2006-11-19 15:26:04 +00001588{
1589 int tab[2];
blueswir1992f48a2007-10-14 16:27:31 +00001590 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00001591
1592 ret = get_errno(socketpair(domain, type, protocol, tab));
1593 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +00001594 if (put_user_s32(tab[0], target_tab_addr)
1595 || put_user_s32(tab[1], target_tab_addr + sizeof(tab[0])))
1596 ret = -TARGET_EFAULT;
pbrook1be9e1d2006-11-19 15:26:04 +00001597 }
1598 return ret;
1599}
1600
ths0da46a62007-10-20 20:23:07 +00001601/* do_sendto() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001602static abi_long do_sendto(int fd, abi_ulong msg, size_t len, int flags,
1603 abi_ulong target_addr, socklen_t addrlen)
pbrook1be9e1d2006-11-19 15:26:04 +00001604{
1605 void *addr;
1606 void *host_msg;
blueswir1992f48a2007-10-14 16:27:31 +00001607 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00001608
aurel32be09ac42009-04-15 16:12:06 +00001609 if (addrlen < 0)
aurel328f7aeaf2009-01-30 19:47:57 +00001610 return -TARGET_EINVAL;
1611
bellard579a97f2007-11-11 14:26:47 +00001612 host_msg = lock_user(VERIFY_READ, msg, len, 1);
1613 if (!host_msg)
1614 return -TARGET_EFAULT;
pbrook1be9e1d2006-11-19 15:26:04 +00001615 if (target_addr) {
1616 addr = alloca(addrlen);
1617 target_to_host_sockaddr(addr, target_addr, addrlen);
1618 ret = get_errno(sendto(fd, host_msg, len, flags, addr, addrlen));
1619 } else {
1620 ret = get_errno(send(fd, host_msg, len, flags));
1621 }
1622 unlock_user(host_msg, msg, 0);
1623 return ret;
1624}
1625
ths0da46a62007-10-20 20:23:07 +00001626/* do_recvfrom() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001627static abi_long do_recvfrom(int fd, abi_ulong msg, size_t len, int flags,
1628 abi_ulong target_addr,
1629 abi_ulong target_addrlen)
pbrook1be9e1d2006-11-19 15:26:04 +00001630{
1631 socklen_t addrlen;
1632 void *addr;
1633 void *host_msg;
blueswir1992f48a2007-10-14 16:27:31 +00001634 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00001635
bellard579a97f2007-11-11 14:26:47 +00001636 host_msg = lock_user(VERIFY_WRITE, msg, len, 0);
1637 if (!host_msg)
1638 return -TARGET_EFAULT;
pbrook1be9e1d2006-11-19 15:26:04 +00001639 if (target_addr) {
bellard2f619692007-11-16 10:46:05 +00001640 if (get_user_u32(addrlen, target_addrlen)) {
1641 ret = -TARGET_EFAULT;
1642 goto fail;
1643 }
aurel32be09ac42009-04-15 16:12:06 +00001644 if (addrlen < 0) {
aurel328f7aeaf2009-01-30 19:47:57 +00001645 ret = -TARGET_EINVAL;
1646 goto fail;
1647 }
pbrook1be9e1d2006-11-19 15:26:04 +00001648 addr = alloca(addrlen);
1649 ret = get_errno(recvfrom(fd, host_msg, len, flags, addr, &addrlen));
1650 } else {
1651 addr = NULL; /* To keep compiler quiet. */
1652 ret = get_errno(recv(fd, host_msg, len, flags));
1653 }
1654 if (!is_error(ret)) {
1655 if (target_addr) {
1656 host_to_target_sockaddr(target_addr, addr, addrlen);
bellard2f619692007-11-16 10:46:05 +00001657 if (put_user_u32(addrlen, target_addrlen)) {
1658 ret = -TARGET_EFAULT;
1659 goto fail;
1660 }
pbrook1be9e1d2006-11-19 15:26:04 +00001661 }
1662 unlock_user(host_msg, msg, len);
1663 } else {
bellard2f619692007-11-16 10:46:05 +00001664fail:
pbrook1be9e1d2006-11-19 15:26:04 +00001665 unlock_user(host_msg, msg, 0);
1666 }
1667 return ret;
1668}
1669
j_mayer32407102007-09-26 23:01:49 +00001670#ifdef TARGET_NR_socketcall
ths0da46a62007-10-20 20:23:07 +00001671/* do_socketcall() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001672static abi_long do_socketcall(int num, abi_ulong vptr)
bellard31e31b82003-02-18 22:55:36 +00001673{
blueswir1992f48a2007-10-14 16:27:31 +00001674 abi_long ret;
1675 const int n = sizeof(abi_ulong);
bellard31e31b82003-02-18 22:55:36 +00001676
1677 switch(num) {
1678 case SOCKOP_socket:
bellard7854b052003-03-29 17:22:23 +00001679 {
bellard2f619692007-11-16 10:46:05 +00001680 int domain, type, protocol;
1681
1682 if (get_user_s32(domain, vptr)
1683 || get_user_s32(type, vptr + n)
1684 || get_user_s32(protocol, vptr + 2 * n))
1685 return -TARGET_EFAULT;
1686
bellard3532fa72006-06-24 15:06:03 +00001687 ret = do_socket(domain, type, protocol);
bellard7854b052003-03-29 17:22:23 +00001688 }
bellard31e31b82003-02-18 22:55:36 +00001689 break;
1690 case SOCKOP_bind:
bellard7854b052003-03-29 17:22:23 +00001691 {
bellard2f619692007-11-16 10:46:05 +00001692 int sockfd;
1693 abi_ulong target_addr;
1694 socklen_t addrlen;
1695
1696 if (get_user_s32(sockfd, vptr)
1697 || get_user_ual(target_addr, vptr + n)
1698 || get_user_u32(addrlen, vptr + 2 * n))
1699 return -TARGET_EFAULT;
1700
bellard3532fa72006-06-24 15:06:03 +00001701 ret = do_bind(sockfd, target_addr, addrlen);
bellard7854b052003-03-29 17:22:23 +00001702 }
bellard31e31b82003-02-18 22:55:36 +00001703 break;
1704 case SOCKOP_connect:
bellard7854b052003-03-29 17:22:23 +00001705 {
bellard2f619692007-11-16 10:46:05 +00001706 int sockfd;
1707 abi_ulong target_addr;
1708 socklen_t addrlen;
1709
1710 if (get_user_s32(sockfd, vptr)
1711 || get_user_ual(target_addr, vptr + n)
1712 || get_user_u32(addrlen, vptr + 2 * n))
1713 return -TARGET_EFAULT;
1714
bellard3532fa72006-06-24 15:06:03 +00001715 ret = do_connect(sockfd, target_addr, addrlen);
bellard7854b052003-03-29 17:22:23 +00001716 }
bellard31e31b82003-02-18 22:55:36 +00001717 break;
1718 case SOCKOP_listen:
bellard7854b052003-03-29 17:22:23 +00001719 {
bellard2f619692007-11-16 10:46:05 +00001720 int sockfd, backlog;
1721
1722 if (get_user_s32(sockfd, vptr)
1723 || get_user_s32(backlog, vptr + n))
1724 return -TARGET_EFAULT;
1725
bellard7854b052003-03-29 17:22:23 +00001726 ret = get_errno(listen(sockfd, backlog));
1727 }
bellard31e31b82003-02-18 22:55:36 +00001728 break;
1729 case SOCKOP_accept:
1730 {
bellard2f619692007-11-16 10:46:05 +00001731 int sockfd;
1732 abi_ulong target_addr, target_addrlen;
1733
1734 if (get_user_s32(sockfd, vptr)
1735 || get_user_ual(target_addr, vptr + n)
1736 || get_user_u32(target_addrlen, vptr + 2 * n))
1737 return -TARGET_EFAULT;
1738
pbrook1be9e1d2006-11-19 15:26:04 +00001739 ret = do_accept(sockfd, target_addr, target_addrlen);
bellard31e31b82003-02-18 22:55:36 +00001740 }
1741 break;
1742 case SOCKOP_getsockname:
1743 {
bellard2f619692007-11-16 10:46:05 +00001744 int sockfd;
1745 abi_ulong target_addr, target_addrlen;
1746
1747 if (get_user_s32(sockfd, vptr)
1748 || get_user_ual(target_addr, vptr + n)
1749 || get_user_u32(target_addrlen, vptr + 2 * n))
1750 return -TARGET_EFAULT;
1751
pbrook1be9e1d2006-11-19 15:26:04 +00001752 ret = do_getsockname(sockfd, target_addr, target_addrlen);
bellard31e31b82003-02-18 22:55:36 +00001753 }
1754 break;
1755 case SOCKOP_getpeername:
1756 {
bellard2f619692007-11-16 10:46:05 +00001757 int sockfd;
1758 abi_ulong target_addr, target_addrlen;
1759
1760 if (get_user_s32(sockfd, vptr)
1761 || get_user_ual(target_addr, vptr + n)
1762 || get_user_u32(target_addrlen, vptr + 2 * n))
1763 return -TARGET_EFAULT;
1764
pbrook1be9e1d2006-11-19 15:26:04 +00001765 ret = do_getpeername(sockfd, target_addr, target_addrlen);
bellard31e31b82003-02-18 22:55:36 +00001766 }
1767 break;
1768 case SOCKOP_socketpair:
1769 {
bellard2f619692007-11-16 10:46:05 +00001770 int domain, type, protocol;
1771 abi_ulong tab;
1772
1773 if (get_user_s32(domain, vptr)
1774 || get_user_s32(type, vptr + n)
1775 || get_user_s32(protocol, vptr + 2 * n)
1776 || get_user_ual(tab, vptr + 3 * n))
1777 return -TARGET_EFAULT;
1778
pbrook1be9e1d2006-11-19 15:26:04 +00001779 ret = do_socketpair(domain, type, protocol, tab);
bellard31e31b82003-02-18 22:55:36 +00001780 }
1781 break;
1782 case SOCKOP_send:
bellard7854b052003-03-29 17:22:23 +00001783 {
bellard2f619692007-11-16 10:46:05 +00001784 int sockfd;
1785 abi_ulong msg;
1786 size_t len;
1787 int flags;
1788
1789 if (get_user_s32(sockfd, vptr)
1790 || get_user_ual(msg, vptr + n)
1791 || get_user_ual(len, vptr + 2 * n)
1792 || get_user_s32(flags, vptr + 3 * n))
1793 return -TARGET_EFAULT;
1794
pbrook1be9e1d2006-11-19 15:26:04 +00001795 ret = do_sendto(sockfd, msg, len, flags, 0, 0);
bellard7854b052003-03-29 17:22:23 +00001796 }
bellard31e31b82003-02-18 22:55:36 +00001797 break;
1798 case SOCKOP_recv:
bellard7854b052003-03-29 17:22:23 +00001799 {
bellard2f619692007-11-16 10:46:05 +00001800 int sockfd;
1801 abi_ulong msg;
1802 size_t len;
1803 int flags;
1804
1805 if (get_user_s32(sockfd, vptr)
1806 || get_user_ual(msg, vptr + n)
1807 || get_user_ual(len, vptr + 2 * n)
1808 || get_user_s32(flags, vptr + 3 * n))
1809 return -TARGET_EFAULT;
1810
pbrook1be9e1d2006-11-19 15:26:04 +00001811 ret = do_recvfrom(sockfd, msg, len, flags, 0, 0);
bellard7854b052003-03-29 17:22:23 +00001812 }
bellard31e31b82003-02-18 22:55:36 +00001813 break;
1814 case SOCKOP_sendto:
bellard7854b052003-03-29 17:22:23 +00001815 {
bellard2f619692007-11-16 10:46:05 +00001816 int sockfd;
1817 abi_ulong msg;
1818 size_t len;
1819 int flags;
1820 abi_ulong addr;
1821 socklen_t addrlen;
1822
1823 if (get_user_s32(sockfd, vptr)
1824 || get_user_ual(msg, vptr + n)
1825 || get_user_ual(len, vptr + 2 * n)
1826 || get_user_s32(flags, vptr + 3 * n)
1827 || get_user_ual(addr, vptr + 4 * n)
1828 || get_user_u32(addrlen, vptr + 5 * n))
1829 return -TARGET_EFAULT;
1830
pbrook1be9e1d2006-11-19 15:26:04 +00001831 ret = do_sendto(sockfd, msg, len, flags, addr, addrlen);
bellard7854b052003-03-29 17:22:23 +00001832 }
bellard31e31b82003-02-18 22:55:36 +00001833 break;
1834 case SOCKOP_recvfrom:
1835 {
bellard2f619692007-11-16 10:46:05 +00001836 int sockfd;
1837 abi_ulong msg;
1838 size_t len;
1839 int flags;
1840 abi_ulong addr;
1841 socklen_t addrlen;
1842
1843 if (get_user_s32(sockfd, vptr)
1844 || get_user_ual(msg, vptr + n)
1845 || get_user_ual(len, vptr + 2 * n)
1846 || get_user_s32(flags, vptr + 3 * n)
1847 || get_user_ual(addr, vptr + 4 * n)
1848 || get_user_u32(addrlen, vptr + 5 * n))
1849 return -TARGET_EFAULT;
1850
pbrook1be9e1d2006-11-19 15:26:04 +00001851 ret = do_recvfrom(sockfd, msg, len, flags, addr, addrlen);
bellard31e31b82003-02-18 22:55:36 +00001852 }
1853 break;
1854 case SOCKOP_shutdown:
bellard7854b052003-03-29 17:22:23 +00001855 {
bellard2f619692007-11-16 10:46:05 +00001856 int sockfd, how;
1857
1858 if (get_user_s32(sockfd, vptr)
1859 || get_user_s32(how, vptr + n))
1860 return -TARGET_EFAULT;
bellard7854b052003-03-29 17:22:23 +00001861
1862 ret = get_errno(shutdown(sockfd, how));
1863 }
bellard31e31b82003-02-18 22:55:36 +00001864 break;
1865 case SOCKOP_sendmsg:
1866 case SOCKOP_recvmsg:
bellard1a9353d2003-03-16 20:28:50 +00001867 {
1868 int fd;
blueswir1992f48a2007-10-14 16:27:31 +00001869 abi_ulong target_msg;
bellard3532fa72006-06-24 15:06:03 +00001870 int flags;
bellard1a9353d2003-03-16 20:28:50 +00001871
bellard2f619692007-11-16 10:46:05 +00001872 if (get_user_s32(fd, vptr)
1873 || get_user_ual(target_msg, vptr + n)
1874 || get_user_s32(flags, vptr + 2 * n))
1875 return -TARGET_EFAULT;
bellard3532fa72006-06-24 15:06:03 +00001876
ths5fafdf22007-09-16 21:08:06 +00001877 ret = do_sendrecvmsg(fd, target_msg, flags,
bellard3532fa72006-06-24 15:06:03 +00001878 (num == SOCKOP_sendmsg));
bellard1a9353d2003-03-16 20:28:50 +00001879 }
1880 break;
bellard31e31b82003-02-18 22:55:36 +00001881 case SOCKOP_setsockopt:
bellard7854b052003-03-29 17:22:23 +00001882 {
bellard2f619692007-11-16 10:46:05 +00001883 int sockfd;
1884 int level;
1885 int optname;
1886 abi_ulong optval;
1887 socklen_t optlen;
1888
1889 if (get_user_s32(sockfd, vptr)
1890 || get_user_s32(level, vptr + n)
1891 || get_user_s32(optname, vptr + 2 * n)
1892 || get_user_ual(optval, vptr + 3 * n)
1893 || get_user_u32(optlen, vptr + 4 * n))
1894 return -TARGET_EFAULT;
bellard7854b052003-03-29 17:22:23 +00001895
1896 ret = do_setsockopt(sockfd, level, optname, optval, optlen);
1897 }
1898 break;
bellard31e31b82003-02-18 22:55:36 +00001899 case SOCKOP_getsockopt:
bellard7854b052003-03-29 17:22:23 +00001900 {
bellard2f619692007-11-16 10:46:05 +00001901 int sockfd;
1902 int level;
1903 int optname;
1904 abi_ulong optval;
1905 socklen_t optlen;
bellard7854b052003-03-29 17:22:23 +00001906
bellard2f619692007-11-16 10:46:05 +00001907 if (get_user_s32(sockfd, vptr)
1908 || get_user_s32(level, vptr + n)
1909 || get_user_s32(optname, vptr + 2 * n)
1910 || get_user_ual(optval, vptr + 3 * n)
1911 || get_user_u32(optlen, vptr + 4 * n))
1912 return -TARGET_EFAULT;
1913
1914 ret = do_getsockopt(sockfd, level, optname, optval, optlen);
bellard7854b052003-03-29 17:22:23 +00001915 }
1916 break;
bellard31e31b82003-02-18 22:55:36 +00001917 default:
1918 gemu_log("Unsupported socketcall: %d\n", num);
ths0da46a62007-10-20 20:23:07 +00001919 ret = -TARGET_ENOSYS;
bellard31e31b82003-02-18 22:55:36 +00001920 break;
1921 }
1922 return ret;
1923}
j_mayer32407102007-09-26 23:01:49 +00001924#endif
bellard31e31b82003-02-18 22:55:36 +00001925
bellard8853f862004-02-22 14:57:26 +00001926#define N_SHM_REGIONS 32
1927
1928static struct shm_region {
bellard5a4a8982007-11-11 17:39:18 +00001929 abi_ulong start;
1930 abi_ulong size;
bellard8853f862004-02-22 14:57:26 +00001931} shm_regions[N_SHM_REGIONS];
1932
ths3eb6b042007-06-03 14:26:27 +00001933struct target_ipc_perm
1934{
blueswir1992f48a2007-10-14 16:27:31 +00001935 abi_long __key;
1936 abi_ulong uid;
1937 abi_ulong gid;
1938 abi_ulong cuid;
1939 abi_ulong cgid;
ths3eb6b042007-06-03 14:26:27 +00001940 unsigned short int mode;
1941 unsigned short int __pad1;
1942 unsigned short int __seq;
1943 unsigned short int __pad2;
blueswir1992f48a2007-10-14 16:27:31 +00001944 abi_ulong __unused1;
1945 abi_ulong __unused2;
ths3eb6b042007-06-03 14:26:27 +00001946};
1947
1948struct target_semid_ds
1949{
1950 struct target_ipc_perm sem_perm;
blueswir1992f48a2007-10-14 16:27:31 +00001951 abi_ulong sem_otime;
1952 abi_ulong __unused1;
1953 abi_ulong sem_ctime;
1954 abi_ulong __unused2;
1955 abi_ulong sem_nsems;
1956 abi_ulong __unused3;
1957 abi_ulong __unused4;
ths3eb6b042007-06-03 14:26:27 +00001958};
1959
bellard579a97f2007-11-11 14:26:47 +00001960static inline abi_long target_to_host_ipc_perm(struct ipc_perm *host_ip,
1961 abi_ulong target_addr)
ths3eb6b042007-06-03 14:26:27 +00001962{
1963 struct target_ipc_perm *target_ip;
1964 struct target_semid_ds *target_sd;
1965
bellard579a97f2007-11-11 14:26:47 +00001966 if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
1967 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00001968 target_ip=&(target_sd->sem_perm);
1969 host_ip->__key = tswapl(target_ip->__key);
1970 host_ip->uid = tswapl(target_ip->uid);
1971 host_ip->gid = tswapl(target_ip->gid);
1972 host_ip->cuid = tswapl(target_ip->cuid);
1973 host_ip->cgid = tswapl(target_ip->cgid);
1974 host_ip->mode = tswapl(target_ip->mode);
1975 unlock_user_struct(target_sd, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00001976 return 0;
ths3eb6b042007-06-03 14:26:27 +00001977}
1978
bellard579a97f2007-11-11 14:26:47 +00001979static inline abi_long host_to_target_ipc_perm(abi_ulong target_addr,
1980 struct ipc_perm *host_ip)
ths3eb6b042007-06-03 14:26:27 +00001981{
1982 struct target_ipc_perm *target_ip;
1983 struct target_semid_ds *target_sd;
1984
bellard579a97f2007-11-11 14:26:47 +00001985 if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
1986 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00001987 target_ip = &(target_sd->sem_perm);
1988 target_ip->__key = tswapl(host_ip->__key);
1989 target_ip->uid = tswapl(host_ip->uid);
1990 target_ip->gid = tswapl(host_ip->gid);
1991 target_ip->cuid = tswapl(host_ip->cuid);
1992 target_ip->cgid = tswapl(host_ip->cgid);
1993 target_ip->mode = tswapl(host_ip->mode);
1994 unlock_user_struct(target_sd, target_addr, 1);
bellard579a97f2007-11-11 14:26:47 +00001995 return 0;
ths3eb6b042007-06-03 14:26:27 +00001996}
1997
bellard579a97f2007-11-11 14:26:47 +00001998static inline abi_long target_to_host_semid_ds(struct semid_ds *host_sd,
1999 abi_ulong target_addr)
ths3eb6b042007-06-03 14:26:27 +00002000{
2001 struct target_semid_ds *target_sd;
2002
bellard579a97f2007-11-11 14:26:47 +00002003 if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
2004 return -TARGET_EFAULT;
aurel32e5289082009-04-18 16:16:12 +00002005 if (target_to_host_ipc_perm(&(host_sd->sem_perm),target_addr))
2006 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00002007 host_sd->sem_nsems = tswapl(target_sd->sem_nsems);
2008 host_sd->sem_otime = tswapl(target_sd->sem_otime);
2009 host_sd->sem_ctime = tswapl(target_sd->sem_ctime);
2010 unlock_user_struct(target_sd, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00002011 return 0;
ths3eb6b042007-06-03 14:26:27 +00002012}
2013
bellard579a97f2007-11-11 14:26:47 +00002014static inline abi_long host_to_target_semid_ds(abi_ulong target_addr,
2015 struct semid_ds *host_sd)
ths3eb6b042007-06-03 14:26:27 +00002016{
2017 struct target_semid_ds *target_sd;
2018
bellard579a97f2007-11-11 14:26:47 +00002019 if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
2020 return -TARGET_EFAULT;
aurel32e5289082009-04-18 16:16:12 +00002021 if (host_to_target_ipc_perm(target_addr,&(host_sd->sem_perm)))
2022 return -TARGET_EFAULT;;
ths3eb6b042007-06-03 14:26:27 +00002023 target_sd->sem_nsems = tswapl(host_sd->sem_nsems);
2024 target_sd->sem_otime = tswapl(host_sd->sem_otime);
2025 target_sd->sem_ctime = tswapl(host_sd->sem_ctime);
2026 unlock_user_struct(target_sd, target_addr, 1);
bellard579a97f2007-11-11 14:26:47 +00002027 return 0;
ths3eb6b042007-06-03 14:26:27 +00002028}
2029
aurel32e5289082009-04-18 16:16:12 +00002030struct target_seminfo {
2031 int semmap;
2032 int semmni;
2033 int semmns;
2034 int semmnu;
2035 int semmsl;
2036 int semopm;
2037 int semume;
2038 int semusz;
2039 int semvmx;
2040 int semaem;
2041};
2042
2043static inline abi_long host_to_target_seminfo(abi_ulong target_addr,
2044 struct seminfo *host_seminfo)
2045{
2046 struct target_seminfo *target_seminfo;
2047 if (!lock_user_struct(VERIFY_WRITE, target_seminfo, target_addr, 0))
2048 return -TARGET_EFAULT;
2049 __put_user(host_seminfo->semmap, &target_seminfo->semmap);
2050 __put_user(host_seminfo->semmni, &target_seminfo->semmni);
2051 __put_user(host_seminfo->semmns, &target_seminfo->semmns);
2052 __put_user(host_seminfo->semmnu, &target_seminfo->semmnu);
2053 __put_user(host_seminfo->semmsl, &target_seminfo->semmsl);
2054 __put_user(host_seminfo->semopm, &target_seminfo->semopm);
2055 __put_user(host_seminfo->semume, &target_seminfo->semume);
2056 __put_user(host_seminfo->semusz, &target_seminfo->semusz);
2057 __put_user(host_seminfo->semvmx, &target_seminfo->semvmx);
2058 __put_user(host_seminfo->semaem, &target_seminfo->semaem);
2059 unlock_user_struct(target_seminfo, target_addr, 1);
2060 return 0;
2061}
2062
thsfa294812007-02-02 22:05:00 +00002063union semun {
2064 int val;
ths3eb6b042007-06-03 14:26:27 +00002065 struct semid_ds *buf;
thsfa294812007-02-02 22:05:00 +00002066 unsigned short *array;
aurel32e5289082009-04-18 16:16:12 +00002067 struct seminfo *__buf;
thsfa294812007-02-02 22:05:00 +00002068};
2069
ths3eb6b042007-06-03 14:26:27 +00002070union target_semun {
2071 int val;
aurel32e5289082009-04-18 16:16:12 +00002072 abi_ulong buf;
2073 abi_ulong array;
2074 abi_ulong __buf;
ths3eb6b042007-06-03 14:26:27 +00002075};
2076
aurel32e5289082009-04-18 16:16:12 +00002077static inline abi_long target_to_host_semarray(int semid, unsigned short **host_array,
2078 abi_ulong target_addr)
ths3eb6b042007-06-03 14:26:27 +00002079{
aurel32e5289082009-04-18 16:16:12 +00002080 int nsems;
2081 unsigned short *array;
2082 union semun semun;
2083 struct semid_ds semid_ds;
2084 int i, ret;
ths3eb6b042007-06-03 14:26:27 +00002085
aurel32e5289082009-04-18 16:16:12 +00002086 semun.buf = &semid_ds;
2087
2088 ret = semctl(semid, 0, IPC_STAT, semun);
2089 if (ret == -1)
2090 return get_errno(ret);
2091
2092 nsems = semid_ds.sem_nsems;
2093
2094 *host_array = malloc(nsems*sizeof(unsigned short));
2095 array = lock_user(VERIFY_READ, target_addr,
2096 nsems*sizeof(unsigned short), 1);
2097 if (!array)
2098 return -TARGET_EFAULT;
2099
2100 for(i=0; i<nsems; i++) {
2101 __get_user((*host_array)[i], &array[i]);
ths3eb6b042007-06-03 14:26:27 +00002102 }
aurel32e5289082009-04-18 16:16:12 +00002103 unlock_user(array, target_addr, 0);
2104
bellard579a97f2007-11-11 14:26:47 +00002105 return 0;
ths3eb6b042007-06-03 14:26:27 +00002106}
2107
aurel32e5289082009-04-18 16:16:12 +00002108static inline abi_long host_to_target_semarray(int semid, abi_ulong target_addr,
2109 unsigned short **host_array)
ths3eb6b042007-06-03 14:26:27 +00002110{
aurel32e5289082009-04-18 16:16:12 +00002111 int nsems;
2112 unsigned short *array;
2113 union semun semun;
2114 struct semid_ds semid_ds;
2115 int i, ret;
ths3eb6b042007-06-03 14:26:27 +00002116
aurel32e5289082009-04-18 16:16:12 +00002117 semun.buf = &semid_ds;
2118
2119 ret = semctl(semid, 0, IPC_STAT, semun);
2120 if (ret == -1)
2121 return get_errno(ret);
2122
2123 nsems = semid_ds.sem_nsems;
2124
2125 array = lock_user(VERIFY_WRITE, target_addr,
2126 nsems*sizeof(unsigned short), 0);
2127 if (!array)
2128 return -TARGET_EFAULT;
2129
2130 for(i=0; i<nsems; i++) {
2131 __put_user((*host_array)[i], &array[i]);
ths3eb6b042007-06-03 14:26:27 +00002132 }
aurel32e5289082009-04-18 16:16:12 +00002133 free(*host_array);
2134 unlock_user(array, target_addr, 1);
2135
bellard579a97f2007-11-11 14:26:47 +00002136 return 0;
ths3eb6b042007-06-03 14:26:27 +00002137}
2138
aurel32e5289082009-04-18 16:16:12 +00002139static inline abi_long do_semctl(int semid, int semnum, int cmd,
2140 union target_semun target_su)
ths3eb6b042007-06-03 14:26:27 +00002141{
2142 union semun arg;
2143 struct semid_ds dsarg;
aurel32e5289082009-04-18 16:16:12 +00002144 unsigned short *array;
2145 struct seminfo seminfo;
2146 abi_long ret = -TARGET_EINVAL;
2147 abi_long err;
2148 cmd &= 0xff;
ths3eb6b042007-06-03 14:26:27 +00002149
2150 switch( cmd ) {
2151 case GETVAL:
ths3eb6b042007-06-03 14:26:27 +00002152 case SETVAL:
aurel32e5289082009-04-18 16:16:12 +00002153 arg.val = tswapl(target_su.val);
2154 ret = get_errno(semctl(semid, semnum, cmd, arg));
2155 target_su.val = tswapl(arg.val);
ths3eb6b042007-06-03 14:26:27 +00002156 break;
2157 case GETALL:
ths3eb6b042007-06-03 14:26:27 +00002158 case SETALL:
aurel32e5289082009-04-18 16:16:12 +00002159 err = target_to_host_semarray(semid, &array, target_su.array);
2160 if (err)
2161 return err;
2162 arg.array = array;
2163 ret = get_errno(semctl(semid, semnum, cmd, arg));
2164 err = host_to_target_semarray(semid, target_su.array, &array);
2165 if (err)
2166 return err;
ths3eb6b042007-06-03 14:26:27 +00002167 break;
2168 case IPC_STAT:
ths3eb6b042007-06-03 14:26:27 +00002169 case IPC_SET:
aurel32e5289082009-04-18 16:16:12 +00002170 case SEM_STAT:
2171 err = target_to_host_semid_ds(&dsarg, target_su.buf);
2172 if (err)
2173 return err;
2174 arg.buf = &dsarg;
2175 ret = get_errno(semctl(semid, semnum, cmd, arg));
2176 err = host_to_target_semid_ds(target_su.buf, &dsarg);
2177 if (err)
2178 return err;
ths3eb6b042007-06-03 14:26:27 +00002179 break;
aurel32e5289082009-04-18 16:16:12 +00002180 case IPC_INFO:
2181 case SEM_INFO:
2182 arg.__buf = &seminfo;
2183 ret = get_errno(semctl(semid, semnum, cmd, arg));
2184 err = host_to_target_seminfo(target_su.__buf, &seminfo);
2185 if (err)
2186 return err;
2187 break;
2188 case IPC_RMID:
2189 case GETPID:
2190 case GETNCNT:
2191 case GETZCNT:
2192 ret = get_errno(semctl(semid, semnum, cmd, NULL));
2193 break;
ths3eb6b042007-06-03 14:26:27 +00002194 }
2195
2196 return ret;
2197}
2198
aurel32e5289082009-04-18 16:16:12 +00002199struct target_sembuf {
2200 unsigned short sem_num;
2201 short sem_op;
2202 short sem_flg;
2203};
2204
2205static inline abi_long target_to_host_sembuf(struct sembuf *host_sembuf,
2206 abi_ulong target_addr,
2207 unsigned nsops)
2208{
2209 struct target_sembuf *target_sembuf;
2210 int i;
2211
2212 target_sembuf = lock_user(VERIFY_READ, target_addr,
2213 nsops*sizeof(struct target_sembuf), 1);
2214 if (!target_sembuf)
2215 return -TARGET_EFAULT;
2216
2217 for(i=0; i<nsops; i++) {
2218 __get_user(host_sembuf[i].sem_num, &target_sembuf[i].sem_num);
2219 __get_user(host_sembuf[i].sem_op, &target_sembuf[i].sem_op);
2220 __get_user(host_sembuf[i].sem_flg, &target_sembuf[i].sem_flg);
2221 }
2222
2223 unlock_user(target_sembuf, target_addr, 0);
2224
2225 return 0;
2226}
2227
2228static inline abi_long do_semop(int semid, abi_long ptr, unsigned nsops)
2229{
2230 struct sembuf sops[nsops];
2231
2232 if (target_to_host_sembuf(sops, ptr, nsops))
2233 return -TARGET_EFAULT;
2234
2235 return semop(semid, sops, nsops);
2236}
2237
ths1bc012f2007-06-03 14:27:49 +00002238struct target_msqid_ds
2239{
aurel321c54ff92008-10-13 21:08:44 +00002240 struct target_ipc_perm msg_perm;
2241 abi_ulong msg_stime;
2242#if TARGET_ABI_BITS == 32
2243 abi_ulong __unused1;
2244#endif
2245 abi_ulong msg_rtime;
2246#if TARGET_ABI_BITS == 32
2247 abi_ulong __unused2;
2248#endif
2249 abi_ulong msg_ctime;
2250#if TARGET_ABI_BITS == 32
2251 abi_ulong __unused3;
2252#endif
2253 abi_ulong __msg_cbytes;
2254 abi_ulong msg_qnum;
2255 abi_ulong msg_qbytes;
2256 abi_ulong msg_lspid;
2257 abi_ulong msg_lrpid;
2258 abi_ulong __unused4;
2259 abi_ulong __unused5;
ths1bc012f2007-06-03 14:27:49 +00002260};
2261
bellard579a97f2007-11-11 14:26:47 +00002262static inline abi_long target_to_host_msqid_ds(struct msqid_ds *host_md,
2263 abi_ulong target_addr)
ths1bc012f2007-06-03 14:27:49 +00002264{
2265 struct target_msqid_ds *target_md;
2266
bellard579a97f2007-11-11 14:26:47 +00002267 if (!lock_user_struct(VERIFY_READ, target_md, target_addr, 1))
2268 return -TARGET_EFAULT;
aurel321c54ff92008-10-13 21:08:44 +00002269 if (target_to_host_ipc_perm(&(host_md->msg_perm),target_addr))
2270 return -TARGET_EFAULT;
ths1bc012f2007-06-03 14:27:49 +00002271 host_md->msg_stime = tswapl(target_md->msg_stime);
2272 host_md->msg_rtime = tswapl(target_md->msg_rtime);
2273 host_md->msg_ctime = tswapl(target_md->msg_ctime);
2274 host_md->__msg_cbytes = tswapl(target_md->__msg_cbytes);
2275 host_md->msg_qnum = tswapl(target_md->msg_qnum);
2276 host_md->msg_qbytes = tswapl(target_md->msg_qbytes);
2277 host_md->msg_lspid = tswapl(target_md->msg_lspid);
2278 host_md->msg_lrpid = tswapl(target_md->msg_lrpid);
2279 unlock_user_struct(target_md, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00002280 return 0;
ths1bc012f2007-06-03 14:27:49 +00002281}
2282
bellard579a97f2007-11-11 14:26:47 +00002283static inline abi_long host_to_target_msqid_ds(abi_ulong target_addr,
2284 struct msqid_ds *host_md)
ths1bc012f2007-06-03 14:27:49 +00002285{
2286 struct target_msqid_ds *target_md;
2287
bellard579a97f2007-11-11 14:26:47 +00002288 if (!lock_user_struct(VERIFY_WRITE, target_md, target_addr, 0))
2289 return -TARGET_EFAULT;
aurel321c54ff92008-10-13 21:08:44 +00002290 if (host_to_target_ipc_perm(target_addr,&(host_md->msg_perm)))
2291 return -TARGET_EFAULT;
ths1bc012f2007-06-03 14:27:49 +00002292 target_md->msg_stime = tswapl(host_md->msg_stime);
2293 target_md->msg_rtime = tswapl(host_md->msg_rtime);
2294 target_md->msg_ctime = tswapl(host_md->msg_ctime);
2295 target_md->__msg_cbytes = tswapl(host_md->__msg_cbytes);
2296 target_md->msg_qnum = tswapl(host_md->msg_qnum);
2297 target_md->msg_qbytes = tswapl(host_md->msg_qbytes);
2298 target_md->msg_lspid = tswapl(host_md->msg_lspid);
2299 target_md->msg_lrpid = tswapl(host_md->msg_lrpid);
2300 unlock_user_struct(target_md, target_addr, 1);
bellard579a97f2007-11-11 14:26:47 +00002301 return 0;
ths1bc012f2007-06-03 14:27:49 +00002302}
2303
aurel321c54ff92008-10-13 21:08:44 +00002304struct target_msginfo {
2305 int msgpool;
2306 int msgmap;
2307 int msgmax;
2308 int msgmnb;
2309 int msgmni;
2310 int msgssz;
2311 int msgtql;
2312 unsigned short int msgseg;
2313};
2314
2315static inline abi_long host_to_target_msginfo(abi_ulong target_addr,
2316 struct msginfo *host_msginfo)
2317{
2318 struct target_msginfo *target_msginfo;
2319 if (!lock_user_struct(VERIFY_WRITE, target_msginfo, target_addr, 0))
2320 return -TARGET_EFAULT;
2321 __put_user(host_msginfo->msgpool, &target_msginfo->msgpool);
2322 __put_user(host_msginfo->msgmap, &target_msginfo->msgmap);
2323 __put_user(host_msginfo->msgmax, &target_msginfo->msgmax);
2324 __put_user(host_msginfo->msgmnb, &target_msginfo->msgmnb);
2325 __put_user(host_msginfo->msgmni, &target_msginfo->msgmni);
2326 __put_user(host_msginfo->msgssz, &target_msginfo->msgssz);
2327 __put_user(host_msginfo->msgtql, &target_msginfo->msgtql);
2328 __put_user(host_msginfo->msgseg, &target_msginfo->msgseg);
2329 unlock_user_struct(target_msginfo, target_addr, 1);
aurel3200b229a2008-10-24 13:12:52 +00002330 return 0;
aurel321c54ff92008-10-13 21:08:44 +00002331}
2332
2333static inline abi_long do_msgctl(int msgid, int cmd, abi_long ptr)
ths1bc012f2007-06-03 14:27:49 +00002334{
2335 struct msqid_ds dsarg;
aurel321c54ff92008-10-13 21:08:44 +00002336 struct msginfo msginfo;
2337 abi_long ret = -TARGET_EINVAL;
2338
2339 cmd &= 0xff;
2340
2341 switch (cmd) {
ths1bc012f2007-06-03 14:27:49 +00002342 case IPC_STAT:
2343 case IPC_SET:
aurel321c54ff92008-10-13 21:08:44 +00002344 case MSG_STAT:
2345 if (target_to_host_msqid_ds(&dsarg,ptr))
2346 return -TARGET_EFAULT;
2347 ret = get_errno(msgctl(msgid, cmd, &dsarg));
2348 if (host_to_target_msqid_ds(ptr,&dsarg))
2349 return -TARGET_EFAULT;
2350 break;
2351 case IPC_RMID:
2352 ret = get_errno(msgctl(msgid, cmd, NULL));
2353 break;
2354 case IPC_INFO:
2355 case MSG_INFO:
2356 ret = get_errno(msgctl(msgid, cmd, (struct msqid_ds *)&msginfo));
2357 if (host_to_target_msginfo(ptr, &msginfo))
2358 return -TARGET_EFAULT;
2359 break;
ths1bc012f2007-06-03 14:27:49 +00002360 }
aurel321c54ff92008-10-13 21:08:44 +00002361
ths1bc012f2007-06-03 14:27:49 +00002362 return ret;
2363}
2364
2365struct target_msgbuf {
aurel321c54ff92008-10-13 21:08:44 +00002366 abi_long mtype;
2367 char mtext[1];
ths1bc012f2007-06-03 14:27:49 +00002368};
2369
blueswir1992f48a2007-10-14 16:27:31 +00002370static inline abi_long do_msgsnd(int msqid, abi_long msgp,
2371 unsigned int msgsz, int msgflg)
ths1bc012f2007-06-03 14:27:49 +00002372{
2373 struct target_msgbuf *target_mb;
2374 struct msgbuf *host_mb;
blueswir1992f48a2007-10-14 16:27:31 +00002375 abi_long ret = 0;
ths1bc012f2007-06-03 14:27:49 +00002376
bellard579a97f2007-11-11 14:26:47 +00002377 if (!lock_user_struct(VERIFY_READ, target_mb, msgp, 0))
2378 return -TARGET_EFAULT;
ths1bc012f2007-06-03 14:27:49 +00002379 host_mb = malloc(msgsz+sizeof(long));
aurel321c54ff92008-10-13 21:08:44 +00002380 host_mb->mtype = (abi_long) tswapl(target_mb->mtype);
2381 memcpy(host_mb->mtext, target_mb->mtext, msgsz);
ths1bc012f2007-06-03 14:27:49 +00002382 ret = get_errno(msgsnd(msqid, host_mb, msgsz, msgflg));
2383 free(host_mb);
2384 unlock_user_struct(target_mb, msgp, 0);
2385
2386 return ret;
2387}
2388
blueswir1992f48a2007-10-14 16:27:31 +00002389static inline abi_long do_msgrcv(int msqid, abi_long msgp,
aurel321c54ff92008-10-13 21:08:44 +00002390 unsigned int msgsz, abi_long msgtyp,
blueswir1992f48a2007-10-14 16:27:31 +00002391 int msgflg)
ths1bc012f2007-06-03 14:27:49 +00002392{
2393 struct target_msgbuf *target_mb;
bellard579a97f2007-11-11 14:26:47 +00002394 char *target_mtext;
ths1bc012f2007-06-03 14:27:49 +00002395 struct msgbuf *host_mb;
blueswir1992f48a2007-10-14 16:27:31 +00002396 abi_long ret = 0;
ths1bc012f2007-06-03 14:27:49 +00002397
bellard579a97f2007-11-11 14:26:47 +00002398 if (!lock_user_struct(VERIFY_WRITE, target_mb, msgp, 0))
2399 return -TARGET_EFAULT;
aurel321c54ff92008-10-13 21:08:44 +00002400
ths1bc012f2007-06-03 14:27:49 +00002401 host_mb = malloc(msgsz+sizeof(long));
aurel321c54ff92008-10-13 21:08:44 +00002402 ret = get_errno(msgrcv(msqid, host_mb, msgsz, tswapl(msgtyp), msgflg));
2403
bellard579a97f2007-11-11 14:26:47 +00002404 if (ret > 0) {
2405 abi_ulong target_mtext_addr = msgp + sizeof(abi_ulong);
2406 target_mtext = lock_user(VERIFY_WRITE, target_mtext_addr, ret, 0);
2407 if (!target_mtext) {
2408 ret = -TARGET_EFAULT;
2409 goto end;
2410 }
aurel321c54ff92008-10-13 21:08:44 +00002411 memcpy(target_mb->mtext, host_mb->mtext, ret);
bellard579a97f2007-11-11 14:26:47 +00002412 unlock_user(target_mtext, target_mtext_addr, ret);
2413 }
aurel321c54ff92008-10-13 21:08:44 +00002414
ths1bc012f2007-06-03 14:27:49 +00002415 target_mb->mtype = tswapl(host_mb->mtype);
2416 free(host_mb);
ths1bc012f2007-06-03 14:27:49 +00002417
bellard579a97f2007-11-11 14:26:47 +00002418end:
2419 if (target_mb)
2420 unlock_user_struct(target_mb, msgp, 1);
ths1bc012f2007-06-03 14:27:49 +00002421 return ret;
2422}
2423
Riku Voipio88a8c982009-04-03 10:42:00 +03002424struct target_shmid_ds
2425{
2426 struct target_ipc_perm shm_perm;
2427 abi_ulong shm_segsz;
2428 abi_ulong shm_atime;
2429#if TARGET_ABI_BITS == 32
2430 abi_ulong __unused1;
2431#endif
2432 abi_ulong shm_dtime;
2433#if TARGET_ABI_BITS == 32
2434 abi_ulong __unused2;
2435#endif
2436 abi_ulong shm_ctime;
2437#if TARGET_ABI_BITS == 32
2438 abi_ulong __unused3;
2439#endif
2440 int shm_cpid;
2441 int shm_lpid;
2442 abi_ulong shm_nattch;
2443 unsigned long int __unused4;
2444 unsigned long int __unused5;
2445};
2446
2447static inline abi_long target_to_host_shmid_ds(struct shmid_ds *host_sd,
2448 abi_ulong target_addr)
2449{
2450 struct target_shmid_ds *target_sd;
2451
2452 if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
2453 return -TARGET_EFAULT;
2454 if (target_to_host_ipc_perm(&(host_sd->shm_perm), target_addr))
2455 return -TARGET_EFAULT;
2456 __get_user(host_sd->shm_segsz, &target_sd->shm_segsz);
2457 __get_user(host_sd->shm_atime, &target_sd->shm_atime);
2458 __get_user(host_sd->shm_dtime, &target_sd->shm_dtime);
2459 __get_user(host_sd->shm_ctime, &target_sd->shm_ctime);
2460 __get_user(host_sd->shm_cpid, &target_sd->shm_cpid);
2461 __get_user(host_sd->shm_lpid, &target_sd->shm_lpid);
2462 __get_user(host_sd->shm_nattch, &target_sd->shm_nattch);
2463 unlock_user_struct(target_sd, target_addr, 0);
2464 return 0;
2465}
2466
2467static inline abi_long host_to_target_shmid_ds(abi_ulong target_addr,
2468 struct shmid_ds *host_sd)
2469{
2470 struct target_shmid_ds *target_sd;
2471
2472 if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
2473 return -TARGET_EFAULT;
2474 if (host_to_target_ipc_perm(target_addr, &(host_sd->shm_perm)))
2475 return -TARGET_EFAULT;
2476 __put_user(host_sd->shm_segsz, &target_sd->shm_segsz);
2477 __put_user(host_sd->shm_atime, &target_sd->shm_atime);
2478 __put_user(host_sd->shm_dtime, &target_sd->shm_dtime);
2479 __put_user(host_sd->shm_ctime, &target_sd->shm_ctime);
2480 __put_user(host_sd->shm_cpid, &target_sd->shm_cpid);
2481 __put_user(host_sd->shm_lpid, &target_sd->shm_lpid);
2482 __put_user(host_sd->shm_nattch, &target_sd->shm_nattch);
2483 unlock_user_struct(target_sd, target_addr, 1);
2484 return 0;
2485}
2486
2487struct target_shminfo {
2488 abi_ulong shmmax;
2489 abi_ulong shmmin;
2490 abi_ulong shmmni;
2491 abi_ulong shmseg;
2492 abi_ulong shmall;
2493};
2494
2495static inline abi_long host_to_target_shminfo(abi_ulong target_addr,
2496 struct shminfo *host_shminfo)
2497{
2498 struct target_shminfo *target_shminfo;
2499 if (!lock_user_struct(VERIFY_WRITE, target_shminfo, target_addr, 0))
2500 return -TARGET_EFAULT;
2501 __put_user(host_shminfo->shmmax, &target_shminfo->shmmax);
2502 __put_user(host_shminfo->shmmin, &target_shminfo->shmmin);
2503 __put_user(host_shminfo->shmmni, &target_shminfo->shmmni);
2504 __put_user(host_shminfo->shmseg, &target_shminfo->shmseg);
2505 __put_user(host_shminfo->shmall, &target_shminfo->shmall);
2506 unlock_user_struct(target_shminfo, target_addr, 1);
2507 return 0;
2508}
2509
2510struct target_shm_info {
2511 int used_ids;
2512 abi_ulong shm_tot;
2513 abi_ulong shm_rss;
2514 abi_ulong shm_swp;
2515 abi_ulong swap_attempts;
2516 abi_ulong swap_successes;
2517};
2518
2519static inline abi_long host_to_target_shm_info(abi_ulong target_addr,
2520 struct shm_info *host_shm_info)
2521{
2522 struct target_shm_info *target_shm_info;
2523 if (!lock_user_struct(VERIFY_WRITE, target_shm_info, target_addr, 0))
2524 return -TARGET_EFAULT;
2525 __put_user(host_shm_info->used_ids, &target_shm_info->used_ids);
2526 __put_user(host_shm_info->shm_tot, &target_shm_info->shm_tot);
2527 __put_user(host_shm_info->shm_rss, &target_shm_info->shm_rss);
2528 __put_user(host_shm_info->shm_swp, &target_shm_info->shm_swp);
2529 __put_user(host_shm_info->swap_attempts, &target_shm_info->swap_attempts);
2530 __put_user(host_shm_info->swap_successes, &target_shm_info->swap_successes);
2531 unlock_user_struct(target_shm_info, target_addr, 1);
2532 return 0;
2533}
2534
2535static inline abi_long do_shmctl(int shmid, int cmd, abi_long buf)
2536{
2537 struct shmid_ds dsarg;
2538 struct shminfo shminfo;
2539 struct shm_info shm_info;
2540 abi_long ret = -TARGET_EINVAL;
2541
2542 cmd &= 0xff;
2543
2544 switch(cmd) {
2545 case IPC_STAT:
2546 case IPC_SET:
2547 case SHM_STAT:
2548 if (target_to_host_shmid_ds(&dsarg, buf))
2549 return -TARGET_EFAULT;
2550 ret = get_errno(shmctl(shmid, cmd, &dsarg));
2551 if (host_to_target_shmid_ds(buf, &dsarg))
2552 return -TARGET_EFAULT;
2553 break;
2554 case IPC_INFO:
2555 ret = get_errno(shmctl(shmid, cmd, (struct shmid_ds *)&shminfo));
2556 if (host_to_target_shminfo(buf, &shminfo))
2557 return -TARGET_EFAULT;
2558 break;
2559 case SHM_INFO:
2560 ret = get_errno(shmctl(shmid, cmd, (struct shmid_ds *)&shm_info));
2561 if (host_to_target_shm_info(buf, &shm_info))
2562 return -TARGET_EFAULT;
2563 break;
2564 case IPC_RMID:
2565 case SHM_LOCK:
2566 case SHM_UNLOCK:
2567 ret = get_errno(shmctl(shmid, cmd, NULL));
2568 break;
2569 }
2570
2571 return ret;
2572}
2573
2574static inline abi_ulong do_shmat(int shmid, abi_ulong shmaddr, int shmflg)
2575{
2576 abi_long raddr;
2577 void *host_raddr;
2578 struct shmid_ds shm_info;
2579 int i,ret;
2580
2581 /* find out the length of the shared memory segment */
2582 ret = get_errno(shmctl(shmid, IPC_STAT, &shm_info));
2583 if (is_error(ret)) {
2584 /* can't get length, bail out */
2585 return ret;
2586 }
2587
2588 mmap_lock();
2589
2590 if (shmaddr)
2591 host_raddr = shmat(shmid, (void *)g2h(shmaddr), shmflg);
2592 else {
2593 abi_ulong mmap_start;
2594
2595 mmap_start = mmap_find_vma(0, shm_info.shm_segsz);
2596
2597 if (mmap_start == -1) {
2598 errno = ENOMEM;
2599 host_raddr = (void *)-1;
2600 } else
2601 host_raddr = shmat(shmid, g2h(mmap_start), shmflg | SHM_REMAP);
2602 }
2603
2604 if (host_raddr == (void *)-1) {
2605 mmap_unlock();
2606 return get_errno((long)host_raddr);
2607 }
2608 raddr=h2g((unsigned long)host_raddr);
2609
2610 page_set_flags(raddr, raddr + shm_info.shm_segsz,
2611 PAGE_VALID | PAGE_READ |
2612 ((shmflg & SHM_RDONLY)? 0 : PAGE_WRITE));
2613
2614 for (i = 0; i < N_SHM_REGIONS; i++) {
2615 if (shm_regions[i].start == 0) {
2616 shm_regions[i].start = raddr;
2617 shm_regions[i].size = shm_info.shm_segsz;
2618 break;
2619 }
2620 }
2621
2622 mmap_unlock();
2623 return raddr;
2624
2625}
2626
2627static inline abi_long do_shmdt(abi_ulong shmaddr)
2628{
2629 int i;
2630
2631 for (i = 0; i < N_SHM_REGIONS; ++i) {
2632 if (shm_regions[i].start == shmaddr) {
2633 shm_regions[i].start = 0;
2634 page_set_flags(shmaddr, shm_regions[i].size, 0);
2635 break;
2636 }
2637 }
2638
2639 return get_errno(shmdt(g2h(shmaddr)));
2640}
2641
aurel321c54ff92008-10-13 21:08:44 +00002642#ifdef TARGET_NR_ipc
pbrook53a59602006-03-25 19:31:22 +00002643/* ??? This only works with linear mappings. */
ths0da46a62007-10-20 20:23:07 +00002644/* do_ipc() must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00002645static abi_long do_ipc(unsigned int call, int first,
2646 int second, int third,
2647 abi_long ptr, abi_long fifth)
bellard8853f862004-02-22 14:57:26 +00002648{
2649 int version;
blueswir1992f48a2007-10-14 16:27:31 +00002650 abi_long ret = 0;
bellard8853f862004-02-22 14:57:26 +00002651
2652 version = call >> 16;
2653 call &= 0xffff;
2654
2655 switch (call) {
thsfa294812007-02-02 22:05:00 +00002656 case IPCOP_semop:
aurel32e5289082009-04-18 16:16:12 +00002657 ret = do_semop(first, ptr, second);
thsfa294812007-02-02 22:05:00 +00002658 break;
2659
2660 case IPCOP_semget:
2661 ret = get_errno(semget(first, second, third));
2662 break;
2663
2664 case IPCOP_semctl:
aurel32e5289082009-04-18 16:16:12 +00002665 ret = do_semctl(first, second, third, (union target_semun)(abi_ulong) ptr);
thsfa294812007-02-02 22:05:00 +00002666 break;
thsd96372e2007-02-02 22:05:44 +00002667
aurel321c54ff92008-10-13 21:08:44 +00002668 case IPCOP_msgget:
2669 ret = get_errno(msgget(first, second));
2670 break;
thsd96372e2007-02-02 22:05:44 +00002671
aurel321c54ff92008-10-13 21:08:44 +00002672 case IPCOP_msgsnd:
2673 ret = do_msgsnd(first, ptr, second, third);
2674 break;
thsd96372e2007-02-02 22:05:44 +00002675
aurel321c54ff92008-10-13 21:08:44 +00002676 case IPCOP_msgctl:
2677 ret = do_msgctl(first, second, ptr);
2678 break;
thsd96372e2007-02-02 22:05:44 +00002679
aurel321c54ff92008-10-13 21:08:44 +00002680 case IPCOP_msgrcv:
2681 switch (version) {
2682 case 0:
2683 {
2684 struct target_ipc_kludge {
2685 abi_long msgp;
2686 abi_long msgtyp;
2687 } *tmp;
thsd96372e2007-02-02 22:05:44 +00002688
aurel321c54ff92008-10-13 21:08:44 +00002689 if (!lock_user_struct(VERIFY_READ, tmp, ptr, 1)) {
2690 ret = -TARGET_EFAULT;
2691 break;
ths1bc012f2007-06-03 14:27:49 +00002692 }
aurel321c54ff92008-10-13 21:08:44 +00002693
2694 ret = do_msgrcv(first, tmp->msgp, second, tmp->msgtyp, third);
2695
2696 unlock_user_struct(tmp, ptr, 0);
2697 break;
2698 }
2699 default:
2700 ret = do_msgrcv(first, ptr, second, fifth, third);
2701 }
2702 break;
thsd96372e2007-02-02 22:05:44 +00002703
bellard8853f862004-02-22 14:57:26 +00002704 case IPCOP_shmat:
Riku Voipio88a8c982009-04-03 10:42:00 +03002705 switch (version) {
2706 default:
bellard5a4a8982007-11-11 17:39:18 +00002707 {
2708 abi_ulong raddr;
Riku Voipio88a8c982009-04-03 10:42:00 +03002709 raddr = do_shmat(first, ptr, second);
2710 if (is_error(raddr))
2711 return get_errno(raddr);
bellard2f619692007-11-16 10:46:05 +00002712 if (put_user_ual(raddr, third))
bellard5a4a8982007-11-11 17:39:18 +00002713 return -TARGET_EFAULT;
Riku Voipio88a8c982009-04-03 10:42:00 +03002714 break;
2715 }
2716 case 1:
2717 ret = -TARGET_EINVAL;
2718 break;
bellard5a4a8982007-11-11 17:39:18 +00002719 }
bellard8853f862004-02-22 14:57:26 +00002720 break;
2721 case IPCOP_shmdt:
Riku Voipio88a8c982009-04-03 10:42:00 +03002722 ret = do_shmdt(ptr);
bellard8853f862004-02-22 14:57:26 +00002723 break;
2724
2725 case IPCOP_shmget:
2726 /* IPC_* flag values are the same on all linux platforms */
2727 ret = get_errno(shmget(first, second, third));
2728 break;
2729
2730 /* IPC_* and SHM_* command values are the same on all linux platforms */
2731 case IPCOP_shmctl:
Riku Voipio88a8c982009-04-03 10:42:00 +03002732 ret = do_shmctl(first, second, third);
bellard8853f862004-02-22 14:57:26 +00002733 break;
2734 default:
j_mayer32407102007-09-26 23:01:49 +00002735 gemu_log("Unsupported ipc call: %d (version %d)\n", call, version);
ths0da46a62007-10-20 20:23:07 +00002736 ret = -TARGET_ENOSYS;
bellard8853f862004-02-22 14:57:26 +00002737 break;
2738 }
2739 return ret;
2740}
j_mayer32407102007-09-26 23:01:49 +00002741#endif
bellard8853f862004-02-22 14:57:26 +00002742
bellard31e31b82003-02-18 22:55:36 +00002743/* kernel structure types definitions */
2744#define IFNAMSIZ 16
2745
Blue Swirl001faf32009-05-13 17:53:17 +00002746#define STRUCT(name, ...) STRUCT_ ## name,
bellard31e31b82003-02-18 22:55:36 +00002747#define STRUCT_SPECIAL(name) STRUCT_ ## name,
2748enum {
2749#include "syscall_types.h"
2750};
2751#undef STRUCT
2752#undef STRUCT_SPECIAL
2753
Blue Swirl001faf32009-05-13 17:53:17 +00002754#define STRUCT(name, ...) static const argtype struct_ ## name ## _def[] = { __VA_ARGS__, TYPE_NULL };
bellard31e31b82003-02-18 22:55:36 +00002755#define STRUCT_SPECIAL(name)
2756#include "syscall_types.h"
2757#undef STRUCT
2758#undef STRUCT_SPECIAL
2759
2760typedef struct IOCTLEntry {
bellard2ab83ea2003-06-15 19:56:46 +00002761 unsigned int target_cmd;
2762 unsigned int host_cmd;
bellard31e31b82003-02-18 22:55:36 +00002763 const char *name;
2764 int access;
bellard1a9353d2003-03-16 20:28:50 +00002765 const argtype arg_type[5];
bellard31e31b82003-02-18 22:55:36 +00002766} IOCTLEntry;
2767
2768#define IOC_R 0x0001
2769#define IOC_W 0x0002
2770#define IOC_RW (IOC_R | IOC_W)
2771
2772#define MAX_STRUCT_SIZE 4096
2773
blueswir19f106a72008-10-05 10:52:52 +00002774static IOCTLEntry ioctl_entries[] = {
Blue Swirl001faf32009-05-13 17:53:17 +00002775#define IOCTL(cmd, access, ...) \
2776 { TARGET_ ## cmd, cmd, #cmd, access, { __VA_ARGS__ } },
bellard31e31b82003-02-18 22:55:36 +00002777#include "ioctls.h"
2778 { 0, 0, },
2779};
2780
pbrook53a59602006-03-25 19:31:22 +00002781/* ??? Implement proper locking for ioctls. */
ths0da46a62007-10-20 20:23:07 +00002782/* do_ioctl() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00002783static abi_long do_ioctl(int fd, abi_long cmd, abi_long arg)
bellard31e31b82003-02-18 22:55:36 +00002784{
2785 const IOCTLEntry *ie;
2786 const argtype *arg_type;
blueswir1992f48a2007-10-14 16:27:31 +00002787 abi_long ret;
bellard31e31b82003-02-18 22:55:36 +00002788 uint8_t buf_temp[MAX_STRUCT_SIZE];
pbrook53a59602006-03-25 19:31:22 +00002789 int target_size;
2790 void *argptr;
bellard31e31b82003-02-18 22:55:36 +00002791
2792 ie = ioctl_entries;
2793 for(;;) {
2794 if (ie->target_cmd == 0) {
j_mayer32407102007-09-26 23:01:49 +00002795 gemu_log("Unsupported ioctl: cmd=0x%04lx\n", (long)cmd);
ths0da46a62007-10-20 20:23:07 +00002796 return -TARGET_ENOSYS;
bellard31e31b82003-02-18 22:55:36 +00002797 }
2798 if (ie->target_cmd == cmd)
2799 break;
2800 ie++;
2801 }
2802 arg_type = ie->arg_type;
bellard9de5e442003-03-23 16:49:39 +00002803#if defined(DEBUG)
j_mayer32407102007-09-26 23:01:49 +00002804 gemu_log("ioctl: cmd=0x%04lx (%s)\n", (long)cmd, ie->name);
bellard72f03902003-02-18 23:33:18 +00002805#endif
bellard31e31b82003-02-18 22:55:36 +00002806 switch(arg_type[0]) {
2807 case TYPE_NULL:
2808 /* no argument */
2809 ret = get_errno(ioctl(fd, ie->host_cmd));
2810 break;
2811 case TYPE_PTRVOID:
2812 case TYPE_INT:
2813 /* int argment */
2814 ret = get_errno(ioctl(fd, ie->host_cmd, arg));
2815 break;
2816 case TYPE_PTR:
2817 arg_type++;
pbrook53a59602006-03-25 19:31:22 +00002818 target_size = thunk_type_size(arg_type, 0);
bellard31e31b82003-02-18 22:55:36 +00002819 switch(ie->access) {
2820 case IOC_R:
2821 ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
2822 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00002823 argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
2824 if (!argptr)
2825 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00002826 thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
2827 unlock_user(argptr, arg, target_size);
bellard31e31b82003-02-18 22:55:36 +00002828 }
2829 break;
2830 case IOC_W:
bellard579a97f2007-11-11 14:26:47 +00002831 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
2832 if (!argptr)
2833 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00002834 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
2835 unlock_user(argptr, arg, 0);
bellard31e31b82003-02-18 22:55:36 +00002836 ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
2837 break;
2838 default:
2839 case IOC_RW:
bellard579a97f2007-11-11 14:26:47 +00002840 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
2841 if (!argptr)
2842 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00002843 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
2844 unlock_user(argptr, arg, 0);
bellard31e31b82003-02-18 22:55:36 +00002845 ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
2846 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00002847 argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
2848 if (!argptr)
2849 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00002850 thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
2851 unlock_user(argptr, arg, target_size);
bellard31e31b82003-02-18 22:55:36 +00002852 }
2853 break;
2854 }
2855 break;
2856 default:
j_mayer32407102007-09-26 23:01:49 +00002857 gemu_log("Unsupported ioctl type: cmd=0x%04lx type=%d\n",
2858 (long)cmd, arg_type[0]);
ths0da46a62007-10-20 20:23:07 +00002859 ret = -TARGET_ENOSYS;
bellard31e31b82003-02-18 22:55:36 +00002860 break;
2861 }
2862 return ret;
2863}
2864
blueswir1b39bc502008-10-05 10:51:10 +00002865static const bitmask_transtbl iflag_tbl[] = {
bellard31e31b82003-02-18 22:55:36 +00002866 { TARGET_IGNBRK, TARGET_IGNBRK, IGNBRK, IGNBRK },
2867 { TARGET_BRKINT, TARGET_BRKINT, BRKINT, BRKINT },
2868 { TARGET_IGNPAR, TARGET_IGNPAR, IGNPAR, IGNPAR },
2869 { TARGET_PARMRK, TARGET_PARMRK, PARMRK, PARMRK },
2870 { TARGET_INPCK, TARGET_INPCK, INPCK, INPCK },
2871 { TARGET_ISTRIP, TARGET_ISTRIP, ISTRIP, ISTRIP },
2872 { TARGET_INLCR, TARGET_INLCR, INLCR, INLCR },
2873 { TARGET_IGNCR, TARGET_IGNCR, IGNCR, IGNCR },
2874 { TARGET_ICRNL, TARGET_ICRNL, ICRNL, ICRNL },
2875 { TARGET_IUCLC, TARGET_IUCLC, IUCLC, IUCLC },
2876 { TARGET_IXON, TARGET_IXON, IXON, IXON },
2877 { TARGET_IXANY, TARGET_IXANY, IXANY, IXANY },
2878 { TARGET_IXOFF, TARGET_IXOFF, IXOFF, IXOFF },
2879 { TARGET_IMAXBEL, TARGET_IMAXBEL, IMAXBEL, IMAXBEL },
2880 { 0, 0, 0, 0 }
2881};
2882
blueswir1b39bc502008-10-05 10:51:10 +00002883static const bitmask_transtbl oflag_tbl[] = {
bellard31e31b82003-02-18 22:55:36 +00002884 { TARGET_OPOST, TARGET_OPOST, OPOST, OPOST },
2885 { TARGET_OLCUC, TARGET_OLCUC, OLCUC, OLCUC },
2886 { TARGET_ONLCR, TARGET_ONLCR, ONLCR, ONLCR },
2887 { TARGET_OCRNL, TARGET_OCRNL, OCRNL, OCRNL },
2888 { TARGET_ONOCR, TARGET_ONOCR, ONOCR, ONOCR },
2889 { TARGET_ONLRET, TARGET_ONLRET, ONLRET, ONLRET },
2890 { TARGET_OFILL, TARGET_OFILL, OFILL, OFILL },
2891 { TARGET_OFDEL, TARGET_OFDEL, OFDEL, OFDEL },
2892 { TARGET_NLDLY, TARGET_NL0, NLDLY, NL0 },
2893 { TARGET_NLDLY, TARGET_NL1, NLDLY, NL1 },
2894 { TARGET_CRDLY, TARGET_CR0, CRDLY, CR0 },
2895 { TARGET_CRDLY, TARGET_CR1, CRDLY, CR1 },
2896 { TARGET_CRDLY, TARGET_CR2, CRDLY, CR2 },
2897 { TARGET_CRDLY, TARGET_CR3, CRDLY, CR3 },
2898 { TARGET_TABDLY, TARGET_TAB0, TABDLY, TAB0 },
2899 { TARGET_TABDLY, TARGET_TAB1, TABDLY, TAB1 },
2900 { TARGET_TABDLY, TARGET_TAB2, TABDLY, TAB2 },
2901 { TARGET_TABDLY, TARGET_TAB3, TABDLY, TAB3 },
2902 { TARGET_BSDLY, TARGET_BS0, BSDLY, BS0 },
2903 { TARGET_BSDLY, TARGET_BS1, BSDLY, BS1 },
2904 { TARGET_VTDLY, TARGET_VT0, VTDLY, VT0 },
2905 { TARGET_VTDLY, TARGET_VT1, VTDLY, VT1 },
2906 { TARGET_FFDLY, TARGET_FF0, FFDLY, FF0 },
2907 { TARGET_FFDLY, TARGET_FF1, FFDLY, FF1 },
2908 { 0, 0, 0, 0 }
2909};
2910
blueswir1b39bc502008-10-05 10:51:10 +00002911static const bitmask_transtbl cflag_tbl[] = {
bellard31e31b82003-02-18 22:55:36 +00002912 { TARGET_CBAUD, TARGET_B0, CBAUD, B0 },
2913 { TARGET_CBAUD, TARGET_B50, CBAUD, B50 },
2914 { TARGET_CBAUD, TARGET_B75, CBAUD, B75 },
2915 { TARGET_CBAUD, TARGET_B110, CBAUD, B110 },
2916 { TARGET_CBAUD, TARGET_B134, CBAUD, B134 },
2917 { TARGET_CBAUD, TARGET_B150, CBAUD, B150 },
2918 { TARGET_CBAUD, TARGET_B200, CBAUD, B200 },
2919 { TARGET_CBAUD, TARGET_B300, CBAUD, B300 },
2920 { TARGET_CBAUD, TARGET_B600, CBAUD, B600 },
2921 { TARGET_CBAUD, TARGET_B1200, CBAUD, B1200 },
2922 { TARGET_CBAUD, TARGET_B1800, CBAUD, B1800 },
2923 { TARGET_CBAUD, TARGET_B2400, CBAUD, B2400 },
2924 { TARGET_CBAUD, TARGET_B4800, CBAUD, B4800 },
2925 { TARGET_CBAUD, TARGET_B9600, CBAUD, B9600 },
2926 { TARGET_CBAUD, TARGET_B19200, CBAUD, B19200 },
2927 { TARGET_CBAUD, TARGET_B38400, CBAUD, B38400 },
2928 { TARGET_CBAUD, TARGET_B57600, CBAUD, B57600 },
2929 { TARGET_CBAUD, TARGET_B115200, CBAUD, B115200 },
2930 { TARGET_CBAUD, TARGET_B230400, CBAUD, B230400 },
2931 { TARGET_CBAUD, TARGET_B460800, CBAUD, B460800 },
2932 { TARGET_CSIZE, TARGET_CS5, CSIZE, CS5 },
2933 { TARGET_CSIZE, TARGET_CS6, CSIZE, CS6 },
2934 { TARGET_CSIZE, TARGET_CS7, CSIZE, CS7 },
2935 { TARGET_CSIZE, TARGET_CS8, CSIZE, CS8 },
2936 { TARGET_CSTOPB, TARGET_CSTOPB, CSTOPB, CSTOPB },
2937 { TARGET_CREAD, TARGET_CREAD, CREAD, CREAD },
2938 { TARGET_PARENB, TARGET_PARENB, PARENB, PARENB },
2939 { TARGET_PARODD, TARGET_PARODD, PARODD, PARODD },
2940 { TARGET_HUPCL, TARGET_HUPCL, HUPCL, HUPCL },
2941 { TARGET_CLOCAL, TARGET_CLOCAL, CLOCAL, CLOCAL },
2942 { TARGET_CRTSCTS, TARGET_CRTSCTS, CRTSCTS, CRTSCTS },
2943 { 0, 0, 0, 0 }
2944};
2945
blueswir1b39bc502008-10-05 10:51:10 +00002946static const bitmask_transtbl lflag_tbl[] = {
bellard31e31b82003-02-18 22:55:36 +00002947 { TARGET_ISIG, TARGET_ISIG, ISIG, ISIG },
2948 { TARGET_ICANON, TARGET_ICANON, ICANON, ICANON },
2949 { TARGET_XCASE, TARGET_XCASE, XCASE, XCASE },
2950 { TARGET_ECHO, TARGET_ECHO, ECHO, ECHO },
2951 { TARGET_ECHOE, TARGET_ECHOE, ECHOE, ECHOE },
2952 { TARGET_ECHOK, TARGET_ECHOK, ECHOK, ECHOK },
2953 { TARGET_ECHONL, TARGET_ECHONL, ECHONL, ECHONL },
2954 { TARGET_NOFLSH, TARGET_NOFLSH, NOFLSH, NOFLSH },
2955 { TARGET_TOSTOP, TARGET_TOSTOP, TOSTOP, TOSTOP },
2956 { TARGET_ECHOCTL, TARGET_ECHOCTL, ECHOCTL, ECHOCTL },
2957 { TARGET_ECHOPRT, TARGET_ECHOPRT, ECHOPRT, ECHOPRT },
2958 { TARGET_ECHOKE, TARGET_ECHOKE, ECHOKE, ECHOKE },
2959 { TARGET_FLUSHO, TARGET_FLUSHO, FLUSHO, FLUSHO },
2960 { TARGET_PENDIN, TARGET_PENDIN, PENDIN, PENDIN },
2961 { TARGET_IEXTEN, TARGET_IEXTEN, IEXTEN, IEXTEN },
2962 { 0, 0, 0, 0 }
2963};
2964
2965static void target_to_host_termios (void *dst, const void *src)
2966{
2967 struct host_termios *host = dst;
2968 const struct target_termios *target = src;
ths3b46e622007-09-17 08:09:54 +00002969
ths5fafdf22007-09-16 21:08:06 +00002970 host->c_iflag =
bellard31e31b82003-02-18 22:55:36 +00002971 target_to_host_bitmask(tswap32(target->c_iflag), iflag_tbl);
ths5fafdf22007-09-16 21:08:06 +00002972 host->c_oflag =
bellard31e31b82003-02-18 22:55:36 +00002973 target_to_host_bitmask(tswap32(target->c_oflag), oflag_tbl);
ths5fafdf22007-09-16 21:08:06 +00002974 host->c_cflag =
bellard31e31b82003-02-18 22:55:36 +00002975 target_to_host_bitmask(tswap32(target->c_cflag), cflag_tbl);
ths5fafdf22007-09-16 21:08:06 +00002976 host->c_lflag =
bellard31e31b82003-02-18 22:55:36 +00002977 target_to_host_bitmask(tswap32(target->c_lflag), lflag_tbl);
2978 host->c_line = target->c_line;
ths3b46e622007-09-17 08:09:54 +00002979
Arnaud Patard44607122009-04-21 17:39:08 +03002980 memset(host->c_cc, 0, sizeof(host->c_cc));
ths5fafdf22007-09-16 21:08:06 +00002981 host->c_cc[VINTR] = target->c_cc[TARGET_VINTR];
2982 host->c_cc[VQUIT] = target->c_cc[TARGET_VQUIT];
ths3b46e622007-09-17 08:09:54 +00002983 host->c_cc[VERASE] = target->c_cc[TARGET_VERASE];
ths5fafdf22007-09-16 21:08:06 +00002984 host->c_cc[VKILL] = target->c_cc[TARGET_VKILL];
ths3b46e622007-09-17 08:09:54 +00002985 host->c_cc[VEOF] = target->c_cc[TARGET_VEOF];
ths5fafdf22007-09-16 21:08:06 +00002986 host->c_cc[VTIME] = target->c_cc[TARGET_VTIME];
ths3b46e622007-09-17 08:09:54 +00002987 host->c_cc[VMIN] = target->c_cc[TARGET_VMIN];
ths5fafdf22007-09-16 21:08:06 +00002988 host->c_cc[VSWTC] = target->c_cc[TARGET_VSWTC];
ths3b46e622007-09-17 08:09:54 +00002989 host->c_cc[VSTART] = target->c_cc[TARGET_VSTART];
ths5fafdf22007-09-16 21:08:06 +00002990 host->c_cc[VSTOP] = target->c_cc[TARGET_VSTOP];
2991 host->c_cc[VSUSP] = target->c_cc[TARGET_VSUSP];
ths3b46e622007-09-17 08:09:54 +00002992 host->c_cc[VEOL] = target->c_cc[TARGET_VEOL];
2993 host->c_cc[VREPRINT] = target->c_cc[TARGET_VREPRINT];
2994 host->c_cc[VDISCARD] = target->c_cc[TARGET_VDISCARD];
2995 host->c_cc[VWERASE] = target->c_cc[TARGET_VWERASE];
2996 host->c_cc[VLNEXT] = target->c_cc[TARGET_VLNEXT];
ths5fafdf22007-09-16 21:08:06 +00002997 host->c_cc[VEOL2] = target->c_cc[TARGET_VEOL2];
bellard31e31b82003-02-18 22:55:36 +00002998}
ths3b46e622007-09-17 08:09:54 +00002999
bellard31e31b82003-02-18 22:55:36 +00003000static void host_to_target_termios (void *dst, const void *src)
3001{
3002 struct target_termios *target = dst;
3003 const struct host_termios *host = src;
3004
ths5fafdf22007-09-16 21:08:06 +00003005 target->c_iflag =
bellard31e31b82003-02-18 22:55:36 +00003006 tswap32(host_to_target_bitmask(host->c_iflag, iflag_tbl));
ths5fafdf22007-09-16 21:08:06 +00003007 target->c_oflag =
bellard31e31b82003-02-18 22:55:36 +00003008 tswap32(host_to_target_bitmask(host->c_oflag, oflag_tbl));
ths5fafdf22007-09-16 21:08:06 +00003009 target->c_cflag =
bellard31e31b82003-02-18 22:55:36 +00003010 tswap32(host_to_target_bitmask(host->c_cflag, cflag_tbl));
ths5fafdf22007-09-16 21:08:06 +00003011 target->c_lflag =
bellard31e31b82003-02-18 22:55:36 +00003012 tswap32(host_to_target_bitmask(host->c_lflag, lflag_tbl));
3013 target->c_line = host->c_line;
ths3b46e622007-09-17 08:09:54 +00003014
Arnaud Patard44607122009-04-21 17:39:08 +03003015 memset(target->c_cc, 0, sizeof(target->c_cc));
bellard31e31b82003-02-18 22:55:36 +00003016 target->c_cc[TARGET_VINTR] = host->c_cc[VINTR];
3017 target->c_cc[TARGET_VQUIT] = host->c_cc[VQUIT];
3018 target->c_cc[TARGET_VERASE] = host->c_cc[VERASE];
3019 target->c_cc[TARGET_VKILL] = host->c_cc[VKILL];
3020 target->c_cc[TARGET_VEOF] = host->c_cc[VEOF];
3021 target->c_cc[TARGET_VTIME] = host->c_cc[VTIME];
3022 target->c_cc[TARGET_VMIN] = host->c_cc[VMIN];
3023 target->c_cc[TARGET_VSWTC] = host->c_cc[VSWTC];
3024 target->c_cc[TARGET_VSTART] = host->c_cc[VSTART];
3025 target->c_cc[TARGET_VSTOP] = host->c_cc[VSTOP];
3026 target->c_cc[TARGET_VSUSP] = host->c_cc[VSUSP];
3027 target->c_cc[TARGET_VEOL] = host->c_cc[VEOL];
3028 target->c_cc[TARGET_VREPRINT] = host->c_cc[VREPRINT];
3029 target->c_cc[TARGET_VDISCARD] = host->c_cc[VDISCARD];
3030 target->c_cc[TARGET_VWERASE] = host->c_cc[VWERASE];
3031 target->c_cc[TARGET_VLNEXT] = host->c_cc[VLNEXT];
3032 target->c_cc[TARGET_VEOL2] = host->c_cc[VEOL2];
3033}
3034
blueswir18e853dc2008-10-05 10:49:32 +00003035static const StructEntry struct_termios_def = {
bellard31e31b82003-02-18 22:55:36 +00003036 .convert = { host_to_target_termios, target_to_host_termios },
3037 .size = { sizeof(struct target_termios), sizeof(struct host_termios) },
3038 .align = { __alignof__(struct target_termios), __alignof__(struct host_termios) },
3039};
3040
bellard5286db72003-06-05 00:57:30 +00003041static bitmask_transtbl mmap_flags_tbl[] = {
3042 { TARGET_MAP_SHARED, TARGET_MAP_SHARED, MAP_SHARED, MAP_SHARED },
3043 { TARGET_MAP_PRIVATE, TARGET_MAP_PRIVATE, MAP_PRIVATE, MAP_PRIVATE },
3044 { TARGET_MAP_FIXED, TARGET_MAP_FIXED, MAP_FIXED, MAP_FIXED },
3045 { TARGET_MAP_ANONYMOUS, TARGET_MAP_ANONYMOUS, MAP_ANONYMOUS, MAP_ANONYMOUS },
3046 { TARGET_MAP_GROWSDOWN, TARGET_MAP_GROWSDOWN, MAP_GROWSDOWN, MAP_GROWSDOWN },
3047 { TARGET_MAP_DENYWRITE, TARGET_MAP_DENYWRITE, MAP_DENYWRITE, MAP_DENYWRITE },
3048 { TARGET_MAP_EXECUTABLE, TARGET_MAP_EXECUTABLE, MAP_EXECUTABLE, MAP_EXECUTABLE },
3049 { TARGET_MAP_LOCKED, TARGET_MAP_LOCKED, MAP_LOCKED, MAP_LOCKED },
3050 { 0, 0, 0, 0 }
3051};
3052
bellard2ab83ea2003-06-15 19:56:46 +00003053#if defined(TARGET_I386)
bellard6dbad632003-03-16 18:05:05 +00003054
3055/* NOTE: there is really one LDT for all the threads */
blueswir1b1d8e522008-10-26 13:43:07 +00003056static uint8_t *ldt_table;
bellard6dbad632003-03-16 18:05:05 +00003057
bellard03acab62007-11-11 14:57:14 +00003058static abi_long read_ldt(abi_ulong ptr, unsigned long bytecount)
bellard6dbad632003-03-16 18:05:05 +00003059{
3060 int size;
pbrook53a59602006-03-25 19:31:22 +00003061 void *p;
bellard6dbad632003-03-16 18:05:05 +00003062
3063 if (!ldt_table)
3064 return 0;
3065 size = TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE;
3066 if (size > bytecount)
3067 size = bytecount;
bellard579a97f2007-11-11 14:26:47 +00003068 p = lock_user(VERIFY_WRITE, ptr, size, 0);
3069 if (!p)
bellard03acab62007-11-11 14:57:14 +00003070 return -TARGET_EFAULT;
bellard579a97f2007-11-11 14:26:47 +00003071 /* ??? Should this by byteswapped? */
pbrook53a59602006-03-25 19:31:22 +00003072 memcpy(p, ldt_table, size);
3073 unlock_user(p, ptr, size);
bellard6dbad632003-03-16 18:05:05 +00003074 return size;
3075}
3076
3077/* XXX: add locking support */
bellard03acab62007-11-11 14:57:14 +00003078static abi_long write_ldt(CPUX86State *env,
3079 abi_ulong ptr, unsigned long bytecount, int oldmode)
bellard6dbad632003-03-16 18:05:05 +00003080{
3081 struct target_modify_ldt_ldt_s ldt_info;
pbrook53a59602006-03-25 19:31:22 +00003082 struct target_modify_ldt_ldt_s *target_ldt_info;
bellard6dbad632003-03-16 18:05:05 +00003083 int seg_32bit, contents, read_exec_only, limit_in_pages;
bellard8d18e892007-11-14 15:18:40 +00003084 int seg_not_present, useable, lm;
bellard6dbad632003-03-16 18:05:05 +00003085 uint32_t *lp, entry_1, entry_2;
3086
3087 if (bytecount != sizeof(ldt_info))
bellard03acab62007-11-11 14:57:14 +00003088 return -TARGET_EINVAL;
bellard579a97f2007-11-11 14:26:47 +00003089 if (!lock_user_struct(VERIFY_READ, target_ldt_info, ptr, 1))
bellard03acab62007-11-11 14:57:14 +00003090 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00003091 ldt_info.entry_number = tswap32(target_ldt_info->entry_number);
3092 ldt_info.base_addr = tswapl(target_ldt_info->base_addr);
3093 ldt_info.limit = tswap32(target_ldt_info->limit);
3094 ldt_info.flags = tswap32(target_ldt_info->flags);
3095 unlock_user_struct(target_ldt_info, ptr, 0);
ths3b46e622007-09-17 08:09:54 +00003096
bellard6dbad632003-03-16 18:05:05 +00003097 if (ldt_info.entry_number >= TARGET_LDT_ENTRIES)
bellard03acab62007-11-11 14:57:14 +00003098 return -TARGET_EINVAL;
bellard6dbad632003-03-16 18:05:05 +00003099 seg_32bit = ldt_info.flags & 1;
3100 contents = (ldt_info.flags >> 1) & 3;
3101 read_exec_only = (ldt_info.flags >> 3) & 1;
3102 limit_in_pages = (ldt_info.flags >> 4) & 1;
3103 seg_not_present = (ldt_info.flags >> 5) & 1;
3104 useable = (ldt_info.flags >> 6) & 1;
bellard8d18e892007-11-14 15:18:40 +00003105#ifdef TARGET_ABI32
3106 lm = 0;
3107#else
3108 lm = (ldt_info.flags >> 7) & 1;
3109#endif
bellard6dbad632003-03-16 18:05:05 +00003110 if (contents == 3) {
3111 if (oldmode)
bellard03acab62007-11-11 14:57:14 +00003112 return -TARGET_EINVAL;
bellard6dbad632003-03-16 18:05:05 +00003113 if (seg_not_present == 0)
bellard03acab62007-11-11 14:57:14 +00003114 return -TARGET_EINVAL;
bellard6dbad632003-03-16 18:05:05 +00003115 }
3116 /* allocate the LDT */
3117 if (!ldt_table) {
balroge4415702008-11-10 02:55:33 +00003118 env->ldt.base = target_mmap(0,
3119 TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE,
3120 PROT_READ|PROT_WRITE,
3121 MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
3122 if (env->ldt.base == -1)
bellard03acab62007-11-11 14:57:14 +00003123 return -TARGET_ENOMEM;
balroge4415702008-11-10 02:55:33 +00003124 memset(g2h(env->ldt.base), 0,
3125 TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE);
bellard6dbad632003-03-16 18:05:05 +00003126 env->ldt.limit = 0xffff;
balroge4415702008-11-10 02:55:33 +00003127 ldt_table = g2h(env->ldt.base);
bellard6dbad632003-03-16 18:05:05 +00003128 }
3129
3130 /* NOTE: same code as Linux kernel */
3131 /* Allow LDTs to be cleared by the user. */
3132 if (ldt_info.base_addr == 0 && ldt_info.limit == 0) {
3133 if (oldmode ||
3134 (contents == 0 &&
3135 read_exec_only == 1 &&
3136 seg_32bit == 0 &&
3137 limit_in_pages == 0 &&
3138 seg_not_present == 1 &&
3139 useable == 0 )) {
3140 entry_1 = 0;
3141 entry_2 = 0;
3142 goto install;
3143 }
3144 }
ths3b46e622007-09-17 08:09:54 +00003145
bellard6dbad632003-03-16 18:05:05 +00003146 entry_1 = ((ldt_info.base_addr & 0x0000ffff) << 16) |
3147 (ldt_info.limit & 0x0ffff);
3148 entry_2 = (ldt_info.base_addr & 0xff000000) |
3149 ((ldt_info.base_addr & 0x00ff0000) >> 16) |
3150 (ldt_info.limit & 0xf0000) |
3151 ((read_exec_only ^ 1) << 9) |
3152 (contents << 10) |
3153 ((seg_not_present ^ 1) << 15) |
3154 (seg_32bit << 22) |
3155 (limit_in_pages << 23) |
bellard8d18e892007-11-14 15:18:40 +00003156 (lm << 21) |
bellard6dbad632003-03-16 18:05:05 +00003157 0x7000;
3158 if (!oldmode)
3159 entry_2 |= (useable << 20);
bellard14ae3ba2003-05-27 23:25:06 +00003160
bellard6dbad632003-03-16 18:05:05 +00003161 /* Install the new entry ... */
3162install:
3163 lp = (uint32_t *)(ldt_table + (ldt_info.entry_number << 3));
3164 lp[0] = tswap32(entry_1);
3165 lp[1] = tswap32(entry_2);
3166 return 0;
3167}
3168
3169/* specific and weird i386 syscalls */
blueswir18fcd3692008-08-17 20:26:25 +00003170static abi_long do_modify_ldt(CPUX86State *env, int func, abi_ulong ptr,
3171 unsigned long bytecount)
bellard6dbad632003-03-16 18:05:05 +00003172{
bellard03acab62007-11-11 14:57:14 +00003173 abi_long ret;
ths3b46e622007-09-17 08:09:54 +00003174
bellard6dbad632003-03-16 18:05:05 +00003175 switch (func) {
3176 case 0:
3177 ret = read_ldt(ptr, bytecount);
3178 break;
3179 case 1:
3180 ret = write_ldt(env, ptr, bytecount, 1);
3181 break;
3182 case 0x11:
3183 ret = write_ldt(env, ptr, bytecount, 0);
3184 break;
bellard03acab62007-11-11 14:57:14 +00003185 default:
3186 ret = -TARGET_ENOSYS;
3187 break;
bellard6dbad632003-03-16 18:05:05 +00003188 }
3189 return ret;
3190}
bellard1b6b0292003-03-22 17:31:38 +00003191
blueswir14583f582008-08-24 10:35:55 +00003192#if defined(TARGET_I386) && defined(TARGET_ABI32)
blueswir18fcd3692008-08-17 20:26:25 +00003193static abi_long do_set_thread_area(CPUX86State *env, abi_ulong ptr)
bellard8d18e892007-11-14 15:18:40 +00003194{
3195 uint64_t *gdt_table = g2h(env->gdt.base);
3196 struct target_modify_ldt_ldt_s ldt_info;
3197 struct target_modify_ldt_ldt_s *target_ldt_info;
3198 int seg_32bit, contents, read_exec_only, limit_in_pages;
3199 int seg_not_present, useable, lm;
3200 uint32_t *lp, entry_1, entry_2;
3201 int i;
3202
3203 lock_user_struct(VERIFY_WRITE, target_ldt_info, ptr, 1);
3204 if (!target_ldt_info)
3205 return -TARGET_EFAULT;
3206 ldt_info.entry_number = tswap32(target_ldt_info->entry_number);
3207 ldt_info.base_addr = tswapl(target_ldt_info->base_addr);
3208 ldt_info.limit = tswap32(target_ldt_info->limit);
3209 ldt_info.flags = tswap32(target_ldt_info->flags);
3210 if (ldt_info.entry_number == -1) {
3211 for (i=TARGET_GDT_ENTRY_TLS_MIN; i<=TARGET_GDT_ENTRY_TLS_MAX; i++) {
3212 if (gdt_table[i] == 0) {
3213 ldt_info.entry_number = i;
3214 target_ldt_info->entry_number = tswap32(i);
3215 break;
3216 }
3217 }
3218 }
3219 unlock_user_struct(target_ldt_info, ptr, 1);
3220
3221 if (ldt_info.entry_number < TARGET_GDT_ENTRY_TLS_MIN ||
3222 ldt_info.entry_number > TARGET_GDT_ENTRY_TLS_MAX)
3223 return -TARGET_EINVAL;
3224 seg_32bit = ldt_info.flags & 1;
3225 contents = (ldt_info.flags >> 1) & 3;
3226 read_exec_only = (ldt_info.flags >> 3) & 1;
3227 limit_in_pages = (ldt_info.flags >> 4) & 1;
3228 seg_not_present = (ldt_info.flags >> 5) & 1;
3229 useable = (ldt_info.flags >> 6) & 1;
3230#ifdef TARGET_ABI32
3231 lm = 0;
3232#else
3233 lm = (ldt_info.flags >> 7) & 1;
3234#endif
3235
3236 if (contents == 3) {
3237 if (seg_not_present == 0)
3238 return -TARGET_EINVAL;
3239 }
3240
3241 /* NOTE: same code as Linux kernel */
3242 /* Allow LDTs to be cleared by the user. */
3243 if (ldt_info.base_addr == 0 && ldt_info.limit == 0) {
3244 if ((contents == 0 &&
3245 read_exec_only == 1 &&
3246 seg_32bit == 0 &&
3247 limit_in_pages == 0 &&
3248 seg_not_present == 1 &&
3249 useable == 0 )) {
3250 entry_1 = 0;
3251 entry_2 = 0;
3252 goto install;
3253 }
3254 }
3255
3256 entry_1 = ((ldt_info.base_addr & 0x0000ffff) << 16) |
3257 (ldt_info.limit & 0x0ffff);
3258 entry_2 = (ldt_info.base_addr & 0xff000000) |
3259 ((ldt_info.base_addr & 0x00ff0000) >> 16) |
3260 (ldt_info.limit & 0xf0000) |
3261 ((read_exec_only ^ 1) << 9) |
3262 (contents << 10) |
3263 ((seg_not_present ^ 1) << 15) |
3264 (seg_32bit << 22) |
3265 (limit_in_pages << 23) |
3266 (useable << 20) |
3267 (lm << 21) |
3268 0x7000;
3269
3270 /* Install the new entry ... */
3271install:
3272 lp = (uint32_t *)(gdt_table + ldt_info.entry_number);
3273 lp[0] = tswap32(entry_1);
3274 lp[1] = tswap32(entry_2);
3275 return 0;
3276}
3277
blueswir18fcd3692008-08-17 20:26:25 +00003278static abi_long do_get_thread_area(CPUX86State *env, abi_ulong ptr)
bellard8d18e892007-11-14 15:18:40 +00003279{
3280 struct target_modify_ldt_ldt_s *target_ldt_info;
3281 uint64_t *gdt_table = g2h(env->gdt.base);
3282 uint32_t base_addr, limit, flags;
3283 int seg_32bit, contents, read_exec_only, limit_in_pages, idx;
3284 int seg_not_present, useable, lm;
3285 uint32_t *lp, entry_1, entry_2;
3286
3287 lock_user_struct(VERIFY_WRITE, target_ldt_info, ptr, 1);
3288 if (!target_ldt_info)
3289 return -TARGET_EFAULT;
3290 idx = tswap32(target_ldt_info->entry_number);
3291 if (idx < TARGET_GDT_ENTRY_TLS_MIN ||
3292 idx > TARGET_GDT_ENTRY_TLS_MAX) {
3293 unlock_user_struct(target_ldt_info, ptr, 1);
3294 return -TARGET_EINVAL;
3295 }
3296 lp = (uint32_t *)(gdt_table + idx);
3297 entry_1 = tswap32(lp[0]);
3298 entry_2 = tswap32(lp[1]);
3299
3300 read_exec_only = ((entry_2 >> 9) & 1) ^ 1;
3301 contents = (entry_2 >> 10) & 3;
3302 seg_not_present = ((entry_2 >> 15) & 1) ^ 1;
3303 seg_32bit = (entry_2 >> 22) & 1;
3304 limit_in_pages = (entry_2 >> 23) & 1;
3305 useable = (entry_2 >> 20) & 1;
3306#ifdef TARGET_ABI32
3307 lm = 0;
3308#else
3309 lm = (entry_2 >> 21) & 1;
3310#endif
3311 flags = (seg_32bit << 0) | (contents << 1) |
3312 (read_exec_only << 3) | (limit_in_pages << 4) |
3313 (seg_not_present << 5) | (useable << 6) | (lm << 7);
3314 limit = (entry_1 & 0xffff) | (entry_2 & 0xf0000);
3315 base_addr = (entry_1 >> 16) |
3316 (entry_2 & 0xff000000) |
3317 ((entry_2 & 0xff) << 16);
3318 target_ldt_info->base_addr = tswapl(base_addr);
3319 target_ldt_info->limit = tswap32(limit);
3320 target_ldt_info->flags = tswap32(flags);
3321 unlock_user_struct(target_ldt_info, ptr, 1);
3322 return 0;
3323}
blueswir14583f582008-08-24 10:35:55 +00003324#endif /* TARGET_I386 && TARGET_ABI32 */
bellard8d18e892007-11-14 15:18:40 +00003325
bellardd2fd1af2007-11-14 18:08:56 +00003326#ifndef TARGET_ABI32
blueswir18fcd3692008-08-17 20:26:25 +00003327static abi_long do_arch_prctl(CPUX86State *env, int code, abi_ulong addr)
bellardd2fd1af2007-11-14 18:08:56 +00003328{
3329 abi_long ret;
3330 abi_ulong val;
3331 int idx;
3332
3333 switch(code) {
3334 case TARGET_ARCH_SET_GS:
3335 case TARGET_ARCH_SET_FS:
3336 if (code == TARGET_ARCH_SET_GS)
3337 idx = R_GS;
3338 else
3339 idx = R_FS;
3340 cpu_x86_load_seg(env, idx, 0);
3341 env->segs[idx].base = addr;
3342 break;
3343 case TARGET_ARCH_GET_GS:
3344 case TARGET_ARCH_GET_FS:
3345 if (code == TARGET_ARCH_GET_GS)
3346 idx = R_GS;
3347 else
3348 idx = R_FS;
3349 val = env->segs[idx].base;
3350 if (put_user(val, addr, abi_ulong))
3351 return -TARGET_EFAULT;
3352 break;
3353 default:
3354 ret = -TARGET_EINVAL;
3355 break;
3356 }
3357 return 0;
3358}
3359#endif
3360
bellard2ab83ea2003-06-15 19:56:46 +00003361#endif /* defined(TARGET_I386) */
3362
pbrookd865bab2008-06-07 22:12:17 +00003363#if defined(USE_NPTL)
3364
3365#define NEW_STACK_SIZE PTHREAD_STACK_MIN
3366
3367static pthread_mutex_t clone_lock = PTHREAD_MUTEX_INITIALIZER;
3368typedef struct {
3369 CPUState *env;
3370 pthread_mutex_t mutex;
3371 pthread_cond_t cond;
3372 pthread_t thread;
3373 uint32_t tid;
3374 abi_ulong child_tidptr;
3375 abi_ulong parent_tidptr;
3376 sigset_t sigmask;
3377} new_thread_info;
3378
3379static void *clone_func(void *arg)
3380{
3381 new_thread_info *info = arg;
3382 CPUState *env;
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03003383 TaskState *ts;
pbrookd865bab2008-06-07 22:12:17 +00003384
3385 env = info->env;
3386 thread_env = env;
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03003387 ts = (TaskState *)thread_env->opaque;
pbrookd865bab2008-06-07 22:12:17 +00003388 info->tid = gettid();
Nathan Froyd1e9fa732009-06-03 11:33:08 -07003389 env->host_tid = info->tid;
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03003390 task_settid(ts);
pbrookd865bab2008-06-07 22:12:17 +00003391 if (info->child_tidptr)
3392 put_user_u32(info->tid, info->child_tidptr);
3393 if (info->parent_tidptr)
3394 put_user_u32(info->tid, info->parent_tidptr);
3395 /* Enable signals. */
3396 sigprocmask(SIG_SETMASK, &info->sigmask, NULL);
3397 /* Signal to the parent that we're ready. */
3398 pthread_mutex_lock(&info->mutex);
3399 pthread_cond_broadcast(&info->cond);
3400 pthread_mutex_unlock(&info->mutex);
3401 /* Wait until the parent has finshed initializing the tls state. */
3402 pthread_mutex_lock(&clone_lock);
3403 pthread_mutex_unlock(&clone_lock);
3404 cpu_loop(env);
3405 /* never exits */
3406 return NULL;
3407}
3408#else
bellard1b6b0292003-03-22 17:31:38 +00003409/* this stack is the equivalent of the kernel stack associated with a
3410 thread/process */
3411#define NEW_STACK_SIZE 8192
3412
3413static int clone_func(void *arg)
3414{
bellard2ab83ea2003-06-15 19:56:46 +00003415 CPUState *env = arg;
bellard1b6b0292003-03-22 17:31:38 +00003416 cpu_loop(env);
3417 /* never exits */
3418 return 0;
3419}
pbrookd865bab2008-06-07 22:12:17 +00003420#endif
bellard1b6b0292003-03-22 17:31:38 +00003421
ths0da46a62007-10-20 20:23:07 +00003422/* do_fork() Must return host values and target errnos (unlike most
3423 do_*() functions). */
pbrookd865bab2008-06-07 22:12:17 +00003424static int do_fork(CPUState *env, unsigned int flags, abi_ulong newsp,
3425 abi_ulong parent_tidptr, target_ulong newtls,
3426 abi_ulong child_tidptr)
bellard1b6b0292003-03-22 17:31:38 +00003427{
3428 int ret;
bellard5cd43932003-03-29 16:54:36 +00003429 TaskState *ts;
bellard1b6b0292003-03-22 17:31:38 +00003430 uint8_t *new_stack;
bellard2ab83ea2003-06-15 19:56:46 +00003431 CPUState *new_env;
pbrookd865bab2008-06-07 22:12:17 +00003432#if defined(USE_NPTL)
3433 unsigned int nptl_flags;
3434 sigset_t sigmask;
3435#endif
ths3b46e622007-09-17 08:09:54 +00003436
balrog436d1242008-09-21 02:39:45 +00003437 /* Emulate vfork() with fork() */
3438 if (flags & CLONE_VFORK)
3439 flags &= ~(CLONE_VFORK | CLONE_VM);
3440
bellard1b6b0292003-03-22 17:31:38 +00003441 if (flags & CLONE_VM) {
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03003442 TaskState *parent_ts = (TaskState *)env->opaque;
pbrookbd0c5662008-05-29 14:34:11 +00003443#if defined(USE_NPTL)
pbrookd865bab2008-06-07 22:12:17 +00003444 new_thread_info info;
3445 pthread_attr_t attr;
pbrookbd0c5662008-05-29 14:34:11 +00003446#endif
pbrookc3a92832008-06-09 14:02:50 +00003447 ts = qemu_mallocz(sizeof(TaskState) + NEW_STACK_SIZE);
pbrook624f7972008-05-31 16:11:38 +00003448 init_task_state(ts);
bellard5cd43932003-03-29 16:54:36 +00003449 new_stack = ts->stack;
bellard1b6b0292003-03-22 17:31:38 +00003450 /* we create a new CPU instance. */
thsc5be9f02007-02-28 20:20:53 +00003451 new_env = cpu_copy(env);
pbrook6e68e072008-05-30 17:22:15 +00003452 /* Init regs that differ from the parent. */
3453 cpu_clone_regs(new_env, newsp);
bellard5cd43932003-03-29 16:54:36 +00003454 new_env->opaque = ts;
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03003455 ts->bprm = parent_ts->bprm;
3456 ts->info = parent_ts->info;
pbrookd865bab2008-06-07 22:12:17 +00003457#if defined(USE_NPTL)
3458 nptl_flags = flags;
3459 flags &= ~CLONE_NPTL_FLAGS2;
3460
pbrookc2764712009-03-07 15:24:59 +00003461 if (nptl_flags & CLONE_CHILD_CLEARTID) {
3462 ts->child_tidptr = child_tidptr;
3463 }
3464
pbrookd865bab2008-06-07 22:12:17 +00003465 if (nptl_flags & CLONE_SETTLS)
3466 cpu_set_tls (new_env, newtls);
3467
3468 /* Grab a mutex so that thread setup appears atomic. */
3469 pthread_mutex_lock(&clone_lock);
3470
3471 memset(&info, 0, sizeof(info));
3472 pthread_mutex_init(&info.mutex, NULL);
3473 pthread_mutex_lock(&info.mutex);
3474 pthread_cond_init(&info.cond, NULL);
3475 info.env = new_env;
3476 if (nptl_flags & CLONE_CHILD_SETTID)
3477 info.child_tidptr = child_tidptr;
3478 if (nptl_flags & CLONE_PARENT_SETTID)
3479 info.parent_tidptr = parent_tidptr;
3480
3481 ret = pthread_attr_init(&attr);
3482 ret = pthread_attr_setstack(&attr, new_stack, NEW_STACK_SIZE);
3483 /* It is not safe to deliver signals until the child has finished
3484 initializing, so temporarily block all signals. */
3485 sigfillset(&sigmask);
3486 sigprocmask(SIG_BLOCK, &sigmask, &info.sigmask);
3487
3488 ret = pthread_create(&info.thread, &attr, clone_func, &info);
pbrookc2764712009-03-07 15:24:59 +00003489 /* TODO: Free new CPU state if thread creation failed. */
pbrookd865bab2008-06-07 22:12:17 +00003490
3491 sigprocmask(SIG_SETMASK, &info.sigmask, NULL);
3492 pthread_attr_destroy(&attr);
3493 if (ret == 0) {
3494 /* Wait for the child to initialize. */
3495 pthread_cond_wait(&info.cond, &info.mutex);
3496 ret = info.tid;
3497 if (flags & CLONE_PARENT_SETTID)
3498 put_user_u32(ret, parent_tidptr);
3499 } else {
3500 ret = -1;
3501 }
3502 pthread_mutex_unlock(&info.mutex);
3503 pthread_cond_destroy(&info.cond);
3504 pthread_mutex_destroy(&info.mutex);
3505 pthread_mutex_unlock(&clone_lock);
3506#else
3507 if (flags & CLONE_NPTL_FLAGS2)
3508 return -EINVAL;
3509 /* This is probably going to die very quickly, but do it anyway. */
bellard27725c12003-04-29 21:08:18 +00003510#ifdef __ia64__
bellardfd4a43e2006-04-24 20:32:17 +00003511 ret = __clone2(clone_func, new_stack + NEW_STACK_SIZE, flags, new_env);
bellard27725c12003-04-29 21:08:18 +00003512#else
3513 ret = clone(clone_func, new_stack + NEW_STACK_SIZE, flags, new_env);
3514#endif
pbrookd865bab2008-06-07 22:12:17 +00003515#endif
bellard1b6b0292003-03-22 17:31:38 +00003516 } else {
3517 /* if no CLONE_VM, we consider it is a fork */
pbrookd865bab2008-06-07 22:12:17 +00003518 if ((flags & ~(CSIGNAL | CLONE_NPTL_FLAGS2)) != 0)
bellard1b6b0292003-03-22 17:31:38 +00003519 return -EINVAL;
pbrookd865bab2008-06-07 22:12:17 +00003520 fork_start();
bellard1b6b0292003-03-22 17:31:38 +00003521 ret = fork();
pbrookd865bab2008-06-07 22:12:17 +00003522 if (ret == 0) {
aurel322b1319c2008-12-18 22:44:04 +00003523 /* Child Process. */
pbrookd865bab2008-06-07 22:12:17 +00003524 cpu_clone_regs(env, newsp);
3525 fork_end(1);
aurel322b1319c2008-12-18 22:44:04 +00003526#if defined(USE_NPTL)
3527 /* There is a race condition here. The parent process could
3528 theoretically read the TID in the child process before the child
3529 tid is set. This would require using either ptrace
3530 (not implemented) or having *_tidptr to point at a shared memory
3531 mapping. We can't repeat the spinlock hack used above because
3532 the child process gets its own copy of the lock. */
pbrookd865bab2008-06-07 22:12:17 +00003533 if (flags & CLONE_CHILD_SETTID)
3534 put_user_u32(gettid(), child_tidptr);
3535 if (flags & CLONE_PARENT_SETTID)
3536 put_user_u32(gettid(), parent_tidptr);
3537 ts = (TaskState *)env->opaque;
3538 if (flags & CLONE_SETTLS)
3539 cpu_set_tls (env, newtls);
pbrookc2764712009-03-07 15:24:59 +00003540 if (flags & CLONE_CHILD_CLEARTID)
3541 ts->child_tidptr = child_tidptr;
aurel322b1319c2008-12-18 22:44:04 +00003542#endif
pbrookd865bab2008-06-07 22:12:17 +00003543 } else {
3544 fork_end(0);
3545 }
bellard1b6b0292003-03-22 17:31:38 +00003546 }
3547 return ret;
3548}
3549
blueswir1992f48a2007-10-14 16:27:31 +00003550static abi_long do_fcntl(int fd, int cmd, abi_ulong arg)
bellard7775e9e2003-05-14 22:46:48 +00003551{
3552 struct flock fl;
pbrook53a59602006-03-25 19:31:22 +00003553 struct target_flock *target_fl;
ths43f238d2007-01-05 20:55:49 +00003554 struct flock64 fl64;
3555 struct target_flock64 *target_fl64;
blueswir1992f48a2007-10-14 16:27:31 +00003556 abi_long ret;
pbrook53a59602006-03-25 19:31:22 +00003557
bellard7775e9e2003-05-14 22:46:48 +00003558 switch(cmd) {
3559 case TARGET_F_GETLK:
bellard579a97f2007-11-11 14:26:47 +00003560 if (!lock_user_struct(VERIFY_READ, target_fl, arg, 1))
3561 return -TARGET_EFAULT;
ths58134272007-03-31 18:59:32 +00003562 fl.l_type = tswap16(target_fl->l_type);
3563 fl.l_whence = tswap16(target_fl->l_whence);
3564 fl.l_start = tswapl(target_fl->l_start);
3565 fl.l_len = tswapl(target_fl->l_len);
3566 fl.l_pid = tswapl(target_fl->l_pid);
3567 unlock_user_struct(target_fl, arg, 0);
bellard9ee1fa22007-11-11 15:11:19 +00003568 ret = get_errno(fcntl(fd, cmd, &fl));
bellard7775e9e2003-05-14 22:46:48 +00003569 if (ret == 0) {
bellard579a97f2007-11-11 14:26:47 +00003570 if (!lock_user_struct(VERIFY_WRITE, target_fl, arg, 0))
3571 return -TARGET_EFAULT;
bellard7775e9e2003-05-14 22:46:48 +00003572 target_fl->l_type = tswap16(fl.l_type);
3573 target_fl->l_whence = tswap16(fl.l_whence);
3574 target_fl->l_start = tswapl(fl.l_start);
3575 target_fl->l_len = tswapl(fl.l_len);
3576 target_fl->l_pid = tswapl(fl.l_pid);
pbrook53a59602006-03-25 19:31:22 +00003577 unlock_user_struct(target_fl, arg, 1);
bellard7775e9e2003-05-14 22:46:48 +00003578 }
3579 break;
ths3b46e622007-09-17 08:09:54 +00003580
bellard7775e9e2003-05-14 22:46:48 +00003581 case TARGET_F_SETLK:
3582 case TARGET_F_SETLKW:
bellard579a97f2007-11-11 14:26:47 +00003583 if (!lock_user_struct(VERIFY_READ, target_fl, arg, 1))
3584 return -TARGET_EFAULT;
bellard7775e9e2003-05-14 22:46:48 +00003585 fl.l_type = tswap16(target_fl->l_type);
3586 fl.l_whence = tswap16(target_fl->l_whence);
3587 fl.l_start = tswapl(target_fl->l_start);
3588 fl.l_len = tswapl(target_fl->l_len);
3589 fl.l_pid = tswapl(target_fl->l_pid);
pbrook53a59602006-03-25 19:31:22 +00003590 unlock_user_struct(target_fl, arg, 0);
bellard9ee1fa22007-11-11 15:11:19 +00003591 ret = get_errno(fcntl(fd, cmd, &fl));
bellard7775e9e2003-05-14 22:46:48 +00003592 break;
ths3b46e622007-09-17 08:09:54 +00003593
bellard7775e9e2003-05-14 22:46:48 +00003594 case TARGET_F_GETLK64:
bellard579a97f2007-11-11 14:26:47 +00003595 if (!lock_user_struct(VERIFY_READ, target_fl64, arg, 1))
3596 return -TARGET_EFAULT;
ths58134272007-03-31 18:59:32 +00003597 fl64.l_type = tswap16(target_fl64->l_type) >> 1;
3598 fl64.l_whence = tswap16(target_fl64->l_whence);
3599 fl64.l_start = tswapl(target_fl64->l_start);
3600 fl64.l_len = tswapl(target_fl64->l_len);
3601 fl64.l_pid = tswap16(target_fl64->l_pid);
3602 unlock_user_struct(target_fl64, arg, 0);
bellard9ee1fa22007-11-11 15:11:19 +00003603 ret = get_errno(fcntl(fd, cmd >> 1, &fl64));
ths43f238d2007-01-05 20:55:49 +00003604 if (ret == 0) {
bellard579a97f2007-11-11 14:26:47 +00003605 if (!lock_user_struct(VERIFY_WRITE, target_fl64, arg, 0))
3606 return -TARGET_EFAULT;
ths43f238d2007-01-05 20:55:49 +00003607 target_fl64->l_type = tswap16(fl64.l_type) >> 1;
3608 target_fl64->l_whence = tswap16(fl64.l_whence);
3609 target_fl64->l_start = tswapl(fl64.l_start);
3610 target_fl64->l_len = tswapl(fl64.l_len);
3611 target_fl64->l_pid = tswapl(fl64.l_pid);
3612 unlock_user_struct(target_fl64, arg, 1);
3613 }
bellard9ee1fa22007-11-11 15:11:19 +00003614 break;
bellard7775e9e2003-05-14 22:46:48 +00003615 case TARGET_F_SETLK64:
3616 case TARGET_F_SETLKW64:
bellard579a97f2007-11-11 14:26:47 +00003617 if (!lock_user_struct(VERIFY_READ, target_fl64, arg, 1))
3618 return -TARGET_EFAULT;
ths43f238d2007-01-05 20:55:49 +00003619 fl64.l_type = tswap16(target_fl64->l_type) >> 1;
3620 fl64.l_whence = tswap16(target_fl64->l_whence);
3621 fl64.l_start = tswapl(target_fl64->l_start);
3622 fl64.l_len = tswapl(target_fl64->l_len);
3623 fl64.l_pid = tswap16(target_fl64->l_pid);
3624 unlock_user_struct(target_fl64, arg, 0);
bellard9ee1fa22007-11-11 15:11:19 +00003625 ret = get_errno(fcntl(fd, cmd >> 1, &fl64));
bellard7775e9e2003-05-14 22:46:48 +00003626 break;
3627
bellardffa65c32004-01-04 23:57:22 +00003628 case F_GETFL:
bellard9ee1fa22007-11-11 15:11:19 +00003629 ret = get_errno(fcntl(fd, cmd, arg));
3630 if (ret >= 0) {
3631 ret = host_to_target_bitmask(ret, fcntl_flags_tbl);
3632 }
bellardffa65c32004-01-04 23:57:22 +00003633 break;
3634
3635 case F_SETFL:
bellard9ee1fa22007-11-11 15:11:19 +00003636 ret = get_errno(fcntl(fd, cmd, target_to_host_bitmask(arg, fcntl_flags_tbl)));
bellardffa65c32004-01-04 23:57:22 +00003637 break;
3638
bellard7775e9e2003-05-14 22:46:48 +00003639 default:
bellard9ee1fa22007-11-11 15:11:19 +00003640 ret = get_errno(fcntl(fd, cmd, arg));
bellard7775e9e2003-05-14 22:46:48 +00003641 break;
3642 }
3643 return ret;
3644}
3645
bellard67867302003-11-23 17:05:30 +00003646#ifdef USE_UID16
bellard7775e9e2003-05-14 22:46:48 +00003647
bellard67867302003-11-23 17:05:30 +00003648static inline int high2lowuid(int uid)
3649{
3650 if (uid > 65535)
3651 return 65534;
3652 else
3653 return uid;
3654}
3655
3656static inline int high2lowgid(int gid)
3657{
3658 if (gid > 65535)
3659 return 65534;
3660 else
3661 return gid;
3662}
3663
3664static inline int low2highuid(int uid)
3665{
3666 if ((int16_t)uid == -1)
3667 return -1;
3668 else
3669 return uid;
3670}
3671
3672static inline int low2highgid(int gid)
3673{
3674 if ((int16_t)gid == -1)
3675 return -1;
3676 else
3677 return gid;
3678}
3679
3680#endif /* USE_UID16 */
bellard1b6b0292003-03-22 17:31:38 +00003681
bellard31e31b82003-02-18 22:55:36 +00003682void syscall_init(void)
3683{
bellard2ab83ea2003-06-15 19:56:46 +00003684 IOCTLEntry *ie;
3685 const argtype *arg_type;
3686 int size;
thsb92c47c2007-11-01 00:07:38 +00003687 int i;
bellard2ab83ea2003-06-15 19:56:46 +00003688
Blue Swirl001faf32009-05-13 17:53:17 +00003689#define STRUCT(name, ...) thunk_register_struct(STRUCT_ ## name, #name, struct_ ## name ## _def);
ths5fafdf22007-09-16 21:08:06 +00003690#define STRUCT_SPECIAL(name) thunk_register_struct_direct(STRUCT_ ## name, #name, &struct_ ## name ## _def);
bellard31e31b82003-02-18 22:55:36 +00003691#include "syscall_types.h"
3692#undef STRUCT
3693#undef STRUCT_SPECIAL
bellard2ab83ea2003-06-15 19:56:46 +00003694
3695 /* we patch the ioctl size if necessary. We rely on the fact that
3696 no ioctl has all the bits at '1' in the size field */
3697 ie = ioctl_entries;
3698 while (ie->target_cmd != 0) {
3699 if (((ie->target_cmd >> TARGET_IOC_SIZESHIFT) & TARGET_IOC_SIZEMASK) ==
3700 TARGET_IOC_SIZEMASK) {
3701 arg_type = ie->arg_type;
3702 if (arg_type[0] != TYPE_PTR) {
ths5fafdf22007-09-16 21:08:06 +00003703 fprintf(stderr, "cannot patch size for ioctl 0x%x\n",
bellard2ab83ea2003-06-15 19:56:46 +00003704 ie->target_cmd);
3705 exit(1);
3706 }
3707 arg_type++;
3708 size = thunk_type_size(arg_type, 0);
ths5fafdf22007-09-16 21:08:06 +00003709 ie->target_cmd = (ie->target_cmd &
bellard2ab83ea2003-06-15 19:56:46 +00003710 ~(TARGET_IOC_SIZEMASK << TARGET_IOC_SIZESHIFT)) |
3711 (size << TARGET_IOC_SIZESHIFT);
3712 }
thsb92c47c2007-11-01 00:07:38 +00003713
3714 /* Build target_to_host_errno_table[] table from
3715 * host_to_target_errno_table[]. */
3716 for (i=0; i < ERRNO_TABLE_SIZE; i++)
3717 target_to_host_errno_table[host_to_target_errno_table[i]] = i;
3718
bellard2ab83ea2003-06-15 19:56:46 +00003719 /* automatic consistency check if same arch */
balrog872ea0c2008-09-21 02:31:19 +00003720#if (defined(__i386__) && defined(TARGET_I386) && defined(TARGET_ABI32)) || \
3721 (defined(__x86_64__) && defined(TARGET_X86_64))
3722 if (unlikely(ie->target_cmd != ie->host_cmd)) {
3723 fprintf(stderr, "ERROR: ioctl(%s): target=0x%x host=0x%x\n",
3724 ie->name, ie->target_cmd, ie->host_cmd);
bellard2ab83ea2003-06-15 19:56:46 +00003725 }
3726#endif
3727 ie++;
3728 }
bellard31e31b82003-02-18 22:55:36 +00003729}
bellardc573ff62004-01-04 15:51:36 +00003730
blueswir1992f48a2007-10-14 16:27:31 +00003731#if TARGET_ABI_BITS == 32
pbrookce4defa2006-02-09 16:49:55 +00003732static inline uint64_t target_offset64(uint32_t word0, uint32_t word1)
3733{
thsaf325d32008-06-10 15:29:15 +00003734#ifdef TARGET_WORDS_BIGENDIAN
pbrookce4defa2006-02-09 16:49:55 +00003735 return ((uint64_t)word0 << 32) | word1;
3736#else
3737 return ((uint64_t)word1 << 32) | word0;
3738#endif
3739}
blueswir1992f48a2007-10-14 16:27:31 +00003740#else /* TARGET_ABI_BITS == 32 */
j_mayer32407102007-09-26 23:01:49 +00003741static inline uint64_t target_offset64(uint64_t word0, uint64_t word1)
3742{
3743 return word0;
3744}
blueswir1992f48a2007-10-14 16:27:31 +00003745#endif /* TARGET_ABI_BITS != 32 */
pbrookce4defa2006-02-09 16:49:55 +00003746
3747#ifdef TARGET_NR_truncate64
blueswir1992f48a2007-10-14 16:27:31 +00003748static inline abi_long target_truncate64(void *cpu_env, const char *arg1,
3749 abi_long arg2,
3750 abi_long arg3,
3751 abi_long arg4)
pbrookce4defa2006-02-09 16:49:55 +00003752{
3753#ifdef TARGET_ARM
3754 if (((CPUARMState *)cpu_env)->eabi)
3755 {
3756 arg2 = arg3;
3757 arg3 = arg4;
3758 }
3759#endif
3760 return get_errno(truncate64(arg1, target_offset64(arg2, arg3)));
3761}
3762#endif
3763
3764#ifdef TARGET_NR_ftruncate64
blueswir1992f48a2007-10-14 16:27:31 +00003765static inline abi_long target_ftruncate64(void *cpu_env, abi_long arg1,
3766 abi_long arg2,
3767 abi_long arg3,
3768 abi_long arg4)
pbrookce4defa2006-02-09 16:49:55 +00003769{
3770#ifdef TARGET_ARM
3771 if (((CPUARMState *)cpu_env)->eabi)
3772 {
3773 arg2 = arg3;
3774 arg3 = arg4;
3775 }
3776#endif
3777 return get_errno(ftruncate64(arg1, target_offset64(arg2, arg3)));
3778}
3779#endif
3780
bellard579a97f2007-11-11 14:26:47 +00003781static inline abi_long target_to_host_timespec(struct timespec *host_ts,
3782 abi_ulong target_addr)
pbrook53a59602006-03-25 19:31:22 +00003783{
3784 struct target_timespec *target_ts;
3785
bellard579a97f2007-11-11 14:26:47 +00003786 if (!lock_user_struct(VERIFY_READ, target_ts, target_addr, 1))
3787 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00003788 host_ts->tv_sec = tswapl(target_ts->tv_sec);
3789 host_ts->tv_nsec = tswapl(target_ts->tv_nsec);
3790 unlock_user_struct(target_ts, target_addr, 0);
bellardb255bfa2008-05-10 21:51:02 +00003791 return 0;
pbrook53a59602006-03-25 19:31:22 +00003792}
3793
bellard579a97f2007-11-11 14:26:47 +00003794static inline abi_long host_to_target_timespec(abi_ulong target_addr,
3795 struct timespec *host_ts)
pbrook53a59602006-03-25 19:31:22 +00003796{
3797 struct target_timespec *target_ts;
3798
bellard579a97f2007-11-11 14:26:47 +00003799 if (!lock_user_struct(VERIFY_WRITE, target_ts, target_addr, 0))
3800 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00003801 target_ts->tv_sec = tswapl(host_ts->tv_sec);
3802 target_ts->tv_nsec = tswapl(host_ts->tv_nsec);
3803 unlock_user_struct(target_ts, target_addr, 1);
bellardb255bfa2008-05-10 21:51:02 +00003804 return 0;
pbrook53a59602006-03-25 19:31:22 +00003805}
3806
aurel329d33b762009-04-08 23:07:05 +00003807#if defined(TARGET_NR_stat64) || defined(TARGET_NR_newfstatat)
balrog6a24a772008-09-20 02:23:36 +00003808static inline abi_long host_to_target_stat64(void *cpu_env,
3809 abi_ulong target_addr,
3810 struct stat *host_st)
3811{
3812#ifdef TARGET_ARM
3813 if (((CPUARMState *)cpu_env)->eabi) {
3814 struct target_eabi_stat64 *target_st;
3815
3816 if (!lock_user_struct(VERIFY_WRITE, target_st, target_addr, 0))
3817 return -TARGET_EFAULT;
3818 memset(target_st, 0, sizeof(struct target_eabi_stat64));
3819 __put_user(host_st->st_dev, &target_st->st_dev);
3820 __put_user(host_st->st_ino, &target_st->st_ino);
3821#ifdef TARGET_STAT64_HAS_BROKEN_ST_INO
3822 __put_user(host_st->st_ino, &target_st->__st_ino);
3823#endif
3824 __put_user(host_st->st_mode, &target_st->st_mode);
3825 __put_user(host_st->st_nlink, &target_st->st_nlink);
3826 __put_user(host_st->st_uid, &target_st->st_uid);
3827 __put_user(host_st->st_gid, &target_st->st_gid);
3828 __put_user(host_st->st_rdev, &target_st->st_rdev);
3829 __put_user(host_st->st_size, &target_st->st_size);
3830 __put_user(host_st->st_blksize, &target_st->st_blksize);
3831 __put_user(host_st->st_blocks, &target_st->st_blocks);
3832 __put_user(host_st->st_atime, &target_st->target_st_atime);
3833 __put_user(host_st->st_mtime, &target_st->target_st_mtime);
3834 __put_user(host_st->st_ctime, &target_st->target_st_ctime);
3835 unlock_user_struct(target_st, target_addr, 1);
3836 } else
3837#endif
3838 {
aurel329d33b762009-04-08 23:07:05 +00003839#if TARGET_LONG_BITS == 64
3840 struct target_stat *target_st;
3841#else
balrog6a24a772008-09-20 02:23:36 +00003842 struct target_stat64 *target_st;
aurel329d33b762009-04-08 23:07:05 +00003843#endif
balrog6a24a772008-09-20 02:23:36 +00003844
3845 if (!lock_user_struct(VERIFY_WRITE, target_st, target_addr, 0))
3846 return -TARGET_EFAULT;
aurel329d33b762009-04-08 23:07:05 +00003847 memset(target_st, 0, sizeof(*target_st));
balrog6a24a772008-09-20 02:23:36 +00003848 __put_user(host_st->st_dev, &target_st->st_dev);
3849 __put_user(host_st->st_ino, &target_st->st_ino);
3850#ifdef TARGET_STAT64_HAS_BROKEN_ST_INO
3851 __put_user(host_st->st_ino, &target_st->__st_ino);
3852#endif
3853 __put_user(host_st->st_mode, &target_st->st_mode);
3854 __put_user(host_st->st_nlink, &target_st->st_nlink);
3855 __put_user(host_st->st_uid, &target_st->st_uid);
3856 __put_user(host_st->st_gid, &target_st->st_gid);
3857 __put_user(host_st->st_rdev, &target_st->st_rdev);
3858 /* XXX: better use of kernel struct */
3859 __put_user(host_st->st_size, &target_st->st_size);
3860 __put_user(host_st->st_blksize, &target_st->st_blksize);
3861 __put_user(host_st->st_blocks, &target_st->st_blocks);
3862 __put_user(host_st->st_atime, &target_st->target_st_atime);
3863 __put_user(host_st->st_mtime, &target_st->target_st_mtime);
3864 __put_user(host_st->st_ctime, &target_st->target_st_ctime);
3865 unlock_user_struct(target_st, target_addr, 1);
3866 }
3867
3868 return 0;
3869}
3870#endif
3871
pbrookbd0c5662008-05-29 14:34:11 +00003872#if defined(USE_NPTL)
3873/* ??? Using host futex calls even when target atomic operations
3874 are not really atomic probably breaks things. However implementing
3875 futexes locally would make futexes shared between multiple processes
3876 tricky. However they're probably useless because guest atomic
3877 operations won't work either. */
blueswir18fcd3692008-08-17 20:26:25 +00003878static int do_futex(target_ulong uaddr, int op, int val, target_ulong timeout,
3879 target_ulong uaddr2, int val3)
pbrookbd0c5662008-05-29 14:34:11 +00003880{
3881 struct timespec ts, *pts;
3882
3883 /* ??? We assume FUTEX_* constants are the same on both host
3884 and target. */
3885 switch (op) {
3886 case FUTEX_WAIT:
3887 if (timeout) {
3888 pts = &ts;
3889 target_to_host_timespec(pts, timeout);
3890 } else {
3891 pts = NULL;
3892 }
3893 return get_errno(sys_futex(g2h(uaddr), FUTEX_WAIT, tswap32(val),
3894 pts, NULL, 0));
3895 case FUTEX_WAKE:
3896 return get_errno(sys_futex(g2h(uaddr), FUTEX_WAKE, val, NULL, NULL, 0));
3897 case FUTEX_FD:
3898 return get_errno(sys_futex(g2h(uaddr), FUTEX_FD, val, NULL, NULL, 0));
3899 case FUTEX_REQUEUE:
3900 return get_errno(sys_futex(g2h(uaddr), FUTEX_REQUEUE, val,
3901 NULL, g2h(uaddr2), 0));
3902 case FUTEX_CMP_REQUEUE:
3903 return get_errno(sys_futex(g2h(uaddr), FUTEX_CMP_REQUEUE, val,
3904 NULL, g2h(uaddr2), tswap32(val3)));
3905 default:
3906 return -TARGET_ENOSYS;
3907 }
3908}
3909#endif
3910
pbrook1d9d8b52009-04-16 15:17:02 +00003911/* Map host to target signal numbers for the wait family of syscalls.
3912 Assume all other status bits are the same. */
3913static int host_to_target_waitstatus(int status)
3914{
3915 if (WIFSIGNALED(status)) {
3916 return host_to_target_signal(WTERMSIG(status)) | (status & ~0x7f);
3917 }
3918 if (WIFSTOPPED(status)) {
3919 return (host_to_target_signal(WSTOPSIG(status)) << 8)
3920 | (status & 0xff);
3921 }
3922 return status;
3923}
3924
pbrooka745ec62008-05-06 15:36:17 +00003925int get_osversion(void)
3926{
3927 static int osversion;
3928 struct new_utsname buf;
3929 const char *s;
3930 int i, n, tmp;
3931 if (osversion)
3932 return osversion;
3933 if (qemu_uname_release && *qemu_uname_release) {
3934 s = qemu_uname_release;
3935 } else {
3936 if (sys_uname(&buf))
3937 return 0;
3938 s = buf.release;
3939 }
3940 tmp = 0;
3941 for (i = 0; i < 3; i++) {
3942 n = 0;
3943 while (*s >= '0' && *s <= '9') {
3944 n *= 10;
3945 n += *s - '0';
3946 s++;
3947 }
3948 tmp = (tmp << 8) + n;
3949 if (*s == '.')
3950 s++;
3951 }
3952 osversion = tmp;
3953 return osversion;
3954}
3955
ths0da46a62007-10-20 20:23:07 +00003956/* do_syscall() should always have a single exit point at the end so
3957 that actions, such as logging of syscall results, can be performed.
3958 All errnos that do_syscall() returns must be -TARGET_<errcode>. */
blueswir1992f48a2007-10-14 16:27:31 +00003959abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
3960 abi_long arg2, abi_long arg3, abi_long arg4,
3961 abi_long arg5, abi_long arg6)
bellard31e31b82003-02-18 22:55:36 +00003962{
blueswir1992f48a2007-10-14 16:27:31 +00003963 abi_long ret;
bellard31e31b82003-02-18 22:55:36 +00003964 struct stat st;
bellard56c8f682005-11-28 22:28:41 +00003965 struct statfs stfs;
pbrook53a59602006-03-25 19:31:22 +00003966 void *p;
ths3b46e622007-09-17 08:09:54 +00003967
bellard72f03902003-02-18 23:33:18 +00003968#ifdef DEBUG
bellardc573ff62004-01-04 15:51:36 +00003969 gemu_log("syscall %d", num);
bellard72f03902003-02-18 23:33:18 +00003970#endif
thsb92c47c2007-11-01 00:07:38 +00003971 if(do_strace)
3972 print_syscall(num, arg1, arg2, arg3, arg4, arg5, arg6);
3973
bellard31e31b82003-02-18 22:55:36 +00003974 switch(num) {
3975 case TARGET_NR_exit:
pbrookc2764712009-03-07 15:24:59 +00003976#ifdef USE_NPTL
3977 /* In old applications this may be used to implement _exit(2).
3978 However in threaded applictions it is used for thread termination,
3979 and _exit_group is used for application termination.
3980 Do thread termination if we have more then one thread. */
3981 /* FIXME: This probably breaks if a signal arrives. We should probably
3982 be disabling signals. */
3983 if (first_cpu->next_cpu) {
Nathan Froyd1e9fa732009-06-03 11:33:08 -07003984 TaskState *ts;
pbrookc2764712009-03-07 15:24:59 +00003985 CPUState **lastp;
3986 CPUState *p;
3987
3988 cpu_list_lock();
3989 lastp = &first_cpu;
3990 p = first_cpu;
3991 while (p && p != (CPUState *)cpu_env) {
3992 lastp = &p->next_cpu;
3993 p = p->next_cpu;
3994 }
3995 /* If we didn't find the CPU for this thread then something is
3996 horribly wrong. */
3997 if (!p)
3998 abort();
3999 /* Remove the CPU from the list. */
4000 *lastp = p->next_cpu;
4001 cpu_list_unlock();
Nathan Froyd1e9fa732009-06-03 11:33:08 -07004002 ts = ((CPUState *)cpu_env)->opaque;
pbrookc2764712009-03-07 15:24:59 +00004003 if (ts->child_tidptr) {
4004 put_user_u32(0, ts->child_tidptr);
4005 sys_futex(g2h(ts->child_tidptr), FUTEX_WAKE, INT_MAX,
4006 NULL, NULL, 0);
4007 }
4008 /* TODO: Free CPU state. */
4009 pthread_exit(NULL);
4010 }
4011#endif
bellard7d132992003-03-06 23:23:54 +00004012#ifdef HAVE_GPROF
4013 _mcleanup();
4014#endif
bellarde9009672005-04-26 20:42:36 +00004015 gdb_exit(cpu_env, arg1);
pbrookc2764712009-03-07 15:24:59 +00004016 _exit(arg1);
bellard31e31b82003-02-18 22:55:36 +00004017 ret = 0; /* avoid warning */
4018 break;
4019 case TARGET_NR_read:
aurel3238d840e2009-01-30 19:48:17 +00004020 if (arg3 == 0)
4021 ret = 0;
4022 else {
4023 if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
4024 goto efault;
4025 ret = get_errno(read(arg1, p, arg3));
4026 unlock_user(p, arg2, ret);
4027 }
bellard31e31b82003-02-18 22:55:36 +00004028 break;
4029 case TARGET_NR_write:
bellard579a97f2007-11-11 14:26:47 +00004030 if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
4031 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004032 ret = get_errno(write(arg1, p, arg3));
4033 unlock_user(p, arg2, 0);
bellard31e31b82003-02-18 22:55:36 +00004034 break;
4035 case TARGET_NR_open:
bellard2f619692007-11-16 10:46:05 +00004036 if (!(p = lock_user_string(arg1)))
4037 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004038 ret = get_errno(open(path(p),
bellardffa65c32004-01-04 23:57:22 +00004039 target_to_host_bitmask(arg2, fcntl_flags_tbl),
4040 arg3));
pbrook53a59602006-03-25 19:31:22 +00004041 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004042 break;
ths82424832007-09-24 09:21:55 +00004043#if defined(TARGET_NR_openat) && defined(__NR_openat)
4044 case TARGET_NR_openat:
bellard579a97f2007-11-11 14:26:47 +00004045 if (!(p = lock_user_string(arg2)))
4046 goto efault;
4047 ret = get_errno(sys_openat(arg1,
4048 path(p),
4049 target_to_host_bitmask(arg3, fcntl_flags_tbl),
4050 arg4));
4051 unlock_user(p, arg2, 0);
ths82424832007-09-24 09:21:55 +00004052 break;
4053#endif
bellard31e31b82003-02-18 22:55:36 +00004054 case TARGET_NR_close:
4055 ret = get_errno(close(arg1));
4056 break;
4057 case TARGET_NR_brk:
pbrook53a59602006-03-25 19:31:22 +00004058 ret = do_brk(arg1);
bellard31e31b82003-02-18 22:55:36 +00004059 break;
4060 case TARGET_NR_fork:
pbrookd865bab2008-06-07 22:12:17 +00004061 ret = get_errno(do_fork(cpu_env, SIGCHLD, 0, 0, 0, 0));
bellard31e31b82003-02-18 22:55:36 +00004062 break;
thse5febef2007-04-01 18:31:35 +00004063#ifdef TARGET_NR_waitpid
bellard31e31b82003-02-18 22:55:36 +00004064 case TARGET_NR_waitpid:
4065 {
pbrook53a59602006-03-25 19:31:22 +00004066 int status;
4067 ret = get_errno(waitpid(arg1, &status, arg3));
bellard2f619692007-11-16 10:46:05 +00004068 if (!is_error(ret) && arg2
pbrook1d9d8b52009-04-16 15:17:02 +00004069 && put_user_s32(host_to_target_waitstatus(status), arg2))
bellard2f619692007-11-16 10:46:05 +00004070 goto efault;
bellard31e31b82003-02-18 22:55:36 +00004071 }
4072 break;
thse5febef2007-04-01 18:31:35 +00004073#endif
pbrookf0cbb612008-05-30 18:20:05 +00004074#ifdef TARGET_NR_waitid
4075 case TARGET_NR_waitid:
4076 {
4077 siginfo_t info;
4078 info.si_pid = 0;
4079 ret = get_errno(waitid(arg1, arg2, &info, arg4));
4080 if (!is_error(ret) && arg3 && info.si_pid != 0) {
4081 if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_siginfo_t), 0)))
4082 goto efault;
4083 host_to_target_siginfo(p, &info);
4084 unlock_user(p, arg3, sizeof(target_siginfo_t));
4085 }
4086 }
4087 break;
4088#endif
j_mayer7a3148a2007-04-05 07:13:51 +00004089#ifdef TARGET_NR_creat /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00004090 case TARGET_NR_creat:
bellard579a97f2007-11-11 14:26:47 +00004091 if (!(p = lock_user_string(arg1)))
4092 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004093 ret = get_errno(creat(p, arg2));
4094 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004095 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004096#endif
bellard31e31b82003-02-18 22:55:36 +00004097 case TARGET_NR_link:
pbrook53a59602006-03-25 19:31:22 +00004098 {
4099 void * p2;
4100 p = lock_user_string(arg1);
4101 p2 = lock_user_string(arg2);
bellard579a97f2007-11-11 14:26:47 +00004102 if (!p || !p2)
4103 ret = -TARGET_EFAULT;
4104 else
4105 ret = get_errno(link(p, p2));
pbrook53a59602006-03-25 19:31:22 +00004106 unlock_user(p2, arg2, 0);
4107 unlock_user(p, arg1, 0);
4108 }
bellard31e31b82003-02-18 22:55:36 +00004109 break;
ths64f0ce42007-09-24 09:25:06 +00004110#if defined(TARGET_NR_linkat) && defined(__NR_linkat)
4111 case TARGET_NR_linkat:
ths64f0ce42007-09-24 09:25:06 +00004112 {
4113 void * p2 = NULL;
bellard579a97f2007-11-11 14:26:47 +00004114 if (!arg2 || !arg4)
4115 goto efault;
ths64f0ce42007-09-24 09:25:06 +00004116 p = lock_user_string(arg2);
4117 p2 = lock_user_string(arg4);
bellard579a97f2007-11-11 14:26:47 +00004118 if (!p || !p2)
ths0da46a62007-10-20 20:23:07 +00004119 ret = -TARGET_EFAULT;
ths64f0ce42007-09-24 09:25:06 +00004120 else
4121 ret = get_errno(sys_linkat(arg1, p, arg3, p2, arg5));
bellard579a97f2007-11-11 14:26:47 +00004122 unlock_user(p, arg2, 0);
4123 unlock_user(p2, arg4, 0);
ths64f0ce42007-09-24 09:25:06 +00004124 }
4125 break;
4126#endif
bellard31e31b82003-02-18 22:55:36 +00004127 case TARGET_NR_unlink:
bellard579a97f2007-11-11 14:26:47 +00004128 if (!(p = lock_user_string(arg1)))
4129 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004130 ret = get_errno(unlink(p));
4131 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004132 break;
ths8170f562007-09-24 09:24:11 +00004133#if defined(TARGET_NR_unlinkat) && defined(__NR_unlinkat)
4134 case TARGET_NR_unlinkat:
bellard579a97f2007-11-11 14:26:47 +00004135 if (!(p = lock_user_string(arg2)))
4136 goto efault;
4137 ret = get_errno(sys_unlinkat(arg1, p, arg3));
4138 unlock_user(p, arg2, 0);
balroged494d82007-12-11 23:23:52 +00004139 break;
balrogb7d35e62007-12-12 00:40:24 +00004140#endif
bellard31e31b82003-02-18 22:55:36 +00004141 case TARGET_NR_execve:
bellard7854b052003-03-29 17:22:23 +00004142 {
4143 char **argp, **envp;
bellardf7341ff2003-03-30 21:00:25 +00004144 int argc, envc;
blueswir1992f48a2007-10-14 16:27:31 +00004145 abi_ulong gp;
4146 abi_ulong guest_argp;
4147 abi_ulong guest_envp;
4148 abi_ulong addr;
bellard7854b052003-03-29 17:22:23 +00004149 char **q;
4150
bellardf7341ff2003-03-30 21:00:25 +00004151 argc = 0;
pbrook53a59602006-03-25 19:31:22 +00004152 guest_argp = arg2;
pbrookda94d262008-05-30 18:24:00 +00004153 for (gp = guest_argp; gp; gp += sizeof(abi_ulong)) {
ths03aa1972007-12-02 06:28:08 +00004154 if (get_user_ual(addr, gp))
bellard2f619692007-11-16 10:46:05 +00004155 goto efault;
ths03aa1972007-12-02 06:28:08 +00004156 if (!addr)
bellard2f619692007-11-16 10:46:05 +00004157 break;
bellard7854b052003-03-29 17:22:23 +00004158 argc++;
bellard2f619692007-11-16 10:46:05 +00004159 }
bellardf7341ff2003-03-30 21:00:25 +00004160 envc = 0;
pbrook53a59602006-03-25 19:31:22 +00004161 guest_envp = arg3;
pbrookda94d262008-05-30 18:24:00 +00004162 for (gp = guest_envp; gp; gp += sizeof(abi_ulong)) {
ths03aa1972007-12-02 06:28:08 +00004163 if (get_user_ual(addr, gp))
bellard2f619692007-11-16 10:46:05 +00004164 goto efault;
ths03aa1972007-12-02 06:28:08 +00004165 if (!addr)
bellard2f619692007-11-16 10:46:05 +00004166 break;
bellard7854b052003-03-29 17:22:23 +00004167 envc++;
bellard2f619692007-11-16 10:46:05 +00004168 }
bellard7854b052003-03-29 17:22:23 +00004169
bellardf7341ff2003-03-30 21:00:25 +00004170 argp = alloca((argc + 1) * sizeof(void *));
4171 envp = alloca((envc + 1) * sizeof(void *));
bellard7854b052003-03-29 17:22:23 +00004172
pbrookda94d262008-05-30 18:24:00 +00004173 for (gp = guest_argp, q = argp; gp;
blueswir1992f48a2007-10-14 16:27:31 +00004174 gp += sizeof(abi_ulong), q++) {
bellard2f619692007-11-16 10:46:05 +00004175 if (get_user_ual(addr, gp))
4176 goto execve_efault;
pbrook53a59602006-03-25 19:31:22 +00004177 if (!addr)
4178 break;
bellard2f619692007-11-16 10:46:05 +00004179 if (!(*q = lock_user_string(addr)))
4180 goto execve_efault;
pbrook53a59602006-03-25 19:31:22 +00004181 }
bellardf7341ff2003-03-30 21:00:25 +00004182 *q = NULL;
4183
pbrookda94d262008-05-30 18:24:00 +00004184 for (gp = guest_envp, q = envp; gp;
blueswir1992f48a2007-10-14 16:27:31 +00004185 gp += sizeof(abi_ulong), q++) {
bellard2f619692007-11-16 10:46:05 +00004186 if (get_user_ual(addr, gp))
4187 goto execve_efault;
pbrook53a59602006-03-25 19:31:22 +00004188 if (!addr)
4189 break;
bellard2f619692007-11-16 10:46:05 +00004190 if (!(*q = lock_user_string(addr)))
4191 goto execve_efault;
pbrook53a59602006-03-25 19:31:22 +00004192 }
bellardf7341ff2003-03-30 21:00:25 +00004193 *q = NULL;
bellard7854b052003-03-29 17:22:23 +00004194
bellard2f619692007-11-16 10:46:05 +00004195 if (!(p = lock_user_string(arg1)))
4196 goto execve_efault;
pbrook53a59602006-03-25 19:31:22 +00004197 ret = get_errno(execve(p, argp, envp));
4198 unlock_user(p, arg1, 0);
4199
bellard2f619692007-11-16 10:46:05 +00004200 goto execve_end;
4201
4202 execve_efault:
4203 ret = -TARGET_EFAULT;
4204
4205 execve_end:
pbrook53a59602006-03-25 19:31:22 +00004206 for (gp = guest_argp, q = argp; *q;
blueswir1992f48a2007-10-14 16:27:31 +00004207 gp += sizeof(abi_ulong), q++) {
bellard2f619692007-11-16 10:46:05 +00004208 if (get_user_ual(addr, gp)
4209 || !addr)
4210 break;
pbrook53a59602006-03-25 19:31:22 +00004211 unlock_user(*q, addr, 0);
4212 }
4213 for (gp = guest_envp, q = envp; *q;
blueswir1992f48a2007-10-14 16:27:31 +00004214 gp += sizeof(abi_ulong), q++) {
bellard2f619692007-11-16 10:46:05 +00004215 if (get_user_ual(addr, gp)
4216 || !addr)
4217 break;
pbrook53a59602006-03-25 19:31:22 +00004218 unlock_user(*q, addr, 0);
4219 }
bellard7854b052003-03-29 17:22:23 +00004220 }
bellard31e31b82003-02-18 22:55:36 +00004221 break;
4222 case TARGET_NR_chdir:
bellard579a97f2007-11-11 14:26:47 +00004223 if (!(p = lock_user_string(arg1)))
4224 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004225 ret = get_errno(chdir(p));
4226 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004227 break;
bellarda315a142005-01-30 22:59:18 +00004228#ifdef TARGET_NR_time
bellard31e31b82003-02-18 22:55:36 +00004229 case TARGET_NR_time:
4230 {
pbrook53a59602006-03-25 19:31:22 +00004231 time_t host_time;
4232 ret = get_errno(time(&host_time));
bellard2f619692007-11-16 10:46:05 +00004233 if (!is_error(ret)
4234 && arg1
4235 && put_user_sal(host_time, arg1))
4236 goto efault;
bellard31e31b82003-02-18 22:55:36 +00004237 }
4238 break;
bellarda315a142005-01-30 22:59:18 +00004239#endif
bellard31e31b82003-02-18 22:55:36 +00004240 case TARGET_NR_mknod:
bellard579a97f2007-11-11 14:26:47 +00004241 if (!(p = lock_user_string(arg1)))
4242 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004243 ret = get_errno(mknod(p, arg2, arg3));
4244 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004245 break;
ths75ac37a2007-09-24 09:23:05 +00004246#if defined(TARGET_NR_mknodat) && defined(__NR_mknodat)
4247 case TARGET_NR_mknodat:
bellard579a97f2007-11-11 14:26:47 +00004248 if (!(p = lock_user_string(arg2)))
4249 goto efault;
4250 ret = get_errno(sys_mknodat(arg1, p, arg3, arg4));
4251 unlock_user(p, arg2, 0);
ths75ac37a2007-09-24 09:23:05 +00004252 break;
4253#endif
bellard31e31b82003-02-18 22:55:36 +00004254 case TARGET_NR_chmod:
bellard579a97f2007-11-11 14:26:47 +00004255 if (!(p = lock_user_string(arg1)))
4256 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004257 ret = get_errno(chmod(p, arg2));
4258 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004259 break;
bellardebc05482003-09-30 21:08:41 +00004260#ifdef TARGET_NR_break
bellard31e31b82003-02-18 22:55:36 +00004261 case TARGET_NR_break:
4262 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004263#endif
4264#ifdef TARGET_NR_oldstat
bellard31e31b82003-02-18 22:55:36 +00004265 case TARGET_NR_oldstat:
4266 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004267#endif
bellard31e31b82003-02-18 22:55:36 +00004268 case TARGET_NR_lseek:
4269 ret = get_errno(lseek(arg1, arg2, arg3));
4270 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004271#ifdef TARGET_NR_getxpid
4272 case TARGET_NR_getxpid:
4273#else
bellard31e31b82003-02-18 22:55:36 +00004274 case TARGET_NR_getpid:
j_mayer7a3148a2007-04-05 07:13:51 +00004275#endif
bellard31e31b82003-02-18 22:55:36 +00004276 ret = get_errno(getpid());
4277 break;
4278 case TARGET_NR_mount:
ths80265912007-02-17 22:25:41 +00004279 {
4280 /* need to look at the data field */
4281 void *p2, *p3;
4282 p = lock_user_string(arg1);
4283 p2 = lock_user_string(arg2);
4284 p3 = lock_user_string(arg3);
bellard579a97f2007-11-11 14:26:47 +00004285 if (!p || !p2 || !p3)
4286 ret = -TARGET_EFAULT;
4287 else
4288 /* FIXME - arg5 should be locked, but it isn't clear how to
4289 * do that since it's not guaranteed to be a NULL-terminated
4290 * string.
4291 */
4292 ret = get_errno(mount(p, p2, p3, (unsigned long)arg4, g2h(arg5)));
4293 unlock_user(p, arg1, 0);
4294 unlock_user(p2, arg2, 0);
4295 unlock_user(p3, arg3, 0);
ths80265912007-02-17 22:25:41 +00004296 break;
4297 }
thse5febef2007-04-01 18:31:35 +00004298#ifdef TARGET_NR_umount
bellard31e31b82003-02-18 22:55:36 +00004299 case TARGET_NR_umount:
bellard579a97f2007-11-11 14:26:47 +00004300 if (!(p = lock_user_string(arg1)))
4301 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004302 ret = get_errno(umount(p));
4303 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004304 break;
thse5febef2007-04-01 18:31:35 +00004305#endif
j_mayer7a3148a2007-04-05 07:13:51 +00004306#ifdef TARGET_NR_stime /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00004307 case TARGET_NR_stime:
4308 {
pbrook53a59602006-03-25 19:31:22 +00004309 time_t host_time;
bellard2f619692007-11-16 10:46:05 +00004310 if (get_user_sal(host_time, arg1))
4311 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004312 ret = get_errno(stime(&host_time));
bellard31e31b82003-02-18 22:55:36 +00004313 }
4314 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004315#endif
bellard31e31b82003-02-18 22:55:36 +00004316 case TARGET_NR_ptrace:
4317 goto unimplemented;
j_mayer7a3148a2007-04-05 07:13:51 +00004318#ifdef TARGET_NR_alarm /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00004319 case TARGET_NR_alarm:
4320 ret = alarm(arg1);
4321 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004322#endif
bellardebc05482003-09-30 21:08:41 +00004323#ifdef TARGET_NR_oldfstat
bellard31e31b82003-02-18 22:55:36 +00004324 case TARGET_NR_oldfstat:
4325 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004326#endif
j_mayer7a3148a2007-04-05 07:13:51 +00004327#ifdef TARGET_NR_pause /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00004328 case TARGET_NR_pause:
4329 ret = get_errno(pause());
4330 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004331#endif
thse5febef2007-04-01 18:31:35 +00004332#ifdef TARGET_NR_utime
bellard31e31b82003-02-18 22:55:36 +00004333 case TARGET_NR_utime:
bellardebc05482003-09-30 21:08:41 +00004334 {
pbrook53a59602006-03-25 19:31:22 +00004335 struct utimbuf tbuf, *host_tbuf;
4336 struct target_utimbuf *target_tbuf;
4337 if (arg2) {
bellard579a97f2007-11-11 14:26:47 +00004338 if (!lock_user_struct(VERIFY_READ, target_tbuf, arg2, 1))
4339 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004340 tbuf.actime = tswapl(target_tbuf->actime);
4341 tbuf.modtime = tswapl(target_tbuf->modtime);
4342 unlock_user_struct(target_tbuf, arg2, 0);
4343 host_tbuf = &tbuf;
bellardf72e8ff2004-05-03 19:23:07 +00004344 } else {
pbrook53a59602006-03-25 19:31:22 +00004345 host_tbuf = NULL;
bellardf72e8ff2004-05-03 19:23:07 +00004346 }
bellard579a97f2007-11-11 14:26:47 +00004347 if (!(p = lock_user_string(arg1)))
4348 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004349 ret = get_errno(utime(p, host_tbuf));
4350 unlock_user(p, arg1, 0);
bellardebc05482003-09-30 21:08:41 +00004351 }
4352 break;
thse5febef2007-04-01 18:31:35 +00004353#endif
bellard978a66f2004-12-06 22:58:05 +00004354 case TARGET_NR_utimes:
4355 {
bellard978a66f2004-12-06 22:58:05 +00004356 struct timeval *tvp, tv[2];
pbrook53a59602006-03-25 19:31:22 +00004357 if (arg2) {
ths788f5ec2007-12-09 02:37:05 +00004358 if (copy_from_user_timeval(&tv[0], arg2)
4359 || copy_from_user_timeval(&tv[1],
4360 arg2 + sizeof(struct target_timeval)))
4361 goto efault;
bellard978a66f2004-12-06 22:58:05 +00004362 tvp = tv;
4363 } else {
4364 tvp = NULL;
4365 }
bellard579a97f2007-11-11 14:26:47 +00004366 if (!(p = lock_user_string(arg1)))
4367 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004368 ret = get_errno(utimes(p, tvp));
4369 unlock_user(p, arg1, 0);
bellard978a66f2004-12-06 22:58:05 +00004370 }
4371 break;
balrogac8a6552008-09-20 02:25:39 +00004372#if defined(TARGET_NR_futimesat) && defined(__NR_futimesat)
4373 case TARGET_NR_futimesat:
4374 {
4375 struct timeval *tvp, tv[2];
4376 if (arg3) {
4377 if (copy_from_user_timeval(&tv[0], arg3)
4378 || copy_from_user_timeval(&tv[1],
4379 arg3 + sizeof(struct target_timeval)))
4380 goto efault;
4381 tvp = tv;
4382 } else {
4383 tvp = NULL;
4384 }
4385 if (!(p = lock_user_string(arg2)))
4386 goto efault;
4387 ret = get_errno(sys_futimesat(arg1, path(p), tvp));
4388 unlock_user(p, arg2, 0);
4389 }
4390 break;
4391#endif
bellardebc05482003-09-30 21:08:41 +00004392#ifdef TARGET_NR_stty
bellard31e31b82003-02-18 22:55:36 +00004393 case TARGET_NR_stty:
4394 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004395#endif
4396#ifdef TARGET_NR_gtty
bellard31e31b82003-02-18 22:55:36 +00004397 case TARGET_NR_gtty:
4398 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004399#endif
bellard31e31b82003-02-18 22:55:36 +00004400 case TARGET_NR_access:
bellard579a97f2007-11-11 14:26:47 +00004401 if (!(p = lock_user_string(arg1)))
4402 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004403 ret = get_errno(access(p, arg2));
4404 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004405 break;
ths92a34c12007-09-24 09:27:49 +00004406#if defined(TARGET_NR_faccessat) && defined(__NR_faccessat)
4407 case TARGET_NR_faccessat:
bellard579a97f2007-11-11 14:26:47 +00004408 if (!(p = lock_user_string(arg2)))
4409 goto efault;
aurel32465c9f02009-04-19 08:52:17 +00004410 ret = get_errno(sys_faccessat(arg1, p, arg3));
bellard579a97f2007-11-11 14:26:47 +00004411 unlock_user(p, arg2, 0);
ths92a34c12007-09-24 09:27:49 +00004412 break;
4413#endif
j_mayer7a3148a2007-04-05 07:13:51 +00004414#ifdef TARGET_NR_nice /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00004415 case TARGET_NR_nice:
4416 ret = get_errno(nice(arg1));
4417 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004418#endif
bellardebc05482003-09-30 21:08:41 +00004419#ifdef TARGET_NR_ftime
bellard31e31b82003-02-18 22:55:36 +00004420 case TARGET_NR_ftime:
4421 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004422#endif
bellard31e31b82003-02-18 22:55:36 +00004423 case TARGET_NR_sync:
bellard04369ff2003-03-20 22:33:23 +00004424 sync();
4425 ret = 0;
bellard31e31b82003-02-18 22:55:36 +00004426 break;
4427 case TARGET_NR_kill:
pbrook4cb05962008-05-30 18:05:19 +00004428 ret = get_errno(kill(arg1, target_to_host_signal(arg2)));
bellard31e31b82003-02-18 22:55:36 +00004429 break;
4430 case TARGET_NR_rename:
pbrook53a59602006-03-25 19:31:22 +00004431 {
4432 void *p2;
4433 p = lock_user_string(arg1);
4434 p2 = lock_user_string(arg2);
bellard579a97f2007-11-11 14:26:47 +00004435 if (!p || !p2)
4436 ret = -TARGET_EFAULT;
4437 else
4438 ret = get_errno(rename(p, p2));
pbrook53a59602006-03-25 19:31:22 +00004439 unlock_user(p2, arg2, 0);
4440 unlock_user(p, arg1, 0);
4441 }
bellard31e31b82003-02-18 22:55:36 +00004442 break;
ths722183f2007-09-24 09:24:37 +00004443#if defined(TARGET_NR_renameat) && defined(__NR_renameat)
4444 case TARGET_NR_renameat:
ths722183f2007-09-24 09:24:37 +00004445 {
bellard579a97f2007-11-11 14:26:47 +00004446 void *p2;
ths722183f2007-09-24 09:24:37 +00004447 p = lock_user_string(arg2);
4448 p2 = lock_user_string(arg4);
bellard579a97f2007-11-11 14:26:47 +00004449 if (!p || !p2)
ths0da46a62007-10-20 20:23:07 +00004450 ret = -TARGET_EFAULT;
ths722183f2007-09-24 09:24:37 +00004451 else
4452 ret = get_errno(sys_renameat(arg1, p, arg3, p2));
bellard579a97f2007-11-11 14:26:47 +00004453 unlock_user(p2, arg4, 0);
4454 unlock_user(p, arg2, 0);
ths722183f2007-09-24 09:24:37 +00004455 }
4456 break;
4457#endif
bellard31e31b82003-02-18 22:55:36 +00004458 case TARGET_NR_mkdir:
bellard579a97f2007-11-11 14:26:47 +00004459 if (!(p = lock_user_string(arg1)))
4460 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004461 ret = get_errno(mkdir(p, arg2));
4462 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004463 break;
ths4472ad02007-09-24 09:22:32 +00004464#if defined(TARGET_NR_mkdirat) && defined(__NR_mkdirat)
4465 case TARGET_NR_mkdirat:
bellard579a97f2007-11-11 14:26:47 +00004466 if (!(p = lock_user_string(arg2)))
4467 goto efault;
4468 ret = get_errno(sys_mkdirat(arg1, p, arg3));
4469 unlock_user(p, arg2, 0);
ths4472ad02007-09-24 09:22:32 +00004470 break;
4471#endif
bellard31e31b82003-02-18 22:55:36 +00004472 case TARGET_NR_rmdir:
bellard579a97f2007-11-11 14:26:47 +00004473 if (!(p = lock_user_string(arg1)))
4474 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004475 ret = get_errno(rmdir(p));
4476 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004477 break;
4478 case TARGET_NR_dup:
4479 ret = get_errno(dup(arg1));
4480 break;
4481 case TARGET_NR_pipe:
4482 {
pbrook53a59602006-03-25 19:31:22 +00004483 int host_pipe[2];
4484 ret = get_errno(pipe(host_pipe));
bellard31e31b82003-02-18 22:55:36 +00004485 if (!is_error(ret)) {
thsc12ab052007-06-01 11:50:36 +00004486#if defined(TARGET_MIPS)
thsead93602007-09-06 00:18:15 +00004487 CPUMIPSState *env = (CPUMIPSState*)cpu_env;
thsb5dc7732008-06-27 10:02:35 +00004488 env->active_tc.gpr[3] = host_pipe[1];
thsc12ab052007-06-01 11:50:36 +00004489 ret = host_pipe[0];
aurel32b5eff352008-03-11 23:30:22 +00004490#elif defined(TARGET_SH4)
4491 ((CPUSH4State*)cpu_env)->gregs[1] = host_pipe[1];
4492 ret = host_pipe[0];
thsc12ab052007-06-01 11:50:36 +00004493#else
bellard2f619692007-11-16 10:46:05 +00004494 if (put_user_s32(host_pipe[0], arg1)
4495 || put_user_s32(host_pipe[1], arg1 + sizeof(host_pipe[0])))
4496 goto efault;
thsc12ab052007-06-01 11:50:36 +00004497#endif
bellard31e31b82003-02-18 22:55:36 +00004498 }
4499 }
4500 break;
4501 case TARGET_NR_times:
bellard32f36bc2003-03-30 21:29:48 +00004502 {
pbrook53a59602006-03-25 19:31:22 +00004503 struct target_tms *tmsp;
bellard32f36bc2003-03-30 21:29:48 +00004504 struct tms tms;
4505 ret = get_errno(times(&tms));
pbrook53a59602006-03-25 19:31:22 +00004506 if (arg1) {
bellard579a97f2007-11-11 14:26:47 +00004507 tmsp = lock_user(VERIFY_WRITE, arg1, sizeof(struct target_tms), 0);
4508 if (!tmsp)
4509 goto efault;
bellardc596ed12003-07-13 17:32:31 +00004510 tmsp->tms_utime = tswapl(host_to_target_clock_t(tms.tms_utime));
4511 tmsp->tms_stime = tswapl(host_to_target_clock_t(tms.tms_stime));
4512 tmsp->tms_cutime = tswapl(host_to_target_clock_t(tms.tms_cutime));
4513 tmsp->tms_cstime = tswapl(host_to_target_clock_t(tms.tms_cstime));
bellard32f36bc2003-03-30 21:29:48 +00004514 }
bellardc596ed12003-07-13 17:32:31 +00004515 if (!is_error(ret))
4516 ret = host_to_target_clock_t(ret);
bellard32f36bc2003-03-30 21:29:48 +00004517 }
4518 break;
bellardebc05482003-09-30 21:08:41 +00004519#ifdef TARGET_NR_prof
bellard31e31b82003-02-18 22:55:36 +00004520 case TARGET_NR_prof:
4521 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004522#endif
thse5febef2007-04-01 18:31:35 +00004523#ifdef TARGET_NR_signal
bellard31e31b82003-02-18 22:55:36 +00004524 case TARGET_NR_signal:
4525 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00004526#endif
bellard31e31b82003-02-18 22:55:36 +00004527 case TARGET_NR_acct:
aurel3238d840e2009-01-30 19:48:17 +00004528 if (arg1 == 0) {
4529 ret = get_errno(acct(NULL));
4530 } else {
4531 if (!(p = lock_user_string(arg1)))
4532 goto efault;
4533 ret = get_errno(acct(path(p)));
4534 unlock_user(p, arg1, 0);
4535 }
pbrook24836682006-04-16 14:14:53 +00004536 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004537#ifdef TARGET_NR_umount2 /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00004538 case TARGET_NR_umount2:
bellard579a97f2007-11-11 14:26:47 +00004539 if (!(p = lock_user_string(arg1)))
4540 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004541 ret = get_errno(umount2(p, arg2));
4542 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004543 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004544#endif
bellardebc05482003-09-30 21:08:41 +00004545#ifdef TARGET_NR_lock
bellard31e31b82003-02-18 22:55:36 +00004546 case TARGET_NR_lock:
4547 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004548#endif
bellard31e31b82003-02-18 22:55:36 +00004549 case TARGET_NR_ioctl:
4550 ret = do_ioctl(arg1, arg2, arg3);
4551 break;
4552 case TARGET_NR_fcntl:
bellard9ee1fa22007-11-11 15:11:19 +00004553 ret = do_fcntl(arg1, arg2, arg3);
bellard31e31b82003-02-18 22:55:36 +00004554 break;
bellardebc05482003-09-30 21:08:41 +00004555#ifdef TARGET_NR_mpx
bellard31e31b82003-02-18 22:55:36 +00004556 case TARGET_NR_mpx:
4557 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004558#endif
bellard31e31b82003-02-18 22:55:36 +00004559 case TARGET_NR_setpgid:
4560 ret = get_errno(setpgid(arg1, arg2));
4561 break;
bellardebc05482003-09-30 21:08:41 +00004562#ifdef TARGET_NR_ulimit
bellard31e31b82003-02-18 22:55:36 +00004563 case TARGET_NR_ulimit:
4564 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004565#endif
4566#ifdef TARGET_NR_oldolduname
bellard31e31b82003-02-18 22:55:36 +00004567 case TARGET_NR_oldolduname:
4568 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004569#endif
bellard31e31b82003-02-18 22:55:36 +00004570 case TARGET_NR_umask:
4571 ret = get_errno(umask(arg1));
4572 break;
4573 case TARGET_NR_chroot:
bellard579a97f2007-11-11 14:26:47 +00004574 if (!(p = lock_user_string(arg1)))
4575 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004576 ret = get_errno(chroot(p));
4577 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004578 break;
4579 case TARGET_NR_ustat:
4580 goto unimplemented;
4581 case TARGET_NR_dup2:
4582 ret = get_errno(dup2(arg1, arg2));
4583 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004584#ifdef TARGET_NR_getppid /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00004585 case TARGET_NR_getppid:
4586 ret = get_errno(getppid());
4587 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004588#endif
bellard31e31b82003-02-18 22:55:36 +00004589 case TARGET_NR_getpgrp:
4590 ret = get_errno(getpgrp());
4591 break;
4592 case TARGET_NR_setsid:
4593 ret = get_errno(setsid());
4594 break;
thse5febef2007-04-01 18:31:35 +00004595#ifdef TARGET_NR_sigaction
bellard31e31b82003-02-18 22:55:36 +00004596 case TARGET_NR_sigaction:
bellard31e31b82003-02-18 22:55:36 +00004597 {
ths388bb212007-05-13 13:58:00 +00004598#if !defined(TARGET_MIPS)
pbrook53a59602006-03-25 19:31:22 +00004599 struct target_old_sigaction *old_act;
bellard66fb9762003-03-23 01:06:05 +00004600 struct target_sigaction act, oact, *pact;
pbrook53a59602006-03-25 19:31:22 +00004601 if (arg2) {
bellard579a97f2007-11-11 14:26:47 +00004602 if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1))
4603 goto efault;
bellard66fb9762003-03-23 01:06:05 +00004604 act._sa_handler = old_act->_sa_handler;
4605 target_siginitset(&act.sa_mask, old_act->sa_mask);
4606 act.sa_flags = old_act->sa_flags;
4607 act.sa_restorer = old_act->sa_restorer;
pbrook53a59602006-03-25 19:31:22 +00004608 unlock_user_struct(old_act, arg2, 0);
bellard66fb9762003-03-23 01:06:05 +00004609 pact = &act;
4610 } else {
4611 pact = NULL;
4612 }
4613 ret = get_errno(do_sigaction(arg1, pact, &oact));
pbrook53a59602006-03-25 19:31:22 +00004614 if (!is_error(ret) && arg3) {
bellard579a97f2007-11-11 14:26:47 +00004615 if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0))
4616 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004617 old_act->_sa_handler = oact._sa_handler;
4618 old_act->sa_mask = oact.sa_mask.sig[0];
4619 old_act->sa_flags = oact.sa_flags;
4620 old_act->sa_restorer = oact.sa_restorer;
4621 unlock_user_struct(old_act, arg3, 1);
bellard66fb9762003-03-23 01:06:05 +00004622 }
ths388bb212007-05-13 13:58:00 +00004623#else
bellard106ec872006-06-27 21:08:10 +00004624 struct target_sigaction act, oact, *pact, *old_act;
4625
4626 if (arg2) {
bellard579a97f2007-11-11 14:26:47 +00004627 if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1))
4628 goto efault;
bellard106ec872006-06-27 21:08:10 +00004629 act._sa_handler = old_act->_sa_handler;
4630 target_siginitset(&act.sa_mask, old_act->sa_mask.sig[0]);
4631 act.sa_flags = old_act->sa_flags;
4632 unlock_user_struct(old_act, arg2, 0);
4633 pact = &act;
4634 } else {
4635 pact = NULL;
4636 }
4637
4638 ret = get_errno(do_sigaction(arg1, pact, &oact));
4639
4640 if (!is_error(ret) && arg3) {
bellard579a97f2007-11-11 14:26:47 +00004641 if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0))
4642 goto efault;
bellard106ec872006-06-27 21:08:10 +00004643 old_act->_sa_handler = oact._sa_handler;
4644 old_act->sa_flags = oact.sa_flags;
4645 old_act->sa_mask.sig[0] = oact.sa_mask.sig[0];
4646 old_act->sa_mask.sig[1] = 0;
4647 old_act->sa_mask.sig[2] = 0;
4648 old_act->sa_mask.sig[3] = 0;
4649 unlock_user_struct(old_act, arg3, 1);
4650 }
ths388bb212007-05-13 13:58:00 +00004651#endif
bellard31e31b82003-02-18 22:55:36 +00004652 }
4653 break;
thse5febef2007-04-01 18:31:35 +00004654#endif
bellard66fb9762003-03-23 01:06:05 +00004655 case TARGET_NR_rt_sigaction:
pbrook53a59602006-03-25 19:31:22 +00004656 {
4657 struct target_sigaction *act;
4658 struct target_sigaction *oact;
4659
bellard579a97f2007-11-11 14:26:47 +00004660 if (arg2) {
4661 if (!lock_user_struct(VERIFY_READ, act, arg2, 1))
4662 goto efault;
4663 } else
pbrook53a59602006-03-25 19:31:22 +00004664 act = NULL;
bellard579a97f2007-11-11 14:26:47 +00004665 if (arg3) {
4666 if (!lock_user_struct(VERIFY_WRITE, oact, arg3, 0)) {
4667 ret = -TARGET_EFAULT;
4668 goto rt_sigaction_fail;
4669 }
4670 } else
pbrook53a59602006-03-25 19:31:22 +00004671 oact = NULL;
4672 ret = get_errno(do_sigaction(arg1, act, oact));
bellard579a97f2007-11-11 14:26:47 +00004673 rt_sigaction_fail:
4674 if (act)
pbrook53a59602006-03-25 19:31:22 +00004675 unlock_user_struct(act, arg2, 0);
bellard579a97f2007-11-11 14:26:47 +00004676 if (oact)
pbrook53a59602006-03-25 19:31:22 +00004677 unlock_user_struct(oact, arg3, 1);
4678 }
bellard66fb9762003-03-23 01:06:05 +00004679 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004680#ifdef TARGET_NR_sgetmask /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00004681 case TARGET_NR_sgetmask:
bellard66fb9762003-03-23 01:06:05 +00004682 {
4683 sigset_t cur_set;
blueswir1992f48a2007-10-14 16:27:31 +00004684 abi_ulong target_set;
bellard66fb9762003-03-23 01:06:05 +00004685 sigprocmask(0, NULL, &cur_set);
4686 host_to_target_old_sigset(&target_set, &cur_set);
4687 ret = target_set;
4688 }
4689 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004690#endif
4691#ifdef TARGET_NR_ssetmask /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00004692 case TARGET_NR_ssetmask:
bellard66fb9762003-03-23 01:06:05 +00004693 {
4694 sigset_t set, oset, cur_set;
blueswir1992f48a2007-10-14 16:27:31 +00004695 abi_ulong target_set = arg1;
bellard66fb9762003-03-23 01:06:05 +00004696 sigprocmask(0, NULL, &cur_set);
4697 target_to_host_old_sigset(&set, &target_set);
4698 sigorset(&set, &set, &cur_set);
4699 sigprocmask(SIG_SETMASK, &set, &oset);
4700 host_to_target_old_sigset(&target_set, &oset);
4701 ret = target_set;
4702 }
4703 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004704#endif
thse5febef2007-04-01 18:31:35 +00004705#ifdef TARGET_NR_sigprocmask
bellard66fb9762003-03-23 01:06:05 +00004706 case TARGET_NR_sigprocmask:
4707 {
4708 int how = arg1;
4709 sigset_t set, oldset, *set_ptr;
ths3b46e622007-09-17 08:09:54 +00004710
pbrook53a59602006-03-25 19:31:22 +00004711 if (arg2) {
bellard66fb9762003-03-23 01:06:05 +00004712 switch(how) {
4713 case TARGET_SIG_BLOCK:
4714 how = SIG_BLOCK;
4715 break;
4716 case TARGET_SIG_UNBLOCK:
4717 how = SIG_UNBLOCK;
4718 break;
4719 case TARGET_SIG_SETMASK:
4720 how = SIG_SETMASK;
4721 break;
4722 default:
ths0da46a62007-10-20 20:23:07 +00004723 ret = -TARGET_EINVAL;
bellard66fb9762003-03-23 01:06:05 +00004724 goto fail;
4725 }
bellard579a97f2007-11-11 14:26:47 +00004726 if (!(p = lock_user(VERIFY_READ, arg2, sizeof(target_sigset_t), 1)))
4727 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004728 target_to_host_old_sigset(&set, p);
4729 unlock_user(p, arg2, 0);
bellard66fb9762003-03-23 01:06:05 +00004730 set_ptr = &set;
4731 } else {
4732 how = 0;
4733 set_ptr = NULL;
4734 }
4735 ret = get_errno(sigprocmask(arg1, set_ptr, &oldset));
pbrook53a59602006-03-25 19:31:22 +00004736 if (!is_error(ret) && arg3) {
bellard579a97f2007-11-11 14:26:47 +00004737 if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0)))
4738 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004739 host_to_target_old_sigset(p, &oldset);
4740 unlock_user(p, arg3, sizeof(target_sigset_t));
bellard66fb9762003-03-23 01:06:05 +00004741 }
4742 }
4743 break;
thse5febef2007-04-01 18:31:35 +00004744#endif
bellard66fb9762003-03-23 01:06:05 +00004745 case TARGET_NR_rt_sigprocmask:
4746 {
4747 int how = arg1;
4748 sigset_t set, oldset, *set_ptr;
ths3b46e622007-09-17 08:09:54 +00004749
pbrook53a59602006-03-25 19:31:22 +00004750 if (arg2) {
bellard66fb9762003-03-23 01:06:05 +00004751 switch(how) {
4752 case TARGET_SIG_BLOCK:
4753 how = SIG_BLOCK;
4754 break;
4755 case TARGET_SIG_UNBLOCK:
4756 how = SIG_UNBLOCK;
4757 break;
4758 case TARGET_SIG_SETMASK:
4759 how = SIG_SETMASK;
4760 break;
4761 default:
ths0da46a62007-10-20 20:23:07 +00004762 ret = -TARGET_EINVAL;
bellard66fb9762003-03-23 01:06:05 +00004763 goto fail;
4764 }
bellard579a97f2007-11-11 14:26:47 +00004765 if (!(p = lock_user(VERIFY_READ, arg2, sizeof(target_sigset_t), 1)))
4766 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004767 target_to_host_sigset(&set, p);
4768 unlock_user(p, arg2, 0);
bellard66fb9762003-03-23 01:06:05 +00004769 set_ptr = &set;
4770 } else {
4771 how = 0;
4772 set_ptr = NULL;
4773 }
4774 ret = get_errno(sigprocmask(how, set_ptr, &oldset));
pbrook53a59602006-03-25 19:31:22 +00004775 if (!is_error(ret) && arg3) {
bellard579a97f2007-11-11 14:26:47 +00004776 if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0)))
4777 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004778 host_to_target_sigset(p, &oldset);
4779 unlock_user(p, arg3, sizeof(target_sigset_t));
bellard66fb9762003-03-23 01:06:05 +00004780 }
4781 }
4782 break;
thse5febef2007-04-01 18:31:35 +00004783#ifdef TARGET_NR_sigpending
bellard66fb9762003-03-23 01:06:05 +00004784 case TARGET_NR_sigpending:
4785 {
4786 sigset_t set;
4787 ret = get_errno(sigpending(&set));
4788 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00004789 if (!(p = lock_user(VERIFY_WRITE, arg1, sizeof(target_sigset_t), 0)))
4790 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004791 host_to_target_old_sigset(p, &set);
4792 unlock_user(p, arg1, sizeof(target_sigset_t));
bellard66fb9762003-03-23 01:06:05 +00004793 }
4794 }
4795 break;
thse5febef2007-04-01 18:31:35 +00004796#endif
bellard66fb9762003-03-23 01:06:05 +00004797 case TARGET_NR_rt_sigpending:
4798 {
4799 sigset_t set;
4800 ret = get_errno(sigpending(&set));
4801 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00004802 if (!(p = lock_user(VERIFY_WRITE, arg1, sizeof(target_sigset_t), 0)))
4803 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004804 host_to_target_sigset(p, &set);
4805 unlock_user(p, arg1, sizeof(target_sigset_t));
bellard66fb9762003-03-23 01:06:05 +00004806 }
4807 }
4808 break;
thse5febef2007-04-01 18:31:35 +00004809#ifdef TARGET_NR_sigsuspend
bellard66fb9762003-03-23 01:06:05 +00004810 case TARGET_NR_sigsuspend:
4811 {
4812 sigset_t set;
bellard579a97f2007-11-11 14:26:47 +00004813 if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
4814 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004815 target_to_host_old_sigset(&set, p);
4816 unlock_user(p, arg1, 0);
bellard66fb9762003-03-23 01:06:05 +00004817 ret = get_errno(sigsuspend(&set));
4818 }
4819 break;
thse5febef2007-04-01 18:31:35 +00004820#endif
bellard66fb9762003-03-23 01:06:05 +00004821 case TARGET_NR_rt_sigsuspend:
4822 {
4823 sigset_t set;
bellard579a97f2007-11-11 14:26:47 +00004824 if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
4825 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004826 target_to_host_sigset(&set, p);
4827 unlock_user(p, arg1, 0);
bellard66fb9762003-03-23 01:06:05 +00004828 ret = get_errno(sigsuspend(&set));
4829 }
4830 break;
4831 case TARGET_NR_rt_sigtimedwait:
4832 {
bellard66fb9762003-03-23 01:06:05 +00004833 sigset_t set;
4834 struct timespec uts, *puts;
4835 siginfo_t uinfo;
ths3b46e622007-09-17 08:09:54 +00004836
bellard579a97f2007-11-11 14:26:47 +00004837 if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
4838 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004839 target_to_host_sigset(&set, p);
4840 unlock_user(p, arg1, 0);
4841 if (arg3) {
bellard66fb9762003-03-23 01:06:05 +00004842 puts = &uts;
pbrook53a59602006-03-25 19:31:22 +00004843 target_to_host_timespec(puts, arg3);
bellard66fb9762003-03-23 01:06:05 +00004844 } else {
4845 puts = NULL;
4846 }
4847 ret = get_errno(sigtimedwait(&set, &uinfo, puts));
pbrook53a59602006-03-25 19:31:22 +00004848 if (!is_error(ret) && arg2) {
pbrooke1e3f302008-05-30 21:53:38 +00004849 if (!(p = lock_user(VERIFY_WRITE, arg2, sizeof(target_siginfo_t), 0)))
bellard579a97f2007-11-11 14:26:47 +00004850 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004851 host_to_target_siginfo(p, &uinfo);
pbrooke1e3f302008-05-30 21:53:38 +00004852 unlock_user(p, arg2, sizeof(target_siginfo_t));
bellard66fb9762003-03-23 01:06:05 +00004853 }
4854 }
4855 break;
4856 case TARGET_NR_rt_sigqueueinfo:
4857 {
4858 siginfo_t uinfo;
bellard579a97f2007-11-11 14:26:47 +00004859 if (!(p = lock_user(VERIFY_READ, arg3, sizeof(target_sigset_t), 1)))
4860 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004861 target_to_host_siginfo(&uinfo, p);
4862 unlock_user(p, arg1, 0);
bellard66fb9762003-03-23 01:06:05 +00004863 ret = get_errno(sys_rt_sigqueueinfo(arg1, arg2, &uinfo));
4864 }
4865 break;
thse5febef2007-04-01 18:31:35 +00004866#ifdef TARGET_NR_sigreturn
bellard66fb9762003-03-23 01:06:05 +00004867 case TARGET_NR_sigreturn:
4868 /* NOTE: ret is eax, so not transcoding must be done */
4869 ret = do_sigreturn(cpu_env);
4870 break;
thse5febef2007-04-01 18:31:35 +00004871#endif
bellard66fb9762003-03-23 01:06:05 +00004872 case TARGET_NR_rt_sigreturn:
4873 /* NOTE: ret is eax, so not transcoding must be done */
4874 ret = do_rt_sigreturn(cpu_env);
4875 break;
bellard31e31b82003-02-18 22:55:36 +00004876 case TARGET_NR_sethostname:
bellard579a97f2007-11-11 14:26:47 +00004877 if (!(p = lock_user_string(arg1)))
4878 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004879 ret = get_errno(sethostname(p, arg2));
4880 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004881 break;
4882 case TARGET_NR_setrlimit:
bellard9de5e442003-03-23 16:49:39 +00004883 {
4884 /* XXX: convert resource ? */
4885 int resource = arg1;
pbrook53a59602006-03-25 19:31:22 +00004886 struct target_rlimit *target_rlim;
bellard9de5e442003-03-23 16:49:39 +00004887 struct rlimit rlim;
bellard579a97f2007-11-11 14:26:47 +00004888 if (!lock_user_struct(VERIFY_READ, target_rlim, arg2, 1))
4889 goto efault;
bellard9de5e442003-03-23 16:49:39 +00004890 rlim.rlim_cur = tswapl(target_rlim->rlim_cur);
4891 rlim.rlim_max = tswapl(target_rlim->rlim_max);
pbrook53a59602006-03-25 19:31:22 +00004892 unlock_user_struct(target_rlim, arg2, 0);
bellard9de5e442003-03-23 16:49:39 +00004893 ret = get_errno(setrlimit(resource, &rlim));
4894 }
4895 break;
bellard31e31b82003-02-18 22:55:36 +00004896 case TARGET_NR_getrlimit:
bellard9de5e442003-03-23 16:49:39 +00004897 {
4898 /* XXX: convert resource ? */
4899 int resource = arg1;
pbrook53a59602006-03-25 19:31:22 +00004900 struct target_rlimit *target_rlim;
bellard9de5e442003-03-23 16:49:39 +00004901 struct rlimit rlim;
ths3b46e622007-09-17 08:09:54 +00004902
bellard9de5e442003-03-23 16:49:39 +00004903 ret = get_errno(getrlimit(resource, &rlim));
4904 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00004905 if (!lock_user_struct(VERIFY_WRITE, target_rlim, arg2, 0))
4906 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004907 rlim.rlim_cur = tswapl(target_rlim->rlim_cur);
4908 rlim.rlim_max = tswapl(target_rlim->rlim_max);
4909 unlock_user_struct(target_rlim, arg2, 1);
bellard9de5e442003-03-23 16:49:39 +00004910 }
4911 }
4912 break;
bellard31e31b82003-02-18 22:55:36 +00004913 case TARGET_NR_getrusage:
bellardb4091862003-05-16 15:39:34 +00004914 {
4915 struct rusage rusage;
bellardb4091862003-05-16 15:39:34 +00004916 ret = get_errno(getrusage(arg1, &rusage));
4917 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00004918 host_to_target_rusage(arg2, &rusage);
bellardb4091862003-05-16 15:39:34 +00004919 }
4920 }
4921 break;
bellard31e31b82003-02-18 22:55:36 +00004922 case TARGET_NR_gettimeofday:
4923 {
bellard31e31b82003-02-18 22:55:36 +00004924 struct timeval tv;
4925 ret = get_errno(gettimeofday(&tv, NULL));
4926 if (!is_error(ret)) {
ths788f5ec2007-12-09 02:37:05 +00004927 if (copy_to_user_timeval(arg1, &tv))
4928 goto efault;
bellard31e31b82003-02-18 22:55:36 +00004929 }
4930 }
4931 break;
4932 case TARGET_NR_settimeofday:
4933 {
bellard31e31b82003-02-18 22:55:36 +00004934 struct timeval tv;
ths788f5ec2007-12-09 02:37:05 +00004935 if (copy_from_user_timeval(&tv, arg1))
4936 goto efault;
bellard31e31b82003-02-18 22:55:36 +00004937 ret = get_errno(settimeofday(&tv, NULL));
4938 }
4939 break;
bellard048f6b42005-11-26 18:47:20 +00004940#ifdef TARGET_NR_select
bellard31e31b82003-02-18 22:55:36 +00004941 case TARGET_NR_select:
bellardf2674e32003-07-09 12:26:09 +00004942 {
pbrook53a59602006-03-25 19:31:22 +00004943 struct target_sel_arg_struct *sel;
blueswir1992f48a2007-10-14 16:27:31 +00004944 abi_ulong inp, outp, exp, tvp;
pbrook53a59602006-03-25 19:31:22 +00004945 long nsel;
4946
bellard579a97f2007-11-11 14:26:47 +00004947 if (!lock_user_struct(VERIFY_READ, sel, arg1, 1))
4948 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004949 nsel = tswapl(sel->n);
4950 inp = tswapl(sel->inp);
4951 outp = tswapl(sel->outp);
4952 exp = tswapl(sel->exp);
4953 tvp = tswapl(sel->tvp);
4954 unlock_user_struct(sel, arg1, 0);
4955 ret = do_select(nsel, inp, outp, exp, tvp);
bellardf2674e32003-07-09 12:26:09 +00004956 }
4957 break;
bellard048f6b42005-11-26 18:47:20 +00004958#endif
bellard31e31b82003-02-18 22:55:36 +00004959 case TARGET_NR_symlink:
pbrook53a59602006-03-25 19:31:22 +00004960 {
4961 void *p2;
4962 p = lock_user_string(arg1);
4963 p2 = lock_user_string(arg2);
bellard579a97f2007-11-11 14:26:47 +00004964 if (!p || !p2)
4965 ret = -TARGET_EFAULT;
4966 else
4967 ret = get_errno(symlink(p, p2));
pbrook53a59602006-03-25 19:31:22 +00004968 unlock_user(p2, arg2, 0);
4969 unlock_user(p, arg1, 0);
4970 }
bellard31e31b82003-02-18 22:55:36 +00004971 break;
thsf0b62432007-09-24 09:25:40 +00004972#if defined(TARGET_NR_symlinkat) && defined(__NR_symlinkat)
4973 case TARGET_NR_symlinkat:
thsf0b62432007-09-24 09:25:40 +00004974 {
bellard579a97f2007-11-11 14:26:47 +00004975 void *p2;
thsf0b62432007-09-24 09:25:40 +00004976 p = lock_user_string(arg1);
4977 p2 = lock_user_string(arg3);
bellard579a97f2007-11-11 14:26:47 +00004978 if (!p || !p2)
ths0da46a62007-10-20 20:23:07 +00004979 ret = -TARGET_EFAULT;
thsf0b62432007-09-24 09:25:40 +00004980 else
4981 ret = get_errno(sys_symlinkat(p, arg2, p2));
bellard579a97f2007-11-11 14:26:47 +00004982 unlock_user(p2, arg3, 0);
4983 unlock_user(p, arg1, 0);
thsf0b62432007-09-24 09:25:40 +00004984 }
4985 break;
4986#endif
bellardebc05482003-09-30 21:08:41 +00004987#ifdef TARGET_NR_oldlstat
bellard31e31b82003-02-18 22:55:36 +00004988 case TARGET_NR_oldlstat:
4989 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004990#endif
bellard31e31b82003-02-18 22:55:36 +00004991 case TARGET_NR_readlink:
pbrook53a59602006-03-25 19:31:22 +00004992 {
aurel32d088d662009-01-30 20:09:01 +00004993 void *p2, *temp;
pbrook53a59602006-03-25 19:31:22 +00004994 p = lock_user_string(arg1);
bellard579a97f2007-11-11 14:26:47 +00004995 p2 = lock_user(VERIFY_WRITE, arg2, arg3, 0);
4996 if (!p || !p2)
4997 ret = -TARGET_EFAULT;
aurel32d088d662009-01-30 20:09:01 +00004998 else {
4999 if (strncmp((const char *)p, "/proc/self/exe", 14) == 0) {
5000 char real[PATH_MAX];
5001 temp = realpath(exec_path,real);
5002 ret = (temp==NULL) ? get_errno(-1) : strlen(real) ;
5003 snprintf((char *)p2, arg3, "%s", real);
5004 }
5005 else
5006 ret = get_errno(readlink(path(p), p2, arg3));
aurel32d088d662009-01-30 20:09:01 +00005007 }
pbrook53a59602006-03-25 19:31:22 +00005008 unlock_user(p2, arg2, ret);
5009 unlock_user(p, arg1, 0);
5010 }
bellard31e31b82003-02-18 22:55:36 +00005011 break;
ths5e0ccb12007-09-24 09:26:10 +00005012#if defined(TARGET_NR_readlinkat) && defined(__NR_readlinkat)
5013 case TARGET_NR_readlinkat:
ths5e0ccb12007-09-24 09:26:10 +00005014 {
bellard579a97f2007-11-11 14:26:47 +00005015 void *p2;
ths5e0ccb12007-09-24 09:26:10 +00005016 p = lock_user_string(arg2);
bellard579a97f2007-11-11 14:26:47 +00005017 p2 = lock_user(VERIFY_WRITE, arg3, arg4, 0);
5018 if (!p || !p2)
ths0da46a62007-10-20 20:23:07 +00005019 ret = -TARGET_EFAULT;
ths5e0ccb12007-09-24 09:26:10 +00005020 else
5021 ret = get_errno(sys_readlinkat(arg1, path(p), p2, arg4));
bellard579a97f2007-11-11 14:26:47 +00005022 unlock_user(p2, arg3, ret);
5023 unlock_user(p, arg2, 0);
ths5e0ccb12007-09-24 09:26:10 +00005024 }
5025 break;
5026#endif
thse5febef2007-04-01 18:31:35 +00005027#ifdef TARGET_NR_uselib
bellard31e31b82003-02-18 22:55:36 +00005028 case TARGET_NR_uselib:
5029 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00005030#endif
5031#ifdef TARGET_NR_swapon
bellard31e31b82003-02-18 22:55:36 +00005032 case TARGET_NR_swapon:
bellard579a97f2007-11-11 14:26:47 +00005033 if (!(p = lock_user_string(arg1)))
5034 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005035 ret = get_errno(swapon(p, arg2));
5036 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00005037 break;
thse5febef2007-04-01 18:31:35 +00005038#endif
bellard31e31b82003-02-18 22:55:36 +00005039 case TARGET_NR_reboot:
5040 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00005041#ifdef TARGET_NR_readdir
bellard31e31b82003-02-18 22:55:36 +00005042 case TARGET_NR_readdir:
5043 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00005044#endif
5045#ifdef TARGET_NR_mmap
bellard31e31b82003-02-18 22:55:36 +00005046 case TARGET_NR_mmap:
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02005047#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 +00005048 {
blueswir1992f48a2007-10-14 16:27:31 +00005049 abi_ulong *v;
5050 abi_ulong v1, v2, v3, v4, v5, v6;
bellard579a97f2007-11-11 14:26:47 +00005051 if (!(v = lock_user(VERIFY_READ, arg1, 6 * sizeof(abi_ulong), 1)))
5052 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005053 v1 = tswapl(v[0]);
5054 v2 = tswapl(v[1]);
5055 v3 = tswapl(v[2]);
5056 v4 = tswapl(v[3]);
5057 v5 = tswapl(v[4]);
5058 v6 = tswapl(v[5]);
5059 unlock_user(v, arg1, 0);
ths5fafdf22007-09-16 21:08:06 +00005060 ret = get_errno(target_mmap(v1, v2, v3,
bellard5286db72003-06-05 00:57:30 +00005061 target_to_host_bitmask(v4, mmap_flags_tbl),
5062 v5, v6));
bellard31e31b82003-02-18 22:55:36 +00005063 }
bellard31e31b82003-02-18 22:55:36 +00005064#else
ths5fafdf22007-09-16 21:08:06 +00005065 ret = get_errno(target_mmap(arg1, arg2, arg3,
5066 target_to_host_bitmask(arg4, mmap_flags_tbl),
bellard6fb883e2003-07-09 17:12:39 +00005067 arg5,
5068 arg6));
bellard31e31b82003-02-18 22:55:36 +00005069#endif
bellard6fb883e2003-07-09 17:12:39 +00005070 break;
thse5febef2007-04-01 18:31:35 +00005071#endif
bellarda315a142005-01-30 22:59:18 +00005072#ifdef TARGET_NR_mmap2
bellard6fb883e2003-07-09 17:12:39 +00005073 case TARGET_NR_mmap2:
pbrookbb7ec042008-03-25 22:28:25 +00005074#ifndef MMAP_SHIFT
bellardc573ff62004-01-04 15:51:36 +00005075#define MMAP_SHIFT 12
bellardc573ff62004-01-04 15:51:36 +00005076#endif
ths5fafdf22007-09-16 21:08:06 +00005077 ret = get_errno(target_mmap(arg1, arg2, arg3,
5078 target_to_host_bitmask(arg4, mmap_flags_tbl),
bellard5286db72003-06-05 00:57:30 +00005079 arg5,
bellardc573ff62004-01-04 15:51:36 +00005080 arg6 << MMAP_SHIFT));
bellard31e31b82003-02-18 22:55:36 +00005081 break;
bellarda315a142005-01-30 22:59:18 +00005082#endif
bellard31e31b82003-02-18 22:55:36 +00005083 case TARGET_NR_munmap:
bellard54936002003-05-13 00:25:15 +00005084 ret = get_errno(target_munmap(arg1, arg2));
bellard31e31b82003-02-18 22:55:36 +00005085 break;
bellard9de5e442003-03-23 16:49:39 +00005086 case TARGET_NR_mprotect:
bellard54936002003-05-13 00:25:15 +00005087 ret = get_errno(target_mprotect(arg1, arg2, arg3));
bellard9de5e442003-03-23 16:49:39 +00005088 break;
thse5febef2007-04-01 18:31:35 +00005089#ifdef TARGET_NR_mremap
bellard9de5e442003-03-23 16:49:39 +00005090 case TARGET_NR_mremap:
bellard54936002003-05-13 00:25:15 +00005091 ret = get_errno(target_mremap(arg1, arg2, arg3, arg4, arg5));
bellard9de5e442003-03-23 16:49:39 +00005092 break;
thse5febef2007-04-01 18:31:35 +00005093#endif
pbrook53a59602006-03-25 19:31:22 +00005094 /* ??? msync/mlock/munlock are broken for softmmu. */
thse5febef2007-04-01 18:31:35 +00005095#ifdef TARGET_NR_msync
bellard9de5e442003-03-23 16:49:39 +00005096 case TARGET_NR_msync:
pbrook53a59602006-03-25 19:31:22 +00005097 ret = get_errno(msync(g2h(arg1), arg2, arg3));
bellard9de5e442003-03-23 16:49:39 +00005098 break;
thse5febef2007-04-01 18:31:35 +00005099#endif
5100#ifdef TARGET_NR_mlock
bellard9de5e442003-03-23 16:49:39 +00005101 case TARGET_NR_mlock:
pbrook53a59602006-03-25 19:31:22 +00005102 ret = get_errno(mlock(g2h(arg1), arg2));
bellard9de5e442003-03-23 16:49:39 +00005103 break;
thse5febef2007-04-01 18:31:35 +00005104#endif
5105#ifdef TARGET_NR_munlock
bellard9de5e442003-03-23 16:49:39 +00005106 case TARGET_NR_munlock:
pbrook53a59602006-03-25 19:31:22 +00005107 ret = get_errno(munlock(g2h(arg1), arg2));
bellard9de5e442003-03-23 16:49:39 +00005108 break;
thse5febef2007-04-01 18:31:35 +00005109#endif
5110#ifdef TARGET_NR_mlockall
bellard9de5e442003-03-23 16:49:39 +00005111 case TARGET_NR_mlockall:
5112 ret = get_errno(mlockall(arg1));
5113 break;
thse5febef2007-04-01 18:31:35 +00005114#endif
5115#ifdef TARGET_NR_munlockall
bellard9de5e442003-03-23 16:49:39 +00005116 case TARGET_NR_munlockall:
5117 ret = get_errno(munlockall());
5118 break;
thse5febef2007-04-01 18:31:35 +00005119#endif
bellard31e31b82003-02-18 22:55:36 +00005120 case TARGET_NR_truncate:
bellard579a97f2007-11-11 14:26:47 +00005121 if (!(p = lock_user_string(arg1)))
5122 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005123 ret = get_errno(truncate(p, arg2));
5124 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00005125 break;
5126 case TARGET_NR_ftruncate:
5127 ret = get_errno(ftruncate(arg1, arg2));
5128 break;
5129 case TARGET_NR_fchmod:
5130 ret = get_errno(fchmod(arg1, arg2));
5131 break;
ths814d7972007-09-24 09:26:51 +00005132#if defined(TARGET_NR_fchmodat) && defined(__NR_fchmodat)
5133 case TARGET_NR_fchmodat:
bellard579a97f2007-11-11 14:26:47 +00005134 if (!(p = lock_user_string(arg2)))
5135 goto efault;
aurel32465c9f02009-04-19 08:52:17 +00005136 ret = get_errno(sys_fchmodat(arg1, p, arg3));
bellard579a97f2007-11-11 14:26:47 +00005137 unlock_user(p, arg2, 0);
ths814d7972007-09-24 09:26:51 +00005138 break;
5139#endif
bellard31e31b82003-02-18 22:55:36 +00005140 case TARGET_NR_getpriority:
thsc6cda172007-10-09 03:42:34 +00005141 /* libc does special remapping of the return value of
5142 * sys_getpriority() so it's just easiest to call
5143 * sys_getpriority() directly rather than through libc. */
5144 ret = sys_getpriority(arg1, arg2);
bellard31e31b82003-02-18 22:55:36 +00005145 break;
5146 case TARGET_NR_setpriority:
5147 ret = get_errno(setpriority(arg1, arg2, arg3));
5148 break;
bellardebc05482003-09-30 21:08:41 +00005149#ifdef TARGET_NR_profil
bellard31e31b82003-02-18 22:55:36 +00005150 case TARGET_NR_profil:
5151 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00005152#endif
bellard31e31b82003-02-18 22:55:36 +00005153 case TARGET_NR_statfs:
bellard579a97f2007-11-11 14:26:47 +00005154 if (!(p = lock_user_string(arg1)))
5155 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005156 ret = get_errno(statfs(path(p), &stfs));
5157 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00005158 convert_statfs:
5159 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00005160 struct target_statfs *target_stfs;
ths3b46e622007-09-17 08:09:54 +00005161
bellard579a97f2007-11-11 14:26:47 +00005162 if (!lock_user_struct(VERIFY_WRITE, target_stfs, arg2, 0))
5163 goto efault;
5164 __put_user(stfs.f_type, &target_stfs->f_type);
5165 __put_user(stfs.f_bsize, &target_stfs->f_bsize);
5166 __put_user(stfs.f_blocks, &target_stfs->f_blocks);
5167 __put_user(stfs.f_bfree, &target_stfs->f_bfree);
5168 __put_user(stfs.f_bavail, &target_stfs->f_bavail);
5169 __put_user(stfs.f_files, &target_stfs->f_files);
5170 __put_user(stfs.f_ffree, &target_stfs->f_ffree);
5171 __put_user(stfs.f_fsid.__val[0], &target_stfs->f_fsid.val[0]);
5172 __put_user(stfs.f_fsid.__val[1], &target_stfs->f_fsid.val[1]);
5173 __put_user(stfs.f_namelen, &target_stfs->f_namelen);
pbrook53a59602006-03-25 19:31:22 +00005174 unlock_user_struct(target_stfs, arg2, 1);
bellard31e31b82003-02-18 22:55:36 +00005175 }
5176 break;
5177 case TARGET_NR_fstatfs:
bellard56c8f682005-11-28 22:28:41 +00005178 ret = get_errno(fstatfs(arg1, &stfs));
bellard31e31b82003-02-18 22:55:36 +00005179 goto convert_statfs;
bellard56c8f682005-11-28 22:28:41 +00005180#ifdef TARGET_NR_statfs64
5181 case TARGET_NR_statfs64:
bellard579a97f2007-11-11 14:26:47 +00005182 if (!(p = lock_user_string(arg1)))
5183 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005184 ret = get_errno(statfs(path(p), &stfs));
5185 unlock_user(p, arg1, 0);
bellard56c8f682005-11-28 22:28:41 +00005186 convert_statfs64:
5187 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00005188 struct target_statfs64 *target_stfs;
ths3b46e622007-09-17 08:09:54 +00005189
bellard579a97f2007-11-11 14:26:47 +00005190 if (!lock_user_struct(VERIFY_WRITE, target_stfs, arg3, 0))
5191 goto efault;
5192 __put_user(stfs.f_type, &target_stfs->f_type);
5193 __put_user(stfs.f_bsize, &target_stfs->f_bsize);
5194 __put_user(stfs.f_blocks, &target_stfs->f_blocks);
5195 __put_user(stfs.f_bfree, &target_stfs->f_bfree);
5196 __put_user(stfs.f_bavail, &target_stfs->f_bavail);
5197 __put_user(stfs.f_files, &target_stfs->f_files);
5198 __put_user(stfs.f_ffree, &target_stfs->f_ffree);
5199 __put_user(stfs.f_fsid.__val[0], &target_stfs->f_fsid.val[0]);
5200 __put_user(stfs.f_fsid.__val[1], &target_stfs->f_fsid.val[1]);
5201 __put_user(stfs.f_namelen, &target_stfs->f_namelen);
5202 unlock_user_struct(target_stfs, arg3, 1);
bellard56c8f682005-11-28 22:28:41 +00005203 }
5204 break;
5205 case TARGET_NR_fstatfs64:
5206 ret = get_errno(fstatfs(arg1, &stfs));
5207 goto convert_statfs64;
5208#endif
bellardebc05482003-09-30 21:08:41 +00005209#ifdef TARGET_NR_ioperm
bellard31e31b82003-02-18 22:55:36 +00005210 case TARGET_NR_ioperm:
5211 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00005212#endif
thse5febef2007-04-01 18:31:35 +00005213#ifdef TARGET_NR_socketcall
bellard31e31b82003-02-18 22:55:36 +00005214 case TARGET_NR_socketcall:
pbrook53a59602006-03-25 19:31:22 +00005215 ret = do_socketcall(arg1, arg2);
bellard31e31b82003-02-18 22:55:36 +00005216 break;
thse5febef2007-04-01 18:31:35 +00005217#endif
bellard3532fa72006-06-24 15:06:03 +00005218#ifdef TARGET_NR_accept
5219 case TARGET_NR_accept:
pbrook1be9e1d2006-11-19 15:26:04 +00005220 ret = do_accept(arg1, arg2, arg3);
bellard3532fa72006-06-24 15:06:03 +00005221 break;
5222#endif
5223#ifdef TARGET_NR_bind
5224 case TARGET_NR_bind:
5225 ret = do_bind(arg1, arg2, arg3);
5226 break;
5227#endif
5228#ifdef TARGET_NR_connect
5229 case TARGET_NR_connect:
5230 ret = do_connect(arg1, arg2, arg3);
5231 break;
5232#endif
5233#ifdef TARGET_NR_getpeername
5234 case TARGET_NR_getpeername:
pbrook1be9e1d2006-11-19 15:26:04 +00005235 ret = do_getpeername(arg1, arg2, arg3);
bellard3532fa72006-06-24 15:06:03 +00005236 break;
5237#endif
5238#ifdef TARGET_NR_getsockname
5239 case TARGET_NR_getsockname:
pbrook1be9e1d2006-11-19 15:26:04 +00005240 ret = do_getsockname(arg1, arg2, arg3);
bellard3532fa72006-06-24 15:06:03 +00005241 break;
5242#endif
5243#ifdef TARGET_NR_getsockopt
5244 case TARGET_NR_getsockopt:
5245 ret = do_getsockopt(arg1, arg2, arg3, arg4, arg5);
5246 break;
5247#endif
5248#ifdef TARGET_NR_listen
5249 case TARGET_NR_listen:
pbrook1be9e1d2006-11-19 15:26:04 +00005250 ret = get_errno(listen(arg1, arg2));
bellard3532fa72006-06-24 15:06:03 +00005251 break;
5252#endif
5253#ifdef TARGET_NR_recv
5254 case TARGET_NR_recv:
pbrook214201b2007-03-17 01:27:24 +00005255 ret = do_recvfrom(arg1, arg2, arg3, arg4, 0, 0);
bellard3532fa72006-06-24 15:06:03 +00005256 break;
5257#endif
5258#ifdef TARGET_NR_recvfrom
5259 case TARGET_NR_recvfrom:
pbrook214201b2007-03-17 01:27:24 +00005260 ret = do_recvfrom(arg1, arg2, arg3, arg4, arg5, arg6);
bellard3532fa72006-06-24 15:06:03 +00005261 break;
5262#endif
5263#ifdef TARGET_NR_recvmsg
5264 case TARGET_NR_recvmsg:
5265 ret = do_sendrecvmsg(arg1, arg2, arg3, 0);
5266 break;
5267#endif
5268#ifdef TARGET_NR_send
5269 case TARGET_NR_send:
pbrook1be9e1d2006-11-19 15:26:04 +00005270 ret = do_sendto(arg1, arg2, arg3, arg4, 0, 0);
bellard3532fa72006-06-24 15:06:03 +00005271 break;
5272#endif
5273#ifdef TARGET_NR_sendmsg
5274 case TARGET_NR_sendmsg:
5275 ret = do_sendrecvmsg(arg1, arg2, arg3, 1);
5276 break;
5277#endif
5278#ifdef TARGET_NR_sendto
5279 case TARGET_NR_sendto:
pbrook1be9e1d2006-11-19 15:26:04 +00005280 ret = do_sendto(arg1, arg2, arg3, arg4, arg5, arg6);
bellard3532fa72006-06-24 15:06:03 +00005281 break;
5282#endif
5283#ifdef TARGET_NR_shutdown
5284 case TARGET_NR_shutdown:
pbrook1be9e1d2006-11-19 15:26:04 +00005285 ret = get_errno(shutdown(arg1, arg2));
bellard3532fa72006-06-24 15:06:03 +00005286 break;
5287#endif
5288#ifdef TARGET_NR_socket
5289 case TARGET_NR_socket:
5290 ret = do_socket(arg1, arg2, arg3);
5291 break;
5292#endif
5293#ifdef TARGET_NR_socketpair
5294 case TARGET_NR_socketpair:
pbrook1be9e1d2006-11-19 15:26:04 +00005295 ret = do_socketpair(arg1, arg2, arg3, arg4);
bellard3532fa72006-06-24 15:06:03 +00005296 break;
5297#endif
5298#ifdef TARGET_NR_setsockopt
5299 case TARGET_NR_setsockopt:
5300 ret = do_setsockopt(arg1, arg2, arg3, arg4, (socklen_t) arg5);
5301 break;
5302#endif
ths7494b0f2007-02-11 18:26:53 +00005303
bellard31e31b82003-02-18 22:55:36 +00005304 case TARGET_NR_syslog:
bellard579a97f2007-11-11 14:26:47 +00005305 if (!(p = lock_user_string(arg2)))
5306 goto efault;
thse5574482007-02-11 20:03:13 +00005307 ret = get_errno(sys_syslog((int)arg1, p, (int)arg3));
5308 unlock_user(p, arg2, 0);
ths7494b0f2007-02-11 18:26:53 +00005309 break;
5310
bellard31e31b82003-02-18 22:55:36 +00005311 case TARGET_NR_setitimer:
bellard66fb9762003-03-23 01:06:05 +00005312 {
bellard66fb9762003-03-23 01:06:05 +00005313 struct itimerval value, ovalue, *pvalue;
5314
pbrook53a59602006-03-25 19:31:22 +00005315 if (arg2) {
bellard66fb9762003-03-23 01:06:05 +00005316 pvalue = &value;
ths788f5ec2007-12-09 02:37:05 +00005317 if (copy_from_user_timeval(&pvalue->it_interval, arg2)
5318 || copy_from_user_timeval(&pvalue->it_value,
5319 arg2 + sizeof(struct target_timeval)))
5320 goto efault;
bellard66fb9762003-03-23 01:06:05 +00005321 } else {
5322 pvalue = NULL;
5323 }
5324 ret = get_errno(setitimer(arg1, pvalue, &ovalue));
pbrook53a59602006-03-25 19:31:22 +00005325 if (!is_error(ret) && arg3) {
ths788f5ec2007-12-09 02:37:05 +00005326 if (copy_to_user_timeval(arg3,
5327 &ovalue.it_interval)
5328 || copy_to_user_timeval(arg3 + sizeof(struct target_timeval),
5329 &ovalue.it_value))
5330 goto efault;
bellard66fb9762003-03-23 01:06:05 +00005331 }
5332 }
5333 break;
bellard31e31b82003-02-18 22:55:36 +00005334 case TARGET_NR_getitimer:
bellard66fb9762003-03-23 01:06:05 +00005335 {
bellard66fb9762003-03-23 01:06:05 +00005336 struct itimerval value;
ths3b46e622007-09-17 08:09:54 +00005337
bellard66fb9762003-03-23 01:06:05 +00005338 ret = get_errno(getitimer(arg1, &value));
pbrook53a59602006-03-25 19:31:22 +00005339 if (!is_error(ret) && arg2) {
ths788f5ec2007-12-09 02:37:05 +00005340 if (copy_to_user_timeval(arg2,
5341 &value.it_interval)
5342 || copy_to_user_timeval(arg2 + sizeof(struct target_timeval),
5343 &value.it_value))
5344 goto efault;
bellard66fb9762003-03-23 01:06:05 +00005345 }
5346 }
5347 break;
bellard31e31b82003-02-18 22:55:36 +00005348 case TARGET_NR_stat:
bellard579a97f2007-11-11 14:26:47 +00005349 if (!(p = lock_user_string(arg1)))
5350 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005351 ret = get_errno(stat(path(p), &st));
5352 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00005353 goto do_stat;
5354 case TARGET_NR_lstat:
bellard579a97f2007-11-11 14:26:47 +00005355 if (!(p = lock_user_string(arg1)))
5356 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005357 ret = get_errno(lstat(path(p), &st));
5358 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00005359 goto do_stat;
5360 case TARGET_NR_fstat:
5361 {
5362 ret = get_errno(fstat(arg1, &st));
5363 do_stat:
5364 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00005365 struct target_stat *target_st;
thse3584652007-06-01 11:49:38 +00005366
bellard579a97f2007-11-11 14:26:47 +00005367 if (!lock_user_struct(VERIFY_WRITE, target_st, arg2, 0))
5368 goto efault;
bellardd2fd1af2007-11-14 18:08:56 +00005369 __put_user(st.st_dev, &target_st->st_dev);
5370 __put_user(st.st_ino, &target_st->st_ino);
5371 __put_user(st.st_mode, &target_st->st_mode);
5372 __put_user(st.st_uid, &target_st->st_uid);
5373 __put_user(st.st_gid, &target_st->st_gid);
5374 __put_user(st.st_nlink, &target_st->st_nlink);
5375 __put_user(st.st_rdev, &target_st->st_rdev);
5376 __put_user(st.st_size, &target_st->st_size);
5377 __put_user(st.st_blksize, &target_st->st_blksize);
5378 __put_user(st.st_blocks, &target_st->st_blocks);
5379 __put_user(st.st_atime, &target_st->target_st_atime);
5380 __put_user(st.st_mtime, &target_st->target_st_mtime);
5381 __put_user(st.st_ctime, &target_st->target_st_ctime);
pbrook53a59602006-03-25 19:31:22 +00005382 unlock_user_struct(target_st, arg2, 1);
bellard31e31b82003-02-18 22:55:36 +00005383 }
5384 }
5385 break;
bellardebc05482003-09-30 21:08:41 +00005386#ifdef TARGET_NR_olduname
bellard31e31b82003-02-18 22:55:36 +00005387 case TARGET_NR_olduname:
5388 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00005389#endif
5390#ifdef TARGET_NR_iopl
bellard31e31b82003-02-18 22:55:36 +00005391 case TARGET_NR_iopl:
5392 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00005393#endif
bellard31e31b82003-02-18 22:55:36 +00005394 case TARGET_NR_vhangup:
5395 ret = get_errno(vhangup());
5396 break;
bellardebc05482003-09-30 21:08:41 +00005397#ifdef TARGET_NR_idle
bellard31e31b82003-02-18 22:55:36 +00005398 case TARGET_NR_idle:
5399 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00005400#endif
bellard42ad6ae2005-01-03 22:48:11 +00005401#ifdef TARGET_NR_syscall
5402 case TARGET_NR_syscall:
5403 ret = do_syscall(cpu_env,arg1 & 0xffff,arg2,arg3,arg4,arg5,arg6,0);
5404 break;
5405#endif
bellard31e31b82003-02-18 22:55:36 +00005406 case TARGET_NR_wait4:
5407 {
5408 int status;
blueswir1992f48a2007-10-14 16:27:31 +00005409 abi_long status_ptr = arg2;
bellard31e31b82003-02-18 22:55:36 +00005410 struct rusage rusage, *rusage_ptr;
blueswir1992f48a2007-10-14 16:27:31 +00005411 abi_ulong target_rusage = arg4;
bellard31e31b82003-02-18 22:55:36 +00005412 if (target_rusage)
5413 rusage_ptr = &rusage;
5414 else
5415 rusage_ptr = NULL;
5416 ret = get_errno(wait4(arg1, &status, arg3, rusage_ptr));
5417 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +00005418 if (status_ptr) {
pbrook1d9d8b52009-04-16 15:17:02 +00005419 status = host_to_target_waitstatus(status);
bellard2f619692007-11-16 10:46:05 +00005420 if (put_user_s32(status, status_ptr))
5421 goto efault;
bellard31e31b82003-02-18 22:55:36 +00005422 }
bellard2f619692007-11-16 10:46:05 +00005423 if (target_rusage)
5424 host_to_target_rusage(target_rusage, &rusage);
bellard31e31b82003-02-18 22:55:36 +00005425 }
5426 }
5427 break;
thse5febef2007-04-01 18:31:35 +00005428#ifdef TARGET_NR_swapoff
bellard31e31b82003-02-18 22:55:36 +00005429 case TARGET_NR_swapoff:
bellard579a97f2007-11-11 14:26:47 +00005430 if (!(p = lock_user_string(arg1)))
5431 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005432 ret = get_errno(swapoff(p));
5433 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00005434 break;
thse5febef2007-04-01 18:31:35 +00005435#endif
bellard31e31b82003-02-18 22:55:36 +00005436 case TARGET_NR_sysinfo:
bellarda5448a72004-06-19 16:59:03 +00005437 {
pbrook53a59602006-03-25 19:31:22 +00005438 struct target_sysinfo *target_value;
bellarda5448a72004-06-19 16:59:03 +00005439 struct sysinfo value;
5440 ret = get_errno(sysinfo(&value));
pbrook53a59602006-03-25 19:31:22 +00005441 if (!is_error(ret) && arg1)
bellarda5448a72004-06-19 16:59:03 +00005442 {
bellard579a97f2007-11-11 14:26:47 +00005443 if (!lock_user_struct(VERIFY_WRITE, target_value, arg1, 0))
5444 goto efault;
bellarda5448a72004-06-19 16:59:03 +00005445 __put_user(value.uptime, &target_value->uptime);
5446 __put_user(value.loads[0], &target_value->loads[0]);
5447 __put_user(value.loads[1], &target_value->loads[1]);
5448 __put_user(value.loads[2], &target_value->loads[2]);
5449 __put_user(value.totalram, &target_value->totalram);
5450 __put_user(value.freeram, &target_value->freeram);
5451 __put_user(value.sharedram, &target_value->sharedram);
5452 __put_user(value.bufferram, &target_value->bufferram);
5453 __put_user(value.totalswap, &target_value->totalswap);
5454 __put_user(value.freeswap, &target_value->freeswap);
5455 __put_user(value.procs, &target_value->procs);
5456 __put_user(value.totalhigh, &target_value->totalhigh);
5457 __put_user(value.freehigh, &target_value->freehigh);
5458 __put_user(value.mem_unit, &target_value->mem_unit);
pbrook53a59602006-03-25 19:31:22 +00005459 unlock_user_struct(target_value, arg1, 1);
bellarda5448a72004-06-19 16:59:03 +00005460 }
5461 }
5462 break;
thse5febef2007-04-01 18:31:35 +00005463#ifdef TARGET_NR_ipc
bellard31e31b82003-02-18 22:55:36 +00005464 case TARGET_NR_ipc:
bellard8853f862004-02-22 14:57:26 +00005465 ret = do_ipc(arg1, arg2, arg3, arg4, arg5, arg6);
5466 break;
thse5febef2007-04-01 18:31:35 +00005467#endif
aurel32e5289082009-04-18 16:16:12 +00005468#ifdef TARGET_NR_semget
5469 case TARGET_NR_semget:
5470 ret = get_errno(semget(arg1, arg2, arg3));
5471 break;
5472#endif
5473#ifdef TARGET_NR_semop
5474 case TARGET_NR_semop:
5475 ret = get_errno(do_semop(arg1, arg2, arg3));
5476 break;
5477#endif
5478#ifdef TARGET_NR_semctl
5479 case TARGET_NR_semctl:
5480 ret = do_semctl(arg1, arg2, arg3, (union target_semun)(abi_ulong)arg4);
5481 break;
5482#endif
aurel32eeb438c2008-10-13 21:08:55 +00005483#ifdef TARGET_NR_msgctl
5484 case TARGET_NR_msgctl:
5485 ret = do_msgctl(arg1, arg2, arg3);
5486 break;
5487#endif
5488#ifdef TARGET_NR_msgget
5489 case TARGET_NR_msgget:
5490 ret = get_errno(msgget(arg1, arg2));
5491 break;
5492#endif
5493#ifdef TARGET_NR_msgrcv
5494 case TARGET_NR_msgrcv:
5495 ret = do_msgrcv(arg1, arg2, arg3, arg4, arg5);
5496 break;
5497#endif
5498#ifdef TARGET_NR_msgsnd
5499 case TARGET_NR_msgsnd:
5500 ret = do_msgsnd(arg1, arg2, arg3, arg4);
5501 break;
5502#endif
Riku Voipio88a8c982009-04-03 10:42:00 +03005503#ifdef TARGET_NR_shmget
5504 case TARGET_NR_shmget:
5505 ret = get_errno(shmget(arg1, arg2, arg3));
5506 break;
5507#endif
5508#ifdef TARGET_NR_shmctl
5509 case TARGET_NR_shmctl:
5510 ret = do_shmctl(arg1, arg2, arg3);
5511 break;
5512#endif
5513#ifdef TARGET_NR_shmat
5514 case TARGET_NR_shmat:
5515 ret = do_shmat(arg1, arg2, arg3);
5516 break;
5517#endif
5518#ifdef TARGET_NR_shmdt
5519 case TARGET_NR_shmdt:
5520 ret = do_shmdt(arg1);
5521 break;
5522#endif
bellard31e31b82003-02-18 22:55:36 +00005523 case TARGET_NR_fsync:
5524 ret = get_errno(fsync(arg1));
5525 break;
bellard31e31b82003-02-18 22:55:36 +00005526 case TARGET_NR_clone:
aurel320b6d3ae2008-09-15 07:43:43 +00005527#if defined(TARGET_SH4)
5528 ret = get_errno(do_fork(cpu_env, arg1, arg2, arg3, arg5, arg4));
edgar_iglb15ad612009-01-07 19:43:47 +00005529#elif defined(TARGET_CRIS)
5530 ret = get_errno(do_fork(cpu_env, arg2, arg1, arg3, arg4, arg5));
aurel320b6d3ae2008-09-15 07:43:43 +00005531#else
pbrookd865bab2008-06-07 22:12:17 +00005532 ret = get_errno(do_fork(cpu_env, arg1, arg2, arg3, arg4, arg5));
aurel320b6d3ae2008-09-15 07:43:43 +00005533#endif
bellard1b6b0292003-03-22 17:31:38 +00005534 break;
bellardec86b0f2003-04-11 00:15:04 +00005535#ifdef __NR_exit_group
5536 /* new thread calls */
5537 case TARGET_NR_exit_group:
aurel326d946cd2008-11-06 16:15:18 +00005538#ifdef HAVE_GPROF
5539 _mcleanup();
5540#endif
bellarde9009672005-04-26 20:42:36 +00005541 gdb_exit(cpu_env, arg1);
bellardec86b0f2003-04-11 00:15:04 +00005542 ret = get_errno(exit_group(arg1));
5543 break;
5544#endif
bellard31e31b82003-02-18 22:55:36 +00005545 case TARGET_NR_setdomainname:
bellard579a97f2007-11-11 14:26:47 +00005546 if (!(p = lock_user_string(arg1)))
5547 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005548 ret = get_errno(setdomainname(p, arg2));
5549 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00005550 break;
5551 case TARGET_NR_uname:
5552 /* no need to transcode because we use the linux syscall */
bellard29e619b2004-09-13 21:41:04 +00005553 {
5554 struct new_utsname * buf;
ths3b46e622007-09-17 08:09:54 +00005555
bellard579a97f2007-11-11 14:26:47 +00005556 if (!lock_user_struct(VERIFY_WRITE, buf, arg1, 0))
5557 goto efault;
bellard29e619b2004-09-13 21:41:04 +00005558 ret = get_errno(sys_uname(buf));
5559 if (!is_error(ret)) {
5560 /* Overrite the native machine name with whatever is being
5561 emulated. */
5562 strcpy (buf->machine, UNAME_MACHINE);
pbrookc5937222006-05-14 11:30:38 +00005563 /* Allow the user to override the reported release. */
5564 if (qemu_uname_release && *qemu_uname_release)
5565 strcpy (buf->release, qemu_uname_release);
bellard29e619b2004-09-13 21:41:04 +00005566 }
pbrook53a59602006-03-25 19:31:22 +00005567 unlock_user_struct(buf, arg1, 1);
bellard29e619b2004-09-13 21:41:04 +00005568 }
bellard31e31b82003-02-18 22:55:36 +00005569 break;
bellard6dbad632003-03-16 18:05:05 +00005570#ifdef TARGET_I386
bellard31e31b82003-02-18 22:55:36 +00005571 case TARGET_NR_modify_ldt:
bellard03acab62007-11-11 14:57:14 +00005572 ret = do_modify_ldt(cpu_env, arg1, arg2, arg3);
bellard5cd43932003-03-29 16:54:36 +00005573 break;
j_mayer84409dd2007-04-06 08:56:50 +00005574#if !defined(TARGET_X86_64)
bellard5cd43932003-03-29 16:54:36 +00005575 case TARGET_NR_vm86old:
5576 goto unimplemented;
5577 case TARGET_NR_vm86:
pbrook53a59602006-03-25 19:31:22 +00005578 ret = do_vm86(cpu_env, arg1, arg2);
bellard6dbad632003-03-16 18:05:05 +00005579 break;
5580#endif
j_mayer84409dd2007-04-06 08:56:50 +00005581#endif
bellard31e31b82003-02-18 22:55:36 +00005582 case TARGET_NR_adjtimex:
5583 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00005584#ifdef TARGET_NR_create_module
bellard31e31b82003-02-18 22:55:36 +00005585 case TARGET_NR_create_module:
thse5febef2007-04-01 18:31:35 +00005586#endif
bellard31e31b82003-02-18 22:55:36 +00005587 case TARGET_NR_init_module:
5588 case TARGET_NR_delete_module:
thse5febef2007-04-01 18:31:35 +00005589#ifdef TARGET_NR_get_kernel_syms
bellard31e31b82003-02-18 22:55:36 +00005590 case TARGET_NR_get_kernel_syms:
thse5febef2007-04-01 18:31:35 +00005591#endif
bellard31e31b82003-02-18 22:55:36 +00005592 goto unimplemented;
5593 case TARGET_NR_quotactl:
5594 goto unimplemented;
5595 case TARGET_NR_getpgid:
5596 ret = get_errno(getpgid(arg1));
5597 break;
5598 case TARGET_NR_fchdir:
5599 ret = get_errno(fchdir(arg1));
5600 break;
j_mayer84409dd2007-04-06 08:56:50 +00005601#ifdef TARGET_NR_bdflush /* not on x86_64 */
bellard31e31b82003-02-18 22:55:36 +00005602 case TARGET_NR_bdflush:
5603 goto unimplemented;
j_mayer84409dd2007-04-06 08:56:50 +00005604#endif
thse5febef2007-04-01 18:31:35 +00005605#ifdef TARGET_NR_sysfs
bellard31e31b82003-02-18 22:55:36 +00005606 case TARGET_NR_sysfs:
5607 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00005608#endif
bellard31e31b82003-02-18 22:55:36 +00005609 case TARGET_NR_personality:
bellard1b6b0292003-03-22 17:31:38 +00005610 ret = get_errno(personality(arg1));
bellard31e31b82003-02-18 22:55:36 +00005611 break;
thse5febef2007-04-01 18:31:35 +00005612#ifdef TARGET_NR_afs_syscall
bellard31e31b82003-02-18 22:55:36 +00005613 case TARGET_NR_afs_syscall:
5614 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00005615#endif
j_mayer7a3148a2007-04-05 07:13:51 +00005616#ifdef TARGET_NR__llseek /* Not on alpha */
bellard31e31b82003-02-18 22:55:36 +00005617 case TARGET_NR__llseek:
5618 {
bellard4f2ac232004-04-26 19:44:02 +00005619#if defined (__x86_64__)
5620 ret = get_errno(lseek(arg1, ((uint64_t )arg2 << 32) | arg3, arg5));
bellard2f619692007-11-16 10:46:05 +00005621 if (put_user_s64(ret, arg4))
5622 goto efault;
bellard4f2ac232004-04-26 19:44:02 +00005623#else
bellard31e31b82003-02-18 22:55:36 +00005624 int64_t res;
5625 ret = get_errno(_llseek(arg1, arg2, arg3, &res, arg5));
bellard2f619692007-11-16 10:46:05 +00005626 if (put_user_s64(res, arg4))
5627 goto efault;
bellard4f2ac232004-04-26 19:44:02 +00005628#endif
bellard31e31b82003-02-18 22:55:36 +00005629 }
5630 break;
j_mayer7a3148a2007-04-05 07:13:51 +00005631#endif
bellard31e31b82003-02-18 22:55:36 +00005632 case TARGET_NR_getdents:
blueswir1992f48a2007-10-14 16:27:31 +00005633#if TARGET_ABI_BITS != 32
pbrook53a59602006-03-25 19:31:22 +00005634 goto unimplemented;
blueswir1992f48a2007-10-14 16:27:31 +00005635#elif TARGET_ABI_BITS == 32 && HOST_LONG_BITS == 64
bellard4add45b2003-06-05 01:52:59 +00005636 {
pbrook53a59602006-03-25 19:31:22 +00005637 struct target_dirent *target_dirp;
aurel326556a832008-10-13 21:08:17 +00005638 struct linux_dirent *dirp;
blueswir1992f48a2007-10-14 16:27:31 +00005639 abi_long count = arg3;
bellard4add45b2003-06-05 01:52:59 +00005640
5641 dirp = malloc(count);
ths0da46a62007-10-20 20:23:07 +00005642 if (!dirp) {
bellard579a97f2007-11-11 14:26:47 +00005643 ret = -TARGET_ENOMEM;
ths0da46a62007-10-20 20:23:07 +00005644 goto fail;
5645 }
ths3b46e622007-09-17 08:09:54 +00005646
bellard4add45b2003-06-05 01:52:59 +00005647 ret = get_errno(sys_getdents(arg1, dirp, count));
5648 if (!is_error(ret)) {
aurel326556a832008-10-13 21:08:17 +00005649 struct linux_dirent *de;
bellard4add45b2003-06-05 01:52:59 +00005650 struct target_dirent *tde;
5651 int len = ret;
5652 int reclen, treclen;
5653 int count1, tnamelen;
5654
5655 count1 = 0;
5656 de = dirp;
bellard579a97f2007-11-11 14:26:47 +00005657 if (!(target_dirp = lock_user(VERIFY_WRITE, arg2, count, 0)))
5658 goto efault;
bellard4add45b2003-06-05 01:52:59 +00005659 tde = target_dirp;
5660 while (len > 0) {
5661 reclen = de->d_reclen;
blueswir1992f48a2007-10-14 16:27:31 +00005662 treclen = reclen - (2 * (sizeof(long) - sizeof(abi_long)));
bellard4add45b2003-06-05 01:52:59 +00005663 tde->d_reclen = tswap16(treclen);
5664 tde->d_ino = tswapl(de->d_ino);
5665 tde->d_off = tswapl(de->d_off);
blueswir1992f48a2007-10-14 16:27:31 +00005666 tnamelen = treclen - (2 * sizeof(abi_long) + 2);
bellard4add45b2003-06-05 01:52:59 +00005667 if (tnamelen > 256)
5668 tnamelen = 256;
bellard80a9d032005-01-03 23:31:27 +00005669 /* XXX: may not be correct */
blueswir1be15b142008-10-25 11:21:28 +00005670 pstrcpy(tde->d_name, tnamelen, de->d_name);
aurel326556a832008-10-13 21:08:17 +00005671 de = (struct linux_dirent *)((char *)de + reclen);
bellard4add45b2003-06-05 01:52:59 +00005672 len -= reclen;
j_mayer1c5bf3b2007-04-14 12:17:59 +00005673 tde = (struct target_dirent *)((char *)tde + treclen);
bellard4add45b2003-06-05 01:52:59 +00005674 count1 += treclen;
5675 }
5676 ret = count1;
bellard579a97f2007-11-11 14:26:47 +00005677 unlock_user(target_dirp, arg2, ret);
bellard4add45b2003-06-05 01:52:59 +00005678 }
5679 free(dirp);
5680 }
5681#else
bellard31e31b82003-02-18 22:55:36 +00005682 {
aurel326556a832008-10-13 21:08:17 +00005683 struct linux_dirent *dirp;
blueswir1992f48a2007-10-14 16:27:31 +00005684 abi_long count = arg3;
bellarddab2ed92003-03-22 15:23:14 +00005685
bellard579a97f2007-11-11 14:26:47 +00005686 if (!(dirp = lock_user(VERIFY_WRITE, arg2, count, 0)))
5687 goto efault;
bellard72f03902003-02-18 23:33:18 +00005688 ret = get_errno(sys_getdents(arg1, dirp, count));
bellard31e31b82003-02-18 22:55:36 +00005689 if (!is_error(ret)) {
aurel326556a832008-10-13 21:08:17 +00005690 struct linux_dirent *de;
bellard31e31b82003-02-18 22:55:36 +00005691 int len = ret;
5692 int reclen;
5693 de = dirp;
5694 while (len > 0) {
bellard8083a3e2003-03-24 23:12:16 +00005695 reclen = de->d_reclen;
bellard31e31b82003-02-18 22:55:36 +00005696 if (reclen > len)
5697 break;
bellard8083a3e2003-03-24 23:12:16 +00005698 de->d_reclen = tswap16(reclen);
bellard31e31b82003-02-18 22:55:36 +00005699 tswapls(&de->d_ino);
5700 tswapls(&de->d_off);
aurel326556a832008-10-13 21:08:17 +00005701 de = (struct linux_dirent *)((char *)de + reclen);
bellard31e31b82003-02-18 22:55:36 +00005702 len -= reclen;
5703 }
5704 }
pbrook53a59602006-03-25 19:31:22 +00005705 unlock_user(dirp, arg2, ret);
bellard31e31b82003-02-18 22:55:36 +00005706 }
bellard4add45b2003-06-05 01:52:59 +00005707#endif
bellard31e31b82003-02-18 22:55:36 +00005708 break;
ths3ae43202007-09-16 21:39:48 +00005709#if defined(TARGET_NR_getdents64) && defined(__NR_getdents64)
bellarddab2ed92003-03-22 15:23:14 +00005710 case TARGET_NR_getdents64:
5711 {
aurel326556a832008-10-13 21:08:17 +00005712 struct linux_dirent64 *dirp;
blueswir1992f48a2007-10-14 16:27:31 +00005713 abi_long count = arg3;
bellard579a97f2007-11-11 14:26:47 +00005714 if (!(dirp = lock_user(VERIFY_WRITE, arg2, count, 0)))
5715 goto efault;
bellarddab2ed92003-03-22 15:23:14 +00005716 ret = get_errno(sys_getdents64(arg1, dirp, count));
5717 if (!is_error(ret)) {
aurel326556a832008-10-13 21:08:17 +00005718 struct linux_dirent64 *de;
bellarddab2ed92003-03-22 15:23:14 +00005719 int len = ret;
5720 int reclen;
5721 de = dirp;
5722 while (len > 0) {
bellard8083a3e2003-03-24 23:12:16 +00005723 reclen = de->d_reclen;
bellarddab2ed92003-03-22 15:23:14 +00005724 if (reclen > len)
5725 break;
bellard8083a3e2003-03-24 23:12:16 +00005726 de->d_reclen = tswap16(reclen);
bellard8582a532007-11-11 23:11:36 +00005727 tswap64s((uint64_t *)&de->d_ino);
5728 tswap64s((uint64_t *)&de->d_off);
aurel326556a832008-10-13 21:08:17 +00005729 de = (struct linux_dirent64 *)((char *)de + reclen);
bellarddab2ed92003-03-22 15:23:14 +00005730 len -= reclen;
5731 }
5732 }
pbrook53a59602006-03-25 19:31:22 +00005733 unlock_user(dirp, arg2, ret);
bellarddab2ed92003-03-22 15:23:14 +00005734 }
5735 break;
bellarda541f292004-04-12 20:39:29 +00005736#endif /* TARGET_NR_getdents64 */
thse5febef2007-04-01 18:31:35 +00005737#ifdef TARGET_NR__newselect
bellard31e31b82003-02-18 22:55:36 +00005738 case TARGET_NR__newselect:
pbrook53a59602006-03-25 19:31:22 +00005739 ret = do_select(arg1, arg2, arg3, arg4, arg5);
bellard31e31b82003-02-18 22:55:36 +00005740 break;
thse5febef2007-04-01 18:31:35 +00005741#endif
5742#ifdef TARGET_NR_poll
bellard9de5e442003-03-23 16:49:39 +00005743 case TARGET_NR_poll:
5744 {
pbrook53a59602006-03-25 19:31:22 +00005745 struct target_pollfd *target_pfd;
bellard9de5e442003-03-23 16:49:39 +00005746 unsigned int nfds = arg2;
5747 int timeout = arg3;
5748 struct pollfd *pfd;
bellard7854b052003-03-29 17:22:23 +00005749 unsigned int i;
bellard9de5e442003-03-23 16:49:39 +00005750
bellard579a97f2007-11-11 14:26:47 +00005751 target_pfd = lock_user(VERIFY_WRITE, arg1, sizeof(struct target_pollfd) * nfds, 1);
5752 if (!target_pfd)
5753 goto efault;
bellard9de5e442003-03-23 16:49:39 +00005754 pfd = alloca(sizeof(struct pollfd) * nfds);
5755 for(i = 0; i < nfds; i++) {
bellard5cd43932003-03-29 16:54:36 +00005756 pfd[i].fd = tswap32(target_pfd[i].fd);
5757 pfd[i].events = tswap16(target_pfd[i].events);
bellard9de5e442003-03-23 16:49:39 +00005758 }
5759 ret = get_errno(poll(pfd, nfds, timeout));
5760 if (!is_error(ret)) {
5761 for(i = 0; i < nfds; i++) {
bellard5cd43932003-03-29 16:54:36 +00005762 target_pfd[i].revents = tswap16(pfd[i].revents);
bellard9de5e442003-03-23 16:49:39 +00005763 }
pbrook53a59602006-03-25 19:31:22 +00005764 ret += nfds * (sizeof(struct target_pollfd)
5765 - sizeof(struct pollfd));
bellard9de5e442003-03-23 16:49:39 +00005766 }
pbrook53a59602006-03-25 19:31:22 +00005767 unlock_user(target_pfd, arg1, ret);
bellard9de5e442003-03-23 16:49:39 +00005768 }
5769 break;
thse5febef2007-04-01 18:31:35 +00005770#endif
bellard31e31b82003-02-18 22:55:36 +00005771 case TARGET_NR_flock:
bellard9de5e442003-03-23 16:49:39 +00005772 /* NOTE: the flock constant seems to be the same for every
5773 Linux platform */
5774 ret = get_errno(flock(arg1, arg2));
bellard31e31b82003-02-18 22:55:36 +00005775 break;
5776 case TARGET_NR_readv:
5777 {
5778 int count = arg3;
bellard31e31b82003-02-18 22:55:36 +00005779 struct iovec *vec;
bellard31e31b82003-02-18 22:55:36 +00005780
5781 vec = alloca(count * sizeof(struct iovec));
bellard41df8412008-02-04 22:26:57 +00005782 if (lock_iovec(VERIFY_WRITE, vec, arg2, count, 0) < 0)
5783 goto efault;
bellard31e31b82003-02-18 22:55:36 +00005784 ret = get_errno(readv(arg1, vec, count));
pbrook53a59602006-03-25 19:31:22 +00005785 unlock_iovec(vec, arg2, count, 1);
bellard31e31b82003-02-18 22:55:36 +00005786 }
5787 break;
5788 case TARGET_NR_writev:
5789 {
5790 int count = arg3;
bellard31e31b82003-02-18 22:55:36 +00005791 struct iovec *vec;
bellard31e31b82003-02-18 22:55:36 +00005792
5793 vec = alloca(count * sizeof(struct iovec));
bellard41df8412008-02-04 22:26:57 +00005794 if (lock_iovec(VERIFY_READ, vec, arg2, count, 1) < 0)
5795 goto efault;
bellard31e31b82003-02-18 22:55:36 +00005796 ret = get_errno(writev(arg1, vec, count));
pbrook53a59602006-03-25 19:31:22 +00005797 unlock_iovec(vec, arg2, count, 0);
bellard31e31b82003-02-18 22:55:36 +00005798 }
5799 break;
5800 case TARGET_NR_getsid:
5801 ret = get_errno(getsid(arg1));
5802 break;
j_mayer7a3148a2007-04-05 07:13:51 +00005803#if defined(TARGET_NR_fdatasync) /* Not on alpha (osf_datasync ?) */
bellard31e31b82003-02-18 22:55:36 +00005804 case TARGET_NR_fdatasync:
bellard5cd43932003-03-29 16:54:36 +00005805 ret = get_errno(fdatasync(arg1));
5806 break;
j_mayer7a3148a2007-04-05 07:13:51 +00005807#endif
bellard31e31b82003-02-18 22:55:36 +00005808 case TARGET_NR__sysctl:
ths0da46a62007-10-20 20:23:07 +00005809 /* We don't implement this, but ENOTDIR is always a safe
bellard29e619b2004-09-13 21:41:04 +00005810 return value. */
ths0da46a62007-10-20 20:23:07 +00005811 ret = -TARGET_ENOTDIR;
5812 break;
bellard31e31b82003-02-18 22:55:36 +00005813 case TARGET_NR_sched_setparam:
bellard5cd43932003-03-29 16:54:36 +00005814 {
pbrook53a59602006-03-25 19:31:22 +00005815 struct sched_param *target_schp;
bellard5cd43932003-03-29 16:54:36 +00005816 struct sched_param schp;
pbrook53a59602006-03-25 19:31:22 +00005817
bellard579a97f2007-11-11 14:26:47 +00005818 if (!lock_user_struct(VERIFY_READ, target_schp, arg2, 1))
5819 goto efault;
bellard5cd43932003-03-29 16:54:36 +00005820 schp.sched_priority = tswap32(target_schp->sched_priority);
pbrook53a59602006-03-25 19:31:22 +00005821 unlock_user_struct(target_schp, arg2, 0);
bellard5cd43932003-03-29 16:54:36 +00005822 ret = get_errno(sched_setparam(arg1, &schp));
5823 }
5824 break;
bellard31e31b82003-02-18 22:55:36 +00005825 case TARGET_NR_sched_getparam:
bellard5cd43932003-03-29 16:54:36 +00005826 {
pbrook53a59602006-03-25 19:31:22 +00005827 struct sched_param *target_schp;
bellard5cd43932003-03-29 16:54:36 +00005828 struct sched_param schp;
5829 ret = get_errno(sched_getparam(arg1, &schp));
5830 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00005831 if (!lock_user_struct(VERIFY_WRITE, target_schp, arg2, 0))
5832 goto efault;
bellard5cd43932003-03-29 16:54:36 +00005833 target_schp->sched_priority = tswap32(schp.sched_priority);
pbrook53a59602006-03-25 19:31:22 +00005834 unlock_user_struct(target_schp, arg2, 1);
bellard5cd43932003-03-29 16:54:36 +00005835 }
5836 }
5837 break;
bellard31e31b82003-02-18 22:55:36 +00005838 case TARGET_NR_sched_setscheduler:
bellard5cd43932003-03-29 16:54:36 +00005839 {
pbrook53a59602006-03-25 19:31:22 +00005840 struct sched_param *target_schp;
bellard5cd43932003-03-29 16:54:36 +00005841 struct sched_param schp;
bellard579a97f2007-11-11 14:26:47 +00005842 if (!lock_user_struct(VERIFY_READ, target_schp, arg3, 1))
5843 goto efault;
bellard5cd43932003-03-29 16:54:36 +00005844 schp.sched_priority = tswap32(target_schp->sched_priority);
pbrook53a59602006-03-25 19:31:22 +00005845 unlock_user_struct(target_schp, arg3, 0);
bellard5cd43932003-03-29 16:54:36 +00005846 ret = get_errno(sched_setscheduler(arg1, arg2, &schp));
5847 }
5848 break;
bellard31e31b82003-02-18 22:55:36 +00005849 case TARGET_NR_sched_getscheduler:
bellard5cd43932003-03-29 16:54:36 +00005850 ret = get_errno(sched_getscheduler(arg1));
5851 break;
bellard31e31b82003-02-18 22:55:36 +00005852 case TARGET_NR_sched_yield:
5853 ret = get_errno(sched_yield());
5854 break;
5855 case TARGET_NR_sched_get_priority_max:
bellard5cd43932003-03-29 16:54:36 +00005856 ret = get_errno(sched_get_priority_max(arg1));
5857 break;
bellard31e31b82003-02-18 22:55:36 +00005858 case TARGET_NR_sched_get_priority_min:
bellard5cd43932003-03-29 16:54:36 +00005859 ret = get_errno(sched_get_priority_min(arg1));
5860 break;
bellard31e31b82003-02-18 22:55:36 +00005861 case TARGET_NR_sched_rr_get_interval:
bellard5cd43932003-03-29 16:54:36 +00005862 {
bellard5cd43932003-03-29 16:54:36 +00005863 struct timespec ts;
5864 ret = get_errno(sched_rr_get_interval(arg1, &ts));
5865 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00005866 host_to_target_timespec(arg2, &ts);
bellard5cd43932003-03-29 16:54:36 +00005867 }
5868 }
5869 break;
bellard31e31b82003-02-18 22:55:36 +00005870 case TARGET_NR_nanosleep:
bellard1b6b0292003-03-22 17:31:38 +00005871 {
bellard1b6b0292003-03-22 17:31:38 +00005872 struct timespec req, rem;
pbrook53a59602006-03-25 19:31:22 +00005873 target_to_host_timespec(&req, arg1);
bellard1b6b0292003-03-22 17:31:38 +00005874 ret = get_errno(nanosleep(&req, &rem));
pbrook53a59602006-03-25 19:31:22 +00005875 if (is_error(ret) && arg2) {
5876 host_to_target_timespec(arg2, &rem);
bellard1b6b0292003-03-22 17:31:38 +00005877 }
5878 }
5879 break;
thse5febef2007-04-01 18:31:35 +00005880#ifdef TARGET_NR_query_module
bellard31e31b82003-02-18 22:55:36 +00005881 case TARGET_NR_query_module:
bellard5cd43932003-03-29 16:54:36 +00005882 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00005883#endif
5884#ifdef TARGET_NR_nfsservctl
bellard31e31b82003-02-18 22:55:36 +00005885 case TARGET_NR_nfsservctl:
bellard5cd43932003-03-29 16:54:36 +00005886 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00005887#endif
bellard31e31b82003-02-18 22:55:36 +00005888 case TARGET_NR_prctl:
thse5574482007-02-11 20:03:13 +00005889 switch (arg1)
5890 {
5891 case PR_GET_PDEATHSIG:
5892 {
5893 int deathsig;
5894 ret = get_errno(prctl(arg1, &deathsig, arg3, arg4, arg5));
bellard2f619692007-11-16 10:46:05 +00005895 if (!is_error(ret) && arg2
5896 && put_user_ual(deathsig, arg2))
5897 goto efault;
thse5574482007-02-11 20:03:13 +00005898 }
5899 break;
5900 default:
5901 ret = get_errno(prctl(arg1, arg2, arg3, arg4, arg5));
5902 break;
5903 }
ths39b9aae2007-02-11 18:36:44 +00005904 break;
bellardd2fd1af2007-11-14 18:08:56 +00005905#ifdef TARGET_NR_arch_prctl
5906 case TARGET_NR_arch_prctl:
5907#if defined(TARGET_I386) && !defined(TARGET_ABI32)
5908 ret = do_arch_prctl(cpu_env, arg1, arg2);
5909 break;
5910#else
5911 goto unimplemented;
5912#endif
5913#endif
bellard67867302003-11-23 17:05:30 +00005914#ifdef TARGET_NR_pread
bellard31e31b82003-02-18 22:55:36 +00005915 case TARGET_NR_pread:
balroga4ae00b2008-09-20 03:14:14 +00005916#ifdef TARGET_ARM
5917 if (((CPUARMState *)cpu_env)->eabi)
5918 arg4 = arg5;
5919#endif
bellard579a97f2007-11-11 14:26:47 +00005920 if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
5921 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005922 ret = get_errno(pread(arg1, p, arg3, arg4));
5923 unlock_user(p, arg2, ret);
bellard206f0fa2003-05-14 19:01:56 +00005924 break;
bellard31e31b82003-02-18 22:55:36 +00005925 case TARGET_NR_pwrite:
balroga4ae00b2008-09-20 03:14:14 +00005926#ifdef TARGET_ARM
5927 if (((CPUARMState *)cpu_env)->eabi)
5928 arg4 = arg5;
5929#endif
bellard579a97f2007-11-11 14:26:47 +00005930 if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
5931 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005932 ret = get_errno(pwrite(arg1, p, arg3, arg4));
5933 unlock_user(p, arg2, 0);
bellard206f0fa2003-05-14 19:01:56 +00005934 break;
bellard67867302003-11-23 17:05:30 +00005935#endif
aurel32f2c7ba12008-03-28 22:32:06 +00005936#ifdef TARGET_NR_pread64
5937 case TARGET_NR_pread64:
5938 if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
5939 goto efault;
5940 ret = get_errno(pread64(arg1, p, arg3, target_offset64(arg4, arg5)));
5941 unlock_user(p, arg2, ret);
5942 break;
5943 case TARGET_NR_pwrite64:
5944 if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
5945 goto efault;
5946 ret = get_errno(pwrite64(arg1, p, arg3, target_offset64(arg4, arg5)));
5947 unlock_user(p, arg2, 0);
5948 break;
5949#endif
bellard31e31b82003-02-18 22:55:36 +00005950 case TARGET_NR_getcwd:
bellard579a97f2007-11-11 14:26:47 +00005951 if (!(p = lock_user(VERIFY_WRITE, arg1, arg2, 0)))
5952 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005953 ret = get_errno(sys_getcwd1(p, arg2));
5954 unlock_user(p, arg1, ret);
bellard31e31b82003-02-18 22:55:36 +00005955 break;
5956 case TARGET_NR_capget:
bellard5cd43932003-03-29 16:54:36 +00005957 goto unimplemented;
bellard31e31b82003-02-18 22:55:36 +00005958 case TARGET_NR_capset:
bellard5cd43932003-03-29 16:54:36 +00005959 goto unimplemented;
bellard31e31b82003-02-18 22:55:36 +00005960 case TARGET_NR_sigaltstack:
ths198a74d2007-09-27 16:44:32 +00005961#if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_MIPS) || \
5962 defined(TARGET_SPARC) || defined(TARGET_PPC) || defined(TARGET_ALPHA)
bellard579a97f2007-11-11 14:26:47 +00005963 ret = do_sigaltstack(arg1, arg2, get_sp_from_cpustate((CPUState *)cpu_env));
thsa04e1342007-09-27 13:57:58 +00005964 break;
5965#else
bellard5cd43932003-03-29 16:54:36 +00005966 goto unimplemented;
thsa04e1342007-09-27 13:57:58 +00005967#endif
bellard31e31b82003-02-18 22:55:36 +00005968 case TARGET_NR_sendfile:
bellard5cd43932003-03-29 16:54:36 +00005969 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00005970#ifdef TARGET_NR_getpmsg
bellard31e31b82003-02-18 22:55:36 +00005971 case TARGET_NR_getpmsg:
bellard5cd43932003-03-29 16:54:36 +00005972 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00005973#endif
5974#ifdef TARGET_NR_putpmsg
bellard31e31b82003-02-18 22:55:36 +00005975 case TARGET_NR_putpmsg:
bellard5cd43932003-03-29 16:54:36 +00005976 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00005977#endif
bellard048f6b42005-11-26 18:47:20 +00005978#ifdef TARGET_NR_vfork
bellard31e31b82003-02-18 22:55:36 +00005979 case TARGET_NR_vfork:
pbrookd865bab2008-06-07 22:12:17 +00005980 ret = get_errno(do_fork(cpu_env, CLONE_VFORK | CLONE_VM | SIGCHLD,
5981 0, 0, 0, 0));
bellard31e31b82003-02-18 22:55:36 +00005982 break;
bellard048f6b42005-11-26 18:47:20 +00005983#endif
bellardebc05482003-09-30 21:08:41 +00005984#ifdef TARGET_NR_ugetrlimit
bellard31e31b82003-02-18 22:55:36 +00005985 case TARGET_NR_ugetrlimit:
bellard728584b2003-04-29 20:43:36 +00005986 {
5987 struct rlimit rlim;
5988 ret = get_errno(getrlimit(arg1, &rlim));
5989 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00005990 struct target_rlimit *target_rlim;
bellard579a97f2007-11-11 14:26:47 +00005991 if (!lock_user_struct(VERIFY_WRITE, target_rlim, arg2, 0))
5992 goto efault;
bellard728584b2003-04-29 20:43:36 +00005993 target_rlim->rlim_cur = tswapl(rlim.rlim_cur);
5994 target_rlim->rlim_max = tswapl(rlim.rlim_max);
pbrook53a59602006-03-25 19:31:22 +00005995 unlock_user_struct(target_rlim, arg2, 1);
bellard728584b2003-04-29 20:43:36 +00005996 }
5997 break;
5998 }
bellardebc05482003-09-30 21:08:41 +00005999#endif
bellarda315a142005-01-30 22:59:18 +00006000#ifdef TARGET_NR_truncate64
bellard31e31b82003-02-18 22:55:36 +00006001 case TARGET_NR_truncate64:
bellard579a97f2007-11-11 14:26:47 +00006002 if (!(p = lock_user_string(arg1)))
6003 goto efault;
pbrook53a59602006-03-25 19:31:22 +00006004 ret = target_truncate64(cpu_env, p, arg2, arg3, arg4);
6005 unlock_user(p, arg1, 0);
bellard667f38b2005-07-23 14:46:27 +00006006 break;
bellarda315a142005-01-30 22:59:18 +00006007#endif
6008#ifdef TARGET_NR_ftruncate64
bellard31e31b82003-02-18 22:55:36 +00006009 case TARGET_NR_ftruncate64:
pbrookce4defa2006-02-09 16:49:55 +00006010 ret = target_ftruncate64(cpu_env, arg1, arg2, arg3, arg4);
bellard667f38b2005-07-23 14:46:27 +00006011 break;
bellarda315a142005-01-30 22:59:18 +00006012#endif
6013#ifdef TARGET_NR_stat64
bellard31e31b82003-02-18 22:55:36 +00006014 case TARGET_NR_stat64:
bellard579a97f2007-11-11 14:26:47 +00006015 if (!(p = lock_user_string(arg1)))
6016 goto efault;
pbrook53a59602006-03-25 19:31:22 +00006017 ret = get_errno(stat(path(p), &st));
6018 unlock_user(p, arg1, 0);
balrog6a24a772008-09-20 02:23:36 +00006019 if (!is_error(ret))
6020 ret = host_to_target_stat64(cpu_env, arg2, &st);
6021 break;
bellarda315a142005-01-30 22:59:18 +00006022#endif
6023#ifdef TARGET_NR_lstat64
bellard31e31b82003-02-18 22:55:36 +00006024 case TARGET_NR_lstat64:
bellard579a97f2007-11-11 14:26:47 +00006025 if (!(p = lock_user_string(arg1)))
6026 goto efault;
pbrook53a59602006-03-25 19:31:22 +00006027 ret = get_errno(lstat(path(p), &st));
6028 unlock_user(p, arg1, 0);
balrog6a24a772008-09-20 02:23:36 +00006029 if (!is_error(ret))
6030 ret = host_to_target_stat64(cpu_env, arg2, &st);
6031 break;
bellarda315a142005-01-30 22:59:18 +00006032#endif
6033#ifdef TARGET_NR_fstat64
bellard31e31b82003-02-18 22:55:36 +00006034 case TARGET_NR_fstat64:
balrog6a24a772008-09-20 02:23:36 +00006035 ret = get_errno(fstat(arg1, &st));
6036 if (!is_error(ret))
6037 ret = host_to_target_stat64(cpu_env, arg2, &st);
6038 break;
bellardec86b0f2003-04-11 00:15:04 +00006039#endif
aurel329d33b762009-04-08 23:07:05 +00006040#if (defined(TARGET_NR_fstatat64) || defined(TARGET_NR_newfstatat)) && \
6041 (defined(__NR_fstatat64) || defined(__NR_newfstatat))
6042#ifdef TARGET_NR_fstatat64
balrog6a24a772008-09-20 02:23:36 +00006043 case TARGET_NR_fstatat64:
aurel329d33b762009-04-08 23:07:05 +00006044#endif
6045#ifdef TARGET_NR_newfstatat
6046 case TARGET_NR_newfstatat:
6047#endif
balrog6a24a772008-09-20 02:23:36 +00006048 if (!(p = lock_user_string(arg2)))
6049 goto efault;
aurel329d33b762009-04-08 23:07:05 +00006050#ifdef __NR_fstatat64
balrog6a24a772008-09-20 02:23:36 +00006051 ret = get_errno(sys_fstatat64(arg1, path(p), &st, arg4));
aurel329d33b762009-04-08 23:07:05 +00006052#else
6053 ret = get_errno(sys_newfstatat(arg1, path(p), &st, arg4));
6054#endif
balrog6a24a772008-09-20 02:23:36 +00006055 if (!is_error(ret))
6056 ret = host_to_target_stat64(cpu_env, arg3, &st);
bellard60cd49d2003-03-16 22:53:56 +00006057 break;
bellarda315a142005-01-30 22:59:18 +00006058#endif
bellard67867302003-11-23 17:05:30 +00006059#ifdef USE_UID16
6060 case TARGET_NR_lchown:
bellard579a97f2007-11-11 14:26:47 +00006061 if (!(p = lock_user_string(arg1)))
6062 goto efault;
pbrook53a59602006-03-25 19:31:22 +00006063 ret = get_errno(lchown(p, low2highuid(arg2), low2highgid(arg3)));
6064 unlock_user(p, arg1, 0);
bellard67867302003-11-23 17:05:30 +00006065 break;
6066 case TARGET_NR_getuid:
6067 ret = get_errno(high2lowuid(getuid()));
6068 break;
6069 case TARGET_NR_getgid:
6070 ret = get_errno(high2lowgid(getgid()));
6071 break;
6072 case TARGET_NR_geteuid:
6073 ret = get_errno(high2lowuid(geteuid()));
6074 break;
6075 case TARGET_NR_getegid:
6076 ret = get_errno(high2lowgid(getegid()));
6077 break;
6078 case TARGET_NR_setreuid:
6079 ret = get_errno(setreuid(low2highuid(arg1), low2highuid(arg2)));
6080 break;
6081 case TARGET_NR_setregid:
6082 ret = get_errno(setregid(low2highgid(arg1), low2highgid(arg2)));
6083 break;
6084 case TARGET_NR_getgroups:
6085 {
6086 int gidsetsize = arg1;
pbrook53a59602006-03-25 19:31:22 +00006087 uint16_t *target_grouplist;
bellard67867302003-11-23 17:05:30 +00006088 gid_t *grouplist;
6089 int i;
6090
6091 grouplist = alloca(gidsetsize * sizeof(gid_t));
6092 ret = get_errno(getgroups(gidsetsize, grouplist));
balrogcb3bc232008-09-20 02:08:13 +00006093 if (gidsetsize == 0)
6094 break;
bellard67867302003-11-23 17:05:30 +00006095 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00006096 target_grouplist = lock_user(VERIFY_WRITE, arg2, gidsetsize * 2, 0);
6097 if (!target_grouplist)
6098 goto efault;
balroga2155fc2008-09-20 02:12:08 +00006099 for(i = 0;i < ret; i++)
bellard67867302003-11-23 17:05:30 +00006100 target_grouplist[i] = tswap16(grouplist[i]);
pbrook53a59602006-03-25 19:31:22 +00006101 unlock_user(target_grouplist, arg2, gidsetsize * 2);
bellard67867302003-11-23 17:05:30 +00006102 }
6103 }
6104 break;
6105 case TARGET_NR_setgroups:
6106 {
6107 int gidsetsize = arg1;
pbrook53a59602006-03-25 19:31:22 +00006108 uint16_t *target_grouplist;
bellard67867302003-11-23 17:05:30 +00006109 gid_t *grouplist;
6110 int i;
6111
6112 grouplist = alloca(gidsetsize * sizeof(gid_t));
bellard579a97f2007-11-11 14:26:47 +00006113 target_grouplist = lock_user(VERIFY_READ, arg2, gidsetsize * 2, 1);
6114 if (!target_grouplist) {
6115 ret = -TARGET_EFAULT;
6116 goto fail;
6117 }
bellard67867302003-11-23 17:05:30 +00006118 for(i = 0;i < gidsetsize; i++)
6119 grouplist[i] = tswap16(target_grouplist[i]);
pbrook53a59602006-03-25 19:31:22 +00006120 unlock_user(target_grouplist, arg2, 0);
bellard67867302003-11-23 17:05:30 +00006121 ret = get_errno(setgroups(gidsetsize, grouplist));
6122 }
6123 break;
6124 case TARGET_NR_fchown:
6125 ret = get_errno(fchown(arg1, low2highuid(arg2), low2highgid(arg3)));
6126 break;
thsccfa72b2007-09-24 09:23:34 +00006127#if defined(TARGET_NR_fchownat) && defined(__NR_fchownat)
6128 case TARGET_NR_fchownat:
bellard579a97f2007-11-11 14:26:47 +00006129 if (!(p = lock_user_string(arg2)))
6130 goto efault;
6131 ret = get_errno(sys_fchownat(arg1, p, low2highuid(arg3), low2highgid(arg4), arg5));
6132 unlock_user(p, arg2, 0);
thsccfa72b2007-09-24 09:23:34 +00006133 break;
6134#endif
bellard67867302003-11-23 17:05:30 +00006135#ifdef TARGET_NR_setresuid
6136 case TARGET_NR_setresuid:
ths5fafdf22007-09-16 21:08:06 +00006137 ret = get_errno(setresuid(low2highuid(arg1),
6138 low2highuid(arg2),
bellard67867302003-11-23 17:05:30 +00006139 low2highuid(arg3)));
6140 break;
6141#endif
6142#ifdef TARGET_NR_getresuid
6143 case TARGET_NR_getresuid:
6144 {
pbrook53a59602006-03-25 19:31:22 +00006145 uid_t ruid, euid, suid;
bellard67867302003-11-23 17:05:30 +00006146 ret = get_errno(getresuid(&ruid, &euid, &suid));
6147 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +00006148 if (put_user_u16(high2lowuid(ruid), arg1)
6149 || put_user_u16(high2lowuid(euid), arg2)
6150 || put_user_u16(high2lowuid(suid), arg3))
6151 goto efault;
bellard67867302003-11-23 17:05:30 +00006152 }
6153 }
6154 break;
6155#endif
6156#ifdef TARGET_NR_getresgid
6157 case TARGET_NR_setresgid:
ths5fafdf22007-09-16 21:08:06 +00006158 ret = get_errno(setresgid(low2highgid(arg1),
6159 low2highgid(arg2),
bellard67867302003-11-23 17:05:30 +00006160 low2highgid(arg3)));
6161 break;
6162#endif
6163#ifdef TARGET_NR_getresgid
6164 case TARGET_NR_getresgid:
6165 {
pbrook53a59602006-03-25 19:31:22 +00006166 gid_t rgid, egid, sgid;
bellard67867302003-11-23 17:05:30 +00006167 ret = get_errno(getresgid(&rgid, &egid, &sgid));
6168 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +00006169 if (put_user_u16(high2lowgid(rgid), arg1)
6170 || put_user_u16(high2lowgid(egid), arg2)
6171 || put_user_u16(high2lowgid(sgid), arg3))
6172 goto efault;
bellard67867302003-11-23 17:05:30 +00006173 }
6174 }
6175 break;
6176#endif
6177 case TARGET_NR_chown:
bellard579a97f2007-11-11 14:26:47 +00006178 if (!(p = lock_user_string(arg1)))
6179 goto efault;
pbrook53a59602006-03-25 19:31:22 +00006180 ret = get_errno(chown(p, low2highuid(arg2), low2highgid(arg3)));
6181 unlock_user(p, arg1, 0);
bellard67867302003-11-23 17:05:30 +00006182 break;
6183 case TARGET_NR_setuid:
6184 ret = get_errno(setuid(low2highuid(arg1)));
6185 break;
6186 case TARGET_NR_setgid:
6187 ret = get_errno(setgid(low2highgid(arg1)));
6188 break;
6189 case TARGET_NR_setfsuid:
6190 ret = get_errno(setfsuid(arg1));
6191 break;
6192 case TARGET_NR_setfsgid:
6193 ret = get_errno(setfsgid(arg1));
6194 break;
6195#endif /* USE_UID16 */
6196
bellarda315a142005-01-30 22:59:18 +00006197#ifdef TARGET_NR_lchown32
bellard31e31b82003-02-18 22:55:36 +00006198 case TARGET_NR_lchown32:
bellard579a97f2007-11-11 14:26:47 +00006199 if (!(p = lock_user_string(arg1)))
6200 goto efault;
pbrook53a59602006-03-25 19:31:22 +00006201 ret = get_errno(lchown(p, arg2, arg3));
6202 unlock_user(p, arg1, 0);
bellardb03c60f2003-03-23 17:19:56 +00006203 break;
bellarda315a142005-01-30 22:59:18 +00006204#endif
6205#ifdef TARGET_NR_getuid32
bellard31e31b82003-02-18 22:55:36 +00006206 case TARGET_NR_getuid32:
bellardb03c60f2003-03-23 17:19:56 +00006207 ret = get_errno(getuid());
6208 break;
bellarda315a142005-01-30 22:59:18 +00006209#endif
aurel3264b4d282008-11-14 17:20:15 +00006210
6211#if defined(TARGET_NR_getxuid) && defined(TARGET_ALPHA)
6212 /* Alpha specific */
6213 case TARGET_NR_getxuid:
6214 {
6215 uid_t euid;
6216 euid=geteuid();
6217 ((CPUAlphaState *)cpu_env)->ir[IR_A4]=euid;
6218 }
6219 ret = get_errno(getuid());
6220 break;
6221#endif
6222#if defined(TARGET_NR_getxgid) && defined(TARGET_ALPHA)
6223 /* Alpha specific */
6224 case TARGET_NR_getxgid:
6225 {
6226 uid_t egid;
6227 egid=getegid();
6228 ((CPUAlphaState *)cpu_env)->ir[IR_A4]=egid;
6229 }
6230 ret = get_errno(getgid());
6231 break;
6232#endif
6233
bellarda315a142005-01-30 22:59:18 +00006234#ifdef TARGET_NR_getgid32
bellard31e31b82003-02-18 22:55:36 +00006235 case TARGET_NR_getgid32:
bellardb03c60f2003-03-23 17:19:56 +00006236 ret = get_errno(getgid());
6237 break;
bellarda315a142005-01-30 22:59:18 +00006238#endif
6239#ifdef TARGET_NR_geteuid32
bellard31e31b82003-02-18 22:55:36 +00006240 case TARGET_NR_geteuid32:
bellardb03c60f2003-03-23 17:19:56 +00006241 ret = get_errno(geteuid());
6242 break;
bellarda315a142005-01-30 22:59:18 +00006243#endif
6244#ifdef TARGET_NR_getegid32
bellard31e31b82003-02-18 22:55:36 +00006245 case TARGET_NR_getegid32:
bellardb03c60f2003-03-23 17:19:56 +00006246 ret = get_errno(getegid());
6247 break;
bellarda315a142005-01-30 22:59:18 +00006248#endif
6249#ifdef TARGET_NR_setreuid32
bellard31e31b82003-02-18 22:55:36 +00006250 case TARGET_NR_setreuid32:
bellardb03c60f2003-03-23 17:19:56 +00006251 ret = get_errno(setreuid(arg1, arg2));
6252 break;
bellarda315a142005-01-30 22:59:18 +00006253#endif
6254#ifdef TARGET_NR_setregid32
bellard31e31b82003-02-18 22:55:36 +00006255 case TARGET_NR_setregid32:
bellardb03c60f2003-03-23 17:19:56 +00006256 ret = get_errno(setregid(arg1, arg2));
6257 break;
bellarda315a142005-01-30 22:59:18 +00006258#endif
6259#ifdef TARGET_NR_getgroups32
bellard31e31b82003-02-18 22:55:36 +00006260 case TARGET_NR_getgroups32:
bellard99c475a2005-01-31 20:45:13 +00006261 {
6262 int gidsetsize = arg1;
pbrook53a59602006-03-25 19:31:22 +00006263 uint32_t *target_grouplist;
bellard99c475a2005-01-31 20:45:13 +00006264 gid_t *grouplist;
6265 int i;
6266
6267 grouplist = alloca(gidsetsize * sizeof(gid_t));
6268 ret = get_errno(getgroups(gidsetsize, grouplist));
balrogcb3bc232008-09-20 02:08:13 +00006269 if (gidsetsize == 0)
6270 break;
bellard99c475a2005-01-31 20:45:13 +00006271 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00006272 target_grouplist = lock_user(VERIFY_WRITE, arg2, gidsetsize * 4, 0);
6273 if (!target_grouplist) {
6274 ret = -TARGET_EFAULT;
6275 goto fail;
6276 }
balroga2155fc2008-09-20 02:12:08 +00006277 for(i = 0;i < ret; i++)
pbrook53a59602006-03-25 19:31:22 +00006278 target_grouplist[i] = tswap32(grouplist[i]);
6279 unlock_user(target_grouplist, arg2, gidsetsize * 4);
bellard99c475a2005-01-31 20:45:13 +00006280 }
6281 }
6282 break;
bellarda315a142005-01-30 22:59:18 +00006283#endif
6284#ifdef TARGET_NR_setgroups32
bellard31e31b82003-02-18 22:55:36 +00006285 case TARGET_NR_setgroups32:
bellard99c475a2005-01-31 20:45:13 +00006286 {
6287 int gidsetsize = arg1;
pbrook53a59602006-03-25 19:31:22 +00006288 uint32_t *target_grouplist;
bellard99c475a2005-01-31 20:45:13 +00006289 gid_t *grouplist;
6290 int i;
ths3b46e622007-09-17 08:09:54 +00006291
bellard99c475a2005-01-31 20:45:13 +00006292 grouplist = alloca(gidsetsize * sizeof(gid_t));
bellard579a97f2007-11-11 14:26:47 +00006293 target_grouplist = lock_user(VERIFY_READ, arg2, gidsetsize * 4, 1);
6294 if (!target_grouplist) {
6295 ret = -TARGET_EFAULT;
6296 goto fail;
6297 }
bellard99c475a2005-01-31 20:45:13 +00006298 for(i = 0;i < gidsetsize; i++)
pbrook53a59602006-03-25 19:31:22 +00006299 grouplist[i] = tswap32(target_grouplist[i]);
6300 unlock_user(target_grouplist, arg2, 0);
bellard99c475a2005-01-31 20:45:13 +00006301 ret = get_errno(setgroups(gidsetsize, grouplist));
6302 }
6303 break;
bellarda315a142005-01-30 22:59:18 +00006304#endif
6305#ifdef TARGET_NR_fchown32
bellard31e31b82003-02-18 22:55:36 +00006306 case TARGET_NR_fchown32:
bellardb03c60f2003-03-23 17:19:56 +00006307 ret = get_errno(fchown(arg1, arg2, arg3));
6308 break;
bellarda315a142005-01-30 22:59:18 +00006309#endif
6310#ifdef TARGET_NR_setresuid32
bellard31e31b82003-02-18 22:55:36 +00006311 case TARGET_NR_setresuid32:
bellardb03c60f2003-03-23 17:19:56 +00006312 ret = get_errno(setresuid(arg1, arg2, arg3));
6313 break;
bellarda315a142005-01-30 22:59:18 +00006314#endif
6315#ifdef TARGET_NR_getresuid32
bellard31e31b82003-02-18 22:55:36 +00006316 case TARGET_NR_getresuid32:
bellardb03c60f2003-03-23 17:19:56 +00006317 {
pbrook53a59602006-03-25 19:31:22 +00006318 uid_t ruid, euid, suid;
bellardb03c60f2003-03-23 17:19:56 +00006319 ret = get_errno(getresuid(&ruid, &euid, &suid));
6320 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +00006321 if (put_user_u32(ruid, arg1)
6322 || put_user_u32(euid, arg2)
6323 || put_user_u32(suid, arg3))
6324 goto efault;
bellardb03c60f2003-03-23 17:19:56 +00006325 }
6326 }
6327 break;
bellarda315a142005-01-30 22:59:18 +00006328#endif
6329#ifdef TARGET_NR_setresgid32
bellard31e31b82003-02-18 22:55:36 +00006330 case TARGET_NR_setresgid32:
bellardb03c60f2003-03-23 17:19:56 +00006331 ret = get_errno(setresgid(arg1, arg2, arg3));
6332 break;
bellarda315a142005-01-30 22:59:18 +00006333#endif
6334#ifdef TARGET_NR_getresgid32
bellard31e31b82003-02-18 22:55:36 +00006335 case TARGET_NR_getresgid32:
bellardb03c60f2003-03-23 17:19:56 +00006336 {
pbrook53a59602006-03-25 19:31:22 +00006337 gid_t rgid, egid, sgid;
bellardb03c60f2003-03-23 17:19:56 +00006338 ret = get_errno(getresgid(&rgid, &egid, &sgid));
6339 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +00006340 if (put_user_u32(rgid, arg1)
6341 || put_user_u32(egid, arg2)
6342 || put_user_u32(sgid, arg3))
6343 goto efault;
bellardb03c60f2003-03-23 17:19:56 +00006344 }
6345 }
6346 break;
bellarda315a142005-01-30 22:59:18 +00006347#endif
6348#ifdef TARGET_NR_chown32
bellard31e31b82003-02-18 22:55:36 +00006349 case TARGET_NR_chown32:
bellard579a97f2007-11-11 14:26:47 +00006350 if (!(p = lock_user_string(arg1)))
6351 goto efault;
pbrook53a59602006-03-25 19:31:22 +00006352 ret = get_errno(chown(p, arg2, arg3));
6353 unlock_user(p, arg1, 0);
bellardb03c60f2003-03-23 17:19:56 +00006354 break;
bellarda315a142005-01-30 22:59:18 +00006355#endif
6356#ifdef TARGET_NR_setuid32
bellard31e31b82003-02-18 22:55:36 +00006357 case TARGET_NR_setuid32:
bellardb03c60f2003-03-23 17:19:56 +00006358 ret = get_errno(setuid(arg1));
6359 break;
bellarda315a142005-01-30 22:59:18 +00006360#endif
6361#ifdef TARGET_NR_setgid32
bellard31e31b82003-02-18 22:55:36 +00006362 case TARGET_NR_setgid32:
bellardb03c60f2003-03-23 17:19:56 +00006363 ret = get_errno(setgid(arg1));
6364 break;
bellarda315a142005-01-30 22:59:18 +00006365#endif
6366#ifdef TARGET_NR_setfsuid32
bellard31e31b82003-02-18 22:55:36 +00006367 case TARGET_NR_setfsuid32:
bellardb03c60f2003-03-23 17:19:56 +00006368 ret = get_errno(setfsuid(arg1));
6369 break;
bellarda315a142005-01-30 22:59:18 +00006370#endif
6371#ifdef TARGET_NR_setfsgid32
bellard31e31b82003-02-18 22:55:36 +00006372 case TARGET_NR_setfsgid32:
bellardb03c60f2003-03-23 17:19:56 +00006373 ret = get_errno(setfsgid(arg1));
6374 break;
bellarda315a142005-01-30 22:59:18 +00006375#endif
bellard67867302003-11-23 17:05:30 +00006376
bellard31e31b82003-02-18 22:55:36 +00006377 case TARGET_NR_pivot_root:
bellardb03c60f2003-03-23 17:19:56 +00006378 goto unimplemented;
bellardffa65c32004-01-04 23:57:22 +00006379#ifdef TARGET_NR_mincore
bellard31e31b82003-02-18 22:55:36 +00006380 case TARGET_NR_mincore:
aurel3204bb9ac2008-10-01 21:46:41 +00006381 {
6382 void *a;
6383 ret = -TARGET_EFAULT;
6384 if (!(a = lock_user(VERIFY_READ, arg1,arg2, 0)))
6385 goto efault;
6386 if (!(p = lock_user_string(arg3)))
6387 goto mincore_fail;
6388 ret = get_errno(mincore(a, arg2, p));
6389 unlock_user(p, arg3, ret);
6390 mincore_fail:
6391 unlock_user(a, arg1, 0);
6392 }
6393 break;
bellardffa65c32004-01-04 23:57:22 +00006394#endif
aurel32408321b2008-10-01 21:46:32 +00006395#ifdef TARGET_NR_arm_fadvise64_64
6396 case TARGET_NR_arm_fadvise64_64:
6397 {
6398 /*
6399 * arm_fadvise64_64 looks like fadvise64_64 but
6400 * with different argument order
6401 */
6402 abi_long temp;
6403 temp = arg3;
6404 arg3 = arg4;
6405 arg4 = temp;
6406 }
6407#endif
6408#if defined(TARGET_NR_fadvise64_64) || defined(TARGET_NR_arm_fadvise64_64)
6409#ifdef TARGET_NR_fadvise64_64
6410 case TARGET_NR_fadvise64_64:
6411#endif
6412 /* This is a hint, so ignoring and returning success is ok. */
6413 ret = get_errno(0);
6414 break;
6415#endif
bellardffa65c32004-01-04 23:57:22 +00006416#ifdef TARGET_NR_madvise
bellard31e31b82003-02-18 22:55:36 +00006417 case TARGET_NR_madvise:
pbrook24836682006-04-16 14:14:53 +00006418 /* A straight passthrough may not be safe because qemu sometimes
6419 turns private flie-backed mappings into anonymous mappings.
6420 This will break MADV_DONTNEED.
6421 This is a hint, so ignoring and returning success is ok. */
6422 ret = get_errno(0);
6423 break;
bellardffa65c32004-01-04 23:57:22 +00006424#endif
blueswir1992f48a2007-10-14 16:27:31 +00006425#if TARGET_ABI_BITS == 32
bellard31e31b82003-02-18 22:55:36 +00006426 case TARGET_NR_fcntl64:
bellard77e46722003-04-29 20:39:06 +00006427 {
thsb1e341e2007-03-20 21:50:52 +00006428 int cmd;
bellard77e46722003-04-29 20:39:06 +00006429 struct flock64 fl;
pbrook53a59602006-03-25 19:31:22 +00006430 struct target_flock64 *target_fl;
pbrookce4defa2006-02-09 16:49:55 +00006431#ifdef TARGET_ARM
pbrook53a59602006-03-25 19:31:22 +00006432 struct target_eabi_flock64 *target_efl;
pbrookce4defa2006-02-09 16:49:55 +00006433#endif
bellard77e46722003-04-29 20:39:06 +00006434
thsb1e341e2007-03-20 21:50:52 +00006435 switch(arg2){
6436 case TARGET_F_GETLK64:
6437 cmd = F_GETLK64;
thsa7222582007-03-22 15:08:55 +00006438 break;
thsb1e341e2007-03-20 21:50:52 +00006439 case TARGET_F_SETLK64:
6440 cmd = F_SETLK64;
thsa7222582007-03-22 15:08:55 +00006441 break;
thsb1e341e2007-03-20 21:50:52 +00006442 case TARGET_F_SETLKW64:
6443 cmd = F_SETLK64;
thsa7222582007-03-22 15:08:55 +00006444 break;
thsb1e341e2007-03-20 21:50:52 +00006445 default:
6446 cmd = arg2;
thsa7222582007-03-22 15:08:55 +00006447 break;
thsb1e341e2007-03-20 21:50:52 +00006448 }
6449
bellard60cd49d2003-03-16 22:53:56 +00006450 switch(arg2) {
thsb1e341e2007-03-20 21:50:52 +00006451 case TARGET_F_GETLK64:
ths58134272007-03-31 18:59:32 +00006452#ifdef TARGET_ARM
6453 if (((CPUARMState *)cpu_env)->eabi) {
bellard9ee1fa22007-11-11 15:11:19 +00006454 if (!lock_user_struct(VERIFY_READ, target_efl, arg3, 1))
6455 goto efault;
ths58134272007-03-31 18:59:32 +00006456 fl.l_type = tswap16(target_efl->l_type);
6457 fl.l_whence = tswap16(target_efl->l_whence);
6458 fl.l_start = tswap64(target_efl->l_start);
6459 fl.l_len = tswap64(target_efl->l_len);
6460 fl.l_pid = tswapl(target_efl->l_pid);
6461 unlock_user_struct(target_efl, arg3, 0);
6462 } else
6463#endif
6464 {
bellard9ee1fa22007-11-11 15:11:19 +00006465 if (!lock_user_struct(VERIFY_READ, target_fl, arg3, 1))
6466 goto efault;
ths58134272007-03-31 18:59:32 +00006467 fl.l_type = tswap16(target_fl->l_type);
6468 fl.l_whence = tswap16(target_fl->l_whence);
6469 fl.l_start = tswap64(target_fl->l_start);
6470 fl.l_len = tswap64(target_fl->l_len);
6471 fl.l_pid = tswapl(target_fl->l_pid);
6472 unlock_user_struct(target_fl, arg3, 0);
6473 }
thsb1e341e2007-03-20 21:50:52 +00006474 ret = get_errno(fcntl(arg1, cmd, &fl));
bellard77e46722003-04-29 20:39:06 +00006475 if (ret == 0) {
pbrookce4defa2006-02-09 16:49:55 +00006476#ifdef TARGET_ARM
6477 if (((CPUARMState *)cpu_env)->eabi) {
bellard9ee1fa22007-11-11 15:11:19 +00006478 if (!lock_user_struct(VERIFY_WRITE, target_efl, arg3, 0))
6479 goto efault;
pbrookce4defa2006-02-09 16:49:55 +00006480 target_efl->l_type = tswap16(fl.l_type);
6481 target_efl->l_whence = tswap16(fl.l_whence);
6482 target_efl->l_start = tswap64(fl.l_start);
6483 target_efl->l_len = tswap64(fl.l_len);
6484 target_efl->l_pid = tswapl(fl.l_pid);
pbrook53a59602006-03-25 19:31:22 +00006485 unlock_user_struct(target_efl, arg3, 1);
pbrookce4defa2006-02-09 16:49:55 +00006486 } else
6487#endif
6488 {
bellard9ee1fa22007-11-11 15:11:19 +00006489 if (!lock_user_struct(VERIFY_WRITE, target_fl, arg3, 0))
6490 goto efault;
pbrookce4defa2006-02-09 16:49:55 +00006491 target_fl->l_type = tswap16(fl.l_type);
6492 target_fl->l_whence = tswap16(fl.l_whence);
6493 target_fl->l_start = tswap64(fl.l_start);
6494 target_fl->l_len = tswap64(fl.l_len);
6495 target_fl->l_pid = tswapl(fl.l_pid);
pbrook53a59602006-03-25 19:31:22 +00006496 unlock_user_struct(target_fl, arg3, 1);
pbrookce4defa2006-02-09 16:49:55 +00006497 }
bellard77e46722003-04-29 20:39:06 +00006498 }
6499 break;
6500
thsb1e341e2007-03-20 21:50:52 +00006501 case TARGET_F_SETLK64:
6502 case TARGET_F_SETLKW64:
pbrookce4defa2006-02-09 16:49:55 +00006503#ifdef TARGET_ARM
6504 if (((CPUARMState *)cpu_env)->eabi) {
bellard9ee1fa22007-11-11 15:11:19 +00006505 if (!lock_user_struct(VERIFY_READ, target_efl, arg3, 1))
6506 goto efault;
pbrookce4defa2006-02-09 16:49:55 +00006507 fl.l_type = tswap16(target_efl->l_type);
6508 fl.l_whence = tswap16(target_efl->l_whence);
6509 fl.l_start = tswap64(target_efl->l_start);
6510 fl.l_len = tswap64(target_efl->l_len);
6511 fl.l_pid = tswapl(target_efl->l_pid);
pbrook53a59602006-03-25 19:31:22 +00006512 unlock_user_struct(target_efl, arg3, 0);
pbrookce4defa2006-02-09 16:49:55 +00006513 } else
6514#endif
6515 {
bellard9ee1fa22007-11-11 15:11:19 +00006516 if (!lock_user_struct(VERIFY_READ, target_fl, arg3, 1))
6517 goto efault;
pbrookce4defa2006-02-09 16:49:55 +00006518 fl.l_type = tswap16(target_fl->l_type);
6519 fl.l_whence = tswap16(target_fl->l_whence);
6520 fl.l_start = tswap64(target_fl->l_start);
6521 fl.l_len = tswap64(target_fl->l_len);
6522 fl.l_pid = tswapl(target_fl->l_pid);
pbrook53a59602006-03-25 19:31:22 +00006523 unlock_user_struct(target_fl, arg3, 0);
pbrookce4defa2006-02-09 16:49:55 +00006524 }
thsb1e341e2007-03-20 21:50:52 +00006525 ret = get_errno(fcntl(arg1, cmd, &fl));
bellard77e46722003-04-29 20:39:06 +00006526 break;
bellard60cd49d2003-03-16 22:53:56 +00006527 default:
bellard9ee1fa22007-11-11 15:11:19 +00006528 ret = do_fcntl(arg1, cmd, arg3);
bellard60cd49d2003-03-16 22:53:56 +00006529 break;
6530 }
bellard77e46722003-04-29 20:39:06 +00006531 break;
6532 }
bellard60cd49d2003-03-16 22:53:56 +00006533#endif
ths7d600c82006-12-08 01:32:58 +00006534#ifdef TARGET_NR_cacheflush
6535 case TARGET_NR_cacheflush:
6536 /* self-modifying code is handled automatically, so nothing needed */
6537 ret = 0;
6538 break;
6539#endif
bellardebc05482003-09-30 21:08:41 +00006540#ifdef TARGET_NR_security
bellard31e31b82003-02-18 22:55:36 +00006541 case TARGET_NR_security:
6542 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00006543#endif
bellardc573ff62004-01-04 15:51:36 +00006544#ifdef TARGET_NR_getpagesize
6545 case TARGET_NR_getpagesize:
6546 ret = TARGET_PAGE_SIZE;
6547 break;
6548#endif
bellard31e31b82003-02-18 22:55:36 +00006549 case TARGET_NR_gettid:
6550 ret = get_errno(gettid());
6551 break;
thse5febef2007-04-01 18:31:35 +00006552#ifdef TARGET_NR_readahead
bellard31e31b82003-02-18 22:55:36 +00006553 case TARGET_NR_readahead:
aurel322054ac92008-10-13 21:08:07 +00006554#if TARGET_ABI_BITS == 32
6555#ifdef TARGET_ARM
6556 if (((CPUARMState *)cpu_env)->eabi)
6557 {
6558 arg2 = arg3;
6559 arg3 = arg4;
6560 arg4 = arg5;
6561 }
6562#endif
6563 ret = get_errno(readahead(arg1, ((off64_t)arg3 << 32) | arg2, arg4));
6564#else
6565 ret = get_errno(readahead(arg1, arg2, arg3));
6566#endif
6567 break;
thse5febef2007-04-01 18:31:35 +00006568#endif
bellardebc05482003-09-30 21:08:41 +00006569#ifdef TARGET_NR_setxattr
bellard31e31b82003-02-18 22:55:36 +00006570 case TARGET_NR_setxattr:
6571 case TARGET_NR_lsetxattr:
6572 case TARGET_NR_fsetxattr:
6573 case TARGET_NR_getxattr:
6574 case TARGET_NR_lgetxattr:
6575 case TARGET_NR_fgetxattr:
6576 case TARGET_NR_listxattr:
6577 case TARGET_NR_llistxattr:
6578 case TARGET_NR_flistxattr:
6579 case TARGET_NR_removexattr:
6580 case TARGET_NR_lremovexattr:
6581 case TARGET_NR_fremovexattr:
bellard5cd43932003-03-29 16:54:36 +00006582 goto unimplemented_nowarn;
bellardebc05482003-09-30 21:08:41 +00006583#endif
6584#ifdef TARGET_NR_set_thread_area
bellard5cd43932003-03-29 16:54:36 +00006585 case TARGET_NR_set_thread_area:
bellard8d18e892007-11-14 15:18:40 +00006586#if defined(TARGET_MIPS)
ths6f5b89a2007-03-02 20:48:00 +00006587 ((CPUMIPSState *) cpu_env)->tls_value = arg1;
6588 ret = 0;
6589 break;
edgar_iglef967792009-01-07 14:19:38 +00006590#elif defined(TARGET_CRIS)
6591 if (arg1 & 0xff)
6592 ret = -TARGET_EINVAL;
6593 else {
6594 ((CPUCRISState *) cpu_env)->pregs[PR_PID] = arg1;
6595 ret = 0;
6596 }
6597 break;
bellard8d18e892007-11-14 15:18:40 +00006598#elif defined(TARGET_I386) && defined(TARGET_ABI32)
6599 ret = do_set_thread_area(cpu_env, arg1);
6600 break;
ths6f5b89a2007-03-02 20:48:00 +00006601#else
6602 goto unimplemented_nowarn;
6603#endif
6604#endif
6605#ifdef TARGET_NR_get_thread_area
bellard5cd43932003-03-29 16:54:36 +00006606 case TARGET_NR_get_thread_area:
bellard8d18e892007-11-14 15:18:40 +00006607#if defined(TARGET_I386) && defined(TARGET_ABI32)
6608 ret = do_get_thread_area(cpu_env, arg1);
6609#else
bellard5cd43932003-03-29 16:54:36 +00006610 goto unimplemented_nowarn;
bellardebc05482003-09-30 21:08:41 +00006611#endif
bellard8d18e892007-11-14 15:18:40 +00006612#endif
bellard48dc41e2006-06-21 18:15:50 +00006613#ifdef TARGET_NR_getdomainname
6614 case TARGET_NR_getdomainname:
6615 goto unimplemented_nowarn;
6616#endif
ths6f5b89a2007-03-02 20:48:00 +00006617
thsb5906f92007-03-19 13:32:45 +00006618#ifdef TARGET_NR_clock_gettime
6619 case TARGET_NR_clock_gettime:
6620 {
6621 struct timespec ts;
6622 ret = get_errno(clock_gettime(arg1, &ts));
6623 if (!is_error(ret)) {
6624 host_to_target_timespec(arg2, &ts);
6625 }
6626 break;
6627 }
6628#endif
6629#ifdef TARGET_NR_clock_getres
6630 case TARGET_NR_clock_getres:
6631 {
6632 struct timespec ts;
6633 ret = get_errno(clock_getres(arg1, &ts));
6634 if (!is_error(ret)) {
6635 host_to_target_timespec(arg2, &ts);
6636 }
6637 break;
6638 }
6639#endif
pbrook63d76512008-05-29 13:43:29 +00006640#ifdef TARGET_NR_clock_nanosleep
6641 case TARGET_NR_clock_nanosleep:
6642 {
6643 struct timespec ts;
6644 target_to_host_timespec(&ts, arg3);
6645 ret = get_errno(clock_nanosleep(arg1, arg2, &ts, arg4 ? &ts : NULL));
6646 if (arg4)
6647 host_to_target_timespec(arg4, &ts);
6648 break;
6649 }
6650#endif
thsb5906f92007-03-19 13:32:45 +00006651
ths6f5b89a2007-03-02 20:48:00 +00006652#if defined(TARGET_NR_set_tid_address) && defined(__NR_set_tid_address)
6653 case TARGET_NR_set_tid_address:
bellard579a97f2007-11-11 14:26:47 +00006654 ret = get_errno(set_tid_address((int *)g2h(arg1)));
6655 break;
ths6f5b89a2007-03-02 20:48:00 +00006656#endif
6657
ths3ae43202007-09-16 21:39:48 +00006658#if defined(TARGET_NR_tkill) && defined(__NR_tkill)
ths4cae1d12007-07-12 11:06:53 +00006659 case TARGET_NR_tkill:
pbrook4cb05962008-05-30 18:05:19 +00006660 ret = get_errno(sys_tkill((int)arg1, target_to_host_signal(arg2)));
ths4cae1d12007-07-12 11:06:53 +00006661 break;
6662#endif
6663
ths3ae43202007-09-16 21:39:48 +00006664#if defined(TARGET_NR_tgkill) && defined(__NR_tgkill)
ths71455572007-06-21 21:45:30 +00006665 case TARGET_NR_tgkill:
pbrook4cb05962008-05-30 18:05:19 +00006666 ret = get_errno(sys_tgkill((int)arg1, (int)arg2,
6667 target_to_host_signal(arg3)));
ths71455572007-06-21 21:45:30 +00006668 break;
6669#endif
6670
ths4f2b1fe2007-06-21 21:57:12 +00006671#ifdef TARGET_NR_set_robust_list
6672 case TARGET_NR_set_robust_list:
6673 goto unimplemented_nowarn;
6674#endif
6675
ths9007f0e2007-09-25 17:50:37 +00006676#if defined(TARGET_NR_utimensat) && defined(__NR_utimensat)
6677 case TARGET_NR_utimensat:
6678 {
Riku Voipioebc996f2009-04-21 15:01:51 +03006679 struct timespec *tsp, ts[2];
6680 if (!arg3) {
6681 tsp = NULL;
6682 } else {
6683 target_to_host_timespec(ts, arg3);
6684 target_to_host_timespec(ts+1, arg3+sizeof(struct target_timespec));
6685 tsp = ts;
6686 }
ths9007f0e2007-09-25 17:50:37 +00006687 if (!arg2)
Riku Voipioebc996f2009-04-21 15:01:51 +03006688 ret = get_errno(sys_utimensat(arg1, NULL, tsp, arg4));
ths9007f0e2007-09-25 17:50:37 +00006689 else {
bellard579a97f2007-11-11 14:26:47 +00006690 if (!(p = lock_user_string(arg2))) {
ths0da46a62007-10-20 20:23:07 +00006691 ret = -TARGET_EFAULT;
bellard579a97f2007-11-11 14:26:47 +00006692 goto fail;
6693 }
Riku Voipioebc996f2009-04-21 15:01:51 +03006694 ret = get_errno(sys_utimensat(arg1, path(p), tsp, arg4));
bellard579a97f2007-11-11 14:26:47 +00006695 unlock_user(p, arg2, 0);
ths9007f0e2007-09-25 17:50:37 +00006696 }
6697 }
6698 break;
6699#endif
pbrookbd0c5662008-05-29 14:34:11 +00006700#if defined(USE_NPTL)
6701 case TARGET_NR_futex:
6702 ret = do_futex(arg1, arg2, arg3, arg4, arg5, arg6);
6703 break;
6704#endif
aurel32dbfe4c32009-04-08 21:29:30 +00006705#if defined(TARGET_NR_inotify_init) && defined(__NR_inotify_init)
aurel3239b59762008-10-01 21:46:50 +00006706 case TARGET_NR_inotify_init:
6707 ret = get_errno(sys_inotify_init());
6708 break;
6709#endif
aurel32dbfe4c32009-04-08 21:29:30 +00006710#if defined(TARGET_NR_inotify_add_watch) && defined(__NR_inotify_add_watch)
aurel3239b59762008-10-01 21:46:50 +00006711 case TARGET_NR_inotify_add_watch:
6712 p = lock_user_string(arg2);
6713 ret = get_errno(sys_inotify_add_watch(arg1, path(p), arg3));
6714 unlock_user(p, arg2, 0);
6715 break;
6716#endif
aurel32dbfe4c32009-04-08 21:29:30 +00006717#if defined(TARGET_NR_inotify_rm_watch) && defined(__NR_inotify_rm_watch)
aurel3239b59762008-10-01 21:46:50 +00006718 case TARGET_NR_inotify_rm_watch:
6719 ret = get_errno(sys_inotify_rm_watch(arg1, arg2));
6720 break;
6721#endif
ths9007f0e2007-09-25 17:50:37 +00006722
aurel3224e10032009-04-15 16:11:43 +00006723#ifdef TARGET_NR_mq_open
6724 case TARGET_NR_mq_open:
6725 {
6726 struct mq_attr posix_mq_attr;
6727
6728 p = lock_user_string(arg1 - 1);
6729 if (arg4 != 0)
6730 copy_from_user_mq_attr (&posix_mq_attr, arg4);
6731 ret = get_errno(mq_open(p, arg2, arg3, &posix_mq_attr));
6732 unlock_user (p, arg1, 0);
6733 }
6734 break;
6735
6736 case TARGET_NR_mq_unlink:
6737 p = lock_user_string(arg1 - 1);
6738 ret = get_errno(mq_unlink(p));
6739 unlock_user (p, arg1, 0);
6740 break;
6741
6742 case TARGET_NR_mq_timedsend:
6743 {
6744 struct timespec ts;
6745
6746 p = lock_user (VERIFY_READ, arg2, arg3, 1);
6747 if (arg5 != 0) {
6748 target_to_host_timespec(&ts, arg5);
6749 ret = get_errno(mq_timedsend(arg1, p, arg3, arg4, &ts));
6750 host_to_target_timespec(arg5, &ts);
6751 }
6752 else
6753 ret = get_errno(mq_send(arg1, p, arg3, arg4));
6754 unlock_user (p, arg2, arg3);
6755 }
6756 break;
6757
6758 case TARGET_NR_mq_timedreceive:
6759 {
6760 struct timespec ts;
6761 unsigned int prio;
6762
6763 p = lock_user (VERIFY_READ, arg2, arg3, 1);
6764 if (arg5 != 0) {
6765 target_to_host_timespec(&ts, arg5);
6766 ret = get_errno(mq_timedreceive(arg1, p, arg3, &prio, &ts));
6767 host_to_target_timespec(arg5, &ts);
6768 }
6769 else
6770 ret = get_errno(mq_receive(arg1, p, arg3, &prio));
6771 unlock_user (p, arg2, arg3);
6772 if (arg4 != 0)
6773 put_user_u32(prio, arg4);
6774 }
6775 break;
6776
6777 /* Not implemented for now... */
6778/* case TARGET_NR_mq_notify: */
6779/* break; */
6780
6781 case TARGET_NR_mq_getsetattr:
6782 {
6783 struct mq_attr posix_mq_attr_in, posix_mq_attr_out;
6784 ret = 0;
6785 if (arg3 != 0) {
6786 ret = mq_getattr(arg1, &posix_mq_attr_out);
6787 copy_to_user_mq_attr(arg3, &posix_mq_attr_out);
6788 }
6789 if (arg2 != 0) {
6790 copy_from_user_mq_attr(&posix_mq_attr_in, arg2);
6791 ret |= mq_setattr(arg1, &posix_mq_attr_in, &posix_mq_attr_out);
6792 }
6793
6794 }
6795 break;
6796#endif
6797
bellard31e31b82003-02-18 22:55:36 +00006798 default:
6799 unimplemented:
bellard5cd43932003-03-29 16:54:36 +00006800 gemu_log("qemu: Unsupported syscall: %d\n", num);
ths4f2b1fe2007-06-21 21:57:12 +00006801#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 +00006802 unimplemented_nowarn:
bellard80a9d032005-01-03 23:31:27 +00006803#endif
ths0da46a62007-10-20 20:23:07 +00006804 ret = -TARGET_ENOSYS;
bellard31e31b82003-02-18 22:55:36 +00006805 break;
6806 }
bellard579a97f2007-11-11 14:26:47 +00006807fail:
bellardc573ff62004-01-04 15:51:36 +00006808#ifdef DEBUG
6809 gemu_log(" = %ld\n", ret);
6810#endif
thsb92c47c2007-11-01 00:07:38 +00006811 if(do_strace)
6812 print_syscall_ret(num, ret);
bellard31e31b82003-02-18 22:55:36 +00006813 return ret;
bellard579a97f2007-11-11 14:26:47 +00006814efault:
6815 ret = -TARGET_EFAULT;
6816 goto fail;
bellard31e31b82003-02-18 22:55:36 +00006817}