blob: 0c7ce51f04d302fbc2638ae2cbcff81fe7716203 [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>
Martin Mohring350d1772009-05-04 21:21:41 +030080#include <linux/fs.h>
pbrookd7e40362008-05-23 16:06:43 +000081#include "linux_loop.h"
bellard31e31b82003-02-18 22:55:36 +000082
bellard3ef693a2003-03-23 20:17:16 +000083#include "qemu.h"
balrog526ccb72008-07-16 12:13:52 +000084#include "qemu-common.h"
bellard31e31b82003-02-18 22:55:36 +000085
pbrook30813ce2008-06-02 15:45:44 +000086#if defined(USE_NPTL)
87#include <linux/futex.h>
pbrookd865bab2008-06-07 22:12:17 +000088#define CLONE_NPTL_FLAGS2 (CLONE_SETTLS | \
89 CLONE_PARENT_SETTID | CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID)
90#else
91/* XXX: Hardcode the above values. */
92#define CLONE_NPTL_FLAGS2 0
pbrook30813ce2008-06-02 15:45:44 +000093#endif
94
bellard72f03902003-02-18 23:33:18 +000095//#define DEBUG
bellard31e31b82003-02-18 22:55:36 +000096
bellard1a9353d2003-03-16 20:28:50 +000097//#include <linux/msdos_fs.h>
aurel326556a832008-10-13 21:08:17 +000098#define VFAT_IOCTL_READDIR_BOTH _IOR('r', 1, struct linux_dirent [2])
99#define VFAT_IOCTL_READDIR_SHORT _IOR('r', 2, struct linux_dirent [2])
bellard1a9353d2003-03-16 20:28:50 +0000100
bellard70a194b2003-08-11 22:20:16 +0000101
bellard70a194b2003-08-11 22:20:16 +0000102#undef _syscall0
103#undef _syscall1
104#undef _syscall2
105#undef _syscall3
106#undef _syscall4
107#undef _syscall5
bellard83fcb512006-06-14 13:37:16 +0000108#undef _syscall6
bellard70a194b2003-08-11 22:20:16 +0000109
bellard83fcb512006-06-14 13:37:16 +0000110#define _syscall0(type,name) \
blueswir18fcd3692008-08-17 20:26:25 +0000111static type name (void) \
bellard83fcb512006-06-14 13:37:16 +0000112{ \
113 return syscall(__NR_##name); \
bellard70a194b2003-08-11 22:20:16 +0000114}
115
bellard83fcb512006-06-14 13:37:16 +0000116#define _syscall1(type,name,type1,arg1) \
blueswir18fcd3692008-08-17 20:26:25 +0000117static type name (type1 arg1) \
bellard83fcb512006-06-14 13:37:16 +0000118{ \
119 return syscall(__NR_##name, arg1); \
bellard70a194b2003-08-11 22:20:16 +0000120}
121
bellard83fcb512006-06-14 13:37:16 +0000122#define _syscall2(type,name,type1,arg1,type2,arg2) \
blueswir18fcd3692008-08-17 20:26:25 +0000123static type name (type1 arg1,type2 arg2) \
bellard83fcb512006-06-14 13:37:16 +0000124{ \
125 return syscall(__NR_##name, arg1, arg2); \
bellard70a194b2003-08-11 22:20:16 +0000126}
127
bellard83fcb512006-06-14 13:37:16 +0000128#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \
blueswir18fcd3692008-08-17 20:26:25 +0000129static type name (type1 arg1,type2 arg2,type3 arg3) \
bellard83fcb512006-06-14 13:37:16 +0000130{ \
131 return syscall(__NR_##name, arg1, arg2, arg3); \
bellard70a194b2003-08-11 22:20:16 +0000132}
133
bellard83fcb512006-06-14 13:37:16 +0000134#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \
blueswir18fcd3692008-08-17 20:26:25 +0000135static type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4) \
bellard83fcb512006-06-14 13:37:16 +0000136{ \
137 return syscall(__NR_##name, arg1, arg2, arg3, arg4); \
bellard70a194b2003-08-11 22:20:16 +0000138}
139
bellard83fcb512006-06-14 13:37:16 +0000140#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
141 type5,arg5) \
blueswir18fcd3692008-08-17 20:26:25 +0000142static type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \
bellard83fcb512006-06-14 13:37:16 +0000143{ \
144 return syscall(__NR_##name, arg1, arg2, arg3, arg4, arg5); \
bellard70a194b2003-08-11 22:20:16 +0000145}
bellard83fcb512006-06-14 13:37:16 +0000146
147
148#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
149 type5,arg5,type6,arg6) \
blueswir18fcd3692008-08-17 20:26:25 +0000150static type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5, \
151 type6 arg6) \
bellard83fcb512006-06-14 13:37:16 +0000152{ \
153 return syscall(__NR_##name, arg1, arg2, arg3, arg4, arg5, arg6); \
154}
155
bellard70a194b2003-08-11 22:20:16 +0000156
bellard31e31b82003-02-18 22:55:36 +0000157#define __NR_sys_uname __NR_uname
ths92a34c12007-09-24 09:27:49 +0000158#define __NR_sys_faccessat __NR_faccessat
ths814d7972007-09-24 09:26:51 +0000159#define __NR_sys_fchmodat __NR_fchmodat
thsccfa72b2007-09-24 09:23:34 +0000160#define __NR_sys_fchownat __NR_fchownat
balrog6a24a772008-09-20 02:23:36 +0000161#define __NR_sys_fstatat64 __NR_fstatat64
balrogac8a6552008-09-20 02:25:39 +0000162#define __NR_sys_futimesat __NR_futimesat
bellard72f03902003-02-18 23:33:18 +0000163#define __NR_sys_getcwd1 __NR_getcwd
bellard72f03902003-02-18 23:33:18 +0000164#define __NR_sys_getdents __NR_getdents
bellarddab2ed92003-03-22 15:23:14 +0000165#define __NR_sys_getdents64 __NR_getdents64
thsc6cda172007-10-09 03:42:34 +0000166#define __NR_sys_getpriority __NR_getpriority
ths64f0ce42007-09-24 09:25:06 +0000167#define __NR_sys_linkat __NR_linkat
ths4472ad02007-09-24 09:22:32 +0000168#define __NR_sys_mkdirat __NR_mkdirat
ths75ac37a2007-09-24 09:23:05 +0000169#define __NR_sys_mknodat __NR_mknodat
aurel329d33b762009-04-08 23:07:05 +0000170#define __NR_sys_newfstatat __NR_newfstatat
ths82424832007-09-24 09:21:55 +0000171#define __NR_sys_openat __NR_openat
ths5e0ccb12007-09-24 09:26:10 +0000172#define __NR_sys_readlinkat __NR_readlinkat
ths722183f2007-09-24 09:24:37 +0000173#define __NR_sys_renameat __NR_renameat
bellard66fb9762003-03-23 01:06:05 +0000174#define __NR_sys_rt_sigqueueinfo __NR_rt_sigqueueinfo
thsf0b62432007-09-24 09:25:40 +0000175#define __NR_sys_symlinkat __NR_symlinkat
ths7494b0f2007-02-11 18:26:53 +0000176#define __NR_sys_syslog __NR_syslog
ths71455572007-06-21 21:45:30 +0000177#define __NR_sys_tgkill __NR_tgkill
ths4cae1d12007-07-12 11:06:53 +0000178#define __NR_sys_tkill __NR_tkill
ths8170f562007-09-24 09:24:11 +0000179#define __NR_sys_unlinkat __NR_unlinkat
ths9007f0e2007-09-25 17:50:37 +0000180#define __NR_sys_utimensat __NR_utimensat
pbrookbd0c5662008-05-29 14:34:11 +0000181#define __NR_sys_futex __NR_futex
aurel3239b59762008-10-01 21:46:50 +0000182#define __NR_sys_inotify_init __NR_inotify_init
183#define __NR_sys_inotify_add_watch __NR_inotify_add_watch
184#define __NR_sys_inotify_rm_watch __NR_inotify_rm_watch
bellard31e31b82003-02-18 22:55:36 +0000185
bellardbc51c5c2004-03-17 23:46:04 +0000186#if defined(__alpha__) || defined (__ia64__) || defined(__x86_64__)
bellard9af9eaa2003-04-07 21:34:41 +0000187#define __NR__llseek __NR_lseek
188#endif
189
bellard72f03902003-02-18 23:33:18 +0000190#ifdef __NR_gettid
bellard31e31b82003-02-18 22:55:36 +0000191_syscall0(int, gettid)
bellard72f03902003-02-18 23:33:18 +0000192#else
ths0da46a62007-10-20 20:23:07 +0000193/* This is a replacement for the host gettid() and must return a host
194 errno. */
bellard72f03902003-02-18 23:33:18 +0000195static int gettid(void) {
196 return -ENOSYS;
197}
198#endif
aurel323b3f24a2009-04-15 16:12:13 +0000199#if TARGET_ABI_BITS == 32
200_syscall3(int, sys_getdents, uint, fd, struct linux_dirent *, dirp, uint, count);
201#endif
202#if defined(TARGET_NR_getdents64) && defined(__NR_getdents64)
203_syscall3(int, sys_getdents64, uint, fd, struct linux_dirent64 *, dirp, uint, count);
204#endif
205_syscall2(int, sys_getpriority, int, which, int, who);
Paul Brook909b69c2009-05-19 15:58:52 +0100206#if defined(TARGET_NR__llseek) && !defined (__x86_64__)
aurel323b3f24a2009-04-15 16:12:13 +0000207_syscall5(int, _llseek, uint, fd, ulong, hi, ulong, lo,
208 loff_t *, res, uint, wh);
209#endif
210_syscall3(int,sys_rt_sigqueueinfo,int,pid,int,sig,siginfo_t *,uinfo)
211_syscall3(int,sys_syslog,int,type,char*,bufp,int,len)
212#if defined(TARGET_NR_tgkill) && defined(__NR_tgkill)
213_syscall3(int,sys_tgkill,int,tgid,int,pid,int,sig)
214#endif
215#if defined(TARGET_NR_tkill) && defined(__NR_tkill)
216_syscall2(int,sys_tkill,int,tid,int,sig)
217#endif
218#ifdef __NR_exit_group
219_syscall1(int,exit_group,int,error_code)
220#endif
221#if defined(TARGET_NR_set_tid_address) && defined(__NR_set_tid_address)
222_syscall1(int,set_tid_address,int *,tidptr)
223#endif
224#if defined(USE_NPTL)
225#if defined(TARGET_NR_futex) && defined(__NR_futex)
226_syscall6(int,sys_futex,int *,uaddr,int,op,int,val,
227 const struct timespec *,timeout,int *,uaddr2,int,val3)
228#endif
229#endif
230
231static bitmask_transtbl fcntl_flags_tbl[] = {
232 { TARGET_O_ACCMODE, TARGET_O_WRONLY, O_ACCMODE, O_WRONLY, },
233 { TARGET_O_ACCMODE, TARGET_O_RDWR, O_ACCMODE, O_RDWR, },
234 { TARGET_O_CREAT, TARGET_O_CREAT, O_CREAT, O_CREAT, },
235 { TARGET_O_EXCL, TARGET_O_EXCL, O_EXCL, O_EXCL, },
236 { TARGET_O_NOCTTY, TARGET_O_NOCTTY, O_NOCTTY, O_NOCTTY, },
237 { TARGET_O_TRUNC, TARGET_O_TRUNC, O_TRUNC, O_TRUNC, },
238 { TARGET_O_APPEND, TARGET_O_APPEND, O_APPEND, O_APPEND, },
239 { TARGET_O_NONBLOCK, TARGET_O_NONBLOCK, O_NONBLOCK, O_NONBLOCK, },
240 { TARGET_O_SYNC, TARGET_O_SYNC, O_SYNC, O_SYNC, },
241 { TARGET_FASYNC, TARGET_FASYNC, FASYNC, FASYNC, },
242 { TARGET_O_DIRECTORY, TARGET_O_DIRECTORY, O_DIRECTORY, O_DIRECTORY, },
243 { TARGET_O_NOFOLLOW, TARGET_O_NOFOLLOW, O_NOFOLLOW, O_NOFOLLOW, },
244 { TARGET_O_LARGEFILE, TARGET_O_LARGEFILE, O_LARGEFILE, O_LARGEFILE, },
245#if defined(O_DIRECT)
246 { TARGET_O_DIRECT, TARGET_O_DIRECT, O_DIRECT, O_DIRECT, },
247#endif
248 { 0, 0, 0, 0 }
249};
250
251#define COPY_UTSNAME_FIELD(dest, src) \
252 do { \
253 /* __NEW_UTS_LEN doesn't include terminating null */ \
254 (void) strncpy((dest), (src), __NEW_UTS_LEN); \
255 (dest)[__NEW_UTS_LEN] = '\0'; \
256 } while (0)
257
258static int sys_uname(struct new_utsname *buf)
259{
260 struct utsname uts_buf;
261
262 if (uname(&uts_buf) < 0)
263 return (-1);
264
265 /*
266 * Just in case these have some differences, we
267 * translate utsname to new_utsname (which is the
268 * struct linux kernel uses).
269 */
270
271 bzero(buf, sizeof (*buf));
272 COPY_UTSNAME_FIELD(buf->sysname, uts_buf.sysname);
273 COPY_UTSNAME_FIELD(buf->nodename, uts_buf.nodename);
274 COPY_UTSNAME_FIELD(buf->release, uts_buf.release);
275 COPY_UTSNAME_FIELD(buf->version, uts_buf.version);
276 COPY_UTSNAME_FIELD(buf->machine, uts_buf.machine);
277#ifdef _GNU_SOURCE
278 COPY_UTSNAME_FIELD(buf->domainname, uts_buf.domainname);
279#endif
280 return (0);
281
282#undef COPY_UTSNAME_FIELD
283}
284
285static int sys_getcwd1(char *buf, size_t size)
286{
287 if (getcwd(buf, size) == NULL) {
288 /* getcwd() sets errno */
289 return (-1);
290 }
aurel32aaf4ad32009-04-16 14:17:14 +0000291 return strlen(buf)+1;
aurel323b3f24a2009-04-15 16:12:13 +0000292}
293
294#ifdef CONFIG_ATFILE
295/*
296 * Host system seems to have atfile syscall stubs available. We
297 * now enable them one by one as specified by target syscall_nr.h.
298 */
299
300#ifdef TARGET_NR_faccessat
aurel32465c9f02009-04-19 08:52:17 +0000301static int sys_faccessat(int dirfd, const char *pathname, int mode)
aurel323b3f24a2009-04-15 16:12:13 +0000302{
aurel32465c9f02009-04-19 08:52:17 +0000303 return (faccessat(dirfd, pathname, mode, 0));
aurel323b3f24a2009-04-15 16:12:13 +0000304}
305#endif
306#ifdef TARGET_NR_fchmodat
aurel32465c9f02009-04-19 08:52:17 +0000307static int sys_fchmodat(int dirfd, const char *pathname, mode_t mode)
aurel323b3f24a2009-04-15 16:12:13 +0000308{
aurel32465c9f02009-04-19 08:52:17 +0000309 return (fchmodat(dirfd, pathname, mode, 0));
aurel323b3f24a2009-04-15 16:12:13 +0000310}
311#endif
aurel32fda33742009-04-15 17:12:01 +0000312#if defined(TARGET_NR_fchownat) && defined(USE_UID16)
aurel323b3f24a2009-04-15 16:12:13 +0000313static int sys_fchownat(int dirfd, const char *pathname, uid_t owner,
314 gid_t group, int flags)
315{
316 return (fchownat(dirfd, pathname, owner, group, flags));
317}
318#endif
319#ifdef __NR_fstatat64
320static int sys_fstatat64(int dirfd, const char *pathname, struct stat *buf,
321 int flags)
322{
323 return (fstatat(dirfd, pathname, buf, flags));
324}
325#endif
326#ifdef __NR_newfstatat
327static int sys_newfstatat(int dirfd, const char *pathname, struct stat *buf,
328 int flags)
329{
330 return (fstatat(dirfd, pathname, buf, flags));
331}
332#endif
333#ifdef TARGET_NR_futimesat
334static int sys_futimesat(int dirfd, const char *pathname,
335 const struct timeval times[2])
336{
337 return (futimesat(dirfd, pathname, times));
338}
339#endif
340#ifdef TARGET_NR_linkat
341static int sys_linkat(int olddirfd, const char *oldpath,
342 int newdirfd, const char *newpath, int flags)
343{
344 return (linkat(olddirfd, oldpath, newdirfd, newpath, flags));
345}
346#endif
347#ifdef TARGET_NR_mkdirat
348static int sys_mkdirat(int dirfd, const char *pathname, mode_t mode)
349{
350 return (mkdirat(dirfd, pathname, mode));
351}
352#endif
353#ifdef TARGET_NR_mknodat
354static int sys_mknodat(int dirfd, const char *pathname, mode_t mode,
355 dev_t dev)
356{
357 return (mknodat(dirfd, pathname, mode, dev));
358}
359#endif
360#ifdef TARGET_NR_openat
361static int sys_openat(int dirfd, const char *pathname, int flags, ...)
362{
363 /*
364 * open(2) has extra parameter 'mode' when called with
365 * flag O_CREAT.
366 */
367 if ((flags & O_CREAT) != 0) {
368 va_list ap;
369 mode_t mode;
370
371 /*
372 * Get the 'mode' parameter and translate it to
373 * host bits.
374 */
375 va_start(ap, flags);
376 mode = va_arg(ap, mode_t);
377 mode = target_to_host_bitmask(mode, fcntl_flags_tbl);
378 va_end(ap);
379
380 return (openat(dirfd, pathname, flags, mode));
381 }
382 return (openat(dirfd, pathname, flags));
383}
384#endif
385#ifdef TARGET_NR_readlinkat
386static int sys_readlinkat(int dirfd, const char *pathname, char *buf, size_t bufsiz)
387{
388 return (readlinkat(dirfd, pathname, buf, bufsiz));
389}
390#endif
391#ifdef TARGET_NR_renameat
392static int sys_renameat(int olddirfd, const char *oldpath,
393 int newdirfd, const char *newpath)
394{
395 return (renameat(olddirfd, oldpath, newdirfd, newpath));
396}
397#endif
398#ifdef TARGET_NR_symlinkat
399static int sys_symlinkat(const char *oldpath, int newdirfd, const char *newpath)
400{
401 return (symlinkat(oldpath, newdirfd, newpath));
402}
403#endif
404#ifdef TARGET_NR_unlinkat
405static int sys_unlinkat(int dirfd, const char *pathname, int flags)
406{
407 return (unlinkat(dirfd, pathname, flags));
408}
409#endif
aurel323b3f24a2009-04-15 16:12:13 +0000410#else /* !CONFIG_ATFILE */
411
412/*
413 * Try direct syscalls instead
414 */
ths92a34c12007-09-24 09:27:49 +0000415#if defined(TARGET_NR_faccessat) && defined(__NR_faccessat)
aurel32465c9f02009-04-19 08:52:17 +0000416_syscall3(int,sys_faccessat,int,dirfd,const char *,pathname,int,mode)
ths92a34c12007-09-24 09:27:49 +0000417#endif
ths814d7972007-09-24 09:26:51 +0000418#if defined(TARGET_NR_fchmodat) && defined(__NR_fchmodat)
aurel32465c9f02009-04-19 08:52:17 +0000419_syscall3(int,sys_fchmodat,int,dirfd,const char *,pathname, mode_t,mode)
ths814d7972007-09-24 09:26:51 +0000420#endif
blueswir14583f582008-08-24 10:35:55 +0000421#if defined(TARGET_NR_fchownat) && defined(__NR_fchownat) && defined(USE_UID16)
thsccfa72b2007-09-24 09:23:34 +0000422_syscall5(int,sys_fchownat,int,dirfd,const char *,pathname,
423 uid_t,owner,gid_t,group,int,flags)
424#endif
aurel329d33b762009-04-08 23:07:05 +0000425#if (defined(TARGET_NR_fstatat64) || defined(TARGET_NR_newfstatat)) && \
426 defined(__NR_fstatat64)
balrog6a24a772008-09-20 02:23:36 +0000427_syscall4(int,sys_fstatat64,int,dirfd,const char *,pathname,
428 struct stat *,buf,int,flags)
429#endif
balrogac8a6552008-09-20 02:25:39 +0000430#if defined(TARGET_NR_futimesat) && defined(__NR_futimesat)
431_syscall3(int,sys_futimesat,int,dirfd,const char *,pathname,
432 const struct timeval *,times)
433#endif
aurel323b3f24a2009-04-15 16:12:13 +0000434#if (defined(TARGET_NR_newfstatat) || defined(TARGET_NR_fstatat64) ) && \
435 defined(__NR_newfstatat)
436_syscall4(int,sys_newfstatat,int,dirfd,const char *,pathname,
437 struct stat *,buf,int,flags)
blueswir18fcd3692008-08-17 20:26:25 +0000438#endif
ths64f0ce42007-09-24 09:25:06 +0000439#if defined(TARGET_NR_linkat) && defined(__NR_linkat)
440_syscall5(int,sys_linkat,int,olddirfd,const char *,oldpath,
aurel323b3f24a2009-04-15 16:12:13 +0000441 int,newdirfd,const char *,newpath,int,flags)
ths64f0ce42007-09-24 09:25:06 +0000442#endif
ths4472ad02007-09-24 09:22:32 +0000443#if defined(TARGET_NR_mkdirat) && defined(__NR_mkdirat)
444_syscall3(int,sys_mkdirat,int,dirfd,const char *,pathname,mode_t,mode)
445#endif
ths75ac37a2007-09-24 09:23:05 +0000446#if defined(TARGET_NR_mknodat) && defined(__NR_mknodat)
447_syscall4(int,sys_mknodat,int,dirfd,const char *,pathname,
448 mode_t,mode,dev_t,dev)
449#endif
ths82424832007-09-24 09:21:55 +0000450#if defined(TARGET_NR_openat) && defined(__NR_openat)
451_syscall4(int,sys_openat,int,dirfd,const char *,pathname,int,flags,mode_t,mode)
452#endif
ths5e0ccb12007-09-24 09:26:10 +0000453#if defined(TARGET_NR_readlinkat) && defined(__NR_readlinkat)
454_syscall4(int,sys_readlinkat,int,dirfd,const char *,pathname,
455 char *,buf,size_t,bufsize)
456#endif
ths722183f2007-09-24 09:24:37 +0000457#if defined(TARGET_NR_renameat) && defined(__NR_renameat)
458_syscall4(int,sys_renameat,int,olddirfd,const char *,oldpath,
459 int,newdirfd,const char *,newpath)
460#endif
thsb51eaa82007-09-25 16:09:22 +0000461#if defined(TARGET_NR_symlinkat) && defined(__NR_symlinkat)
thsf0b62432007-09-24 09:25:40 +0000462_syscall3(int,sys_symlinkat,const char *,oldpath,
463 int,newdirfd,const char *,newpath)
464#endif
ths8170f562007-09-24 09:24:11 +0000465#if defined(TARGET_NR_unlinkat) && defined(__NR_unlinkat)
466_syscall3(int,sys_unlinkat,int,dirfd,const char *,pathname,int,flags)
467#endif
Riku Voipioebc996f2009-04-21 15:01:51 +0300468
469#endif /* CONFIG_ATFILE */
470
471#ifdef CONFIG_UTIMENSAT
472static int sys_utimensat(int dirfd, const char *pathname,
473 const struct timespec times[2], int flags)
474{
475 if (pathname == NULL)
476 return futimens(dirfd, times);
477 else
478 return utimensat(dirfd, pathname, times, flags);
479}
480#else
ths9007f0e2007-09-25 17:50:37 +0000481#if defined(TARGET_NR_utimensat) && defined(__NR_utimensat)
482_syscall4(int,sys_utimensat,int,dirfd,const char *,pathname,
483 const struct timespec *,tsp,int,flags)
484#endif
Riku Voipioebc996f2009-04-21 15:01:51 +0300485#endif /* CONFIG_UTIMENSAT */
aurel323b3f24a2009-04-15 16:12:13 +0000486
487#ifdef CONFIG_INOTIFY
aurel328690e422009-04-17 13:50:32 +0000488#include <sys/inotify.h>
aurel323b3f24a2009-04-15 16:12:13 +0000489
aurel3239b59762008-10-01 21:46:50 +0000490#if defined(TARGET_NR_inotify_init) && defined(__NR_inotify_init)
aurel323b3f24a2009-04-15 16:12:13 +0000491static int sys_inotify_init(void)
492{
493 return (inotify_init());
494}
aurel3239b59762008-10-01 21:46:50 +0000495#endif
496#if defined(TARGET_NR_inotify_add_watch) && defined(__NR_inotify_add_watch)
aurel323b3f24a2009-04-15 16:12:13 +0000497static int sys_inotify_add_watch(int fd,const char *pathname, int32_t mask)
498{
499 return (inotify_add_watch(fd, pathname, mask));
500}
aurel3239b59762008-10-01 21:46:50 +0000501#endif
502#if defined(TARGET_NR_inotify_rm_watch) && defined(__NR_inotify_rm_watch)
aurel323b3f24a2009-04-15 16:12:13 +0000503static int sys_inotify_rm_watch(int fd, int32_t wd)
504{
aurel328690e422009-04-17 13:50:32 +0000505 return (inotify_rm_watch(fd, wd));
aurel323b3f24a2009-04-15 16:12:13 +0000506}
aurel3239b59762008-10-01 21:46:50 +0000507#endif
aurel323b3f24a2009-04-15 16:12:13 +0000508#else
509/* Userspace can usually survive runtime without inotify */
510#undef TARGET_NR_inotify_init
511#undef TARGET_NR_inotify_add_watch
512#undef TARGET_NR_inotify_rm_watch
513#endif /* CONFIG_INOTIFY */
514
bellard66fb9762003-03-23 01:06:05 +0000515
516extern int personality(int);
bellard9de5e442003-03-23 16:49:39 +0000517extern int flock(int, int);
518extern int setfsuid(int);
519extern int setfsgid(int);
bellard19b84f32003-05-08 15:41:49 +0000520extern int setgroups(int, gid_t *);
bellard31e31b82003-02-18 22:55:36 +0000521
thsb92c47c2007-11-01 00:07:38 +0000522#define ERRNO_TABLE_SIZE 1200
523
524/* target_to_host_errno_table[] is initialized from
525 * host_to_target_errno_table[] in syscall_init(). */
526static uint16_t target_to_host_errno_table[ERRNO_TABLE_SIZE] = {
527};
528
ths637947f2007-06-01 12:09:19 +0000529/*
thsfe8f0962007-07-12 10:59:21 +0000530 * This list is the union of errno values overridden in asm-<arch>/errno.h
ths637947f2007-06-01 12:09:19 +0000531 * minus the errnos that are not actually generic to all archs.
532 */
thsb92c47c2007-11-01 00:07:38 +0000533static uint16_t host_to_target_errno_table[ERRNO_TABLE_SIZE] = {
ths637947f2007-06-01 12:09:19 +0000534 [EIDRM] = TARGET_EIDRM,
535 [ECHRNG] = TARGET_ECHRNG,
536 [EL2NSYNC] = TARGET_EL2NSYNC,
537 [EL3HLT] = TARGET_EL3HLT,
538 [EL3RST] = TARGET_EL3RST,
539 [ELNRNG] = TARGET_ELNRNG,
540 [EUNATCH] = TARGET_EUNATCH,
541 [ENOCSI] = TARGET_ENOCSI,
542 [EL2HLT] = TARGET_EL2HLT,
543 [EDEADLK] = TARGET_EDEADLK,
544 [ENOLCK] = TARGET_ENOLCK,
545 [EBADE] = TARGET_EBADE,
546 [EBADR] = TARGET_EBADR,
547 [EXFULL] = TARGET_EXFULL,
548 [ENOANO] = TARGET_ENOANO,
549 [EBADRQC] = TARGET_EBADRQC,
550 [EBADSLT] = TARGET_EBADSLT,
551 [EBFONT] = TARGET_EBFONT,
552 [ENOSTR] = TARGET_ENOSTR,
553 [ENODATA] = TARGET_ENODATA,
554 [ETIME] = TARGET_ETIME,
555 [ENOSR] = TARGET_ENOSR,
556 [ENONET] = TARGET_ENONET,
557 [ENOPKG] = TARGET_ENOPKG,
558 [EREMOTE] = TARGET_EREMOTE,
559 [ENOLINK] = TARGET_ENOLINK,
560 [EADV] = TARGET_EADV,
561 [ESRMNT] = TARGET_ESRMNT,
562 [ECOMM] = TARGET_ECOMM,
563 [EPROTO] = TARGET_EPROTO,
564 [EDOTDOT] = TARGET_EDOTDOT,
565 [EMULTIHOP] = TARGET_EMULTIHOP,
566 [EBADMSG] = TARGET_EBADMSG,
567 [ENAMETOOLONG] = TARGET_ENAMETOOLONG,
568 [EOVERFLOW] = TARGET_EOVERFLOW,
569 [ENOTUNIQ] = TARGET_ENOTUNIQ,
570 [EBADFD] = TARGET_EBADFD,
571 [EREMCHG] = TARGET_EREMCHG,
572 [ELIBACC] = TARGET_ELIBACC,
573 [ELIBBAD] = TARGET_ELIBBAD,
574 [ELIBSCN] = TARGET_ELIBSCN,
575 [ELIBMAX] = TARGET_ELIBMAX,
576 [ELIBEXEC] = TARGET_ELIBEXEC,
577 [EILSEQ] = TARGET_EILSEQ,
578 [ENOSYS] = TARGET_ENOSYS,
579 [ELOOP] = TARGET_ELOOP,
580 [ERESTART] = TARGET_ERESTART,
581 [ESTRPIPE] = TARGET_ESTRPIPE,
582 [ENOTEMPTY] = TARGET_ENOTEMPTY,
583 [EUSERS] = TARGET_EUSERS,
584 [ENOTSOCK] = TARGET_ENOTSOCK,
585 [EDESTADDRREQ] = TARGET_EDESTADDRREQ,
586 [EMSGSIZE] = TARGET_EMSGSIZE,
587 [EPROTOTYPE] = TARGET_EPROTOTYPE,
588 [ENOPROTOOPT] = TARGET_ENOPROTOOPT,
589 [EPROTONOSUPPORT] = TARGET_EPROTONOSUPPORT,
590 [ESOCKTNOSUPPORT] = TARGET_ESOCKTNOSUPPORT,
591 [EOPNOTSUPP] = TARGET_EOPNOTSUPP,
592 [EPFNOSUPPORT] = TARGET_EPFNOSUPPORT,
593 [EAFNOSUPPORT] = TARGET_EAFNOSUPPORT,
594 [EADDRINUSE] = TARGET_EADDRINUSE,
595 [EADDRNOTAVAIL] = TARGET_EADDRNOTAVAIL,
596 [ENETDOWN] = TARGET_ENETDOWN,
597 [ENETUNREACH] = TARGET_ENETUNREACH,
598 [ENETRESET] = TARGET_ENETRESET,
599 [ECONNABORTED] = TARGET_ECONNABORTED,
600 [ECONNRESET] = TARGET_ECONNRESET,
601 [ENOBUFS] = TARGET_ENOBUFS,
602 [EISCONN] = TARGET_EISCONN,
603 [ENOTCONN] = TARGET_ENOTCONN,
604 [EUCLEAN] = TARGET_EUCLEAN,
605 [ENOTNAM] = TARGET_ENOTNAM,
606 [ENAVAIL] = TARGET_ENAVAIL,
607 [EISNAM] = TARGET_EISNAM,
608 [EREMOTEIO] = TARGET_EREMOTEIO,
609 [ESHUTDOWN] = TARGET_ESHUTDOWN,
610 [ETOOMANYREFS] = TARGET_ETOOMANYREFS,
611 [ETIMEDOUT] = TARGET_ETIMEDOUT,
612 [ECONNREFUSED] = TARGET_ECONNREFUSED,
613 [EHOSTDOWN] = TARGET_EHOSTDOWN,
614 [EHOSTUNREACH] = TARGET_EHOSTUNREACH,
615 [EALREADY] = TARGET_EALREADY,
616 [EINPROGRESS] = TARGET_EINPROGRESS,
617 [ESTALE] = TARGET_ESTALE,
618 [ECANCELED] = TARGET_ECANCELED,
619 [ENOMEDIUM] = TARGET_ENOMEDIUM,
620 [EMEDIUMTYPE] = TARGET_EMEDIUMTYPE,
thsb7fe5db2007-07-23 15:37:46 +0000621#ifdef ENOKEY
ths637947f2007-06-01 12:09:19 +0000622 [ENOKEY] = TARGET_ENOKEY,
thsb7fe5db2007-07-23 15:37:46 +0000623#endif
624#ifdef EKEYEXPIRED
ths637947f2007-06-01 12:09:19 +0000625 [EKEYEXPIRED] = TARGET_EKEYEXPIRED,
thsb7fe5db2007-07-23 15:37:46 +0000626#endif
627#ifdef EKEYREVOKED
ths637947f2007-06-01 12:09:19 +0000628 [EKEYREVOKED] = TARGET_EKEYREVOKED,
thsb7fe5db2007-07-23 15:37:46 +0000629#endif
630#ifdef EKEYREJECTED
ths637947f2007-06-01 12:09:19 +0000631 [EKEYREJECTED] = TARGET_EKEYREJECTED,
thsb7fe5db2007-07-23 15:37:46 +0000632#endif
633#ifdef EOWNERDEAD
ths637947f2007-06-01 12:09:19 +0000634 [EOWNERDEAD] = TARGET_EOWNERDEAD,
thsb7fe5db2007-07-23 15:37:46 +0000635#endif
636#ifdef ENOTRECOVERABLE
ths637947f2007-06-01 12:09:19 +0000637 [ENOTRECOVERABLE] = TARGET_ENOTRECOVERABLE,
thsb7fe5db2007-07-23 15:37:46 +0000638#endif
thsb92c47c2007-11-01 00:07:38 +0000639};
ths637947f2007-06-01 12:09:19 +0000640
641static inline int host_to_target_errno(int err)
642{
643 if(host_to_target_errno_table[err])
644 return host_to_target_errno_table[err];
645 return err;
646}
647
thsb92c47c2007-11-01 00:07:38 +0000648static inline int target_to_host_errno(int err)
649{
650 if (target_to_host_errno_table[err])
651 return target_to_host_errno_table[err];
652 return err;
653}
654
blueswir1992f48a2007-10-14 16:27:31 +0000655static inline abi_long get_errno(abi_long ret)
bellard31e31b82003-02-18 22:55:36 +0000656{
657 if (ret == -1)
ths637947f2007-06-01 12:09:19 +0000658 return -host_to_target_errno(errno);
bellard31e31b82003-02-18 22:55:36 +0000659 else
660 return ret;
661}
662
blueswir1992f48a2007-10-14 16:27:31 +0000663static inline int is_error(abi_long ret)
bellard31e31b82003-02-18 22:55:36 +0000664{
blueswir1992f48a2007-10-14 16:27:31 +0000665 return (abi_ulong)ret >= (abi_ulong)(-4096);
bellard31e31b82003-02-18 22:55:36 +0000666}
667
thsb92c47c2007-11-01 00:07:38 +0000668char *target_strerror(int err)
669{
670 return strerror(target_to_host_errno(err));
671}
672
blueswir1992f48a2007-10-14 16:27:31 +0000673static abi_ulong target_brk;
674static abi_ulong target_original_brk;
bellard31e31b82003-02-18 22:55:36 +0000675
blueswir1992f48a2007-10-14 16:27:31 +0000676void target_set_brk(abi_ulong new_brk)
bellard31e31b82003-02-18 22:55:36 +0000677{
blueswir14c1de732007-07-07 20:45:44 +0000678 target_original_brk = target_brk = HOST_PAGE_ALIGN(new_brk);
bellard31e31b82003-02-18 22:55:36 +0000679}
680
ths0da46a62007-10-20 20:23:07 +0000681/* do_brk() must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +0000682abi_long do_brk(abi_ulong new_brk)
bellard31e31b82003-02-18 22:55:36 +0000683{
blueswir1992f48a2007-10-14 16:27:31 +0000684 abi_ulong brk_page;
685 abi_long mapped_addr;
bellard31e31b82003-02-18 22:55:36 +0000686 int new_alloc_size;
687
688 if (!new_brk)
pbrook53a59602006-03-25 19:31:22 +0000689 return target_brk;
bellard31e31b82003-02-18 22:55:36 +0000690 if (new_brk < target_original_brk)
balrog7ab240a2008-04-26 12:17:34 +0000691 return target_brk;
ths3b46e622007-09-17 08:09:54 +0000692
pbrook53a59602006-03-25 19:31:22 +0000693 brk_page = HOST_PAGE_ALIGN(target_brk);
bellard31e31b82003-02-18 22:55:36 +0000694
695 /* If the new brk is less than this, set it and we're done... */
696 if (new_brk < brk_page) {
697 target_brk = new_brk;
pbrook53a59602006-03-25 19:31:22 +0000698 return target_brk;
bellard31e31b82003-02-18 22:55:36 +0000699 }
700
701 /* We need to allocate more memory after the brk... */
bellard54936002003-05-13 00:25:15 +0000702 new_alloc_size = HOST_PAGE_ALIGN(new_brk - brk_page + 1);
ths5fafdf22007-09-16 21:08:06 +0000703 mapped_addr = get_errno(target_mmap(brk_page, new_alloc_size,
bellard54936002003-05-13 00:25:15 +0000704 PROT_READ|PROT_WRITE,
705 MAP_ANON|MAP_FIXED|MAP_PRIVATE, 0, 0));
balrog7ab240a2008-04-26 12:17:34 +0000706
707 if (!is_error(mapped_addr))
bellard31e31b82003-02-18 22:55:36 +0000708 target_brk = new_brk;
balrog7ab240a2008-04-26 12:17:34 +0000709
710 return target_brk;
bellard31e31b82003-02-18 22:55:36 +0000711}
712
ths26edcf42007-12-09 02:25:24 +0000713static inline abi_long copy_from_user_fdset(fd_set *fds,
714 abi_ulong target_fds_addr,
715 int n)
bellard31e31b82003-02-18 22:55:36 +0000716{
ths26edcf42007-12-09 02:25:24 +0000717 int i, nw, j, k;
718 abi_ulong b, *target_fds;
719
720 nw = (n + TARGET_ABI_BITS - 1) / TARGET_ABI_BITS;
721 if (!(target_fds = lock_user(VERIFY_READ,
722 target_fds_addr,
723 sizeof(abi_ulong) * nw,
724 1)))
725 return -TARGET_EFAULT;
726
727 FD_ZERO(fds);
728 k = 0;
729 for (i = 0; i < nw; i++) {
730 /* grab the abi_ulong */
731 __get_user(b, &target_fds[i]);
732 for (j = 0; j < TARGET_ABI_BITS; j++) {
733 /* check the bit inside the abi_ulong */
734 if ((b >> j) & 1)
735 FD_SET(k, fds);
736 k++;
bellard31e31b82003-02-18 22:55:36 +0000737 }
bellard31e31b82003-02-18 22:55:36 +0000738 }
ths26edcf42007-12-09 02:25:24 +0000739
740 unlock_user(target_fds, target_fds_addr, 0);
741
742 return 0;
bellard31e31b82003-02-18 22:55:36 +0000743}
744
ths26edcf42007-12-09 02:25:24 +0000745static inline abi_long copy_to_user_fdset(abi_ulong target_fds_addr,
746 const fd_set *fds,
747 int n)
bellard31e31b82003-02-18 22:55:36 +0000748{
bellard31e31b82003-02-18 22:55:36 +0000749 int i, nw, j, k;
blueswir1992f48a2007-10-14 16:27:31 +0000750 abi_long v;
ths26edcf42007-12-09 02:25:24 +0000751 abi_ulong *target_fds;
bellard31e31b82003-02-18 22:55:36 +0000752
ths26edcf42007-12-09 02:25:24 +0000753 nw = (n + TARGET_ABI_BITS - 1) / TARGET_ABI_BITS;
754 if (!(target_fds = lock_user(VERIFY_WRITE,
755 target_fds_addr,
756 sizeof(abi_ulong) * nw,
757 0)))
758 return -TARGET_EFAULT;
759
760 k = 0;
761 for (i = 0; i < nw; i++) {
762 v = 0;
763 for (j = 0; j < TARGET_ABI_BITS; j++) {
764 v |= ((FD_ISSET(k, fds) != 0) << j);
765 k++;
bellard31e31b82003-02-18 22:55:36 +0000766 }
ths26edcf42007-12-09 02:25:24 +0000767 __put_user(v, &target_fds[i]);
bellard31e31b82003-02-18 22:55:36 +0000768 }
ths26edcf42007-12-09 02:25:24 +0000769
770 unlock_user(target_fds, target_fds_addr, sizeof(abi_ulong) * nw);
771
772 return 0;
bellard31e31b82003-02-18 22:55:36 +0000773}
774
bellardc596ed12003-07-13 17:32:31 +0000775#if defined(__alpha__)
776#define HOST_HZ 1024
777#else
778#define HOST_HZ 100
779#endif
780
blueswir1992f48a2007-10-14 16:27:31 +0000781static inline abi_long host_to_target_clock_t(long ticks)
bellardc596ed12003-07-13 17:32:31 +0000782{
783#if HOST_HZ == TARGET_HZ
784 return ticks;
785#else
786 return ((int64_t)ticks * TARGET_HZ) / HOST_HZ;
787#endif
788}
789
bellard579a97f2007-11-11 14:26:47 +0000790static inline abi_long host_to_target_rusage(abi_ulong target_addr,
791 const struct rusage *rusage)
bellardb4091862003-05-16 15:39:34 +0000792{
pbrook53a59602006-03-25 19:31:22 +0000793 struct target_rusage *target_rusage;
794
bellard579a97f2007-11-11 14:26:47 +0000795 if (!lock_user_struct(VERIFY_WRITE, target_rusage, target_addr, 0))
796 return -TARGET_EFAULT;
bellardb4091862003-05-16 15:39:34 +0000797 target_rusage->ru_utime.tv_sec = tswapl(rusage->ru_utime.tv_sec);
798 target_rusage->ru_utime.tv_usec = tswapl(rusage->ru_utime.tv_usec);
799 target_rusage->ru_stime.tv_sec = tswapl(rusage->ru_stime.tv_sec);
800 target_rusage->ru_stime.tv_usec = tswapl(rusage->ru_stime.tv_usec);
801 target_rusage->ru_maxrss = tswapl(rusage->ru_maxrss);
802 target_rusage->ru_ixrss = tswapl(rusage->ru_ixrss);
803 target_rusage->ru_idrss = tswapl(rusage->ru_idrss);
804 target_rusage->ru_isrss = tswapl(rusage->ru_isrss);
805 target_rusage->ru_minflt = tswapl(rusage->ru_minflt);
806 target_rusage->ru_majflt = tswapl(rusage->ru_majflt);
807 target_rusage->ru_nswap = tswapl(rusage->ru_nswap);
808 target_rusage->ru_inblock = tswapl(rusage->ru_inblock);
809 target_rusage->ru_oublock = tswapl(rusage->ru_oublock);
810 target_rusage->ru_msgsnd = tswapl(rusage->ru_msgsnd);
811 target_rusage->ru_msgrcv = tswapl(rusage->ru_msgrcv);
812 target_rusage->ru_nsignals = tswapl(rusage->ru_nsignals);
813 target_rusage->ru_nvcsw = tswapl(rusage->ru_nvcsw);
814 target_rusage->ru_nivcsw = tswapl(rusage->ru_nivcsw);
pbrook53a59602006-03-25 19:31:22 +0000815 unlock_user_struct(target_rusage, target_addr, 1);
bellard579a97f2007-11-11 14:26:47 +0000816
817 return 0;
bellardb4091862003-05-16 15:39:34 +0000818}
819
ths788f5ec2007-12-09 02:37:05 +0000820static inline abi_long copy_from_user_timeval(struct timeval *tv,
821 abi_ulong target_tv_addr)
bellard31e31b82003-02-18 22:55:36 +0000822{
pbrook53a59602006-03-25 19:31:22 +0000823 struct target_timeval *target_tv;
824
ths788f5ec2007-12-09 02:37:05 +0000825 if (!lock_user_struct(VERIFY_READ, target_tv, target_tv_addr, 1))
bellard579a97f2007-11-11 14:26:47 +0000826 return -TARGET_EFAULT;
ths788f5ec2007-12-09 02:37:05 +0000827
828 __get_user(tv->tv_sec, &target_tv->tv_sec);
829 __get_user(tv->tv_usec, &target_tv->tv_usec);
830
831 unlock_user_struct(target_tv, target_tv_addr, 0);
bellard579a97f2007-11-11 14:26:47 +0000832
833 return 0;
bellard31e31b82003-02-18 22:55:36 +0000834}
835
ths788f5ec2007-12-09 02:37:05 +0000836static inline abi_long copy_to_user_timeval(abi_ulong target_tv_addr,
837 const struct timeval *tv)
bellard31e31b82003-02-18 22:55:36 +0000838{
pbrook53a59602006-03-25 19:31:22 +0000839 struct target_timeval *target_tv;
840
ths788f5ec2007-12-09 02:37:05 +0000841 if (!lock_user_struct(VERIFY_WRITE, target_tv, target_tv_addr, 0))
bellard579a97f2007-11-11 14:26:47 +0000842 return -TARGET_EFAULT;
ths788f5ec2007-12-09 02:37:05 +0000843
844 __put_user(tv->tv_sec, &target_tv->tv_sec);
845 __put_user(tv->tv_usec, &target_tv->tv_usec);
846
847 unlock_user_struct(target_tv, target_tv_addr, 1);
bellard579a97f2007-11-11 14:26:47 +0000848
849 return 0;
bellard31e31b82003-02-18 22:55:36 +0000850}
851
aurel3224e10032009-04-15 16:11:43 +0000852static inline abi_long copy_from_user_mq_attr(struct mq_attr *attr,
853 abi_ulong target_mq_attr_addr)
854{
855 struct target_mq_attr *target_mq_attr;
856
857 if (!lock_user_struct(VERIFY_READ, target_mq_attr,
858 target_mq_attr_addr, 1))
859 return -TARGET_EFAULT;
860
861 __get_user(attr->mq_flags, &target_mq_attr->mq_flags);
862 __get_user(attr->mq_maxmsg, &target_mq_attr->mq_maxmsg);
863 __get_user(attr->mq_msgsize, &target_mq_attr->mq_msgsize);
864 __get_user(attr->mq_curmsgs, &target_mq_attr->mq_curmsgs);
865
866 unlock_user_struct(target_mq_attr, target_mq_attr_addr, 0);
867
868 return 0;
869}
870
871static inline abi_long copy_to_user_mq_attr(abi_ulong target_mq_attr_addr,
872 const struct mq_attr *attr)
873{
874 struct target_mq_attr *target_mq_attr;
875
876 if (!lock_user_struct(VERIFY_WRITE, target_mq_attr,
877 target_mq_attr_addr, 0))
878 return -TARGET_EFAULT;
879
880 __put_user(attr->mq_flags, &target_mq_attr->mq_flags);
881 __put_user(attr->mq_maxmsg, &target_mq_attr->mq_maxmsg);
882 __put_user(attr->mq_msgsize, &target_mq_attr->mq_msgsize);
883 __put_user(attr->mq_curmsgs, &target_mq_attr->mq_curmsgs);
884
885 unlock_user_struct(target_mq_attr, target_mq_attr_addr, 1);
886
887 return 0;
888}
bellard31e31b82003-02-18 22:55:36 +0000889
ths0da46a62007-10-20 20:23:07 +0000890/* do_select() must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +0000891static abi_long do_select(int n,
ths26edcf42007-12-09 02:25:24 +0000892 abi_ulong rfd_addr, abi_ulong wfd_addr,
893 abi_ulong efd_addr, abi_ulong target_tv_addr)
bellard31e31b82003-02-18 22:55:36 +0000894{
895 fd_set rfds, wfds, efds;
896 fd_set *rfds_ptr, *wfds_ptr, *efds_ptr;
897 struct timeval tv, *tv_ptr;
blueswir1992f48a2007-10-14 16:27:31 +0000898 abi_long ret;
bellard31e31b82003-02-18 22:55:36 +0000899
ths26edcf42007-12-09 02:25:24 +0000900 if (rfd_addr) {
901 if (copy_from_user_fdset(&rfds, rfd_addr, n))
902 return -TARGET_EFAULT;
903 rfds_ptr = &rfds;
pbrook53a59602006-03-25 19:31:22 +0000904 } else {
pbrook53a59602006-03-25 19:31:22 +0000905 rfds_ptr = NULL;
906 }
ths26edcf42007-12-09 02:25:24 +0000907 if (wfd_addr) {
908 if (copy_from_user_fdset(&wfds, wfd_addr, n))
909 return -TARGET_EFAULT;
910 wfds_ptr = &wfds;
pbrook53a59602006-03-25 19:31:22 +0000911 } else {
pbrook53a59602006-03-25 19:31:22 +0000912 wfds_ptr = NULL;
913 }
ths26edcf42007-12-09 02:25:24 +0000914 if (efd_addr) {
915 if (copy_from_user_fdset(&efds, efd_addr, n))
916 return -TARGET_EFAULT;
917 efds_ptr = &efds;
pbrook53a59602006-03-25 19:31:22 +0000918 } else {
pbrook53a59602006-03-25 19:31:22 +0000919 efds_ptr = NULL;
920 }
ths3b46e622007-09-17 08:09:54 +0000921
ths26edcf42007-12-09 02:25:24 +0000922 if (target_tv_addr) {
ths788f5ec2007-12-09 02:37:05 +0000923 if (copy_from_user_timeval(&tv, target_tv_addr))
924 return -TARGET_EFAULT;
bellard31e31b82003-02-18 22:55:36 +0000925 tv_ptr = &tv;
926 } else {
927 tv_ptr = NULL;
928 }
ths26edcf42007-12-09 02:25:24 +0000929
bellard31e31b82003-02-18 22:55:36 +0000930 ret = get_errno(select(n, rfds_ptr, wfds_ptr, efds_ptr, tv_ptr));
pbrook53a59602006-03-25 19:31:22 +0000931
ths26edcf42007-12-09 02:25:24 +0000932 if (!is_error(ret)) {
933 if (rfd_addr && copy_to_user_fdset(rfd_addr, &rfds, n))
934 return -TARGET_EFAULT;
935 if (wfd_addr && copy_to_user_fdset(wfd_addr, &wfds, n))
936 return -TARGET_EFAULT;
937 if (efd_addr && copy_to_user_fdset(efd_addr, &efds, n))
938 return -TARGET_EFAULT;
bellard31e31b82003-02-18 22:55:36 +0000939
ths788f5ec2007-12-09 02:37:05 +0000940 if (target_tv_addr && copy_to_user_timeval(target_tv_addr, &tv))
941 return -TARGET_EFAULT;
bellard31e31b82003-02-18 22:55:36 +0000942 }
bellard579a97f2007-11-11 14:26:47 +0000943
bellard31e31b82003-02-18 22:55:36 +0000944 return ret;
945}
946
Lionel Landwerlinb975b832009-04-25 23:30:19 +0200947static inline abi_long target_to_host_ip_mreq(struct ip_mreqn *mreqn,
948 abi_ulong target_addr,
949 socklen_t len)
950{
951 struct target_ip_mreqn *target_smreqn;
952
953 target_smreqn = lock_user(VERIFY_READ, target_addr, len, 1);
954 if (!target_smreqn)
955 return -TARGET_EFAULT;
956 mreqn->imr_multiaddr.s_addr = target_smreqn->imr_multiaddr.s_addr;
957 mreqn->imr_address.s_addr = target_smreqn->imr_address.s_addr;
958 if (len == sizeof(struct target_ip_mreqn))
959 mreqn->imr_ifindex = tswapl(target_smreqn->imr_ifindex);
960 unlock_user(target_smreqn, target_addr, 0);
961
962 return 0;
963}
964
bellard579a97f2007-11-11 14:26:47 +0000965static inline abi_long target_to_host_sockaddr(struct sockaddr *addr,
966 abi_ulong target_addr,
967 socklen_t len)
bellard7854b052003-03-29 17:22:23 +0000968{
aurel32607175e2009-04-15 16:11:59 +0000969 const socklen_t unix_maxlen = sizeof (struct sockaddr_un);
970 sa_family_t sa_family;
pbrook53a59602006-03-25 19:31:22 +0000971 struct target_sockaddr *target_saddr;
972
bellard579a97f2007-11-11 14:26:47 +0000973 target_saddr = lock_user(VERIFY_READ, target_addr, len, 1);
974 if (!target_saddr)
975 return -TARGET_EFAULT;
aurel32607175e2009-04-15 16:11:59 +0000976
977 sa_family = tswap16(target_saddr->sa_family);
978
979 /* Oops. The caller might send a incomplete sun_path; sun_path
980 * must be terminated by \0 (see the manual page), but
981 * unfortunately it is quite common to specify sockaddr_un
982 * length as "strlen(x->sun_path)" while it should be
983 * "strlen(...) + 1". We'll fix that here if needed.
984 * Linux kernel has a similar feature.
985 */
986
987 if (sa_family == AF_UNIX) {
988 if (len < unix_maxlen && len > 0) {
989 char *cp = (char*)target_saddr;
990
991 if ( cp[len-1] && !cp[len] )
992 len++;
993 }
994 if (len > unix_maxlen)
995 len = unix_maxlen;
996 }
997
pbrook53a59602006-03-25 19:31:22 +0000998 memcpy(addr, target_saddr, len);
aurel32607175e2009-04-15 16:11:59 +0000999 addr->sa_family = sa_family;
pbrook53a59602006-03-25 19:31:22 +00001000 unlock_user(target_saddr, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00001001
1002 return 0;
bellard7854b052003-03-29 17:22:23 +00001003}
1004
bellard579a97f2007-11-11 14:26:47 +00001005static inline abi_long host_to_target_sockaddr(abi_ulong target_addr,
1006 struct sockaddr *addr,
1007 socklen_t len)
bellard7854b052003-03-29 17:22:23 +00001008{
pbrook53a59602006-03-25 19:31:22 +00001009 struct target_sockaddr *target_saddr;
1010
bellard579a97f2007-11-11 14:26:47 +00001011 target_saddr = lock_user(VERIFY_WRITE, target_addr, len, 0);
1012 if (!target_saddr)
1013 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00001014 memcpy(target_saddr, addr, len);
1015 target_saddr->sa_family = tswap16(addr->sa_family);
1016 unlock_user(target_saddr, target_addr, len);
bellard579a97f2007-11-11 14:26:47 +00001017
1018 return 0;
bellard7854b052003-03-29 17:22:23 +00001019}
1020
pbrook53a59602006-03-25 19:31:22 +00001021/* ??? Should this also swap msgh->name? */
bellard5a4a8982007-11-11 17:39:18 +00001022static inline abi_long target_to_host_cmsg(struct msghdr *msgh,
1023 struct target_msghdr *target_msgh)
bellard7854b052003-03-29 17:22:23 +00001024{
1025 struct cmsghdr *cmsg = CMSG_FIRSTHDR(msgh);
bellard5a4a8982007-11-11 17:39:18 +00001026 abi_long msg_controllen;
1027 abi_ulong target_cmsg_addr;
1028 struct target_cmsghdr *target_cmsg;
bellard7854b052003-03-29 17:22:23 +00001029 socklen_t space = 0;
bellard5a4a8982007-11-11 17:39:18 +00001030
1031 msg_controllen = tswapl(target_msgh->msg_controllen);
1032 if (msg_controllen < sizeof (struct target_cmsghdr))
1033 goto the_end;
1034 target_cmsg_addr = tswapl(target_msgh->msg_control);
1035 target_cmsg = lock_user(VERIFY_READ, target_cmsg_addr, msg_controllen, 1);
1036 if (!target_cmsg)
1037 return -TARGET_EFAULT;
bellard7854b052003-03-29 17:22:23 +00001038
1039 while (cmsg && target_cmsg) {
1040 void *data = CMSG_DATA(cmsg);
1041 void *target_data = TARGET_CMSG_DATA(target_cmsg);
1042
ths5fafdf22007-09-16 21:08:06 +00001043 int len = tswapl(target_cmsg->cmsg_len)
bellard7854b052003-03-29 17:22:23 +00001044 - TARGET_CMSG_ALIGN(sizeof (struct target_cmsghdr));
1045
1046 space += CMSG_SPACE(len);
1047 if (space > msgh->msg_controllen) {
1048 space -= CMSG_SPACE(len);
bellard31febb72005-12-18 20:03:27 +00001049 gemu_log("Host cmsg overflow\n");
bellard7854b052003-03-29 17:22:23 +00001050 break;
1051 }
1052
1053 cmsg->cmsg_level = tswap32(target_cmsg->cmsg_level);
1054 cmsg->cmsg_type = tswap32(target_cmsg->cmsg_type);
1055 cmsg->cmsg_len = CMSG_LEN(len);
1056
bellard3532fa72006-06-24 15:06:03 +00001057 if (cmsg->cmsg_level != TARGET_SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS) {
bellard7854b052003-03-29 17:22:23 +00001058 gemu_log("Unsupported ancillary data: %d/%d\n", cmsg->cmsg_level, cmsg->cmsg_type);
1059 memcpy(data, target_data, len);
1060 } else {
1061 int *fd = (int *)data;
1062 int *target_fd = (int *)target_data;
1063 int i, numfds = len / sizeof(int);
1064
1065 for (i = 0; i < numfds; i++)
1066 fd[i] = tswap32(target_fd[i]);
1067 }
1068
1069 cmsg = CMSG_NXTHDR(msgh, cmsg);
1070 target_cmsg = TARGET_CMSG_NXTHDR(target_msgh, target_cmsg);
1071 }
bellard5a4a8982007-11-11 17:39:18 +00001072 unlock_user(target_cmsg, target_cmsg_addr, 0);
1073 the_end:
bellard7854b052003-03-29 17:22:23 +00001074 msgh->msg_controllen = space;
bellard5a4a8982007-11-11 17:39:18 +00001075 return 0;
bellard7854b052003-03-29 17:22:23 +00001076}
1077
pbrook53a59602006-03-25 19:31:22 +00001078/* ??? Should this also swap msgh->name? */
bellard5a4a8982007-11-11 17:39:18 +00001079static inline abi_long host_to_target_cmsg(struct target_msghdr *target_msgh,
1080 struct msghdr *msgh)
bellard7854b052003-03-29 17:22:23 +00001081{
1082 struct cmsghdr *cmsg = CMSG_FIRSTHDR(msgh);
bellard5a4a8982007-11-11 17:39:18 +00001083 abi_long msg_controllen;
1084 abi_ulong target_cmsg_addr;
1085 struct target_cmsghdr *target_cmsg;
bellard7854b052003-03-29 17:22:23 +00001086 socklen_t space = 0;
1087
bellard5a4a8982007-11-11 17:39:18 +00001088 msg_controllen = tswapl(target_msgh->msg_controllen);
1089 if (msg_controllen < sizeof (struct target_cmsghdr))
1090 goto the_end;
1091 target_cmsg_addr = tswapl(target_msgh->msg_control);
1092 target_cmsg = lock_user(VERIFY_WRITE, target_cmsg_addr, msg_controllen, 0);
1093 if (!target_cmsg)
1094 return -TARGET_EFAULT;
1095
bellard7854b052003-03-29 17:22:23 +00001096 while (cmsg && target_cmsg) {
1097 void *data = CMSG_DATA(cmsg);
1098 void *target_data = TARGET_CMSG_DATA(target_cmsg);
1099
1100 int len = cmsg->cmsg_len - CMSG_ALIGN(sizeof (struct cmsghdr));
1101
1102 space += TARGET_CMSG_SPACE(len);
bellard5a4a8982007-11-11 17:39:18 +00001103 if (space > msg_controllen) {
bellard7854b052003-03-29 17:22:23 +00001104 space -= TARGET_CMSG_SPACE(len);
bellard31febb72005-12-18 20:03:27 +00001105 gemu_log("Target cmsg overflow\n");
bellard7854b052003-03-29 17:22:23 +00001106 break;
1107 }
1108
1109 target_cmsg->cmsg_level = tswap32(cmsg->cmsg_level);
1110 target_cmsg->cmsg_type = tswap32(cmsg->cmsg_type);
1111 target_cmsg->cmsg_len = tswapl(TARGET_CMSG_LEN(len));
1112
bellard3532fa72006-06-24 15:06:03 +00001113 if (cmsg->cmsg_level != TARGET_SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS) {
bellard7854b052003-03-29 17:22:23 +00001114 gemu_log("Unsupported ancillary data: %d/%d\n", cmsg->cmsg_level, cmsg->cmsg_type);
1115 memcpy(target_data, data, len);
1116 } else {
1117 int *fd = (int *)data;
1118 int *target_fd = (int *)target_data;
1119 int i, numfds = len / sizeof(int);
1120
1121 for (i = 0; i < numfds; i++)
1122 target_fd[i] = tswap32(fd[i]);
1123 }
1124
1125 cmsg = CMSG_NXTHDR(msgh, cmsg);
1126 target_cmsg = TARGET_CMSG_NXTHDR(target_msgh, target_cmsg);
1127 }
bellard5a4a8982007-11-11 17:39:18 +00001128 unlock_user(target_cmsg, target_cmsg_addr, space);
1129 the_end:
1130 target_msgh->msg_controllen = tswapl(space);
1131 return 0;
bellard7854b052003-03-29 17:22:23 +00001132}
1133
ths0da46a62007-10-20 20:23:07 +00001134/* do_setsockopt() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001135static abi_long do_setsockopt(int sockfd, int level, int optname,
bellard2f619692007-11-16 10:46:05 +00001136 abi_ulong optval_addr, socklen_t optlen)
bellard7854b052003-03-29 17:22:23 +00001137{
blueswir1992f48a2007-10-14 16:27:31 +00001138 abi_long ret;
j_mayer32407102007-09-26 23:01:49 +00001139 int val;
Lionel Landwerlinb975b832009-04-25 23:30:19 +02001140 struct ip_mreqn *ip_mreq;
Lionel Landwerlin6e3cb582009-04-25 23:31:18 +02001141 struct ip_mreq_source *ip_mreq_source;
ths3b46e622007-09-17 08:09:54 +00001142
bellard8853f862004-02-22 14:57:26 +00001143 switch(level) {
1144 case SOL_TCP:
bellard7854b052003-03-29 17:22:23 +00001145 /* TCP options all take an 'int' value. */
bellard7854b052003-03-29 17:22:23 +00001146 if (optlen < sizeof(uint32_t))
ths0da46a62007-10-20 20:23:07 +00001147 return -TARGET_EINVAL;
ths3b46e622007-09-17 08:09:54 +00001148
bellard2f619692007-11-16 10:46:05 +00001149 if (get_user_u32(val, optval_addr))
1150 return -TARGET_EFAULT;
bellard8853f862004-02-22 14:57:26 +00001151 ret = get_errno(setsockopt(sockfd, level, optname, &val, sizeof(val)));
1152 break;
1153 case SOL_IP:
1154 switch(optname) {
bellard2efbe912005-07-23 15:10:20 +00001155 case IP_TOS:
1156 case IP_TTL:
bellard8853f862004-02-22 14:57:26 +00001157 case IP_HDRINCL:
bellard2efbe912005-07-23 15:10:20 +00001158 case IP_ROUTER_ALERT:
1159 case IP_RECVOPTS:
1160 case IP_RETOPTS:
1161 case IP_PKTINFO:
1162 case IP_MTU_DISCOVER:
1163 case IP_RECVERR:
1164 case IP_RECVTOS:
1165#ifdef IP_FREEBIND
1166 case IP_FREEBIND:
1167#endif
1168 case IP_MULTICAST_TTL:
1169 case IP_MULTICAST_LOOP:
bellard8853f862004-02-22 14:57:26 +00001170 val = 0;
1171 if (optlen >= sizeof(uint32_t)) {
bellard2f619692007-11-16 10:46:05 +00001172 if (get_user_u32(val, optval_addr))
1173 return -TARGET_EFAULT;
bellard8853f862004-02-22 14:57:26 +00001174 } else if (optlen >= 1) {
bellard2f619692007-11-16 10:46:05 +00001175 if (get_user_u8(val, optval_addr))
1176 return -TARGET_EFAULT;
bellard8853f862004-02-22 14:57:26 +00001177 }
1178 ret = get_errno(setsockopt(sockfd, level, optname, &val, sizeof(val)));
1179 break;
Lionel Landwerlinb975b832009-04-25 23:30:19 +02001180 case IP_ADD_MEMBERSHIP:
1181 case IP_DROP_MEMBERSHIP:
1182 if (optlen < sizeof (struct target_ip_mreq) ||
1183 optlen > sizeof (struct target_ip_mreqn))
1184 return -TARGET_EINVAL;
1185
1186 ip_mreq = (struct ip_mreqn *) alloca(optlen);
1187 target_to_host_ip_mreq(ip_mreq, optval_addr, optlen);
1188 ret = get_errno(setsockopt(sockfd, level, optname, ip_mreq, optlen));
1189 break;
1190
Lionel Landwerlin6e3cb582009-04-25 23:31:18 +02001191 case IP_BLOCK_SOURCE:
1192 case IP_UNBLOCK_SOURCE:
1193 case IP_ADD_SOURCE_MEMBERSHIP:
1194 case IP_DROP_SOURCE_MEMBERSHIP:
1195 if (optlen != sizeof (struct target_ip_mreq_source))
1196 return -TARGET_EINVAL;
1197
1198 ip_mreq_source = lock_user(VERIFY_READ, optval_addr, optlen, 1);
1199 ret = get_errno(setsockopt(sockfd, level, optname, ip_mreq_source, optlen));
1200 unlock_user (ip_mreq_source, optval_addr, 0);
1201 break;
1202
bellard8853f862004-02-22 14:57:26 +00001203 default:
1204 goto unimplemented;
1205 }
1206 break;
bellard3532fa72006-06-24 15:06:03 +00001207 case TARGET_SOL_SOCKET:
bellard8853f862004-02-22 14:57:26 +00001208 switch (optname) {
1209 /* Options with 'int' argument. */
bellard3532fa72006-06-24 15:06:03 +00001210 case TARGET_SO_DEBUG:
1211 optname = SO_DEBUG;
1212 break;
1213 case TARGET_SO_REUSEADDR:
1214 optname = SO_REUSEADDR;
1215 break;
1216 case TARGET_SO_TYPE:
1217 optname = SO_TYPE;
1218 break;
1219 case TARGET_SO_ERROR:
1220 optname = SO_ERROR;
1221 break;
1222 case TARGET_SO_DONTROUTE:
1223 optname = SO_DONTROUTE;
1224 break;
1225 case TARGET_SO_BROADCAST:
1226 optname = SO_BROADCAST;
1227 break;
1228 case TARGET_SO_SNDBUF:
1229 optname = SO_SNDBUF;
1230 break;
1231 case TARGET_SO_RCVBUF:
1232 optname = SO_RCVBUF;
1233 break;
1234 case TARGET_SO_KEEPALIVE:
1235 optname = SO_KEEPALIVE;
1236 break;
1237 case TARGET_SO_OOBINLINE:
1238 optname = SO_OOBINLINE;
1239 break;
1240 case TARGET_SO_NO_CHECK:
1241 optname = SO_NO_CHECK;
1242 break;
1243 case TARGET_SO_PRIORITY:
1244 optname = SO_PRIORITY;
1245 break;
bellard5e83e8e2005-03-01 22:32:06 +00001246#ifdef SO_BSDCOMPAT
bellard3532fa72006-06-24 15:06:03 +00001247 case TARGET_SO_BSDCOMPAT:
1248 optname = SO_BSDCOMPAT;
1249 break;
bellard5e83e8e2005-03-01 22:32:06 +00001250#endif
bellard3532fa72006-06-24 15:06:03 +00001251 case TARGET_SO_PASSCRED:
1252 optname = SO_PASSCRED;
1253 break;
1254 case TARGET_SO_TIMESTAMP:
1255 optname = SO_TIMESTAMP;
1256 break;
1257 case TARGET_SO_RCVLOWAT:
1258 optname = SO_RCVLOWAT;
1259 break;
1260 case TARGET_SO_RCVTIMEO:
1261 optname = SO_RCVTIMEO;
1262 break;
1263 case TARGET_SO_SNDTIMEO:
1264 optname = SO_SNDTIMEO;
1265 break;
bellard8853f862004-02-22 14:57:26 +00001266 break;
1267 default:
1268 goto unimplemented;
1269 }
bellard3532fa72006-06-24 15:06:03 +00001270 if (optlen < sizeof(uint32_t))
bellard2f619692007-11-16 10:46:05 +00001271 return -TARGET_EINVAL;
bellard3532fa72006-06-24 15:06:03 +00001272
bellard2f619692007-11-16 10:46:05 +00001273 if (get_user_u32(val, optval_addr))
1274 return -TARGET_EFAULT;
bellard3532fa72006-06-24 15:06:03 +00001275 ret = get_errno(setsockopt(sockfd, SOL_SOCKET, optname, &val, sizeof(val)));
bellard8853f862004-02-22 14:57:26 +00001276 break;
bellard7854b052003-03-29 17:22:23 +00001277 default:
bellard8853f862004-02-22 14:57:26 +00001278 unimplemented:
1279 gemu_log("Unsupported setsockopt level=%d optname=%d \n", level, optname);
ths6fa13c12007-12-18 02:41:04 +00001280 ret = -TARGET_ENOPROTOOPT;
bellard7854b052003-03-29 17:22:23 +00001281 }
bellard8853f862004-02-22 14:57:26 +00001282 return ret;
bellard7854b052003-03-29 17:22:23 +00001283}
1284
ths0da46a62007-10-20 20:23:07 +00001285/* do_getsockopt() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001286static abi_long do_getsockopt(int sockfd, int level, int optname,
bellard2f619692007-11-16 10:46:05 +00001287 abi_ulong optval_addr, abi_ulong optlen)
bellard7854b052003-03-29 17:22:23 +00001288{
blueswir1992f48a2007-10-14 16:27:31 +00001289 abi_long ret;
blueswir1b55266b2008-09-20 08:07:15 +00001290 int len, val;
1291 socklen_t lv;
bellard8853f862004-02-22 14:57:26 +00001292
1293 switch(level) {
bellard3532fa72006-06-24 15:06:03 +00001294 case TARGET_SOL_SOCKET:
1295 level = SOL_SOCKET;
bellard8853f862004-02-22 14:57:26 +00001296 switch (optname) {
bellard3532fa72006-06-24 15:06:03 +00001297 case TARGET_SO_LINGER:
1298 case TARGET_SO_RCVTIMEO:
1299 case TARGET_SO_SNDTIMEO:
1300 case TARGET_SO_PEERCRED:
1301 case TARGET_SO_PEERNAME:
bellard8853f862004-02-22 14:57:26 +00001302 /* These don't just return a single integer */
1303 goto unimplemented;
1304 default:
bellard2efbe912005-07-23 15:10:20 +00001305 goto int_case;
1306 }
1307 break;
1308 case SOL_TCP:
1309 /* TCP options all take an 'int' value. */
1310 int_case:
bellard2f619692007-11-16 10:46:05 +00001311 if (get_user_u32(len, optlen))
1312 return -TARGET_EFAULT;
bellard2efbe912005-07-23 15:10:20 +00001313 if (len < 0)
ths0da46a62007-10-20 20:23:07 +00001314 return -TARGET_EINVAL;
bellard2efbe912005-07-23 15:10:20 +00001315 lv = sizeof(int);
1316 ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
1317 if (ret < 0)
1318 return ret;
1319 val = tswap32(val);
1320 if (len > lv)
1321 len = lv;
bellard2f619692007-11-16 10:46:05 +00001322 if (len == 4) {
1323 if (put_user_u32(val, optval_addr))
1324 return -TARGET_EFAULT;
1325 } else {
1326 if (put_user_u8(val, optval_addr))
1327 return -TARGET_EFAULT;
1328 }
1329 if (put_user_u32(len, optlen))
1330 return -TARGET_EFAULT;
bellard2efbe912005-07-23 15:10:20 +00001331 break;
1332 case SOL_IP:
1333 switch(optname) {
1334 case IP_TOS:
1335 case IP_TTL:
1336 case IP_HDRINCL:
1337 case IP_ROUTER_ALERT:
1338 case IP_RECVOPTS:
1339 case IP_RETOPTS:
1340 case IP_PKTINFO:
1341 case IP_MTU_DISCOVER:
1342 case IP_RECVERR:
1343 case IP_RECVTOS:
1344#ifdef IP_FREEBIND
1345 case IP_FREEBIND:
1346#endif
1347 case IP_MULTICAST_TTL:
1348 case IP_MULTICAST_LOOP:
bellard2f619692007-11-16 10:46:05 +00001349 if (get_user_u32(len, optlen))
1350 return -TARGET_EFAULT;
bellard8853f862004-02-22 14:57:26 +00001351 if (len < 0)
ths0da46a62007-10-20 20:23:07 +00001352 return -TARGET_EINVAL;
bellard8853f862004-02-22 14:57:26 +00001353 lv = sizeof(int);
1354 ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
1355 if (ret < 0)
1356 return ret;
bellard2efbe912005-07-23 15:10:20 +00001357 if (len < sizeof(int) && len > 0 && val >= 0 && val < 255) {
bellard2efbe912005-07-23 15:10:20 +00001358 len = 1;
bellard2f619692007-11-16 10:46:05 +00001359 if (put_user_u32(len, optlen)
1360 || put_user_u8(val, optval_addr))
1361 return -TARGET_EFAULT;
bellard2efbe912005-07-23 15:10:20 +00001362 } else {
bellard2efbe912005-07-23 15:10:20 +00001363 if (len > sizeof(int))
1364 len = sizeof(int);
bellard2f619692007-11-16 10:46:05 +00001365 if (put_user_u32(len, optlen)
1366 || put_user_u32(val, optval_addr))
1367 return -TARGET_EFAULT;
bellard2efbe912005-07-23 15:10:20 +00001368 }
bellard8853f862004-02-22 14:57:26 +00001369 break;
bellard2efbe912005-07-23 15:10:20 +00001370 default:
thsc02f4992007-12-18 02:39:59 +00001371 ret = -TARGET_ENOPROTOOPT;
1372 break;
bellard8853f862004-02-22 14:57:26 +00001373 }
1374 break;
1375 default:
1376 unimplemented:
1377 gemu_log("getsockopt level=%d optname=%d not yet supported\n",
1378 level, optname);
thsc02f4992007-12-18 02:39:59 +00001379 ret = -TARGET_EOPNOTSUPP;
bellard8853f862004-02-22 14:57:26 +00001380 break;
1381 }
1382 return ret;
bellard7854b052003-03-29 17:22:23 +00001383}
1384
bellard579a97f2007-11-11 14:26:47 +00001385/* FIXME
1386 * lock_iovec()/unlock_iovec() have a return code of 0 for success where
1387 * other lock functions have a return code of 0 for failure.
1388 */
1389static abi_long lock_iovec(int type, struct iovec *vec, abi_ulong target_addr,
1390 int count, int copy)
pbrook53a59602006-03-25 19:31:22 +00001391{
1392 struct target_iovec *target_vec;
blueswir1992f48a2007-10-14 16:27:31 +00001393 abi_ulong base;
balrogd732dcb2008-10-28 10:21:03 +00001394 int i;
pbrook53a59602006-03-25 19:31:22 +00001395
bellard579a97f2007-11-11 14:26:47 +00001396 target_vec = lock_user(VERIFY_READ, target_addr, count * sizeof(struct target_iovec), 1);
1397 if (!target_vec)
1398 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00001399 for(i = 0;i < count; i++) {
1400 base = tswapl(target_vec[i].iov_base);
1401 vec[i].iov_len = tswapl(target_vec[i].iov_len);
bellard41df8412008-02-04 22:26:57 +00001402 if (vec[i].iov_len != 0) {
1403 vec[i].iov_base = lock_user(type, base, vec[i].iov_len, copy);
balrogd732dcb2008-10-28 10:21:03 +00001404 /* Don't check lock_user return value. We must call writev even
1405 if a element has invalid base address. */
bellard41df8412008-02-04 22:26:57 +00001406 } else {
1407 /* zero length pointer is ignored */
1408 vec[i].iov_base = NULL;
1409 }
pbrook53a59602006-03-25 19:31:22 +00001410 }
1411 unlock_user (target_vec, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00001412 return 0;
pbrook53a59602006-03-25 19:31:22 +00001413}
1414
bellard579a97f2007-11-11 14:26:47 +00001415static abi_long unlock_iovec(struct iovec *vec, abi_ulong target_addr,
1416 int count, int copy)
pbrook53a59602006-03-25 19:31:22 +00001417{
1418 struct target_iovec *target_vec;
blueswir1992f48a2007-10-14 16:27:31 +00001419 abi_ulong base;
pbrook53a59602006-03-25 19:31:22 +00001420 int i;
1421
bellard579a97f2007-11-11 14:26:47 +00001422 target_vec = lock_user(VERIFY_READ, target_addr, count * sizeof(struct target_iovec), 1);
1423 if (!target_vec)
1424 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00001425 for(i = 0;i < count; i++) {
balrogd732dcb2008-10-28 10:21:03 +00001426 if (target_vec[i].iov_base) {
1427 base = tswapl(target_vec[i].iov_base);
1428 unlock_user(vec[i].iov_base, base, copy ? vec[i].iov_len : 0);
1429 }
pbrook53a59602006-03-25 19:31:22 +00001430 }
1431 unlock_user (target_vec, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00001432
1433 return 0;
pbrook53a59602006-03-25 19:31:22 +00001434}
1435
ths0da46a62007-10-20 20:23:07 +00001436/* do_socket() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001437static abi_long do_socket(int domain, int type, int protocol)
bellard3532fa72006-06-24 15:06:03 +00001438{
1439#if defined(TARGET_MIPS)
1440 switch(type) {
1441 case TARGET_SOCK_DGRAM:
1442 type = SOCK_DGRAM;
1443 break;
1444 case TARGET_SOCK_STREAM:
1445 type = SOCK_STREAM;
1446 break;
1447 case TARGET_SOCK_RAW:
1448 type = SOCK_RAW;
1449 break;
1450 case TARGET_SOCK_RDM:
1451 type = SOCK_RDM;
1452 break;
1453 case TARGET_SOCK_SEQPACKET:
1454 type = SOCK_SEQPACKET;
1455 break;
1456 case TARGET_SOCK_PACKET:
1457 type = SOCK_PACKET;
1458 break;
1459 }
1460#endif
balrog12bc92a2007-10-30 21:06:14 +00001461 if (domain == PF_NETLINK)
1462 return -EAFNOSUPPORT; /* do not NETLINK socket connections possible */
bellard3532fa72006-06-24 15:06:03 +00001463 return get_errno(socket(domain, type, protocol));
1464}
1465
ths0da46a62007-10-20 20:23:07 +00001466/* do_bind() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001467static abi_long do_bind(int sockfd, abi_ulong target_addr,
1468 socklen_t addrlen)
bellard3532fa72006-06-24 15:06:03 +00001469{
aurel328f7aeaf2009-01-30 19:47:57 +00001470 void *addr;
1471
aurel32be09ac42009-04-15 16:12:06 +00001472 if (addrlen < 0)
aurel328f7aeaf2009-01-30 19:47:57 +00001473 return -TARGET_EINVAL;
1474
aurel32607175e2009-04-15 16:11:59 +00001475 addr = alloca(addrlen+1);
ths3b46e622007-09-17 08:09:54 +00001476
bellard3532fa72006-06-24 15:06:03 +00001477 target_to_host_sockaddr(addr, target_addr, addrlen);
1478 return get_errno(bind(sockfd, addr, addrlen));
1479}
1480
ths0da46a62007-10-20 20:23:07 +00001481/* do_connect() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001482static abi_long do_connect(int sockfd, abi_ulong target_addr,
1483 socklen_t addrlen)
bellard3532fa72006-06-24 15:06:03 +00001484{
aurel328f7aeaf2009-01-30 19:47:57 +00001485 void *addr;
1486
aurel32be09ac42009-04-15 16:12:06 +00001487 if (addrlen < 0)
aurel328f7aeaf2009-01-30 19:47:57 +00001488 return -TARGET_EINVAL;
1489
1490 addr = alloca(addrlen);
ths3b46e622007-09-17 08:09:54 +00001491
bellard3532fa72006-06-24 15:06:03 +00001492 target_to_host_sockaddr(addr, target_addr, addrlen);
1493 return get_errno(connect(sockfd, addr, addrlen));
1494}
1495
ths0da46a62007-10-20 20:23:07 +00001496/* do_sendrecvmsg() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001497static abi_long do_sendrecvmsg(int fd, abi_ulong target_msg,
1498 int flags, int send)
bellard3532fa72006-06-24 15:06:03 +00001499{
balrog6de645c2008-10-28 10:26:29 +00001500 abi_long ret, len;
bellard3532fa72006-06-24 15:06:03 +00001501 struct target_msghdr *msgp;
1502 struct msghdr msg;
1503 int count;
1504 struct iovec *vec;
blueswir1992f48a2007-10-14 16:27:31 +00001505 abi_ulong target_vec;
bellard3532fa72006-06-24 15:06:03 +00001506
bellard579a97f2007-11-11 14:26:47 +00001507 /* FIXME */
1508 if (!lock_user_struct(send ? VERIFY_READ : VERIFY_WRITE,
1509 msgp,
1510 target_msg,
1511 send ? 1 : 0))
1512 return -TARGET_EFAULT;
bellard3532fa72006-06-24 15:06:03 +00001513 if (msgp->msg_name) {
1514 msg.msg_namelen = tswap32(msgp->msg_namelen);
1515 msg.msg_name = alloca(msg.msg_namelen);
1516 target_to_host_sockaddr(msg.msg_name, tswapl(msgp->msg_name),
1517 msg.msg_namelen);
1518 } else {
1519 msg.msg_name = NULL;
1520 msg.msg_namelen = 0;
1521 }
1522 msg.msg_controllen = 2 * tswapl(msgp->msg_controllen);
1523 msg.msg_control = alloca(msg.msg_controllen);
1524 msg.msg_flags = tswap32(msgp->msg_flags);
ths3b46e622007-09-17 08:09:54 +00001525
bellard3532fa72006-06-24 15:06:03 +00001526 count = tswapl(msgp->msg_iovlen);
1527 vec = alloca(count * sizeof(struct iovec));
1528 target_vec = tswapl(msgp->msg_iov);
bellard579a97f2007-11-11 14:26:47 +00001529 lock_iovec(send ? VERIFY_READ : VERIFY_WRITE, vec, target_vec, count, send);
bellard3532fa72006-06-24 15:06:03 +00001530 msg.msg_iovlen = count;
1531 msg.msg_iov = vec;
ths3b46e622007-09-17 08:09:54 +00001532
bellard3532fa72006-06-24 15:06:03 +00001533 if (send) {
bellard5a4a8982007-11-11 17:39:18 +00001534 ret = target_to_host_cmsg(&msg, msgp);
1535 if (ret == 0)
1536 ret = get_errno(sendmsg(fd, &msg, flags));
bellard3532fa72006-06-24 15:06:03 +00001537 } else {
1538 ret = get_errno(recvmsg(fd, &msg, flags));
balrog6de645c2008-10-28 10:26:29 +00001539 if (!is_error(ret)) {
1540 len = ret;
bellard5a4a8982007-11-11 17:39:18 +00001541 ret = host_to_target_cmsg(msgp, &msg);
balrog6de645c2008-10-28 10:26:29 +00001542 if (!is_error(ret))
1543 ret = len;
1544 }
bellard3532fa72006-06-24 15:06:03 +00001545 }
1546 unlock_iovec(vec, target_vec, count, !send);
bellard579a97f2007-11-11 14:26:47 +00001547 unlock_user_struct(msgp, target_msg, send ? 0 : 1);
bellard3532fa72006-06-24 15:06:03 +00001548 return ret;
1549}
1550
ths0da46a62007-10-20 20:23:07 +00001551/* do_accept() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001552static abi_long do_accept(int fd, abi_ulong target_addr,
bellard2f619692007-11-16 10:46:05 +00001553 abi_ulong target_addrlen_addr)
pbrook1be9e1d2006-11-19 15:26:04 +00001554{
bellard2f619692007-11-16 10:46:05 +00001555 socklen_t addrlen;
1556 void *addr;
blueswir1992f48a2007-10-14 16:27:31 +00001557 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00001558
bellard2f619692007-11-16 10:46:05 +00001559 if (get_user_u32(addrlen, target_addrlen_addr))
1560 return -TARGET_EFAULT;
1561
aurel32be09ac42009-04-15 16:12:06 +00001562 if (addrlen < 0)
aurel328f7aeaf2009-01-30 19:47:57 +00001563 return -TARGET_EINVAL;
1564
bellard2f619692007-11-16 10:46:05 +00001565 addr = alloca(addrlen);
1566
pbrook1be9e1d2006-11-19 15:26:04 +00001567 ret = get_errno(accept(fd, addr, &addrlen));
1568 if (!is_error(ret)) {
1569 host_to_target_sockaddr(target_addr, addr, addrlen);
bellard2f619692007-11-16 10:46:05 +00001570 if (put_user_u32(addrlen, target_addrlen_addr))
1571 ret = -TARGET_EFAULT;
pbrook1be9e1d2006-11-19 15:26:04 +00001572 }
1573 return ret;
1574}
1575
ths0da46a62007-10-20 20:23:07 +00001576/* do_getpeername() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001577static abi_long do_getpeername(int fd, abi_ulong target_addr,
bellard2f619692007-11-16 10:46:05 +00001578 abi_ulong target_addrlen_addr)
pbrook1be9e1d2006-11-19 15:26:04 +00001579{
bellard2f619692007-11-16 10:46:05 +00001580 socklen_t addrlen;
1581 void *addr;
blueswir1992f48a2007-10-14 16:27:31 +00001582 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00001583
bellard2f619692007-11-16 10:46:05 +00001584 if (get_user_u32(addrlen, target_addrlen_addr))
1585 return -TARGET_EFAULT;
1586
aurel32be09ac42009-04-15 16:12:06 +00001587 if (addrlen < 0)
aurel328f7aeaf2009-01-30 19:47:57 +00001588 return -TARGET_EINVAL;
1589
bellard2f619692007-11-16 10:46:05 +00001590 addr = alloca(addrlen);
1591
pbrook1be9e1d2006-11-19 15:26:04 +00001592 ret = get_errno(getpeername(fd, addr, &addrlen));
1593 if (!is_error(ret)) {
1594 host_to_target_sockaddr(target_addr, addr, addrlen);
bellard2f619692007-11-16 10:46:05 +00001595 if (put_user_u32(addrlen, target_addrlen_addr))
1596 ret = -TARGET_EFAULT;
pbrook1be9e1d2006-11-19 15:26:04 +00001597 }
1598 return ret;
1599}
1600
ths0da46a62007-10-20 20:23:07 +00001601/* do_getsockname() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001602static abi_long do_getsockname(int fd, abi_ulong target_addr,
bellard2f619692007-11-16 10:46:05 +00001603 abi_ulong target_addrlen_addr)
pbrook1be9e1d2006-11-19 15:26:04 +00001604{
bellard2f619692007-11-16 10:46:05 +00001605 socklen_t addrlen;
1606 void *addr;
blueswir1992f48a2007-10-14 16:27:31 +00001607 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00001608
aurel328fea3602009-01-30 19:47:47 +00001609 if (target_addr == 0)
1610 return get_errno(accept(fd, NULL, NULL));
1611
bellard2f619692007-11-16 10:46:05 +00001612 if (get_user_u32(addrlen, target_addrlen_addr))
1613 return -TARGET_EFAULT;
1614
aurel32be09ac42009-04-15 16:12:06 +00001615 if (addrlen < 0)
aurel328f7aeaf2009-01-30 19:47:57 +00001616 return -TARGET_EINVAL;
1617
bellard2f619692007-11-16 10:46:05 +00001618 addr = alloca(addrlen);
1619
pbrook1be9e1d2006-11-19 15:26:04 +00001620 ret = get_errno(getsockname(fd, addr, &addrlen));
1621 if (!is_error(ret)) {
1622 host_to_target_sockaddr(target_addr, addr, addrlen);
bellard2f619692007-11-16 10:46:05 +00001623 if (put_user_u32(addrlen, target_addrlen_addr))
1624 ret = -TARGET_EFAULT;
pbrook1be9e1d2006-11-19 15:26:04 +00001625 }
1626 return ret;
1627}
1628
ths0da46a62007-10-20 20:23:07 +00001629/* do_socketpair() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001630static abi_long do_socketpair(int domain, int type, int protocol,
bellard2f619692007-11-16 10:46:05 +00001631 abi_ulong target_tab_addr)
pbrook1be9e1d2006-11-19 15:26:04 +00001632{
1633 int tab[2];
blueswir1992f48a2007-10-14 16:27:31 +00001634 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00001635
1636 ret = get_errno(socketpair(domain, type, protocol, tab));
1637 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +00001638 if (put_user_s32(tab[0], target_tab_addr)
1639 || put_user_s32(tab[1], target_tab_addr + sizeof(tab[0])))
1640 ret = -TARGET_EFAULT;
pbrook1be9e1d2006-11-19 15:26:04 +00001641 }
1642 return ret;
1643}
1644
ths0da46a62007-10-20 20:23:07 +00001645/* do_sendto() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001646static abi_long do_sendto(int fd, abi_ulong msg, size_t len, int flags,
1647 abi_ulong target_addr, socklen_t addrlen)
pbrook1be9e1d2006-11-19 15:26:04 +00001648{
1649 void *addr;
1650 void *host_msg;
blueswir1992f48a2007-10-14 16:27:31 +00001651 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00001652
aurel32be09ac42009-04-15 16:12:06 +00001653 if (addrlen < 0)
aurel328f7aeaf2009-01-30 19:47:57 +00001654 return -TARGET_EINVAL;
1655
bellard579a97f2007-11-11 14:26:47 +00001656 host_msg = lock_user(VERIFY_READ, msg, len, 1);
1657 if (!host_msg)
1658 return -TARGET_EFAULT;
pbrook1be9e1d2006-11-19 15:26:04 +00001659 if (target_addr) {
1660 addr = alloca(addrlen);
1661 target_to_host_sockaddr(addr, target_addr, addrlen);
1662 ret = get_errno(sendto(fd, host_msg, len, flags, addr, addrlen));
1663 } else {
1664 ret = get_errno(send(fd, host_msg, len, flags));
1665 }
1666 unlock_user(host_msg, msg, 0);
1667 return ret;
1668}
1669
ths0da46a62007-10-20 20:23:07 +00001670/* do_recvfrom() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001671static abi_long do_recvfrom(int fd, abi_ulong msg, size_t len, int flags,
1672 abi_ulong target_addr,
1673 abi_ulong target_addrlen)
pbrook1be9e1d2006-11-19 15:26:04 +00001674{
1675 socklen_t addrlen;
1676 void *addr;
1677 void *host_msg;
blueswir1992f48a2007-10-14 16:27:31 +00001678 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00001679
bellard579a97f2007-11-11 14:26:47 +00001680 host_msg = lock_user(VERIFY_WRITE, msg, len, 0);
1681 if (!host_msg)
1682 return -TARGET_EFAULT;
pbrook1be9e1d2006-11-19 15:26:04 +00001683 if (target_addr) {
bellard2f619692007-11-16 10:46:05 +00001684 if (get_user_u32(addrlen, target_addrlen)) {
1685 ret = -TARGET_EFAULT;
1686 goto fail;
1687 }
aurel32be09ac42009-04-15 16:12:06 +00001688 if (addrlen < 0) {
aurel328f7aeaf2009-01-30 19:47:57 +00001689 ret = -TARGET_EINVAL;
1690 goto fail;
1691 }
pbrook1be9e1d2006-11-19 15:26:04 +00001692 addr = alloca(addrlen);
1693 ret = get_errno(recvfrom(fd, host_msg, len, flags, addr, &addrlen));
1694 } else {
1695 addr = NULL; /* To keep compiler quiet. */
1696 ret = get_errno(recv(fd, host_msg, len, flags));
1697 }
1698 if (!is_error(ret)) {
1699 if (target_addr) {
1700 host_to_target_sockaddr(target_addr, addr, addrlen);
bellard2f619692007-11-16 10:46:05 +00001701 if (put_user_u32(addrlen, target_addrlen)) {
1702 ret = -TARGET_EFAULT;
1703 goto fail;
1704 }
pbrook1be9e1d2006-11-19 15:26:04 +00001705 }
1706 unlock_user(host_msg, msg, len);
1707 } else {
bellard2f619692007-11-16 10:46:05 +00001708fail:
pbrook1be9e1d2006-11-19 15:26:04 +00001709 unlock_user(host_msg, msg, 0);
1710 }
1711 return ret;
1712}
1713
j_mayer32407102007-09-26 23:01:49 +00001714#ifdef TARGET_NR_socketcall
ths0da46a62007-10-20 20:23:07 +00001715/* do_socketcall() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001716static abi_long do_socketcall(int num, abi_ulong vptr)
bellard31e31b82003-02-18 22:55:36 +00001717{
blueswir1992f48a2007-10-14 16:27:31 +00001718 abi_long ret;
1719 const int n = sizeof(abi_ulong);
bellard31e31b82003-02-18 22:55:36 +00001720
1721 switch(num) {
1722 case SOCKOP_socket:
bellard7854b052003-03-29 17:22:23 +00001723 {
bellard2f619692007-11-16 10:46:05 +00001724 int domain, type, protocol;
1725
1726 if (get_user_s32(domain, vptr)
1727 || get_user_s32(type, vptr + n)
1728 || get_user_s32(protocol, vptr + 2 * n))
1729 return -TARGET_EFAULT;
1730
bellard3532fa72006-06-24 15:06:03 +00001731 ret = do_socket(domain, type, protocol);
bellard7854b052003-03-29 17:22:23 +00001732 }
bellard31e31b82003-02-18 22:55:36 +00001733 break;
1734 case SOCKOP_bind:
bellard7854b052003-03-29 17:22:23 +00001735 {
bellard2f619692007-11-16 10:46:05 +00001736 int sockfd;
1737 abi_ulong target_addr;
1738 socklen_t addrlen;
1739
1740 if (get_user_s32(sockfd, vptr)
1741 || get_user_ual(target_addr, vptr + n)
1742 || get_user_u32(addrlen, vptr + 2 * n))
1743 return -TARGET_EFAULT;
1744
bellard3532fa72006-06-24 15:06:03 +00001745 ret = do_bind(sockfd, target_addr, addrlen);
bellard7854b052003-03-29 17:22:23 +00001746 }
bellard31e31b82003-02-18 22:55:36 +00001747 break;
1748 case SOCKOP_connect:
bellard7854b052003-03-29 17:22:23 +00001749 {
bellard2f619692007-11-16 10:46:05 +00001750 int sockfd;
1751 abi_ulong target_addr;
1752 socklen_t addrlen;
1753
1754 if (get_user_s32(sockfd, vptr)
1755 || get_user_ual(target_addr, vptr + n)
1756 || get_user_u32(addrlen, vptr + 2 * n))
1757 return -TARGET_EFAULT;
1758
bellard3532fa72006-06-24 15:06:03 +00001759 ret = do_connect(sockfd, target_addr, addrlen);
bellard7854b052003-03-29 17:22:23 +00001760 }
bellard31e31b82003-02-18 22:55:36 +00001761 break;
1762 case SOCKOP_listen:
bellard7854b052003-03-29 17:22:23 +00001763 {
bellard2f619692007-11-16 10:46:05 +00001764 int sockfd, backlog;
1765
1766 if (get_user_s32(sockfd, vptr)
1767 || get_user_s32(backlog, vptr + n))
1768 return -TARGET_EFAULT;
1769
bellard7854b052003-03-29 17:22:23 +00001770 ret = get_errno(listen(sockfd, backlog));
1771 }
bellard31e31b82003-02-18 22:55:36 +00001772 break;
1773 case SOCKOP_accept:
1774 {
bellard2f619692007-11-16 10:46:05 +00001775 int sockfd;
1776 abi_ulong target_addr, target_addrlen;
1777
1778 if (get_user_s32(sockfd, vptr)
1779 || get_user_ual(target_addr, vptr + n)
1780 || get_user_u32(target_addrlen, vptr + 2 * n))
1781 return -TARGET_EFAULT;
1782
pbrook1be9e1d2006-11-19 15:26:04 +00001783 ret = do_accept(sockfd, target_addr, target_addrlen);
bellard31e31b82003-02-18 22:55:36 +00001784 }
1785 break;
1786 case SOCKOP_getsockname:
1787 {
bellard2f619692007-11-16 10:46:05 +00001788 int sockfd;
1789 abi_ulong target_addr, target_addrlen;
1790
1791 if (get_user_s32(sockfd, vptr)
1792 || get_user_ual(target_addr, vptr + n)
1793 || get_user_u32(target_addrlen, vptr + 2 * n))
1794 return -TARGET_EFAULT;
1795
pbrook1be9e1d2006-11-19 15:26:04 +00001796 ret = do_getsockname(sockfd, target_addr, target_addrlen);
bellard31e31b82003-02-18 22:55:36 +00001797 }
1798 break;
1799 case SOCKOP_getpeername:
1800 {
bellard2f619692007-11-16 10:46:05 +00001801 int sockfd;
1802 abi_ulong target_addr, target_addrlen;
1803
1804 if (get_user_s32(sockfd, vptr)
1805 || get_user_ual(target_addr, vptr + n)
1806 || get_user_u32(target_addrlen, vptr + 2 * n))
1807 return -TARGET_EFAULT;
1808
pbrook1be9e1d2006-11-19 15:26:04 +00001809 ret = do_getpeername(sockfd, target_addr, target_addrlen);
bellard31e31b82003-02-18 22:55:36 +00001810 }
1811 break;
1812 case SOCKOP_socketpair:
1813 {
bellard2f619692007-11-16 10:46:05 +00001814 int domain, type, protocol;
1815 abi_ulong tab;
1816
1817 if (get_user_s32(domain, vptr)
1818 || get_user_s32(type, vptr + n)
1819 || get_user_s32(protocol, vptr + 2 * n)
1820 || get_user_ual(tab, vptr + 3 * n))
1821 return -TARGET_EFAULT;
1822
pbrook1be9e1d2006-11-19 15:26:04 +00001823 ret = do_socketpair(domain, type, protocol, tab);
bellard31e31b82003-02-18 22:55:36 +00001824 }
1825 break;
1826 case SOCKOP_send:
bellard7854b052003-03-29 17:22:23 +00001827 {
bellard2f619692007-11-16 10:46:05 +00001828 int sockfd;
1829 abi_ulong msg;
1830 size_t len;
1831 int flags;
1832
1833 if (get_user_s32(sockfd, vptr)
1834 || get_user_ual(msg, vptr + n)
1835 || get_user_ual(len, vptr + 2 * n)
1836 || get_user_s32(flags, vptr + 3 * n))
1837 return -TARGET_EFAULT;
1838
pbrook1be9e1d2006-11-19 15:26:04 +00001839 ret = do_sendto(sockfd, msg, len, flags, 0, 0);
bellard7854b052003-03-29 17:22:23 +00001840 }
bellard31e31b82003-02-18 22:55:36 +00001841 break;
1842 case SOCKOP_recv:
bellard7854b052003-03-29 17:22:23 +00001843 {
bellard2f619692007-11-16 10:46:05 +00001844 int sockfd;
1845 abi_ulong msg;
1846 size_t len;
1847 int flags;
1848
1849 if (get_user_s32(sockfd, vptr)
1850 || get_user_ual(msg, vptr + n)
1851 || get_user_ual(len, vptr + 2 * n)
1852 || get_user_s32(flags, vptr + 3 * n))
1853 return -TARGET_EFAULT;
1854
pbrook1be9e1d2006-11-19 15:26:04 +00001855 ret = do_recvfrom(sockfd, msg, len, flags, 0, 0);
bellard7854b052003-03-29 17:22:23 +00001856 }
bellard31e31b82003-02-18 22:55:36 +00001857 break;
1858 case SOCKOP_sendto:
bellard7854b052003-03-29 17:22:23 +00001859 {
bellard2f619692007-11-16 10:46:05 +00001860 int sockfd;
1861 abi_ulong msg;
1862 size_t len;
1863 int flags;
1864 abi_ulong addr;
1865 socklen_t addrlen;
1866
1867 if (get_user_s32(sockfd, vptr)
1868 || get_user_ual(msg, vptr + n)
1869 || get_user_ual(len, vptr + 2 * n)
1870 || get_user_s32(flags, vptr + 3 * n)
1871 || get_user_ual(addr, vptr + 4 * n)
1872 || get_user_u32(addrlen, vptr + 5 * n))
1873 return -TARGET_EFAULT;
1874
pbrook1be9e1d2006-11-19 15:26:04 +00001875 ret = do_sendto(sockfd, msg, len, flags, addr, addrlen);
bellard7854b052003-03-29 17:22:23 +00001876 }
bellard31e31b82003-02-18 22:55:36 +00001877 break;
1878 case SOCKOP_recvfrom:
1879 {
bellard2f619692007-11-16 10:46:05 +00001880 int sockfd;
1881 abi_ulong msg;
1882 size_t len;
1883 int flags;
1884 abi_ulong addr;
1885 socklen_t addrlen;
1886
1887 if (get_user_s32(sockfd, vptr)
1888 || get_user_ual(msg, vptr + n)
1889 || get_user_ual(len, vptr + 2 * n)
1890 || get_user_s32(flags, vptr + 3 * n)
1891 || get_user_ual(addr, vptr + 4 * n)
1892 || get_user_u32(addrlen, vptr + 5 * n))
1893 return -TARGET_EFAULT;
1894
pbrook1be9e1d2006-11-19 15:26:04 +00001895 ret = do_recvfrom(sockfd, msg, len, flags, addr, addrlen);
bellard31e31b82003-02-18 22:55:36 +00001896 }
1897 break;
1898 case SOCKOP_shutdown:
bellard7854b052003-03-29 17:22:23 +00001899 {
bellard2f619692007-11-16 10:46:05 +00001900 int sockfd, how;
1901
1902 if (get_user_s32(sockfd, vptr)
1903 || get_user_s32(how, vptr + n))
1904 return -TARGET_EFAULT;
bellard7854b052003-03-29 17:22:23 +00001905
1906 ret = get_errno(shutdown(sockfd, how));
1907 }
bellard31e31b82003-02-18 22:55:36 +00001908 break;
1909 case SOCKOP_sendmsg:
1910 case SOCKOP_recvmsg:
bellard1a9353d2003-03-16 20:28:50 +00001911 {
1912 int fd;
blueswir1992f48a2007-10-14 16:27:31 +00001913 abi_ulong target_msg;
bellard3532fa72006-06-24 15:06:03 +00001914 int flags;
bellard1a9353d2003-03-16 20:28:50 +00001915
bellard2f619692007-11-16 10:46:05 +00001916 if (get_user_s32(fd, vptr)
1917 || get_user_ual(target_msg, vptr + n)
1918 || get_user_s32(flags, vptr + 2 * n))
1919 return -TARGET_EFAULT;
bellard3532fa72006-06-24 15:06:03 +00001920
ths5fafdf22007-09-16 21:08:06 +00001921 ret = do_sendrecvmsg(fd, target_msg, flags,
bellard3532fa72006-06-24 15:06:03 +00001922 (num == SOCKOP_sendmsg));
bellard1a9353d2003-03-16 20:28:50 +00001923 }
1924 break;
bellard31e31b82003-02-18 22:55:36 +00001925 case SOCKOP_setsockopt:
bellard7854b052003-03-29 17:22:23 +00001926 {
bellard2f619692007-11-16 10:46:05 +00001927 int sockfd;
1928 int level;
1929 int optname;
1930 abi_ulong optval;
1931 socklen_t optlen;
1932
1933 if (get_user_s32(sockfd, vptr)
1934 || get_user_s32(level, vptr + n)
1935 || get_user_s32(optname, vptr + 2 * n)
1936 || get_user_ual(optval, vptr + 3 * n)
1937 || get_user_u32(optlen, vptr + 4 * n))
1938 return -TARGET_EFAULT;
bellard7854b052003-03-29 17:22:23 +00001939
1940 ret = do_setsockopt(sockfd, level, optname, optval, optlen);
1941 }
1942 break;
bellard31e31b82003-02-18 22:55:36 +00001943 case SOCKOP_getsockopt:
bellard7854b052003-03-29 17:22:23 +00001944 {
bellard2f619692007-11-16 10:46:05 +00001945 int sockfd;
1946 int level;
1947 int optname;
1948 abi_ulong optval;
1949 socklen_t optlen;
bellard7854b052003-03-29 17:22:23 +00001950
bellard2f619692007-11-16 10:46:05 +00001951 if (get_user_s32(sockfd, vptr)
1952 || get_user_s32(level, vptr + n)
1953 || get_user_s32(optname, vptr + 2 * n)
1954 || get_user_ual(optval, vptr + 3 * n)
1955 || get_user_u32(optlen, vptr + 4 * n))
1956 return -TARGET_EFAULT;
1957
1958 ret = do_getsockopt(sockfd, level, optname, optval, optlen);
bellard7854b052003-03-29 17:22:23 +00001959 }
1960 break;
bellard31e31b82003-02-18 22:55:36 +00001961 default:
1962 gemu_log("Unsupported socketcall: %d\n", num);
ths0da46a62007-10-20 20:23:07 +00001963 ret = -TARGET_ENOSYS;
bellard31e31b82003-02-18 22:55:36 +00001964 break;
1965 }
1966 return ret;
1967}
j_mayer32407102007-09-26 23:01:49 +00001968#endif
bellard31e31b82003-02-18 22:55:36 +00001969
bellard8853f862004-02-22 14:57:26 +00001970#define N_SHM_REGIONS 32
1971
1972static struct shm_region {
bellard5a4a8982007-11-11 17:39:18 +00001973 abi_ulong start;
1974 abi_ulong size;
bellard8853f862004-02-22 14:57:26 +00001975} shm_regions[N_SHM_REGIONS];
1976
ths3eb6b042007-06-03 14:26:27 +00001977struct target_ipc_perm
1978{
blueswir1992f48a2007-10-14 16:27:31 +00001979 abi_long __key;
1980 abi_ulong uid;
1981 abi_ulong gid;
1982 abi_ulong cuid;
1983 abi_ulong cgid;
ths3eb6b042007-06-03 14:26:27 +00001984 unsigned short int mode;
1985 unsigned short int __pad1;
1986 unsigned short int __seq;
1987 unsigned short int __pad2;
blueswir1992f48a2007-10-14 16:27:31 +00001988 abi_ulong __unused1;
1989 abi_ulong __unused2;
ths3eb6b042007-06-03 14:26:27 +00001990};
1991
1992struct target_semid_ds
1993{
1994 struct target_ipc_perm sem_perm;
blueswir1992f48a2007-10-14 16:27:31 +00001995 abi_ulong sem_otime;
1996 abi_ulong __unused1;
1997 abi_ulong sem_ctime;
1998 abi_ulong __unused2;
1999 abi_ulong sem_nsems;
2000 abi_ulong __unused3;
2001 abi_ulong __unused4;
ths3eb6b042007-06-03 14:26:27 +00002002};
2003
bellard579a97f2007-11-11 14:26:47 +00002004static inline abi_long target_to_host_ipc_perm(struct ipc_perm *host_ip,
2005 abi_ulong target_addr)
ths3eb6b042007-06-03 14:26:27 +00002006{
2007 struct target_ipc_perm *target_ip;
2008 struct target_semid_ds *target_sd;
2009
bellard579a97f2007-11-11 14:26:47 +00002010 if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
2011 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00002012 target_ip=&(target_sd->sem_perm);
2013 host_ip->__key = tswapl(target_ip->__key);
2014 host_ip->uid = tswapl(target_ip->uid);
2015 host_ip->gid = tswapl(target_ip->gid);
2016 host_ip->cuid = tswapl(target_ip->cuid);
2017 host_ip->cgid = tswapl(target_ip->cgid);
2018 host_ip->mode = tswapl(target_ip->mode);
2019 unlock_user_struct(target_sd, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00002020 return 0;
ths3eb6b042007-06-03 14:26:27 +00002021}
2022
bellard579a97f2007-11-11 14:26:47 +00002023static inline abi_long host_to_target_ipc_perm(abi_ulong target_addr,
2024 struct ipc_perm *host_ip)
ths3eb6b042007-06-03 14:26:27 +00002025{
2026 struct target_ipc_perm *target_ip;
2027 struct target_semid_ds *target_sd;
2028
bellard579a97f2007-11-11 14:26:47 +00002029 if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
2030 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00002031 target_ip = &(target_sd->sem_perm);
2032 target_ip->__key = tswapl(host_ip->__key);
2033 target_ip->uid = tswapl(host_ip->uid);
2034 target_ip->gid = tswapl(host_ip->gid);
2035 target_ip->cuid = tswapl(host_ip->cuid);
2036 target_ip->cgid = tswapl(host_ip->cgid);
2037 target_ip->mode = tswapl(host_ip->mode);
2038 unlock_user_struct(target_sd, target_addr, 1);
bellard579a97f2007-11-11 14:26:47 +00002039 return 0;
ths3eb6b042007-06-03 14:26:27 +00002040}
2041
bellard579a97f2007-11-11 14:26:47 +00002042static inline abi_long target_to_host_semid_ds(struct semid_ds *host_sd,
2043 abi_ulong target_addr)
ths3eb6b042007-06-03 14:26:27 +00002044{
2045 struct target_semid_ds *target_sd;
2046
bellard579a97f2007-11-11 14:26:47 +00002047 if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
2048 return -TARGET_EFAULT;
aurel32e5289082009-04-18 16:16:12 +00002049 if (target_to_host_ipc_perm(&(host_sd->sem_perm),target_addr))
2050 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00002051 host_sd->sem_nsems = tswapl(target_sd->sem_nsems);
2052 host_sd->sem_otime = tswapl(target_sd->sem_otime);
2053 host_sd->sem_ctime = tswapl(target_sd->sem_ctime);
2054 unlock_user_struct(target_sd, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00002055 return 0;
ths3eb6b042007-06-03 14:26:27 +00002056}
2057
bellard579a97f2007-11-11 14:26:47 +00002058static inline abi_long host_to_target_semid_ds(abi_ulong target_addr,
2059 struct semid_ds *host_sd)
ths3eb6b042007-06-03 14:26:27 +00002060{
2061 struct target_semid_ds *target_sd;
2062
bellard579a97f2007-11-11 14:26:47 +00002063 if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
2064 return -TARGET_EFAULT;
aurel32e5289082009-04-18 16:16:12 +00002065 if (host_to_target_ipc_perm(target_addr,&(host_sd->sem_perm)))
2066 return -TARGET_EFAULT;;
ths3eb6b042007-06-03 14:26:27 +00002067 target_sd->sem_nsems = tswapl(host_sd->sem_nsems);
2068 target_sd->sem_otime = tswapl(host_sd->sem_otime);
2069 target_sd->sem_ctime = tswapl(host_sd->sem_ctime);
2070 unlock_user_struct(target_sd, target_addr, 1);
bellard579a97f2007-11-11 14:26:47 +00002071 return 0;
ths3eb6b042007-06-03 14:26:27 +00002072}
2073
aurel32e5289082009-04-18 16:16:12 +00002074struct target_seminfo {
2075 int semmap;
2076 int semmni;
2077 int semmns;
2078 int semmnu;
2079 int semmsl;
2080 int semopm;
2081 int semume;
2082 int semusz;
2083 int semvmx;
2084 int semaem;
2085};
2086
2087static inline abi_long host_to_target_seminfo(abi_ulong target_addr,
2088 struct seminfo *host_seminfo)
2089{
2090 struct target_seminfo *target_seminfo;
2091 if (!lock_user_struct(VERIFY_WRITE, target_seminfo, target_addr, 0))
2092 return -TARGET_EFAULT;
2093 __put_user(host_seminfo->semmap, &target_seminfo->semmap);
2094 __put_user(host_seminfo->semmni, &target_seminfo->semmni);
2095 __put_user(host_seminfo->semmns, &target_seminfo->semmns);
2096 __put_user(host_seminfo->semmnu, &target_seminfo->semmnu);
2097 __put_user(host_seminfo->semmsl, &target_seminfo->semmsl);
2098 __put_user(host_seminfo->semopm, &target_seminfo->semopm);
2099 __put_user(host_seminfo->semume, &target_seminfo->semume);
2100 __put_user(host_seminfo->semusz, &target_seminfo->semusz);
2101 __put_user(host_seminfo->semvmx, &target_seminfo->semvmx);
2102 __put_user(host_seminfo->semaem, &target_seminfo->semaem);
2103 unlock_user_struct(target_seminfo, target_addr, 1);
2104 return 0;
2105}
2106
thsfa294812007-02-02 22:05:00 +00002107union semun {
2108 int val;
ths3eb6b042007-06-03 14:26:27 +00002109 struct semid_ds *buf;
thsfa294812007-02-02 22:05:00 +00002110 unsigned short *array;
aurel32e5289082009-04-18 16:16:12 +00002111 struct seminfo *__buf;
thsfa294812007-02-02 22:05:00 +00002112};
2113
ths3eb6b042007-06-03 14:26:27 +00002114union target_semun {
2115 int val;
aurel32e5289082009-04-18 16:16:12 +00002116 abi_ulong buf;
2117 abi_ulong array;
2118 abi_ulong __buf;
ths3eb6b042007-06-03 14:26:27 +00002119};
2120
aurel32e5289082009-04-18 16:16:12 +00002121static inline abi_long target_to_host_semarray(int semid, unsigned short **host_array,
2122 abi_ulong target_addr)
ths3eb6b042007-06-03 14:26:27 +00002123{
aurel32e5289082009-04-18 16:16:12 +00002124 int nsems;
2125 unsigned short *array;
2126 union semun semun;
2127 struct semid_ds semid_ds;
2128 int i, ret;
ths3eb6b042007-06-03 14:26:27 +00002129
aurel32e5289082009-04-18 16:16:12 +00002130 semun.buf = &semid_ds;
2131
2132 ret = semctl(semid, 0, IPC_STAT, semun);
2133 if (ret == -1)
2134 return get_errno(ret);
2135
2136 nsems = semid_ds.sem_nsems;
2137
2138 *host_array = malloc(nsems*sizeof(unsigned short));
2139 array = lock_user(VERIFY_READ, target_addr,
2140 nsems*sizeof(unsigned short), 1);
2141 if (!array)
2142 return -TARGET_EFAULT;
2143
2144 for(i=0; i<nsems; i++) {
2145 __get_user((*host_array)[i], &array[i]);
ths3eb6b042007-06-03 14:26:27 +00002146 }
aurel32e5289082009-04-18 16:16:12 +00002147 unlock_user(array, target_addr, 0);
2148
bellard579a97f2007-11-11 14:26:47 +00002149 return 0;
ths3eb6b042007-06-03 14:26:27 +00002150}
2151
aurel32e5289082009-04-18 16:16:12 +00002152static inline abi_long host_to_target_semarray(int semid, abi_ulong target_addr,
2153 unsigned short **host_array)
ths3eb6b042007-06-03 14:26:27 +00002154{
aurel32e5289082009-04-18 16:16:12 +00002155 int nsems;
2156 unsigned short *array;
2157 union semun semun;
2158 struct semid_ds semid_ds;
2159 int i, ret;
ths3eb6b042007-06-03 14:26:27 +00002160
aurel32e5289082009-04-18 16:16:12 +00002161 semun.buf = &semid_ds;
2162
2163 ret = semctl(semid, 0, IPC_STAT, semun);
2164 if (ret == -1)
2165 return get_errno(ret);
2166
2167 nsems = semid_ds.sem_nsems;
2168
2169 array = lock_user(VERIFY_WRITE, target_addr,
2170 nsems*sizeof(unsigned short), 0);
2171 if (!array)
2172 return -TARGET_EFAULT;
2173
2174 for(i=0; i<nsems; i++) {
2175 __put_user((*host_array)[i], &array[i]);
ths3eb6b042007-06-03 14:26:27 +00002176 }
aurel32e5289082009-04-18 16:16:12 +00002177 free(*host_array);
2178 unlock_user(array, target_addr, 1);
2179
bellard579a97f2007-11-11 14:26:47 +00002180 return 0;
ths3eb6b042007-06-03 14:26:27 +00002181}
2182
aurel32e5289082009-04-18 16:16:12 +00002183static inline abi_long do_semctl(int semid, int semnum, int cmd,
2184 union target_semun target_su)
ths3eb6b042007-06-03 14:26:27 +00002185{
2186 union semun arg;
2187 struct semid_ds dsarg;
aurel32e5289082009-04-18 16:16:12 +00002188 unsigned short *array;
2189 struct seminfo seminfo;
2190 abi_long ret = -TARGET_EINVAL;
2191 abi_long err;
2192 cmd &= 0xff;
ths3eb6b042007-06-03 14:26:27 +00002193
2194 switch( cmd ) {
2195 case GETVAL:
ths3eb6b042007-06-03 14:26:27 +00002196 case SETVAL:
aurel32e5289082009-04-18 16:16:12 +00002197 arg.val = tswapl(target_su.val);
2198 ret = get_errno(semctl(semid, semnum, cmd, arg));
2199 target_su.val = tswapl(arg.val);
ths3eb6b042007-06-03 14:26:27 +00002200 break;
2201 case GETALL:
ths3eb6b042007-06-03 14:26:27 +00002202 case SETALL:
aurel32e5289082009-04-18 16:16:12 +00002203 err = target_to_host_semarray(semid, &array, target_su.array);
2204 if (err)
2205 return err;
2206 arg.array = array;
2207 ret = get_errno(semctl(semid, semnum, cmd, arg));
2208 err = host_to_target_semarray(semid, target_su.array, &array);
2209 if (err)
2210 return err;
ths3eb6b042007-06-03 14:26:27 +00002211 break;
2212 case IPC_STAT:
ths3eb6b042007-06-03 14:26:27 +00002213 case IPC_SET:
aurel32e5289082009-04-18 16:16:12 +00002214 case SEM_STAT:
2215 err = target_to_host_semid_ds(&dsarg, target_su.buf);
2216 if (err)
2217 return err;
2218 arg.buf = &dsarg;
2219 ret = get_errno(semctl(semid, semnum, cmd, arg));
2220 err = host_to_target_semid_ds(target_su.buf, &dsarg);
2221 if (err)
2222 return err;
ths3eb6b042007-06-03 14:26:27 +00002223 break;
aurel32e5289082009-04-18 16:16:12 +00002224 case IPC_INFO:
2225 case SEM_INFO:
2226 arg.__buf = &seminfo;
2227 ret = get_errno(semctl(semid, semnum, cmd, arg));
2228 err = host_to_target_seminfo(target_su.__buf, &seminfo);
2229 if (err)
2230 return err;
2231 break;
2232 case IPC_RMID:
2233 case GETPID:
2234 case GETNCNT:
2235 case GETZCNT:
2236 ret = get_errno(semctl(semid, semnum, cmd, NULL));
2237 break;
ths3eb6b042007-06-03 14:26:27 +00002238 }
2239
2240 return ret;
2241}
2242
aurel32e5289082009-04-18 16:16:12 +00002243struct target_sembuf {
2244 unsigned short sem_num;
2245 short sem_op;
2246 short sem_flg;
2247};
2248
2249static inline abi_long target_to_host_sembuf(struct sembuf *host_sembuf,
2250 abi_ulong target_addr,
2251 unsigned nsops)
2252{
2253 struct target_sembuf *target_sembuf;
2254 int i;
2255
2256 target_sembuf = lock_user(VERIFY_READ, target_addr,
2257 nsops*sizeof(struct target_sembuf), 1);
2258 if (!target_sembuf)
2259 return -TARGET_EFAULT;
2260
2261 for(i=0; i<nsops; i++) {
2262 __get_user(host_sembuf[i].sem_num, &target_sembuf[i].sem_num);
2263 __get_user(host_sembuf[i].sem_op, &target_sembuf[i].sem_op);
2264 __get_user(host_sembuf[i].sem_flg, &target_sembuf[i].sem_flg);
2265 }
2266
2267 unlock_user(target_sembuf, target_addr, 0);
2268
2269 return 0;
2270}
2271
2272static inline abi_long do_semop(int semid, abi_long ptr, unsigned nsops)
2273{
2274 struct sembuf sops[nsops];
2275
2276 if (target_to_host_sembuf(sops, ptr, nsops))
2277 return -TARGET_EFAULT;
2278
2279 return semop(semid, sops, nsops);
2280}
2281
ths1bc012f2007-06-03 14:27:49 +00002282struct target_msqid_ds
2283{
aurel321c54ff92008-10-13 21:08:44 +00002284 struct target_ipc_perm msg_perm;
2285 abi_ulong msg_stime;
2286#if TARGET_ABI_BITS == 32
2287 abi_ulong __unused1;
2288#endif
2289 abi_ulong msg_rtime;
2290#if TARGET_ABI_BITS == 32
2291 abi_ulong __unused2;
2292#endif
2293 abi_ulong msg_ctime;
2294#if TARGET_ABI_BITS == 32
2295 abi_ulong __unused3;
2296#endif
2297 abi_ulong __msg_cbytes;
2298 abi_ulong msg_qnum;
2299 abi_ulong msg_qbytes;
2300 abi_ulong msg_lspid;
2301 abi_ulong msg_lrpid;
2302 abi_ulong __unused4;
2303 abi_ulong __unused5;
ths1bc012f2007-06-03 14:27:49 +00002304};
2305
bellard579a97f2007-11-11 14:26:47 +00002306static inline abi_long target_to_host_msqid_ds(struct msqid_ds *host_md,
2307 abi_ulong target_addr)
ths1bc012f2007-06-03 14:27:49 +00002308{
2309 struct target_msqid_ds *target_md;
2310
bellard579a97f2007-11-11 14:26:47 +00002311 if (!lock_user_struct(VERIFY_READ, target_md, target_addr, 1))
2312 return -TARGET_EFAULT;
aurel321c54ff92008-10-13 21:08:44 +00002313 if (target_to_host_ipc_perm(&(host_md->msg_perm),target_addr))
2314 return -TARGET_EFAULT;
ths1bc012f2007-06-03 14:27:49 +00002315 host_md->msg_stime = tswapl(target_md->msg_stime);
2316 host_md->msg_rtime = tswapl(target_md->msg_rtime);
2317 host_md->msg_ctime = tswapl(target_md->msg_ctime);
2318 host_md->__msg_cbytes = tswapl(target_md->__msg_cbytes);
2319 host_md->msg_qnum = tswapl(target_md->msg_qnum);
2320 host_md->msg_qbytes = tswapl(target_md->msg_qbytes);
2321 host_md->msg_lspid = tswapl(target_md->msg_lspid);
2322 host_md->msg_lrpid = tswapl(target_md->msg_lrpid);
2323 unlock_user_struct(target_md, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00002324 return 0;
ths1bc012f2007-06-03 14:27:49 +00002325}
2326
bellard579a97f2007-11-11 14:26:47 +00002327static inline abi_long host_to_target_msqid_ds(abi_ulong target_addr,
2328 struct msqid_ds *host_md)
ths1bc012f2007-06-03 14:27:49 +00002329{
2330 struct target_msqid_ds *target_md;
2331
bellard579a97f2007-11-11 14:26:47 +00002332 if (!lock_user_struct(VERIFY_WRITE, target_md, target_addr, 0))
2333 return -TARGET_EFAULT;
aurel321c54ff92008-10-13 21:08:44 +00002334 if (host_to_target_ipc_perm(target_addr,&(host_md->msg_perm)))
2335 return -TARGET_EFAULT;
ths1bc012f2007-06-03 14:27:49 +00002336 target_md->msg_stime = tswapl(host_md->msg_stime);
2337 target_md->msg_rtime = tswapl(host_md->msg_rtime);
2338 target_md->msg_ctime = tswapl(host_md->msg_ctime);
2339 target_md->__msg_cbytes = tswapl(host_md->__msg_cbytes);
2340 target_md->msg_qnum = tswapl(host_md->msg_qnum);
2341 target_md->msg_qbytes = tswapl(host_md->msg_qbytes);
2342 target_md->msg_lspid = tswapl(host_md->msg_lspid);
2343 target_md->msg_lrpid = tswapl(host_md->msg_lrpid);
2344 unlock_user_struct(target_md, target_addr, 1);
bellard579a97f2007-11-11 14:26:47 +00002345 return 0;
ths1bc012f2007-06-03 14:27:49 +00002346}
2347
aurel321c54ff92008-10-13 21:08:44 +00002348struct target_msginfo {
2349 int msgpool;
2350 int msgmap;
2351 int msgmax;
2352 int msgmnb;
2353 int msgmni;
2354 int msgssz;
2355 int msgtql;
2356 unsigned short int msgseg;
2357};
2358
2359static inline abi_long host_to_target_msginfo(abi_ulong target_addr,
2360 struct msginfo *host_msginfo)
2361{
2362 struct target_msginfo *target_msginfo;
2363 if (!lock_user_struct(VERIFY_WRITE, target_msginfo, target_addr, 0))
2364 return -TARGET_EFAULT;
2365 __put_user(host_msginfo->msgpool, &target_msginfo->msgpool);
2366 __put_user(host_msginfo->msgmap, &target_msginfo->msgmap);
2367 __put_user(host_msginfo->msgmax, &target_msginfo->msgmax);
2368 __put_user(host_msginfo->msgmnb, &target_msginfo->msgmnb);
2369 __put_user(host_msginfo->msgmni, &target_msginfo->msgmni);
2370 __put_user(host_msginfo->msgssz, &target_msginfo->msgssz);
2371 __put_user(host_msginfo->msgtql, &target_msginfo->msgtql);
2372 __put_user(host_msginfo->msgseg, &target_msginfo->msgseg);
2373 unlock_user_struct(target_msginfo, target_addr, 1);
aurel3200b229a2008-10-24 13:12:52 +00002374 return 0;
aurel321c54ff92008-10-13 21:08:44 +00002375}
2376
2377static inline abi_long do_msgctl(int msgid, int cmd, abi_long ptr)
ths1bc012f2007-06-03 14:27:49 +00002378{
2379 struct msqid_ds dsarg;
aurel321c54ff92008-10-13 21:08:44 +00002380 struct msginfo msginfo;
2381 abi_long ret = -TARGET_EINVAL;
2382
2383 cmd &= 0xff;
2384
2385 switch (cmd) {
ths1bc012f2007-06-03 14:27:49 +00002386 case IPC_STAT:
2387 case IPC_SET:
aurel321c54ff92008-10-13 21:08:44 +00002388 case MSG_STAT:
2389 if (target_to_host_msqid_ds(&dsarg,ptr))
2390 return -TARGET_EFAULT;
2391 ret = get_errno(msgctl(msgid, cmd, &dsarg));
2392 if (host_to_target_msqid_ds(ptr,&dsarg))
2393 return -TARGET_EFAULT;
2394 break;
2395 case IPC_RMID:
2396 ret = get_errno(msgctl(msgid, cmd, NULL));
2397 break;
2398 case IPC_INFO:
2399 case MSG_INFO:
2400 ret = get_errno(msgctl(msgid, cmd, (struct msqid_ds *)&msginfo));
2401 if (host_to_target_msginfo(ptr, &msginfo))
2402 return -TARGET_EFAULT;
2403 break;
ths1bc012f2007-06-03 14:27:49 +00002404 }
aurel321c54ff92008-10-13 21:08:44 +00002405
ths1bc012f2007-06-03 14:27:49 +00002406 return ret;
2407}
2408
2409struct target_msgbuf {
aurel321c54ff92008-10-13 21:08:44 +00002410 abi_long mtype;
2411 char mtext[1];
ths1bc012f2007-06-03 14:27:49 +00002412};
2413
blueswir1992f48a2007-10-14 16:27:31 +00002414static inline abi_long do_msgsnd(int msqid, abi_long msgp,
2415 unsigned int msgsz, int msgflg)
ths1bc012f2007-06-03 14:27:49 +00002416{
2417 struct target_msgbuf *target_mb;
2418 struct msgbuf *host_mb;
blueswir1992f48a2007-10-14 16:27:31 +00002419 abi_long ret = 0;
ths1bc012f2007-06-03 14:27:49 +00002420
bellard579a97f2007-11-11 14:26:47 +00002421 if (!lock_user_struct(VERIFY_READ, target_mb, msgp, 0))
2422 return -TARGET_EFAULT;
ths1bc012f2007-06-03 14:27:49 +00002423 host_mb = malloc(msgsz+sizeof(long));
aurel321c54ff92008-10-13 21:08:44 +00002424 host_mb->mtype = (abi_long) tswapl(target_mb->mtype);
2425 memcpy(host_mb->mtext, target_mb->mtext, msgsz);
ths1bc012f2007-06-03 14:27:49 +00002426 ret = get_errno(msgsnd(msqid, host_mb, msgsz, msgflg));
2427 free(host_mb);
2428 unlock_user_struct(target_mb, msgp, 0);
2429
2430 return ret;
2431}
2432
blueswir1992f48a2007-10-14 16:27:31 +00002433static inline abi_long do_msgrcv(int msqid, abi_long msgp,
aurel321c54ff92008-10-13 21:08:44 +00002434 unsigned int msgsz, abi_long msgtyp,
blueswir1992f48a2007-10-14 16:27:31 +00002435 int msgflg)
ths1bc012f2007-06-03 14:27:49 +00002436{
2437 struct target_msgbuf *target_mb;
bellard579a97f2007-11-11 14:26:47 +00002438 char *target_mtext;
ths1bc012f2007-06-03 14:27:49 +00002439 struct msgbuf *host_mb;
blueswir1992f48a2007-10-14 16:27:31 +00002440 abi_long ret = 0;
ths1bc012f2007-06-03 14:27:49 +00002441
bellard579a97f2007-11-11 14:26:47 +00002442 if (!lock_user_struct(VERIFY_WRITE, target_mb, msgp, 0))
2443 return -TARGET_EFAULT;
aurel321c54ff92008-10-13 21:08:44 +00002444
ths1bc012f2007-06-03 14:27:49 +00002445 host_mb = malloc(msgsz+sizeof(long));
aurel321c54ff92008-10-13 21:08:44 +00002446 ret = get_errno(msgrcv(msqid, host_mb, msgsz, tswapl(msgtyp), msgflg));
2447
bellard579a97f2007-11-11 14:26:47 +00002448 if (ret > 0) {
2449 abi_ulong target_mtext_addr = msgp + sizeof(abi_ulong);
2450 target_mtext = lock_user(VERIFY_WRITE, target_mtext_addr, ret, 0);
2451 if (!target_mtext) {
2452 ret = -TARGET_EFAULT;
2453 goto end;
2454 }
aurel321c54ff92008-10-13 21:08:44 +00002455 memcpy(target_mb->mtext, host_mb->mtext, ret);
bellard579a97f2007-11-11 14:26:47 +00002456 unlock_user(target_mtext, target_mtext_addr, ret);
2457 }
aurel321c54ff92008-10-13 21:08:44 +00002458
ths1bc012f2007-06-03 14:27:49 +00002459 target_mb->mtype = tswapl(host_mb->mtype);
2460 free(host_mb);
ths1bc012f2007-06-03 14:27:49 +00002461
bellard579a97f2007-11-11 14:26:47 +00002462end:
2463 if (target_mb)
2464 unlock_user_struct(target_mb, msgp, 1);
ths1bc012f2007-06-03 14:27:49 +00002465 return ret;
2466}
2467
Riku Voipio88a8c982009-04-03 10:42:00 +03002468struct target_shmid_ds
2469{
2470 struct target_ipc_perm shm_perm;
2471 abi_ulong shm_segsz;
2472 abi_ulong shm_atime;
2473#if TARGET_ABI_BITS == 32
2474 abi_ulong __unused1;
2475#endif
2476 abi_ulong shm_dtime;
2477#if TARGET_ABI_BITS == 32
2478 abi_ulong __unused2;
2479#endif
2480 abi_ulong shm_ctime;
2481#if TARGET_ABI_BITS == 32
2482 abi_ulong __unused3;
2483#endif
2484 int shm_cpid;
2485 int shm_lpid;
2486 abi_ulong shm_nattch;
2487 unsigned long int __unused4;
2488 unsigned long int __unused5;
2489};
2490
2491static inline abi_long target_to_host_shmid_ds(struct shmid_ds *host_sd,
2492 abi_ulong target_addr)
2493{
2494 struct target_shmid_ds *target_sd;
2495
2496 if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
2497 return -TARGET_EFAULT;
2498 if (target_to_host_ipc_perm(&(host_sd->shm_perm), target_addr))
2499 return -TARGET_EFAULT;
2500 __get_user(host_sd->shm_segsz, &target_sd->shm_segsz);
2501 __get_user(host_sd->shm_atime, &target_sd->shm_atime);
2502 __get_user(host_sd->shm_dtime, &target_sd->shm_dtime);
2503 __get_user(host_sd->shm_ctime, &target_sd->shm_ctime);
2504 __get_user(host_sd->shm_cpid, &target_sd->shm_cpid);
2505 __get_user(host_sd->shm_lpid, &target_sd->shm_lpid);
2506 __get_user(host_sd->shm_nattch, &target_sd->shm_nattch);
2507 unlock_user_struct(target_sd, target_addr, 0);
2508 return 0;
2509}
2510
2511static inline abi_long host_to_target_shmid_ds(abi_ulong target_addr,
2512 struct shmid_ds *host_sd)
2513{
2514 struct target_shmid_ds *target_sd;
2515
2516 if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
2517 return -TARGET_EFAULT;
2518 if (host_to_target_ipc_perm(target_addr, &(host_sd->shm_perm)))
2519 return -TARGET_EFAULT;
2520 __put_user(host_sd->shm_segsz, &target_sd->shm_segsz);
2521 __put_user(host_sd->shm_atime, &target_sd->shm_atime);
2522 __put_user(host_sd->shm_dtime, &target_sd->shm_dtime);
2523 __put_user(host_sd->shm_ctime, &target_sd->shm_ctime);
2524 __put_user(host_sd->shm_cpid, &target_sd->shm_cpid);
2525 __put_user(host_sd->shm_lpid, &target_sd->shm_lpid);
2526 __put_user(host_sd->shm_nattch, &target_sd->shm_nattch);
2527 unlock_user_struct(target_sd, target_addr, 1);
2528 return 0;
2529}
2530
2531struct target_shminfo {
2532 abi_ulong shmmax;
2533 abi_ulong shmmin;
2534 abi_ulong shmmni;
2535 abi_ulong shmseg;
2536 abi_ulong shmall;
2537};
2538
2539static inline abi_long host_to_target_shminfo(abi_ulong target_addr,
2540 struct shminfo *host_shminfo)
2541{
2542 struct target_shminfo *target_shminfo;
2543 if (!lock_user_struct(VERIFY_WRITE, target_shminfo, target_addr, 0))
2544 return -TARGET_EFAULT;
2545 __put_user(host_shminfo->shmmax, &target_shminfo->shmmax);
2546 __put_user(host_shminfo->shmmin, &target_shminfo->shmmin);
2547 __put_user(host_shminfo->shmmni, &target_shminfo->shmmni);
2548 __put_user(host_shminfo->shmseg, &target_shminfo->shmseg);
2549 __put_user(host_shminfo->shmall, &target_shminfo->shmall);
2550 unlock_user_struct(target_shminfo, target_addr, 1);
2551 return 0;
2552}
2553
2554struct target_shm_info {
2555 int used_ids;
2556 abi_ulong shm_tot;
2557 abi_ulong shm_rss;
2558 abi_ulong shm_swp;
2559 abi_ulong swap_attempts;
2560 abi_ulong swap_successes;
2561};
2562
2563static inline abi_long host_to_target_shm_info(abi_ulong target_addr,
2564 struct shm_info *host_shm_info)
2565{
2566 struct target_shm_info *target_shm_info;
2567 if (!lock_user_struct(VERIFY_WRITE, target_shm_info, target_addr, 0))
2568 return -TARGET_EFAULT;
2569 __put_user(host_shm_info->used_ids, &target_shm_info->used_ids);
2570 __put_user(host_shm_info->shm_tot, &target_shm_info->shm_tot);
2571 __put_user(host_shm_info->shm_rss, &target_shm_info->shm_rss);
2572 __put_user(host_shm_info->shm_swp, &target_shm_info->shm_swp);
2573 __put_user(host_shm_info->swap_attempts, &target_shm_info->swap_attempts);
2574 __put_user(host_shm_info->swap_successes, &target_shm_info->swap_successes);
2575 unlock_user_struct(target_shm_info, target_addr, 1);
2576 return 0;
2577}
2578
2579static inline abi_long do_shmctl(int shmid, int cmd, abi_long buf)
2580{
2581 struct shmid_ds dsarg;
2582 struct shminfo shminfo;
2583 struct shm_info shm_info;
2584 abi_long ret = -TARGET_EINVAL;
2585
2586 cmd &= 0xff;
2587
2588 switch(cmd) {
2589 case IPC_STAT:
2590 case IPC_SET:
2591 case SHM_STAT:
2592 if (target_to_host_shmid_ds(&dsarg, buf))
2593 return -TARGET_EFAULT;
2594 ret = get_errno(shmctl(shmid, cmd, &dsarg));
2595 if (host_to_target_shmid_ds(buf, &dsarg))
2596 return -TARGET_EFAULT;
2597 break;
2598 case IPC_INFO:
2599 ret = get_errno(shmctl(shmid, cmd, (struct shmid_ds *)&shminfo));
2600 if (host_to_target_shminfo(buf, &shminfo))
2601 return -TARGET_EFAULT;
2602 break;
2603 case SHM_INFO:
2604 ret = get_errno(shmctl(shmid, cmd, (struct shmid_ds *)&shm_info));
2605 if (host_to_target_shm_info(buf, &shm_info))
2606 return -TARGET_EFAULT;
2607 break;
2608 case IPC_RMID:
2609 case SHM_LOCK:
2610 case SHM_UNLOCK:
2611 ret = get_errno(shmctl(shmid, cmd, NULL));
2612 break;
2613 }
2614
2615 return ret;
2616}
2617
2618static inline abi_ulong do_shmat(int shmid, abi_ulong shmaddr, int shmflg)
2619{
2620 abi_long raddr;
2621 void *host_raddr;
2622 struct shmid_ds shm_info;
2623 int i,ret;
2624
2625 /* find out the length of the shared memory segment */
2626 ret = get_errno(shmctl(shmid, IPC_STAT, &shm_info));
2627 if (is_error(ret)) {
2628 /* can't get length, bail out */
2629 return ret;
2630 }
2631
2632 mmap_lock();
2633
2634 if (shmaddr)
2635 host_raddr = shmat(shmid, (void *)g2h(shmaddr), shmflg);
2636 else {
2637 abi_ulong mmap_start;
2638
2639 mmap_start = mmap_find_vma(0, shm_info.shm_segsz);
2640
2641 if (mmap_start == -1) {
2642 errno = ENOMEM;
2643 host_raddr = (void *)-1;
2644 } else
2645 host_raddr = shmat(shmid, g2h(mmap_start), shmflg | SHM_REMAP);
2646 }
2647
2648 if (host_raddr == (void *)-1) {
2649 mmap_unlock();
2650 return get_errno((long)host_raddr);
2651 }
2652 raddr=h2g((unsigned long)host_raddr);
2653
2654 page_set_flags(raddr, raddr + shm_info.shm_segsz,
2655 PAGE_VALID | PAGE_READ |
2656 ((shmflg & SHM_RDONLY)? 0 : PAGE_WRITE));
2657
2658 for (i = 0; i < N_SHM_REGIONS; i++) {
2659 if (shm_regions[i].start == 0) {
2660 shm_regions[i].start = raddr;
2661 shm_regions[i].size = shm_info.shm_segsz;
2662 break;
2663 }
2664 }
2665
2666 mmap_unlock();
2667 return raddr;
2668
2669}
2670
2671static inline abi_long do_shmdt(abi_ulong shmaddr)
2672{
2673 int i;
2674
2675 for (i = 0; i < N_SHM_REGIONS; ++i) {
2676 if (shm_regions[i].start == shmaddr) {
2677 shm_regions[i].start = 0;
2678 page_set_flags(shmaddr, shm_regions[i].size, 0);
2679 break;
2680 }
2681 }
2682
2683 return get_errno(shmdt(g2h(shmaddr)));
2684}
2685
aurel321c54ff92008-10-13 21:08:44 +00002686#ifdef TARGET_NR_ipc
pbrook53a59602006-03-25 19:31:22 +00002687/* ??? This only works with linear mappings. */
ths0da46a62007-10-20 20:23:07 +00002688/* do_ipc() must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00002689static abi_long do_ipc(unsigned int call, int first,
2690 int second, int third,
2691 abi_long ptr, abi_long fifth)
bellard8853f862004-02-22 14:57:26 +00002692{
2693 int version;
blueswir1992f48a2007-10-14 16:27:31 +00002694 abi_long ret = 0;
bellard8853f862004-02-22 14:57:26 +00002695
2696 version = call >> 16;
2697 call &= 0xffff;
2698
2699 switch (call) {
thsfa294812007-02-02 22:05:00 +00002700 case IPCOP_semop:
aurel32e5289082009-04-18 16:16:12 +00002701 ret = do_semop(first, ptr, second);
thsfa294812007-02-02 22:05:00 +00002702 break;
2703
2704 case IPCOP_semget:
2705 ret = get_errno(semget(first, second, third));
2706 break;
2707
2708 case IPCOP_semctl:
aurel32e5289082009-04-18 16:16:12 +00002709 ret = do_semctl(first, second, third, (union target_semun)(abi_ulong) ptr);
thsfa294812007-02-02 22:05:00 +00002710 break;
thsd96372e2007-02-02 22:05:44 +00002711
aurel321c54ff92008-10-13 21:08:44 +00002712 case IPCOP_msgget:
2713 ret = get_errno(msgget(first, second));
2714 break;
thsd96372e2007-02-02 22:05:44 +00002715
aurel321c54ff92008-10-13 21:08:44 +00002716 case IPCOP_msgsnd:
2717 ret = do_msgsnd(first, ptr, second, third);
2718 break;
thsd96372e2007-02-02 22:05:44 +00002719
aurel321c54ff92008-10-13 21:08:44 +00002720 case IPCOP_msgctl:
2721 ret = do_msgctl(first, second, ptr);
2722 break;
thsd96372e2007-02-02 22:05:44 +00002723
aurel321c54ff92008-10-13 21:08:44 +00002724 case IPCOP_msgrcv:
2725 switch (version) {
2726 case 0:
2727 {
2728 struct target_ipc_kludge {
2729 abi_long msgp;
2730 abi_long msgtyp;
2731 } *tmp;
thsd96372e2007-02-02 22:05:44 +00002732
aurel321c54ff92008-10-13 21:08:44 +00002733 if (!lock_user_struct(VERIFY_READ, tmp, ptr, 1)) {
2734 ret = -TARGET_EFAULT;
2735 break;
ths1bc012f2007-06-03 14:27:49 +00002736 }
aurel321c54ff92008-10-13 21:08:44 +00002737
2738 ret = do_msgrcv(first, tmp->msgp, second, tmp->msgtyp, third);
2739
2740 unlock_user_struct(tmp, ptr, 0);
2741 break;
2742 }
2743 default:
2744 ret = do_msgrcv(first, ptr, second, fifth, third);
2745 }
2746 break;
thsd96372e2007-02-02 22:05:44 +00002747
bellard8853f862004-02-22 14:57:26 +00002748 case IPCOP_shmat:
Riku Voipio88a8c982009-04-03 10:42:00 +03002749 switch (version) {
2750 default:
bellard5a4a8982007-11-11 17:39:18 +00002751 {
2752 abi_ulong raddr;
Riku Voipio88a8c982009-04-03 10:42:00 +03002753 raddr = do_shmat(first, ptr, second);
2754 if (is_error(raddr))
2755 return get_errno(raddr);
bellard2f619692007-11-16 10:46:05 +00002756 if (put_user_ual(raddr, third))
bellard5a4a8982007-11-11 17:39:18 +00002757 return -TARGET_EFAULT;
Riku Voipio88a8c982009-04-03 10:42:00 +03002758 break;
2759 }
2760 case 1:
2761 ret = -TARGET_EINVAL;
2762 break;
bellard5a4a8982007-11-11 17:39:18 +00002763 }
bellard8853f862004-02-22 14:57:26 +00002764 break;
2765 case IPCOP_shmdt:
Riku Voipio88a8c982009-04-03 10:42:00 +03002766 ret = do_shmdt(ptr);
bellard8853f862004-02-22 14:57:26 +00002767 break;
2768
2769 case IPCOP_shmget:
2770 /* IPC_* flag values are the same on all linux platforms */
2771 ret = get_errno(shmget(first, second, third));
2772 break;
2773
2774 /* IPC_* and SHM_* command values are the same on all linux platforms */
2775 case IPCOP_shmctl:
Riku Voipio88a8c982009-04-03 10:42:00 +03002776 ret = do_shmctl(first, second, third);
bellard8853f862004-02-22 14:57:26 +00002777 break;
2778 default:
j_mayer32407102007-09-26 23:01:49 +00002779 gemu_log("Unsupported ipc call: %d (version %d)\n", call, version);
ths0da46a62007-10-20 20:23:07 +00002780 ret = -TARGET_ENOSYS;
bellard8853f862004-02-22 14:57:26 +00002781 break;
2782 }
2783 return ret;
2784}
j_mayer32407102007-09-26 23:01:49 +00002785#endif
bellard8853f862004-02-22 14:57:26 +00002786
bellard31e31b82003-02-18 22:55:36 +00002787/* kernel structure types definitions */
2788#define IFNAMSIZ 16
2789
Blue Swirl001faf32009-05-13 17:53:17 +00002790#define STRUCT(name, ...) STRUCT_ ## name,
bellard31e31b82003-02-18 22:55:36 +00002791#define STRUCT_SPECIAL(name) STRUCT_ ## name,
2792enum {
2793#include "syscall_types.h"
2794};
2795#undef STRUCT
2796#undef STRUCT_SPECIAL
2797
Blue Swirl001faf32009-05-13 17:53:17 +00002798#define STRUCT(name, ...) static const argtype struct_ ## name ## _def[] = { __VA_ARGS__, TYPE_NULL };
bellard31e31b82003-02-18 22:55:36 +00002799#define STRUCT_SPECIAL(name)
2800#include "syscall_types.h"
2801#undef STRUCT
2802#undef STRUCT_SPECIAL
2803
2804typedef struct IOCTLEntry {
bellard2ab83ea2003-06-15 19:56:46 +00002805 unsigned int target_cmd;
2806 unsigned int host_cmd;
bellard31e31b82003-02-18 22:55:36 +00002807 const char *name;
2808 int access;
bellard1a9353d2003-03-16 20:28:50 +00002809 const argtype arg_type[5];
bellard31e31b82003-02-18 22:55:36 +00002810} IOCTLEntry;
2811
2812#define IOC_R 0x0001
2813#define IOC_W 0x0002
2814#define IOC_RW (IOC_R | IOC_W)
2815
2816#define MAX_STRUCT_SIZE 4096
2817
blueswir19f106a72008-10-05 10:52:52 +00002818static IOCTLEntry ioctl_entries[] = {
Blue Swirl001faf32009-05-13 17:53:17 +00002819#define IOCTL(cmd, access, ...) \
2820 { TARGET_ ## cmd, cmd, #cmd, access, { __VA_ARGS__ } },
bellard31e31b82003-02-18 22:55:36 +00002821#include "ioctls.h"
2822 { 0, 0, },
2823};
2824
pbrook53a59602006-03-25 19:31:22 +00002825/* ??? Implement proper locking for ioctls. */
ths0da46a62007-10-20 20:23:07 +00002826/* do_ioctl() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00002827static abi_long do_ioctl(int fd, abi_long cmd, abi_long arg)
bellard31e31b82003-02-18 22:55:36 +00002828{
2829 const IOCTLEntry *ie;
2830 const argtype *arg_type;
blueswir1992f48a2007-10-14 16:27:31 +00002831 abi_long ret;
bellard31e31b82003-02-18 22:55:36 +00002832 uint8_t buf_temp[MAX_STRUCT_SIZE];
pbrook53a59602006-03-25 19:31:22 +00002833 int target_size;
2834 void *argptr;
bellard31e31b82003-02-18 22:55:36 +00002835
2836 ie = ioctl_entries;
2837 for(;;) {
2838 if (ie->target_cmd == 0) {
j_mayer32407102007-09-26 23:01:49 +00002839 gemu_log("Unsupported ioctl: cmd=0x%04lx\n", (long)cmd);
ths0da46a62007-10-20 20:23:07 +00002840 return -TARGET_ENOSYS;
bellard31e31b82003-02-18 22:55:36 +00002841 }
2842 if (ie->target_cmd == cmd)
2843 break;
2844 ie++;
2845 }
2846 arg_type = ie->arg_type;
bellard9de5e442003-03-23 16:49:39 +00002847#if defined(DEBUG)
j_mayer32407102007-09-26 23:01:49 +00002848 gemu_log("ioctl: cmd=0x%04lx (%s)\n", (long)cmd, ie->name);
bellard72f03902003-02-18 23:33:18 +00002849#endif
bellard31e31b82003-02-18 22:55:36 +00002850 switch(arg_type[0]) {
2851 case TYPE_NULL:
2852 /* no argument */
2853 ret = get_errno(ioctl(fd, ie->host_cmd));
2854 break;
2855 case TYPE_PTRVOID:
2856 case TYPE_INT:
2857 /* int argment */
2858 ret = get_errno(ioctl(fd, ie->host_cmd, arg));
2859 break;
2860 case TYPE_PTR:
2861 arg_type++;
pbrook53a59602006-03-25 19:31:22 +00002862 target_size = thunk_type_size(arg_type, 0);
bellard31e31b82003-02-18 22:55:36 +00002863 switch(ie->access) {
2864 case IOC_R:
2865 ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
2866 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00002867 argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
2868 if (!argptr)
2869 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00002870 thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
2871 unlock_user(argptr, arg, target_size);
bellard31e31b82003-02-18 22:55:36 +00002872 }
2873 break;
2874 case IOC_W:
bellard579a97f2007-11-11 14:26:47 +00002875 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
2876 if (!argptr)
2877 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00002878 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
2879 unlock_user(argptr, arg, 0);
bellard31e31b82003-02-18 22:55:36 +00002880 ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
2881 break;
2882 default:
2883 case IOC_RW:
bellard579a97f2007-11-11 14:26:47 +00002884 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
2885 if (!argptr)
2886 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00002887 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
2888 unlock_user(argptr, arg, 0);
bellard31e31b82003-02-18 22:55:36 +00002889 ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
2890 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00002891 argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
2892 if (!argptr)
2893 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00002894 thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
2895 unlock_user(argptr, arg, target_size);
bellard31e31b82003-02-18 22:55:36 +00002896 }
2897 break;
2898 }
2899 break;
2900 default:
j_mayer32407102007-09-26 23:01:49 +00002901 gemu_log("Unsupported ioctl type: cmd=0x%04lx type=%d\n",
2902 (long)cmd, arg_type[0]);
ths0da46a62007-10-20 20:23:07 +00002903 ret = -TARGET_ENOSYS;
bellard31e31b82003-02-18 22:55:36 +00002904 break;
2905 }
2906 return ret;
2907}
2908
blueswir1b39bc502008-10-05 10:51:10 +00002909static const bitmask_transtbl iflag_tbl[] = {
bellard31e31b82003-02-18 22:55:36 +00002910 { TARGET_IGNBRK, TARGET_IGNBRK, IGNBRK, IGNBRK },
2911 { TARGET_BRKINT, TARGET_BRKINT, BRKINT, BRKINT },
2912 { TARGET_IGNPAR, TARGET_IGNPAR, IGNPAR, IGNPAR },
2913 { TARGET_PARMRK, TARGET_PARMRK, PARMRK, PARMRK },
2914 { TARGET_INPCK, TARGET_INPCK, INPCK, INPCK },
2915 { TARGET_ISTRIP, TARGET_ISTRIP, ISTRIP, ISTRIP },
2916 { TARGET_INLCR, TARGET_INLCR, INLCR, INLCR },
2917 { TARGET_IGNCR, TARGET_IGNCR, IGNCR, IGNCR },
2918 { TARGET_ICRNL, TARGET_ICRNL, ICRNL, ICRNL },
2919 { TARGET_IUCLC, TARGET_IUCLC, IUCLC, IUCLC },
2920 { TARGET_IXON, TARGET_IXON, IXON, IXON },
2921 { TARGET_IXANY, TARGET_IXANY, IXANY, IXANY },
2922 { TARGET_IXOFF, TARGET_IXOFF, IXOFF, IXOFF },
2923 { TARGET_IMAXBEL, TARGET_IMAXBEL, IMAXBEL, IMAXBEL },
2924 { 0, 0, 0, 0 }
2925};
2926
blueswir1b39bc502008-10-05 10:51:10 +00002927static const bitmask_transtbl oflag_tbl[] = {
bellard31e31b82003-02-18 22:55:36 +00002928 { TARGET_OPOST, TARGET_OPOST, OPOST, OPOST },
2929 { TARGET_OLCUC, TARGET_OLCUC, OLCUC, OLCUC },
2930 { TARGET_ONLCR, TARGET_ONLCR, ONLCR, ONLCR },
2931 { TARGET_OCRNL, TARGET_OCRNL, OCRNL, OCRNL },
2932 { TARGET_ONOCR, TARGET_ONOCR, ONOCR, ONOCR },
2933 { TARGET_ONLRET, TARGET_ONLRET, ONLRET, ONLRET },
2934 { TARGET_OFILL, TARGET_OFILL, OFILL, OFILL },
2935 { TARGET_OFDEL, TARGET_OFDEL, OFDEL, OFDEL },
2936 { TARGET_NLDLY, TARGET_NL0, NLDLY, NL0 },
2937 { TARGET_NLDLY, TARGET_NL1, NLDLY, NL1 },
2938 { TARGET_CRDLY, TARGET_CR0, CRDLY, CR0 },
2939 { TARGET_CRDLY, TARGET_CR1, CRDLY, CR1 },
2940 { TARGET_CRDLY, TARGET_CR2, CRDLY, CR2 },
2941 { TARGET_CRDLY, TARGET_CR3, CRDLY, CR3 },
2942 { TARGET_TABDLY, TARGET_TAB0, TABDLY, TAB0 },
2943 { TARGET_TABDLY, TARGET_TAB1, TABDLY, TAB1 },
2944 { TARGET_TABDLY, TARGET_TAB2, TABDLY, TAB2 },
2945 { TARGET_TABDLY, TARGET_TAB3, TABDLY, TAB3 },
2946 { TARGET_BSDLY, TARGET_BS0, BSDLY, BS0 },
2947 { TARGET_BSDLY, TARGET_BS1, BSDLY, BS1 },
2948 { TARGET_VTDLY, TARGET_VT0, VTDLY, VT0 },
2949 { TARGET_VTDLY, TARGET_VT1, VTDLY, VT1 },
2950 { TARGET_FFDLY, TARGET_FF0, FFDLY, FF0 },
2951 { TARGET_FFDLY, TARGET_FF1, FFDLY, FF1 },
2952 { 0, 0, 0, 0 }
2953};
2954
blueswir1b39bc502008-10-05 10:51:10 +00002955static const bitmask_transtbl cflag_tbl[] = {
bellard31e31b82003-02-18 22:55:36 +00002956 { TARGET_CBAUD, TARGET_B0, CBAUD, B0 },
2957 { TARGET_CBAUD, TARGET_B50, CBAUD, B50 },
2958 { TARGET_CBAUD, TARGET_B75, CBAUD, B75 },
2959 { TARGET_CBAUD, TARGET_B110, CBAUD, B110 },
2960 { TARGET_CBAUD, TARGET_B134, CBAUD, B134 },
2961 { TARGET_CBAUD, TARGET_B150, CBAUD, B150 },
2962 { TARGET_CBAUD, TARGET_B200, CBAUD, B200 },
2963 { TARGET_CBAUD, TARGET_B300, CBAUD, B300 },
2964 { TARGET_CBAUD, TARGET_B600, CBAUD, B600 },
2965 { TARGET_CBAUD, TARGET_B1200, CBAUD, B1200 },
2966 { TARGET_CBAUD, TARGET_B1800, CBAUD, B1800 },
2967 { TARGET_CBAUD, TARGET_B2400, CBAUD, B2400 },
2968 { TARGET_CBAUD, TARGET_B4800, CBAUD, B4800 },
2969 { TARGET_CBAUD, TARGET_B9600, CBAUD, B9600 },
2970 { TARGET_CBAUD, TARGET_B19200, CBAUD, B19200 },
2971 { TARGET_CBAUD, TARGET_B38400, CBAUD, B38400 },
2972 { TARGET_CBAUD, TARGET_B57600, CBAUD, B57600 },
2973 { TARGET_CBAUD, TARGET_B115200, CBAUD, B115200 },
2974 { TARGET_CBAUD, TARGET_B230400, CBAUD, B230400 },
2975 { TARGET_CBAUD, TARGET_B460800, CBAUD, B460800 },
2976 { TARGET_CSIZE, TARGET_CS5, CSIZE, CS5 },
2977 { TARGET_CSIZE, TARGET_CS6, CSIZE, CS6 },
2978 { TARGET_CSIZE, TARGET_CS7, CSIZE, CS7 },
2979 { TARGET_CSIZE, TARGET_CS8, CSIZE, CS8 },
2980 { TARGET_CSTOPB, TARGET_CSTOPB, CSTOPB, CSTOPB },
2981 { TARGET_CREAD, TARGET_CREAD, CREAD, CREAD },
2982 { TARGET_PARENB, TARGET_PARENB, PARENB, PARENB },
2983 { TARGET_PARODD, TARGET_PARODD, PARODD, PARODD },
2984 { TARGET_HUPCL, TARGET_HUPCL, HUPCL, HUPCL },
2985 { TARGET_CLOCAL, TARGET_CLOCAL, CLOCAL, CLOCAL },
2986 { TARGET_CRTSCTS, TARGET_CRTSCTS, CRTSCTS, CRTSCTS },
2987 { 0, 0, 0, 0 }
2988};
2989
blueswir1b39bc502008-10-05 10:51:10 +00002990static const bitmask_transtbl lflag_tbl[] = {
bellard31e31b82003-02-18 22:55:36 +00002991 { TARGET_ISIG, TARGET_ISIG, ISIG, ISIG },
2992 { TARGET_ICANON, TARGET_ICANON, ICANON, ICANON },
2993 { TARGET_XCASE, TARGET_XCASE, XCASE, XCASE },
2994 { TARGET_ECHO, TARGET_ECHO, ECHO, ECHO },
2995 { TARGET_ECHOE, TARGET_ECHOE, ECHOE, ECHOE },
2996 { TARGET_ECHOK, TARGET_ECHOK, ECHOK, ECHOK },
2997 { TARGET_ECHONL, TARGET_ECHONL, ECHONL, ECHONL },
2998 { TARGET_NOFLSH, TARGET_NOFLSH, NOFLSH, NOFLSH },
2999 { TARGET_TOSTOP, TARGET_TOSTOP, TOSTOP, TOSTOP },
3000 { TARGET_ECHOCTL, TARGET_ECHOCTL, ECHOCTL, ECHOCTL },
3001 { TARGET_ECHOPRT, TARGET_ECHOPRT, ECHOPRT, ECHOPRT },
3002 { TARGET_ECHOKE, TARGET_ECHOKE, ECHOKE, ECHOKE },
3003 { TARGET_FLUSHO, TARGET_FLUSHO, FLUSHO, FLUSHO },
3004 { TARGET_PENDIN, TARGET_PENDIN, PENDIN, PENDIN },
3005 { TARGET_IEXTEN, TARGET_IEXTEN, IEXTEN, IEXTEN },
3006 { 0, 0, 0, 0 }
3007};
3008
3009static void target_to_host_termios (void *dst, const void *src)
3010{
3011 struct host_termios *host = dst;
3012 const struct target_termios *target = src;
ths3b46e622007-09-17 08:09:54 +00003013
ths5fafdf22007-09-16 21:08:06 +00003014 host->c_iflag =
bellard31e31b82003-02-18 22:55:36 +00003015 target_to_host_bitmask(tswap32(target->c_iflag), iflag_tbl);
ths5fafdf22007-09-16 21:08:06 +00003016 host->c_oflag =
bellard31e31b82003-02-18 22:55:36 +00003017 target_to_host_bitmask(tswap32(target->c_oflag), oflag_tbl);
ths5fafdf22007-09-16 21:08:06 +00003018 host->c_cflag =
bellard31e31b82003-02-18 22:55:36 +00003019 target_to_host_bitmask(tswap32(target->c_cflag), cflag_tbl);
ths5fafdf22007-09-16 21:08:06 +00003020 host->c_lflag =
bellard31e31b82003-02-18 22:55:36 +00003021 target_to_host_bitmask(tswap32(target->c_lflag), lflag_tbl);
3022 host->c_line = target->c_line;
ths3b46e622007-09-17 08:09:54 +00003023
Arnaud Patard44607122009-04-21 17:39:08 +03003024 memset(host->c_cc, 0, sizeof(host->c_cc));
ths5fafdf22007-09-16 21:08:06 +00003025 host->c_cc[VINTR] = target->c_cc[TARGET_VINTR];
3026 host->c_cc[VQUIT] = target->c_cc[TARGET_VQUIT];
ths3b46e622007-09-17 08:09:54 +00003027 host->c_cc[VERASE] = target->c_cc[TARGET_VERASE];
ths5fafdf22007-09-16 21:08:06 +00003028 host->c_cc[VKILL] = target->c_cc[TARGET_VKILL];
ths3b46e622007-09-17 08:09:54 +00003029 host->c_cc[VEOF] = target->c_cc[TARGET_VEOF];
ths5fafdf22007-09-16 21:08:06 +00003030 host->c_cc[VTIME] = target->c_cc[TARGET_VTIME];
ths3b46e622007-09-17 08:09:54 +00003031 host->c_cc[VMIN] = target->c_cc[TARGET_VMIN];
ths5fafdf22007-09-16 21:08:06 +00003032 host->c_cc[VSWTC] = target->c_cc[TARGET_VSWTC];
ths3b46e622007-09-17 08:09:54 +00003033 host->c_cc[VSTART] = target->c_cc[TARGET_VSTART];
ths5fafdf22007-09-16 21:08:06 +00003034 host->c_cc[VSTOP] = target->c_cc[TARGET_VSTOP];
3035 host->c_cc[VSUSP] = target->c_cc[TARGET_VSUSP];
ths3b46e622007-09-17 08:09:54 +00003036 host->c_cc[VEOL] = target->c_cc[TARGET_VEOL];
3037 host->c_cc[VREPRINT] = target->c_cc[TARGET_VREPRINT];
3038 host->c_cc[VDISCARD] = target->c_cc[TARGET_VDISCARD];
3039 host->c_cc[VWERASE] = target->c_cc[TARGET_VWERASE];
3040 host->c_cc[VLNEXT] = target->c_cc[TARGET_VLNEXT];
ths5fafdf22007-09-16 21:08:06 +00003041 host->c_cc[VEOL2] = target->c_cc[TARGET_VEOL2];
bellard31e31b82003-02-18 22:55:36 +00003042}
ths3b46e622007-09-17 08:09:54 +00003043
bellard31e31b82003-02-18 22:55:36 +00003044static void host_to_target_termios (void *dst, const void *src)
3045{
3046 struct target_termios *target = dst;
3047 const struct host_termios *host = src;
3048
ths5fafdf22007-09-16 21:08:06 +00003049 target->c_iflag =
bellard31e31b82003-02-18 22:55:36 +00003050 tswap32(host_to_target_bitmask(host->c_iflag, iflag_tbl));
ths5fafdf22007-09-16 21:08:06 +00003051 target->c_oflag =
bellard31e31b82003-02-18 22:55:36 +00003052 tswap32(host_to_target_bitmask(host->c_oflag, oflag_tbl));
ths5fafdf22007-09-16 21:08:06 +00003053 target->c_cflag =
bellard31e31b82003-02-18 22:55:36 +00003054 tswap32(host_to_target_bitmask(host->c_cflag, cflag_tbl));
ths5fafdf22007-09-16 21:08:06 +00003055 target->c_lflag =
bellard31e31b82003-02-18 22:55:36 +00003056 tswap32(host_to_target_bitmask(host->c_lflag, lflag_tbl));
3057 target->c_line = host->c_line;
ths3b46e622007-09-17 08:09:54 +00003058
Arnaud Patard44607122009-04-21 17:39:08 +03003059 memset(target->c_cc, 0, sizeof(target->c_cc));
bellard31e31b82003-02-18 22:55:36 +00003060 target->c_cc[TARGET_VINTR] = host->c_cc[VINTR];
3061 target->c_cc[TARGET_VQUIT] = host->c_cc[VQUIT];
3062 target->c_cc[TARGET_VERASE] = host->c_cc[VERASE];
3063 target->c_cc[TARGET_VKILL] = host->c_cc[VKILL];
3064 target->c_cc[TARGET_VEOF] = host->c_cc[VEOF];
3065 target->c_cc[TARGET_VTIME] = host->c_cc[VTIME];
3066 target->c_cc[TARGET_VMIN] = host->c_cc[VMIN];
3067 target->c_cc[TARGET_VSWTC] = host->c_cc[VSWTC];
3068 target->c_cc[TARGET_VSTART] = host->c_cc[VSTART];
3069 target->c_cc[TARGET_VSTOP] = host->c_cc[VSTOP];
3070 target->c_cc[TARGET_VSUSP] = host->c_cc[VSUSP];
3071 target->c_cc[TARGET_VEOL] = host->c_cc[VEOL];
3072 target->c_cc[TARGET_VREPRINT] = host->c_cc[VREPRINT];
3073 target->c_cc[TARGET_VDISCARD] = host->c_cc[VDISCARD];
3074 target->c_cc[TARGET_VWERASE] = host->c_cc[VWERASE];
3075 target->c_cc[TARGET_VLNEXT] = host->c_cc[VLNEXT];
3076 target->c_cc[TARGET_VEOL2] = host->c_cc[VEOL2];
3077}
3078
blueswir18e853dc2008-10-05 10:49:32 +00003079static const StructEntry struct_termios_def = {
bellard31e31b82003-02-18 22:55:36 +00003080 .convert = { host_to_target_termios, target_to_host_termios },
3081 .size = { sizeof(struct target_termios), sizeof(struct host_termios) },
3082 .align = { __alignof__(struct target_termios), __alignof__(struct host_termios) },
3083};
3084
bellard5286db72003-06-05 00:57:30 +00003085static bitmask_transtbl mmap_flags_tbl[] = {
3086 { TARGET_MAP_SHARED, TARGET_MAP_SHARED, MAP_SHARED, MAP_SHARED },
3087 { TARGET_MAP_PRIVATE, TARGET_MAP_PRIVATE, MAP_PRIVATE, MAP_PRIVATE },
3088 { TARGET_MAP_FIXED, TARGET_MAP_FIXED, MAP_FIXED, MAP_FIXED },
3089 { TARGET_MAP_ANONYMOUS, TARGET_MAP_ANONYMOUS, MAP_ANONYMOUS, MAP_ANONYMOUS },
3090 { TARGET_MAP_GROWSDOWN, TARGET_MAP_GROWSDOWN, MAP_GROWSDOWN, MAP_GROWSDOWN },
3091 { TARGET_MAP_DENYWRITE, TARGET_MAP_DENYWRITE, MAP_DENYWRITE, MAP_DENYWRITE },
3092 { TARGET_MAP_EXECUTABLE, TARGET_MAP_EXECUTABLE, MAP_EXECUTABLE, MAP_EXECUTABLE },
3093 { TARGET_MAP_LOCKED, TARGET_MAP_LOCKED, MAP_LOCKED, MAP_LOCKED },
3094 { 0, 0, 0, 0 }
3095};
3096
bellard2ab83ea2003-06-15 19:56:46 +00003097#if defined(TARGET_I386)
bellard6dbad632003-03-16 18:05:05 +00003098
3099/* NOTE: there is really one LDT for all the threads */
blueswir1b1d8e522008-10-26 13:43:07 +00003100static uint8_t *ldt_table;
bellard6dbad632003-03-16 18:05:05 +00003101
bellard03acab62007-11-11 14:57:14 +00003102static abi_long read_ldt(abi_ulong ptr, unsigned long bytecount)
bellard6dbad632003-03-16 18:05:05 +00003103{
3104 int size;
pbrook53a59602006-03-25 19:31:22 +00003105 void *p;
bellard6dbad632003-03-16 18:05:05 +00003106
3107 if (!ldt_table)
3108 return 0;
3109 size = TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE;
3110 if (size > bytecount)
3111 size = bytecount;
bellard579a97f2007-11-11 14:26:47 +00003112 p = lock_user(VERIFY_WRITE, ptr, size, 0);
3113 if (!p)
bellard03acab62007-11-11 14:57:14 +00003114 return -TARGET_EFAULT;
bellard579a97f2007-11-11 14:26:47 +00003115 /* ??? Should this by byteswapped? */
pbrook53a59602006-03-25 19:31:22 +00003116 memcpy(p, ldt_table, size);
3117 unlock_user(p, ptr, size);
bellard6dbad632003-03-16 18:05:05 +00003118 return size;
3119}
3120
3121/* XXX: add locking support */
bellard03acab62007-11-11 14:57:14 +00003122static abi_long write_ldt(CPUX86State *env,
3123 abi_ulong ptr, unsigned long bytecount, int oldmode)
bellard6dbad632003-03-16 18:05:05 +00003124{
3125 struct target_modify_ldt_ldt_s ldt_info;
pbrook53a59602006-03-25 19:31:22 +00003126 struct target_modify_ldt_ldt_s *target_ldt_info;
bellard6dbad632003-03-16 18:05:05 +00003127 int seg_32bit, contents, read_exec_only, limit_in_pages;
bellard8d18e892007-11-14 15:18:40 +00003128 int seg_not_present, useable, lm;
bellard6dbad632003-03-16 18:05:05 +00003129 uint32_t *lp, entry_1, entry_2;
3130
3131 if (bytecount != sizeof(ldt_info))
bellard03acab62007-11-11 14:57:14 +00003132 return -TARGET_EINVAL;
bellard579a97f2007-11-11 14:26:47 +00003133 if (!lock_user_struct(VERIFY_READ, target_ldt_info, ptr, 1))
bellard03acab62007-11-11 14:57:14 +00003134 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00003135 ldt_info.entry_number = tswap32(target_ldt_info->entry_number);
3136 ldt_info.base_addr = tswapl(target_ldt_info->base_addr);
3137 ldt_info.limit = tswap32(target_ldt_info->limit);
3138 ldt_info.flags = tswap32(target_ldt_info->flags);
3139 unlock_user_struct(target_ldt_info, ptr, 0);
ths3b46e622007-09-17 08:09:54 +00003140
bellard6dbad632003-03-16 18:05:05 +00003141 if (ldt_info.entry_number >= TARGET_LDT_ENTRIES)
bellard03acab62007-11-11 14:57:14 +00003142 return -TARGET_EINVAL;
bellard6dbad632003-03-16 18:05:05 +00003143 seg_32bit = ldt_info.flags & 1;
3144 contents = (ldt_info.flags >> 1) & 3;
3145 read_exec_only = (ldt_info.flags >> 3) & 1;
3146 limit_in_pages = (ldt_info.flags >> 4) & 1;
3147 seg_not_present = (ldt_info.flags >> 5) & 1;
3148 useable = (ldt_info.flags >> 6) & 1;
bellard8d18e892007-11-14 15:18:40 +00003149#ifdef TARGET_ABI32
3150 lm = 0;
3151#else
3152 lm = (ldt_info.flags >> 7) & 1;
3153#endif
bellard6dbad632003-03-16 18:05:05 +00003154 if (contents == 3) {
3155 if (oldmode)
bellard03acab62007-11-11 14:57:14 +00003156 return -TARGET_EINVAL;
bellard6dbad632003-03-16 18:05:05 +00003157 if (seg_not_present == 0)
bellard03acab62007-11-11 14:57:14 +00003158 return -TARGET_EINVAL;
bellard6dbad632003-03-16 18:05:05 +00003159 }
3160 /* allocate the LDT */
3161 if (!ldt_table) {
balroge4415702008-11-10 02:55:33 +00003162 env->ldt.base = target_mmap(0,
3163 TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE,
3164 PROT_READ|PROT_WRITE,
3165 MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
3166 if (env->ldt.base == -1)
bellard03acab62007-11-11 14:57:14 +00003167 return -TARGET_ENOMEM;
balroge4415702008-11-10 02:55:33 +00003168 memset(g2h(env->ldt.base), 0,
3169 TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE);
bellard6dbad632003-03-16 18:05:05 +00003170 env->ldt.limit = 0xffff;
balroge4415702008-11-10 02:55:33 +00003171 ldt_table = g2h(env->ldt.base);
bellard6dbad632003-03-16 18:05:05 +00003172 }
3173
3174 /* NOTE: same code as Linux kernel */
3175 /* Allow LDTs to be cleared by the user. */
3176 if (ldt_info.base_addr == 0 && ldt_info.limit == 0) {
3177 if (oldmode ||
3178 (contents == 0 &&
3179 read_exec_only == 1 &&
3180 seg_32bit == 0 &&
3181 limit_in_pages == 0 &&
3182 seg_not_present == 1 &&
3183 useable == 0 )) {
3184 entry_1 = 0;
3185 entry_2 = 0;
3186 goto install;
3187 }
3188 }
ths3b46e622007-09-17 08:09:54 +00003189
bellard6dbad632003-03-16 18:05:05 +00003190 entry_1 = ((ldt_info.base_addr & 0x0000ffff) << 16) |
3191 (ldt_info.limit & 0x0ffff);
3192 entry_2 = (ldt_info.base_addr & 0xff000000) |
3193 ((ldt_info.base_addr & 0x00ff0000) >> 16) |
3194 (ldt_info.limit & 0xf0000) |
3195 ((read_exec_only ^ 1) << 9) |
3196 (contents << 10) |
3197 ((seg_not_present ^ 1) << 15) |
3198 (seg_32bit << 22) |
3199 (limit_in_pages << 23) |
bellard8d18e892007-11-14 15:18:40 +00003200 (lm << 21) |
bellard6dbad632003-03-16 18:05:05 +00003201 0x7000;
3202 if (!oldmode)
3203 entry_2 |= (useable << 20);
bellard14ae3ba2003-05-27 23:25:06 +00003204
bellard6dbad632003-03-16 18:05:05 +00003205 /* Install the new entry ... */
3206install:
3207 lp = (uint32_t *)(ldt_table + (ldt_info.entry_number << 3));
3208 lp[0] = tswap32(entry_1);
3209 lp[1] = tswap32(entry_2);
3210 return 0;
3211}
3212
3213/* specific and weird i386 syscalls */
blueswir18fcd3692008-08-17 20:26:25 +00003214static abi_long do_modify_ldt(CPUX86State *env, int func, abi_ulong ptr,
3215 unsigned long bytecount)
bellard6dbad632003-03-16 18:05:05 +00003216{
bellard03acab62007-11-11 14:57:14 +00003217 abi_long ret;
ths3b46e622007-09-17 08:09:54 +00003218
bellard6dbad632003-03-16 18:05:05 +00003219 switch (func) {
3220 case 0:
3221 ret = read_ldt(ptr, bytecount);
3222 break;
3223 case 1:
3224 ret = write_ldt(env, ptr, bytecount, 1);
3225 break;
3226 case 0x11:
3227 ret = write_ldt(env, ptr, bytecount, 0);
3228 break;
bellard03acab62007-11-11 14:57:14 +00003229 default:
3230 ret = -TARGET_ENOSYS;
3231 break;
bellard6dbad632003-03-16 18:05:05 +00003232 }
3233 return ret;
3234}
bellard1b6b0292003-03-22 17:31:38 +00003235
blueswir14583f582008-08-24 10:35:55 +00003236#if defined(TARGET_I386) && defined(TARGET_ABI32)
blueswir18fcd3692008-08-17 20:26:25 +00003237static abi_long do_set_thread_area(CPUX86State *env, abi_ulong ptr)
bellard8d18e892007-11-14 15:18:40 +00003238{
3239 uint64_t *gdt_table = g2h(env->gdt.base);
3240 struct target_modify_ldt_ldt_s ldt_info;
3241 struct target_modify_ldt_ldt_s *target_ldt_info;
3242 int seg_32bit, contents, read_exec_only, limit_in_pages;
3243 int seg_not_present, useable, lm;
3244 uint32_t *lp, entry_1, entry_2;
3245 int i;
3246
3247 lock_user_struct(VERIFY_WRITE, target_ldt_info, ptr, 1);
3248 if (!target_ldt_info)
3249 return -TARGET_EFAULT;
3250 ldt_info.entry_number = tswap32(target_ldt_info->entry_number);
3251 ldt_info.base_addr = tswapl(target_ldt_info->base_addr);
3252 ldt_info.limit = tswap32(target_ldt_info->limit);
3253 ldt_info.flags = tswap32(target_ldt_info->flags);
3254 if (ldt_info.entry_number == -1) {
3255 for (i=TARGET_GDT_ENTRY_TLS_MIN; i<=TARGET_GDT_ENTRY_TLS_MAX; i++) {
3256 if (gdt_table[i] == 0) {
3257 ldt_info.entry_number = i;
3258 target_ldt_info->entry_number = tswap32(i);
3259 break;
3260 }
3261 }
3262 }
3263 unlock_user_struct(target_ldt_info, ptr, 1);
3264
3265 if (ldt_info.entry_number < TARGET_GDT_ENTRY_TLS_MIN ||
3266 ldt_info.entry_number > TARGET_GDT_ENTRY_TLS_MAX)
3267 return -TARGET_EINVAL;
3268 seg_32bit = ldt_info.flags & 1;
3269 contents = (ldt_info.flags >> 1) & 3;
3270 read_exec_only = (ldt_info.flags >> 3) & 1;
3271 limit_in_pages = (ldt_info.flags >> 4) & 1;
3272 seg_not_present = (ldt_info.flags >> 5) & 1;
3273 useable = (ldt_info.flags >> 6) & 1;
3274#ifdef TARGET_ABI32
3275 lm = 0;
3276#else
3277 lm = (ldt_info.flags >> 7) & 1;
3278#endif
3279
3280 if (contents == 3) {
3281 if (seg_not_present == 0)
3282 return -TARGET_EINVAL;
3283 }
3284
3285 /* NOTE: same code as Linux kernel */
3286 /* Allow LDTs to be cleared by the user. */
3287 if (ldt_info.base_addr == 0 && ldt_info.limit == 0) {
3288 if ((contents == 0 &&
3289 read_exec_only == 1 &&
3290 seg_32bit == 0 &&
3291 limit_in_pages == 0 &&
3292 seg_not_present == 1 &&
3293 useable == 0 )) {
3294 entry_1 = 0;
3295 entry_2 = 0;
3296 goto install;
3297 }
3298 }
3299
3300 entry_1 = ((ldt_info.base_addr & 0x0000ffff) << 16) |
3301 (ldt_info.limit & 0x0ffff);
3302 entry_2 = (ldt_info.base_addr & 0xff000000) |
3303 ((ldt_info.base_addr & 0x00ff0000) >> 16) |
3304 (ldt_info.limit & 0xf0000) |
3305 ((read_exec_only ^ 1) << 9) |
3306 (contents << 10) |
3307 ((seg_not_present ^ 1) << 15) |
3308 (seg_32bit << 22) |
3309 (limit_in_pages << 23) |
3310 (useable << 20) |
3311 (lm << 21) |
3312 0x7000;
3313
3314 /* Install the new entry ... */
3315install:
3316 lp = (uint32_t *)(gdt_table + ldt_info.entry_number);
3317 lp[0] = tswap32(entry_1);
3318 lp[1] = tswap32(entry_2);
3319 return 0;
3320}
3321
blueswir18fcd3692008-08-17 20:26:25 +00003322static abi_long do_get_thread_area(CPUX86State *env, abi_ulong ptr)
bellard8d18e892007-11-14 15:18:40 +00003323{
3324 struct target_modify_ldt_ldt_s *target_ldt_info;
3325 uint64_t *gdt_table = g2h(env->gdt.base);
3326 uint32_t base_addr, limit, flags;
3327 int seg_32bit, contents, read_exec_only, limit_in_pages, idx;
3328 int seg_not_present, useable, lm;
3329 uint32_t *lp, entry_1, entry_2;
3330
3331 lock_user_struct(VERIFY_WRITE, target_ldt_info, ptr, 1);
3332 if (!target_ldt_info)
3333 return -TARGET_EFAULT;
3334 idx = tswap32(target_ldt_info->entry_number);
3335 if (idx < TARGET_GDT_ENTRY_TLS_MIN ||
3336 idx > TARGET_GDT_ENTRY_TLS_MAX) {
3337 unlock_user_struct(target_ldt_info, ptr, 1);
3338 return -TARGET_EINVAL;
3339 }
3340 lp = (uint32_t *)(gdt_table + idx);
3341 entry_1 = tswap32(lp[0]);
3342 entry_2 = tswap32(lp[1]);
3343
3344 read_exec_only = ((entry_2 >> 9) & 1) ^ 1;
3345 contents = (entry_2 >> 10) & 3;
3346 seg_not_present = ((entry_2 >> 15) & 1) ^ 1;
3347 seg_32bit = (entry_2 >> 22) & 1;
3348 limit_in_pages = (entry_2 >> 23) & 1;
3349 useable = (entry_2 >> 20) & 1;
3350#ifdef TARGET_ABI32
3351 lm = 0;
3352#else
3353 lm = (entry_2 >> 21) & 1;
3354#endif
3355 flags = (seg_32bit << 0) | (contents << 1) |
3356 (read_exec_only << 3) | (limit_in_pages << 4) |
3357 (seg_not_present << 5) | (useable << 6) | (lm << 7);
3358 limit = (entry_1 & 0xffff) | (entry_2 & 0xf0000);
3359 base_addr = (entry_1 >> 16) |
3360 (entry_2 & 0xff000000) |
3361 ((entry_2 & 0xff) << 16);
3362 target_ldt_info->base_addr = tswapl(base_addr);
3363 target_ldt_info->limit = tswap32(limit);
3364 target_ldt_info->flags = tswap32(flags);
3365 unlock_user_struct(target_ldt_info, ptr, 1);
3366 return 0;
3367}
blueswir14583f582008-08-24 10:35:55 +00003368#endif /* TARGET_I386 && TARGET_ABI32 */
bellard8d18e892007-11-14 15:18:40 +00003369
bellardd2fd1af2007-11-14 18:08:56 +00003370#ifndef TARGET_ABI32
blueswir18fcd3692008-08-17 20:26:25 +00003371static abi_long do_arch_prctl(CPUX86State *env, int code, abi_ulong addr)
bellardd2fd1af2007-11-14 18:08:56 +00003372{
3373 abi_long ret;
3374 abi_ulong val;
3375 int idx;
3376
3377 switch(code) {
3378 case TARGET_ARCH_SET_GS:
3379 case TARGET_ARCH_SET_FS:
3380 if (code == TARGET_ARCH_SET_GS)
3381 idx = R_GS;
3382 else
3383 idx = R_FS;
3384 cpu_x86_load_seg(env, idx, 0);
3385 env->segs[idx].base = addr;
3386 break;
3387 case TARGET_ARCH_GET_GS:
3388 case TARGET_ARCH_GET_FS:
3389 if (code == TARGET_ARCH_GET_GS)
3390 idx = R_GS;
3391 else
3392 idx = R_FS;
3393 val = env->segs[idx].base;
3394 if (put_user(val, addr, abi_ulong))
3395 return -TARGET_EFAULT;
3396 break;
3397 default:
3398 ret = -TARGET_EINVAL;
3399 break;
3400 }
3401 return 0;
3402}
3403#endif
3404
bellard2ab83ea2003-06-15 19:56:46 +00003405#endif /* defined(TARGET_I386) */
3406
pbrookd865bab2008-06-07 22:12:17 +00003407#if defined(USE_NPTL)
3408
3409#define NEW_STACK_SIZE PTHREAD_STACK_MIN
3410
3411static pthread_mutex_t clone_lock = PTHREAD_MUTEX_INITIALIZER;
3412typedef struct {
3413 CPUState *env;
3414 pthread_mutex_t mutex;
3415 pthread_cond_t cond;
3416 pthread_t thread;
3417 uint32_t tid;
3418 abi_ulong child_tidptr;
3419 abi_ulong parent_tidptr;
3420 sigset_t sigmask;
3421} new_thread_info;
3422
3423static void *clone_func(void *arg)
3424{
3425 new_thread_info *info = arg;
3426 CPUState *env;
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03003427 TaskState *ts;
pbrookd865bab2008-06-07 22:12:17 +00003428
3429 env = info->env;
3430 thread_env = env;
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03003431 ts = (TaskState *)thread_env->opaque;
pbrookd865bab2008-06-07 22:12:17 +00003432 info->tid = gettid();
Nathan Froyd1e9fa732009-06-03 11:33:08 -07003433 env->host_tid = info->tid;
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03003434 task_settid(ts);
pbrookd865bab2008-06-07 22:12:17 +00003435 if (info->child_tidptr)
3436 put_user_u32(info->tid, info->child_tidptr);
3437 if (info->parent_tidptr)
3438 put_user_u32(info->tid, info->parent_tidptr);
3439 /* Enable signals. */
3440 sigprocmask(SIG_SETMASK, &info->sigmask, NULL);
3441 /* Signal to the parent that we're ready. */
3442 pthread_mutex_lock(&info->mutex);
3443 pthread_cond_broadcast(&info->cond);
3444 pthread_mutex_unlock(&info->mutex);
3445 /* Wait until the parent has finshed initializing the tls state. */
3446 pthread_mutex_lock(&clone_lock);
3447 pthread_mutex_unlock(&clone_lock);
3448 cpu_loop(env);
3449 /* never exits */
3450 return NULL;
3451}
3452#else
bellard1b6b0292003-03-22 17:31:38 +00003453/* this stack is the equivalent of the kernel stack associated with a
3454 thread/process */
3455#define NEW_STACK_SIZE 8192
3456
3457static int clone_func(void *arg)
3458{
bellard2ab83ea2003-06-15 19:56:46 +00003459 CPUState *env = arg;
bellard1b6b0292003-03-22 17:31:38 +00003460 cpu_loop(env);
3461 /* never exits */
3462 return 0;
3463}
pbrookd865bab2008-06-07 22:12:17 +00003464#endif
bellard1b6b0292003-03-22 17:31:38 +00003465
ths0da46a62007-10-20 20:23:07 +00003466/* do_fork() Must return host values and target errnos (unlike most
3467 do_*() functions). */
pbrookd865bab2008-06-07 22:12:17 +00003468static int do_fork(CPUState *env, unsigned int flags, abi_ulong newsp,
3469 abi_ulong parent_tidptr, target_ulong newtls,
3470 abi_ulong child_tidptr)
bellard1b6b0292003-03-22 17:31:38 +00003471{
3472 int ret;
bellard5cd43932003-03-29 16:54:36 +00003473 TaskState *ts;
bellard1b6b0292003-03-22 17:31:38 +00003474 uint8_t *new_stack;
bellard2ab83ea2003-06-15 19:56:46 +00003475 CPUState *new_env;
pbrookd865bab2008-06-07 22:12:17 +00003476#if defined(USE_NPTL)
3477 unsigned int nptl_flags;
3478 sigset_t sigmask;
3479#endif
ths3b46e622007-09-17 08:09:54 +00003480
balrog436d1242008-09-21 02:39:45 +00003481 /* Emulate vfork() with fork() */
3482 if (flags & CLONE_VFORK)
3483 flags &= ~(CLONE_VFORK | CLONE_VM);
3484
bellard1b6b0292003-03-22 17:31:38 +00003485 if (flags & CLONE_VM) {
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03003486 TaskState *parent_ts = (TaskState *)env->opaque;
pbrookbd0c5662008-05-29 14:34:11 +00003487#if defined(USE_NPTL)
pbrookd865bab2008-06-07 22:12:17 +00003488 new_thread_info info;
3489 pthread_attr_t attr;
pbrookbd0c5662008-05-29 14:34:11 +00003490#endif
pbrookc3a92832008-06-09 14:02:50 +00003491 ts = qemu_mallocz(sizeof(TaskState) + NEW_STACK_SIZE);
pbrook624f7972008-05-31 16:11:38 +00003492 init_task_state(ts);
bellard5cd43932003-03-29 16:54:36 +00003493 new_stack = ts->stack;
bellard1b6b0292003-03-22 17:31:38 +00003494 /* we create a new CPU instance. */
thsc5be9f02007-02-28 20:20:53 +00003495 new_env = cpu_copy(env);
pbrook6e68e072008-05-30 17:22:15 +00003496 /* Init regs that differ from the parent. */
3497 cpu_clone_regs(new_env, newsp);
bellard5cd43932003-03-29 16:54:36 +00003498 new_env->opaque = ts;
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03003499 ts->bprm = parent_ts->bprm;
3500 ts->info = parent_ts->info;
pbrookd865bab2008-06-07 22:12:17 +00003501#if defined(USE_NPTL)
3502 nptl_flags = flags;
3503 flags &= ~CLONE_NPTL_FLAGS2;
3504
pbrookc2764712009-03-07 15:24:59 +00003505 if (nptl_flags & CLONE_CHILD_CLEARTID) {
3506 ts->child_tidptr = child_tidptr;
3507 }
3508
pbrookd865bab2008-06-07 22:12:17 +00003509 if (nptl_flags & CLONE_SETTLS)
3510 cpu_set_tls (new_env, newtls);
3511
3512 /* Grab a mutex so that thread setup appears atomic. */
3513 pthread_mutex_lock(&clone_lock);
3514
3515 memset(&info, 0, sizeof(info));
3516 pthread_mutex_init(&info.mutex, NULL);
3517 pthread_mutex_lock(&info.mutex);
3518 pthread_cond_init(&info.cond, NULL);
3519 info.env = new_env;
3520 if (nptl_flags & CLONE_CHILD_SETTID)
3521 info.child_tidptr = child_tidptr;
3522 if (nptl_flags & CLONE_PARENT_SETTID)
3523 info.parent_tidptr = parent_tidptr;
3524
3525 ret = pthread_attr_init(&attr);
3526 ret = pthread_attr_setstack(&attr, new_stack, NEW_STACK_SIZE);
3527 /* It is not safe to deliver signals until the child has finished
3528 initializing, so temporarily block all signals. */
3529 sigfillset(&sigmask);
3530 sigprocmask(SIG_BLOCK, &sigmask, &info.sigmask);
3531
3532 ret = pthread_create(&info.thread, &attr, clone_func, &info);
pbrookc2764712009-03-07 15:24:59 +00003533 /* TODO: Free new CPU state if thread creation failed. */
pbrookd865bab2008-06-07 22:12:17 +00003534
3535 sigprocmask(SIG_SETMASK, &info.sigmask, NULL);
3536 pthread_attr_destroy(&attr);
3537 if (ret == 0) {
3538 /* Wait for the child to initialize. */
3539 pthread_cond_wait(&info.cond, &info.mutex);
3540 ret = info.tid;
3541 if (flags & CLONE_PARENT_SETTID)
3542 put_user_u32(ret, parent_tidptr);
3543 } else {
3544 ret = -1;
3545 }
3546 pthread_mutex_unlock(&info.mutex);
3547 pthread_cond_destroy(&info.cond);
3548 pthread_mutex_destroy(&info.mutex);
3549 pthread_mutex_unlock(&clone_lock);
3550#else
3551 if (flags & CLONE_NPTL_FLAGS2)
3552 return -EINVAL;
3553 /* This is probably going to die very quickly, but do it anyway. */
bellard27725c12003-04-29 21:08:18 +00003554#ifdef __ia64__
bellardfd4a43e2006-04-24 20:32:17 +00003555 ret = __clone2(clone_func, new_stack + NEW_STACK_SIZE, flags, new_env);
bellard27725c12003-04-29 21:08:18 +00003556#else
3557 ret = clone(clone_func, new_stack + NEW_STACK_SIZE, flags, new_env);
3558#endif
pbrookd865bab2008-06-07 22:12:17 +00003559#endif
bellard1b6b0292003-03-22 17:31:38 +00003560 } else {
3561 /* if no CLONE_VM, we consider it is a fork */
pbrookd865bab2008-06-07 22:12:17 +00003562 if ((flags & ~(CSIGNAL | CLONE_NPTL_FLAGS2)) != 0)
bellard1b6b0292003-03-22 17:31:38 +00003563 return -EINVAL;
pbrookd865bab2008-06-07 22:12:17 +00003564 fork_start();
bellard1b6b0292003-03-22 17:31:38 +00003565 ret = fork();
pbrookd865bab2008-06-07 22:12:17 +00003566 if (ret == 0) {
aurel322b1319c2008-12-18 22:44:04 +00003567 /* Child Process. */
pbrookd865bab2008-06-07 22:12:17 +00003568 cpu_clone_regs(env, newsp);
3569 fork_end(1);
aurel322b1319c2008-12-18 22:44:04 +00003570#if defined(USE_NPTL)
3571 /* There is a race condition here. The parent process could
3572 theoretically read the TID in the child process before the child
3573 tid is set. This would require using either ptrace
3574 (not implemented) or having *_tidptr to point at a shared memory
3575 mapping. We can't repeat the spinlock hack used above because
3576 the child process gets its own copy of the lock. */
pbrookd865bab2008-06-07 22:12:17 +00003577 if (flags & CLONE_CHILD_SETTID)
3578 put_user_u32(gettid(), child_tidptr);
3579 if (flags & CLONE_PARENT_SETTID)
3580 put_user_u32(gettid(), parent_tidptr);
3581 ts = (TaskState *)env->opaque;
3582 if (flags & CLONE_SETTLS)
3583 cpu_set_tls (env, newtls);
pbrookc2764712009-03-07 15:24:59 +00003584 if (flags & CLONE_CHILD_CLEARTID)
3585 ts->child_tidptr = child_tidptr;
aurel322b1319c2008-12-18 22:44:04 +00003586#endif
pbrookd865bab2008-06-07 22:12:17 +00003587 } else {
3588 fork_end(0);
3589 }
bellard1b6b0292003-03-22 17:31:38 +00003590 }
3591 return ret;
3592}
3593
blueswir1992f48a2007-10-14 16:27:31 +00003594static abi_long do_fcntl(int fd, int cmd, abi_ulong arg)
bellard7775e9e2003-05-14 22:46:48 +00003595{
3596 struct flock fl;
pbrook53a59602006-03-25 19:31:22 +00003597 struct target_flock *target_fl;
ths43f238d2007-01-05 20:55:49 +00003598 struct flock64 fl64;
3599 struct target_flock64 *target_fl64;
blueswir1992f48a2007-10-14 16:27:31 +00003600 abi_long ret;
pbrook53a59602006-03-25 19:31:22 +00003601
bellard7775e9e2003-05-14 22:46:48 +00003602 switch(cmd) {
3603 case TARGET_F_GETLK:
bellard579a97f2007-11-11 14:26:47 +00003604 if (!lock_user_struct(VERIFY_READ, target_fl, arg, 1))
3605 return -TARGET_EFAULT;
ths58134272007-03-31 18:59:32 +00003606 fl.l_type = tswap16(target_fl->l_type);
3607 fl.l_whence = tswap16(target_fl->l_whence);
3608 fl.l_start = tswapl(target_fl->l_start);
3609 fl.l_len = tswapl(target_fl->l_len);
3610 fl.l_pid = tswapl(target_fl->l_pid);
3611 unlock_user_struct(target_fl, arg, 0);
bellard9ee1fa22007-11-11 15:11:19 +00003612 ret = get_errno(fcntl(fd, cmd, &fl));
bellard7775e9e2003-05-14 22:46:48 +00003613 if (ret == 0) {
bellard579a97f2007-11-11 14:26:47 +00003614 if (!lock_user_struct(VERIFY_WRITE, target_fl, arg, 0))
3615 return -TARGET_EFAULT;
bellard7775e9e2003-05-14 22:46:48 +00003616 target_fl->l_type = tswap16(fl.l_type);
3617 target_fl->l_whence = tswap16(fl.l_whence);
3618 target_fl->l_start = tswapl(fl.l_start);
3619 target_fl->l_len = tswapl(fl.l_len);
3620 target_fl->l_pid = tswapl(fl.l_pid);
pbrook53a59602006-03-25 19:31:22 +00003621 unlock_user_struct(target_fl, arg, 1);
bellard7775e9e2003-05-14 22:46:48 +00003622 }
3623 break;
ths3b46e622007-09-17 08:09:54 +00003624
bellard7775e9e2003-05-14 22:46:48 +00003625 case TARGET_F_SETLK:
3626 case TARGET_F_SETLKW:
bellard579a97f2007-11-11 14:26:47 +00003627 if (!lock_user_struct(VERIFY_READ, target_fl, arg, 1))
3628 return -TARGET_EFAULT;
bellard7775e9e2003-05-14 22:46:48 +00003629 fl.l_type = tswap16(target_fl->l_type);
3630 fl.l_whence = tswap16(target_fl->l_whence);
3631 fl.l_start = tswapl(target_fl->l_start);
3632 fl.l_len = tswapl(target_fl->l_len);
3633 fl.l_pid = tswapl(target_fl->l_pid);
pbrook53a59602006-03-25 19:31:22 +00003634 unlock_user_struct(target_fl, arg, 0);
bellard9ee1fa22007-11-11 15:11:19 +00003635 ret = get_errno(fcntl(fd, cmd, &fl));
bellard7775e9e2003-05-14 22:46:48 +00003636 break;
ths3b46e622007-09-17 08:09:54 +00003637
bellard7775e9e2003-05-14 22:46:48 +00003638 case TARGET_F_GETLK64:
bellard579a97f2007-11-11 14:26:47 +00003639 if (!lock_user_struct(VERIFY_READ, target_fl64, arg, 1))
3640 return -TARGET_EFAULT;
ths58134272007-03-31 18:59:32 +00003641 fl64.l_type = tswap16(target_fl64->l_type) >> 1;
3642 fl64.l_whence = tswap16(target_fl64->l_whence);
3643 fl64.l_start = tswapl(target_fl64->l_start);
3644 fl64.l_len = tswapl(target_fl64->l_len);
3645 fl64.l_pid = tswap16(target_fl64->l_pid);
3646 unlock_user_struct(target_fl64, arg, 0);
bellard9ee1fa22007-11-11 15:11:19 +00003647 ret = get_errno(fcntl(fd, cmd >> 1, &fl64));
ths43f238d2007-01-05 20:55:49 +00003648 if (ret == 0) {
bellard579a97f2007-11-11 14:26:47 +00003649 if (!lock_user_struct(VERIFY_WRITE, target_fl64, arg, 0))
3650 return -TARGET_EFAULT;
ths43f238d2007-01-05 20:55:49 +00003651 target_fl64->l_type = tswap16(fl64.l_type) >> 1;
3652 target_fl64->l_whence = tswap16(fl64.l_whence);
3653 target_fl64->l_start = tswapl(fl64.l_start);
3654 target_fl64->l_len = tswapl(fl64.l_len);
3655 target_fl64->l_pid = tswapl(fl64.l_pid);
3656 unlock_user_struct(target_fl64, arg, 1);
3657 }
bellard9ee1fa22007-11-11 15:11:19 +00003658 break;
bellard7775e9e2003-05-14 22:46:48 +00003659 case TARGET_F_SETLK64:
3660 case TARGET_F_SETLKW64:
bellard579a97f2007-11-11 14:26:47 +00003661 if (!lock_user_struct(VERIFY_READ, target_fl64, arg, 1))
3662 return -TARGET_EFAULT;
ths43f238d2007-01-05 20:55:49 +00003663 fl64.l_type = tswap16(target_fl64->l_type) >> 1;
3664 fl64.l_whence = tswap16(target_fl64->l_whence);
3665 fl64.l_start = tswapl(target_fl64->l_start);
3666 fl64.l_len = tswapl(target_fl64->l_len);
3667 fl64.l_pid = tswap16(target_fl64->l_pid);
3668 unlock_user_struct(target_fl64, arg, 0);
bellard9ee1fa22007-11-11 15:11:19 +00003669 ret = get_errno(fcntl(fd, cmd >> 1, &fl64));
bellard7775e9e2003-05-14 22:46:48 +00003670 break;
3671
bellardffa65c32004-01-04 23:57:22 +00003672 case F_GETFL:
bellard9ee1fa22007-11-11 15:11:19 +00003673 ret = get_errno(fcntl(fd, cmd, arg));
3674 if (ret >= 0) {
3675 ret = host_to_target_bitmask(ret, fcntl_flags_tbl);
3676 }
bellardffa65c32004-01-04 23:57:22 +00003677 break;
3678
3679 case F_SETFL:
bellard9ee1fa22007-11-11 15:11:19 +00003680 ret = get_errno(fcntl(fd, cmd, target_to_host_bitmask(arg, fcntl_flags_tbl)));
bellardffa65c32004-01-04 23:57:22 +00003681 break;
3682
bellard7775e9e2003-05-14 22:46:48 +00003683 default:
bellard9ee1fa22007-11-11 15:11:19 +00003684 ret = get_errno(fcntl(fd, cmd, arg));
bellard7775e9e2003-05-14 22:46:48 +00003685 break;
3686 }
3687 return ret;
3688}
3689
bellard67867302003-11-23 17:05:30 +00003690#ifdef USE_UID16
bellard7775e9e2003-05-14 22:46:48 +00003691
bellard67867302003-11-23 17:05:30 +00003692static inline int high2lowuid(int uid)
3693{
3694 if (uid > 65535)
3695 return 65534;
3696 else
3697 return uid;
3698}
3699
3700static inline int high2lowgid(int gid)
3701{
3702 if (gid > 65535)
3703 return 65534;
3704 else
3705 return gid;
3706}
3707
3708static inline int low2highuid(int uid)
3709{
3710 if ((int16_t)uid == -1)
3711 return -1;
3712 else
3713 return uid;
3714}
3715
3716static inline int low2highgid(int gid)
3717{
3718 if ((int16_t)gid == -1)
3719 return -1;
3720 else
3721 return gid;
3722}
3723
3724#endif /* USE_UID16 */
bellard1b6b0292003-03-22 17:31:38 +00003725
bellard31e31b82003-02-18 22:55:36 +00003726void syscall_init(void)
3727{
bellard2ab83ea2003-06-15 19:56:46 +00003728 IOCTLEntry *ie;
3729 const argtype *arg_type;
3730 int size;
thsb92c47c2007-11-01 00:07:38 +00003731 int i;
bellard2ab83ea2003-06-15 19:56:46 +00003732
Blue Swirl001faf32009-05-13 17:53:17 +00003733#define STRUCT(name, ...) thunk_register_struct(STRUCT_ ## name, #name, struct_ ## name ## _def);
ths5fafdf22007-09-16 21:08:06 +00003734#define STRUCT_SPECIAL(name) thunk_register_struct_direct(STRUCT_ ## name, #name, &struct_ ## name ## _def);
bellard31e31b82003-02-18 22:55:36 +00003735#include "syscall_types.h"
3736#undef STRUCT
3737#undef STRUCT_SPECIAL
bellard2ab83ea2003-06-15 19:56:46 +00003738
3739 /* we patch the ioctl size if necessary. We rely on the fact that
3740 no ioctl has all the bits at '1' in the size field */
3741 ie = ioctl_entries;
3742 while (ie->target_cmd != 0) {
3743 if (((ie->target_cmd >> TARGET_IOC_SIZESHIFT) & TARGET_IOC_SIZEMASK) ==
3744 TARGET_IOC_SIZEMASK) {
3745 arg_type = ie->arg_type;
3746 if (arg_type[0] != TYPE_PTR) {
ths5fafdf22007-09-16 21:08:06 +00003747 fprintf(stderr, "cannot patch size for ioctl 0x%x\n",
bellard2ab83ea2003-06-15 19:56:46 +00003748 ie->target_cmd);
3749 exit(1);
3750 }
3751 arg_type++;
3752 size = thunk_type_size(arg_type, 0);
ths5fafdf22007-09-16 21:08:06 +00003753 ie->target_cmd = (ie->target_cmd &
bellard2ab83ea2003-06-15 19:56:46 +00003754 ~(TARGET_IOC_SIZEMASK << TARGET_IOC_SIZESHIFT)) |
3755 (size << TARGET_IOC_SIZESHIFT);
3756 }
thsb92c47c2007-11-01 00:07:38 +00003757
3758 /* Build target_to_host_errno_table[] table from
3759 * host_to_target_errno_table[]. */
3760 for (i=0; i < ERRNO_TABLE_SIZE; i++)
3761 target_to_host_errno_table[host_to_target_errno_table[i]] = i;
3762
bellard2ab83ea2003-06-15 19:56:46 +00003763 /* automatic consistency check if same arch */
balrog872ea0c2008-09-21 02:31:19 +00003764#if (defined(__i386__) && defined(TARGET_I386) && defined(TARGET_ABI32)) || \
3765 (defined(__x86_64__) && defined(TARGET_X86_64))
3766 if (unlikely(ie->target_cmd != ie->host_cmd)) {
3767 fprintf(stderr, "ERROR: ioctl(%s): target=0x%x host=0x%x\n",
3768 ie->name, ie->target_cmd, ie->host_cmd);
bellard2ab83ea2003-06-15 19:56:46 +00003769 }
3770#endif
3771 ie++;
3772 }
bellard31e31b82003-02-18 22:55:36 +00003773}
bellardc573ff62004-01-04 15:51:36 +00003774
blueswir1992f48a2007-10-14 16:27:31 +00003775#if TARGET_ABI_BITS == 32
pbrookce4defa2006-02-09 16:49:55 +00003776static inline uint64_t target_offset64(uint32_t word0, uint32_t word1)
3777{
thsaf325d32008-06-10 15:29:15 +00003778#ifdef TARGET_WORDS_BIGENDIAN
pbrookce4defa2006-02-09 16:49:55 +00003779 return ((uint64_t)word0 << 32) | word1;
3780#else
3781 return ((uint64_t)word1 << 32) | word0;
3782#endif
3783}
blueswir1992f48a2007-10-14 16:27:31 +00003784#else /* TARGET_ABI_BITS == 32 */
j_mayer32407102007-09-26 23:01:49 +00003785static inline uint64_t target_offset64(uint64_t word0, uint64_t word1)
3786{
3787 return word0;
3788}
blueswir1992f48a2007-10-14 16:27:31 +00003789#endif /* TARGET_ABI_BITS != 32 */
pbrookce4defa2006-02-09 16:49:55 +00003790
3791#ifdef TARGET_NR_truncate64
blueswir1992f48a2007-10-14 16:27:31 +00003792static inline abi_long target_truncate64(void *cpu_env, const char *arg1,
3793 abi_long arg2,
3794 abi_long arg3,
3795 abi_long arg4)
pbrookce4defa2006-02-09 16:49:55 +00003796{
3797#ifdef TARGET_ARM
3798 if (((CPUARMState *)cpu_env)->eabi)
3799 {
3800 arg2 = arg3;
3801 arg3 = arg4;
3802 }
3803#endif
3804 return get_errno(truncate64(arg1, target_offset64(arg2, arg3)));
3805}
3806#endif
3807
3808#ifdef TARGET_NR_ftruncate64
blueswir1992f48a2007-10-14 16:27:31 +00003809static inline abi_long target_ftruncate64(void *cpu_env, abi_long arg1,
3810 abi_long arg2,
3811 abi_long arg3,
3812 abi_long arg4)
pbrookce4defa2006-02-09 16:49:55 +00003813{
3814#ifdef TARGET_ARM
3815 if (((CPUARMState *)cpu_env)->eabi)
3816 {
3817 arg2 = arg3;
3818 arg3 = arg4;
3819 }
3820#endif
3821 return get_errno(ftruncate64(arg1, target_offset64(arg2, arg3)));
3822}
3823#endif
3824
bellard579a97f2007-11-11 14:26:47 +00003825static inline abi_long target_to_host_timespec(struct timespec *host_ts,
3826 abi_ulong target_addr)
pbrook53a59602006-03-25 19:31:22 +00003827{
3828 struct target_timespec *target_ts;
3829
bellard579a97f2007-11-11 14:26:47 +00003830 if (!lock_user_struct(VERIFY_READ, target_ts, target_addr, 1))
3831 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00003832 host_ts->tv_sec = tswapl(target_ts->tv_sec);
3833 host_ts->tv_nsec = tswapl(target_ts->tv_nsec);
3834 unlock_user_struct(target_ts, target_addr, 0);
bellardb255bfa2008-05-10 21:51:02 +00003835 return 0;
pbrook53a59602006-03-25 19:31:22 +00003836}
3837
bellard579a97f2007-11-11 14:26:47 +00003838static inline abi_long host_to_target_timespec(abi_ulong target_addr,
3839 struct timespec *host_ts)
pbrook53a59602006-03-25 19:31:22 +00003840{
3841 struct target_timespec *target_ts;
3842
bellard579a97f2007-11-11 14:26:47 +00003843 if (!lock_user_struct(VERIFY_WRITE, target_ts, target_addr, 0))
3844 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00003845 target_ts->tv_sec = tswapl(host_ts->tv_sec);
3846 target_ts->tv_nsec = tswapl(host_ts->tv_nsec);
3847 unlock_user_struct(target_ts, target_addr, 1);
bellardb255bfa2008-05-10 21:51:02 +00003848 return 0;
pbrook53a59602006-03-25 19:31:22 +00003849}
3850
aurel329d33b762009-04-08 23:07:05 +00003851#if defined(TARGET_NR_stat64) || defined(TARGET_NR_newfstatat)
balrog6a24a772008-09-20 02:23:36 +00003852static inline abi_long host_to_target_stat64(void *cpu_env,
3853 abi_ulong target_addr,
3854 struct stat *host_st)
3855{
3856#ifdef TARGET_ARM
3857 if (((CPUARMState *)cpu_env)->eabi) {
3858 struct target_eabi_stat64 *target_st;
3859
3860 if (!lock_user_struct(VERIFY_WRITE, target_st, target_addr, 0))
3861 return -TARGET_EFAULT;
3862 memset(target_st, 0, sizeof(struct target_eabi_stat64));
3863 __put_user(host_st->st_dev, &target_st->st_dev);
3864 __put_user(host_st->st_ino, &target_st->st_ino);
3865#ifdef TARGET_STAT64_HAS_BROKEN_ST_INO
3866 __put_user(host_st->st_ino, &target_st->__st_ino);
3867#endif
3868 __put_user(host_st->st_mode, &target_st->st_mode);
3869 __put_user(host_st->st_nlink, &target_st->st_nlink);
3870 __put_user(host_st->st_uid, &target_st->st_uid);
3871 __put_user(host_st->st_gid, &target_st->st_gid);
3872 __put_user(host_st->st_rdev, &target_st->st_rdev);
3873 __put_user(host_st->st_size, &target_st->st_size);
3874 __put_user(host_st->st_blksize, &target_st->st_blksize);
3875 __put_user(host_st->st_blocks, &target_st->st_blocks);
3876 __put_user(host_st->st_atime, &target_st->target_st_atime);
3877 __put_user(host_st->st_mtime, &target_st->target_st_mtime);
3878 __put_user(host_st->st_ctime, &target_st->target_st_ctime);
3879 unlock_user_struct(target_st, target_addr, 1);
3880 } else
3881#endif
3882 {
aurel329d33b762009-04-08 23:07:05 +00003883#if TARGET_LONG_BITS == 64
3884 struct target_stat *target_st;
3885#else
balrog6a24a772008-09-20 02:23:36 +00003886 struct target_stat64 *target_st;
aurel329d33b762009-04-08 23:07:05 +00003887#endif
balrog6a24a772008-09-20 02:23:36 +00003888
3889 if (!lock_user_struct(VERIFY_WRITE, target_st, target_addr, 0))
3890 return -TARGET_EFAULT;
aurel329d33b762009-04-08 23:07:05 +00003891 memset(target_st, 0, sizeof(*target_st));
balrog6a24a772008-09-20 02:23:36 +00003892 __put_user(host_st->st_dev, &target_st->st_dev);
3893 __put_user(host_st->st_ino, &target_st->st_ino);
3894#ifdef TARGET_STAT64_HAS_BROKEN_ST_INO
3895 __put_user(host_st->st_ino, &target_st->__st_ino);
3896#endif
3897 __put_user(host_st->st_mode, &target_st->st_mode);
3898 __put_user(host_st->st_nlink, &target_st->st_nlink);
3899 __put_user(host_st->st_uid, &target_st->st_uid);
3900 __put_user(host_st->st_gid, &target_st->st_gid);
3901 __put_user(host_st->st_rdev, &target_st->st_rdev);
3902 /* XXX: better use of kernel struct */
3903 __put_user(host_st->st_size, &target_st->st_size);
3904 __put_user(host_st->st_blksize, &target_st->st_blksize);
3905 __put_user(host_st->st_blocks, &target_st->st_blocks);
3906 __put_user(host_st->st_atime, &target_st->target_st_atime);
3907 __put_user(host_st->st_mtime, &target_st->target_st_mtime);
3908 __put_user(host_st->st_ctime, &target_st->target_st_ctime);
3909 unlock_user_struct(target_st, target_addr, 1);
3910 }
3911
3912 return 0;
3913}
3914#endif
3915
pbrookbd0c5662008-05-29 14:34:11 +00003916#if defined(USE_NPTL)
3917/* ??? Using host futex calls even when target atomic operations
3918 are not really atomic probably breaks things. However implementing
3919 futexes locally would make futexes shared between multiple processes
3920 tricky. However they're probably useless because guest atomic
3921 operations won't work either. */
blueswir18fcd3692008-08-17 20:26:25 +00003922static int do_futex(target_ulong uaddr, int op, int val, target_ulong timeout,
3923 target_ulong uaddr2, int val3)
pbrookbd0c5662008-05-29 14:34:11 +00003924{
3925 struct timespec ts, *pts;
3926
3927 /* ??? We assume FUTEX_* constants are the same on both host
3928 and target. */
3929 switch (op) {
3930 case FUTEX_WAIT:
3931 if (timeout) {
3932 pts = &ts;
3933 target_to_host_timespec(pts, timeout);
3934 } else {
3935 pts = NULL;
3936 }
3937 return get_errno(sys_futex(g2h(uaddr), FUTEX_WAIT, tswap32(val),
3938 pts, NULL, 0));
3939 case FUTEX_WAKE:
3940 return get_errno(sys_futex(g2h(uaddr), FUTEX_WAKE, val, NULL, NULL, 0));
3941 case FUTEX_FD:
3942 return get_errno(sys_futex(g2h(uaddr), FUTEX_FD, val, NULL, NULL, 0));
3943 case FUTEX_REQUEUE:
3944 return get_errno(sys_futex(g2h(uaddr), FUTEX_REQUEUE, val,
3945 NULL, g2h(uaddr2), 0));
3946 case FUTEX_CMP_REQUEUE:
3947 return get_errno(sys_futex(g2h(uaddr), FUTEX_CMP_REQUEUE, val,
3948 NULL, g2h(uaddr2), tswap32(val3)));
3949 default:
3950 return -TARGET_ENOSYS;
3951 }
3952}
3953#endif
3954
pbrook1d9d8b52009-04-16 15:17:02 +00003955/* Map host to target signal numbers for the wait family of syscalls.
3956 Assume all other status bits are the same. */
3957static int host_to_target_waitstatus(int status)
3958{
3959 if (WIFSIGNALED(status)) {
3960 return host_to_target_signal(WTERMSIG(status)) | (status & ~0x7f);
3961 }
3962 if (WIFSTOPPED(status)) {
3963 return (host_to_target_signal(WSTOPSIG(status)) << 8)
3964 | (status & 0xff);
3965 }
3966 return status;
3967}
3968
pbrooka745ec62008-05-06 15:36:17 +00003969int get_osversion(void)
3970{
3971 static int osversion;
3972 struct new_utsname buf;
3973 const char *s;
3974 int i, n, tmp;
3975 if (osversion)
3976 return osversion;
3977 if (qemu_uname_release && *qemu_uname_release) {
3978 s = qemu_uname_release;
3979 } else {
3980 if (sys_uname(&buf))
3981 return 0;
3982 s = buf.release;
3983 }
3984 tmp = 0;
3985 for (i = 0; i < 3; i++) {
3986 n = 0;
3987 while (*s >= '0' && *s <= '9') {
3988 n *= 10;
3989 n += *s - '0';
3990 s++;
3991 }
3992 tmp = (tmp << 8) + n;
3993 if (*s == '.')
3994 s++;
3995 }
3996 osversion = tmp;
3997 return osversion;
3998}
3999
ths0da46a62007-10-20 20:23:07 +00004000/* do_syscall() should always have a single exit point at the end so
4001 that actions, such as logging of syscall results, can be performed.
4002 All errnos that do_syscall() returns must be -TARGET_<errcode>. */
blueswir1992f48a2007-10-14 16:27:31 +00004003abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
4004 abi_long arg2, abi_long arg3, abi_long arg4,
4005 abi_long arg5, abi_long arg6)
bellard31e31b82003-02-18 22:55:36 +00004006{
blueswir1992f48a2007-10-14 16:27:31 +00004007 abi_long ret;
bellard31e31b82003-02-18 22:55:36 +00004008 struct stat st;
bellard56c8f682005-11-28 22:28:41 +00004009 struct statfs stfs;
pbrook53a59602006-03-25 19:31:22 +00004010 void *p;
ths3b46e622007-09-17 08:09:54 +00004011
bellard72f03902003-02-18 23:33:18 +00004012#ifdef DEBUG
bellardc573ff62004-01-04 15:51:36 +00004013 gemu_log("syscall %d", num);
bellard72f03902003-02-18 23:33:18 +00004014#endif
thsb92c47c2007-11-01 00:07:38 +00004015 if(do_strace)
4016 print_syscall(num, arg1, arg2, arg3, arg4, arg5, arg6);
4017
bellard31e31b82003-02-18 22:55:36 +00004018 switch(num) {
4019 case TARGET_NR_exit:
pbrookc2764712009-03-07 15:24:59 +00004020#ifdef USE_NPTL
4021 /* In old applications this may be used to implement _exit(2).
4022 However in threaded applictions it is used for thread termination,
4023 and _exit_group is used for application termination.
4024 Do thread termination if we have more then one thread. */
4025 /* FIXME: This probably breaks if a signal arrives. We should probably
4026 be disabling signals. */
4027 if (first_cpu->next_cpu) {
Nathan Froyd1e9fa732009-06-03 11:33:08 -07004028 TaskState *ts;
pbrookc2764712009-03-07 15:24:59 +00004029 CPUState **lastp;
4030 CPUState *p;
4031
4032 cpu_list_lock();
4033 lastp = &first_cpu;
4034 p = first_cpu;
4035 while (p && p != (CPUState *)cpu_env) {
4036 lastp = &p->next_cpu;
4037 p = p->next_cpu;
4038 }
4039 /* If we didn't find the CPU for this thread then something is
4040 horribly wrong. */
4041 if (!p)
4042 abort();
4043 /* Remove the CPU from the list. */
4044 *lastp = p->next_cpu;
4045 cpu_list_unlock();
Nathan Froyd1e9fa732009-06-03 11:33:08 -07004046 ts = ((CPUState *)cpu_env)->opaque;
pbrookc2764712009-03-07 15:24:59 +00004047 if (ts->child_tidptr) {
4048 put_user_u32(0, ts->child_tidptr);
4049 sys_futex(g2h(ts->child_tidptr), FUTEX_WAKE, INT_MAX,
4050 NULL, NULL, 0);
4051 }
4052 /* TODO: Free CPU state. */
4053 pthread_exit(NULL);
4054 }
4055#endif
bellard7d132992003-03-06 23:23:54 +00004056#ifdef HAVE_GPROF
4057 _mcleanup();
4058#endif
bellarde9009672005-04-26 20:42:36 +00004059 gdb_exit(cpu_env, arg1);
pbrookc2764712009-03-07 15:24:59 +00004060 _exit(arg1);
bellard31e31b82003-02-18 22:55:36 +00004061 ret = 0; /* avoid warning */
4062 break;
4063 case TARGET_NR_read:
aurel3238d840e2009-01-30 19:48:17 +00004064 if (arg3 == 0)
4065 ret = 0;
4066 else {
4067 if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
4068 goto efault;
4069 ret = get_errno(read(arg1, p, arg3));
4070 unlock_user(p, arg2, ret);
4071 }
bellard31e31b82003-02-18 22:55:36 +00004072 break;
4073 case TARGET_NR_write:
bellard579a97f2007-11-11 14:26:47 +00004074 if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
4075 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004076 ret = get_errno(write(arg1, p, arg3));
4077 unlock_user(p, arg2, 0);
bellard31e31b82003-02-18 22:55:36 +00004078 break;
4079 case TARGET_NR_open:
bellard2f619692007-11-16 10:46:05 +00004080 if (!(p = lock_user_string(arg1)))
4081 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004082 ret = get_errno(open(path(p),
bellardffa65c32004-01-04 23:57:22 +00004083 target_to_host_bitmask(arg2, fcntl_flags_tbl),
4084 arg3));
pbrook53a59602006-03-25 19:31:22 +00004085 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004086 break;
ths82424832007-09-24 09:21:55 +00004087#if defined(TARGET_NR_openat) && defined(__NR_openat)
4088 case TARGET_NR_openat:
bellard579a97f2007-11-11 14:26:47 +00004089 if (!(p = lock_user_string(arg2)))
4090 goto efault;
4091 ret = get_errno(sys_openat(arg1,
4092 path(p),
4093 target_to_host_bitmask(arg3, fcntl_flags_tbl),
4094 arg4));
4095 unlock_user(p, arg2, 0);
ths82424832007-09-24 09:21:55 +00004096 break;
4097#endif
bellard31e31b82003-02-18 22:55:36 +00004098 case TARGET_NR_close:
4099 ret = get_errno(close(arg1));
4100 break;
4101 case TARGET_NR_brk:
pbrook53a59602006-03-25 19:31:22 +00004102 ret = do_brk(arg1);
bellard31e31b82003-02-18 22:55:36 +00004103 break;
4104 case TARGET_NR_fork:
pbrookd865bab2008-06-07 22:12:17 +00004105 ret = get_errno(do_fork(cpu_env, SIGCHLD, 0, 0, 0, 0));
bellard31e31b82003-02-18 22:55:36 +00004106 break;
thse5febef2007-04-01 18:31:35 +00004107#ifdef TARGET_NR_waitpid
bellard31e31b82003-02-18 22:55:36 +00004108 case TARGET_NR_waitpid:
4109 {
pbrook53a59602006-03-25 19:31:22 +00004110 int status;
4111 ret = get_errno(waitpid(arg1, &status, arg3));
bellard2f619692007-11-16 10:46:05 +00004112 if (!is_error(ret) && arg2
pbrook1d9d8b52009-04-16 15:17:02 +00004113 && put_user_s32(host_to_target_waitstatus(status), arg2))
bellard2f619692007-11-16 10:46:05 +00004114 goto efault;
bellard31e31b82003-02-18 22:55:36 +00004115 }
4116 break;
thse5febef2007-04-01 18:31:35 +00004117#endif
pbrookf0cbb612008-05-30 18:20:05 +00004118#ifdef TARGET_NR_waitid
4119 case TARGET_NR_waitid:
4120 {
4121 siginfo_t info;
4122 info.si_pid = 0;
4123 ret = get_errno(waitid(arg1, arg2, &info, arg4));
4124 if (!is_error(ret) && arg3 && info.si_pid != 0) {
4125 if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_siginfo_t), 0)))
4126 goto efault;
4127 host_to_target_siginfo(p, &info);
4128 unlock_user(p, arg3, sizeof(target_siginfo_t));
4129 }
4130 }
4131 break;
4132#endif
j_mayer7a3148a2007-04-05 07:13:51 +00004133#ifdef TARGET_NR_creat /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00004134 case TARGET_NR_creat:
bellard579a97f2007-11-11 14:26:47 +00004135 if (!(p = lock_user_string(arg1)))
4136 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004137 ret = get_errno(creat(p, arg2));
4138 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004139 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004140#endif
bellard31e31b82003-02-18 22:55:36 +00004141 case TARGET_NR_link:
pbrook53a59602006-03-25 19:31:22 +00004142 {
4143 void * p2;
4144 p = lock_user_string(arg1);
4145 p2 = lock_user_string(arg2);
bellard579a97f2007-11-11 14:26:47 +00004146 if (!p || !p2)
4147 ret = -TARGET_EFAULT;
4148 else
4149 ret = get_errno(link(p, p2));
pbrook53a59602006-03-25 19:31:22 +00004150 unlock_user(p2, arg2, 0);
4151 unlock_user(p, arg1, 0);
4152 }
bellard31e31b82003-02-18 22:55:36 +00004153 break;
ths64f0ce42007-09-24 09:25:06 +00004154#if defined(TARGET_NR_linkat) && defined(__NR_linkat)
4155 case TARGET_NR_linkat:
ths64f0ce42007-09-24 09:25:06 +00004156 {
4157 void * p2 = NULL;
bellard579a97f2007-11-11 14:26:47 +00004158 if (!arg2 || !arg4)
4159 goto efault;
ths64f0ce42007-09-24 09:25:06 +00004160 p = lock_user_string(arg2);
4161 p2 = lock_user_string(arg4);
bellard579a97f2007-11-11 14:26:47 +00004162 if (!p || !p2)
ths0da46a62007-10-20 20:23:07 +00004163 ret = -TARGET_EFAULT;
ths64f0ce42007-09-24 09:25:06 +00004164 else
4165 ret = get_errno(sys_linkat(arg1, p, arg3, p2, arg5));
bellard579a97f2007-11-11 14:26:47 +00004166 unlock_user(p, arg2, 0);
4167 unlock_user(p2, arg4, 0);
ths64f0ce42007-09-24 09:25:06 +00004168 }
4169 break;
4170#endif
bellard31e31b82003-02-18 22:55:36 +00004171 case TARGET_NR_unlink:
bellard579a97f2007-11-11 14:26:47 +00004172 if (!(p = lock_user_string(arg1)))
4173 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004174 ret = get_errno(unlink(p));
4175 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004176 break;
ths8170f562007-09-24 09:24:11 +00004177#if defined(TARGET_NR_unlinkat) && defined(__NR_unlinkat)
4178 case TARGET_NR_unlinkat:
bellard579a97f2007-11-11 14:26:47 +00004179 if (!(p = lock_user_string(arg2)))
4180 goto efault;
4181 ret = get_errno(sys_unlinkat(arg1, p, arg3));
4182 unlock_user(p, arg2, 0);
balroged494d82007-12-11 23:23:52 +00004183 break;
balrogb7d35e62007-12-12 00:40:24 +00004184#endif
bellard31e31b82003-02-18 22:55:36 +00004185 case TARGET_NR_execve:
bellard7854b052003-03-29 17:22:23 +00004186 {
4187 char **argp, **envp;
bellardf7341ff2003-03-30 21:00:25 +00004188 int argc, envc;
blueswir1992f48a2007-10-14 16:27:31 +00004189 abi_ulong gp;
4190 abi_ulong guest_argp;
4191 abi_ulong guest_envp;
4192 abi_ulong addr;
bellard7854b052003-03-29 17:22:23 +00004193 char **q;
4194
bellardf7341ff2003-03-30 21:00:25 +00004195 argc = 0;
pbrook53a59602006-03-25 19:31:22 +00004196 guest_argp = arg2;
pbrookda94d262008-05-30 18:24:00 +00004197 for (gp = guest_argp; gp; gp += sizeof(abi_ulong)) {
ths03aa1972007-12-02 06:28:08 +00004198 if (get_user_ual(addr, gp))
bellard2f619692007-11-16 10:46:05 +00004199 goto efault;
ths03aa1972007-12-02 06:28:08 +00004200 if (!addr)
bellard2f619692007-11-16 10:46:05 +00004201 break;
bellard7854b052003-03-29 17:22:23 +00004202 argc++;
bellard2f619692007-11-16 10:46:05 +00004203 }
bellardf7341ff2003-03-30 21:00:25 +00004204 envc = 0;
pbrook53a59602006-03-25 19:31:22 +00004205 guest_envp = arg3;
pbrookda94d262008-05-30 18:24:00 +00004206 for (gp = guest_envp; gp; gp += sizeof(abi_ulong)) {
ths03aa1972007-12-02 06:28:08 +00004207 if (get_user_ual(addr, gp))
bellard2f619692007-11-16 10:46:05 +00004208 goto efault;
ths03aa1972007-12-02 06:28:08 +00004209 if (!addr)
bellard2f619692007-11-16 10:46:05 +00004210 break;
bellard7854b052003-03-29 17:22:23 +00004211 envc++;
bellard2f619692007-11-16 10:46:05 +00004212 }
bellard7854b052003-03-29 17:22:23 +00004213
bellardf7341ff2003-03-30 21:00:25 +00004214 argp = alloca((argc + 1) * sizeof(void *));
4215 envp = alloca((envc + 1) * sizeof(void *));
bellard7854b052003-03-29 17:22:23 +00004216
pbrookda94d262008-05-30 18:24:00 +00004217 for (gp = guest_argp, q = argp; gp;
blueswir1992f48a2007-10-14 16:27:31 +00004218 gp += sizeof(abi_ulong), q++) {
bellard2f619692007-11-16 10:46:05 +00004219 if (get_user_ual(addr, gp))
4220 goto execve_efault;
pbrook53a59602006-03-25 19:31:22 +00004221 if (!addr)
4222 break;
bellard2f619692007-11-16 10:46:05 +00004223 if (!(*q = lock_user_string(addr)))
4224 goto execve_efault;
pbrook53a59602006-03-25 19:31:22 +00004225 }
bellardf7341ff2003-03-30 21:00:25 +00004226 *q = NULL;
4227
pbrookda94d262008-05-30 18:24:00 +00004228 for (gp = guest_envp, q = envp; gp;
blueswir1992f48a2007-10-14 16:27:31 +00004229 gp += sizeof(abi_ulong), q++) {
bellard2f619692007-11-16 10:46:05 +00004230 if (get_user_ual(addr, gp))
4231 goto execve_efault;
pbrook53a59602006-03-25 19:31:22 +00004232 if (!addr)
4233 break;
bellard2f619692007-11-16 10:46:05 +00004234 if (!(*q = lock_user_string(addr)))
4235 goto execve_efault;
pbrook53a59602006-03-25 19:31:22 +00004236 }
bellardf7341ff2003-03-30 21:00:25 +00004237 *q = NULL;
bellard7854b052003-03-29 17:22:23 +00004238
bellard2f619692007-11-16 10:46:05 +00004239 if (!(p = lock_user_string(arg1)))
4240 goto execve_efault;
pbrook53a59602006-03-25 19:31:22 +00004241 ret = get_errno(execve(p, argp, envp));
4242 unlock_user(p, arg1, 0);
4243
bellard2f619692007-11-16 10:46:05 +00004244 goto execve_end;
4245
4246 execve_efault:
4247 ret = -TARGET_EFAULT;
4248
4249 execve_end:
pbrook53a59602006-03-25 19:31:22 +00004250 for (gp = guest_argp, q = argp; *q;
blueswir1992f48a2007-10-14 16:27:31 +00004251 gp += sizeof(abi_ulong), q++) {
bellard2f619692007-11-16 10:46:05 +00004252 if (get_user_ual(addr, gp)
4253 || !addr)
4254 break;
pbrook53a59602006-03-25 19:31:22 +00004255 unlock_user(*q, addr, 0);
4256 }
4257 for (gp = guest_envp, q = envp; *q;
blueswir1992f48a2007-10-14 16:27:31 +00004258 gp += sizeof(abi_ulong), q++) {
bellard2f619692007-11-16 10:46:05 +00004259 if (get_user_ual(addr, gp)
4260 || !addr)
4261 break;
pbrook53a59602006-03-25 19:31:22 +00004262 unlock_user(*q, addr, 0);
4263 }
bellard7854b052003-03-29 17:22:23 +00004264 }
bellard31e31b82003-02-18 22:55:36 +00004265 break;
4266 case TARGET_NR_chdir:
bellard579a97f2007-11-11 14:26:47 +00004267 if (!(p = lock_user_string(arg1)))
4268 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004269 ret = get_errno(chdir(p));
4270 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004271 break;
bellarda315a142005-01-30 22:59:18 +00004272#ifdef TARGET_NR_time
bellard31e31b82003-02-18 22:55:36 +00004273 case TARGET_NR_time:
4274 {
pbrook53a59602006-03-25 19:31:22 +00004275 time_t host_time;
4276 ret = get_errno(time(&host_time));
bellard2f619692007-11-16 10:46:05 +00004277 if (!is_error(ret)
4278 && arg1
4279 && put_user_sal(host_time, arg1))
4280 goto efault;
bellard31e31b82003-02-18 22:55:36 +00004281 }
4282 break;
bellarda315a142005-01-30 22:59:18 +00004283#endif
bellard31e31b82003-02-18 22:55:36 +00004284 case TARGET_NR_mknod:
bellard579a97f2007-11-11 14:26:47 +00004285 if (!(p = lock_user_string(arg1)))
4286 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004287 ret = get_errno(mknod(p, arg2, arg3));
4288 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004289 break;
ths75ac37a2007-09-24 09:23:05 +00004290#if defined(TARGET_NR_mknodat) && defined(__NR_mknodat)
4291 case TARGET_NR_mknodat:
bellard579a97f2007-11-11 14:26:47 +00004292 if (!(p = lock_user_string(arg2)))
4293 goto efault;
4294 ret = get_errno(sys_mknodat(arg1, p, arg3, arg4));
4295 unlock_user(p, arg2, 0);
ths75ac37a2007-09-24 09:23:05 +00004296 break;
4297#endif
bellard31e31b82003-02-18 22:55:36 +00004298 case TARGET_NR_chmod:
bellard579a97f2007-11-11 14:26:47 +00004299 if (!(p = lock_user_string(arg1)))
4300 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004301 ret = get_errno(chmod(p, arg2));
4302 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004303 break;
bellardebc05482003-09-30 21:08:41 +00004304#ifdef TARGET_NR_break
bellard31e31b82003-02-18 22:55:36 +00004305 case TARGET_NR_break:
4306 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004307#endif
4308#ifdef TARGET_NR_oldstat
bellard31e31b82003-02-18 22:55:36 +00004309 case TARGET_NR_oldstat:
4310 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004311#endif
bellard31e31b82003-02-18 22:55:36 +00004312 case TARGET_NR_lseek:
4313 ret = get_errno(lseek(arg1, arg2, arg3));
4314 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004315#ifdef TARGET_NR_getxpid
4316 case TARGET_NR_getxpid:
4317#else
bellard31e31b82003-02-18 22:55:36 +00004318 case TARGET_NR_getpid:
j_mayer7a3148a2007-04-05 07:13:51 +00004319#endif
bellard31e31b82003-02-18 22:55:36 +00004320 ret = get_errno(getpid());
4321 break;
4322 case TARGET_NR_mount:
ths80265912007-02-17 22:25:41 +00004323 {
4324 /* need to look at the data field */
4325 void *p2, *p3;
4326 p = lock_user_string(arg1);
4327 p2 = lock_user_string(arg2);
4328 p3 = lock_user_string(arg3);
bellard579a97f2007-11-11 14:26:47 +00004329 if (!p || !p2 || !p3)
4330 ret = -TARGET_EFAULT;
4331 else
4332 /* FIXME - arg5 should be locked, but it isn't clear how to
4333 * do that since it's not guaranteed to be a NULL-terminated
4334 * string.
4335 */
4336 ret = get_errno(mount(p, p2, p3, (unsigned long)arg4, g2h(arg5)));
4337 unlock_user(p, arg1, 0);
4338 unlock_user(p2, arg2, 0);
4339 unlock_user(p3, arg3, 0);
ths80265912007-02-17 22:25:41 +00004340 break;
4341 }
thse5febef2007-04-01 18:31:35 +00004342#ifdef TARGET_NR_umount
bellard31e31b82003-02-18 22:55:36 +00004343 case TARGET_NR_umount:
bellard579a97f2007-11-11 14:26:47 +00004344 if (!(p = lock_user_string(arg1)))
4345 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004346 ret = get_errno(umount(p));
4347 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004348 break;
thse5febef2007-04-01 18:31:35 +00004349#endif
j_mayer7a3148a2007-04-05 07:13:51 +00004350#ifdef TARGET_NR_stime /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00004351 case TARGET_NR_stime:
4352 {
pbrook53a59602006-03-25 19:31:22 +00004353 time_t host_time;
bellard2f619692007-11-16 10:46:05 +00004354 if (get_user_sal(host_time, arg1))
4355 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004356 ret = get_errno(stime(&host_time));
bellard31e31b82003-02-18 22:55:36 +00004357 }
4358 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004359#endif
bellard31e31b82003-02-18 22:55:36 +00004360 case TARGET_NR_ptrace:
4361 goto unimplemented;
j_mayer7a3148a2007-04-05 07:13:51 +00004362#ifdef TARGET_NR_alarm /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00004363 case TARGET_NR_alarm:
4364 ret = alarm(arg1);
4365 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004366#endif
bellardebc05482003-09-30 21:08:41 +00004367#ifdef TARGET_NR_oldfstat
bellard31e31b82003-02-18 22:55:36 +00004368 case TARGET_NR_oldfstat:
4369 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004370#endif
j_mayer7a3148a2007-04-05 07:13:51 +00004371#ifdef TARGET_NR_pause /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00004372 case TARGET_NR_pause:
4373 ret = get_errno(pause());
4374 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004375#endif
thse5febef2007-04-01 18:31:35 +00004376#ifdef TARGET_NR_utime
bellard31e31b82003-02-18 22:55:36 +00004377 case TARGET_NR_utime:
bellardebc05482003-09-30 21:08:41 +00004378 {
pbrook53a59602006-03-25 19:31:22 +00004379 struct utimbuf tbuf, *host_tbuf;
4380 struct target_utimbuf *target_tbuf;
4381 if (arg2) {
bellard579a97f2007-11-11 14:26:47 +00004382 if (!lock_user_struct(VERIFY_READ, target_tbuf, arg2, 1))
4383 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004384 tbuf.actime = tswapl(target_tbuf->actime);
4385 tbuf.modtime = tswapl(target_tbuf->modtime);
4386 unlock_user_struct(target_tbuf, arg2, 0);
4387 host_tbuf = &tbuf;
bellardf72e8ff2004-05-03 19:23:07 +00004388 } else {
pbrook53a59602006-03-25 19:31:22 +00004389 host_tbuf = NULL;
bellardf72e8ff2004-05-03 19:23:07 +00004390 }
bellard579a97f2007-11-11 14:26:47 +00004391 if (!(p = lock_user_string(arg1)))
4392 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004393 ret = get_errno(utime(p, host_tbuf));
4394 unlock_user(p, arg1, 0);
bellardebc05482003-09-30 21:08:41 +00004395 }
4396 break;
thse5febef2007-04-01 18:31:35 +00004397#endif
bellard978a66f2004-12-06 22:58:05 +00004398 case TARGET_NR_utimes:
4399 {
bellard978a66f2004-12-06 22:58:05 +00004400 struct timeval *tvp, tv[2];
pbrook53a59602006-03-25 19:31:22 +00004401 if (arg2) {
ths788f5ec2007-12-09 02:37:05 +00004402 if (copy_from_user_timeval(&tv[0], arg2)
4403 || copy_from_user_timeval(&tv[1],
4404 arg2 + sizeof(struct target_timeval)))
4405 goto efault;
bellard978a66f2004-12-06 22:58:05 +00004406 tvp = tv;
4407 } else {
4408 tvp = NULL;
4409 }
bellard579a97f2007-11-11 14:26:47 +00004410 if (!(p = lock_user_string(arg1)))
4411 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004412 ret = get_errno(utimes(p, tvp));
4413 unlock_user(p, arg1, 0);
bellard978a66f2004-12-06 22:58:05 +00004414 }
4415 break;
balrogac8a6552008-09-20 02:25:39 +00004416#if defined(TARGET_NR_futimesat) && defined(__NR_futimesat)
4417 case TARGET_NR_futimesat:
4418 {
4419 struct timeval *tvp, tv[2];
4420 if (arg3) {
4421 if (copy_from_user_timeval(&tv[0], arg3)
4422 || copy_from_user_timeval(&tv[1],
4423 arg3 + sizeof(struct target_timeval)))
4424 goto efault;
4425 tvp = tv;
4426 } else {
4427 tvp = NULL;
4428 }
4429 if (!(p = lock_user_string(arg2)))
4430 goto efault;
4431 ret = get_errno(sys_futimesat(arg1, path(p), tvp));
4432 unlock_user(p, arg2, 0);
4433 }
4434 break;
4435#endif
bellardebc05482003-09-30 21:08:41 +00004436#ifdef TARGET_NR_stty
bellard31e31b82003-02-18 22:55:36 +00004437 case TARGET_NR_stty:
4438 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004439#endif
4440#ifdef TARGET_NR_gtty
bellard31e31b82003-02-18 22:55:36 +00004441 case TARGET_NR_gtty:
4442 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004443#endif
bellard31e31b82003-02-18 22:55:36 +00004444 case TARGET_NR_access:
bellard579a97f2007-11-11 14:26:47 +00004445 if (!(p = lock_user_string(arg1)))
4446 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004447 ret = get_errno(access(p, arg2));
4448 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004449 break;
ths92a34c12007-09-24 09:27:49 +00004450#if defined(TARGET_NR_faccessat) && defined(__NR_faccessat)
4451 case TARGET_NR_faccessat:
bellard579a97f2007-11-11 14:26:47 +00004452 if (!(p = lock_user_string(arg2)))
4453 goto efault;
aurel32465c9f02009-04-19 08:52:17 +00004454 ret = get_errno(sys_faccessat(arg1, p, arg3));
bellard579a97f2007-11-11 14:26:47 +00004455 unlock_user(p, arg2, 0);
ths92a34c12007-09-24 09:27:49 +00004456 break;
4457#endif
j_mayer7a3148a2007-04-05 07:13:51 +00004458#ifdef TARGET_NR_nice /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00004459 case TARGET_NR_nice:
4460 ret = get_errno(nice(arg1));
4461 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004462#endif
bellardebc05482003-09-30 21:08:41 +00004463#ifdef TARGET_NR_ftime
bellard31e31b82003-02-18 22:55:36 +00004464 case TARGET_NR_ftime:
4465 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004466#endif
bellard31e31b82003-02-18 22:55:36 +00004467 case TARGET_NR_sync:
bellard04369ff2003-03-20 22:33:23 +00004468 sync();
4469 ret = 0;
bellard31e31b82003-02-18 22:55:36 +00004470 break;
4471 case TARGET_NR_kill:
pbrook4cb05962008-05-30 18:05:19 +00004472 ret = get_errno(kill(arg1, target_to_host_signal(arg2)));
bellard31e31b82003-02-18 22:55:36 +00004473 break;
4474 case TARGET_NR_rename:
pbrook53a59602006-03-25 19:31:22 +00004475 {
4476 void *p2;
4477 p = lock_user_string(arg1);
4478 p2 = lock_user_string(arg2);
bellard579a97f2007-11-11 14:26:47 +00004479 if (!p || !p2)
4480 ret = -TARGET_EFAULT;
4481 else
4482 ret = get_errno(rename(p, p2));
pbrook53a59602006-03-25 19:31:22 +00004483 unlock_user(p2, arg2, 0);
4484 unlock_user(p, arg1, 0);
4485 }
bellard31e31b82003-02-18 22:55:36 +00004486 break;
ths722183f2007-09-24 09:24:37 +00004487#if defined(TARGET_NR_renameat) && defined(__NR_renameat)
4488 case TARGET_NR_renameat:
ths722183f2007-09-24 09:24:37 +00004489 {
bellard579a97f2007-11-11 14:26:47 +00004490 void *p2;
ths722183f2007-09-24 09:24:37 +00004491 p = lock_user_string(arg2);
4492 p2 = lock_user_string(arg4);
bellard579a97f2007-11-11 14:26:47 +00004493 if (!p || !p2)
ths0da46a62007-10-20 20:23:07 +00004494 ret = -TARGET_EFAULT;
ths722183f2007-09-24 09:24:37 +00004495 else
4496 ret = get_errno(sys_renameat(arg1, p, arg3, p2));
bellard579a97f2007-11-11 14:26:47 +00004497 unlock_user(p2, arg4, 0);
4498 unlock_user(p, arg2, 0);
ths722183f2007-09-24 09:24:37 +00004499 }
4500 break;
4501#endif
bellard31e31b82003-02-18 22:55:36 +00004502 case TARGET_NR_mkdir:
bellard579a97f2007-11-11 14:26:47 +00004503 if (!(p = lock_user_string(arg1)))
4504 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004505 ret = get_errno(mkdir(p, arg2));
4506 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004507 break;
ths4472ad02007-09-24 09:22:32 +00004508#if defined(TARGET_NR_mkdirat) && defined(__NR_mkdirat)
4509 case TARGET_NR_mkdirat:
bellard579a97f2007-11-11 14:26:47 +00004510 if (!(p = lock_user_string(arg2)))
4511 goto efault;
4512 ret = get_errno(sys_mkdirat(arg1, p, arg3));
4513 unlock_user(p, arg2, 0);
ths4472ad02007-09-24 09:22:32 +00004514 break;
4515#endif
bellard31e31b82003-02-18 22:55:36 +00004516 case TARGET_NR_rmdir:
bellard579a97f2007-11-11 14:26:47 +00004517 if (!(p = lock_user_string(arg1)))
4518 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004519 ret = get_errno(rmdir(p));
4520 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004521 break;
4522 case TARGET_NR_dup:
4523 ret = get_errno(dup(arg1));
4524 break;
4525 case TARGET_NR_pipe:
4526 {
pbrook53a59602006-03-25 19:31:22 +00004527 int host_pipe[2];
4528 ret = get_errno(pipe(host_pipe));
bellard31e31b82003-02-18 22:55:36 +00004529 if (!is_error(ret)) {
thsc12ab052007-06-01 11:50:36 +00004530#if defined(TARGET_MIPS)
thsead93602007-09-06 00:18:15 +00004531 CPUMIPSState *env = (CPUMIPSState*)cpu_env;
thsb5dc7732008-06-27 10:02:35 +00004532 env->active_tc.gpr[3] = host_pipe[1];
thsc12ab052007-06-01 11:50:36 +00004533 ret = host_pipe[0];
aurel32b5eff352008-03-11 23:30:22 +00004534#elif defined(TARGET_SH4)
4535 ((CPUSH4State*)cpu_env)->gregs[1] = host_pipe[1];
4536 ret = host_pipe[0];
thsc12ab052007-06-01 11:50:36 +00004537#else
bellard2f619692007-11-16 10:46:05 +00004538 if (put_user_s32(host_pipe[0], arg1)
4539 || put_user_s32(host_pipe[1], arg1 + sizeof(host_pipe[0])))
4540 goto efault;
thsc12ab052007-06-01 11:50:36 +00004541#endif
bellard31e31b82003-02-18 22:55:36 +00004542 }
4543 }
4544 break;
4545 case TARGET_NR_times:
bellard32f36bc2003-03-30 21:29:48 +00004546 {
pbrook53a59602006-03-25 19:31:22 +00004547 struct target_tms *tmsp;
bellard32f36bc2003-03-30 21:29:48 +00004548 struct tms tms;
4549 ret = get_errno(times(&tms));
pbrook53a59602006-03-25 19:31:22 +00004550 if (arg1) {
bellard579a97f2007-11-11 14:26:47 +00004551 tmsp = lock_user(VERIFY_WRITE, arg1, sizeof(struct target_tms), 0);
4552 if (!tmsp)
4553 goto efault;
bellardc596ed12003-07-13 17:32:31 +00004554 tmsp->tms_utime = tswapl(host_to_target_clock_t(tms.tms_utime));
4555 tmsp->tms_stime = tswapl(host_to_target_clock_t(tms.tms_stime));
4556 tmsp->tms_cutime = tswapl(host_to_target_clock_t(tms.tms_cutime));
4557 tmsp->tms_cstime = tswapl(host_to_target_clock_t(tms.tms_cstime));
bellard32f36bc2003-03-30 21:29:48 +00004558 }
bellardc596ed12003-07-13 17:32:31 +00004559 if (!is_error(ret))
4560 ret = host_to_target_clock_t(ret);
bellard32f36bc2003-03-30 21:29:48 +00004561 }
4562 break;
bellardebc05482003-09-30 21:08:41 +00004563#ifdef TARGET_NR_prof
bellard31e31b82003-02-18 22:55:36 +00004564 case TARGET_NR_prof:
4565 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004566#endif
thse5febef2007-04-01 18:31:35 +00004567#ifdef TARGET_NR_signal
bellard31e31b82003-02-18 22:55:36 +00004568 case TARGET_NR_signal:
4569 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00004570#endif
bellard31e31b82003-02-18 22:55:36 +00004571 case TARGET_NR_acct:
aurel3238d840e2009-01-30 19:48:17 +00004572 if (arg1 == 0) {
4573 ret = get_errno(acct(NULL));
4574 } else {
4575 if (!(p = lock_user_string(arg1)))
4576 goto efault;
4577 ret = get_errno(acct(path(p)));
4578 unlock_user(p, arg1, 0);
4579 }
pbrook24836682006-04-16 14:14:53 +00004580 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004581#ifdef TARGET_NR_umount2 /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00004582 case TARGET_NR_umount2:
bellard579a97f2007-11-11 14:26:47 +00004583 if (!(p = lock_user_string(arg1)))
4584 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004585 ret = get_errno(umount2(p, arg2));
4586 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004587 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004588#endif
bellardebc05482003-09-30 21:08:41 +00004589#ifdef TARGET_NR_lock
bellard31e31b82003-02-18 22:55:36 +00004590 case TARGET_NR_lock:
4591 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004592#endif
bellard31e31b82003-02-18 22:55:36 +00004593 case TARGET_NR_ioctl:
4594 ret = do_ioctl(arg1, arg2, arg3);
4595 break;
4596 case TARGET_NR_fcntl:
bellard9ee1fa22007-11-11 15:11:19 +00004597 ret = do_fcntl(arg1, arg2, arg3);
bellard31e31b82003-02-18 22:55:36 +00004598 break;
bellardebc05482003-09-30 21:08:41 +00004599#ifdef TARGET_NR_mpx
bellard31e31b82003-02-18 22:55:36 +00004600 case TARGET_NR_mpx:
4601 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004602#endif
bellard31e31b82003-02-18 22:55:36 +00004603 case TARGET_NR_setpgid:
4604 ret = get_errno(setpgid(arg1, arg2));
4605 break;
bellardebc05482003-09-30 21:08:41 +00004606#ifdef TARGET_NR_ulimit
bellard31e31b82003-02-18 22:55:36 +00004607 case TARGET_NR_ulimit:
4608 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004609#endif
4610#ifdef TARGET_NR_oldolduname
bellard31e31b82003-02-18 22:55:36 +00004611 case TARGET_NR_oldolduname:
4612 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004613#endif
bellard31e31b82003-02-18 22:55:36 +00004614 case TARGET_NR_umask:
4615 ret = get_errno(umask(arg1));
4616 break;
4617 case TARGET_NR_chroot:
bellard579a97f2007-11-11 14:26:47 +00004618 if (!(p = lock_user_string(arg1)))
4619 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004620 ret = get_errno(chroot(p));
4621 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004622 break;
4623 case TARGET_NR_ustat:
4624 goto unimplemented;
4625 case TARGET_NR_dup2:
4626 ret = get_errno(dup2(arg1, arg2));
4627 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004628#ifdef TARGET_NR_getppid /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00004629 case TARGET_NR_getppid:
4630 ret = get_errno(getppid());
4631 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004632#endif
bellard31e31b82003-02-18 22:55:36 +00004633 case TARGET_NR_getpgrp:
4634 ret = get_errno(getpgrp());
4635 break;
4636 case TARGET_NR_setsid:
4637 ret = get_errno(setsid());
4638 break;
thse5febef2007-04-01 18:31:35 +00004639#ifdef TARGET_NR_sigaction
bellard31e31b82003-02-18 22:55:36 +00004640 case TARGET_NR_sigaction:
bellard31e31b82003-02-18 22:55:36 +00004641 {
ths388bb212007-05-13 13:58:00 +00004642#if !defined(TARGET_MIPS)
pbrook53a59602006-03-25 19:31:22 +00004643 struct target_old_sigaction *old_act;
bellard66fb9762003-03-23 01:06:05 +00004644 struct target_sigaction act, oact, *pact;
pbrook53a59602006-03-25 19:31:22 +00004645 if (arg2) {
bellard579a97f2007-11-11 14:26:47 +00004646 if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1))
4647 goto efault;
bellard66fb9762003-03-23 01:06:05 +00004648 act._sa_handler = old_act->_sa_handler;
4649 target_siginitset(&act.sa_mask, old_act->sa_mask);
4650 act.sa_flags = old_act->sa_flags;
4651 act.sa_restorer = old_act->sa_restorer;
pbrook53a59602006-03-25 19:31:22 +00004652 unlock_user_struct(old_act, arg2, 0);
bellard66fb9762003-03-23 01:06:05 +00004653 pact = &act;
4654 } else {
4655 pact = NULL;
4656 }
4657 ret = get_errno(do_sigaction(arg1, pact, &oact));
pbrook53a59602006-03-25 19:31:22 +00004658 if (!is_error(ret) && arg3) {
bellard579a97f2007-11-11 14:26:47 +00004659 if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0))
4660 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004661 old_act->_sa_handler = oact._sa_handler;
4662 old_act->sa_mask = oact.sa_mask.sig[0];
4663 old_act->sa_flags = oact.sa_flags;
4664 old_act->sa_restorer = oact.sa_restorer;
4665 unlock_user_struct(old_act, arg3, 1);
bellard66fb9762003-03-23 01:06:05 +00004666 }
ths388bb212007-05-13 13:58:00 +00004667#else
bellard106ec872006-06-27 21:08:10 +00004668 struct target_sigaction act, oact, *pact, *old_act;
4669
4670 if (arg2) {
bellard579a97f2007-11-11 14:26:47 +00004671 if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1))
4672 goto efault;
bellard106ec872006-06-27 21:08:10 +00004673 act._sa_handler = old_act->_sa_handler;
4674 target_siginitset(&act.sa_mask, old_act->sa_mask.sig[0]);
4675 act.sa_flags = old_act->sa_flags;
4676 unlock_user_struct(old_act, arg2, 0);
4677 pact = &act;
4678 } else {
4679 pact = NULL;
4680 }
4681
4682 ret = get_errno(do_sigaction(arg1, pact, &oact));
4683
4684 if (!is_error(ret) && arg3) {
bellard579a97f2007-11-11 14:26:47 +00004685 if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0))
4686 goto efault;
bellard106ec872006-06-27 21:08:10 +00004687 old_act->_sa_handler = oact._sa_handler;
4688 old_act->sa_flags = oact.sa_flags;
4689 old_act->sa_mask.sig[0] = oact.sa_mask.sig[0];
4690 old_act->sa_mask.sig[1] = 0;
4691 old_act->sa_mask.sig[2] = 0;
4692 old_act->sa_mask.sig[3] = 0;
4693 unlock_user_struct(old_act, arg3, 1);
4694 }
ths388bb212007-05-13 13:58:00 +00004695#endif
bellard31e31b82003-02-18 22:55:36 +00004696 }
4697 break;
thse5febef2007-04-01 18:31:35 +00004698#endif
bellard66fb9762003-03-23 01:06:05 +00004699 case TARGET_NR_rt_sigaction:
pbrook53a59602006-03-25 19:31:22 +00004700 {
4701 struct target_sigaction *act;
4702 struct target_sigaction *oact;
4703
bellard579a97f2007-11-11 14:26:47 +00004704 if (arg2) {
4705 if (!lock_user_struct(VERIFY_READ, act, arg2, 1))
4706 goto efault;
4707 } else
pbrook53a59602006-03-25 19:31:22 +00004708 act = NULL;
bellard579a97f2007-11-11 14:26:47 +00004709 if (arg3) {
4710 if (!lock_user_struct(VERIFY_WRITE, oact, arg3, 0)) {
4711 ret = -TARGET_EFAULT;
4712 goto rt_sigaction_fail;
4713 }
4714 } else
pbrook53a59602006-03-25 19:31:22 +00004715 oact = NULL;
4716 ret = get_errno(do_sigaction(arg1, act, oact));
bellard579a97f2007-11-11 14:26:47 +00004717 rt_sigaction_fail:
4718 if (act)
pbrook53a59602006-03-25 19:31:22 +00004719 unlock_user_struct(act, arg2, 0);
bellard579a97f2007-11-11 14:26:47 +00004720 if (oact)
pbrook53a59602006-03-25 19:31:22 +00004721 unlock_user_struct(oact, arg3, 1);
4722 }
bellard66fb9762003-03-23 01:06:05 +00004723 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004724#ifdef TARGET_NR_sgetmask /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00004725 case TARGET_NR_sgetmask:
bellard66fb9762003-03-23 01:06:05 +00004726 {
4727 sigset_t cur_set;
blueswir1992f48a2007-10-14 16:27:31 +00004728 abi_ulong target_set;
bellard66fb9762003-03-23 01:06:05 +00004729 sigprocmask(0, NULL, &cur_set);
4730 host_to_target_old_sigset(&target_set, &cur_set);
4731 ret = target_set;
4732 }
4733 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004734#endif
4735#ifdef TARGET_NR_ssetmask /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00004736 case TARGET_NR_ssetmask:
bellard66fb9762003-03-23 01:06:05 +00004737 {
4738 sigset_t set, oset, cur_set;
blueswir1992f48a2007-10-14 16:27:31 +00004739 abi_ulong target_set = arg1;
bellard66fb9762003-03-23 01:06:05 +00004740 sigprocmask(0, NULL, &cur_set);
4741 target_to_host_old_sigset(&set, &target_set);
4742 sigorset(&set, &set, &cur_set);
4743 sigprocmask(SIG_SETMASK, &set, &oset);
4744 host_to_target_old_sigset(&target_set, &oset);
4745 ret = target_set;
4746 }
4747 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004748#endif
thse5febef2007-04-01 18:31:35 +00004749#ifdef TARGET_NR_sigprocmask
bellard66fb9762003-03-23 01:06:05 +00004750 case TARGET_NR_sigprocmask:
4751 {
4752 int how = arg1;
4753 sigset_t set, oldset, *set_ptr;
ths3b46e622007-09-17 08:09:54 +00004754
pbrook53a59602006-03-25 19:31:22 +00004755 if (arg2) {
bellard66fb9762003-03-23 01:06:05 +00004756 switch(how) {
4757 case TARGET_SIG_BLOCK:
4758 how = SIG_BLOCK;
4759 break;
4760 case TARGET_SIG_UNBLOCK:
4761 how = SIG_UNBLOCK;
4762 break;
4763 case TARGET_SIG_SETMASK:
4764 how = SIG_SETMASK;
4765 break;
4766 default:
ths0da46a62007-10-20 20:23:07 +00004767 ret = -TARGET_EINVAL;
bellard66fb9762003-03-23 01:06:05 +00004768 goto fail;
4769 }
bellard579a97f2007-11-11 14:26:47 +00004770 if (!(p = lock_user(VERIFY_READ, arg2, sizeof(target_sigset_t), 1)))
4771 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004772 target_to_host_old_sigset(&set, p);
4773 unlock_user(p, arg2, 0);
bellard66fb9762003-03-23 01:06:05 +00004774 set_ptr = &set;
4775 } else {
4776 how = 0;
4777 set_ptr = NULL;
4778 }
4779 ret = get_errno(sigprocmask(arg1, set_ptr, &oldset));
pbrook53a59602006-03-25 19:31:22 +00004780 if (!is_error(ret) && arg3) {
bellard579a97f2007-11-11 14:26:47 +00004781 if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0)))
4782 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004783 host_to_target_old_sigset(p, &oldset);
4784 unlock_user(p, arg3, sizeof(target_sigset_t));
bellard66fb9762003-03-23 01:06:05 +00004785 }
4786 }
4787 break;
thse5febef2007-04-01 18:31:35 +00004788#endif
bellard66fb9762003-03-23 01:06:05 +00004789 case TARGET_NR_rt_sigprocmask:
4790 {
4791 int how = arg1;
4792 sigset_t set, oldset, *set_ptr;
ths3b46e622007-09-17 08:09:54 +00004793
pbrook53a59602006-03-25 19:31:22 +00004794 if (arg2) {
bellard66fb9762003-03-23 01:06:05 +00004795 switch(how) {
4796 case TARGET_SIG_BLOCK:
4797 how = SIG_BLOCK;
4798 break;
4799 case TARGET_SIG_UNBLOCK:
4800 how = SIG_UNBLOCK;
4801 break;
4802 case TARGET_SIG_SETMASK:
4803 how = SIG_SETMASK;
4804 break;
4805 default:
ths0da46a62007-10-20 20:23:07 +00004806 ret = -TARGET_EINVAL;
bellard66fb9762003-03-23 01:06:05 +00004807 goto fail;
4808 }
bellard579a97f2007-11-11 14:26:47 +00004809 if (!(p = lock_user(VERIFY_READ, arg2, sizeof(target_sigset_t), 1)))
4810 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004811 target_to_host_sigset(&set, p);
4812 unlock_user(p, arg2, 0);
bellard66fb9762003-03-23 01:06:05 +00004813 set_ptr = &set;
4814 } else {
4815 how = 0;
4816 set_ptr = NULL;
4817 }
4818 ret = get_errno(sigprocmask(how, set_ptr, &oldset));
pbrook53a59602006-03-25 19:31:22 +00004819 if (!is_error(ret) && arg3) {
bellard579a97f2007-11-11 14:26:47 +00004820 if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0)))
4821 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004822 host_to_target_sigset(p, &oldset);
4823 unlock_user(p, arg3, sizeof(target_sigset_t));
bellard66fb9762003-03-23 01:06:05 +00004824 }
4825 }
4826 break;
thse5febef2007-04-01 18:31:35 +00004827#ifdef TARGET_NR_sigpending
bellard66fb9762003-03-23 01:06:05 +00004828 case TARGET_NR_sigpending:
4829 {
4830 sigset_t set;
4831 ret = get_errno(sigpending(&set));
4832 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00004833 if (!(p = lock_user(VERIFY_WRITE, arg1, sizeof(target_sigset_t), 0)))
4834 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004835 host_to_target_old_sigset(p, &set);
4836 unlock_user(p, arg1, sizeof(target_sigset_t));
bellard66fb9762003-03-23 01:06:05 +00004837 }
4838 }
4839 break;
thse5febef2007-04-01 18:31:35 +00004840#endif
bellard66fb9762003-03-23 01:06:05 +00004841 case TARGET_NR_rt_sigpending:
4842 {
4843 sigset_t set;
4844 ret = get_errno(sigpending(&set));
4845 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00004846 if (!(p = lock_user(VERIFY_WRITE, arg1, sizeof(target_sigset_t), 0)))
4847 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004848 host_to_target_sigset(p, &set);
4849 unlock_user(p, arg1, sizeof(target_sigset_t));
bellard66fb9762003-03-23 01:06:05 +00004850 }
4851 }
4852 break;
thse5febef2007-04-01 18:31:35 +00004853#ifdef TARGET_NR_sigsuspend
bellard66fb9762003-03-23 01:06:05 +00004854 case TARGET_NR_sigsuspend:
4855 {
4856 sigset_t set;
bellard579a97f2007-11-11 14:26:47 +00004857 if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
4858 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004859 target_to_host_old_sigset(&set, p);
4860 unlock_user(p, arg1, 0);
bellard66fb9762003-03-23 01:06:05 +00004861 ret = get_errno(sigsuspend(&set));
4862 }
4863 break;
thse5febef2007-04-01 18:31:35 +00004864#endif
bellard66fb9762003-03-23 01:06:05 +00004865 case TARGET_NR_rt_sigsuspend:
4866 {
4867 sigset_t set;
bellard579a97f2007-11-11 14:26:47 +00004868 if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
4869 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004870 target_to_host_sigset(&set, p);
4871 unlock_user(p, arg1, 0);
bellard66fb9762003-03-23 01:06:05 +00004872 ret = get_errno(sigsuspend(&set));
4873 }
4874 break;
4875 case TARGET_NR_rt_sigtimedwait:
4876 {
bellard66fb9762003-03-23 01:06:05 +00004877 sigset_t set;
4878 struct timespec uts, *puts;
4879 siginfo_t uinfo;
ths3b46e622007-09-17 08:09:54 +00004880
bellard579a97f2007-11-11 14:26:47 +00004881 if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
4882 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004883 target_to_host_sigset(&set, p);
4884 unlock_user(p, arg1, 0);
4885 if (arg3) {
bellard66fb9762003-03-23 01:06:05 +00004886 puts = &uts;
pbrook53a59602006-03-25 19:31:22 +00004887 target_to_host_timespec(puts, arg3);
bellard66fb9762003-03-23 01:06:05 +00004888 } else {
4889 puts = NULL;
4890 }
4891 ret = get_errno(sigtimedwait(&set, &uinfo, puts));
pbrook53a59602006-03-25 19:31:22 +00004892 if (!is_error(ret) && arg2) {
pbrooke1e3f302008-05-30 21:53:38 +00004893 if (!(p = lock_user(VERIFY_WRITE, arg2, sizeof(target_siginfo_t), 0)))
bellard579a97f2007-11-11 14:26:47 +00004894 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004895 host_to_target_siginfo(p, &uinfo);
pbrooke1e3f302008-05-30 21:53:38 +00004896 unlock_user(p, arg2, sizeof(target_siginfo_t));
bellard66fb9762003-03-23 01:06:05 +00004897 }
4898 }
4899 break;
4900 case TARGET_NR_rt_sigqueueinfo:
4901 {
4902 siginfo_t uinfo;
bellard579a97f2007-11-11 14:26:47 +00004903 if (!(p = lock_user(VERIFY_READ, arg3, sizeof(target_sigset_t), 1)))
4904 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004905 target_to_host_siginfo(&uinfo, p);
4906 unlock_user(p, arg1, 0);
bellard66fb9762003-03-23 01:06:05 +00004907 ret = get_errno(sys_rt_sigqueueinfo(arg1, arg2, &uinfo));
4908 }
4909 break;
thse5febef2007-04-01 18:31:35 +00004910#ifdef TARGET_NR_sigreturn
bellard66fb9762003-03-23 01:06:05 +00004911 case TARGET_NR_sigreturn:
4912 /* NOTE: ret is eax, so not transcoding must be done */
4913 ret = do_sigreturn(cpu_env);
4914 break;
thse5febef2007-04-01 18:31:35 +00004915#endif
bellard66fb9762003-03-23 01:06:05 +00004916 case TARGET_NR_rt_sigreturn:
4917 /* NOTE: ret is eax, so not transcoding must be done */
4918 ret = do_rt_sigreturn(cpu_env);
4919 break;
bellard31e31b82003-02-18 22:55:36 +00004920 case TARGET_NR_sethostname:
bellard579a97f2007-11-11 14:26:47 +00004921 if (!(p = lock_user_string(arg1)))
4922 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004923 ret = get_errno(sethostname(p, arg2));
4924 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004925 break;
4926 case TARGET_NR_setrlimit:
bellard9de5e442003-03-23 16:49:39 +00004927 {
4928 /* XXX: convert resource ? */
4929 int resource = arg1;
pbrook53a59602006-03-25 19:31:22 +00004930 struct target_rlimit *target_rlim;
bellard9de5e442003-03-23 16:49:39 +00004931 struct rlimit rlim;
bellard579a97f2007-11-11 14:26:47 +00004932 if (!lock_user_struct(VERIFY_READ, target_rlim, arg2, 1))
4933 goto efault;
bellard9de5e442003-03-23 16:49:39 +00004934 rlim.rlim_cur = tswapl(target_rlim->rlim_cur);
4935 rlim.rlim_max = tswapl(target_rlim->rlim_max);
pbrook53a59602006-03-25 19:31:22 +00004936 unlock_user_struct(target_rlim, arg2, 0);
bellard9de5e442003-03-23 16:49:39 +00004937 ret = get_errno(setrlimit(resource, &rlim));
4938 }
4939 break;
bellard31e31b82003-02-18 22:55:36 +00004940 case TARGET_NR_getrlimit:
bellard9de5e442003-03-23 16:49:39 +00004941 {
4942 /* XXX: convert resource ? */
4943 int resource = arg1;
pbrook53a59602006-03-25 19:31:22 +00004944 struct target_rlimit *target_rlim;
bellard9de5e442003-03-23 16:49:39 +00004945 struct rlimit rlim;
ths3b46e622007-09-17 08:09:54 +00004946
bellard9de5e442003-03-23 16:49:39 +00004947 ret = get_errno(getrlimit(resource, &rlim));
4948 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00004949 if (!lock_user_struct(VERIFY_WRITE, target_rlim, arg2, 0))
4950 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004951 rlim.rlim_cur = tswapl(target_rlim->rlim_cur);
4952 rlim.rlim_max = tswapl(target_rlim->rlim_max);
4953 unlock_user_struct(target_rlim, arg2, 1);
bellard9de5e442003-03-23 16:49:39 +00004954 }
4955 }
4956 break;
bellard31e31b82003-02-18 22:55:36 +00004957 case TARGET_NR_getrusage:
bellardb4091862003-05-16 15:39:34 +00004958 {
4959 struct rusage rusage;
bellardb4091862003-05-16 15:39:34 +00004960 ret = get_errno(getrusage(arg1, &rusage));
4961 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00004962 host_to_target_rusage(arg2, &rusage);
bellardb4091862003-05-16 15:39:34 +00004963 }
4964 }
4965 break;
bellard31e31b82003-02-18 22:55:36 +00004966 case TARGET_NR_gettimeofday:
4967 {
bellard31e31b82003-02-18 22:55:36 +00004968 struct timeval tv;
4969 ret = get_errno(gettimeofday(&tv, NULL));
4970 if (!is_error(ret)) {
ths788f5ec2007-12-09 02:37:05 +00004971 if (copy_to_user_timeval(arg1, &tv))
4972 goto efault;
bellard31e31b82003-02-18 22:55:36 +00004973 }
4974 }
4975 break;
4976 case TARGET_NR_settimeofday:
4977 {
bellard31e31b82003-02-18 22:55:36 +00004978 struct timeval tv;
ths788f5ec2007-12-09 02:37:05 +00004979 if (copy_from_user_timeval(&tv, arg1))
4980 goto efault;
bellard31e31b82003-02-18 22:55:36 +00004981 ret = get_errno(settimeofday(&tv, NULL));
4982 }
4983 break;
bellard048f6b42005-11-26 18:47:20 +00004984#ifdef TARGET_NR_select
bellard31e31b82003-02-18 22:55:36 +00004985 case TARGET_NR_select:
bellardf2674e32003-07-09 12:26:09 +00004986 {
pbrook53a59602006-03-25 19:31:22 +00004987 struct target_sel_arg_struct *sel;
blueswir1992f48a2007-10-14 16:27:31 +00004988 abi_ulong inp, outp, exp, tvp;
pbrook53a59602006-03-25 19:31:22 +00004989 long nsel;
4990
bellard579a97f2007-11-11 14:26:47 +00004991 if (!lock_user_struct(VERIFY_READ, sel, arg1, 1))
4992 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004993 nsel = tswapl(sel->n);
4994 inp = tswapl(sel->inp);
4995 outp = tswapl(sel->outp);
4996 exp = tswapl(sel->exp);
4997 tvp = tswapl(sel->tvp);
4998 unlock_user_struct(sel, arg1, 0);
4999 ret = do_select(nsel, inp, outp, exp, tvp);
bellardf2674e32003-07-09 12:26:09 +00005000 }
5001 break;
bellard048f6b42005-11-26 18:47:20 +00005002#endif
bellard31e31b82003-02-18 22:55:36 +00005003 case TARGET_NR_symlink:
pbrook53a59602006-03-25 19:31:22 +00005004 {
5005 void *p2;
5006 p = lock_user_string(arg1);
5007 p2 = lock_user_string(arg2);
bellard579a97f2007-11-11 14:26:47 +00005008 if (!p || !p2)
5009 ret = -TARGET_EFAULT;
5010 else
5011 ret = get_errno(symlink(p, p2));
pbrook53a59602006-03-25 19:31:22 +00005012 unlock_user(p2, arg2, 0);
5013 unlock_user(p, arg1, 0);
5014 }
bellard31e31b82003-02-18 22:55:36 +00005015 break;
thsf0b62432007-09-24 09:25:40 +00005016#if defined(TARGET_NR_symlinkat) && defined(__NR_symlinkat)
5017 case TARGET_NR_symlinkat:
thsf0b62432007-09-24 09:25:40 +00005018 {
bellard579a97f2007-11-11 14:26:47 +00005019 void *p2;
thsf0b62432007-09-24 09:25:40 +00005020 p = lock_user_string(arg1);
5021 p2 = lock_user_string(arg3);
bellard579a97f2007-11-11 14:26:47 +00005022 if (!p || !p2)
ths0da46a62007-10-20 20:23:07 +00005023 ret = -TARGET_EFAULT;
thsf0b62432007-09-24 09:25:40 +00005024 else
5025 ret = get_errno(sys_symlinkat(p, arg2, p2));
bellard579a97f2007-11-11 14:26:47 +00005026 unlock_user(p2, arg3, 0);
5027 unlock_user(p, arg1, 0);
thsf0b62432007-09-24 09:25:40 +00005028 }
5029 break;
5030#endif
bellardebc05482003-09-30 21:08:41 +00005031#ifdef TARGET_NR_oldlstat
bellard31e31b82003-02-18 22:55:36 +00005032 case TARGET_NR_oldlstat:
5033 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00005034#endif
bellard31e31b82003-02-18 22:55:36 +00005035 case TARGET_NR_readlink:
pbrook53a59602006-03-25 19:31:22 +00005036 {
aurel32d088d662009-01-30 20:09:01 +00005037 void *p2, *temp;
pbrook53a59602006-03-25 19:31:22 +00005038 p = lock_user_string(arg1);
bellard579a97f2007-11-11 14:26:47 +00005039 p2 = lock_user(VERIFY_WRITE, arg2, arg3, 0);
5040 if (!p || !p2)
5041 ret = -TARGET_EFAULT;
aurel32d088d662009-01-30 20:09:01 +00005042 else {
5043 if (strncmp((const char *)p, "/proc/self/exe", 14) == 0) {
5044 char real[PATH_MAX];
5045 temp = realpath(exec_path,real);
5046 ret = (temp==NULL) ? get_errno(-1) : strlen(real) ;
5047 snprintf((char *)p2, arg3, "%s", real);
5048 }
5049 else
5050 ret = get_errno(readlink(path(p), p2, arg3));
aurel32d088d662009-01-30 20:09:01 +00005051 }
pbrook53a59602006-03-25 19:31:22 +00005052 unlock_user(p2, arg2, ret);
5053 unlock_user(p, arg1, 0);
5054 }
bellard31e31b82003-02-18 22:55:36 +00005055 break;
ths5e0ccb12007-09-24 09:26:10 +00005056#if defined(TARGET_NR_readlinkat) && defined(__NR_readlinkat)
5057 case TARGET_NR_readlinkat:
ths5e0ccb12007-09-24 09:26:10 +00005058 {
bellard579a97f2007-11-11 14:26:47 +00005059 void *p2;
ths5e0ccb12007-09-24 09:26:10 +00005060 p = lock_user_string(arg2);
bellard579a97f2007-11-11 14:26:47 +00005061 p2 = lock_user(VERIFY_WRITE, arg3, arg4, 0);
5062 if (!p || !p2)
ths0da46a62007-10-20 20:23:07 +00005063 ret = -TARGET_EFAULT;
ths5e0ccb12007-09-24 09:26:10 +00005064 else
5065 ret = get_errno(sys_readlinkat(arg1, path(p), p2, arg4));
bellard579a97f2007-11-11 14:26:47 +00005066 unlock_user(p2, arg3, ret);
5067 unlock_user(p, arg2, 0);
ths5e0ccb12007-09-24 09:26:10 +00005068 }
5069 break;
5070#endif
thse5febef2007-04-01 18:31:35 +00005071#ifdef TARGET_NR_uselib
bellard31e31b82003-02-18 22:55:36 +00005072 case TARGET_NR_uselib:
5073 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00005074#endif
5075#ifdef TARGET_NR_swapon
bellard31e31b82003-02-18 22:55:36 +00005076 case TARGET_NR_swapon:
bellard579a97f2007-11-11 14:26:47 +00005077 if (!(p = lock_user_string(arg1)))
5078 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005079 ret = get_errno(swapon(p, arg2));
5080 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00005081 break;
thse5febef2007-04-01 18:31:35 +00005082#endif
bellard31e31b82003-02-18 22:55:36 +00005083 case TARGET_NR_reboot:
5084 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00005085#ifdef TARGET_NR_readdir
bellard31e31b82003-02-18 22:55:36 +00005086 case TARGET_NR_readdir:
5087 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00005088#endif
5089#ifdef TARGET_NR_mmap
bellard31e31b82003-02-18 22:55:36 +00005090 case TARGET_NR_mmap:
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02005091#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 +00005092 {
blueswir1992f48a2007-10-14 16:27:31 +00005093 abi_ulong *v;
5094 abi_ulong v1, v2, v3, v4, v5, v6;
bellard579a97f2007-11-11 14:26:47 +00005095 if (!(v = lock_user(VERIFY_READ, arg1, 6 * sizeof(abi_ulong), 1)))
5096 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005097 v1 = tswapl(v[0]);
5098 v2 = tswapl(v[1]);
5099 v3 = tswapl(v[2]);
5100 v4 = tswapl(v[3]);
5101 v5 = tswapl(v[4]);
5102 v6 = tswapl(v[5]);
5103 unlock_user(v, arg1, 0);
ths5fafdf22007-09-16 21:08:06 +00005104 ret = get_errno(target_mmap(v1, v2, v3,
bellard5286db72003-06-05 00:57:30 +00005105 target_to_host_bitmask(v4, mmap_flags_tbl),
5106 v5, v6));
bellard31e31b82003-02-18 22:55:36 +00005107 }
bellard31e31b82003-02-18 22:55:36 +00005108#else
ths5fafdf22007-09-16 21:08:06 +00005109 ret = get_errno(target_mmap(arg1, arg2, arg3,
5110 target_to_host_bitmask(arg4, mmap_flags_tbl),
bellard6fb883e2003-07-09 17:12:39 +00005111 arg5,
5112 arg6));
bellard31e31b82003-02-18 22:55:36 +00005113#endif
bellard6fb883e2003-07-09 17:12:39 +00005114 break;
thse5febef2007-04-01 18:31:35 +00005115#endif
bellarda315a142005-01-30 22:59:18 +00005116#ifdef TARGET_NR_mmap2
bellard6fb883e2003-07-09 17:12:39 +00005117 case TARGET_NR_mmap2:
pbrookbb7ec042008-03-25 22:28:25 +00005118#ifndef MMAP_SHIFT
bellardc573ff62004-01-04 15:51:36 +00005119#define MMAP_SHIFT 12
bellardc573ff62004-01-04 15:51:36 +00005120#endif
ths5fafdf22007-09-16 21:08:06 +00005121 ret = get_errno(target_mmap(arg1, arg2, arg3,
5122 target_to_host_bitmask(arg4, mmap_flags_tbl),
bellard5286db72003-06-05 00:57:30 +00005123 arg5,
bellardc573ff62004-01-04 15:51:36 +00005124 arg6 << MMAP_SHIFT));
bellard31e31b82003-02-18 22:55:36 +00005125 break;
bellarda315a142005-01-30 22:59:18 +00005126#endif
bellard31e31b82003-02-18 22:55:36 +00005127 case TARGET_NR_munmap:
bellard54936002003-05-13 00:25:15 +00005128 ret = get_errno(target_munmap(arg1, arg2));
bellard31e31b82003-02-18 22:55:36 +00005129 break;
bellard9de5e442003-03-23 16:49:39 +00005130 case TARGET_NR_mprotect:
bellard54936002003-05-13 00:25:15 +00005131 ret = get_errno(target_mprotect(arg1, arg2, arg3));
bellard9de5e442003-03-23 16:49:39 +00005132 break;
thse5febef2007-04-01 18:31:35 +00005133#ifdef TARGET_NR_mremap
bellard9de5e442003-03-23 16:49:39 +00005134 case TARGET_NR_mremap:
bellard54936002003-05-13 00:25:15 +00005135 ret = get_errno(target_mremap(arg1, arg2, arg3, arg4, arg5));
bellard9de5e442003-03-23 16:49:39 +00005136 break;
thse5febef2007-04-01 18:31:35 +00005137#endif
pbrook53a59602006-03-25 19:31:22 +00005138 /* ??? msync/mlock/munlock are broken for softmmu. */
thse5febef2007-04-01 18:31:35 +00005139#ifdef TARGET_NR_msync
bellard9de5e442003-03-23 16:49:39 +00005140 case TARGET_NR_msync:
pbrook53a59602006-03-25 19:31:22 +00005141 ret = get_errno(msync(g2h(arg1), arg2, arg3));
bellard9de5e442003-03-23 16:49:39 +00005142 break;
thse5febef2007-04-01 18:31:35 +00005143#endif
5144#ifdef TARGET_NR_mlock
bellard9de5e442003-03-23 16:49:39 +00005145 case TARGET_NR_mlock:
pbrook53a59602006-03-25 19:31:22 +00005146 ret = get_errno(mlock(g2h(arg1), arg2));
bellard9de5e442003-03-23 16:49:39 +00005147 break;
thse5febef2007-04-01 18:31:35 +00005148#endif
5149#ifdef TARGET_NR_munlock
bellard9de5e442003-03-23 16:49:39 +00005150 case TARGET_NR_munlock:
pbrook53a59602006-03-25 19:31:22 +00005151 ret = get_errno(munlock(g2h(arg1), arg2));
bellard9de5e442003-03-23 16:49:39 +00005152 break;
thse5febef2007-04-01 18:31:35 +00005153#endif
5154#ifdef TARGET_NR_mlockall
bellard9de5e442003-03-23 16:49:39 +00005155 case TARGET_NR_mlockall:
5156 ret = get_errno(mlockall(arg1));
5157 break;
thse5febef2007-04-01 18:31:35 +00005158#endif
5159#ifdef TARGET_NR_munlockall
bellard9de5e442003-03-23 16:49:39 +00005160 case TARGET_NR_munlockall:
5161 ret = get_errno(munlockall());
5162 break;
thse5febef2007-04-01 18:31:35 +00005163#endif
bellard31e31b82003-02-18 22:55:36 +00005164 case TARGET_NR_truncate:
bellard579a97f2007-11-11 14:26:47 +00005165 if (!(p = lock_user_string(arg1)))
5166 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005167 ret = get_errno(truncate(p, arg2));
5168 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00005169 break;
5170 case TARGET_NR_ftruncate:
5171 ret = get_errno(ftruncate(arg1, arg2));
5172 break;
5173 case TARGET_NR_fchmod:
5174 ret = get_errno(fchmod(arg1, arg2));
5175 break;
ths814d7972007-09-24 09:26:51 +00005176#if defined(TARGET_NR_fchmodat) && defined(__NR_fchmodat)
5177 case TARGET_NR_fchmodat:
bellard579a97f2007-11-11 14:26:47 +00005178 if (!(p = lock_user_string(arg2)))
5179 goto efault;
aurel32465c9f02009-04-19 08:52:17 +00005180 ret = get_errno(sys_fchmodat(arg1, p, arg3));
bellard579a97f2007-11-11 14:26:47 +00005181 unlock_user(p, arg2, 0);
ths814d7972007-09-24 09:26:51 +00005182 break;
5183#endif
bellard31e31b82003-02-18 22:55:36 +00005184 case TARGET_NR_getpriority:
thsc6cda172007-10-09 03:42:34 +00005185 /* libc does special remapping of the return value of
5186 * sys_getpriority() so it's just easiest to call
5187 * sys_getpriority() directly rather than through libc. */
5188 ret = sys_getpriority(arg1, arg2);
bellard31e31b82003-02-18 22:55:36 +00005189 break;
5190 case TARGET_NR_setpriority:
5191 ret = get_errno(setpriority(arg1, arg2, arg3));
5192 break;
bellardebc05482003-09-30 21:08:41 +00005193#ifdef TARGET_NR_profil
bellard31e31b82003-02-18 22:55:36 +00005194 case TARGET_NR_profil:
5195 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00005196#endif
bellard31e31b82003-02-18 22:55:36 +00005197 case TARGET_NR_statfs:
bellard579a97f2007-11-11 14:26:47 +00005198 if (!(p = lock_user_string(arg1)))
5199 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005200 ret = get_errno(statfs(path(p), &stfs));
5201 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00005202 convert_statfs:
5203 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00005204 struct target_statfs *target_stfs;
ths3b46e622007-09-17 08:09:54 +00005205
bellard579a97f2007-11-11 14:26:47 +00005206 if (!lock_user_struct(VERIFY_WRITE, target_stfs, arg2, 0))
5207 goto efault;
5208 __put_user(stfs.f_type, &target_stfs->f_type);
5209 __put_user(stfs.f_bsize, &target_stfs->f_bsize);
5210 __put_user(stfs.f_blocks, &target_stfs->f_blocks);
5211 __put_user(stfs.f_bfree, &target_stfs->f_bfree);
5212 __put_user(stfs.f_bavail, &target_stfs->f_bavail);
5213 __put_user(stfs.f_files, &target_stfs->f_files);
5214 __put_user(stfs.f_ffree, &target_stfs->f_ffree);
5215 __put_user(stfs.f_fsid.__val[0], &target_stfs->f_fsid.val[0]);
5216 __put_user(stfs.f_fsid.__val[1], &target_stfs->f_fsid.val[1]);
5217 __put_user(stfs.f_namelen, &target_stfs->f_namelen);
pbrook53a59602006-03-25 19:31:22 +00005218 unlock_user_struct(target_stfs, arg2, 1);
bellard31e31b82003-02-18 22:55:36 +00005219 }
5220 break;
5221 case TARGET_NR_fstatfs:
bellard56c8f682005-11-28 22:28:41 +00005222 ret = get_errno(fstatfs(arg1, &stfs));
bellard31e31b82003-02-18 22:55:36 +00005223 goto convert_statfs;
bellard56c8f682005-11-28 22:28:41 +00005224#ifdef TARGET_NR_statfs64
5225 case TARGET_NR_statfs64:
bellard579a97f2007-11-11 14:26:47 +00005226 if (!(p = lock_user_string(arg1)))
5227 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005228 ret = get_errno(statfs(path(p), &stfs));
5229 unlock_user(p, arg1, 0);
bellard56c8f682005-11-28 22:28:41 +00005230 convert_statfs64:
5231 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00005232 struct target_statfs64 *target_stfs;
ths3b46e622007-09-17 08:09:54 +00005233
bellard579a97f2007-11-11 14:26:47 +00005234 if (!lock_user_struct(VERIFY_WRITE, target_stfs, arg3, 0))
5235 goto efault;
5236 __put_user(stfs.f_type, &target_stfs->f_type);
5237 __put_user(stfs.f_bsize, &target_stfs->f_bsize);
5238 __put_user(stfs.f_blocks, &target_stfs->f_blocks);
5239 __put_user(stfs.f_bfree, &target_stfs->f_bfree);
5240 __put_user(stfs.f_bavail, &target_stfs->f_bavail);
5241 __put_user(stfs.f_files, &target_stfs->f_files);
5242 __put_user(stfs.f_ffree, &target_stfs->f_ffree);
5243 __put_user(stfs.f_fsid.__val[0], &target_stfs->f_fsid.val[0]);
5244 __put_user(stfs.f_fsid.__val[1], &target_stfs->f_fsid.val[1]);
5245 __put_user(stfs.f_namelen, &target_stfs->f_namelen);
5246 unlock_user_struct(target_stfs, arg3, 1);
bellard56c8f682005-11-28 22:28:41 +00005247 }
5248 break;
5249 case TARGET_NR_fstatfs64:
5250 ret = get_errno(fstatfs(arg1, &stfs));
5251 goto convert_statfs64;
5252#endif
bellardebc05482003-09-30 21:08:41 +00005253#ifdef TARGET_NR_ioperm
bellard31e31b82003-02-18 22:55:36 +00005254 case TARGET_NR_ioperm:
5255 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00005256#endif
thse5febef2007-04-01 18:31:35 +00005257#ifdef TARGET_NR_socketcall
bellard31e31b82003-02-18 22:55:36 +00005258 case TARGET_NR_socketcall:
pbrook53a59602006-03-25 19:31:22 +00005259 ret = do_socketcall(arg1, arg2);
bellard31e31b82003-02-18 22:55:36 +00005260 break;
thse5febef2007-04-01 18:31:35 +00005261#endif
bellard3532fa72006-06-24 15:06:03 +00005262#ifdef TARGET_NR_accept
5263 case TARGET_NR_accept:
pbrook1be9e1d2006-11-19 15:26:04 +00005264 ret = do_accept(arg1, arg2, arg3);
bellard3532fa72006-06-24 15:06:03 +00005265 break;
5266#endif
5267#ifdef TARGET_NR_bind
5268 case TARGET_NR_bind:
5269 ret = do_bind(arg1, arg2, arg3);
5270 break;
5271#endif
5272#ifdef TARGET_NR_connect
5273 case TARGET_NR_connect:
5274 ret = do_connect(arg1, arg2, arg3);
5275 break;
5276#endif
5277#ifdef TARGET_NR_getpeername
5278 case TARGET_NR_getpeername:
pbrook1be9e1d2006-11-19 15:26:04 +00005279 ret = do_getpeername(arg1, arg2, arg3);
bellard3532fa72006-06-24 15:06:03 +00005280 break;
5281#endif
5282#ifdef TARGET_NR_getsockname
5283 case TARGET_NR_getsockname:
pbrook1be9e1d2006-11-19 15:26:04 +00005284 ret = do_getsockname(arg1, arg2, arg3);
bellard3532fa72006-06-24 15:06:03 +00005285 break;
5286#endif
5287#ifdef TARGET_NR_getsockopt
5288 case TARGET_NR_getsockopt:
5289 ret = do_getsockopt(arg1, arg2, arg3, arg4, arg5);
5290 break;
5291#endif
5292#ifdef TARGET_NR_listen
5293 case TARGET_NR_listen:
pbrook1be9e1d2006-11-19 15:26:04 +00005294 ret = get_errno(listen(arg1, arg2));
bellard3532fa72006-06-24 15:06:03 +00005295 break;
5296#endif
5297#ifdef TARGET_NR_recv
5298 case TARGET_NR_recv:
pbrook214201b2007-03-17 01:27:24 +00005299 ret = do_recvfrom(arg1, arg2, arg3, arg4, 0, 0);
bellard3532fa72006-06-24 15:06:03 +00005300 break;
5301#endif
5302#ifdef TARGET_NR_recvfrom
5303 case TARGET_NR_recvfrom:
pbrook214201b2007-03-17 01:27:24 +00005304 ret = do_recvfrom(arg1, arg2, arg3, arg4, arg5, arg6);
bellard3532fa72006-06-24 15:06:03 +00005305 break;
5306#endif
5307#ifdef TARGET_NR_recvmsg
5308 case TARGET_NR_recvmsg:
5309 ret = do_sendrecvmsg(arg1, arg2, arg3, 0);
5310 break;
5311#endif
5312#ifdef TARGET_NR_send
5313 case TARGET_NR_send:
pbrook1be9e1d2006-11-19 15:26:04 +00005314 ret = do_sendto(arg1, arg2, arg3, arg4, 0, 0);
bellard3532fa72006-06-24 15:06:03 +00005315 break;
5316#endif
5317#ifdef TARGET_NR_sendmsg
5318 case TARGET_NR_sendmsg:
5319 ret = do_sendrecvmsg(arg1, arg2, arg3, 1);
5320 break;
5321#endif
5322#ifdef TARGET_NR_sendto
5323 case TARGET_NR_sendto:
pbrook1be9e1d2006-11-19 15:26:04 +00005324 ret = do_sendto(arg1, arg2, arg3, arg4, arg5, arg6);
bellard3532fa72006-06-24 15:06:03 +00005325 break;
5326#endif
5327#ifdef TARGET_NR_shutdown
5328 case TARGET_NR_shutdown:
pbrook1be9e1d2006-11-19 15:26:04 +00005329 ret = get_errno(shutdown(arg1, arg2));
bellard3532fa72006-06-24 15:06:03 +00005330 break;
5331#endif
5332#ifdef TARGET_NR_socket
5333 case TARGET_NR_socket:
5334 ret = do_socket(arg1, arg2, arg3);
5335 break;
5336#endif
5337#ifdef TARGET_NR_socketpair
5338 case TARGET_NR_socketpair:
pbrook1be9e1d2006-11-19 15:26:04 +00005339 ret = do_socketpair(arg1, arg2, arg3, arg4);
bellard3532fa72006-06-24 15:06:03 +00005340 break;
5341#endif
5342#ifdef TARGET_NR_setsockopt
5343 case TARGET_NR_setsockopt:
5344 ret = do_setsockopt(arg1, arg2, arg3, arg4, (socklen_t) arg5);
5345 break;
5346#endif
ths7494b0f2007-02-11 18:26:53 +00005347
bellard31e31b82003-02-18 22:55:36 +00005348 case TARGET_NR_syslog:
bellard579a97f2007-11-11 14:26:47 +00005349 if (!(p = lock_user_string(arg2)))
5350 goto efault;
thse5574482007-02-11 20:03:13 +00005351 ret = get_errno(sys_syslog((int)arg1, p, (int)arg3));
5352 unlock_user(p, arg2, 0);
ths7494b0f2007-02-11 18:26:53 +00005353 break;
5354
bellard31e31b82003-02-18 22:55:36 +00005355 case TARGET_NR_setitimer:
bellard66fb9762003-03-23 01:06:05 +00005356 {
bellard66fb9762003-03-23 01:06:05 +00005357 struct itimerval value, ovalue, *pvalue;
5358
pbrook53a59602006-03-25 19:31:22 +00005359 if (arg2) {
bellard66fb9762003-03-23 01:06:05 +00005360 pvalue = &value;
ths788f5ec2007-12-09 02:37:05 +00005361 if (copy_from_user_timeval(&pvalue->it_interval, arg2)
5362 || copy_from_user_timeval(&pvalue->it_value,
5363 arg2 + sizeof(struct target_timeval)))
5364 goto efault;
bellard66fb9762003-03-23 01:06:05 +00005365 } else {
5366 pvalue = NULL;
5367 }
5368 ret = get_errno(setitimer(arg1, pvalue, &ovalue));
pbrook53a59602006-03-25 19:31:22 +00005369 if (!is_error(ret) && arg3) {
ths788f5ec2007-12-09 02:37:05 +00005370 if (copy_to_user_timeval(arg3,
5371 &ovalue.it_interval)
5372 || copy_to_user_timeval(arg3 + sizeof(struct target_timeval),
5373 &ovalue.it_value))
5374 goto efault;
bellard66fb9762003-03-23 01:06:05 +00005375 }
5376 }
5377 break;
bellard31e31b82003-02-18 22:55:36 +00005378 case TARGET_NR_getitimer:
bellard66fb9762003-03-23 01:06:05 +00005379 {
bellard66fb9762003-03-23 01:06:05 +00005380 struct itimerval value;
ths3b46e622007-09-17 08:09:54 +00005381
bellard66fb9762003-03-23 01:06:05 +00005382 ret = get_errno(getitimer(arg1, &value));
pbrook53a59602006-03-25 19:31:22 +00005383 if (!is_error(ret) && arg2) {
ths788f5ec2007-12-09 02:37:05 +00005384 if (copy_to_user_timeval(arg2,
5385 &value.it_interval)
5386 || copy_to_user_timeval(arg2 + sizeof(struct target_timeval),
5387 &value.it_value))
5388 goto efault;
bellard66fb9762003-03-23 01:06:05 +00005389 }
5390 }
5391 break;
bellard31e31b82003-02-18 22:55:36 +00005392 case TARGET_NR_stat:
bellard579a97f2007-11-11 14:26:47 +00005393 if (!(p = lock_user_string(arg1)))
5394 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005395 ret = get_errno(stat(path(p), &st));
5396 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00005397 goto do_stat;
5398 case TARGET_NR_lstat:
bellard579a97f2007-11-11 14:26:47 +00005399 if (!(p = lock_user_string(arg1)))
5400 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005401 ret = get_errno(lstat(path(p), &st));
5402 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00005403 goto do_stat;
5404 case TARGET_NR_fstat:
5405 {
5406 ret = get_errno(fstat(arg1, &st));
5407 do_stat:
5408 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00005409 struct target_stat *target_st;
thse3584652007-06-01 11:49:38 +00005410
bellard579a97f2007-11-11 14:26:47 +00005411 if (!lock_user_struct(VERIFY_WRITE, target_st, arg2, 0))
5412 goto efault;
bellardd2fd1af2007-11-14 18:08:56 +00005413 __put_user(st.st_dev, &target_st->st_dev);
5414 __put_user(st.st_ino, &target_st->st_ino);
5415 __put_user(st.st_mode, &target_st->st_mode);
5416 __put_user(st.st_uid, &target_st->st_uid);
5417 __put_user(st.st_gid, &target_st->st_gid);
5418 __put_user(st.st_nlink, &target_st->st_nlink);
5419 __put_user(st.st_rdev, &target_st->st_rdev);
5420 __put_user(st.st_size, &target_st->st_size);
5421 __put_user(st.st_blksize, &target_st->st_blksize);
5422 __put_user(st.st_blocks, &target_st->st_blocks);
5423 __put_user(st.st_atime, &target_st->target_st_atime);
5424 __put_user(st.st_mtime, &target_st->target_st_mtime);
5425 __put_user(st.st_ctime, &target_st->target_st_ctime);
pbrook53a59602006-03-25 19:31:22 +00005426 unlock_user_struct(target_st, arg2, 1);
bellard31e31b82003-02-18 22:55:36 +00005427 }
5428 }
5429 break;
bellardebc05482003-09-30 21:08:41 +00005430#ifdef TARGET_NR_olduname
bellard31e31b82003-02-18 22:55:36 +00005431 case TARGET_NR_olduname:
5432 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00005433#endif
5434#ifdef TARGET_NR_iopl
bellard31e31b82003-02-18 22:55:36 +00005435 case TARGET_NR_iopl:
5436 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00005437#endif
bellard31e31b82003-02-18 22:55:36 +00005438 case TARGET_NR_vhangup:
5439 ret = get_errno(vhangup());
5440 break;
bellardebc05482003-09-30 21:08:41 +00005441#ifdef TARGET_NR_idle
bellard31e31b82003-02-18 22:55:36 +00005442 case TARGET_NR_idle:
5443 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00005444#endif
bellard42ad6ae2005-01-03 22:48:11 +00005445#ifdef TARGET_NR_syscall
5446 case TARGET_NR_syscall:
5447 ret = do_syscall(cpu_env,arg1 & 0xffff,arg2,arg3,arg4,arg5,arg6,0);
5448 break;
5449#endif
bellard31e31b82003-02-18 22:55:36 +00005450 case TARGET_NR_wait4:
5451 {
5452 int status;
blueswir1992f48a2007-10-14 16:27:31 +00005453 abi_long status_ptr = arg2;
bellard31e31b82003-02-18 22:55:36 +00005454 struct rusage rusage, *rusage_ptr;
blueswir1992f48a2007-10-14 16:27:31 +00005455 abi_ulong target_rusage = arg4;
bellard31e31b82003-02-18 22:55:36 +00005456 if (target_rusage)
5457 rusage_ptr = &rusage;
5458 else
5459 rusage_ptr = NULL;
5460 ret = get_errno(wait4(arg1, &status, arg3, rusage_ptr));
5461 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +00005462 if (status_ptr) {
pbrook1d9d8b52009-04-16 15:17:02 +00005463 status = host_to_target_waitstatus(status);
bellard2f619692007-11-16 10:46:05 +00005464 if (put_user_s32(status, status_ptr))
5465 goto efault;
bellard31e31b82003-02-18 22:55:36 +00005466 }
bellard2f619692007-11-16 10:46:05 +00005467 if (target_rusage)
5468 host_to_target_rusage(target_rusage, &rusage);
bellard31e31b82003-02-18 22:55:36 +00005469 }
5470 }
5471 break;
thse5febef2007-04-01 18:31:35 +00005472#ifdef TARGET_NR_swapoff
bellard31e31b82003-02-18 22:55:36 +00005473 case TARGET_NR_swapoff:
bellard579a97f2007-11-11 14:26:47 +00005474 if (!(p = lock_user_string(arg1)))
5475 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005476 ret = get_errno(swapoff(p));
5477 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00005478 break;
thse5febef2007-04-01 18:31:35 +00005479#endif
bellard31e31b82003-02-18 22:55:36 +00005480 case TARGET_NR_sysinfo:
bellarda5448a72004-06-19 16:59:03 +00005481 {
pbrook53a59602006-03-25 19:31:22 +00005482 struct target_sysinfo *target_value;
bellarda5448a72004-06-19 16:59:03 +00005483 struct sysinfo value;
5484 ret = get_errno(sysinfo(&value));
pbrook53a59602006-03-25 19:31:22 +00005485 if (!is_error(ret) && arg1)
bellarda5448a72004-06-19 16:59:03 +00005486 {
bellard579a97f2007-11-11 14:26:47 +00005487 if (!lock_user_struct(VERIFY_WRITE, target_value, arg1, 0))
5488 goto efault;
bellarda5448a72004-06-19 16:59:03 +00005489 __put_user(value.uptime, &target_value->uptime);
5490 __put_user(value.loads[0], &target_value->loads[0]);
5491 __put_user(value.loads[1], &target_value->loads[1]);
5492 __put_user(value.loads[2], &target_value->loads[2]);
5493 __put_user(value.totalram, &target_value->totalram);
5494 __put_user(value.freeram, &target_value->freeram);
5495 __put_user(value.sharedram, &target_value->sharedram);
5496 __put_user(value.bufferram, &target_value->bufferram);
5497 __put_user(value.totalswap, &target_value->totalswap);
5498 __put_user(value.freeswap, &target_value->freeswap);
5499 __put_user(value.procs, &target_value->procs);
5500 __put_user(value.totalhigh, &target_value->totalhigh);
5501 __put_user(value.freehigh, &target_value->freehigh);
5502 __put_user(value.mem_unit, &target_value->mem_unit);
pbrook53a59602006-03-25 19:31:22 +00005503 unlock_user_struct(target_value, arg1, 1);
bellarda5448a72004-06-19 16:59:03 +00005504 }
5505 }
5506 break;
thse5febef2007-04-01 18:31:35 +00005507#ifdef TARGET_NR_ipc
bellard31e31b82003-02-18 22:55:36 +00005508 case TARGET_NR_ipc:
bellard8853f862004-02-22 14:57:26 +00005509 ret = do_ipc(arg1, arg2, arg3, arg4, arg5, arg6);
5510 break;
thse5febef2007-04-01 18:31:35 +00005511#endif
aurel32e5289082009-04-18 16:16:12 +00005512#ifdef TARGET_NR_semget
5513 case TARGET_NR_semget:
5514 ret = get_errno(semget(arg1, arg2, arg3));
5515 break;
5516#endif
5517#ifdef TARGET_NR_semop
5518 case TARGET_NR_semop:
5519 ret = get_errno(do_semop(arg1, arg2, arg3));
5520 break;
5521#endif
5522#ifdef TARGET_NR_semctl
5523 case TARGET_NR_semctl:
5524 ret = do_semctl(arg1, arg2, arg3, (union target_semun)(abi_ulong)arg4);
5525 break;
5526#endif
aurel32eeb438c2008-10-13 21:08:55 +00005527#ifdef TARGET_NR_msgctl
5528 case TARGET_NR_msgctl:
5529 ret = do_msgctl(arg1, arg2, arg3);
5530 break;
5531#endif
5532#ifdef TARGET_NR_msgget
5533 case TARGET_NR_msgget:
5534 ret = get_errno(msgget(arg1, arg2));
5535 break;
5536#endif
5537#ifdef TARGET_NR_msgrcv
5538 case TARGET_NR_msgrcv:
5539 ret = do_msgrcv(arg1, arg2, arg3, arg4, arg5);
5540 break;
5541#endif
5542#ifdef TARGET_NR_msgsnd
5543 case TARGET_NR_msgsnd:
5544 ret = do_msgsnd(arg1, arg2, arg3, arg4);
5545 break;
5546#endif
Riku Voipio88a8c982009-04-03 10:42:00 +03005547#ifdef TARGET_NR_shmget
5548 case TARGET_NR_shmget:
5549 ret = get_errno(shmget(arg1, arg2, arg3));
5550 break;
5551#endif
5552#ifdef TARGET_NR_shmctl
5553 case TARGET_NR_shmctl:
5554 ret = do_shmctl(arg1, arg2, arg3);
5555 break;
5556#endif
5557#ifdef TARGET_NR_shmat
5558 case TARGET_NR_shmat:
5559 ret = do_shmat(arg1, arg2, arg3);
5560 break;
5561#endif
5562#ifdef TARGET_NR_shmdt
5563 case TARGET_NR_shmdt:
5564 ret = do_shmdt(arg1);
5565 break;
5566#endif
bellard31e31b82003-02-18 22:55:36 +00005567 case TARGET_NR_fsync:
5568 ret = get_errno(fsync(arg1));
5569 break;
bellard31e31b82003-02-18 22:55:36 +00005570 case TARGET_NR_clone:
aurel320b6d3ae2008-09-15 07:43:43 +00005571#if defined(TARGET_SH4)
5572 ret = get_errno(do_fork(cpu_env, arg1, arg2, arg3, arg5, arg4));
edgar_iglb15ad612009-01-07 19:43:47 +00005573#elif defined(TARGET_CRIS)
5574 ret = get_errno(do_fork(cpu_env, arg2, arg1, arg3, arg4, arg5));
aurel320b6d3ae2008-09-15 07:43:43 +00005575#else
pbrookd865bab2008-06-07 22:12:17 +00005576 ret = get_errno(do_fork(cpu_env, arg1, arg2, arg3, arg4, arg5));
aurel320b6d3ae2008-09-15 07:43:43 +00005577#endif
bellard1b6b0292003-03-22 17:31:38 +00005578 break;
bellardec86b0f2003-04-11 00:15:04 +00005579#ifdef __NR_exit_group
5580 /* new thread calls */
5581 case TARGET_NR_exit_group:
aurel326d946cd2008-11-06 16:15:18 +00005582#ifdef HAVE_GPROF
5583 _mcleanup();
5584#endif
bellarde9009672005-04-26 20:42:36 +00005585 gdb_exit(cpu_env, arg1);
bellardec86b0f2003-04-11 00:15:04 +00005586 ret = get_errno(exit_group(arg1));
5587 break;
5588#endif
bellard31e31b82003-02-18 22:55:36 +00005589 case TARGET_NR_setdomainname:
bellard579a97f2007-11-11 14:26:47 +00005590 if (!(p = lock_user_string(arg1)))
5591 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005592 ret = get_errno(setdomainname(p, arg2));
5593 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00005594 break;
5595 case TARGET_NR_uname:
5596 /* no need to transcode because we use the linux syscall */
bellard29e619b2004-09-13 21:41:04 +00005597 {
5598 struct new_utsname * buf;
ths3b46e622007-09-17 08:09:54 +00005599
bellard579a97f2007-11-11 14:26:47 +00005600 if (!lock_user_struct(VERIFY_WRITE, buf, arg1, 0))
5601 goto efault;
bellard29e619b2004-09-13 21:41:04 +00005602 ret = get_errno(sys_uname(buf));
5603 if (!is_error(ret)) {
5604 /* Overrite the native machine name with whatever is being
5605 emulated. */
5606 strcpy (buf->machine, UNAME_MACHINE);
pbrookc5937222006-05-14 11:30:38 +00005607 /* Allow the user to override the reported release. */
5608 if (qemu_uname_release && *qemu_uname_release)
5609 strcpy (buf->release, qemu_uname_release);
bellard29e619b2004-09-13 21:41:04 +00005610 }
pbrook53a59602006-03-25 19:31:22 +00005611 unlock_user_struct(buf, arg1, 1);
bellard29e619b2004-09-13 21:41:04 +00005612 }
bellard31e31b82003-02-18 22:55:36 +00005613 break;
bellard6dbad632003-03-16 18:05:05 +00005614#ifdef TARGET_I386
bellard31e31b82003-02-18 22:55:36 +00005615 case TARGET_NR_modify_ldt:
bellard03acab62007-11-11 14:57:14 +00005616 ret = do_modify_ldt(cpu_env, arg1, arg2, arg3);
bellard5cd43932003-03-29 16:54:36 +00005617 break;
j_mayer84409dd2007-04-06 08:56:50 +00005618#if !defined(TARGET_X86_64)
bellard5cd43932003-03-29 16:54:36 +00005619 case TARGET_NR_vm86old:
5620 goto unimplemented;
5621 case TARGET_NR_vm86:
pbrook53a59602006-03-25 19:31:22 +00005622 ret = do_vm86(cpu_env, arg1, arg2);
bellard6dbad632003-03-16 18:05:05 +00005623 break;
5624#endif
j_mayer84409dd2007-04-06 08:56:50 +00005625#endif
bellard31e31b82003-02-18 22:55:36 +00005626 case TARGET_NR_adjtimex:
5627 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00005628#ifdef TARGET_NR_create_module
bellard31e31b82003-02-18 22:55:36 +00005629 case TARGET_NR_create_module:
thse5febef2007-04-01 18:31:35 +00005630#endif
bellard31e31b82003-02-18 22:55:36 +00005631 case TARGET_NR_init_module:
5632 case TARGET_NR_delete_module:
thse5febef2007-04-01 18:31:35 +00005633#ifdef TARGET_NR_get_kernel_syms
bellard31e31b82003-02-18 22:55:36 +00005634 case TARGET_NR_get_kernel_syms:
thse5febef2007-04-01 18:31:35 +00005635#endif
bellard31e31b82003-02-18 22:55:36 +00005636 goto unimplemented;
5637 case TARGET_NR_quotactl:
5638 goto unimplemented;
5639 case TARGET_NR_getpgid:
5640 ret = get_errno(getpgid(arg1));
5641 break;
5642 case TARGET_NR_fchdir:
5643 ret = get_errno(fchdir(arg1));
5644 break;
j_mayer84409dd2007-04-06 08:56:50 +00005645#ifdef TARGET_NR_bdflush /* not on x86_64 */
bellard31e31b82003-02-18 22:55:36 +00005646 case TARGET_NR_bdflush:
5647 goto unimplemented;
j_mayer84409dd2007-04-06 08:56:50 +00005648#endif
thse5febef2007-04-01 18:31:35 +00005649#ifdef TARGET_NR_sysfs
bellard31e31b82003-02-18 22:55:36 +00005650 case TARGET_NR_sysfs:
5651 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00005652#endif
bellard31e31b82003-02-18 22:55:36 +00005653 case TARGET_NR_personality:
bellard1b6b0292003-03-22 17:31:38 +00005654 ret = get_errno(personality(arg1));
bellard31e31b82003-02-18 22:55:36 +00005655 break;
thse5febef2007-04-01 18:31:35 +00005656#ifdef TARGET_NR_afs_syscall
bellard31e31b82003-02-18 22:55:36 +00005657 case TARGET_NR_afs_syscall:
5658 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00005659#endif
j_mayer7a3148a2007-04-05 07:13:51 +00005660#ifdef TARGET_NR__llseek /* Not on alpha */
bellard31e31b82003-02-18 22:55:36 +00005661 case TARGET_NR__llseek:
5662 {
bellard4f2ac232004-04-26 19:44:02 +00005663#if defined (__x86_64__)
5664 ret = get_errno(lseek(arg1, ((uint64_t )arg2 << 32) | arg3, arg5));
bellard2f619692007-11-16 10:46:05 +00005665 if (put_user_s64(ret, arg4))
5666 goto efault;
bellard4f2ac232004-04-26 19:44:02 +00005667#else
bellard31e31b82003-02-18 22:55:36 +00005668 int64_t res;
5669 ret = get_errno(_llseek(arg1, arg2, arg3, &res, arg5));
bellard2f619692007-11-16 10:46:05 +00005670 if (put_user_s64(res, arg4))
5671 goto efault;
bellard4f2ac232004-04-26 19:44:02 +00005672#endif
bellard31e31b82003-02-18 22:55:36 +00005673 }
5674 break;
j_mayer7a3148a2007-04-05 07:13:51 +00005675#endif
bellard31e31b82003-02-18 22:55:36 +00005676 case TARGET_NR_getdents:
blueswir1992f48a2007-10-14 16:27:31 +00005677#if TARGET_ABI_BITS != 32
pbrook53a59602006-03-25 19:31:22 +00005678 goto unimplemented;
blueswir1992f48a2007-10-14 16:27:31 +00005679#elif TARGET_ABI_BITS == 32 && HOST_LONG_BITS == 64
bellard4add45b2003-06-05 01:52:59 +00005680 {
pbrook53a59602006-03-25 19:31:22 +00005681 struct target_dirent *target_dirp;
aurel326556a832008-10-13 21:08:17 +00005682 struct linux_dirent *dirp;
blueswir1992f48a2007-10-14 16:27:31 +00005683 abi_long count = arg3;
bellard4add45b2003-06-05 01:52:59 +00005684
5685 dirp = malloc(count);
ths0da46a62007-10-20 20:23:07 +00005686 if (!dirp) {
bellard579a97f2007-11-11 14:26:47 +00005687 ret = -TARGET_ENOMEM;
ths0da46a62007-10-20 20:23:07 +00005688 goto fail;
5689 }
ths3b46e622007-09-17 08:09:54 +00005690
bellard4add45b2003-06-05 01:52:59 +00005691 ret = get_errno(sys_getdents(arg1, dirp, count));
5692 if (!is_error(ret)) {
aurel326556a832008-10-13 21:08:17 +00005693 struct linux_dirent *de;
bellard4add45b2003-06-05 01:52:59 +00005694 struct target_dirent *tde;
5695 int len = ret;
5696 int reclen, treclen;
5697 int count1, tnamelen;
5698
5699 count1 = 0;
5700 de = dirp;
bellard579a97f2007-11-11 14:26:47 +00005701 if (!(target_dirp = lock_user(VERIFY_WRITE, arg2, count, 0)))
5702 goto efault;
bellard4add45b2003-06-05 01:52:59 +00005703 tde = target_dirp;
5704 while (len > 0) {
5705 reclen = de->d_reclen;
blueswir1992f48a2007-10-14 16:27:31 +00005706 treclen = reclen - (2 * (sizeof(long) - sizeof(abi_long)));
bellard4add45b2003-06-05 01:52:59 +00005707 tde->d_reclen = tswap16(treclen);
5708 tde->d_ino = tswapl(de->d_ino);
5709 tde->d_off = tswapl(de->d_off);
blueswir1992f48a2007-10-14 16:27:31 +00005710 tnamelen = treclen - (2 * sizeof(abi_long) + 2);
bellard4add45b2003-06-05 01:52:59 +00005711 if (tnamelen > 256)
5712 tnamelen = 256;
bellard80a9d032005-01-03 23:31:27 +00005713 /* XXX: may not be correct */
blueswir1be15b142008-10-25 11:21:28 +00005714 pstrcpy(tde->d_name, tnamelen, de->d_name);
aurel326556a832008-10-13 21:08:17 +00005715 de = (struct linux_dirent *)((char *)de + reclen);
bellard4add45b2003-06-05 01:52:59 +00005716 len -= reclen;
j_mayer1c5bf3b2007-04-14 12:17:59 +00005717 tde = (struct target_dirent *)((char *)tde + treclen);
bellard4add45b2003-06-05 01:52:59 +00005718 count1 += treclen;
5719 }
5720 ret = count1;
bellard579a97f2007-11-11 14:26:47 +00005721 unlock_user(target_dirp, arg2, ret);
bellard4add45b2003-06-05 01:52:59 +00005722 }
5723 free(dirp);
5724 }
5725#else
bellard31e31b82003-02-18 22:55:36 +00005726 {
aurel326556a832008-10-13 21:08:17 +00005727 struct linux_dirent *dirp;
blueswir1992f48a2007-10-14 16:27:31 +00005728 abi_long count = arg3;
bellarddab2ed92003-03-22 15:23:14 +00005729
bellard579a97f2007-11-11 14:26:47 +00005730 if (!(dirp = lock_user(VERIFY_WRITE, arg2, count, 0)))
5731 goto efault;
bellard72f03902003-02-18 23:33:18 +00005732 ret = get_errno(sys_getdents(arg1, dirp, count));
bellard31e31b82003-02-18 22:55:36 +00005733 if (!is_error(ret)) {
aurel326556a832008-10-13 21:08:17 +00005734 struct linux_dirent *de;
bellard31e31b82003-02-18 22:55:36 +00005735 int len = ret;
5736 int reclen;
5737 de = dirp;
5738 while (len > 0) {
bellard8083a3e2003-03-24 23:12:16 +00005739 reclen = de->d_reclen;
bellard31e31b82003-02-18 22:55:36 +00005740 if (reclen > len)
5741 break;
bellard8083a3e2003-03-24 23:12:16 +00005742 de->d_reclen = tswap16(reclen);
bellard31e31b82003-02-18 22:55:36 +00005743 tswapls(&de->d_ino);
5744 tswapls(&de->d_off);
aurel326556a832008-10-13 21:08:17 +00005745 de = (struct linux_dirent *)((char *)de + reclen);
bellard31e31b82003-02-18 22:55:36 +00005746 len -= reclen;
5747 }
5748 }
pbrook53a59602006-03-25 19:31:22 +00005749 unlock_user(dirp, arg2, ret);
bellard31e31b82003-02-18 22:55:36 +00005750 }
bellard4add45b2003-06-05 01:52:59 +00005751#endif
bellard31e31b82003-02-18 22:55:36 +00005752 break;
ths3ae43202007-09-16 21:39:48 +00005753#if defined(TARGET_NR_getdents64) && defined(__NR_getdents64)
bellarddab2ed92003-03-22 15:23:14 +00005754 case TARGET_NR_getdents64:
5755 {
aurel326556a832008-10-13 21:08:17 +00005756 struct linux_dirent64 *dirp;
blueswir1992f48a2007-10-14 16:27:31 +00005757 abi_long count = arg3;
bellard579a97f2007-11-11 14:26:47 +00005758 if (!(dirp = lock_user(VERIFY_WRITE, arg2, count, 0)))
5759 goto efault;
bellarddab2ed92003-03-22 15:23:14 +00005760 ret = get_errno(sys_getdents64(arg1, dirp, count));
5761 if (!is_error(ret)) {
aurel326556a832008-10-13 21:08:17 +00005762 struct linux_dirent64 *de;
bellarddab2ed92003-03-22 15:23:14 +00005763 int len = ret;
5764 int reclen;
5765 de = dirp;
5766 while (len > 0) {
bellard8083a3e2003-03-24 23:12:16 +00005767 reclen = de->d_reclen;
bellarddab2ed92003-03-22 15:23:14 +00005768 if (reclen > len)
5769 break;
bellard8083a3e2003-03-24 23:12:16 +00005770 de->d_reclen = tswap16(reclen);
bellard8582a532007-11-11 23:11:36 +00005771 tswap64s((uint64_t *)&de->d_ino);
5772 tswap64s((uint64_t *)&de->d_off);
aurel326556a832008-10-13 21:08:17 +00005773 de = (struct linux_dirent64 *)((char *)de + reclen);
bellarddab2ed92003-03-22 15:23:14 +00005774 len -= reclen;
5775 }
5776 }
pbrook53a59602006-03-25 19:31:22 +00005777 unlock_user(dirp, arg2, ret);
bellarddab2ed92003-03-22 15:23:14 +00005778 }
5779 break;
bellarda541f292004-04-12 20:39:29 +00005780#endif /* TARGET_NR_getdents64 */
thse5febef2007-04-01 18:31:35 +00005781#ifdef TARGET_NR__newselect
bellard31e31b82003-02-18 22:55:36 +00005782 case TARGET_NR__newselect:
pbrook53a59602006-03-25 19:31:22 +00005783 ret = do_select(arg1, arg2, arg3, arg4, arg5);
bellard31e31b82003-02-18 22:55:36 +00005784 break;
thse5febef2007-04-01 18:31:35 +00005785#endif
5786#ifdef TARGET_NR_poll
bellard9de5e442003-03-23 16:49:39 +00005787 case TARGET_NR_poll:
5788 {
pbrook53a59602006-03-25 19:31:22 +00005789 struct target_pollfd *target_pfd;
bellard9de5e442003-03-23 16:49:39 +00005790 unsigned int nfds = arg2;
5791 int timeout = arg3;
5792 struct pollfd *pfd;
bellard7854b052003-03-29 17:22:23 +00005793 unsigned int i;
bellard9de5e442003-03-23 16:49:39 +00005794
bellard579a97f2007-11-11 14:26:47 +00005795 target_pfd = lock_user(VERIFY_WRITE, arg1, sizeof(struct target_pollfd) * nfds, 1);
5796 if (!target_pfd)
5797 goto efault;
bellard9de5e442003-03-23 16:49:39 +00005798 pfd = alloca(sizeof(struct pollfd) * nfds);
5799 for(i = 0; i < nfds; i++) {
bellard5cd43932003-03-29 16:54:36 +00005800 pfd[i].fd = tswap32(target_pfd[i].fd);
5801 pfd[i].events = tswap16(target_pfd[i].events);
bellard9de5e442003-03-23 16:49:39 +00005802 }
5803 ret = get_errno(poll(pfd, nfds, timeout));
5804 if (!is_error(ret)) {
5805 for(i = 0; i < nfds; i++) {
bellard5cd43932003-03-29 16:54:36 +00005806 target_pfd[i].revents = tswap16(pfd[i].revents);
bellard9de5e442003-03-23 16:49:39 +00005807 }
pbrook53a59602006-03-25 19:31:22 +00005808 ret += nfds * (sizeof(struct target_pollfd)
5809 - sizeof(struct pollfd));
bellard9de5e442003-03-23 16:49:39 +00005810 }
pbrook53a59602006-03-25 19:31:22 +00005811 unlock_user(target_pfd, arg1, ret);
bellard9de5e442003-03-23 16:49:39 +00005812 }
5813 break;
thse5febef2007-04-01 18:31:35 +00005814#endif
bellard31e31b82003-02-18 22:55:36 +00005815 case TARGET_NR_flock:
bellard9de5e442003-03-23 16:49:39 +00005816 /* NOTE: the flock constant seems to be the same for every
5817 Linux platform */
5818 ret = get_errno(flock(arg1, arg2));
bellard31e31b82003-02-18 22:55:36 +00005819 break;
5820 case TARGET_NR_readv:
5821 {
5822 int count = arg3;
bellard31e31b82003-02-18 22:55:36 +00005823 struct iovec *vec;
bellard31e31b82003-02-18 22:55:36 +00005824
5825 vec = alloca(count * sizeof(struct iovec));
bellard41df8412008-02-04 22:26:57 +00005826 if (lock_iovec(VERIFY_WRITE, vec, arg2, count, 0) < 0)
5827 goto efault;
bellard31e31b82003-02-18 22:55:36 +00005828 ret = get_errno(readv(arg1, vec, count));
pbrook53a59602006-03-25 19:31:22 +00005829 unlock_iovec(vec, arg2, count, 1);
bellard31e31b82003-02-18 22:55:36 +00005830 }
5831 break;
5832 case TARGET_NR_writev:
5833 {
5834 int count = arg3;
bellard31e31b82003-02-18 22:55:36 +00005835 struct iovec *vec;
bellard31e31b82003-02-18 22:55:36 +00005836
5837 vec = alloca(count * sizeof(struct iovec));
bellard41df8412008-02-04 22:26:57 +00005838 if (lock_iovec(VERIFY_READ, vec, arg2, count, 1) < 0)
5839 goto efault;
bellard31e31b82003-02-18 22:55:36 +00005840 ret = get_errno(writev(arg1, vec, count));
pbrook53a59602006-03-25 19:31:22 +00005841 unlock_iovec(vec, arg2, count, 0);
bellard31e31b82003-02-18 22:55:36 +00005842 }
5843 break;
5844 case TARGET_NR_getsid:
5845 ret = get_errno(getsid(arg1));
5846 break;
j_mayer7a3148a2007-04-05 07:13:51 +00005847#if defined(TARGET_NR_fdatasync) /* Not on alpha (osf_datasync ?) */
bellard31e31b82003-02-18 22:55:36 +00005848 case TARGET_NR_fdatasync:
bellard5cd43932003-03-29 16:54:36 +00005849 ret = get_errno(fdatasync(arg1));
5850 break;
j_mayer7a3148a2007-04-05 07:13:51 +00005851#endif
bellard31e31b82003-02-18 22:55:36 +00005852 case TARGET_NR__sysctl:
ths0da46a62007-10-20 20:23:07 +00005853 /* We don't implement this, but ENOTDIR is always a safe
bellard29e619b2004-09-13 21:41:04 +00005854 return value. */
ths0da46a62007-10-20 20:23:07 +00005855 ret = -TARGET_ENOTDIR;
5856 break;
bellard31e31b82003-02-18 22:55:36 +00005857 case TARGET_NR_sched_setparam:
bellard5cd43932003-03-29 16:54:36 +00005858 {
pbrook53a59602006-03-25 19:31:22 +00005859 struct sched_param *target_schp;
bellard5cd43932003-03-29 16:54:36 +00005860 struct sched_param schp;
pbrook53a59602006-03-25 19:31:22 +00005861
bellard579a97f2007-11-11 14:26:47 +00005862 if (!lock_user_struct(VERIFY_READ, target_schp, arg2, 1))
5863 goto efault;
bellard5cd43932003-03-29 16:54:36 +00005864 schp.sched_priority = tswap32(target_schp->sched_priority);
pbrook53a59602006-03-25 19:31:22 +00005865 unlock_user_struct(target_schp, arg2, 0);
bellard5cd43932003-03-29 16:54:36 +00005866 ret = get_errno(sched_setparam(arg1, &schp));
5867 }
5868 break;
bellard31e31b82003-02-18 22:55:36 +00005869 case TARGET_NR_sched_getparam:
bellard5cd43932003-03-29 16:54:36 +00005870 {
pbrook53a59602006-03-25 19:31:22 +00005871 struct sched_param *target_schp;
bellard5cd43932003-03-29 16:54:36 +00005872 struct sched_param schp;
5873 ret = get_errno(sched_getparam(arg1, &schp));
5874 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00005875 if (!lock_user_struct(VERIFY_WRITE, target_schp, arg2, 0))
5876 goto efault;
bellard5cd43932003-03-29 16:54:36 +00005877 target_schp->sched_priority = tswap32(schp.sched_priority);
pbrook53a59602006-03-25 19:31:22 +00005878 unlock_user_struct(target_schp, arg2, 1);
bellard5cd43932003-03-29 16:54:36 +00005879 }
5880 }
5881 break;
bellard31e31b82003-02-18 22:55:36 +00005882 case TARGET_NR_sched_setscheduler:
bellard5cd43932003-03-29 16:54:36 +00005883 {
pbrook53a59602006-03-25 19:31:22 +00005884 struct sched_param *target_schp;
bellard5cd43932003-03-29 16:54:36 +00005885 struct sched_param schp;
bellard579a97f2007-11-11 14:26:47 +00005886 if (!lock_user_struct(VERIFY_READ, target_schp, arg3, 1))
5887 goto efault;
bellard5cd43932003-03-29 16:54:36 +00005888 schp.sched_priority = tswap32(target_schp->sched_priority);
pbrook53a59602006-03-25 19:31:22 +00005889 unlock_user_struct(target_schp, arg3, 0);
bellard5cd43932003-03-29 16:54:36 +00005890 ret = get_errno(sched_setscheduler(arg1, arg2, &schp));
5891 }
5892 break;
bellard31e31b82003-02-18 22:55:36 +00005893 case TARGET_NR_sched_getscheduler:
bellard5cd43932003-03-29 16:54:36 +00005894 ret = get_errno(sched_getscheduler(arg1));
5895 break;
bellard31e31b82003-02-18 22:55:36 +00005896 case TARGET_NR_sched_yield:
5897 ret = get_errno(sched_yield());
5898 break;
5899 case TARGET_NR_sched_get_priority_max:
bellard5cd43932003-03-29 16:54:36 +00005900 ret = get_errno(sched_get_priority_max(arg1));
5901 break;
bellard31e31b82003-02-18 22:55:36 +00005902 case TARGET_NR_sched_get_priority_min:
bellard5cd43932003-03-29 16:54:36 +00005903 ret = get_errno(sched_get_priority_min(arg1));
5904 break;
bellard31e31b82003-02-18 22:55:36 +00005905 case TARGET_NR_sched_rr_get_interval:
bellard5cd43932003-03-29 16:54:36 +00005906 {
bellard5cd43932003-03-29 16:54:36 +00005907 struct timespec ts;
5908 ret = get_errno(sched_rr_get_interval(arg1, &ts));
5909 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00005910 host_to_target_timespec(arg2, &ts);
bellard5cd43932003-03-29 16:54:36 +00005911 }
5912 }
5913 break;
bellard31e31b82003-02-18 22:55:36 +00005914 case TARGET_NR_nanosleep:
bellard1b6b0292003-03-22 17:31:38 +00005915 {
bellard1b6b0292003-03-22 17:31:38 +00005916 struct timespec req, rem;
pbrook53a59602006-03-25 19:31:22 +00005917 target_to_host_timespec(&req, arg1);
bellard1b6b0292003-03-22 17:31:38 +00005918 ret = get_errno(nanosleep(&req, &rem));
pbrook53a59602006-03-25 19:31:22 +00005919 if (is_error(ret) && arg2) {
5920 host_to_target_timespec(arg2, &rem);
bellard1b6b0292003-03-22 17:31:38 +00005921 }
5922 }
5923 break;
thse5febef2007-04-01 18:31:35 +00005924#ifdef TARGET_NR_query_module
bellard31e31b82003-02-18 22:55:36 +00005925 case TARGET_NR_query_module:
bellard5cd43932003-03-29 16:54:36 +00005926 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00005927#endif
5928#ifdef TARGET_NR_nfsservctl
bellard31e31b82003-02-18 22:55:36 +00005929 case TARGET_NR_nfsservctl:
bellard5cd43932003-03-29 16:54:36 +00005930 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00005931#endif
bellard31e31b82003-02-18 22:55:36 +00005932 case TARGET_NR_prctl:
thse5574482007-02-11 20:03:13 +00005933 switch (arg1)
5934 {
5935 case PR_GET_PDEATHSIG:
5936 {
5937 int deathsig;
5938 ret = get_errno(prctl(arg1, &deathsig, arg3, arg4, arg5));
bellard2f619692007-11-16 10:46:05 +00005939 if (!is_error(ret) && arg2
5940 && put_user_ual(deathsig, arg2))
5941 goto efault;
thse5574482007-02-11 20:03:13 +00005942 }
5943 break;
5944 default:
5945 ret = get_errno(prctl(arg1, arg2, arg3, arg4, arg5));
5946 break;
5947 }
ths39b9aae2007-02-11 18:36:44 +00005948 break;
bellardd2fd1af2007-11-14 18:08:56 +00005949#ifdef TARGET_NR_arch_prctl
5950 case TARGET_NR_arch_prctl:
5951#if defined(TARGET_I386) && !defined(TARGET_ABI32)
5952 ret = do_arch_prctl(cpu_env, arg1, arg2);
5953 break;
5954#else
5955 goto unimplemented;
5956#endif
5957#endif
bellard67867302003-11-23 17:05:30 +00005958#ifdef TARGET_NR_pread
bellard31e31b82003-02-18 22:55:36 +00005959 case TARGET_NR_pread:
balroga4ae00b2008-09-20 03:14:14 +00005960#ifdef TARGET_ARM
5961 if (((CPUARMState *)cpu_env)->eabi)
5962 arg4 = arg5;
5963#endif
bellard579a97f2007-11-11 14:26:47 +00005964 if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
5965 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005966 ret = get_errno(pread(arg1, p, arg3, arg4));
5967 unlock_user(p, arg2, ret);
bellard206f0fa2003-05-14 19:01:56 +00005968 break;
bellard31e31b82003-02-18 22:55:36 +00005969 case TARGET_NR_pwrite:
balroga4ae00b2008-09-20 03:14:14 +00005970#ifdef TARGET_ARM
5971 if (((CPUARMState *)cpu_env)->eabi)
5972 arg4 = arg5;
5973#endif
bellard579a97f2007-11-11 14:26:47 +00005974 if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
5975 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005976 ret = get_errno(pwrite(arg1, p, arg3, arg4));
5977 unlock_user(p, arg2, 0);
bellard206f0fa2003-05-14 19:01:56 +00005978 break;
bellard67867302003-11-23 17:05:30 +00005979#endif
aurel32f2c7ba12008-03-28 22:32:06 +00005980#ifdef TARGET_NR_pread64
5981 case TARGET_NR_pread64:
5982 if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
5983 goto efault;
5984 ret = get_errno(pread64(arg1, p, arg3, target_offset64(arg4, arg5)));
5985 unlock_user(p, arg2, ret);
5986 break;
5987 case TARGET_NR_pwrite64:
5988 if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
5989 goto efault;
5990 ret = get_errno(pwrite64(arg1, p, arg3, target_offset64(arg4, arg5)));
5991 unlock_user(p, arg2, 0);
5992 break;
5993#endif
bellard31e31b82003-02-18 22:55:36 +00005994 case TARGET_NR_getcwd:
bellard579a97f2007-11-11 14:26:47 +00005995 if (!(p = lock_user(VERIFY_WRITE, arg1, arg2, 0)))
5996 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005997 ret = get_errno(sys_getcwd1(p, arg2));
5998 unlock_user(p, arg1, ret);
bellard31e31b82003-02-18 22:55:36 +00005999 break;
6000 case TARGET_NR_capget:
bellard5cd43932003-03-29 16:54:36 +00006001 goto unimplemented;
bellard31e31b82003-02-18 22:55:36 +00006002 case TARGET_NR_capset:
bellard5cd43932003-03-29 16:54:36 +00006003 goto unimplemented;
bellard31e31b82003-02-18 22:55:36 +00006004 case TARGET_NR_sigaltstack:
ths198a74d2007-09-27 16:44:32 +00006005#if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_MIPS) || \
6006 defined(TARGET_SPARC) || defined(TARGET_PPC) || defined(TARGET_ALPHA)
bellard579a97f2007-11-11 14:26:47 +00006007 ret = do_sigaltstack(arg1, arg2, get_sp_from_cpustate((CPUState *)cpu_env));
thsa04e1342007-09-27 13:57:58 +00006008 break;
6009#else
bellard5cd43932003-03-29 16:54:36 +00006010 goto unimplemented;
thsa04e1342007-09-27 13:57:58 +00006011#endif
bellard31e31b82003-02-18 22:55:36 +00006012 case TARGET_NR_sendfile:
bellard5cd43932003-03-29 16:54:36 +00006013 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00006014#ifdef TARGET_NR_getpmsg
bellard31e31b82003-02-18 22:55:36 +00006015 case TARGET_NR_getpmsg:
bellard5cd43932003-03-29 16:54:36 +00006016 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00006017#endif
6018#ifdef TARGET_NR_putpmsg
bellard31e31b82003-02-18 22:55:36 +00006019 case TARGET_NR_putpmsg:
bellard5cd43932003-03-29 16:54:36 +00006020 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00006021#endif
bellard048f6b42005-11-26 18:47:20 +00006022#ifdef TARGET_NR_vfork
bellard31e31b82003-02-18 22:55:36 +00006023 case TARGET_NR_vfork:
pbrookd865bab2008-06-07 22:12:17 +00006024 ret = get_errno(do_fork(cpu_env, CLONE_VFORK | CLONE_VM | SIGCHLD,
6025 0, 0, 0, 0));
bellard31e31b82003-02-18 22:55:36 +00006026 break;
bellard048f6b42005-11-26 18:47:20 +00006027#endif
bellardebc05482003-09-30 21:08:41 +00006028#ifdef TARGET_NR_ugetrlimit
bellard31e31b82003-02-18 22:55:36 +00006029 case TARGET_NR_ugetrlimit:
bellard728584b2003-04-29 20:43:36 +00006030 {
6031 struct rlimit rlim;
6032 ret = get_errno(getrlimit(arg1, &rlim));
6033 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00006034 struct target_rlimit *target_rlim;
bellard579a97f2007-11-11 14:26:47 +00006035 if (!lock_user_struct(VERIFY_WRITE, target_rlim, arg2, 0))
6036 goto efault;
bellard728584b2003-04-29 20:43:36 +00006037 target_rlim->rlim_cur = tswapl(rlim.rlim_cur);
6038 target_rlim->rlim_max = tswapl(rlim.rlim_max);
pbrook53a59602006-03-25 19:31:22 +00006039 unlock_user_struct(target_rlim, arg2, 1);
bellard728584b2003-04-29 20:43:36 +00006040 }
6041 break;
6042 }
bellardebc05482003-09-30 21:08:41 +00006043#endif
bellarda315a142005-01-30 22:59:18 +00006044#ifdef TARGET_NR_truncate64
bellard31e31b82003-02-18 22:55:36 +00006045 case TARGET_NR_truncate64:
bellard579a97f2007-11-11 14:26:47 +00006046 if (!(p = lock_user_string(arg1)))
6047 goto efault;
pbrook53a59602006-03-25 19:31:22 +00006048 ret = target_truncate64(cpu_env, p, arg2, arg3, arg4);
6049 unlock_user(p, arg1, 0);
bellard667f38b2005-07-23 14:46:27 +00006050 break;
bellarda315a142005-01-30 22:59:18 +00006051#endif
6052#ifdef TARGET_NR_ftruncate64
bellard31e31b82003-02-18 22:55:36 +00006053 case TARGET_NR_ftruncate64:
pbrookce4defa2006-02-09 16:49:55 +00006054 ret = target_ftruncate64(cpu_env, arg1, arg2, arg3, arg4);
bellard667f38b2005-07-23 14:46:27 +00006055 break;
bellarda315a142005-01-30 22:59:18 +00006056#endif
6057#ifdef TARGET_NR_stat64
bellard31e31b82003-02-18 22:55:36 +00006058 case TARGET_NR_stat64:
bellard579a97f2007-11-11 14:26:47 +00006059 if (!(p = lock_user_string(arg1)))
6060 goto efault;
pbrook53a59602006-03-25 19:31:22 +00006061 ret = get_errno(stat(path(p), &st));
6062 unlock_user(p, arg1, 0);
balrog6a24a772008-09-20 02:23:36 +00006063 if (!is_error(ret))
6064 ret = host_to_target_stat64(cpu_env, arg2, &st);
6065 break;
bellarda315a142005-01-30 22:59:18 +00006066#endif
6067#ifdef TARGET_NR_lstat64
bellard31e31b82003-02-18 22:55:36 +00006068 case TARGET_NR_lstat64:
bellard579a97f2007-11-11 14:26:47 +00006069 if (!(p = lock_user_string(arg1)))
6070 goto efault;
pbrook53a59602006-03-25 19:31:22 +00006071 ret = get_errno(lstat(path(p), &st));
6072 unlock_user(p, arg1, 0);
balrog6a24a772008-09-20 02:23:36 +00006073 if (!is_error(ret))
6074 ret = host_to_target_stat64(cpu_env, arg2, &st);
6075 break;
bellarda315a142005-01-30 22:59:18 +00006076#endif
6077#ifdef TARGET_NR_fstat64
bellard31e31b82003-02-18 22:55:36 +00006078 case TARGET_NR_fstat64:
balrog6a24a772008-09-20 02:23:36 +00006079 ret = get_errno(fstat(arg1, &st));
6080 if (!is_error(ret))
6081 ret = host_to_target_stat64(cpu_env, arg2, &st);
6082 break;
bellardec86b0f2003-04-11 00:15:04 +00006083#endif
aurel329d33b762009-04-08 23:07:05 +00006084#if (defined(TARGET_NR_fstatat64) || defined(TARGET_NR_newfstatat)) && \
6085 (defined(__NR_fstatat64) || defined(__NR_newfstatat))
6086#ifdef TARGET_NR_fstatat64
balrog6a24a772008-09-20 02:23:36 +00006087 case TARGET_NR_fstatat64:
aurel329d33b762009-04-08 23:07:05 +00006088#endif
6089#ifdef TARGET_NR_newfstatat
6090 case TARGET_NR_newfstatat:
6091#endif
balrog6a24a772008-09-20 02:23:36 +00006092 if (!(p = lock_user_string(arg2)))
6093 goto efault;
aurel329d33b762009-04-08 23:07:05 +00006094#ifdef __NR_fstatat64
balrog6a24a772008-09-20 02:23:36 +00006095 ret = get_errno(sys_fstatat64(arg1, path(p), &st, arg4));
aurel329d33b762009-04-08 23:07:05 +00006096#else
6097 ret = get_errno(sys_newfstatat(arg1, path(p), &st, arg4));
6098#endif
balrog6a24a772008-09-20 02:23:36 +00006099 if (!is_error(ret))
6100 ret = host_to_target_stat64(cpu_env, arg3, &st);
bellard60cd49d2003-03-16 22:53:56 +00006101 break;
bellarda315a142005-01-30 22:59:18 +00006102#endif
bellard67867302003-11-23 17:05:30 +00006103#ifdef USE_UID16
6104 case TARGET_NR_lchown:
bellard579a97f2007-11-11 14:26:47 +00006105 if (!(p = lock_user_string(arg1)))
6106 goto efault;
pbrook53a59602006-03-25 19:31:22 +00006107 ret = get_errno(lchown(p, low2highuid(arg2), low2highgid(arg3)));
6108 unlock_user(p, arg1, 0);
bellard67867302003-11-23 17:05:30 +00006109 break;
6110 case TARGET_NR_getuid:
6111 ret = get_errno(high2lowuid(getuid()));
6112 break;
6113 case TARGET_NR_getgid:
6114 ret = get_errno(high2lowgid(getgid()));
6115 break;
6116 case TARGET_NR_geteuid:
6117 ret = get_errno(high2lowuid(geteuid()));
6118 break;
6119 case TARGET_NR_getegid:
6120 ret = get_errno(high2lowgid(getegid()));
6121 break;
6122 case TARGET_NR_setreuid:
6123 ret = get_errno(setreuid(low2highuid(arg1), low2highuid(arg2)));
6124 break;
6125 case TARGET_NR_setregid:
6126 ret = get_errno(setregid(low2highgid(arg1), low2highgid(arg2)));
6127 break;
6128 case TARGET_NR_getgroups:
6129 {
6130 int gidsetsize = arg1;
pbrook53a59602006-03-25 19:31:22 +00006131 uint16_t *target_grouplist;
bellard67867302003-11-23 17:05:30 +00006132 gid_t *grouplist;
6133 int i;
6134
6135 grouplist = alloca(gidsetsize * sizeof(gid_t));
6136 ret = get_errno(getgroups(gidsetsize, grouplist));
balrogcb3bc232008-09-20 02:08:13 +00006137 if (gidsetsize == 0)
6138 break;
bellard67867302003-11-23 17:05:30 +00006139 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00006140 target_grouplist = lock_user(VERIFY_WRITE, arg2, gidsetsize * 2, 0);
6141 if (!target_grouplist)
6142 goto efault;
balroga2155fc2008-09-20 02:12:08 +00006143 for(i = 0;i < ret; i++)
bellard67867302003-11-23 17:05:30 +00006144 target_grouplist[i] = tswap16(grouplist[i]);
pbrook53a59602006-03-25 19:31:22 +00006145 unlock_user(target_grouplist, arg2, gidsetsize * 2);
bellard67867302003-11-23 17:05:30 +00006146 }
6147 }
6148 break;
6149 case TARGET_NR_setgroups:
6150 {
6151 int gidsetsize = arg1;
pbrook53a59602006-03-25 19:31:22 +00006152 uint16_t *target_grouplist;
bellard67867302003-11-23 17:05:30 +00006153 gid_t *grouplist;
6154 int i;
6155
6156 grouplist = alloca(gidsetsize * sizeof(gid_t));
bellard579a97f2007-11-11 14:26:47 +00006157 target_grouplist = lock_user(VERIFY_READ, arg2, gidsetsize * 2, 1);
6158 if (!target_grouplist) {
6159 ret = -TARGET_EFAULT;
6160 goto fail;
6161 }
bellard67867302003-11-23 17:05:30 +00006162 for(i = 0;i < gidsetsize; i++)
6163 grouplist[i] = tswap16(target_grouplist[i]);
pbrook53a59602006-03-25 19:31:22 +00006164 unlock_user(target_grouplist, arg2, 0);
bellard67867302003-11-23 17:05:30 +00006165 ret = get_errno(setgroups(gidsetsize, grouplist));
6166 }
6167 break;
6168 case TARGET_NR_fchown:
6169 ret = get_errno(fchown(arg1, low2highuid(arg2), low2highgid(arg3)));
6170 break;
thsccfa72b2007-09-24 09:23:34 +00006171#if defined(TARGET_NR_fchownat) && defined(__NR_fchownat)
6172 case TARGET_NR_fchownat:
bellard579a97f2007-11-11 14:26:47 +00006173 if (!(p = lock_user_string(arg2)))
6174 goto efault;
6175 ret = get_errno(sys_fchownat(arg1, p, low2highuid(arg3), low2highgid(arg4), arg5));
6176 unlock_user(p, arg2, 0);
thsccfa72b2007-09-24 09:23:34 +00006177 break;
6178#endif
bellard67867302003-11-23 17:05:30 +00006179#ifdef TARGET_NR_setresuid
6180 case TARGET_NR_setresuid:
ths5fafdf22007-09-16 21:08:06 +00006181 ret = get_errno(setresuid(low2highuid(arg1),
6182 low2highuid(arg2),
bellard67867302003-11-23 17:05:30 +00006183 low2highuid(arg3)));
6184 break;
6185#endif
6186#ifdef TARGET_NR_getresuid
6187 case TARGET_NR_getresuid:
6188 {
pbrook53a59602006-03-25 19:31:22 +00006189 uid_t ruid, euid, suid;
bellard67867302003-11-23 17:05:30 +00006190 ret = get_errno(getresuid(&ruid, &euid, &suid));
6191 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +00006192 if (put_user_u16(high2lowuid(ruid), arg1)
6193 || put_user_u16(high2lowuid(euid), arg2)
6194 || put_user_u16(high2lowuid(suid), arg3))
6195 goto efault;
bellard67867302003-11-23 17:05:30 +00006196 }
6197 }
6198 break;
6199#endif
6200#ifdef TARGET_NR_getresgid
6201 case TARGET_NR_setresgid:
ths5fafdf22007-09-16 21:08:06 +00006202 ret = get_errno(setresgid(low2highgid(arg1),
6203 low2highgid(arg2),
bellard67867302003-11-23 17:05:30 +00006204 low2highgid(arg3)));
6205 break;
6206#endif
6207#ifdef TARGET_NR_getresgid
6208 case TARGET_NR_getresgid:
6209 {
pbrook53a59602006-03-25 19:31:22 +00006210 gid_t rgid, egid, sgid;
bellard67867302003-11-23 17:05:30 +00006211 ret = get_errno(getresgid(&rgid, &egid, &sgid));
6212 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +00006213 if (put_user_u16(high2lowgid(rgid), arg1)
6214 || put_user_u16(high2lowgid(egid), arg2)
6215 || put_user_u16(high2lowgid(sgid), arg3))
6216 goto efault;
bellard67867302003-11-23 17:05:30 +00006217 }
6218 }
6219 break;
6220#endif
6221 case TARGET_NR_chown:
bellard579a97f2007-11-11 14:26:47 +00006222 if (!(p = lock_user_string(arg1)))
6223 goto efault;
pbrook53a59602006-03-25 19:31:22 +00006224 ret = get_errno(chown(p, low2highuid(arg2), low2highgid(arg3)));
6225 unlock_user(p, arg1, 0);
bellard67867302003-11-23 17:05:30 +00006226 break;
6227 case TARGET_NR_setuid:
6228 ret = get_errno(setuid(low2highuid(arg1)));
6229 break;
6230 case TARGET_NR_setgid:
6231 ret = get_errno(setgid(low2highgid(arg1)));
6232 break;
6233 case TARGET_NR_setfsuid:
6234 ret = get_errno(setfsuid(arg1));
6235 break;
6236 case TARGET_NR_setfsgid:
6237 ret = get_errno(setfsgid(arg1));
6238 break;
6239#endif /* USE_UID16 */
6240
bellarda315a142005-01-30 22:59:18 +00006241#ifdef TARGET_NR_lchown32
bellard31e31b82003-02-18 22:55:36 +00006242 case TARGET_NR_lchown32:
bellard579a97f2007-11-11 14:26:47 +00006243 if (!(p = lock_user_string(arg1)))
6244 goto efault;
pbrook53a59602006-03-25 19:31:22 +00006245 ret = get_errno(lchown(p, arg2, arg3));
6246 unlock_user(p, arg1, 0);
bellardb03c60f2003-03-23 17:19:56 +00006247 break;
bellarda315a142005-01-30 22:59:18 +00006248#endif
6249#ifdef TARGET_NR_getuid32
bellard31e31b82003-02-18 22:55:36 +00006250 case TARGET_NR_getuid32:
bellardb03c60f2003-03-23 17:19:56 +00006251 ret = get_errno(getuid());
6252 break;
bellarda315a142005-01-30 22:59:18 +00006253#endif
aurel3264b4d282008-11-14 17:20:15 +00006254
6255#if defined(TARGET_NR_getxuid) && defined(TARGET_ALPHA)
6256 /* Alpha specific */
6257 case TARGET_NR_getxuid:
6258 {
6259 uid_t euid;
6260 euid=geteuid();
6261 ((CPUAlphaState *)cpu_env)->ir[IR_A4]=euid;
6262 }
6263 ret = get_errno(getuid());
6264 break;
6265#endif
6266#if defined(TARGET_NR_getxgid) && defined(TARGET_ALPHA)
6267 /* Alpha specific */
6268 case TARGET_NR_getxgid:
6269 {
6270 uid_t egid;
6271 egid=getegid();
6272 ((CPUAlphaState *)cpu_env)->ir[IR_A4]=egid;
6273 }
6274 ret = get_errno(getgid());
6275 break;
6276#endif
6277
bellarda315a142005-01-30 22:59:18 +00006278#ifdef TARGET_NR_getgid32
bellard31e31b82003-02-18 22:55:36 +00006279 case TARGET_NR_getgid32:
bellardb03c60f2003-03-23 17:19:56 +00006280 ret = get_errno(getgid());
6281 break;
bellarda315a142005-01-30 22:59:18 +00006282#endif
6283#ifdef TARGET_NR_geteuid32
bellard31e31b82003-02-18 22:55:36 +00006284 case TARGET_NR_geteuid32:
bellardb03c60f2003-03-23 17:19:56 +00006285 ret = get_errno(geteuid());
6286 break;
bellarda315a142005-01-30 22:59:18 +00006287#endif
6288#ifdef TARGET_NR_getegid32
bellard31e31b82003-02-18 22:55:36 +00006289 case TARGET_NR_getegid32:
bellardb03c60f2003-03-23 17:19:56 +00006290 ret = get_errno(getegid());
6291 break;
bellarda315a142005-01-30 22:59:18 +00006292#endif
6293#ifdef TARGET_NR_setreuid32
bellard31e31b82003-02-18 22:55:36 +00006294 case TARGET_NR_setreuid32:
bellardb03c60f2003-03-23 17:19:56 +00006295 ret = get_errno(setreuid(arg1, arg2));
6296 break;
bellarda315a142005-01-30 22:59:18 +00006297#endif
6298#ifdef TARGET_NR_setregid32
bellard31e31b82003-02-18 22:55:36 +00006299 case TARGET_NR_setregid32:
bellardb03c60f2003-03-23 17:19:56 +00006300 ret = get_errno(setregid(arg1, arg2));
6301 break;
bellarda315a142005-01-30 22:59:18 +00006302#endif
6303#ifdef TARGET_NR_getgroups32
bellard31e31b82003-02-18 22:55:36 +00006304 case TARGET_NR_getgroups32:
bellard99c475a2005-01-31 20:45:13 +00006305 {
6306 int gidsetsize = arg1;
pbrook53a59602006-03-25 19:31:22 +00006307 uint32_t *target_grouplist;
bellard99c475a2005-01-31 20:45:13 +00006308 gid_t *grouplist;
6309 int i;
6310
6311 grouplist = alloca(gidsetsize * sizeof(gid_t));
6312 ret = get_errno(getgroups(gidsetsize, grouplist));
balrogcb3bc232008-09-20 02:08:13 +00006313 if (gidsetsize == 0)
6314 break;
bellard99c475a2005-01-31 20:45:13 +00006315 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00006316 target_grouplist = lock_user(VERIFY_WRITE, arg2, gidsetsize * 4, 0);
6317 if (!target_grouplist) {
6318 ret = -TARGET_EFAULT;
6319 goto fail;
6320 }
balroga2155fc2008-09-20 02:12:08 +00006321 for(i = 0;i < ret; i++)
pbrook53a59602006-03-25 19:31:22 +00006322 target_grouplist[i] = tswap32(grouplist[i]);
6323 unlock_user(target_grouplist, arg2, gidsetsize * 4);
bellard99c475a2005-01-31 20:45:13 +00006324 }
6325 }
6326 break;
bellarda315a142005-01-30 22:59:18 +00006327#endif
6328#ifdef TARGET_NR_setgroups32
bellard31e31b82003-02-18 22:55:36 +00006329 case TARGET_NR_setgroups32:
bellard99c475a2005-01-31 20:45:13 +00006330 {
6331 int gidsetsize = arg1;
pbrook53a59602006-03-25 19:31:22 +00006332 uint32_t *target_grouplist;
bellard99c475a2005-01-31 20:45:13 +00006333 gid_t *grouplist;
6334 int i;
ths3b46e622007-09-17 08:09:54 +00006335
bellard99c475a2005-01-31 20:45:13 +00006336 grouplist = alloca(gidsetsize * sizeof(gid_t));
bellard579a97f2007-11-11 14:26:47 +00006337 target_grouplist = lock_user(VERIFY_READ, arg2, gidsetsize * 4, 1);
6338 if (!target_grouplist) {
6339 ret = -TARGET_EFAULT;
6340 goto fail;
6341 }
bellard99c475a2005-01-31 20:45:13 +00006342 for(i = 0;i < gidsetsize; i++)
pbrook53a59602006-03-25 19:31:22 +00006343 grouplist[i] = tswap32(target_grouplist[i]);
6344 unlock_user(target_grouplist, arg2, 0);
bellard99c475a2005-01-31 20:45:13 +00006345 ret = get_errno(setgroups(gidsetsize, grouplist));
6346 }
6347 break;
bellarda315a142005-01-30 22:59:18 +00006348#endif
6349#ifdef TARGET_NR_fchown32
bellard31e31b82003-02-18 22:55:36 +00006350 case TARGET_NR_fchown32:
bellardb03c60f2003-03-23 17:19:56 +00006351 ret = get_errno(fchown(arg1, arg2, arg3));
6352 break;
bellarda315a142005-01-30 22:59:18 +00006353#endif
6354#ifdef TARGET_NR_setresuid32
bellard31e31b82003-02-18 22:55:36 +00006355 case TARGET_NR_setresuid32:
bellardb03c60f2003-03-23 17:19:56 +00006356 ret = get_errno(setresuid(arg1, arg2, arg3));
6357 break;
bellarda315a142005-01-30 22:59:18 +00006358#endif
6359#ifdef TARGET_NR_getresuid32
bellard31e31b82003-02-18 22:55:36 +00006360 case TARGET_NR_getresuid32:
bellardb03c60f2003-03-23 17:19:56 +00006361 {
pbrook53a59602006-03-25 19:31:22 +00006362 uid_t ruid, euid, suid;
bellardb03c60f2003-03-23 17:19:56 +00006363 ret = get_errno(getresuid(&ruid, &euid, &suid));
6364 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +00006365 if (put_user_u32(ruid, arg1)
6366 || put_user_u32(euid, arg2)
6367 || put_user_u32(suid, arg3))
6368 goto efault;
bellardb03c60f2003-03-23 17:19:56 +00006369 }
6370 }
6371 break;
bellarda315a142005-01-30 22:59:18 +00006372#endif
6373#ifdef TARGET_NR_setresgid32
bellard31e31b82003-02-18 22:55:36 +00006374 case TARGET_NR_setresgid32:
bellardb03c60f2003-03-23 17:19:56 +00006375 ret = get_errno(setresgid(arg1, arg2, arg3));
6376 break;
bellarda315a142005-01-30 22:59:18 +00006377#endif
6378#ifdef TARGET_NR_getresgid32
bellard31e31b82003-02-18 22:55:36 +00006379 case TARGET_NR_getresgid32:
bellardb03c60f2003-03-23 17:19:56 +00006380 {
pbrook53a59602006-03-25 19:31:22 +00006381 gid_t rgid, egid, sgid;
bellardb03c60f2003-03-23 17:19:56 +00006382 ret = get_errno(getresgid(&rgid, &egid, &sgid));
6383 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +00006384 if (put_user_u32(rgid, arg1)
6385 || put_user_u32(egid, arg2)
6386 || put_user_u32(sgid, arg3))
6387 goto efault;
bellardb03c60f2003-03-23 17:19:56 +00006388 }
6389 }
6390 break;
bellarda315a142005-01-30 22:59:18 +00006391#endif
6392#ifdef TARGET_NR_chown32
bellard31e31b82003-02-18 22:55:36 +00006393 case TARGET_NR_chown32:
bellard579a97f2007-11-11 14:26:47 +00006394 if (!(p = lock_user_string(arg1)))
6395 goto efault;
pbrook53a59602006-03-25 19:31:22 +00006396 ret = get_errno(chown(p, arg2, arg3));
6397 unlock_user(p, arg1, 0);
bellardb03c60f2003-03-23 17:19:56 +00006398 break;
bellarda315a142005-01-30 22:59:18 +00006399#endif
6400#ifdef TARGET_NR_setuid32
bellard31e31b82003-02-18 22:55:36 +00006401 case TARGET_NR_setuid32:
bellardb03c60f2003-03-23 17:19:56 +00006402 ret = get_errno(setuid(arg1));
6403 break;
bellarda315a142005-01-30 22:59:18 +00006404#endif
6405#ifdef TARGET_NR_setgid32
bellard31e31b82003-02-18 22:55:36 +00006406 case TARGET_NR_setgid32:
bellardb03c60f2003-03-23 17:19:56 +00006407 ret = get_errno(setgid(arg1));
6408 break;
bellarda315a142005-01-30 22:59:18 +00006409#endif
6410#ifdef TARGET_NR_setfsuid32
bellard31e31b82003-02-18 22:55:36 +00006411 case TARGET_NR_setfsuid32:
bellardb03c60f2003-03-23 17:19:56 +00006412 ret = get_errno(setfsuid(arg1));
6413 break;
bellarda315a142005-01-30 22:59:18 +00006414#endif
6415#ifdef TARGET_NR_setfsgid32
bellard31e31b82003-02-18 22:55:36 +00006416 case TARGET_NR_setfsgid32:
bellardb03c60f2003-03-23 17:19:56 +00006417 ret = get_errno(setfsgid(arg1));
6418 break;
bellarda315a142005-01-30 22:59:18 +00006419#endif
bellard67867302003-11-23 17:05:30 +00006420
bellard31e31b82003-02-18 22:55:36 +00006421 case TARGET_NR_pivot_root:
bellardb03c60f2003-03-23 17:19:56 +00006422 goto unimplemented;
bellardffa65c32004-01-04 23:57:22 +00006423#ifdef TARGET_NR_mincore
bellard31e31b82003-02-18 22:55:36 +00006424 case TARGET_NR_mincore:
aurel3204bb9ac2008-10-01 21:46:41 +00006425 {
6426 void *a;
6427 ret = -TARGET_EFAULT;
6428 if (!(a = lock_user(VERIFY_READ, arg1,arg2, 0)))
6429 goto efault;
6430 if (!(p = lock_user_string(arg3)))
6431 goto mincore_fail;
6432 ret = get_errno(mincore(a, arg2, p));
6433 unlock_user(p, arg3, ret);
6434 mincore_fail:
6435 unlock_user(a, arg1, 0);
6436 }
6437 break;
bellardffa65c32004-01-04 23:57:22 +00006438#endif
aurel32408321b2008-10-01 21:46:32 +00006439#ifdef TARGET_NR_arm_fadvise64_64
6440 case TARGET_NR_arm_fadvise64_64:
6441 {
6442 /*
6443 * arm_fadvise64_64 looks like fadvise64_64 but
6444 * with different argument order
6445 */
6446 abi_long temp;
6447 temp = arg3;
6448 arg3 = arg4;
6449 arg4 = temp;
6450 }
6451#endif
6452#if defined(TARGET_NR_fadvise64_64) || defined(TARGET_NR_arm_fadvise64_64)
6453#ifdef TARGET_NR_fadvise64_64
6454 case TARGET_NR_fadvise64_64:
6455#endif
6456 /* This is a hint, so ignoring and returning success is ok. */
6457 ret = get_errno(0);
6458 break;
6459#endif
bellardffa65c32004-01-04 23:57:22 +00006460#ifdef TARGET_NR_madvise
bellard31e31b82003-02-18 22:55:36 +00006461 case TARGET_NR_madvise:
pbrook24836682006-04-16 14:14:53 +00006462 /* A straight passthrough may not be safe because qemu sometimes
6463 turns private flie-backed mappings into anonymous mappings.
6464 This will break MADV_DONTNEED.
6465 This is a hint, so ignoring and returning success is ok. */
6466 ret = get_errno(0);
6467 break;
bellardffa65c32004-01-04 23:57:22 +00006468#endif
blueswir1992f48a2007-10-14 16:27:31 +00006469#if TARGET_ABI_BITS == 32
bellard31e31b82003-02-18 22:55:36 +00006470 case TARGET_NR_fcntl64:
bellard77e46722003-04-29 20:39:06 +00006471 {
thsb1e341e2007-03-20 21:50:52 +00006472 int cmd;
bellard77e46722003-04-29 20:39:06 +00006473 struct flock64 fl;
pbrook53a59602006-03-25 19:31:22 +00006474 struct target_flock64 *target_fl;
pbrookce4defa2006-02-09 16:49:55 +00006475#ifdef TARGET_ARM
pbrook53a59602006-03-25 19:31:22 +00006476 struct target_eabi_flock64 *target_efl;
pbrookce4defa2006-02-09 16:49:55 +00006477#endif
bellard77e46722003-04-29 20:39:06 +00006478
thsb1e341e2007-03-20 21:50:52 +00006479 switch(arg2){
6480 case TARGET_F_GETLK64:
6481 cmd = F_GETLK64;
thsa7222582007-03-22 15:08:55 +00006482 break;
thsb1e341e2007-03-20 21:50:52 +00006483 case TARGET_F_SETLK64:
6484 cmd = F_SETLK64;
thsa7222582007-03-22 15:08:55 +00006485 break;
thsb1e341e2007-03-20 21:50:52 +00006486 case TARGET_F_SETLKW64:
6487 cmd = F_SETLK64;
thsa7222582007-03-22 15:08:55 +00006488 break;
thsb1e341e2007-03-20 21:50:52 +00006489 default:
6490 cmd = arg2;
thsa7222582007-03-22 15:08:55 +00006491 break;
thsb1e341e2007-03-20 21:50:52 +00006492 }
6493
bellard60cd49d2003-03-16 22:53:56 +00006494 switch(arg2) {
thsb1e341e2007-03-20 21:50:52 +00006495 case TARGET_F_GETLK64:
ths58134272007-03-31 18:59:32 +00006496#ifdef TARGET_ARM
6497 if (((CPUARMState *)cpu_env)->eabi) {
bellard9ee1fa22007-11-11 15:11:19 +00006498 if (!lock_user_struct(VERIFY_READ, target_efl, arg3, 1))
6499 goto efault;
ths58134272007-03-31 18:59:32 +00006500 fl.l_type = tswap16(target_efl->l_type);
6501 fl.l_whence = tswap16(target_efl->l_whence);
6502 fl.l_start = tswap64(target_efl->l_start);
6503 fl.l_len = tswap64(target_efl->l_len);
6504 fl.l_pid = tswapl(target_efl->l_pid);
6505 unlock_user_struct(target_efl, arg3, 0);
6506 } else
6507#endif
6508 {
bellard9ee1fa22007-11-11 15:11:19 +00006509 if (!lock_user_struct(VERIFY_READ, target_fl, arg3, 1))
6510 goto efault;
ths58134272007-03-31 18:59:32 +00006511 fl.l_type = tswap16(target_fl->l_type);
6512 fl.l_whence = tswap16(target_fl->l_whence);
6513 fl.l_start = tswap64(target_fl->l_start);
6514 fl.l_len = tswap64(target_fl->l_len);
6515 fl.l_pid = tswapl(target_fl->l_pid);
6516 unlock_user_struct(target_fl, arg3, 0);
6517 }
thsb1e341e2007-03-20 21:50:52 +00006518 ret = get_errno(fcntl(arg1, cmd, &fl));
bellard77e46722003-04-29 20:39:06 +00006519 if (ret == 0) {
pbrookce4defa2006-02-09 16:49:55 +00006520#ifdef TARGET_ARM
6521 if (((CPUARMState *)cpu_env)->eabi) {
bellard9ee1fa22007-11-11 15:11:19 +00006522 if (!lock_user_struct(VERIFY_WRITE, target_efl, arg3, 0))
6523 goto efault;
pbrookce4defa2006-02-09 16:49:55 +00006524 target_efl->l_type = tswap16(fl.l_type);
6525 target_efl->l_whence = tswap16(fl.l_whence);
6526 target_efl->l_start = tswap64(fl.l_start);
6527 target_efl->l_len = tswap64(fl.l_len);
6528 target_efl->l_pid = tswapl(fl.l_pid);
pbrook53a59602006-03-25 19:31:22 +00006529 unlock_user_struct(target_efl, arg3, 1);
pbrookce4defa2006-02-09 16:49:55 +00006530 } else
6531#endif
6532 {
bellard9ee1fa22007-11-11 15:11:19 +00006533 if (!lock_user_struct(VERIFY_WRITE, target_fl, arg3, 0))
6534 goto efault;
pbrookce4defa2006-02-09 16:49:55 +00006535 target_fl->l_type = tswap16(fl.l_type);
6536 target_fl->l_whence = tswap16(fl.l_whence);
6537 target_fl->l_start = tswap64(fl.l_start);
6538 target_fl->l_len = tswap64(fl.l_len);
6539 target_fl->l_pid = tswapl(fl.l_pid);
pbrook53a59602006-03-25 19:31:22 +00006540 unlock_user_struct(target_fl, arg3, 1);
pbrookce4defa2006-02-09 16:49:55 +00006541 }
bellard77e46722003-04-29 20:39:06 +00006542 }
6543 break;
6544
thsb1e341e2007-03-20 21:50:52 +00006545 case TARGET_F_SETLK64:
6546 case TARGET_F_SETLKW64:
pbrookce4defa2006-02-09 16:49:55 +00006547#ifdef TARGET_ARM
6548 if (((CPUARMState *)cpu_env)->eabi) {
bellard9ee1fa22007-11-11 15:11:19 +00006549 if (!lock_user_struct(VERIFY_READ, target_efl, arg3, 1))
6550 goto efault;
pbrookce4defa2006-02-09 16:49:55 +00006551 fl.l_type = tswap16(target_efl->l_type);
6552 fl.l_whence = tswap16(target_efl->l_whence);
6553 fl.l_start = tswap64(target_efl->l_start);
6554 fl.l_len = tswap64(target_efl->l_len);
6555 fl.l_pid = tswapl(target_efl->l_pid);
pbrook53a59602006-03-25 19:31:22 +00006556 unlock_user_struct(target_efl, arg3, 0);
pbrookce4defa2006-02-09 16:49:55 +00006557 } else
6558#endif
6559 {
bellard9ee1fa22007-11-11 15:11:19 +00006560 if (!lock_user_struct(VERIFY_READ, target_fl, arg3, 1))
6561 goto efault;
pbrookce4defa2006-02-09 16:49:55 +00006562 fl.l_type = tswap16(target_fl->l_type);
6563 fl.l_whence = tswap16(target_fl->l_whence);
6564 fl.l_start = tswap64(target_fl->l_start);
6565 fl.l_len = tswap64(target_fl->l_len);
6566 fl.l_pid = tswapl(target_fl->l_pid);
pbrook53a59602006-03-25 19:31:22 +00006567 unlock_user_struct(target_fl, arg3, 0);
pbrookce4defa2006-02-09 16:49:55 +00006568 }
thsb1e341e2007-03-20 21:50:52 +00006569 ret = get_errno(fcntl(arg1, cmd, &fl));
bellard77e46722003-04-29 20:39:06 +00006570 break;
bellard60cd49d2003-03-16 22:53:56 +00006571 default:
bellard9ee1fa22007-11-11 15:11:19 +00006572 ret = do_fcntl(arg1, cmd, arg3);
bellard60cd49d2003-03-16 22:53:56 +00006573 break;
6574 }
bellard77e46722003-04-29 20:39:06 +00006575 break;
6576 }
bellard60cd49d2003-03-16 22:53:56 +00006577#endif
ths7d600c82006-12-08 01:32:58 +00006578#ifdef TARGET_NR_cacheflush
6579 case TARGET_NR_cacheflush:
6580 /* self-modifying code is handled automatically, so nothing needed */
6581 ret = 0;
6582 break;
6583#endif
bellardebc05482003-09-30 21:08:41 +00006584#ifdef TARGET_NR_security
bellard31e31b82003-02-18 22:55:36 +00006585 case TARGET_NR_security:
6586 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00006587#endif
bellardc573ff62004-01-04 15:51:36 +00006588#ifdef TARGET_NR_getpagesize
6589 case TARGET_NR_getpagesize:
6590 ret = TARGET_PAGE_SIZE;
6591 break;
6592#endif
bellard31e31b82003-02-18 22:55:36 +00006593 case TARGET_NR_gettid:
6594 ret = get_errno(gettid());
6595 break;
thse5febef2007-04-01 18:31:35 +00006596#ifdef TARGET_NR_readahead
bellard31e31b82003-02-18 22:55:36 +00006597 case TARGET_NR_readahead:
aurel322054ac92008-10-13 21:08:07 +00006598#if TARGET_ABI_BITS == 32
6599#ifdef TARGET_ARM
6600 if (((CPUARMState *)cpu_env)->eabi)
6601 {
6602 arg2 = arg3;
6603 arg3 = arg4;
6604 arg4 = arg5;
6605 }
6606#endif
6607 ret = get_errno(readahead(arg1, ((off64_t)arg3 << 32) | arg2, arg4));
6608#else
6609 ret = get_errno(readahead(arg1, arg2, arg3));
6610#endif
6611 break;
thse5febef2007-04-01 18:31:35 +00006612#endif
bellardebc05482003-09-30 21:08:41 +00006613#ifdef TARGET_NR_setxattr
bellard31e31b82003-02-18 22:55:36 +00006614 case TARGET_NR_setxattr:
6615 case TARGET_NR_lsetxattr:
6616 case TARGET_NR_fsetxattr:
6617 case TARGET_NR_getxattr:
6618 case TARGET_NR_lgetxattr:
6619 case TARGET_NR_fgetxattr:
6620 case TARGET_NR_listxattr:
6621 case TARGET_NR_llistxattr:
6622 case TARGET_NR_flistxattr:
6623 case TARGET_NR_removexattr:
6624 case TARGET_NR_lremovexattr:
6625 case TARGET_NR_fremovexattr:
Arnaud Patard6f932f92009-04-21 21:04:18 +03006626 ret = -TARGET_EOPNOTSUPP;
6627 break;
bellardebc05482003-09-30 21:08:41 +00006628#endif
6629#ifdef TARGET_NR_set_thread_area
bellard5cd43932003-03-29 16:54:36 +00006630 case TARGET_NR_set_thread_area:
bellard8d18e892007-11-14 15:18:40 +00006631#if defined(TARGET_MIPS)
ths6f5b89a2007-03-02 20:48:00 +00006632 ((CPUMIPSState *) cpu_env)->tls_value = arg1;
6633 ret = 0;
6634 break;
edgar_iglef967792009-01-07 14:19:38 +00006635#elif defined(TARGET_CRIS)
6636 if (arg1 & 0xff)
6637 ret = -TARGET_EINVAL;
6638 else {
6639 ((CPUCRISState *) cpu_env)->pregs[PR_PID] = arg1;
6640 ret = 0;
6641 }
6642 break;
bellard8d18e892007-11-14 15:18:40 +00006643#elif defined(TARGET_I386) && defined(TARGET_ABI32)
6644 ret = do_set_thread_area(cpu_env, arg1);
6645 break;
ths6f5b89a2007-03-02 20:48:00 +00006646#else
6647 goto unimplemented_nowarn;
6648#endif
6649#endif
6650#ifdef TARGET_NR_get_thread_area
bellard5cd43932003-03-29 16:54:36 +00006651 case TARGET_NR_get_thread_area:
bellard8d18e892007-11-14 15:18:40 +00006652#if defined(TARGET_I386) && defined(TARGET_ABI32)
6653 ret = do_get_thread_area(cpu_env, arg1);
6654#else
bellard5cd43932003-03-29 16:54:36 +00006655 goto unimplemented_nowarn;
bellardebc05482003-09-30 21:08:41 +00006656#endif
bellard8d18e892007-11-14 15:18:40 +00006657#endif
bellard48dc41e2006-06-21 18:15:50 +00006658#ifdef TARGET_NR_getdomainname
6659 case TARGET_NR_getdomainname:
6660 goto unimplemented_nowarn;
6661#endif
ths6f5b89a2007-03-02 20:48:00 +00006662
thsb5906f92007-03-19 13:32:45 +00006663#ifdef TARGET_NR_clock_gettime
6664 case TARGET_NR_clock_gettime:
6665 {
6666 struct timespec ts;
6667 ret = get_errno(clock_gettime(arg1, &ts));
6668 if (!is_error(ret)) {
6669 host_to_target_timespec(arg2, &ts);
6670 }
6671 break;
6672 }
6673#endif
6674#ifdef TARGET_NR_clock_getres
6675 case TARGET_NR_clock_getres:
6676 {
6677 struct timespec ts;
6678 ret = get_errno(clock_getres(arg1, &ts));
6679 if (!is_error(ret)) {
6680 host_to_target_timespec(arg2, &ts);
6681 }
6682 break;
6683 }
6684#endif
pbrook63d76512008-05-29 13:43:29 +00006685#ifdef TARGET_NR_clock_nanosleep
6686 case TARGET_NR_clock_nanosleep:
6687 {
6688 struct timespec ts;
6689 target_to_host_timespec(&ts, arg3);
6690 ret = get_errno(clock_nanosleep(arg1, arg2, &ts, arg4 ? &ts : NULL));
6691 if (arg4)
6692 host_to_target_timespec(arg4, &ts);
6693 break;
6694 }
6695#endif
thsb5906f92007-03-19 13:32:45 +00006696
ths6f5b89a2007-03-02 20:48:00 +00006697#if defined(TARGET_NR_set_tid_address) && defined(__NR_set_tid_address)
6698 case TARGET_NR_set_tid_address:
bellard579a97f2007-11-11 14:26:47 +00006699 ret = get_errno(set_tid_address((int *)g2h(arg1)));
6700 break;
ths6f5b89a2007-03-02 20:48:00 +00006701#endif
6702
ths3ae43202007-09-16 21:39:48 +00006703#if defined(TARGET_NR_tkill) && defined(__NR_tkill)
ths4cae1d12007-07-12 11:06:53 +00006704 case TARGET_NR_tkill:
pbrook4cb05962008-05-30 18:05:19 +00006705 ret = get_errno(sys_tkill((int)arg1, target_to_host_signal(arg2)));
ths4cae1d12007-07-12 11:06:53 +00006706 break;
6707#endif
6708
ths3ae43202007-09-16 21:39:48 +00006709#if defined(TARGET_NR_tgkill) && defined(__NR_tgkill)
ths71455572007-06-21 21:45:30 +00006710 case TARGET_NR_tgkill:
pbrook4cb05962008-05-30 18:05:19 +00006711 ret = get_errno(sys_tgkill((int)arg1, (int)arg2,
6712 target_to_host_signal(arg3)));
ths71455572007-06-21 21:45:30 +00006713 break;
6714#endif
6715
ths4f2b1fe2007-06-21 21:57:12 +00006716#ifdef TARGET_NR_set_robust_list
6717 case TARGET_NR_set_robust_list:
6718 goto unimplemented_nowarn;
6719#endif
6720
ths9007f0e2007-09-25 17:50:37 +00006721#if defined(TARGET_NR_utimensat) && defined(__NR_utimensat)
6722 case TARGET_NR_utimensat:
6723 {
Riku Voipioebc996f2009-04-21 15:01:51 +03006724 struct timespec *tsp, ts[2];
6725 if (!arg3) {
6726 tsp = NULL;
6727 } else {
6728 target_to_host_timespec(ts, arg3);
6729 target_to_host_timespec(ts+1, arg3+sizeof(struct target_timespec));
6730 tsp = ts;
6731 }
ths9007f0e2007-09-25 17:50:37 +00006732 if (!arg2)
Riku Voipioebc996f2009-04-21 15:01:51 +03006733 ret = get_errno(sys_utimensat(arg1, NULL, tsp, arg4));
ths9007f0e2007-09-25 17:50:37 +00006734 else {
bellard579a97f2007-11-11 14:26:47 +00006735 if (!(p = lock_user_string(arg2))) {
ths0da46a62007-10-20 20:23:07 +00006736 ret = -TARGET_EFAULT;
bellard579a97f2007-11-11 14:26:47 +00006737 goto fail;
6738 }
Riku Voipioebc996f2009-04-21 15:01:51 +03006739 ret = get_errno(sys_utimensat(arg1, path(p), tsp, arg4));
bellard579a97f2007-11-11 14:26:47 +00006740 unlock_user(p, arg2, 0);
ths9007f0e2007-09-25 17:50:37 +00006741 }
6742 }
6743 break;
6744#endif
pbrookbd0c5662008-05-29 14:34:11 +00006745#if defined(USE_NPTL)
6746 case TARGET_NR_futex:
6747 ret = do_futex(arg1, arg2, arg3, arg4, arg5, arg6);
6748 break;
6749#endif
aurel32dbfe4c32009-04-08 21:29:30 +00006750#if defined(TARGET_NR_inotify_init) && defined(__NR_inotify_init)
aurel3239b59762008-10-01 21:46:50 +00006751 case TARGET_NR_inotify_init:
6752 ret = get_errno(sys_inotify_init());
6753 break;
6754#endif
aurel32dbfe4c32009-04-08 21:29:30 +00006755#if defined(TARGET_NR_inotify_add_watch) && defined(__NR_inotify_add_watch)
aurel3239b59762008-10-01 21:46:50 +00006756 case TARGET_NR_inotify_add_watch:
6757 p = lock_user_string(arg2);
6758 ret = get_errno(sys_inotify_add_watch(arg1, path(p), arg3));
6759 unlock_user(p, arg2, 0);
6760 break;
6761#endif
aurel32dbfe4c32009-04-08 21:29:30 +00006762#if defined(TARGET_NR_inotify_rm_watch) && defined(__NR_inotify_rm_watch)
aurel3239b59762008-10-01 21:46:50 +00006763 case TARGET_NR_inotify_rm_watch:
6764 ret = get_errno(sys_inotify_rm_watch(arg1, arg2));
6765 break;
6766#endif
ths9007f0e2007-09-25 17:50:37 +00006767
aurel3224e10032009-04-15 16:11:43 +00006768#ifdef TARGET_NR_mq_open
6769 case TARGET_NR_mq_open:
6770 {
6771 struct mq_attr posix_mq_attr;
6772
6773 p = lock_user_string(arg1 - 1);
6774 if (arg4 != 0)
6775 copy_from_user_mq_attr (&posix_mq_attr, arg4);
6776 ret = get_errno(mq_open(p, arg2, arg3, &posix_mq_attr));
6777 unlock_user (p, arg1, 0);
6778 }
6779 break;
6780
6781 case TARGET_NR_mq_unlink:
6782 p = lock_user_string(arg1 - 1);
6783 ret = get_errno(mq_unlink(p));
6784 unlock_user (p, arg1, 0);
6785 break;
6786
6787 case TARGET_NR_mq_timedsend:
6788 {
6789 struct timespec ts;
6790
6791 p = lock_user (VERIFY_READ, arg2, arg3, 1);
6792 if (arg5 != 0) {
6793 target_to_host_timespec(&ts, arg5);
6794 ret = get_errno(mq_timedsend(arg1, p, arg3, arg4, &ts));
6795 host_to_target_timespec(arg5, &ts);
6796 }
6797 else
6798 ret = get_errno(mq_send(arg1, p, arg3, arg4));
6799 unlock_user (p, arg2, arg3);
6800 }
6801 break;
6802
6803 case TARGET_NR_mq_timedreceive:
6804 {
6805 struct timespec ts;
6806 unsigned int prio;
6807
6808 p = lock_user (VERIFY_READ, arg2, arg3, 1);
6809 if (arg5 != 0) {
6810 target_to_host_timespec(&ts, arg5);
6811 ret = get_errno(mq_timedreceive(arg1, p, arg3, &prio, &ts));
6812 host_to_target_timespec(arg5, &ts);
6813 }
6814 else
6815 ret = get_errno(mq_receive(arg1, p, arg3, &prio));
6816 unlock_user (p, arg2, arg3);
6817 if (arg4 != 0)
6818 put_user_u32(prio, arg4);
6819 }
6820 break;
6821
6822 /* Not implemented for now... */
6823/* case TARGET_NR_mq_notify: */
6824/* break; */
6825
6826 case TARGET_NR_mq_getsetattr:
6827 {
6828 struct mq_attr posix_mq_attr_in, posix_mq_attr_out;
6829 ret = 0;
6830 if (arg3 != 0) {
6831 ret = mq_getattr(arg1, &posix_mq_attr_out);
6832 copy_to_user_mq_attr(arg3, &posix_mq_attr_out);
6833 }
6834 if (arg2 != 0) {
6835 copy_from_user_mq_attr(&posix_mq_attr_in, arg2);
6836 ret |= mq_setattr(arg1, &posix_mq_attr_in, &posix_mq_attr_out);
6837 }
6838
6839 }
6840 break;
6841#endif
6842
bellard31e31b82003-02-18 22:55:36 +00006843 default:
6844 unimplemented:
bellard5cd43932003-03-29 16:54:36 +00006845 gemu_log("qemu: Unsupported syscall: %d\n", num);
ths4f2b1fe2007-06-21 21:57:12 +00006846#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 +00006847 unimplemented_nowarn:
bellard80a9d032005-01-03 23:31:27 +00006848#endif
ths0da46a62007-10-20 20:23:07 +00006849 ret = -TARGET_ENOSYS;
bellard31e31b82003-02-18 22:55:36 +00006850 break;
6851 }
bellard579a97f2007-11-11 14:26:47 +00006852fail:
bellardc573ff62004-01-04 15:51:36 +00006853#ifdef DEBUG
6854 gemu_log(" = %ld\n", ret);
6855#endif
thsb92c47c2007-11-01 00:07:38 +00006856 if(do_strace)
6857 print_syscall_ret(num, ret);
bellard31e31b82003-02-18 22:55:36 +00006858 return ret;
bellard579a97f2007-11-11 14:26:47 +00006859efault:
6860 ret = -TARGET_EFAULT;
6861 goto fail;
bellard31e31b82003-02-18 22:55:36 +00006862}