blob: 36eb9f5b5317eae2e0cd980a64d29d259baf7690 [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
Riku Voipio099d6b02009-05-05 12:10:04 +0300947static abi_long do_pipe2(int host_pipe[], int flags)
948{
949#ifdef CONFIG_PIPE2
950 return pipe2(host_pipe, flags);
951#else
952 return -ENOSYS;
953#endif
954}
955
956static abi_long do_pipe(void *cpu_env, int pipedes, int flags)
957{
958 int host_pipe[2];
959 abi_long ret;
960 ret = flags ? do_pipe2(host_pipe, flags) : pipe(host_pipe);
961
962 if (is_error(ret))
963 return get_errno(ret);
964#if defined(TARGET_MIPS)
965 ((CPUMIPSState*)cpu_env)->active_tc.gpr[3] = host_pipe[1];
966 ret = host_pipe[0];
967#elif defined(TARGET_SH4)
968 ((CPUSH4State*)cpu_env)->gregs[1] = host_pipe[1];
969 ret = host_pipe[0];
970#else
971 if (put_user_s32(host_pipe[0], pipedes)
972 || put_user_s32(host_pipe[1], pipedes + sizeof(host_pipe[0])))
973 return -TARGET_EFAULT;
974#endif
975 return get_errno(ret);
976}
977
Lionel Landwerlinb975b832009-04-25 23:30:19 +0200978static inline abi_long target_to_host_ip_mreq(struct ip_mreqn *mreqn,
979 abi_ulong target_addr,
980 socklen_t len)
981{
982 struct target_ip_mreqn *target_smreqn;
983
984 target_smreqn = lock_user(VERIFY_READ, target_addr, len, 1);
985 if (!target_smreqn)
986 return -TARGET_EFAULT;
987 mreqn->imr_multiaddr.s_addr = target_smreqn->imr_multiaddr.s_addr;
988 mreqn->imr_address.s_addr = target_smreqn->imr_address.s_addr;
989 if (len == sizeof(struct target_ip_mreqn))
990 mreqn->imr_ifindex = tswapl(target_smreqn->imr_ifindex);
991 unlock_user(target_smreqn, target_addr, 0);
992
993 return 0;
994}
995
bellard579a97f2007-11-11 14:26:47 +0000996static inline abi_long target_to_host_sockaddr(struct sockaddr *addr,
997 abi_ulong target_addr,
998 socklen_t len)
bellard7854b052003-03-29 17:22:23 +0000999{
aurel32607175e2009-04-15 16:11:59 +00001000 const socklen_t unix_maxlen = sizeof (struct sockaddr_un);
1001 sa_family_t sa_family;
pbrook53a59602006-03-25 19:31:22 +00001002 struct target_sockaddr *target_saddr;
1003
bellard579a97f2007-11-11 14:26:47 +00001004 target_saddr = lock_user(VERIFY_READ, target_addr, len, 1);
1005 if (!target_saddr)
1006 return -TARGET_EFAULT;
aurel32607175e2009-04-15 16:11:59 +00001007
1008 sa_family = tswap16(target_saddr->sa_family);
1009
1010 /* Oops. The caller might send a incomplete sun_path; sun_path
1011 * must be terminated by \0 (see the manual page), but
1012 * unfortunately it is quite common to specify sockaddr_un
1013 * length as "strlen(x->sun_path)" while it should be
1014 * "strlen(...) + 1". We'll fix that here if needed.
1015 * Linux kernel has a similar feature.
1016 */
1017
1018 if (sa_family == AF_UNIX) {
1019 if (len < unix_maxlen && len > 0) {
1020 char *cp = (char*)target_saddr;
1021
1022 if ( cp[len-1] && !cp[len] )
1023 len++;
1024 }
1025 if (len > unix_maxlen)
1026 len = unix_maxlen;
1027 }
1028
pbrook53a59602006-03-25 19:31:22 +00001029 memcpy(addr, target_saddr, len);
aurel32607175e2009-04-15 16:11:59 +00001030 addr->sa_family = sa_family;
pbrook53a59602006-03-25 19:31:22 +00001031 unlock_user(target_saddr, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00001032
1033 return 0;
bellard7854b052003-03-29 17:22:23 +00001034}
1035
bellard579a97f2007-11-11 14:26:47 +00001036static inline abi_long host_to_target_sockaddr(abi_ulong target_addr,
1037 struct sockaddr *addr,
1038 socklen_t len)
bellard7854b052003-03-29 17:22:23 +00001039{
pbrook53a59602006-03-25 19:31:22 +00001040 struct target_sockaddr *target_saddr;
1041
bellard579a97f2007-11-11 14:26:47 +00001042 target_saddr = lock_user(VERIFY_WRITE, target_addr, len, 0);
1043 if (!target_saddr)
1044 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00001045 memcpy(target_saddr, addr, len);
1046 target_saddr->sa_family = tswap16(addr->sa_family);
1047 unlock_user(target_saddr, target_addr, len);
bellard579a97f2007-11-11 14:26:47 +00001048
1049 return 0;
bellard7854b052003-03-29 17:22:23 +00001050}
1051
pbrook53a59602006-03-25 19:31:22 +00001052/* ??? Should this also swap msgh->name? */
bellard5a4a8982007-11-11 17:39:18 +00001053static inline abi_long target_to_host_cmsg(struct msghdr *msgh,
1054 struct target_msghdr *target_msgh)
bellard7854b052003-03-29 17:22:23 +00001055{
1056 struct cmsghdr *cmsg = CMSG_FIRSTHDR(msgh);
bellard5a4a8982007-11-11 17:39:18 +00001057 abi_long msg_controllen;
1058 abi_ulong target_cmsg_addr;
1059 struct target_cmsghdr *target_cmsg;
bellard7854b052003-03-29 17:22:23 +00001060 socklen_t space = 0;
bellard5a4a8982007-11-11 17:39:18 +00001061
1062 msg_controllen = tswapl(target_msgh->msg_controllen);
1063 if (msg_controllen < sizeof (struct target_cmsghdr))
1064 goto the_end;
1065 target_cmsg_addr = tswapl(target_msgh->msg_control);
1066 target_cmsg = lock_user(VERIFY_READ, target_cmsg_addr, msg_controllen, 1);
1067 if (!target_cmsg)
1068 return -TARGET_EFAULT;
bellard7854b052003-03-29 17:22:23 +00001069
1070 while (cmsg && target_cmsg) {
1071 void *data = CMSG_DATA(cmsg);
1072 void *target_data = TARGET_CMSG_DATA(target_cmsg);
1073
ths5fafdf22007-09-16 21:08:06 +00001074 int len = tswapl(target_cmsg->cmsg_len)
bellard7854b052003-03-29 17:22:23 +00001075 - TARGET_CMSG_ALIGN(sizeof (struct target_cmsghdr));
1076
1077 space += CMSG_SPACE(len);
1078 if (space > msgh->msg_controllen) {
1079 space -= CMSG_SPACE(len);
bellard31febb72005-12-18 20:03:27 +00001080 gemu_log("Host cmsg overflow\n");
bellard7854b052003-03-29 17:22:23 +00001081 break;
1082 }
1083
1084 cmsg->cmsg_level = tswap32(target_cmsg->cmsg_level);
1085 cmsg->cmsg_type = tswap32(target_cmsg->cmsg_type);
1086 cmsg->cmsg_len = CMSG_LEN(len);
1087
bellard3532fa72006-06-24 15:06:03 +00001088 if (cmsg->cmsg_level != TARGET_SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS) {
bellard7854b052003-03-29 17:22:23 +00001089 gemu_log("Unsupported ancillary data: %d/%d\n", cmsg->cmsg_level, cmsg->cmsg_type);
1090 memcpy(data, target_data, len);
1091 } else {
1092 int *fd = (int *)data;
1093 int *target_fd = (int *)target_data;
1094 int i, numfds = len / sizeof(int);
1095
1096 for (i = 0; i < numfds; i++)
1097 fd[i] = tswap32(target_fd[i]);
1098 }
1099
1100 cmsg = CMSG_NXTHDR(msgh, cmsg);
1101 target_cmsg = TARGET_CMSG_NXTHDR(target_msgh, target_cmsg);
1102 }
bellard5a4a8982007-11-11 17:39:18 +00001103 unlock_user(target_cmsg, target_cmsg_addr, 0);
1104 the_end:
bellard7854b052003-03-29 17:22:23 +00001105 msgh->msg_controllen = space;
bellard5a4a8982007-11-11 17:39:18 +00001106 return 0;
bellard7854b052003-03-29 17:22:23 +00001107}
1108
pbrook53a59602006-03-25 19:31:22 +00001109/* ??? Should this also swap msgh->name? */
bellard5a4a8982007-11-11 17:39:18 +00001110static inline abi_long host_to_target_cmsg(struct target_msghdr *target_msgh,
1111 struct msghdr *msgh)
bellard7854b052003-03-29 17:22:23 +00001112{
1113 struct cmsghdr *cmsg = CMSG_FIRSTHDR(msgh);
bellard5a4a8982007-11-11 17:39:18 +00001114 abi_long msg_controllen;
1115 abi_ulong target_cmsg_addr;
1116 struct target_cmsghdr *target_cmsg;
bellard7854b052003-03-29 17:22:23 +00001117 socklen_t space = 0;
1118
bellard5a4a8982007-11-11 17:39:18 +00001119 msg_controllen = tswapl(target_msgh->msg_controllen);
1120 if (msg_controllen < sizeof (struct target_cmsghdr))
1121 goto the_end;
1122 target_cmsg_addr = tswapl(target_msgh->msg_control);
1123 target_cmsg = lock_user(VERIFY_WRITE, target_cmsg_addr, msg_controllen, 0);
1124 if (!target_cmsg)
1125 return -TARGET_EFAULT;
1126
bellard7854b052003-03-29 17:22:23 +00001127 while (cmsg && target_cmsg) {
1128 void *data = CMSG_DATA(cmsg);
1129 void *target_data = TARGET_CMSG_DATA(target_cmsg);
1130
1131 int len = cmsg->cmsg_len - CMSG_ALIGN(sizeof (struct cmsghdr));
1132
1133 space += TARGET_CMSG_SPACE(len);
bellard5a4a8982007-11-11 17:39:18 +00001134 if (space > msg_controllen) {
bellard7854b052003-03-29 17:22:23 +00001135 space -= TARGET_CMSG_SPACE(len);
bellard31febb72005-12-18 20:03:27 +00001136 gemu_log("Target cmsg overflow\n");
bellard7854b052003-03-29 17:22:23 +00001137 break;
1138 }
1139
1140 target_cmsg->cmsg_level = tswap32(cmsg->cmsg_level);
1141 target_cmsg->cmsg_type = tswap32(cmsg->cmsg_type);
1142 target_cmsg->cmsg_len = tswapl(TARGET_CMSG_LEN(len));
1143
bellard3532fa72006-06-24 15:06:03 +00001144 if (cmsg->cmsg_level != TARGET_SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS) {
bellard7854b052003-03-29 17:22:23 +00001145 gemu_log("Unsupported ancillary data: %d/%d\n", cmsg->cmsg_level, cmsg->cmsg_type);
1146 memcpy(target_data, data, len);
1147 } else {
1148 int *fd = (int *)data;
1149 int *target_fd = (int *)target_data;
1150 int i, numfds = len / sizeof(int);
1151
1152 for (i = 0; i < numfds; i++)
1153 target_fd[i] = tswap32(fd[i]);
1154 }
1155
1156 cmsg = CMSG_NXTHDR(msgh, cmsg);
1157 target_cmsg = TARGET_CMSG_NXTHDR(target_msgh, target_cmsg);
1158 }
bellard5a4a8982007-11-11 17:39:18 +00001159 unlock_user(target_cmsg, target_cmsg_addr, space);
1160 the_end:
1161 target_msgh->msg_controllen = tswapl(space);
1162 return 0;
bellard7854b052003-03-29 17:22:23 +00001163}
1164
ths0da46a62007-10-20 20:23:07 +00001165/* do_setsockopt() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001166static abi_long do_setsockopt(int sockfd, int level, int optname,
bellard2f619692007-11-16 10:46:05 +00001167 abi_ulong optval_addr, socklen_t optlen)
bellard7854b052003-03-29 17:22:23 +00001168{
blueswir1992f48a2007-10-14 16:27:31 +00001169 abi_long ret;
j_mayer32407102007-09-26 23:01:49 +00001170 int val;
Lionel Landwerlinb975b832009-04-25 23:30:19 +02001171 struct ip_mreqn *ip_mreq;
Lionel Landwerlin6e3cb582009-04-25 23:31:18 +02001172 struct ip_mreq_source *ip_mreq_source;
ths3b46e622007-09-17 08:09:54 +00001173
bellard8853f862004-02-22 14:57:26 +00001174 switch(level) {
1175 case SOL_TCP:
bellard7854b052003-03-29 17:22:23 +00001176 /* TCP options all take an 'int' value. */
bellard7854b052003-03-29 17:22:23 +00001177 if (optlen < sizeof(uint32_t))
ths0da46a62007-10-20 20:23:07 +00001178 return -TARGET_EINVAL;
ths3b46e622007-09-17 08:09:54 +00001179
bellard2f619692007-11-16 10:46:05 +00001180 if (get_user_u32(val, optval_addr))
1181 return -TARGET_EFAULT;
bellard8853f862004-02-22 14:57:26 +00001182 ret = get_errno(setsockopt(sockfd, level, optname, &val, sizeof(val)));
1183 break;
1184 case SOL_IP:
1185 switch(optname) {
bellard2efbe912005-07-23 15:10:20 +00001186 case IP_TOS:
1187 case IP_TTL:
bellard8853f862004-02-22 14:57:26 +00001188 case IP_HDRINCL:
bellard2efbe912005-07-23 15:10:20 +00001189 case IP_ROUTER_ALERT:
1190 case IP_RECVOPTS:
1191 case IP_RETOPTS:
1192 case IP_PKTINFO:
1193 case IP_MTU_DISCOVER:
1194 case IP_RECVERR:
1195 case IP_RECVTOS:
1196#ifdef IP_FREEBIND
1197 case IP_FREEBIND:
1198#endif
1199 case IP_MULTICAST_TTL:
1200 case IP_MULTICAST_LOOP:
bellard8853f862004-02-22 14:57:26 +00001201 val = 0;
1202 if (optlen >= sizeof(uint32_t)) {
bellard2f619692007-11-16 10:46:05 +00001203 if (get_user_u32(val, optval_addr))
1204 return -TARGET_EFAULT;
bellard8853f862004-02-22 14:57:26 +00001205 } else if (optlen >= 1) {
bellard2f619692007-11-16 10:46:05 +00001206 if (get_user_u8(val, optval_addr))
1207 return -TARGET_EFAULT;
bellard8853f862004-02-22 14:57:26 +00001208 }
1209 ret = get_errno(setsockopt(sockfd, level, optname, &val, sizeof(val)));
1210 break;
Lionel Landwerlinb975b832009-04-25 23:30:19 +02001211 case IP_ADD_MEMBERSHIP:
1212 case IP_DROP_MEMBERSHIP:
1213 if (optlen < sizeof (struct target_ip_mreq) ||
1214 optlen > sizeof (struct target_ip_mreqn))
1215 return -TARGET_EINVAL;
1216
1217 ip_mreq = (struct ip_mreqn *) alloca(optlen);
1218 target_to_host_ip_mreq(ip_mreq, optval_addr, optlen);
1219 ret = get_errno(setsockopt(sockfd, level, optname, ip_mreq, optlen));
1220 break;
1221
Lionel Landwerlin6e3cb582009-04-25 23:31:18 +02001222 case IP_BLOCK_SOURCE:
1223 case IP_UNBLOCK_SOURCE:
1224 case IP_ADD_SOURCE_MEMBERSHIP:
1225 case IP_DROP_SOURCE_MEMBERSHIP:
1226 if (optlen != sizeof (struct target_ip_mreq_source))
1227 return -TARGET_EINVAL;
1228
1229 ip_mreq_source = lock_user(VERIFY_READ, optval_addr, optlen, 1);
1230 ret = get_errno(setsockopt(sockfd, level, optname, ip_mreq_source, optlen));
1231 unlock_user (ip_mreq_source, optval_addr, 0);
1232 break;
1233
bellard8853f862004-02-22 14:57:26 +00001234 default:
1235 goto unimplemented;
1236 }
1237 break;
bellard3532fa72006-06-24 15:06:03 +00001238 case TARGET_SOL_SOCKET:
bellard8853f862004-02-22 14:57:26 +00001239 switch (optname) {
1240 /* Options with 'int' argument. */
bellard3532fa72006-06-24 15:06:03 +00001241 case TARGET_SO_DEBUG:
1242 optname = SO_DEBUG;
1243 break;
1244 case TARGET_SO_REUSEADDR:
1245 optname = SO_REUSEADDR;
1246 break;
1247 case TARGET_SO_TYPE:
1248 optname = SO_TYPE;
1249 break;
1250 case TARGET_SO_ERROR:
1251 optname = SO_ERROR;
1252 break;
1253 case TARGET_SO_DONTROUTE:
1254 optname = SO_DONTROUTE;
1255 break;
1256 case TARGET_SO_BROADCAST:
1257 optname = SO_BROADCAST;
1258 break;
1259 case TARGET_SO_SNDBUF:
1260 optname = SO_SNDBUF;
1261 break;
1262 case TARGET_SO_RCVBUF:
1263 optname = SO_RCVBUF;
1264 break;
1265 case TARGET_SO_KEEPALIVE:
1266 optname = SO_KEEPALIVE;
1267 break;
1268 case TARGET_SO_OOBINLINE:
1269 optname = SO_OOBINLINE;
1270 break;
1271 case TARGET_SO_NO_CHECK:
1272 optname = SO_NO_CHECK;
1273 break;
1274 case TARGET_SO_PRIORITY:
1275 optname = SO_PRIORITY;
1276 break;
bellard5e83e8e2005-03-01 22:32:06 +00001277#ifdef SO_BSDCOMPAT
bellard3532fa72006-06-24 15:06:03 +00001278 case TARGET_SO_BSDCOMPAT:
1279 optname = SO_BSDCOMPAT;
1280 break;
bellard5e83e8e2005-03-01 22:32:06 +00001281#endif
bellard3532fa72006-06-24 15:06:03 +00001282 case TARGET_SO_PASSCRED:
1283 optname = SO_PASSCRED;
1284 break;
1285 case TARGET_SO_TIMESTAMP:
1286 optname = SO_TIMESTAMP;
1287 break;
1288 case TARGET_SO_RCVLOWAT:
1289 optname = SO_RCVLOWAT;
1290 break;
1291 case TARGET_SO_RCVTIMEO:
1292 optname = SO_RCVTIMEO;
1293 break;
1294 case TARGET_SO_SNDTIMEO:
1295 optname = SO_SNDTIMEO;
1296 break;
bellard8853f862004-02-22 14:57:26 +00001297 break;
1298 default:
1299 goto unimplemented;
1300 }
bellard3532fa72006-06-24 15:06:03 +00001301 if (optlen < sizeof(uint32_t))
bellard2f619692007-11-16 10:46:05 +00001302 return -TARGET_EINVAL;
bellard3532fa72006-06-24 15:06:03 +00001303
bellard2f619692007-11-16 10:46:05 +00001304 if (get_user_u32(val, optval_addr))
1305 return -TARGET_EFAULT;
bellard3532fa72006-06-24 15:06:03 +00001306 ret = get_errno(setsockopt(sockfd, SOL_SOCKET, optname, &val, sizeof(val)));
bellard8853f862004-02-22 14:57:26 +00001307 break;
bellard7854b052003-03-29 17:22:23 +00001308 default:
bellard8853f862004-02-22 14:57:26 +00001309 unimplemented:
1310 gemu_log("Unsupported setsockopt level=%d optname=%d \n", level, optname);
ths6fa13c12007-12-18 02:41:04 +00001311 ret = -TARGET_ENOPROTOOPT;
bellard7854b052003-03-29 17:22:23 +00001312 }
bellard8853f862004-02-22 14:57:26 +00001313 return ret;
bellard7854b052003-03-29 17:22:23 +00001314}
1315
ths0da46a62007-10-20 20:23:07 +00001316/* do_getsockopt() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001317static abi_long do_getsockopt(int sockfd, int level, int optname,
bellard2f619692007-11-16 10:46:05 +00001318 abi_ulong optval_addr, abi_ulong optlen)
bellard7854b052003-03-29 17:22:23 +00001319{
blueswir1992f48a2007-10-14 16:27:31 +00001320 abi_long ret;
blueswir1b55266b2008-09-20 08:07:15 +00001321 int len, val;
1322 socklen_t lv;
bellard8853f862004-02-22 14:57:26 +00001323
1324 switch(level) {
bellard3532fa72006-06-24 15:06:03 +00001325 case TARGET_SOL_SOCKET:
1326 level = SOL_SOCKET;
bellard8853f862004-02-22 14:57:26 +00001327 switch (optname) {
bellard3532fa72006-06-24 15:06:03 +00001328 case TARGET_SO_LINGER:
1329 case TARGET_SO_RCVTIMEO:
1330 case TARGET_SO_SNDTIMEO:
1331 case TARGET_SO_PEERCRED:
1332 case TARGET_SO_PEERNAME:
bellard8853f862004-02-22 14:57:26 +00001333 /* These don't just return a single integer */
1334 goto unimplemented;
1335 default:
bellard2efbe912005-07-23 15:10:20 +00001336 goto int_case;
1337 }
1338 break;
1339 case SOL_TCP:
1340 /* TCP options all take an 'int' value. */
1341 int_case:
bellard2f619692007-11-16 10:46:05 +00001342 if (get_user_u32(len, optlen))
1343 return -TARGET_EFAULT;
bellard2efbe912005-07-23 15:10:20 +00001344 if (len < 0)
ths0da46a62007-10-20 20:23:07 +00001345 return -TARGET_EINVAL;
bellard2efbe912005-07-23 15:10:20 +00001346 lv = sizeof(int);
1347 ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
1348 if (ret < 0)
1349 return ret;
1350 val = tswap32(val);
1351 if (len > lv)
1352 len = lv;
bellard2f619692007-11-16 10:46:05 +00001353 if (len == 4) {
1354 if (put_user_u32(val, optval_addr))
1355 return -TARGET_EFAULT;
1356 } else {
1357 if (put_user_u8(val, optval_addr))
1358 return -TARGET_EFAULT;
1359 }
1360 if (put_user_u32(len, optlen))
1361 return -TARGET_EFAULT;
bellard2efbe912005-07-23 15:10:20 +00001362 break;
1363 case SOL_IP:
1364 switch(optname) {
1365 case IP_TOS:
1366 case IP_TTL:
1367 case IP_HDRINCL:
1368 case IP_ROUTER_ALERT:
1369 case IP_RECVOPTS:
1370 case IP_RETOPTS:
1371 case IP_PKTINFO:
1372 case IP_MTU_DISCOVER:
1373 case IP_RECVERR:
1374 case IP_RECVTOS:
1375#ifdef IP_FREEBIND
1376 case IP_FREEBIND:
1377#endif
1378 case IP_MULTICAST_TTL:
1379 case IP_MULTICAST_LOOP:
bellard2f619692007-11-16 10:46:05 +00001380 if (get_user_u32(len, optlen))
1381 return -TARGET_EFAULT;
bellard8853f862004-02-22 14:57:26 +00001382 if (len < 0)
ths0da46a62007-10-20 20:23:07 +00001383 return -TARGET_EINVAL;
bellard8853f862004-02-22 14:57:26 +00001384 lv = sizeof(int);
1385 ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
1386 if (ret < 0)
1387 return ret;
bellard2efbe912005-07-23 15:10:20 +00001388 if (len < sizeof(int) && len > 0 && val >= 0 && val < 255) {
bellard2efbe912005-07-23 15:10:20 +00001389 len = 1;
bellard2f619692007-11-16 10:46:05 +00001390 if (put_user_u32(len, optlen)
1391 || put_user_u8(val, optval_addr))
1392 return -TARGET_EFAULT;
bellard2efbe912005-07-23 15:10:20 +00001393 } else {
bellard2efbe912005-07-23 15:10:20 +00001394 if (len > sizeof(int))
1395 len = sizeof(int);
bellard2f619692007-11-16 10:46:05 +00001396 if (put_user_u32(len, optlen)
1397 || put_user_u32(val, optval_addr))
1398 return -TARGET_EFAULT;
bellard2efbe912005-07-23 15:10:20 +00001399 }
bellard8853f862004-02-22 14:57:26 +00001400 break;
bellard2efbe912005-07-23 15:10:20 +00001401 default:
thsc02f4992007-12-18 02:39:59 +00001402 ret = -TARGET_ENOPROTOOPT;
1403 break;
bellard8853f862004-02-22 14:57:26 +00001404 }
1405 break;
1406 default:
1407 unimplemented:
1408 gemu_log("getsockopt level=%d optname=%d not yet supported\n",
1409 level, optname);
thsc02f4992007-12-18 02:39:59 +00001410 ret = -TARGET_EOPNOTSUPP;
bellard8853f862004-02-22 14:57:26 +00001411 break;
1412 }
1413 return ret;
bellard7854b052003-03-29 17:22:23 +00001414}
1415
bellard579a97f2007-11-11 14:26:47 +00001416/* FIXME
1417 * lock_iovec()/unlock_iovec() have a return code of 0 for success where
1418 * other lock functions have a return code of 0 for failure.
1419 */
1420static abi_long lock_iovec(int type, struct iovec *vec, abi_ulong target_addr,
1421 int count, int copy)
pbrook53a59602006-03-25 19:31:22 +00001422{
1423 struct target_iovec *target_vec;
blueswir1992f48a2007-10-14 16:27:31 +00001424 abi_ulong base;
balrogd732dcb2008-10-28 10:21:03 +00001425 int i;
pbrook53a59602006-03-25 19:31:22 +00001426
bellard579a97f2007-11-11 14:26:47 +00001427 target_vec = lock_user(VERIFY_READ, target_addr, count * sizeof(struct target_iovec), 1);
1428 if (!target_vec)
1429 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00001430 for(i = 0;i < count; i++) {
1431 base = tswapl(target_vec[i].iov_base);
1432 vec[i].iov_len = tswapl(target_vec[i].iov_len);
bellard41df8412008-02-04 22:26:57 +00001433 if (vec[i].iov_len != 0) {
1434 vec[i].iov_base = lock_user(type, base, vec[i].iov_len, copy);
balrogd732dcb2008-10-28 10:21:03 +00001435 /* Don't check lock_user return value. We must call writev even
1436 if a element has invalid base address. */
bellard41df8412008-02-04 22:26:57 +00001437 } else {
1438 /* zero length pointer is ignored */
1439 vec[i].iov_base = NULL;
1440 }
pbrook53a59602006-03-25 19:31:22 +00001441 }
1442 unlock_user (target_vec, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00001443 return 0;
pbrook53a59602006-03-25 19:31:22 +00001444}
1445
bellard579a97f2007-11-11 14:26:47 +00001446static abi_long unlock_iovec(struct iovec *vec, abi_ulong target_addr,
1447 int count, int copy)
pbrook53a59602006-03-25 19:31:22 +00001448{
1449 struct target_iovec *target_vec;
blueswir1992f48a2007-10-14 16:27:31 +00001450 abi_ulong base;
pbrook53a59602006-03-25 19:31:22 +00001451 int i;
1452
bellard579a97f2007-11-11 14:26:47 +00001453 target_vec = lock_user(VERIFY_READ, target_addr, count * sizeof(struct target_iovec), 1);
1454 if (!target_vec)
1455 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00001456 for(i = 0;i < count; i++) {
balrogd732dcb2008-10-28 10:21:03 +00001457 if (target_vec[i].iov_base) {
1458 base = tswapl(target_vec[i].iov_base);
1459 unlock_user(vec[i].iov_base, base, copy ? vec[i].iov_len : 0);
1460 }
pbrook53a59602006-03-25 19:31:22 +00001461 }
1462 unlock_user (target_vec, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00001463
1464 return 0;
pbrook53a59602006-03-25 19:31:22 +00001465}
1466
ths0da46a62007-10-20 20:23:07 +00001467/* do_socket() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001468static abi_long do_socket(int domain, int type, int protocol)
bellard3532fa72006-06-24 15:06:03 +00001469{
1470#if defined(TARGET_MIPS)
1471 switch(type) {
1472 case TARGET_SOCK_DGRAM:
1473 type = SOCK_DGRAM;
1474 break;
1475 case TARGET_SOCK_STREAM:
1476 type = SOCK_STREAM;
1477 break;
1478 case TARGET_SOCK_RAW:
1479 type = SOCK_RAW;
1480 break;
1481 case TARGET_SOCK_RDM:
1482 type = SOCK_RDM;
1483 break;
1484 case TARGET_SOCK_SEQPACKET:
1485 type = SOCK_SEQPACKET;
1486 break;
1487 case TARGET_SOCK_PACKET:
1488 type = SOCK_PACKET;
1489 break;
1490 }
1491#endif
balrog12bc92a2007-10-30 21:06:14 +00001492 if (domain == PF_NETLINK)
1493 return -EAFNOSUPPORT; /* do not NETLINK socket connections possible */
bellard3532fa72006-06-24 15:06:03 +00001494 return get_errno(socket(domain, type, protocol));
1495}
1496
ths0da46a62007-10-20 20:23:07 +00001497/* do_bind() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001498static abi_long do_bind(int sockfd, abi_ulong target_addr,
1499 socklen_t addrlen)
bellard3532fa72006-06-24 15:06:03 +00001500{
aurel328f7aeaf2009-01-30 19:47:57 +00001501 void *addr;
1502
aurel32be09ac42009-04-15 16:12:06 +00001503 if (addrlen < 0)
aurel328f7aeaf2009-01-30 19:47:57 +00001504 return -TARGET_EINVAL;
1505
aurel32607175e2009-04-15 16:11:59 +00001506 addr = alloca(addrlen+1);
ths3b46e622007-09-17 08:09:54 +00001507
bellard3532fa72006-06-24 15:06:03 +00001508 target_to_host_sockaddr(addr, target_addr, addrlen);
1509 return get_errno(bind(sockfd, addr, addrlen));
1510}
1511
ths0da46a62007-10-20 20:23:07 +00001512/* do_connect() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001513static abi_long do_connect(int sockfd, abi_ulong target_addr,
1514 socklen_t addrlen)
bellard3532fa72006-06-24 15:06:03 +00001515{
aurel328f7aeaf2009-01-30 19:47:57 +00001516 void *addr;
1517
aurel32be09ac42009-04-15 16:12:06 +00001518 if (addrlen < 0)
aurel328f7aeaf2009-01-30 19:47:57 +00001519 return -TARGET_EINVAL;
1520
1521 addr = alloca(addrlen);
ths3b46e622007-09-17 08:09:54 +00001522
bellard3532fa72006-06-24 15:06:03 +00001523 target_to_host_sockaddr(addr, target_addr, addrlen);
1524 return get_errno(connect(sockfd, addr, addrlen));
1525}
1526
ths0da46a62007-10-20 20:23:07 +00001527/* do_sendrecvmsg() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001528static abi_long do_sendrecvmsg(int fd, abi_ulong target_msg,
1529 int flags, int send)
bellard3532fa72006-06-24 15:06:03 +00001530{
balrog6de645c2008-10-28 10:26:29 +00001531 abi_long ret, len;
bellard3532fa72006-06-24 15:06:03 +00001532 struct target_msghdr *msgp;
1533 struct msghdr msg;
1534 int count;
1535 struct iovec *vec;
blueswir1992f48a2007-10-14 16:27:31 +00001536 abi_ulong target_vec;
bellard3532fa72006-06-24 15:06:03 +00001537
bellard579a97f2007-11-11 14:26:47 +00001538 /* FIXME */
1539 if (!lock_user_struct(send ? VERIFY_READ : VERIFY_WRITE,
1540 msgp,
1541 target_msg,
1542 send ? 1 : 0))
1543 return -TARGET_EFAULT;
bellard3532fa72006-06-24 15:06:03 +00001544 if (msgp->msg_name) {
1545 msg.msg_namelen = tswap32(msgp->msg_namelen);
1546 msg.msg_name = alloca(msg.msg_namelen);
1547 target_to_host_sockaddr(msg.msg_name, tswapl(msgp->msg_name),
1548 msg.msg_namelen);
1549 } else {
1550 msg.msg_name = NULL;
1551 msg.msg_namelen = 0;
1552 }
1553 msg.msg_controllen = 2 * tswapl(msgp->msg_controllen);
1554 msg.msg_control = alloca(msg.msg_controllen);
1555 msg.msg_flags = tswap32(msgp->msg_flags);
ths3b46e622007-09-17 08:09:54 +00001556
bellard3532fa72006-06-24 15:06:03 +00001557 count = tswapl(msgp->msg_iovlen);
1558 vec = alloca(count * sizeof(struct iovec));
1559 target_vec = tswapl(msgp->msg_iov);
bellard579a97f2007-11-11 14:26:47 +00001560 lock_iovec(send ? VERIFY_READ : VERIFY_WRITE, vec, target_vec, count, send);
bellard3532fa72006-06-24 15:06:03 +00001561 msg.msg_iovlen = count;
1562 msg.msg_iov = vec;
ths3b46e622007-09-17 08:09:54 +00001563
bellard3532fa72006-06-24 15:06:03 +00001564 if (send) {
bellard5a4a8982007-11-11 17:39:18 +00001565 ret = target_to_host_cmsg(&msg, msgp);
1566 if (ret == 0)
1567 ret = get_errno(sendmsg(fd, &msg, flags));
bellard3532fa72006-06-24 15:06:03 +00001568 } else {
1569 ret = get_errno(recvmsg(fd, &msg, flags));
balrog6de645c2008-10-28 10:26:29 +00001570 if (!is_error(ret)) {
1571 len = ret;
bellard5a4a8982007-11-11 17:39:18 +00001572 ret = host_to_target_cmsg(msgp, &msg);
balrog6de645c2008-10-28 10:26:29 +00001573 if (!is_error(ret))
1574 ret = len;
1575 }
bellard3532fa72006-06-24 15:06:03 +00001576 }
1577 unlock_iovec(vec, target_vec, count, !send);
bellard579a97f2007-11-11 14:26:47 +00001578 unlock_user_struct(msgp, target_msg, send ? 0 : 1);
bellard3532fa72006-06-24 15:06:03 +00001579 return ret;
1580}
1581
ths0da46a62007-10-20 20:23:07 +00001582/* do_accept() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001583static abi_long do_accept(int fd, abi_ulong target_addr,
bellard2f619692007-11-16 10:46:05 +00001584 abi_ulong target_addrlen_addr)
pbrook1be9e1d2006-11-19 15:26:04 +00001585{
bellard2f619692007-11-16 10:46:05 +00001586 socklen_t addrlen;
1587 void *addr;
blueswir1992f48a2007-10-14 16:27:31 +00001588 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00001589
bellard2f619692007-11-16 10:46:05 +00001590 if (get_user_u32(addrlen, target_addrlen_addr))
1591 return -TARGET_EFAULT;
1592
aurel32be09ac42009-04-15 16:12:06 +00001593 if (addrlen < 0)
aurel328f7aeaf2009-01-30 19:47:57 +00001594 return -TARGET_EINVAL;
1595
bellard2f619692007-11-16 10:46:05 +00001596 addr = alloca(addrlen);
1597
pbrook1be9e1d2006-11-19 15:26:04 +00001598 ret = get_errno(accept(fd, addr, &addrlen));
1599 if (!is_error(ret)) {
1600 host_to_target_sockaddr(target_addr, addr, addrlen);
bellard2f619692007-11-16 10:46:05 +00001601 if (put_user_u32(addrlen, target_addrlen_addr))
1602 ret = -TARGET_EFAULT;
pbrook1be9e1d2006-11-19 15:26:04 +00001603 }
1604 return ret;
1605}
1606
ths0da46a62007-10-20 20:23:07 +00001607/* do_getpeername() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001608static abi_long do_getpeername(int fd, abi_ulong target_addr,
bellard2f619692007-11-16 10:46:05 +00001609 abi_ulong target_addrlen_addr)
pbrook1be9e1d2006-11-19 15:26:04 +00001610{
bellard2f619692007-11-16 10:46:05 +00001611 socklen_t addrlen;
1612 void *addr;
blueswir1992f48a2007-10-14 16:27:31 +00001613 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00001614
bellard2f619692007-11-16 10:46:05 +00001615 if (get_user_u32(addrlen, target_addrlen_addr))
1616 return -TARGET_EFAULT;
1617
aurel32be09ac42009-04-15 16:12:06 +00001618 if (addrlen < 0)
aurel328f7aeaf2009-01-30 19:47:57 +00001619 return -TARGET_EINVAL;
1620
bellard2f619692007-11-16 10:46:05 +00001621 addr = alloca(addrlen);
1622
pbrook1be9e1d2006-11-19 15:26:04 +00001623 ret = get_errno(getpeername(fd, addr, &addrlen));
1624 if (!is_error(ret)) {
1625 host_to_target_sockaddr(target_addr, addr, addrlen);
bellard2f619692007-11-16 10:46:05 +00001626 if (put_user_u32(addrlen, target_addrlen_addr))
1627 ret = -TARGET_EFAULT;
pbrook1be9e1d2006-11-19 15:26:04 +00001628 }
1629 return ret;
1630}
1631
ths0da46a62007-10-20 20:23:07 +00001632/* do_getsockname() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001633static abi_long do_getsockname(int fd, abi_ulong target_addr,
bellard2f619692007-11-16 10:46:05 +00001634 abi_ulong target_addrlen_addr)
pbrook1be9e1d2006-11-19 15:26:04 +00001635{
bellard2f619692007-11-16 10:46:05 +00001636 socklen_t addrlen;
1637 void *addr;
blueswir1992f48a2007-10-14 16:27:31 +00001638 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00001639
aurel328fea3602009-01-30 19:47:47 +00001640 if (target_addr == 0)
1641 return get_errno(accept(fd, NULL, NULL));
1642
bellard2f619692007-11-16 10:46:05 +00001643 if (get_user_u32(addrlen, target_addrlen_addr))
1644 return -TARGET_EFAULT;
1645
aurel32be09ac42009-04-15 16:12:06 +00001646 if (addrlen < 0)
aurel328f7aeaf2009-01-30 19:47:57 +00001647 return -TARGET_EINVAL;
1648
bellard2f619692007-11-16 10:46:05 +00001649 addr = alloca(addrlen);
1650
pbrook1be9e1d2006-11-19 15:26:04 +00001651 ret = get_errno(getsockname(fd, addr, &addrlen));
1652 if (!is_error(ret)) {
1653 host_to_target_sockaddr(target_addr, addr, addrlen);
bellard2f619692007-11-16 10:46:05 +00001654 if (put_user_u32(addrlen, target_addrlen_addr))
1655 ret = -TARGET_EFAULT;
pbrook1be9e1d2006-11-19 15:26:04 +00001656 }
1657 return ret;
1658}
1659
ths0da46a62007-10-20 20:23:07 +00001660/* do_socketpair() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001661static abi_long do_socketpair(int domain, int type, int protocol,
bellard2f619692007-11-16 10:46:05 +00001662 abi_ulong target_tab_addr)
pbrook1be9e1d2006-11-19 15:26:04 +00001663{
1664 int tab[2];
blueswir1992f48a2007-10-14 16:27:31 +00001665 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00001666
1667 ret = get_errno(socketpair(domain, type, protocol, tab));
1668 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +00001669 if (put_user_s32(tab[0], target_tab_addr)
1670 || put_user_s32(tab[1], target_tab_addr + sizeof(tab[0])))
1671 ret = -TARGET_EFAULT;
pbrook1be9e1d2006-11-19 15:26:04 +00001672 }
1673 return ret;
1674}
1675
ths0da46a62007-10-20 20:23:07 +00001676/* do_sendto() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001677static abi_long do_sendto(int fd, abi_ulong msg, size_t len, int flags,
1678 abi_ulong target_addr, socklen_t addrlen)
pbrook1be9e1d2006-11-19 15:26:04 +00001679{
1680 void *addr;
1681 void *host_msg;
blueswir1992f48a2007-10-14 16:27:31 +00001682 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00001683
aurel32be09ac42009-04-15 16:12:06 +00001684 if (addrlen < 0)
aurel328f7aeaf2009-01-30 19:47:57 +00001685 return -TARGET_EINVAL;
1686
bellard579a97f2007-11-11 14:26:47 +00001687 host_msg = lock_user(VERIFY_READ, msg, len, 1);
1688 if (!host_msg)
1689 return -TARGET_EFAULT;
pbrook1be9e1d2006-11-19 15:26:04 +00001690 if (target_addr) {
1691 addr = alloca(addrlen);
1692 target_to_host_sockaddr(addr, target_addr, addrlen);
1693 ret = get_errno(sendto(fd, host_msg, len, flags, addr, addrlen));
1694 } else {
1695 ret = get_errno(send(fd, host_msg, len, flags));
1696 }
1697 unlock_user(host_msg, msg, 0);
1698 return ret;
1699}
1700
ths0da46a62007-10-20 20:23:07 +00001701/* do_recvfrom() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001702static abi_long do_recvfrom(int fd, abi_ulong msg, size_t len, int flags,
1703 abi_ulong target_addr,
1704 abi_ulong target_addrlen)
pbrook1be9e1d2006-11-19 15:26:04 +00001705{
1706 socklen_t addrlen;
1707 void *addr;
1708 void *host_msg;
blueswir1992f48a2007-10-14 16:27:31 +00001709 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00001710
bellard579a97f2007-11-11 14:26:47 +00001711 host_msg = lock_user(VERIFY_WRITE, msg, len, 0);
1712 if (!host_msg)
1713 return -TARGET_EFAULT;
pbrook1be9e1d2006-11-19 15:26:04 +00001714 if (target_addr) {
bellard2f619692007-11-16 10:46:05 +00001715 if (get_user_u32(addrlen, target_addrlen)) {
1716 ret = -TARGET_EFAULT;
1717 goto fail;
1718 }
aurel32be09ac42009-04-15 16:12:06 +00001719 if (addrlen < 0) {
aurel328f7aeaf2009-01-30 19:47:57 +00001720 ret = -TARGET_EINVAL;
1721 goto fail;
1722 }
pbrook1be9e1d2006-11-19 15:26:04 +00001723 addr = alloca(addrlen);
1724 ret = get_errno(recvfrom(fd, host_msg, len, flags, addr, &addrlen));
1725 } else {
1726 addr = NULL; /* To keep compiler quiet. */
1727 ret = get_errno(recv(fd, host_msg, len, flags));
1728 }
1729 if (!is_error(ret)) {
1730 if (target_addr) {
1731 host_to_target_sockaddr(target_addr, addr, addrlen);
bellard2f619692007-11-16 10:46:05 +00001732 if (put_user_u32(addrlen, target_addrlen)) {
1733 ret = -TARGET_EFAULT;
1734 goto fail;
1735 }
pbrook1be9e1d2006-11-19 15:26:04 +00001736 }
1737 unlock_user(host_msg, msg, len);
1738 } else {
bellard2f619692007-11-16 10:46:05 +00001739fail:
pbrook1be9e1d2006-11-19 15:26:04 +00001740 unlock_user(host_msg, msg, 0);
1741 }
1742 return ret;
1743}
1744
j_mayer32407102007-09-26 23:01:49 +00001745#ifdef TARGET_NR_socketcall
ths0da46a62007-10-20 20:23:07 +00001746/* do_socketcall() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001747static abi_long do_socketcall(int num, abi_ulong vptr)
bellard31e31b82003-02-18 22:55:36 +00001748{
blueswir1992f48a2007-10-14 16:27:31 +00001749 abi_long ret;
1750 const int n = sizeof(abi_ulong);
bellard31e31b82003-02-18 22:55:36 +00001751
1752 switch(num) {
1753 case SOCKOP_socket:
bellard7854b052003-03-29 17:22:23 +00001754 {
bellard2f619692007-11-16 10:46:05 +00001755 int domain, type, protocol;
1756
1757 if (get_user_s32(domain, vptr)
1758 || get_user_s32(type, vptr + n)
1759 || get_user_s32(protocol, vptr + 2 * n))
1760 return -TARGET_EFAULT;
1761
bellard3532fa72006-06-24 15:06:03 +00001762 ret = do_socket(domain, type, protocol);
bellard7854b052003-03-29 17:22:23 +00001763 }
bellard31e31b82003-02-18 22:55:36 +00001764 break;
1765 case SOCKOP_bind:
bellard7854b052003-03-29 17:22:23 +00001766 {
bellard2f619692007-11-16 10:46:05 +00001767 int sockfd;
1768 abi_ulong target_addr;
1769 socklen_t addrlen;
1770
1771 if (get_user_s32(sockfd, vptr)
1772 || get_user_ual(target_addr, vptr + n)
1773 || get_user_u32(addrlen, vptr + 2 * n))
1774 return -TARGET_EFAULT;
1775
bellard3532fa72006-06-24 15:06:03 +00001776 ret = do_bind(sockfd, target_addr, addrlen);
bellard7854b052003-03-29 17:22:23 +00001777 }
bellard31e31b82003-02-18 22:55:36 +00001778 break;
1779 case SOCKOP_connect:
bellard7854b052003-03-29 17:22:23 +00001780 {
bellard2f619692007-11-16 10:46:05 +00001781 int sockfd;
1782 abi_ulong target_addr;
1783 socklen_t addrlen;
1784
1785 if (get_user_s32(sockfd, vptr)
1786 || get_user_ual(target_addr, vptr + n)
1787 || get_user_u32(addrlen, vptr + 2 * n))
1788 return -TARGET_EFAULT;
1789
bellard3532fa72006-06-24 15:06:03 +00001790 ret = do_connect(sockfd, target_addr, addrlen);
bellard7854b052003-03-29 17:22:23 +00001791 }
bellard31e31b82003-02-18 22:55:36 +00001792 break;
1793 case SOCKOP_listen:
bellard7854b052003-03-29 17:22:23 +00001794 {
bellard2f619692007-11-16 10:46:05 +00001795 int sockfd, backlog;
1796
1797 if (get_user_s32(sockfd, vptr)
1798 || get_user_s32(backlog, vptr + n))
1799 return -TARGET_EFAULT;
1800
bellard7854b052003-03-29 17:22:23 +00001801 ret = get_errno(listen(sockfd, backlog));
1802 }
bellard31e31b82003-02-18 22:55:36 +00001803 break;
1804 case SOCKOP_accept:
1805 {
bellard2f619692007-11-16 10:46:05 +00001806 int sockfd;
1807 abi_ulong target_addr, target_addrlen;
1808
1809 if (get_user_s32(sockfd, vptr)
1810 || get_user_ual(target_addr, vptr + n)
1811 || get_user_u32(target_addrlen, vptr + 2 * n))
1812 return -TARGET_EFAULT;
1813
pbrook1be9e1d2006-11-19 15:26:04 +00001814 ret = do_accept(sockfd, target_addr, target_addrlen);
bellard31e31b82003-02-18 22:55:36 +00001815 }
1816 break;
1817 case SOCKOP_getsockname:
1818 {
bellard2f619692007-11-16 10:46:05 +00001819 int sockfd;
1820 abi_ulong target_addr, target_addrlen;
1821
1822 if (get_user_s32(sockfd, vptr)
1823 || get_user_ual(target_addr, vptr + n)
1824 || get_user_u32(target_addrlen, vptr + 2 * n))
1825 return -TARGET_EFAULT;
1826
pbrook1be9e1d2006-11-19 15:26:04 +00001827 ret = do_getsockname(sockfd, target_addr, target_addrlen);
bellard31e31b82003-02-18 22:55:36 +00001828 }
1829 break;
1830 case SOCKOP_getpeername:
1831 {
bellard2f619692007-11-16 10:46:05 +00001832 int sockfd;
1833 abi_ulong target_addr, target_addrlen;
1834
1835 if (get_user_s32(sockfd, vptr)
1836 || get_user_ual(target_addr, vptr + n)
1837 || get_user_u32(target_addrlen, vptr + 2 * n))
1838 return -TARGET_EFAULT;
1839
pbrook1be9e1d2006-11-19 15:26:04 +00001840 ret = do_getpeername(sockfd, target_addr, target_addrlen);
bellard31e31b82003-02-18 22:55:36 +00001841 }
1842 break;
1843 case SOCKOP_socketpair:
1844 {
bellard2f619692007-11-16 10:46:05 +00001845 int domain, type, protocol;
1846 abi_ulong tab;
1847
1848 if (get_user_s32(domain, vptr)
1849 || get_user_s32(type, vptr + n)
1850 || get_user_s32(protocol, vptr + 2 * n)
1851 || get_user_ual(tab, vptr + 3 * n))
1852 return -TARGET_EFAULT;
1853
pbrook1be9e1d2006-11-19 15:26:04 +00001854 ret = do_socketpair(domain, type, protocol, tab);
bellard31e31b82003-02-18 22:55:36 +00001855 }
1856 break;
1857 case SOCKOP_send:
bellard7854b052003-03-29 17:22:23 +00001858 {
bellard2f619692007-11-16 10:46:05 +00001859 int sockfd;
1860 abi_ulong msg;
1861 size_t len;
1862 int flags;
1863
1864 if (get_user_s32(sockfd, vptr)
1865 || get_user_ual(msg, vptr + n)
1866 || get_user_ual(len, vptr + 2 * n)
1867 || get_user_s32(flags, vptr + 3 * n))
1868 return -TARGET_EFAULT;
1869
pbrook1be9e1d2006-11-19 15:26:04 +00001870 ret = do_sendto(sockfd, msg, len, flags, 0, 0);
bellard7854b052003-03-29 17:22:23 +00001871 }
bellard31e31b82003-02-18 22:55:36 +00001872 break;
1873 case SOCKOP_recv:
bellard7854b052003-03-29 17:22:23 +00001874 {
bellard2f619692007-11-16 10:46:05 +00001875 int sockfd;
1876 abi_ulong msg;
1877 size_t len;
1878 int flags;
1879
1880 if (get_user_s32(sockfd, vptr)
1881 || get_user_ual(msg, vptr + n)
1882 || get_user_ual(len, vptr + 2 * n)
1883 || get_user_s32(flags, vptr + 3 * n))
1884 return -TARGET_EFAULT;
1885
pbrook1be9e1d2006-11-19 15:26:04 +00001886 ret = do_recvfrom(sockfd, msg, len, flags, 0, 0);
bellard7854b052003-03-29 17:22:23 +00001887 }
bellard31e31b82003-02-18 22:55:36 +00001888 break;
1889 case SOCKOP_sendto:
bellard7854b052003-03-29 17:22:23 +00001890 {
bellard2f619692007-11-16 10:46:05 +00001891 int sockfd;
1892 abi_ulong msg;
1893 size_t len;
1894 int flags;
1895 abi_ulong addr;
1896 socklen_t addrlen;
1897
1898 if (get_user_s32(sockfd, vptr)
1899 || get_user_ual(msg, vptr + n)
1900 || get_user_ual(len, vptr + 2 * n)
1901 || get_user_s32(flags, vptr + 3 * n)
1902 || get_user_ual(addr, vptr + 4 * n)
1903 || get_user_u32(addrlen, vptr + 5 * n))
1904 return -TARGET_EFAULT;
1905
pbrook1be9e1d2006-11-19 15:26:04 +00001906 ret = do_sendto(sockfd, msg, len, flags, addr, addrlen);
bellard7854b052003-03-29 17:22:23 +00001907 }
bellard31e31b82003-02-18 22:55:36 +00001908 break;
1909 case SOCKOP_recvfrom:
1910 {
bellard2f619692007-11-16 10:46:05 +00001911 int sockfd;
1912 abi_ulong msg;
1913 size_t len;
1914 int flags;
1915 abi_ulong addr;
1916 socklen_t addrlen;
1917
1918 if (get_user_s32(sockfd, vptr)
1919 || get_user_ual(msg, vptr + n)
1920 || get_user_ual(len, vptr + 2 * n)
1921 || get_user_s32(flags, vptr + 3 * n)
1922 || get_user_ual(addr, vptr + 4 * n)
1923 || get_user_u32(addrlen, vptr + 5 * n))
1924 return -TARGET_EFAULT;
1925
pbrook1be9e1d2006-11-19 15:26:04 +00001926 ret = do_recvfrom(sockfd, msg, len, flags, addr, addrlen);
bellard31e31b82003-02-18 22:55:36 +00001927 }
1928 break;
1929 case SOCKOP_shutdown:
bellard7854b052003-03-29 17:22:23 +00001930 {
bellard2f619692007-11-16 10:46:05 +00001931 int sockfd, how;
1932
1933 if (get_user_s32(sockfd, vptr)
1934 || get_user_s32(how, vptr + n))
1935 return -TARGET_EFAULT;
bellard7854b052003-03-29 17:22:23 +00001936
1937 ret = get_errno(shutdown(sockfd, how));
1938 }
bellard31e31b82003-02-18 22:55:36 +00001939 break;
1940 case SOCKOP_sendmsg:
1941 case SOCKOP_recvmsg:
bellard1a9353d2003-03-16 20:28:50 +00001942 {
1943 int fd;
blueswir1992f48a2007-10-14 16:27:31 +00001944 abi_ulong target_msg;
bellard3532fa72006-06-24 15:06:03 +00001945 int flags;
bellard1a9353d2003-03-16 20:28:50 +00001946
bellard2f619692007-11-16 10:46:05 +00001947 if (get_user_s32(fd, vptr)
1948 || get_user_ual(target_msg, vptr + n)
1949 || get_user_s32(flags, vptr + 2 * n))
1950 return -TARGET_EFAULT;
bellard3532fa72006-06-24 15:06:03 +00001951
ths5fafdf22007-09-16 21:08:06 +00001952 ret = do_sendrecvmsg(fd, target_msg, flags,
bellard3532fa72006-06-24 15:06:03 +00001953 (num == SOCKOP_sendmsg));
bellard1a9353d2003-03-16 20:28:50 +00001954 }
1955 break;
bellard31e31b82003-02-18 22:55:36 +00001956 case SOCKOP_setsockopt:
bellard7854b052003-03-29 17:22:23 +00001957 {
bellard2f619692007-11-16 10:46:05 +00001958 int sockfd;
1959 int level;
1960 int optname;
1961 abi_ulong optval;
1962 socklen_t optlen;
1963
1964 if (get_user_s32(sockfd, vptr)
1965 || get_user_s32(level, vptr + n)
1966 || get_user_s32(optname, vptr + 2 * n)
1967 || get_user_ual(optval, vptr + 3 * n)
1968 || get_user_u32(optlen, vptr + 4 * n))
1969 return -TARGET_EFAULT;
bellard7854b052003-03-29 17:22:23 +00001970
1971 ret = do_setsockopt(sockfd, level, optname, optval, optlen);
1972 }
1973 break;
bellard31e31b82003-02-18 22:55:36 +00001974 case SOCKOP_getsockopt:
bellard7854b052003-03-29 17:22:23 +00001975 {
bellard2f619692007-11-16 10:46:05 +00001976 int sockfd;
1977 int level;
1978 int optname;
1979 abi_ulong optval;
1980 socklen_t optlen;
bellard7854b052003-03-29 17:22:23 +00001981
bellard2f619692007-11-16 10:46:05 +00001982 if (get_user_s32(sockfd, vptr)
1983 || get_user_s32(level, vptr + n)
1984 || get_user_s32(optname, vptr + 2 * n)
1985 || get_user_ual(optval, vptr + 3 * n)
1986 || get_user_u32(optlen, vptr + 4 * n))
1987 return -TARGET_EFAULT;
1988
1989 ret = do_getsockopt(sockfd, level, optname, optval, optlen);
bellard7854b052003-03-29 17:22:23 +00001990 }
1991 break;
bellard31e31b82003-02-18 22:55:36 +00001992 default:
1993 gemu_log("Unsupported socketcall: %d\n", num);
ths0da46a62007-10-20 20:23:07 +00001994 ret = -TARGET_ENOSYS;
bellard31e31b82003-02-18 22:55:36 +00001995 break;
1996 }
1997 return ret;
1998}
j_mayer32407102007-09-26 23:01:49 +00001999#endif
bellard31e31b82003-02-18 22:55:36 +00002000
bellard8853f862004-02-22 14:57:26 +00002001#define N_SHM_REGIONS 32
2002
2003static struct shm_region {
bellard5a4a8982007-11-11 17:39:18 +00002004 abi_ulong start;
2005 abi_ulong size;
bellard8853f862004-02-22 14:57:26 +00002006} shm_regions[N_SHM_REGIONS];
2007
ths3eb6b042007-06-03 14:26:27 +00002008struct target_ipc_perm
2009{
blueswir1992f48a2007-10-14 16:27:31 +00002010 abi_long __key;
2011 abi_ulong uid;
2012 abi_ulong gid;
2013 abi_ulong cuid;
2014 abi_ulong cgid;
ths3eb6b042007-06-03 14:26:27 +00002015 unsigned short int mode;
2016 unsigned short int __pad1;
2017 unsigned short int __seq;
2018 unsigned short int __pad2;
blueswir1992f48a2007-10-14 16:27:31 +00002019 abi_ulong __unused1;
2020 abi_ulong __unused2;
ths3eb6b042007-06-03 14:26:27 +00002021};
2022
2023struct target_semid_ds
2024{
2025 struct target_ipc_perm sem_perm;
blueswir1992f48a2007-10-14 16:27:31 +00002026 abi_ulong sem_otime;
2027 abi_ulong __unused1;
2028 abi_ulong sem_ctime;
2029 abi_ulong __unused2;
2030 abi_ulong sem_nsems;
2031 abi_ulong __unused3;
2032 abi_ulong __unused4;
ths3eb6b042007-06-03 14:26:27 +00002033};
2034
bellard579a97f2007-11-11 14:26:47 +00002035static inline abi_long target_to_host_ipc_perm(struct ipc_perm *host_ip,
2036 abi_ulong target_addr)
ths3eb6b042007-06-03 14:26:27 +00002037{
2038 struct target_ipc_perm *target_ip;
2039 struct target_semid_ds *target_sd;
2040
bellard579a97f2007-11-11 14:26:47 +00002041 if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
2042 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00002043 target_ip=&(target_sd->sem_perm);
2044 host_ip->__key = tswapl(target_ip->__key);
2045 host_ip->uid = tswapl(target_ip->uid);
2046 host_ip->gid = tswapl(target_ip->gid);
2047 host_ip->cuid = tswapl(target_ip->cuid);
2048 host_ip->cgid = tswapl(target_ip->cgid);
2049 host_ip->mode = tswapl(target_ip->mode);
2050 unlock_user_struct(target_sd, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00002051 return 0;
ths3eb6b042007-06-03 14:26:27 +00002052}
2053
bellard579a97f2007-11-11 14:26:47 +00002054static inline abi_long host_to_target_ipc_perm(abi_ulong target_addr,
2055 struct ipc_perm *host_ip)
ths3eb6b042007-06-03 14:26:27 +00002056{
2057 struct target_ipc_perm *target_ip;
2058 struct target_semid_ds *target_sd;
2059
bellard579a97f2007-11-11 14:26:47 +00002060 if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
2061 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00002062 target_ip = &(target_sd->sem_perm);
2063 target_ip->__key = tswapl(host_ip->__key);
2064 target_ip->uid = tswapl(host_ip->uid);
2065 target_ip->gid = tswapl(host_ip->gid);
2066 target_ip->cuid = tswapl(host_ip->cuid);
2067 target_ip->cgid = tswapl(host_ip->cgid);
2068 target_ip->mode = tswapl(host_ip->mode);
2069 unlock_user_struct(target_sd, target_addr, 1);
bellard579a97f2007-11-11 14:26:47 +00002070 return 0;
ths3eb6b042007-06-03 14:26:27 +00002071}
2072
bellard579a97f2007-11-11 14:26:47 +00002073static inline abi_long target_to_host_semid_ds(struct semid_ds *host_sd,
2074 abi_ulong target_addr)
ths3eb6b042007-06-03 14:26:27 +00002075{
2076 struct target_semid_ds *target_sd;
2077
bellard579a97f2007-11-11 14:26:47 +00002078 if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
2079 return -TARGET_EFAULT;
aurel32e5289082009-04-18 16:16:12 +00002080 if (target_to_host_ipc_perm(&(host_sd->sem_perm),target_addr))
2081 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00002082 host_sd->sem_nsems = tswapl(target_sd->sem_nsems);
2083 host_sd->sem_otime = tswapl(target_sd->sem_otime);
2084 host_sd->sem_ctime = tswapl(target_sd->sem_ctime);
2085 unlock_user_struct(target_sd, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00002086 return 0;
ths3eb6b042007-06-03 14:26:27 +00002087}
2088
bellard579a97f2007-11-11 14:26:47 +00002089static inline abi_long host_to_target_semid_ds(abi_ulong target_addr,
2090 struct semid_ds *host_sd)
ths3eb6b042007-06-03 14:26:27 +00002091{
2092 struct target_semid_ds *target_sd;
2093
bellard579a97f2007-11-11 14:26:47 +00002094 if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
2095 return -TARGET_EFAULT;
aurel32e5289082009-04-18 16:16:12 +00002096 if (host_to_target_ipc_perm(target_addr,&(host_sd->sem_perm)))
2097 return -TARGET_EFAULT;;
ths3eb6b042007-06-03 14:26:27 +00002098 target_sd->sem_nsems = tswapl(host_sd->sem_nsems);
2099 target_sd->sem_otime = tswapl(host_sd->sem_otime);
2100 target_sd->sem_ctime = tswapl(host_sd->sem_ctime);
2101 unlock_user_struct(target_sd, target_addr, 1);
bellard579a97f2007-11-11 14:26:47 +00002102 return 0;
ths3eb6b042007-06-03 14:26:27 +00002103}
2104
aurel32e5289082009-04-18 16:16:12 +00002105struct target_seminfo {
2106 int semmap;
2107 int semmni;
2108 int semmns;
2109 int semmnu;
2110 int semmsl;
2111 int semopm;
2112 int semume;
2113 int semusz;
2114 int semvmx;
2115 int semaem;
2116};
2117
2118static inline abi_long host_to_target_seminfo(abi_ulong target_addr,
2119 struct seminfo *host_seminfo)
2120{
2121 struct target_seminfo *target_seminfo;
2122 if (!lock_user_struct(VERIFY_WRITE, target_seminfo, target_addr, 0))
2123 return -TARGET_EFAULT;
2124 __put_user(host_seminfo->semmap, &target_seminfo->semmap);
2125 __put_user(host_seminfo->semmni, &target_seminfo->semmni);
2126 __put_user(host_seminfo->semmns, &target_seminfo->semmns);
2127 __put_user(host_seminfo->semmnu, &target_seminfo->semmnu);
2128 __put_user(host_seminfo->semmsl, &target_seminfo->semmsl);
2129 __put_user(host_seminfo->semopm, &target_seminfo->semopm);
2130 __put_user(host_seminfo->semume, &target_seminfo->semume);
2131 __put_user(host_seminfo->semusz, &target_seminfo->semusz);
2132 __put_user(host_seminfo->semvmx, &target_seminfo->semvmx);
2133 __put_user(host_seminfo->semaem, &target_seminfo->semaem);
2134 unlock_user_struct(target_seminfo, target_addr, 1);
2135 return 0;
2136}
2137
thsfa294812007-02-02 22:05:00 +00002138union semun {
2139 int val;
ths3eb6b042007-06-03 14:26:27 +00002140 struct semid_ds *buf;
thsfa294812007-02-02 22:05:00 +00002141 unsigned short *array;
aurel32e5289082009-04-18 16:16:12 +00002142 struct seminfo *__buf;
thsfa294812007-02-02 22:05:00 +00002143};
2144
ths3eb6b042007-06-03 14:26:27 +00002145union target_semun {
2146 int val;
aurel32e5289082009-04-18 16:16:12 +00002147 abi_ulong buf;
2148 abi_ulong array;
2149 abi_ulong __buf;
ths3eb6b042007-06-03 14:26:27 +00002150};
2151
aurel32e5289082009-04-18 16:16:12 +00002152static inline abi_long target_to_host_semarray(int semid, unsigned short **host_array,
2153 abi_ulong target_addr)
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 *host_array = malloc(nsems*sizeof(unsigned short));
2170 array = lock_user(VERIFY_READ, target_addr,
2171 nsems*sizeof(unsigned short), 1);
2172 if (!array)
2173 return -TARGET_EFAULT;
2174
2175 for(i=0; i<nsems; i++) {
2176 __get_user((*host_array)[i], &array[i]);
ths3eb6b042007-06-03 14:26:27 +00002177 }
aurel32e5289082009-04-18 16:16:12 +00002178 unlock_user(array, target_addr, 0);
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 host_to_target_semarray(int semid, abi_ulong target_addr,
2184 unsigned short **host_array)
ths3eb6b042007-06-03 14:26:27 +00002185{
aurel32e5289082009-04-18 16:16:12 +00002186 int nsems;
2187 unsigned short *array;
2188 union semun semun;
2189 struct semid_ds semid_ds;
2190 int i, ret;
ths3eb6b042007-06-03 14:26:27 +00002191
aurel32e5289082009-04-18 16:16:12 +00002192 semun.buf = &semid_ds;
2193
2194 ret = semctl(semid, 0, IPC_STAT, semun);
2195 if (ret == -1)
2196 return get_errno(ret);
2197
2198 nsems = semid_ds.sem_nsems;
2199
2200 array = lock_user(VERIFY_WRITE, target_addr,
2201 nsems*sizeof(unsigned short), 0);
2202 if (!array)
2203 return -TARGET_EFAULT;
2204
2205 for(i=0; i<nsems; i++) {
2206 __put_user((*host_array)[i], &array[i]);
ths3eb6b042007-06-03 14:26:27 +00002207 }
aurel32e5289082009-04-18 16:16:12 +00002208 free(*host_array);
2209 unlock_user(array, target_addr, 1);
2210
bellard579a97f2007-11-11 14:26:47 +00002211 return 0;
ths3eb6b042007-06-03 14:26:27 +00002212}
2213
aurel32e5289082009-04-18 16:16:12 +00002214static inline abi_long do_semctl(int semid, int semnum, int cmd,
2215 union target_semun target_su)
ths3eb6b042007-06-03 14:26:27 +00002216{
2217 union semun arg;
2218 struct semid_ds dsarg;
aurel32e5289082009-04-18 16:16:12 +00002219 unsigned short *array;
2220 struct seminfo seminfo;
2221 abi_long ret = -TARGET_EINVAL;
2222 abi_long err;
2223 cmd &= 0xff;
ths3eb6b042007-06-03 14:26:27 +00002224
2225 switch( cmd ) {
2226 case GETVAL:
ths3eb6b042007-06-03 14:26:27 +00002227 case SETVAL:
aurel32e5289082009-04-18 16:16:12 +00002228 arg.val = tswapl(target_su.val);
2229 ret = get_errno(semctl(semid, semnum, cmd, arg));
2230 target_su.val = tswapl(arg.val);
ths3eb6b042007-06-03 14:26:27 +00002231 break;
2232 case GETALL:
ths3eb6b042007-06-03 14:26:27 +00002233 case SETALL:
aurel32e5289082009-04-18 16:16:12 +00002234 err = target_to_host_semarray(semid, &array, target_su.array);
2235 if (err)
2236 return err;
2237 arg.array = array;
2238 ret = get_errno(semctl(semid, semnum, cmd, arg));
2239 err = host_to_target_semarray(semid, target_su.array, &array);
2240 if (err)
2241 return err;
ths3eb6b042007-06-03 14:26:27 +00002242 break;
2243 case IPC_STAT:
ths3eb6b042007-06-03 14:26:27 +00002244 case IPC_SET:
aurel32e5289082009-04-18 16:16:12 +00002245 case SEM_STAT:
2246 err = target_to_host_semid_ds(&dsarg, target_su.buf);
2247 if (err)
2248 return err;
2249 arg.buf = &dsarg;
2250 ret = get_errno(semctl(semid, semnum, cmd, arg));
2251 err = host_to_target_semid_ds(target_su.buf, &dsarg);
2252 if (err)
2253 return err;
ths3eb6b042007-06-03 14:26:27 +00002254 break;
aurel32e5289082009-04-18 16:16:12 +00002255 case IPC_INFO:
2256 case SEM_INFO:
2257 arg.__buf = &seminfo;
2258 ret = get_errno(semctl(semid, semnum, cmd, arg));
2259 err = host_to_target_seminfo(target_su.__buf, &seminfo);
2260 if (err)
2261 return err;
2262 break;
2263 case IPC_RMID:
2264 case GETPID:
2265 case GETNCNT:
2266 case GETZCNT:
2267 ret = get_errno(semctl(semid, semnum, cmd, NULL));
2268 break;
ths3eb6b042007-06-03 14:26:27 +00002269 }
2270
2271 return ret;
2272}
2273
aurel32e5289082009-04-18 16:16:12 +00002274struct target_sembuf {
2275 unsigned short sem_num;
2276 short sem_op;
2277 short sem_flg;
2278};
2279
2280static inline abi_long target_to_host_sembuf(struct sembuf *host_sembuf,
2281 abi_ulong target_addr,
2282 unsigned nsops)
2283{
2284 struct target_sembuf *target_sembuf;
2285 int i;
2286
2287 target_sembuf = lock_user(VERIFY_READ, target_addr,
2288 nsops*sizeof(struct target_sembuf), 1);
2289 if (!target_sembuf)
2290 return -TARGET_EFAULT;
2291
2292 for(i=0; i<nsops; i++) {
2293 __get_user(host_sembuf[i].sem_num, &target_sembuf[i].sem_num);
2294 __get_user(host_sembuf[i].sem_op, &target_sembuf[i].sem_op);
2295 __get_user(host_sembuf[i].sem_flg, &target_sembuf[i].sem_flg);
2296 }
2297
2298 unlock_user(target_sembuf, target_addr, 0);
2299
2300 return 0;
2301}
2302
2303static inline abi_long do_semop(int semid, abi_long ptr, unsigned nsops)
2304{
2305 struct sembuf sops[nsops];
2306
2307 if (target_to_host_sembuf(sops, ptr, nsops))
2308 return -TARGET_EFAULT;
2309
2310 return semop(semid, sops, nsops);
2311}
2312
ths1bc012f2007-06-03 14:27:49 +00002313struct target_msqid_ds
2314{
aurel321c54ff92008-10-13 21:08:44 +00002315 struct target_ipc_perm msg_perm;
2316 abi_ulong msg_stime;
2317#if TARGET_ABI_BITS == 32
2318 abi_ulong __unused1;
2319#endif
2320 abi_ulong msg_rtime;
2321#if TARGET_ABI_BITS == 32
2322 abi_ulong __unused2;
2323#endif
2324 abi_ulong msg_ctime;
2325#if TARGET_ABI_BITS == 32
2326 abi_ulong __unused3;
2327#endif
2328 abi_ulong __msg_cbytes;
2329 abi_ulong msg_qnum;
2330 abi_ulong msg_qbytes;
2331 abi_ulong msg_lspid;
2332 abi_ulong msg_lrpid;
2333 abi_ulong __unused4;
2334 abi_ulong __unused5;
ths1bc012f2007-06-03 14:27:49 +00002335};
2336
bellard579a97f2007-11-11 14:26:47 +00002337static inline abi_long target_to_host_msqid_ds(struct msqid_ds *host_md,
2338 abi_ulong target_addr)
ths1bc012f2007-06-03 14:27:49 +00002339{
2340 struct target_msqid_ds *target_md;
2341
bellard579a97f2007-11-11 14:26:47 +00002342 if (!lock_user_struct(VERIFY_READ, target_md, target_addr, 1))
2343 return -TARGET_EFAULT;
aurel321c54ff92008-10-13 21:08:44 +00002344 if (target_to_host_ipc_perm(&(host_md->msg_perm),target_addr))
2345 return -TARGET_EFAULT;
ths1bc012f2007-06-03 14:27:49 +00002346 host_md->msg_stime = tswapl(target_md->msg_stime);
2347 host_md->msg_rtime = tswapl(target_md->msg_rtime);
2348 host_md->msg_ctime = tswapl(target_md->msg_ctime);
2349 host_md->__msg_cbytes = tswapl(target_md->__msg_cbytes);
2350 host_md->msg_qnum = tswapl(target_md->msg_qnum);
2351 host_md->msg_qbytes = tswapl(target_md->msg_qbytes);
2352 host_md->msg_lspid = tswapl(target_md->msg_lspid);
2353 host_md->msg_lrpid = tswapl(target_md->msg_lrpid);
2354 unlock_user_struct(target_md, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00002355 return 0;
ths1bc012f2007-06-03 14:27:49 +00002356}
2357
bellard579a97f2007-11-11 14:26:47 +00002358static inline abi_long host_to_target_msqid_ds(abi_ulong target_addr,
2359 struct msqid_ds *host_md)
ths1bc012f2007-06-03 14:27:49 +00002360{
2361 struct target_msqid_ds *target_md;
2362
bellard579a97f2007-11-11 14:26:47 +00002363 if (!lock_user_struct(VERIFY_WRITE, target_md, target_addr, 0))
2364 return -TARGET_EFAULT;
aurel321c54ff92008-10-13 21:08:44 +00002365 if (host_to_target_ipc_perm(target_addr,&(host_md->msg_perm)))
2366 return -TARGET_EFAULT;
ths1bc012f2007-06-03 14:27:49 +00002367 target_md->msg_stime = tswapl(host_md->msg_stime);
2368 target_md->msg_rtime = tswapl(host_md->msg_rtime);
2369 target_md->msg_ctime = tswapl(host_md->msg_ctime);
2370 target_md->__msg_cbytes = tswapl(host_md->__msg_cbytes);
2371 target_md->msg_qnum = tswapl(host_md->msg_qnum);
2372 target_md->msg_qbytes = tswapl(host_md->msg_qbytes);
2373 target_md->msg_lspid = tswapl(host_md->msg_lspid);
2374 target_md->msg_lrpid = tswapl(host_md->msg_lrpid);
2375 unlock_user_struct(target_md, target_addr, 1);
bellard579a97f2007-11-11 14:26:47 +00002376 return 0;
ths1bc012f2007-06-03 14:27:49 +00002377}
2378
aurel321c54ff92008-10-13 21:08:44 +00002379struct target_msginfo {
2380 int msgpool;
2381 int msgmap;
2382 int msgmax;
2383 int msgmnb;
2384 int msgmni;
2385 int msgssz;
2386 int msgtql;
2387 unsigned short int msgseg;
2388};
2389
2390static inline abi_long host_to_target_msginfo(abi_ulong target_addr,
2391 struct msginfo *host_msginfo)
2392{
2393 struct target_msginfo *target_msginfo;
2394 if (!lock_user_struct(VERIFY_WRITE, target_msginfo, target_addr, 0))
2395 return -TARGET_EFAULT;
2396 __put_user(host_msginfo->msgpool, &target_msginfo->msgpool);
2397 __put_user(host_msginfo->msgmap, &target_msginfo->msgmap);
2398 __put_user(host_msginfo->msgmax, &target_msginfo->msgmax);
2399 __put_user(host_msginfo->msgmnb, &target_msginfo->msgmnb);
2400 __put_user(host_msginfo->msgmni, &target_msginfo->msgmni);
2401 __put_user(host_msginfo->msgssz, &target_msginfo->msgssz);
2402 __put_user(host_msginfo->msgtql, &target_msginfo->msgtql);
2403 __put_user(host_msginfo->msgseg, &target_msginfo->msgseg);
2404 unlock_user_struct(target_msginfo, target_addr, 1);
aurel3200b229a2008-10-24 13:12:52 +00002405 return 0;
aurel321c54ff92008-10-13 21:08:44 +00002406}
2407
2408static inline abi_long do_msgctl(int msgid, int cmd, abi_long ptr)
ths1bc012f2007-06-03 14:27:49 +00002409{
2410 struct msqid_ds dsarg;
aurel321c54ff92008-10-13 21:08:44 +00002411 struct msginfo msginfo;
2412 abi_long ret = -TARGET_EINVAL;
2413
2414 cmd &= 0xff;
2415
2416 switch (cmd) {
ths1bc012f2007-06-03 14:27:49 +00002417 case IPC_STAT:
2418 case IPC_SET:
aurel321c54ff92008-10-13 21:08:44 +00002419 case MSG_STAT:
2420 if (target_to_host_msqid_ds(&dsarg,ptr))
2421 return -TARGET_EFAULT;
2422 ret = get_errno(msgctl(msgid, cmd, &dsarg));
2423 if (host_to_target_msqid_ds(ptr,&dsarg))
2424 return -TARGET_EFAULT;
2425 break;
2426 case IPC_RMID:
2427 ret = get_errno(msgctl(msgid, cmd, NULL));
2428 break;
2429 case IPC_INFO:
2430 case MSG_INFO:
2431 ret = get_errno(msgctl(msgid, cmd, (struct msqid_ds *)&msginfo));
2432 if (host_to_target_msginfo(ptr, &msginfo))
2433 return -TARGET_EFAULT;
2434 break;
ths1bc012f2007-06-03 14:27:49 +00002435 }
aurel321c54ff92008-10-13 21:08:44 +00002436
ths1bc012f2007-06-03 14:27:49 +00002437 return ret;
2438}
2439
2440struct target_msgbuf {
aurel321c54ff92008-10-13 21:08:44 +00002441 abi_long mtype;
2442 char mtext[1];
ths1bc012f2007-06-03 14:27:49 +00002443};
2444
blueswir1992f48a2007-10-14 16:27:31 +00002445static inline abi_long do_msgsnd(int msqid, abi_long msgp,
2446 unsigned int msgsz, int msgflg)
ths1bc012f2007-06-03 14:27:49 +00002447{
2448 struct target_msgbuf *target_mb;
2449 struct msgbuf *host_mb;
blueswir1992f48a2007-10-14 16:27:31 +00002450 abi_long ret = 0;
ths1bc012f2007-06-03 14:27:49 +00002451
bellard579a97f2007-11-11 14:26:47 +00002452 if (!lock_user_struct(VERIFY_READ, target_mb, msgp, 0))
2453 return -TARGET_EFAULT;
ths1bc012f2007-06-03 14:27:49 +00002454 host_mb = malloc(msgsz+sizeof(long));
aurel321c54ff92008-10-13 21:08:44 +00002455 host_mb->mtype = (abi_long) tswapl(target_mb->mtype);
2456 memcpy(host_mb->mtext, target_mb->mtext, msgsz);
ths1bc012f2007-06-03 14:27:49 +00002457 ret = get_errno(msgsnd(msqid, host_mb, msgsz, msgflg));
2458 free(host_mb);
2459 unlock_user_struct(target_mb, msgp, 0);
2460
2461 return ret;
2462}
2463
blueswir1992f48a2007-10-14 16:27:31 +00002464static inline abi_long do_msgrcv(int msqid, abi_long msgp,
aurel321c54ff92008-10-13 21:08:44 +00002465 unsigned int msgsz, abi_long msgtyp,
blueswir1992f48a2007-10-14 16:27:31 +00002466 int msgflg)
ths1bc012f2007-06-03 14:27:49 +00002467{
2468 struct target_msgbuf *target_mb;
bellard579a97f2007-11-11 14:26:47 +00002469 char *target_mtext;
ths1bc012f2007-06-03 14:27:49 +00002470 struct msgbuf *host_mb;
blueswir1992f48a2007-10-14 16:27:31 +00002471 abi_long ret = 0;
ths1bc012f2007-06-03 14:27:49 +00002472
bellard579a97f2007-11-11 14:26:47 +00002473 if (!lock_user_struct(VERIFY_WRITE, target_mb, msgp, 0))
2474 return -TARGET_EFAULT;
aurel321c54ff92008-10-13 21:08:44 +00002475
ths1bc012f2007-06-03 14:27:49 +00002476 host_mb = malloc(msgsz+sizeof(long));
aurel321c54ff92008-10-13 21:08:44 +00002477 ret = get_errno(msgrcv(msqid, host_mb, msgsz, tswapl(msgtyp), msgflg));
2478
bellard579a97f2007-11-11 14:26:47 +00002479 if (ret > 0) {
2480 abi_ulong target_mtext_addr = msgp + sizeof(abi_ulong);
2481 target_mtext = lock_user(VERIFY_WRITE, target_mtext_addr, ret, 0);
2482 if (!target_mtext) {
2483 ret = -TARGET_EFAULT;
2484 goto end;
2485 }
aurel321c54ff92008-10-13 21:08:44 +00002486 memcpy(target_mb->mtext, host_mb->mtext, ret);
bellard579a97f2007-11-11 14:26:47 +00002487 unlock_user(target_mtext, target_mtext_addr, ret);
2488 }
aurel321c54ff92008-10-13 21:08:44 +00002489
ths1bc012f2007-06-03 14:27:49 +00002490 target_mb->mtype = tswapl(host_mb->mtype);
2491 free(host_mb);
ths1bc012f2007-06-03 14:27:49 +00002492
bellard579a97f2007-11-11 14:26:47 +00002493end:
2494 if (target_mb)
2495 unlock_user_struct(target_mb, msgp, 1);
ths1bc012f2007-06-03 14:27:49 +00002496 return ret;
2497}
2498
Riku Voipio88a8c982009-04-03 10:42:00 +03002499struct target_shmid_ds
2500{
2501 struct target_ipc_perm shm_perm;
2502 abi_ulong shm_segsz;
2503 abi_ulong shm_atime;
2504#if TARGET_ABI_BITS == 32
2505 abi_ulong __unused1;
2506#endif
2507 abi_ulong shm_dtime;
2508#if TARGET_ABI_BITS == 32
2509 abi_ulong __unused2;
2510#endif
2511 abi_ulong shm_ctime;
2512#if TARGET_ABI_BITS == 32
2513 abi_ulong __unused3;
2514#endif
2515 int shm_cpid;
2516 int shm_lpid;
2517 abi_ulong shm_nattch;
2518 unsigned long int __unused4;
2519 unsigned long int __unused5;
2520};
2521
2522static inline abi_long target_to_host_shmid_ds(struct shmid_ds *host_sd,
2523 abi_ulong target_addr)
2524{
2525 struct target_shmid_ds *target_sd;
2526
2527 if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
2528 return -TARGET_EFAULT;
2529 if (target_to_host_ipc_perm(&(host_sd->shm_perm), target_addr))
2530 return -TARGET_EFAULT;
2531 __get_user(host_sd->shm_segsz, &target_sd->shm_segsz);
2532 __get_user(host_sd->shm_atime, &target_sd->shm_atime);
2533 __get_user(host_sd->shm_dtime, &target_sd->shm_dtime);
2534 __get_user(host_sd->shm_ctime, &target_sd->shm_ctime);
2535 __get_user(host_sd->shm_cpid, &target_sd->shm_cpid);
2536 __get_user(host_sd->shm_lpid, &target_sd->shm_lpid);
2537 __get_user(host_sd->shm_nattch, &target_sd->shm_nattch);
2538 unlock_user_struct(target_sd, target_addr, 0);
2539 return 0;
2540}
2541
2542static inline abi_long host_to_target_shmid_ds(abi_ulong target_addr,
2543 struct shmid_ds *host_sd)
2544{
2545 struct target_shmid_ds *target_sd;
2546
2547 if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
2548 return -TARGET_EFAULT;
2549 if (host_to_target_ipc_perm(target_addr, &(host_sd->shm_perm)))
2550 return -TARGET_EFAULT;
2551 __put_user(host_sd->shm_segsz, &target_sd->shm_segsz);
2552 __put_user(host_sd->shm_atime, &target_sd->shm_atime);
2553 __put_user(host_sd->shm_dtime, &target_sd->shm_dtime);
2554 __put_user(host_sd->shm_ctime, &target_sd->shm_ctime);
2555 __put_user(host_sd->shm_cpid, &target_sd->shm_cpid);
2556 __put_user(host_sd->shm_lpid, &target_sd->shm_lpid);
2557 __put_user(host_sd->shm_nattch, &target_sd->shm_nattch);
2558 unlock_user_struct(target_sd, target_addr, 1);
2559 return 0;
2560}
2561
2562struct target_shminfo {
2563 abi_ulong shmmax;
2564 abi_ulong shmmin;
2565 abi_ulong shmmni;
2566 abi_ulong shmseg;
2567 abi_ulong shmall;
2568};
2569
2570static inline abi_long host_to_target_shminfo(abi_ulong target_addr,
2571 struct shminfo *host_shminfo)
2572{
2573 struct target_shminfo *target_shminfo;
2574 if (!lock_user_struct(VERIFY_WRITE, target_shminfo, target_addr, 0))
2575 return -TARGET_EFAULT;
2576 __put_user(host_shminfo->shmmax, &target_shminfo->shmmax);
2577 __put_user(host_shminfo->shmmin, &target_shminfo->shmmin);
2578 __put_user(host_shminfo->shmmni, &target_shminfo->shmmni);
2579 __put_user(host_shminfo->shmseg, &target_shminfo->shmseg);
2580 __put_user(host_shminfo->shmall, &target_shminfo->shmall);
2581 unlock_user_struct(target_shminfo, target_addr, 1);
2582 return 0;
2583}
2584
2585struct target_shm_info {
2586 int used_ids;
2587 abi_ulong shm_tot;
2588 abi_ulong shm_rss;
2589 abi_ulong shm_swp;
2590 abi_ulong swap_attempts;
2591 abi_ulong swap_successes;
2592};
2593
2594static inline abi_long host_to_target_shm_info(abi_ulong target_addr,
2595 struct shm_info *host_shm_info)
2596{
2597 struct target_shm_info *target_shm_info;
2598 if (!lock_user_struct(VERIFY_WRITE, target_shm_info, target_addr, 0))
2599 return -TARGET_EFAULT;
2600 __put_user(host_shm_info->used_ids, &target_shm_info->used_ids);
2601 __put_user(host_shm_info->shm_tot, &target_shm_info->shm_tot);
2602 __put_user(host_shm_info->shm_rss, &target_shm_info->shm_rss);
2603 __put_user(host_shm_info->shm_swp, &target_shm_info->shm_swp);
2604 __put_user(host_shm_info->swap_attempts, &target_shm_info->swap_attempts);
2605 __put_user(host_shm_info->swap_successes, &target_shm_info->swap_successes);
2606 unlock_user_struct(target_shm_info, target_addr, 1);
2607 return 0;
2608}
2609
2610static inline abi_long do_shmctl(int shmid, int cmd, abi_long buf)
2611{
2612 struct shmid_ds dsarg;
2613 struct shminfo shminfo;
2614 struct shm_info shm_info;
2615 abi_long ret = -TARGET_EINVAL;
2616
2617 cmd &= 0xff;
2618
2619 switch(cmd) {
2620 case IPC_STAT:
2621 case IPC_SET:
2622 case SHM_STAT:
2623 if (target_to_host_shmid_ds(&dsarg, buf))
2624 return -TARGET_EFAULT;
2625 ret = get_errno(shmctl(shmid, cmd, &dsarg));
2626 if (host_to_target_shmid_ds(buf, &dsarg))
2627 return -TARGET_EFAULT;
2628 break;
2629 case IPC_INFO:
2630 ret = get_errno(shmctl(shmid, cmd, (struct shmid_ds *)&shminfo));
2631 if (host_to_target_shminfo(buf, &shminfo))
2632 return -TARGET_EFAULT;
2633 break;
2634 case SHM_INFO:
2635 ret = get_errno(shmctl(shmid, cmd, (struct shmid_ds *)&shm_info));
2636 if (host_to_target_shm_info(buf, &shm_info))
2637 return -TARGET_EFAULT;
2638 break;
2639 case IPC_RMID:
2640 case SHM_LOCK:
2641 case SHM_UNLOCK:
2642 ret = get_errno(shmctl(shmid, cmd, NULL));
2643 break;
2644 }
2645
2646 return ret;
2647}
2648
2649static inline abi_ulong do_shmat(int shmid, abi_ulong shmaddr, int shmflg)
2650{
2651 abi_long raddr;
2652 void *host_raddr;
2653 struct shmid_ds shm_info;
2654 int i,ret;
2655
2656 /* find out the length of the shared memory segment */
2657 ret = get_errno(shmctl(shmid, IPC_STAT, &shm_info));
2658 if (is_error(ret)) {
2659 /* can't get length, bail out */
2660 return ret;
2661 }
2662
2663 mmap_lock();
2664
2665 if (shmaddr)
2666 host_raddr = shmat(shmid, (void *)g2h(shmaddr), shmflg);
2667 else {
2668 abi_ulong mmap_start;
2669
2670 mmap_start = mmap_find_vma(0, shm_info.shm_segsz);
2671
2672 if (mmap_start == -1) {
2673 errno = ENOMEM;
2674 host_raddr = (void *)-1;
2675 } else
2676 host_raddr = shmat(shmid, g2h(mmap_start), shmflg | SHM_REMAP);
2677 }
2678
2679 if (host_raddr == (void *)-1) {
2680 mmap_unlock();
2681 return get_errno((long)host_raddr);
2682 }
2683 raddr=h2g((unsigned long)host_raddr);
2684
2685 page_set_flags(raddr, raddr + shm_info.shm_segsz,
2686 PAGE_VALID | PAGE_READ |
2687 ((shmflg & SHM_RDONLY)? 0 : PAGE_WRITE));
2688
2689 for (i = 0; i < N_SHM_REGIONS; i++) {
2690 if (shm_regions[i].start == 0) {
2691 shm_regions[i].start = raddr;
2692 shm_regions[i].size = shm_info.shm_segsz;
2693 break;
2694 }
2695 }
2696
2697 mmap_unlock();
2698 return raddr;
2699
2700}
2701
2702static inline abi_long do_shmdt(abi_ulong shmaddr)
2703{
2704 int i;
2705
2706 for (i = 0; i < N_SHM_REGIONS; ++i) {
2707 if (shm_regions[i].start == shmaddr) {
2708 shm_regions[i].start = 0;
2709 page_set_flags(shmaddr, shm_regions[i].size, 0);
2710 break;
2711 }
2712 }
2713
2714 return get_errno(shmdt(g2h(shmaddr)));
2715}
2716
aurel321c54ff92008-10-13 21:08:44 +00002717#ifdef TARGET_NR_ipc
pbrook53a59602006-03-25 19:31:22 +00002718/* ??? This only works with linear mappings. */
ths0da46a62007-10-20 20:23:07 +00002719/* do_ipc() must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00002720static abi_long do_ipc(unsigned int call, int first,
2721 int second, int third,
2722 abi_long ptr, abi_long fifth)
bellard8853f862004-02-22 14:57:26 +00002723{
2724 int version;
blueswir1992f48a2007-10-14 16:27:31 +00002725 abi_long ret = 0;
bellard8853f862004-02-22 14:57:26 +00002726
2727 version = call >> 16;
2728 call &= 0xffff;
2729
2730 switch (call) {
thsfa294812007-02-02 22:05:00 +00002731 case IPCOP_semop:
aurel32e5289082009-04-18 16:16:12 +00002732 ret = do_semop(first, ptr, second);
thsfa294812007-02-02 22:05:00 +00002733 break;
2734
2735 case IPCOP_semget:
2736 ret = get_errno(semget(first, second, third));
2737 break;
2738
2739 case IPCOP_semctl:
aurel32e5289082009-04-18 16:16:12 +00002740 ret = do_semctl(first, second, third, (union target_semun)(abi_ulong) ptr);
thsfa294812007-02-02 22:05:00 +00002741 break;
thsd96372e2007-02-02 22:05:44 +00002742
aurel321c54ff92008-10-13 21:08:44 +00002743 case IPCOP_msgget:
2744 ret = get_errno(msgget(first, second));
2745 break;
thsd96372e2007-02-02 22:05:44 +00002746
aurel321c54ff92008-10-13 21:08:44 +00002747 case IPCOP_msgsnd:
2748 ret = do_msgsnd(first, ptr, second, third);
2749 break;
thsd96372e2007-02-02 22:05:44 +00002750
aurel321c54ff92008-10-13 21:08:44 +00002751 case IPCOP_msgctl:
2752 ret = do_msgctl(first, second, ptr);
2753 break;
thsd96372e2007-02-02 22:05:44 +00002754
aurel321c54ff92008-10-13 21:08:44 +00002755 case IPCOP_msgrcv:
2756 switch (version) {
2757 case 0:
2758 {
2759 struct target_ipc_kludge {
2760 abi_long msgp;
2761 abi_long msgtyp;
2762 } *tmp;
thsd96372e2007-02-02 22:05:44 +00002763
aurel321c54ff92008-10-13 21:08:44 +00002764 if (!lock_user_struct(VERIFY_READ, tmp, ptr, 1)) {
2765 ret = -TARGET_EFAULT;
2766 break;
ths1bc012f2007-06-03 14:27:49 +00002767 }
aurel321c54ff92008-10-13 21:08:44 +00002768
2769 ret = do_msgrcv(first, tmp->msgp, second, tmp->msgtyp, third);
2770
2771 unlock_user_struct(tmp, ptr, 0);
2772 break;
2773 }
2774 default:
2775 ret = do_msgrcv(first, ptr, second, fifth, third);
2776 }
2777 break;
thsd96372e2007-02-02 22:05:44 +00002778
bellard8853f862004-02-22 14:57:26 +00002779 case IPCOP_shmat:
Riku Voipio88a8c982009-04-03 10:42:00 +03002780 switch (version) {
2781 default:
bellard5a4a8982007-11-11 17:39:18 +00002782 {
2783 abi_ulong raddr;
Riku Voipio88a8c982009-04-03 10:42:00 +03002784 raddr = do_shmat(first, ptr, second);
2785 if (is_error(raddr))
2786 return get_errno(raddr);
bellard2f619692007-11-16 10:46:05 +00002787 if (put_user_ual(raddr, third))
bellard5a4a8982007-11-11 17:39:18 +00002788 return -TARGET_EFAULT;
Riku Voipio88a8c982009-04-03 10:42:00 +03002789 break;
2790 }
2791 case 1:
2792 ret = -TARGET_EINVAL;
2793 break;
bellard5a4a8982007-11-11 17:39:18 +00002794 }
bellard8853f862004-02-22 14:57:26 +00002795 break;
2796 case IPCOP_shmdt:
Riku Voipio88a8c982009-04-03 10:42:00 +03002797 ret = do_shmdt(ptr);
bellard8853f862004-02-22 14:57:26 +00002798 break;
2799
2800 case IPCOP_shmget:
2801 /* IPC_* flag values are the same on all linux platforms */
2802 ret = get_errno(shmget(first, second, third));
2803 break;
2804
2805 /* IPC_* and SHM_* command values are the same on all linux platforms */
2806 case IPCOP_shmctl:
Riku Voipio88a8c982009-04-03 10:42:00 +03002807 ret = do_shmctl(first, second, third);
bellard8853f862004-02-22 14:57:26 +00002808 break;
2809 default:
j_mayer32407102007-09-26 23:01:49 +00002810 gemu_log("Unsupported ipc call: %d (version %d)\n", call, version);
ths0da46a62007-10-20 20:23:07 +00002811 ret = -TARGET_ENOSYS;
bellard8853f862004-02-22 14:57:26 +00002812 break;
2813 }
2814 return ret;
2815}
j_mayer32407102007-09-26 23:01:49 +00002816#endif
bellard8853f862004-02-22 14:57:26 +00002817
bellard31e31b82003-02-18 22:55:36 +00002818/* kernel structure types definitions */
2819#define IFNAMSIZ 16
2820
Blue Swirl001faf32009-05-13 17:53:17 +00002821#define STRUCT(name, ...) STRUCT_ ## name,
bellard31e31b82003-02-18 22:55:36 +00002822#define STRUCT_SPECIAL(name) STRUCT_ ## name,
2823enum {
2824#include "syscall_types.h"
2825};
2826#undef STRUCT
2827#undef STRUCT_SPECIAL
2828
Blue Swirl001faf32009-05-13 17:53:17 +00002829#define STRUCT(name, ...) static const argtype struct_ ## name ## _def[] = { __VA_ARGS__, TYPE_NULL };
bellard31e31b82003-02-18 22:55:36 +00002830#define STRUCT_SPECIAL(name)
2831#include "syscall_types.h"
2832#undef STRUCT
2833#undef STRUCT_SPECIAL
2834
2835typedef struct IOCTLEntry {
bellard2ab83ea2003-06-15 19:56:46 +00002836 unsigned int target_cmd;
2837 unsigned int host_cmd;
bellard31e31b82003-02-18 22:55:36 +00002838 const char *name;
2839 int access;
bellard1a9353d2003-03-16 20:28:50 +00002840 const argtype arg_type[5];
bellard31e31b82003-02-18 22:55:36 +00002841} IOCTLEntry;
2842
2843#define IOC_R 0x0001
2844#define IOC_W 0x0002
2845#define IOC_RW (IOC_R | IOC_W)
2846
2847#define MAX_STRUCT_SIZE 4096
2848
blueswir19f106a72008-10-05 10:52:52 +00002849static IOCTLEntry ioctl_entries[] = {
Blue Swirl001faf32009-05-13 17:53:17 +00002850#define IOCTL(cmd, access, ...) \
2851 { TARGET_ ## cmd, cmd, #cmd, access, { __VA_ARGS__ } },
bellard31e31b82003-02-18 22:55:36 +00002852#include "ioctls.h"
2853 { 0, 0, },
2854};
2855
pbrook53a59602006-03-25 19:31:22 +00002856/* ??? Implement proper locking for ioctls. */
ths0da46a62007-10-20 20:23:07 +00002857/* do_ioctl() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00002858static abi_long do_ioctl(int fd, abi_long cmd, abi_long arg)
bellard31e31b82003-02-18 22:55:36 +00002859{
2860 const IOCTLEntry *ie;
2861 const argtype *arg_type;
blueswir1992f48a2007-10-14 16:27:31 +00002862 abi_long ret;
bellard31e31b82003-02-18 22:55:36 +00002863 uint8_t buf_temp[MAX_STRUCT_SIZE];
pbrook53a59602006-03-25 19:31:22 +00002864 int target_size;
2865 void *argptr;
bellard31e31b82003-02-18 22:55:36 +00002866
2867 ie = ioctl_entries;
2868 for(;;) {
2869 if (ie->target_cmd == 0) {
j_mayer32407102007-09-26 23:01:49 +00002870 gemu_log("Unsupported ioctl: cmd=0x%04lx\n", (long)cmd);
ths0da46a62007-10-20 20:23:07 +00002871 return -TARGET_ENOSYS;
bellard31e31b82003-02-18 22:55:36 +00002872 }
2873 if (ie->target_cmd == cmd)
2874 break;
2875 ie++;
2876 }
2877 arg_type = ie->arg_type;
bellard9de5e442003-03-23 16:49:39 +00002878#if defined(DEBUG)
j_mayer32407102007-09-26 23:01:49 +00002879 gemu_log("ioctl: cmd=0x%04lx (%s)\n", (long)cmd, ie->name);
bellard72f03902003-02-18 23:33:18 +00002880#endif
bellard31e31b82003-02-18 22:55:36 +00002881 switch(arg_type[0]) {
2882 case TYPE_NULL:
2883 /* no argument */
2884 ret = get_errno(ioctl(fd, ie->host_cmd));
2885 break;
2886 case TYPE_PTRVOID:
2887 case TYPE_INT:
2888 /* int argment */
2889 ret = get_errno(ioctl(fd, ie->host_cmd, arg));
2890 break;
2891 case TYPE_PTR:
2892 arg_type++;
pbrook53a59602006-03-25 19:31:22 +00002893 target_size = thunk_type_size(arg_type, 0);
bellard31e31b82003-02-18 22:55:36 +00002894 switch(ie->access) {
2895 case IOC_R:
2896 ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
2897 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00002898 argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
2899 if (!argptr)
2900 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00002901 thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
2902 unlock_user(argptr, arg, target_size);
bellard31e31b82003-02-18 22:55:36 +00002903 }
2904 break;
2905 case IOC_W:
bellard579a97f2007-11-11 14:26:47 +00002906 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
2907 if (!argptr)
2908 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00002909 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
2910 unlock_user(argptr, arg, 0);
bellard31e31b82003-02-18 22:55:36 +00002911 ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
2912 break;
2913 default:
2914 case IOC_RW:
bellard579a97f2007-11-11 14:26:47 +00002915 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
2916 if (!argptr)
2917 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00002918 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
2919 unlock_user(argptr, arg, 0);
bellard31e31b82003-02-18 22:55:36 +00002920 ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
2921 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00002922 argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
2923 if (!argptr)
2924 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00002925 thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
2926 unlock_user(argptr, arg, target_size);
bellard31e31b82003-02-18 22:55:36 +00002927 }
2928 break;
2929 }
2930 break;
2931 default:
j_mayer32407102007-09-26 23:01:49 +00002932 gemu_log("Unsupported ioctl type: cmd=0x%04lx type=%d\n",
2933 (long)cmd, arg_type[0]);
ths0da46a62007-10-20 20:23:07 +00002934 ret = -TARGET_ENOSYS;
bellard31e31b82003-02-18 22:55:36 +00002935 break;
2936 }
2937 return ret;
2938}
2939
blueswir1b39bc502008-10-05 10:51:10 +00002940static const bitmask_transtbl iflag_tbl[] = {
bellard31e31b82003-02-18 22:55:36 +00002941 { TARGET_IGNBRK, TARGET_IGNBRK, IGNBRK, IGNBRK },
2942 { TARGET_BRKINT, TARGET_BRKINT, BRKINT, BRKINT },
2943 { TARGET_IGNPAR, TARGET_IGNPAR, IGNPAR, IGNPAR },
2944 { TARGET_PARMRK, TARGET_PARMRK, PARMRK, PARMRK },
2945 { TARGET_INPCK, TARGET_INPCK, INPCK, INPCK },
2946 { TARGET_ISTRIP, TARGET_ISTRIP, ISTRIP, ISTRIP },
2947 { TARGET_INLCR, TARGET_INLCR, INLCR, INLCR },
2948 { TARGET_IGNCR, TARGET_IGNCR, IGNCR, IGNCR },
2949 { TARGET_ICRNL, TARGET_ICRNL, ICRNL, ICRNL },
2950 { TARGET_IUCLC, TARGET_IUCLC, IUCLC, IUCLC },
2951 { TARGET_IXON, TARGET_IXON, IXON, IXON },
2952 { TARGET_IXANY, TARGET_IXANY, IXANY, IXANY },
2953 { TARGET_IXOFF, TARGET_IXOFF, IXOFF, IXOFF },
2954 { TARGET_IMAXBEL, TARGET_IMAXBEL, IMAXBEL, IMAXBEL },
2955 { 0, 0, 0, 0 }
2956};
2957
blueswir1b39bc502008-10-05 10:51:10 +00002958static const bitmask_transtbl oflag_tbl[] = {
bellard31e31b82003-02-18 22:55:36 +00002959 { TARGET_OPOST, TARGET_OPOST, OPOST, OPOST },
2960 { TARGET_OLCUC, TARGET_OLCUC, OLCUC, OLCUC },
2961 { TARGET_ONLCR, TARGET_ONLCR, ONLCR, ONLCR },
2962 { TARGET_OCRNL, TARGET_OCRNL, OCRNL, OCRNL },
2963 { TARGET_ONOCR, TARGET_ONOCR, ONOCR, ONOCR },
2964 { TARGET_ONLRET, TARGET_ONLRET, ONLRET, ONLRET },
2965 { TARGET_OFILL, TARGET_OFILL, OFILL, OFILL },
2966 { TARGET_OFDEL, TARGET_OFDEL, OFDEL, OFDEL },
2967 { TARGET_NLDLY, TARGET_NL0, NLDLY, NL0 },
2968 { TARGET_NLDLY, TARGET_NL1, NLDLY, NL1 },
2969 { TARGET_CRDLY, TARGET_CR0, CRDLY, CR0 },
2970 { TARGET_CRDLY, TARGET_CR1, CRDLY, CR1 },
2971 { TARGET_CRDLY, TARGET_CR2, CRDLY, CR2 },
2972 { TARGET_CRDLY, TARGET_CR3, CRDLY, CR3 },
2973 { TARGET_TABDLY, TARGET_TAB0, TABDLY, TAB0 },
2974 { TARGET_TABDLY, TARGET_TAB1, TABDLY, TAB1 },
2975 { TARGET_TABDLY, TARGET_TAB2, TABDLY, TAB2 },
2976 { TARGET_TABDLY, TARGET_TAB3, TABDLY, TAB3 },
2977 { TARGET_BSDLY, TARGET_BS0, BSDLY, BS0 },
2978 { TARGET_BSDLY, TARGET_BS1, BSDLY, BS1 },
2979 { TARGET_VTDLY, TARGET_VT0, VTDLY, VT0 },
2980 { TARGET_VTDLY, TARGET_VT1, VTDLY, VT1 },
2981 { TARGET_FFDLY, TARGET_FF0, FFDLY, FF0 },
2982 { TARGET_FFDLY, TARGET_FF1, FFDLY, FF1 },
2983 { 0, 0, 0, 0 }
2984};
2985
blueswir1b39bc502008-10-05 10:51:10 +00002986static const bitmask_transtbl cflag_tbl[] = {
bellard31e31b82003-02-18 22:55:36 +00002987 { TARGET_CBAUD, TARGET_B0, CBAUD, B0 },
2988 { TARGET_CBAUD, TARGET_B50, CBAUD, B50 },
2989 { TARGET_CBAUD, TARGET_B75, CBAUD, B75 },
2990 { TARGET_CBAUD, TARGET_B110, CBAUD, B110 },
2991 { TARGET_CBAUD, TARGET_B134, CBAUD, B134 },
2992 { TARGET_CBAUD, TARGET_B150, CBAUD, B150 },
2993 { TARGET_CBAUD, TARGET_B200, CBAUD, B200 },
2994 { TARGET_CBAUD, TARGET_B300, CBAUD, B300 },
2995 { TARGET_CBAUD, TARGET_B600, CBAUD, B600 },
2996 { TARGET_CBAUD, TARGET_B1200, CBAUD, B1200 },
2997 { TARGET_CBAUD, TARGET_B1800, CBAUD, B1800 },
2998 { TARGET_CBAUD, TARGET_B2400, CBAUD, B2400 },
2999 { TARGET_CBAUD, TARGET_B4800, CBAUD, B4800 },
3000 { TARGET_CBAUD, TARGET_B9600, CBAUD, B9600 },
3001 { TARGET_CBAUD, TARGET_B19200, CBAUD, B19200 },
3002 { TARGET_CBAUD, TARGET_B38400, CBAUD, B38400 },
3003 { TARGET_CBAUD, TARGET_B57600, CBAUD, B57600 },
3004 { TARGET_CBAUD, TARGET_B115200, CBAUD, B115200 },
3005 { TARGET_CBAUD, TARGET_B230400, CBAUD, B230400 },
3006 { TARGET_CBAUD, TARGET_B460800, CBAUD, B460800 },
3007 { TARGET_CSIZE, TARGET_CS5, CSIZE, CS5 },
3008 { TARGET_CSIZE, TARGET_CS6, CSIZE, CS6 },
3009 { TARGET_CSIZE, TARGET_CS7, CSIZE, CS7 },
3010 { TARGET_CSIZE, TARGET_CS8, CSIZE, CS8 },
3011 { TARGET_CSTOPB, TARGET_CSTOPB, CSTOPB, CSTOPB },
3012 { TARGET_CREAD, TARGET_CREAD, CREAD, CREAD },
3013 { TARGET_PARENB, TARGET_PARENB, PARENB, PARENB },
3014 { TARGET_PARODD, TARGET_PARODD, PARODD, PARODD },
3015 { TARGET_HUPCL, TARGET_HUPCL, HUPCL, HUPCL },
3016 { TARGET_CLOCAL, TARGET_CLOCAL, CLOCAL, CLOCAL },
3017 { TARGET_CRTSCTS, TARGET_CRTSCTS, CRTSCTS, CRTSCTS },
3018 { 0, 0, 0, 0 }
3019};
3020
blueswir1b39bc502008-10-05 10:51:10 +00003021static const bitmask_transtbl lflag_tbl[] = {
bellard31e31b82003-02-18 22:55:36 +00003022 { TARGET_ISIG, TARGET_ISIG, ISIG, ISIG },
3023 { TARGET_ICANON, TARGET_ICANON, ICANON, ICANON },
3024 { TARGET_XCASE, TARGET_XCASE, XCASE, XCASE },
3025 { TARGET_ECHO, TARGET_ECHO, ECHO, ECHO },
3026 { TARGET_ECHOE, TARGET_ECHOE, ECHOE, ECHOE },
3027 { TARGET_ECHOK, TARGET_ECHOK, ECHOK, ECHOK },
3028 { TARGET_ECHONL, TARGET_ECHONL, ECHONL, ECHONL },
3029 { TARGET_NOFLSH, TARGET_NOFLSH, NOFLSH, NOFLSH },
3030 { TARGET_TOSTOP, TARGET_TOSTOP, TOSTOP, TOSTOP },
3031 { TARGET_ECHOCTL, TARGET_ECHOCTL, ECHOCTL, ECHOCTL },
3032 { TARGET_ECHOPRT, TARGET_ECHOPRT, ECHOPRT, ECHOPRT },
3033 { TARGET_ECHOKE, TARGET_ECHOKE, ECHOKE, ECHOKE },
3034 { TARGET_FLUSHO, TARGET_FLUSHO, FLUSHO, FLUSHO },
3035 { TARGET_PENDIN, TARGET_PENDIN, PENDIN, PENDIN },
3036 { TARGET_IEXTEN, TARGET_IEXTEN, IEXTEN, IEXTEN },
3037 { 0, 0, 0, 0 }
3038};
3039
3040static void target_to_host_termios (void *dst, const void *src)
3041{
3042 struct host_termios *host = dst;
3043 const struct target_termios *target = src;
ths3b46e622007-09-17 08:09:54 +00003044
ths5fafdf22007-09-16 21:08:06 +00003045 host->c_iflag =
bellard31e31b82003-02-18 22:55:36 +00003046 target_to_host_bitmask(tswap32(target->c_iflag), iflag_tbl);
ths5fafdf22007-09-16 21:08:06 +00003047 host->c_oflag =
bellard31e31b82003-02-18 22:55:36 +00003048 target_to_host_bitmask(tswap32(target->c_oflag), oflag_tbl);
ths5fafdf22007-09-16 21:08:06 +00003049 host->c_cflag =
bellard31e31b82003-02-18 22:55:36 +00003050 target_to_host_bitmask(tswap32(target->c_cflag), cflag_tbl);
ths5fafdf22007-09-16 21:08:06 +00003051 host->c_lflag =
bellard31e31b82003-02-18 22:55:36 +00003052 target_to_host_bitmask(tswap32(target->c_lflag), lflag_tbl);
3053 host->c_line = target->c_line;
ths3b46e622007-09-17 08:09:54 +00003054
Arnaud Patard44607122009-04-21 17:39:08 +03003055 memset(host->c_cc, 0, sizeof(host->c_cc));
ths5fafdf22007-09-16 21:08:06 +00003056 host->c_cc[VINTR] = target->c_cc[TARGET_VINTR];
3057 host->c_cc[VQUIT] = target->c_cc[TARGET_VQUIT];
ths3b46e622007-09-17 08:09:54 +00003058 host->c_cc[VERASE] = target->c_cc[TARGET_VERASE];
ths5fafdf22007-09-16 21:08:06 +00003059 host->c_cc[VKILL] = target->c_cc[TARGET_VKILL];
ths3b46e622007-09-17 08:09:54 +00003060 host->c_cc[VEOF] = target->c_cc[TARGET_VEOF];
ths5fafdf22007-09-16 21:08:06 +00003061 host->c_cc[VTIME] = target->c_cc[TARGET_VTIME];
ths3b46e622007-09-17 08:09:54 +00003062 host->c_cc[VMIN] = target->c_cc[TARGET_VMIN];
ths5fafdf22007-09-16 21:08:06 +00003063 host->c_cc[VSWTC] = target->c_cc[TARGET_VSWTC];
ths3b46e622007-09-17 08:09:54 +00003064 host->c_cc[VSTART] = target->c_cc[TARGET_VSTART];
ths5fafdf22007-09-16 21:08:06 +00003065 host->c_cc[VSTOP] = target->c_cc[TARGET_VSTOP];
3066 host->c_cc[VSUSP] = target->c_cc[TARGET_VSUSP];
ths3b46e622007-09-17 08:09:54 +00003067 host->c_cc[VEOL] = target->c_cc[TARGET_VEOL];
3068 host->c_cc[VREPRINT] = target->c_cc[TARGET_VREPRINT];
3069 host->c_cc[VDISCARD] = target->c_cc[TARGET_VDISCARD];
3070 host->c_cc[VWERASE] = target->c_cc[TARGET_VWERASE];
3071 host->c_cc[VLNEXT] = target->c_cc[TARGET_VLNEXT];
ths5fafdf22007-09-16 21:08:06 +00003072 host->c_cc[VEOL2] = target->c_cc[TARGET_VEOL2];
bellard31e31b82003-02-18 22:55:36 +00003073}
ths3b46e622007-09-17 08:09:54 +00003074
bellard31e31b82003-02-18 22:55:36 +00003075static void host_to_target_termios (void *dst, const void *src)
3076{
3077 struct target_termios *target = dst;
3078 const struct host_termios *host = src;
3079
ths5fafdf22007-09-16 21:08:06 +00003080 target->c_iflag =
bellard31e31b82003-02-18 22:55:36 +00003081 tswap32(host_to_target_bitmask(host->c_iflag, iflag_tbl));
ths5fafdf22007-09-16 21:08:06 +00003082 target->c_oflag =
bellard31e31b82003-02-18 22:55:36 +00003083 tswap32(host_to_target_bitmask(host->c_oflag, oflag_tbl));
ths5fafdf22007-09-16 21:08:06 +00003084 target->c_cflag =
bellard31e31b82003-02-18 22:55:36 +00003085 tswap32(host_to_target_bitmask(host->c_cflag, cflag_tbl));
ths5fafdf22007-09-16 21:08:06 +00003086 target->c_lflag =
bellard31e31b82003-02-18 22:55:36 +00003087 tswap32(host_to_target_bitmask(host->c_lflag, lflag_tbl));
3088 target->c_line = host->c_line;
ths3b46e622007-09-17 08:09:54 +00003089
Arnaud Patard44607122009-04-21 17:39:08 +03003090 memset(target->c_cc, 0, sizeof(target->c_cc));
bellard31e31b82003-02-18 22:55:36 +00003091 target->c_cc[TARGET_VINTR] = host->c_cc[VINTR];
3092 target->c_cc[TARGET_VQUIT] = host->c_cc[VQUIT];
3093 target->c_cc[TARGET_VERASE] = host->c_cc[VERASE];
3094 target->c_cc[TARGET_VKILL] = host->c_cc[VKILL];
3095 target->c_cc[TARGET_VEOF] = host->c_cc[VEOF];
3096 target->c_cc[TARGET_VTIME] = host->c_cc[VTIME];
3097 target->c_cc[TARGET_VMIN] = host->c_cc[VMIN];
3098 target->c_cc[TARGET_VSWTC] = host->c_cc[VSWTC];
3099 target->c_cc[TARGET_VSTART] = host->c_cc[VSTART];
3100 target->c_cc[TARGET_VSTOP] = host->c_cc[VSTOP];
3101 target->c_cc[TARGET_VSUSP] = host->c_cc[VSUSP];
3102 target->c_cc[TARGET_VEOL] = host->c_cc[VEOL];
3103 target->c_cc[TARGET_VREPRINT] = host->c_cc[VREPRINT];
3104 target->c_cc[TARGET_VDISCARD] = host->c_cc[VDISCARD];
3105 target->c_cc[TARGET_VWERASE] = host->c_cc[VWERASE];
3106 target->c_cc[TARGET_VLNEXT] = host->c_cc[VLNEXT];
3107 target->c_cc[TARGET_VEOL2] = host->c_cc[VEOL2];
3108}
3109
blueswir18e853dc2008-10-05 10:49:32 +00003110static const StructEntry struct_termios_def = {
bellard31e31b82003-02-18 22:55:36 +00003111 .convert = { host_to_target_termios, target_to_host_termios },
3112 .size = { sizeof(struct target_termios), sizeof(struct host_termios) },
3113 .align = { __alignof__(struct target_termios), __alignof__(struct host_termios) },
3114};
3115
bellard5286db72003-06-05 00:57:30 +00003116static bitmask_transtbl mmap_flags_tbl[] = {
3117 { TARGET_MAP_SHARED, TARGET_MAP_SHARED, MAP_SHARED, MAP_SHARED },
3118 { TARGET_MAP_PRIVATE, TARGET_MAP_PRIVATE, MAP_PRIVATE, MAP_PRIVATE },
3119 { TARGET_MAP_FIXED, TARGET_MAP_FIXED, MAP_FIXED, MAP_FIXED },
3120 { TARGET_MAP_ANONYMOUS, TARGET_MAP_ANONYMOUS, MAP_ANONYMOUS, MAP_ANONYMOUS },
3121 { TARGET_MAP_GROWSDOWN, TARGET_MAP_GROWSDOWN, MAP_GROWSDOWN, MAP_GROWSDOWN },
3122 { TARGET_MAP_DENYWRITE, TARGET_MAP_DENYWRITE, MAP_DENYWRITE, MAP_DENYWRITE },
3123 { TARGET_MAP_EXECUTABLE, TARGET_MAP_EXECUTABLE, MAP_EXECUTABLE, MAP_EXECUTABLE },
3124 { TARGET_MAP_LOCKED, TARGET_MAP_LOCKED, MAP_LOCKED, MAP_LOCKED },
3125 { 0, 0, 0, 0 }
3126};
3127
bellard2ab83ea2003-06-15 19:56:46 +00003128#if defined(TARGET_I386)
bellard6dbad632003-03-16 18:05:05 +00003129
3130/* NOTE: there is really one LDT for all the threads */
blueswir1b1d8e522008-10-26 13:43:07 +00003131static uint8_t *ldt_table;
bellard6dbad632003-03-16 18:05:05 +00003132
bellard03acab62007-11-11 14:57:14 +00003133static abi_long read_ldt(abi_ulong ptr, unsigned long bytecount)
bellard6dbad632003-03-16 18:05:05 +00003134{
3135 int size;
pbrook53a59602006-03-25 19:31:22 +00003136 void *p;
bellard6dbad632003-03-16 18:05:05 +00003137
3138 if (!ldt_table)
3139 return 0;
3140 size = TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE;
3141 if (size > bytecount)
3142 size = bytecount;
bellard579a97f2007-11-11 14:26:47 +00003143 p = lock_user(VERIFY_WRITE, ptr, size, 0);
3144 if (!p)
bellard03acab62007-11-11 14:57:14 +00003145 return -TARGET_EFAULT;
bellard579a97f2007-11-11 14:26:47 +00003146 /* ??? Should this by byteswapped? */
pbrook53a59602006-03-25 19:31:22 +00003147 memcpy(p, ldt_table, size);
3148 unlock_user(p, ptr, size);
bellard6dbad632003-03-16 18:05:05 +00003149 return size;
3150}
3151
3152/* XXX: add locking support */
bellard03acab62007-11-11 14:57:14 +00003153static abi_long write_ldt(CPUX86State *env,
3154 abi_ulong ptr, unsigned long bytecount, int oldmode)
bellard6dbad632003-03-16 18:05:05 +00003155{
3156 struct target_modify_ldt_ldt_s ldt_info;
pbrook53a59602006-03-25 19:31:22 +00003157 struct target_modify_ldt_ldt_s *target_ldt_info;
bellard6dbad632003-03-16 18:05:05 +00003158 int seg_32bit, contents, read_exec_only, limit_in_pages;
bellard8d18e892007-11-14 15:18:40 +00003159 int seg_not_present, useable, lm;
bellard6dbad632003-03-16 18:05:05 +00003160 uint32_t *lp, entry_1, entry_2;
3161
3162 if (bytecount != sizeof(ldt_info))
bellard03acab62007-11-11 14:57:14 +00003163 return -TARGET_EINVAL;
bellard579a97f2007-11-11 14:26:47 +00003164 if (!lock_user_struct(VERIFY_READ, target_ldt_info, ptr, 1))
bellard03acab62007-11-11 14:57:14 +00003165 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00003166 ldt_info.entry_number = tswap32(target_ldt_info->entry_number);
3167 ldt_info.base_addr = tswapl(target_ldt_info->base_addr);
3168 ldt_info.limit = tswap32(target_ldt_info->limit);
3169 ldt_info.flags = tswap32(target_ldt_info->flags);
3170 unlock_user_struct(target_ldt_info, ptr, 0);
ths3b46e622007-09-17 08:09:54 +00003171
bellard6dbad632003-03-16 18:05:05 +00003172 if (ldt_info.entry_number >= TARGET_LDT_ENTRIES)
bellard03acab62007-11-11 14:57:14 +00003173 return -TARGET_EINVAL;
bellard6dbad632003-03-16 18:05:05 +00003174 seg_32bit = ldt_info.flags & 1;
3175 contents = (ldt_info.flags >> 1) & 3;
3176 read_exec_only = (ldt_info.flags >> 3) & 1;
3177 limit_in_pages = (ldt_info.flags >> 4) & 1;
3178 seg_not_present = (ldt_info.flags >> 5) & 1;
3179 useable = (ldt_info.flags >> 6) & 1;
bellard8d18e892007-11-14 15:18:40 +00003180#ifdef TARGET_ABI32
3181 lm = 0;
3182#else
3183 lm = (ldt_info.flags >> 7) & 1;
3184#endif
bellard6dbad632003-03-16 18:05:05 +00003185 if (contents == 3) {
3186 if (oldmode)
bellard03acab62007-11-11 14:57:14 +00003187 return -TARGET_EINVAL;
bellard6dbad632003-03-16 18:05:05 +00003188 if (seg_not_present == 0)
bellard03acab62007-11-11 14:57:14 +00003189 return -TARGET_EINVAL;
bellard6dbad632003-03-16 18:05:05 +00003190 }
3191 /* allocate the LDT */
3192 if (!ldt_table) {
balroge4415702008-11-10 02:55:33 +00003193 env->ldt.base = target_mmap(0,
3194 TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE,
3195 PROT_READ|PROT_WRITE,
3196 MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
3197 if (env->ldt.base == -1)
bellard03acab62007-11-11 14:57:14 +00003198 return -TARGET_ENOMEM;
balroge4415702008-11-10 02:55:33 +00003199 memset(g2h(env->ldt.base), 0,
3200 TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE);
bellard6dbad632003-03-16 18:05:05 +00003201 env->ldt.limit = 0xffff;
balroge4415702008-11-10 02:55:33 +00003202 ldt_table = g2h(env->ldt.base);
bellard6dbad632003-03-16 18:05:05 +00003203 }
3204
3205 /* NOTE: same code as Linux kernel */
3206 /* Allow LDTs to be cleared by the user. */
3207 if (ldt_info.base_addr == 0 && ldt_info.limit == 0) {
3208 if (oldmode ||
3209 (contents == 0 &&
3210 read_exec_only == 1 &&
3211 seg_32bit == 0 &&
3212 limit_in_pages == 0 &&
3213 seg_not_present == 1 &&
3214 useable == 0 )) {
3215 entry_1 = 0;
3216 entry_2 = 0;
3217 goto install;
3218 }
3219 }
ths3b46e622007-09-17 08:09:54 +00003220
bellard6dbad632003-03-16 18:05:05 +00003221 entry_1 = ((ldt_info.base_addr & 0x0000ffff) << 16) |
3222 (ldt_info.limit & 0x0ffff);
3223 entry_2 = (ldt_info.base_addr & 0xff000000) |
3224 ((ldt_info.base_addr & 0x00ff0000) >> 16) |
3225 (ldt_info.limit & 0xf0000) |
3226 ((read_exec_only ^ 1) << 9) |
3227 (contents << 10) |
3228 ((seg_not_present ^ 1) << 15) |
3229 (seg_32bit << 22) |
3230 (limit_in_pages << 23) |
bellard8d18e892007-11-14 15:18:40 +00003231 (lm << 21) |
bellard6dbad632003-03-16 18:05:05 +00003232 0x7000;
3233 if (!oldmode)
3234 entry_2 |= (useable << 20);
bellard14ae3ba2003-05-27 23:25:06 +00003235
bellard6dbad632003-03-16 18:05:05 +00003236 /* Install the new entry ... */
3237install:
3238 lp = (uint32_t *)(ldt_table + (ldt_info.entry_number << 3));
3239 lp[0] = tswap32(entry_1);
3240 lp[1] = tswap32(entry_2);
3241 return 0;
3242}
3243
3244/* specific and weird i386 syscalls */
blueswir18fcd3692008-08-17 20:26:25 +00003245static abi_long do_modify_ldt(CPUX86State *env, int func, abi_ulong ptr,
3246 unsigned long bytecount)
bellard6dbad632003-03-16 18:05:05 +00003247{
bellard03acab62007-11-11 14:57:14 +00003248 abi_long ret;
ths3b46e622007-09-17 08:09:54 +00003249
bellard6dbad632003-03-16 18:05:05 +00003250 switch (func) {
3251 case 0:
3252 ret = read_ldt(ptr, bytecount);
3253 break;
3254 case 1:
3255 ret = write_ldt(env, ptr, bytecount, 1);
3256 break;
3257 case 0x11:
3258 ret = write_ldt(env, ptr, bytecount, 0);
3259 break;
bellard03acab62007-11-11 14:57:14 +00003260 default:
3261 ret = -TARGET_ENOSYS;
3262 break;
bellard6dbad632003-03-16 18:05:05 +00003263 }
3264 return ret;
3265}
bellard1b6b0292003-03-22 17:31:38 +00003266
blueswir14583f582008-08-24 10:35:55 +00003267#if defined(TARGET_I386) && defined(TARGET_ABI32)
blueswir18fcd3692008-08-17 20:26:25 +00003268static abi_long do_set_thread_area(CPUX86State *env, abi_ulong ptr)
bellard8d18e892007-11-14 15:18:40 +00003269{
3270 uint64_t *gdt_table = g2h(env->gdt.base);
3271 struct target_modify_ldt_ldt_s ldt_info;
3272 struct target_modify_ldt_ldt_s *target_ldt_info;
3273 int seg_32bit, contents, read_exec_only, limit_in_pages;
3274 int seg_not_present, useable, lm;
3275 uint32_t *lp, entry_1, entry_2;
3276 int i;
3277
3278 lock_user_struct(VERIFY_WRITE, target_ldt_info, ptr, 1);
3279 if (!target_ldt_info)
3280 return -TARGET_EFAULT;
3281 ldt_info.entry_number = tswap32(target_ldt_info->entry_number);
3282 ldt_info.base_addr = tswapl(target_ldt_info->base_addr);
3283 ldt_info.limit = tswap32(target_ldt_info->limit);
3284 ldt_info.flags = tswap32(target_ldt_info->flags);
3285 if (ldt_info.entry_number == -1) {
3286 for (i=TARGET_GDT_ENTRY_TLS_MIN; i<=TARGET_GDT_ENTRY_TLS_MAX; i++) {
3287 if (gdt_table[i] == 0) {
3288 ldt_info.entry_number = i;
3289 target_ldt_info->entry_number = tswap32(i);
3290 break;
3291 }
3292 }
3293 }
3294 unlock_user_struct(target_ldt_info, ptr, 1);
3295
3296 if (ldt_info.entry_number < TARGET_GDT_ENTRY_TLS_MIN ||
3297 ldt_info.entry_number > TARGET_GDT_ENTRY_TLS_MAX)
3298 return -TARGET_EINVAL;
3299 seg_32bit = ldt_info.flags & 1;
3300 contents = (ldt_info.flags >> 1) & 3;
3301 read_exec_only = (ldt_info.flags >> 3) & 1;
3302 limit_in_pages = (ldt_info.flags >> 4) & 1;
3303 seg_not_present = (ldt_info.flags >> 5) & 1;
3304 useable = (ldt_info.flags >> 6) & 1;
3305#ifdef TARGET_ABI32
3306 lm = 0;
3307#else
3308 lm = (ldt_info.flags >> 7) & 1;
3309#endif
3310
3311 if (contents == 3) {
3312 if (seg_not_present == 0)
3313 return -TARGET_EINVAL;
3314 }
3315
3316 /* NOTE: same code as Linux kernel */
3317 /* Allow LDTs to be cleared by the user. */
3318 if (ldt_info.base_addr == 0 && ldt_info.limit == 0) {
3319 if ((contents == 0 &&
3320 read_exec_only == 1 &&
3321 seg_32bit == 0 &&
3322 limit_in_pages == 0 &&
3323 seg_not_present == 1 &&
3324 useable == 0 )) {
3325 entry_1 = 0;
3326 entry_2 = 0;
3327 goto install;
3328 }
3329 }
3330
3331 entry_1 = ((ldt_info.base_addr & 0x0000ffff) << 16) |
3332 (ldt_info.limit & 0x0ffff);
3333 entry_2 = (ldt_info.base_addr & 0xff000000) |
3334 ((ldt_info.base_addr & 0x00ff0000) >> 16) |
3335 (ldt_info.limit & 0xf0000) |
3336 ((read_exec_only ^ 1) << 9) |
3337 (contents << 10) |
3338 ((seg_not_present ^ 1) << 15) |
3339 (seg_32bit << 22) |
3340 (limit_in_pages << 23) |
3341 (useable << 20) |
3342 (lm << 21) |
3343 0x7000;
3344
3345 /* Install the new entry ... */
3346install:
3347 lp = (uint32_t *)(gdt_table + ldt_info.entry_number);
3348 lp[0] = tswap32(entry_1);
3349 lp[1] = tswap32(entry_2);
3350 return 0;
3351}
3352
blueswir18fcd3692008-08-17 20:26:25 +00003353static abi_long do_get_thread_area(CPUX86State *env, abi_ulong ptr)
bellard8d18e892007-11-14 15:18:40 +00003354{
3355 struct target_modify_ldt_ldt_s *target_ldt_info;
3356 uint64_t *gdt_table = g2h(env->gdt.base);
3357 uint32_t base_addr, limit, flags;
3358 int seg_32bit, contents, read_exec_only, limit_in_pages, idx;
3359 int seg_not_present, useable, lm;
3360 uint32_t *lp, entry_1, entry_2;
3361
3362 lock_user_struct(VERIFY_WRITE, target_ldt_info, ptr, 1);
3363 if (!target_ldt_info)
3364 return -TARGET_EFAULT;
3365 idx = tswap32(target_ldt_info->entry_number);
3366 if (idx < TARGET_GDT_ENTRY_TLS_MIN ||
3367 idx > TARGET_GDT_ENTRY_TLS_MAX) {
3368 unlock_user_struct(target_ldt_info, ptr, 1);
3369 return -TARGET_EINVAL;
3370 }
3371 lp = (uint32_t *)(gdt_table + idx);
3372 entry_1 = tswap32(lp[0]);
3373 entry_2 = tswap32(lp[1]);
3374
3375 read_exec_only = ((entry_2 >> 9) & 1) ^ 1;
3376 contents = (entry_2 >> 10) & 3;
3377 seg_not_present = ((entry_2 >> 15) & 1) ^ 1;
3378 seg_32bit = (entry_2 >> 22) & 1;
3379 limit_in_pages = (entry_2 >> 23) & 1;
3380 useable = (entry_2 >> 20) & 1;
3381#ifdef TARGET_ABI32
3382 lm = 0;
3383#else
3384 lm = (entry_2 >> 21) & 1;
3385#endif
3386 flags = (seg_32bit << 0) | (contents << 1) |
3387 (read_exec_only << 3) | (limit_in_pages << 4) |
3388 (seg_not_present << 5) | (useable << 6) | (lm << 7);
3389 limit = (entry_1 & 0xffff) | (entry_2 & 0xf0000);
3390 base_addr = (entry_1 >> 16) |
3391 (entry_2 & 0xff000000) |
3392 ((entry_2 & 0xff) << 16);
3393 target_ldt_info->base_addr = tswapl(base_addr);
3394 target_ldt_info->limit = tswap32(limit);
3395 target_ldt_info->flags = tswap32(flags);
3396 unlock_user_struct(target_ldt_info, ptr, 1);
3397 return 0;
3398}
blueswir14583f582008-08-24 10:35:55 +00003399#endif /* TARGET_I386 && TARGET_ABI32 */
bellard8d18e892007-11-14 15:18:40 +00003400
bellardd2fd1af2007-11-14 18:08:56 +00003401#ifndef TARGET_ABI32
blueswir18fcd3692008-08-17 20:26:25 +00003402static abi_long do_arch_prctl(CPUX86State *env, int code, abi_ulong addr)
bellardd2fd1af2007-11-14 18:08:56 +00003403{
3404 abi_long ret;
3405 abi_ulong val;
3406 int idx;
3407
3408 switch(code) {
3409 case TARGET_ARCH_SET_GS:
3410 case TARGET_ARCH_SET_FS:
3411 if (code == TARGET_ARCH_SET_GS)
3412 idx = R_GS;
3413 else
3414 idx = R_FS;
3415 cpu_x86_load_seg(env, idx, 0);
3416 env->segs[idx].base = addr;
3417 break;
3418 case TARGET_ARCH_GET_GS:
3419 case TARGET_ARCH_GET_FS:
3420 if (code == TARGET_ARCH_GET_GS)
3421 idx = R_GS;
3422 else
3423 idx = R_FS;
3424 val = env->segs[idx].base;
3425 if (put_user(val, addr, abi_ulong))
3426 return -TARGET_EFAULT;
3427 break;
3428 default:
3429 ret = -TARGET_EINVAL;
3430 break;
3431 }
3432 return 0;
3433}
3434#endif
3435
bellard2ab83ea2003-06-15 19:56:46 +00003436#endif /* defined(TARGET_I386) */
3437
pbrookd865bab2008-06-07 22:12:17 +00003438#if defined(USE_NPTL)
3439
3440#define NEW_STACK_SIZE PTHREAD_STACK_MIN
3441
3442static pthread_mutex_t clone_lock = PTHREAD_MUTEX_INITIALIZER;
3443typedef struct {
3444 CPUState *env;
3445 pthread_mutex_t mutex;
3446 pthread_cond_t cond;
3447 pthread_t thread;
3448 uint32_t tid;
3449 abi_ulong child_tidptr;
3450 abi_ulong parent_tidptr;
3451 sigset_t sigmask;
3452} new_thread_info;
3453
3454static void *clone_func(void *arg)
3455{
3456 new_thread_info *info = arg;
3457 CPUState *env;
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03003458 TaskState *ts;
pbrookd865bab2008-06-07 22:12:17 +00003459
3460 env = info->env;
3461 thread_env = env;
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03003462 ts = (TaskState *)thread_env->opaque;
pbrookd865bab2008-06-07 22:12:17 +00003463 info->tid = gettid();
Nathan Froyd1e9fa732009-06-03 11:33:08 -07003464 env->host_tid = info->tid;
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03003465 task_settid(ts);
pbrookd865bab2008-06-07 22:12:17 +00003466 if (info->child_tidptr)
3467 put_user_u32(info->tid, info->child_tidptr);
3468 if (info->parent_tidptr)
3469 put_user_u32(info->tid, info->parent_tidptr);
3470 /* Enable signals. */
3471 sigprocmask(SIG_SETMASK, &info->sigmask, NULL);
3472 /* Signal to the parent that we're ready. */
3473 pthread_mutex_lock(&info->mutex);
3474 pthread_cond_broadcast(&info->cond);
3475 pthread_mutex_unlock(&info->mutex);
3476 /* Wait until the parent has finshed initializing the tls state. */
3477 pthread_mutex_lock(&clone_lock);
3478 pthread_mutex_unlock(&clone_lock);
3479 cpu_loop(env);
3480 /* never exits */
3481 return NULL;
3482}
3483#else
bellard1b6b0292003-03-22 17:31:38 +00003484/* this stack is the equivalent of the kernel stack associated with a
3485 thread/process */
3486#define NEW_STACK_SIZE 8192
3487
3488static int clone_func(void *arg)
3489{
bellard2ab83ea2003-06-15 19:56:46 +00003490 CPUState *env = arg;
bellard1b6b0292003-03-22 17:31:38 +00003491 cpu_loop(env);
3492 /* never exits */
3493 return 0;
3494}
pbrookd865bab2008-06-07 22:12:17 +00003495#endif
bellard1b6b0292003-03-22 17:31:38 +00003496
ths0da46a62007-10-20 20:23:07 +00003497/* do_fork() Must return host values and target errnos (unlike most
3498 do_*() functions). */
pbrookd865bab2008-06-07 22:12:17 +00003499static int do_fork(CPUState *env, unsigned int flags, abi_ulong newsp,
3500 abi_ulong parent_tidptr, target_ulong newtls,
3501 abi_ulong child_tidptr)
bellard1b6b0292003-03-22 17:31:38 +00003502{
3503 int ret;
bellard5cd43932003-03-29 16:54:36 +00003504 TaskState *ts;
bellard1b6b0292003-03-22 17:31:38 +00003505 uint8_t *new_stack;
bellard2ab83ea2003-06-15 19:56:46 +00003506 CPUState *new_env;
pbrookd865bab2008-06-07 22:12:17 +00003507#if defined(USE_NPTL)
3508 unsigned int nptl_flags;
3509 sigset_t sigmask;
3510#endif
ths3b46e622007-09-17 08:09:54 +00003511
balrog436d1242008-09-21 02:39:45 +00003512 /* Emulate vfork() with fork() */
3513 if (flags & CLONE_VFORK)
3514 flags &= ~(CLONE_VFORK | CLONE_VM);
3515
bellard1b6b0292003-03-22 17:31:38 +00003516 if (flags & CLONE_VM) {
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03003517 TaskState *parent_ts = (TaskState *)env->opaque;
pbrookbd0c5662008-05-29 14:34:11 +00003518#if defined(USE_NPTL)
pbrookd865bab2008-06-07 22:12:17 +00003519 new_thread_info info;
3520 pthread_attr_t attr;
pbrookbd0c5662008-05-29 14:34:11 +00003521#endif
pbrookc3a92832008-06-09 14:02:50 +00003522 ts = qemu_mallocz(sizeof(TaskState) + NEW_STACK_SIZE);
pbrook624f7972008-05-31 16:11:38 +00003523 init_task_state(ts);
bellard5cd43932003-03-29 16:54:36 +00003524 new_stack = ts->stack;
bellard1b6b0292003-03-22 17:31:38 +00003525 /* we create a new CPU instance. */
thsc5be9f02007-02-28 20:20:53 +00003526 new_env = cpu_copy(env);
pbrook6e68e072008-05-30 17:22:15 +00003527 /* Init regs that differ from the parent. */
3528 cpu_clone_regs(new_env, newsp);
bellard5cd43932003-03-29 16:54:36 +00003529 new_env->opaque = ts;
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03003530 ts->bprm = parent_ts->bprm;
3531 ts->info = parent_ts->info;
pbrookd865bab2008-06-07 22:12:17 +00003532#if defined(USE_NPTL)
3533 nptl_flags = flags;
3534 flags &= ~CLONE_NPTL_FLAGS2;
3535
pbrookc2764712009-03-07 15:24:59 +00003536 if (nptl_flags & CLONE_CHILD_CLEARTID) {
3537 ts->child_tidptr = child_tidptr;
3538 }
3539
pbrookd865bab2008-06-07 22:12:17 +00003540 if (nptl_flags & CLONE_SETTLS)
3541 cpu_set_tls (new_env, newtls);
3542
3543 /* Grab a mutex so that thread setup appears atomic. */
3544 pthread_mutex_lock(&clone_lock);
3545
3546 memset(&info, 0, sizeof(info));
3547 pthread_mutex_init(&info.mutex, NULL);
3548 pthread_mutex_lock(&info.mutex);
3549 pthread_cond_init(&info.cond, NULL);
3550 info.env = new_env;
3551 if (nptl_flags & CLONE_CHILD_SETTID)
3552 info.child_tidptr = child_tidptr;
3553 if (nptl_flags & CLONE_PARENT_SETTID)
3554 info.parent_tidptr = parent_tidptr;
3555
3556 ret = pthread_attr_init(&attr);
3557 ret = pthread_attr_setstack(&attr, new_stack, NEW_STACK_SIZE);
3558 /* It is not safe to deliver signals until the child has finished
3559 initializing, so temporarily block all signals. */
3560 sigfillset(&sigmask);
3561 sigprocmask(SIG_BLOCK, &sigmask, &info.sigmask);
3562
3563 ret = pthread_create(&info.thread, &attr, clone_func, &info);
pbrookc2764712009-03-07 15:24:59 +00003564 /* TODO: Free new CPU state if thread creation failed. */
pbrookd865bab2008-06-07 22:12:17 +00003565
3566 sigprocmask(SIG_SETMASK, &info.sigmask, NULL);
3567 pthread_attr_destroy(&attr);
3568 if (ret == 0) {
3569 /* Wait for the child to initialize. */
3570 pthread_cond_wait(&info.cond, &info.mutex);
3571 ret = info.tid;
3572 if (flags & CLONE_PARENT_SETTID)
3573 put_user_u32(ret, parent_tidptr);
3574 } else {
3575 ret = -1;
3576 }
3577 pthread_mutex_unlock(&info.mutex);
3578 pthread_cond_destroy(&info.cond);
3579 pthread_mutex_destroy(&info.mutex);
3580 pthread_mutex_unlock(&clone_lock);
3581#else
3582 if (flags & CLONE_NPTL_FLAGS2)
3583 return -EINVAL;
3584 /* This is probably going to die very quickly, but do it anyway. */
bellard27725c12003-04-29 21:08:18 +00003585#ifdef __ia64__
bellardfd4a43e2006-04-24 20:32:17 +00003586 ret = __clone2(clone_func, new_stack + NEW_STACK_SIZE, flags, new_env);
bellard27725c12003-04-29 21:08:18 +00003587#else
3588 ret = clone(clone_func, new_stack + NEW_STACK_SIZE, flags, new_env);
3589#endif
pbrookd865bab2008-06-07 22:12:17 +00003590#endif
bellard1b6b0292003-03-22 17:31:38 +00003591 } else {
3592 /* if no CLONE_VM, we consider it is a fork */
pbrookd865bab2008-06-07 22:12:17 +00003593 if ((flags & ~(CSIGNAL | CLONE_NPTL_FLAGS2)) != 0)
bellard1b6b0292003-03-22 17:31:38 +00003594 return -EINVAL;
pbrookd865bab2008-06-07 22:12:17 +00003595 fork_start();
bellard1b6b0292003-03-22 17:31:38 +00003596 ret = fork();
pbrookd865bab2008-06-07 22:12:17 +00003597 if (ret == 0) {
aurel322b1319c2008-12-18 22:44:04 +00003598 /* Child Process. */
pbrookd865bab2008-06-07 22:12:17 +00003599 cpu_clone_regs(env, newsp);
3600 fork_end(1);
aurel322b1319c2008-12-18 22:44:04 +00003601#if defined(USE_NPTL)
3602 /* There is a race condition here. The parent process could
3603 theoretically read the TID in the child process before the child
3604 tid is set. This would require using either ptrace
3605 (not implemented) or having *_tidptr to point at a shared memory
3606 mapping. We can't repeat the spinlock hack used above because
3607 the child process gets its own copy of the lock. */
pbrookd865bab2008-06-07 22:12:17 +00003608 if (flags & CLONE_CHILD_SETTID)
3609 put_user_u32(gettid(), child_tidptr);
3610 if (flags & CLONE_PARENT_SETTID)
3611 put_user_u32(gettid(), parent_tidptr);
3612 ts = (TaskState *)env->opaque;
3613 if (flags & CLONE_SETTLS)
3614 cpu_set_tls (env, newtls);
pbrookc2764712009-03-07 15:24:59 +00003615 if (flags & CLONE_CHILD_CLEARTID)
3616 ts->child_tidptr = child_tidptr;
aurel322b1319c2008-12-18 22:44:04 +00003617#endif
pbrookd865bab2008-06-07 22:12:17 +00003618 } else {
3619 fork_end(0);
3620 }
bellard1b6b0292003-03-22 17:31:38 +00003621 }
3622 return ret;
3623}
3624
blueswir1992f48a2007-10-14 16:27:31 +00003625static abi_long do_fcntl(int fd, int cmd, abi_ulong arg)
bellard7775e9e2003-05-14 22:46:48 +00003626{
3627 struct flock fl;
pbrook53a59602006-03-25 19:31:22 +00003628 struct target_flock *target_fl;
ths43f238d2007-01-05 20:55:49 +00003629 struct flock64 fl64;
3630 struct target_flock64 *target_fl64;
blueswir1992f48a2007-10-14 16:27:31 +00003631 abi_long ret;
pbrook53a59602006-03-25 19:31:22 +00003632
bellard7775e9e2003-05-14 22:46:48 +00003633 switch(cmd) {
3634 case TARGET_F_GETLK:
bellard579a97f2007-11-11 14:26:47 +00003635 if (!lock_user_struct(VERIFY_READ, target_fl, arg, 1))
3636 return -TARGET_EFAULT;
ths58134272007-03-31 18:59:32 +00003637 fl.l_type = tswap16(target_fl->l_type);
3638 fl.l_whence = tswap16(target_fl->l_whence);
3639 fl.l_start = tswapl(target_fl->l_start);
3640 fl.l_len = tswapl(target_fl->l_len);
3641 fl.l_pid = tswapl(target_fl->l_pid);
3642 unlock_user_struct(target_fl, arg, 0);
bellard9ee1fa22007-11-11 15:11:19 +00003643 ret = get_errno(fcntl(fd, cmd, &fl));
bellard7775e9e2003-05-14 22:46:48 +00003644 if (ret == 0) {
bellard579a97f2007-11-11 14:26:47 +00003645 if (!lock_user_struct(VERIFY_WRITE, target_fl, arg, 0))
3646 return -TARGET_EFAULT;
bellard7775e9e2003-05-14 22:46:48 +00003647 target_fl->l_type = tswap16(fl.l_type);
3648 target_fl->l_whence = tswap16(fl.l_whence);
3649 target_fl->l_start = tswapl(fl.l_start);
3650 target_fl->l_len = tswapl(fl.l_len);
3651 target_fl->l_pid = tswapl(fl.l_pid);
pbrook53a59602006-03-25 19:31:22 +00003652 unlock_user_struct(target_fl, arg, 1);
bellard7775e9e2003-05-14 22:46:48 +00003653 }
3654 break;
ths3b46e622007-09-17 08:09:54 +00003655
bellard7775e9e2003-05-14 22:46:48 +00003656 case TARGET_F_SETLK:
3657 case TARGET_F_SETLKW:
bellard579a97f2007-11-11 14:26:47 +00003658 if (!lock_user_struct(VERIFY_READ, target_fl, arg, 1))
3659 return -TARGET_EFAULT;
bellard7775e9e2003-05-14 22:46:48 +00003660 fl.l_type = tswap16(target_fl->l_type);
3661 fl.l_whence = tswap16(target_fl->l_whence);
3662 fl.l_start = tswapl(target_fl->l_start);
3663 fl.l_len = tswapl(target_fl->l_len);
3664 fl.l_pid = tswapl(target_fl->l_pid);
pbrook53a59602006-03-25 19:31:22 +00003665 unlock_user_struct(target_fl, arg, 0);
bellard9ee1fa22007-11-11 15:11:19 +00003666 ret = get_errno(fcntl(fd, cmd, &fl));
bellard7775e9e2003-05-14 22:46:48 +00003667 break;
ths3b46e622007-09-17 08:09:54 +00003668
bellard7775e9e2003-05-14 22:46:48 +00003669 case TARGET_F_GETLK64:
bellard579a97f2007-11-11 14:26:47 +00003670 if (!lock_user_struct(VERIFY_READ, target_fl64, arg, 1))
3671 return -TARGET_EFAULT;
ths58134272007-03-31 18:59:32 +00003672 fl64.l_type = tswap16(target_fl64->l_type) >> 1;
3673 fl64.l_whence = tswap16(target_fl64->l_whence);
3674 fl64.l_start = tswapl(target_fl64->l_start);
3675 fl64.l_len = tswapl(target_fl64->l_len);
3676 fl64.l_pid = tswap16(target_fl64->l_pid);
3677 unlock_user_struct(target_fl64, arg, 0);
bellard9ee1fa22007-11-11 15:11:19 +00003678 ret = get_errno(fcntl(fd, cmd >> 1, &fl64));
ths43f238d2007-01-05 20:55:49 +00003679 if (ret == 0) {
bellard579a97f2007-11-11 14:26:47 +00003680 if (!lock_user_struct(VERIFY_WRITE, target_fl64, arg, 0))
3681 return -TARGET_EFAULT;
ths43f238d2007-01-05 20:55:49 +00003682 target_fl64->l_type = tswap16(fl64.l_type) >> 1;
3683 target_fl64->l_whence = tswap16(fl64.l_whence);
3684 target_fl64->l_start = tswapl(fl64.l_start);
3685 target_fl64->l_len = tswapl(fl64.l_len);
3686 target_fl64->l_pid = tswapl(fl64.l_pid);
3687 unlock_user_struct(target_fl64, arg, 1);
3688 }
bellard9ee1fa22007-11-11 15:11:19 +00003689 break;
bellard7775e9e2003-05-14 22:46:48 +00003690 case TARGET_F_SETLK64:
3691 case TARGET_F_SETLKW64:
bellard579a97f2007-11-11 14:26:47 +00003692 if (!lock_user_struct(VERIFY_READ, target_fl64, arg, 1))
3693 return -TARGET_EFAULT;
ths43f238d2007-01-05 20:55:49 +00003694 fl64.l_type = tswap16(target_fl64->l_type) >> 1;
3695 fl64.l_whence = tswap16(target_fl64->l_whence);
3696 fl64.l_start = tswapl(target_fl64->l_start);
3697 fl64.l_len = tswapl(target_fl64->l_len);
3698 fl64.l_pid = tswap16(target_fl64->l_pid);
3699 unlock_user_struct(target_fl64, arg, 0);
bellard9ee1fa22007-11-11 15:11:19 +00003700 ret = get_errno(fcntl(fd, cmd >> 1, &fl64));
bellard7775e9e2003-05-14 22:46:48 +00003701 break;
3702
bellardffa65c32004-01-04 23:57:22 +00003703 case F_GETFL:
bellard9ee1fa22007-11-11 15:11:19 +00003704 ret = get_errno(fcntl(fd, cmd, arg));
3705 if (ret >= 0) {
3706 ret = host_to_target_bitmask(ret, fcntl_flags_tbl);
3707 }
bellardffa65c32004-01-04 23:57:22 +00003708 break;
3709
3710 case F_SETFL:
bellard9ee1fa22007-11-11 15:11:19 +00003711 ret = get_errno(fcntl(fd, cmd, target_to_host_bitmask(arg, fcntl_flags_tbl)));
bellardffa65c32004-01-04 23:57:22 +00003712 break;
3713
bellard7775e9e2003-05-14 22:46:48 +00003714 default:
bellard9ee1fa22007-11-11 15:11:19 +00003715 ret = get_errno(fcntl(fd, cmd, arg));
bellard7775e9e2003-05-14 22:46:48 +00003716 break;
3717 }
3718 return ret;
3719}
3720
bellard67867302003-11-23 17:05:30 +00003721#ifdef USE_UID16
bellard7775e9e2003-05-14 22:46:48 +00003722
bellard67867302003-11-23 17:05:30 +00003723static inline int high2lowuid(int uid)
3724{
3725 if (uid > 65535)
3726 return 65534;
3727 else
3728 return uid;
3729}
3730
3731static inline int high2lowgid(int gid)
3732{
3733 if (gid > 65535)
3734 return 65534;
3735 else
3736 return gid;
3737}
3738
3739static inline int low2highuid(int uid)
3740{
3741 if ((int16_t)uid == -1)
3742 return -1;
3743 else
3744 return uid;
3745}
3746
3747static inline int low2highgid(int gid)
3748{
3749 if ((int16_t)gid == -1)
3750 return -1;
3751 else
3752 return gid;
3753}
3754
3755#endif /* USE_UID16 */
bellard1b6b0292003-03-22 17:31:38 +00003756
bellard31e31b82003-02-18 22:55:36 +00003757void syscall_init(void)
3758{
bellard2ab83ea2003-06-15 19:56:46 +00003759 IOCTLEntry *ie;
3760 const argtype *arg_type;
3761 int size;
thsb92c47c2007-11-01 00:07:38 +00003762 int i;
bellard2ab83ea2003-06-15 19:56:46 +00003763
Blue Swirl001faf32009-05-13 17:53:17 +00003764#define STRUCT(name, ...) thunk_register_struct(STRUCT_ ## name, #name, struct_ ## name ## _def);
ths5fafdf22007-09-16 21:08:06 +00003765#define STRUCT_SPECIAL(name) thunk_register_struct_direct(STRUCT_ ## name, #name, &struct_ ## name ## _def);
bellard31e31b82003-02-18 22:55:36 +00003766#include "syscall_types.h"
3767#undef STRUCT
3768#undef STRUCT_SPECIAL
bellard2ab83ea2003-06-15 19:56:46 +00003769
3770 /* we patch the ioctl size if necessary. We rely on the fact that
3771 no ioctl has all the bits at '1' in the size field */
3772 ie = ioctl_entries;
3773 while (ie->target_cmd != 0) {
3774 if (((ie->target_cmd >> TARGET_IOC_SIZESHIFT) & TARGET_IOC_SIZEMASK) ==
3775 TARGET_IOC_SIZEMASK) {
3776 arg_type = ie->arg_type;
3777 if (arg_type[0] != TYPE_PTR) {
ths5fafdf22007-09-16 21:08:06 +00003778 fprintf(stderr, "cannot patch size for ioctl 0x%x\n",
bellard2ab83ea2003-06-15 19:56:46 +00003779 ie->target_cmd);
3780 exit(1);
3781 }
3782 arg_type++;
3783 size = thunk_type_size(arg_type, 0);
ths5fafdf22007-09-16 21:08:06 +00003784 ie->target_cmd = (ie->target_cmd &
bellard2ab83ea2003-06-15 19:56:46 +00003785 ~(TARGET_IOC_SIZEMASK << TARGET_IOC_SIZESHIFT)) |
3786 (size << TARGET_IOC_SIZESHIFT);
3787 }
thsb92c47c2007-11-01 00:07:38 +00003788
3789 /* Build target_to_host_errno_table[] table from
3790 * host_to_target_errno_table[]. */
3791 for (i=0; i < ERRNO_TABLE_SIZE; i++)
3792 target_to_host_errno_table[host_to_target_errno_table[i]] = i;
3793
bellard2ab83ea2003-06-15 19:56:46 +00003794 /* automatic consistency check if same arch */
balrog872ea0c2008-09-21 02:31:19 +00003795#if (defined(__i386__) && defined(TARGET_I386) && defined(TARGET_ABI32)) || \
3796 (defined(__x86_64__) && defined(TARGET_X86_64))
3797 if (unlikely(ie->target_cmd != ie->host_cmd)) {
3798 fprintf(stderr, "ERROR: ioctl(%s): target=0x%x host=0x%x\n",
3799 ie->name, ie->target_cmd, ie->host_cmd);
bellard2ab83ea2003-06-15 19:56:46 +00003800 }
3801#endif
3802 ie++;
3803 }
bellard31e31b82003-02-18 22:55:36 +00003804}
bellardc573ff62004-01-04 15:51:36 +00003805
blueswir1992f48a2007-10-14 16:27:31 +00003806#if TARGET_ABI_BITS == 32
pbrookce4defa2006-02-09 16:49:55 +00003807static inline uint64_t target_offset64(uint32_t word0, uint32_t word1)
3808{
thsaf325d32008-06-10 15:29:15 +00003809#ifdef TARGET_WORDS_BIGENDIAN
pbrookce4defa2006-02-09 16:49:55 +00003810 return ((uint64_t)word0 << 32) | word1;
3811#else
3812 return ((uint64_t)word1 << 32) | word0;
3813#endif
3814}
blueswir1992f48a2007-10-14 16:27:31 +00003815#else /* TARGET_ABI_BITS == 32 */
j_mayer32407102007-09-26 23:01:49 +00003816static inline uint64_t target_offset64(uint64_t word0, uint64_t word1)
3817{
3818 return word0;
3819}
blueswir1992f48a2007-10-14 16:27:31 +00003820#endif /* TARGET_ABI_BITS != 32 */
pbrookce4defa2006-02-09 16:49:55 +00003821
3822#ifdef TARGET_NR_truncate64
blueswir1992f48a2007-10-14 16:27:31 +00003823static inline abi_long target_truncate64(void *cpu_env, const char *arg1,
3824 abi_long arg2,
3825 abi_long arg3,
3826 abi_long arg4)
pbrookce4defa2006-02-09 16:49:55 +00003827{
3828#ifdef TARGET_ARM
3829 if (((CPUARMState *)cpu_env)->eabi)
3830 {
3831 arg2 = arg3;
3832 arg3 = arg4;
3833 }
3834#endif
3835 return get_errno(truncate64(arg1, target_offset64(arg2, arg3)));
3836}
3837#endif
3838
3839#ifdef TARGET_NR_ftruncate64
blueswir1992f48a2007-10-14 16:27:31 +00003840static inline abi_long target_ftruncate64(void *cpu_env, abi_long arg1,
3841 abi_long arg2,
3842 abi_long arg3,
3843 abi_long arg4)
pbrookce4defa2006-02-09 16:49:55 +00003844{
3845#ifdef TARGET_ARM
3846 if (((CPUARMState *)cpu_env)->eabi)
3847 {
3848 arg2 = arg3;
3849 arg3 = arg4;
3850 }
3851#endif
3852 return get_errno(ftruncate64(arg1, target_offset64(arg2, arg3)));
3853}
3854#endif
3855
bellard579a97f2007-11-11 14:26:47 +00003856static inline abi_long target_to_host_timespec(struct timespec *host_ts,
3857 abi_ulong target_addr)
pbrook53a59602006-03-25 19:31:22 +00003858{
3859 struct target_timespec *target_ts;
3860
bellard579a97f2007-11-11 14:26:47 +00003861 if (!lock_user_struct(VERIFY_READ, target_ts, target_addr, 1))
3862 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00003863 host_ts->tv_sec = tswapl(target_ts->tv_sec);
3864 host_ts->tv_nsec = tswapl(target_ts->tv_nsec);
3865 unlock_user_struct(target_ts, target_addr, 0);
bellardb255bfa2008-05-10 21:51:02 +00003866 return 0;
pbrook53a59602006-03-25 19:31:22 +00003867}
3868
bellard579a97f2007-11-11 14:26:47 +00003869static inline abi_long host_to_target_timespec(abi_ulong target_addr,
3870 struct timespec *host_ts)
pbrook53a59602006-03-25 19:31:22 +00003871{
3872 struct target_timespec *target_ts;
3873
bellard579a97f2007-11-11 14:26:47 +00003874 if (!lock_user_struct(VERIFY_WRITE, target_ts, target_addr, 0))
3875 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00003876 target_ts->tv_sec = tswapl(host_ts->tv_sec);
3877 target_ts->tv_nsec = tswapl(host_ts->tv_nsec);
3878 unlock_user_struct(target_ts, target_addr, 1);
bellardb255bfa2008-05-10 21:51:02 +00003879 return 0;
pbrook53a59602006-03-25 19:31:22 +00003880}
3881
aurel329d33b762009-04-08 23:07:05 +00003882#if defined(TARGET_NR_stat64) || defined(TARGET_NR_newfstatat)
balrog6a24a772008-09-20 02:23:36 +00003883static inline abi_long host_to_target_stat64(void *cpu_env,
3884 abi_ulong target_addr,
3885 struct stat *host_st)
3886{
3887#ifdef TARGET_ARM
3888 if (((CPUARMState *)cpu_env)->eabi) {
3889 struct target_eabi_stat64 *target_st;
3890
3891 if (!lock_user_struct(VERIFY_WRITE, target_st, target_addr, 0))
3892 return -TARGET_EFAULT;
3893 memset(target_st, 0, sizeof(struct target_eabi_stat64));
3894 __put_user(host_st->st_dev, &target_st->st_dev);
3895 __put_user(host_st->st_ino, &target_st->st_ino);
3896#ifdef TARGET_STAT64_HAS_BROKEN_ST_INO
3897 __put_user(host_st->st_ino, &target_st->__st_ino);
3898#endif
3899 __put_user(host_st->st_mode, &target_st->st_mode);
3900 __put_user(host_st->st_nlink, &target_st->st_nlink);
3901 __put_user(host_st->st_uid, &target_st->st_uid);
3902 __put_user(host_st->st_gid, &target_st->st_gid);
3903 __put_user(host_st->st_rdev, &target_st->st_rdev);
3904 __put_user(host_st->st_size, &target_st->st_size);
3905 __put_user(host_st->st_blksize, &target_st->st_blksize);
3906 __put_user(host_st->st_blocks, &target_st->st_blocks);
3907 __put_user(host_st->st_atime, &target_st->target_st_atime);
3908 __put_user(host_st->st_mtime, &target_st->target_st_mtime);
3909 __put_user(host_st->st_ctime, &target_st->target_st_ctime);
3910 unlock_user_struct(target_st, target_addr, 1);
3911 } else
3912#endif
3913 {
aurel329d33b762009-04-08 23:07:05 +00003914#if TARGET_LONG_BITS == 64
3915 struct target_stat *target_st;
3916#else
balrog6a24a772008-09-20 02:23:36 +00003917 struct target_stat64 *target_st;
aurel329d33b762009-04-08 23:07:05 +00003918#endif
balrog6a24a772008-09-20 02:23:36 +00003919
3920 if (!lock_user_struct(VERIFY_WRITE, target_st, target_addr, 0))
3921 return -TARGET_EFAULT;
aurel329d33b762009-04-08 23:07:05 +00003922 memset(target_st, 0, sizeof(*target_st));
balrog6a24a772008-09-20 02:23:36 +00003923 __put_user(host_st->st_dev, &target_st->st_dev);
3924 __put_user(host_st->st_ino, &target_st->st_ino);
3925#ifdef TARGET_STAT64_HAS_BROKEN_ST_INO
3926 __put_user(host_st->st_ino, &target_st->__st_ino);
3927#endif
3928 __put_user(host_st->st_mode, &target_st->st_mode);
3929 __put_user(host_st->st_nlink, &target_st->st_nlink);
3930 __put_user(host_st->st_uid, &target_st->st_uid);
3931 __put_user(host_st->st_gid, &target_st->st_gid);
3932 __put_user(host_st->st_rdev, &target_st->st_rdev);
3933 /* XXX: better use of kernel struct */
3934 __put_user(host_st->st_size, &target_st->st_size);
3935 __put_user(host_st->st_blksize, &target_st->st_blksize);
3936 __put_user(host_st->st_blocks, &target_st->st_blocks);
3937 __put_user(host_st->st_atime, &target_st->target_st_atime);
3938 __put_user(host_st->st_mtime, &target_st->target_st_mtime);
3939 __put_user(host_st->st_ctime, &target_st->target_st_ctime);
3940 unlock_user_struct(target_st, target_addr, 1);
3941 }
3942
3943 return 0;
3944}
3945#endif
3946
pbrookbd0c5662008-05-29 14:34:11 +00003947#if defined(USE_NPTL)
3948/* ??? Using host futex calls even when target atomic operations
3949 are not really atomic probably breaks things. However implementing
3950 futexes locally would make futexes shared between multiple processes
3951 tricky. However they're probably useless because guest atomic
3952 operations won't work either. */
blueswir18fcd3692008-08-17 20:26:25 +00003953static int do_futex(target_ulong uaddr, int op, int val, target_ulong timeout,
3954 target_ulong uaddr2, int val3)
pbrookbd0c5662008-05-29 14:34:11 +00003955{
3956 struct timespec ts, *pts;
3957
3958 /* ??? We assume FUTEX_* constants are the same on both host
3959 and target. */
Martin Mohringa29ccd62009-05-04 21:34:56 +03003960#ifdef FUTEX_CMD_MASK
3961 switch ((op&FUTEX_CMD_MASK)) {
3962#else
pbrookbd0c5662008-05-29 14:34:11 +00003963 switch (op) {
Martin Mohringa29ccd62009-05-04 21:34:56 +03003964#endif
pbrookbd0c5662008-05-29 14:34:11 +00003965 case FUTEX_WAIT:
3966 if (timeout) {
3967 pts = &ts;
3968 target_to_host_timespec(pts, timeout);
3969 } else {
3970 pts = NULL;
3971 }
Martin Mohringa29ccd62009-05-04 21:34:56 +03003972 return get_errno(sys_futex(g2h(uaddr), op, tswap32(val),
pbrookbd0c5662008-05-29 14:34:11 +00003973 pts, NULL, 0));
3974 case FUTEX_WAKE:
Martin Mohringa29ccd62009-05-04 21:34:56 +03003975 return get_errno(sys_futex(g2h(uaddr), op, val, NULL, NULL, 0));
Riku Voipioc4d23022009-05-28 12:13:41 +03003976 case FUTEX_WAKE_OP:
3977 return get_errno(sys_futex(g2h(uaddr), op, val, NULL, g2h(uaddr2), val3 ));
pbrookbd0c5662008-05-29 14:34:11 +00003978 case FUTEX_FD:
Martin Mohringa29ccd62009-05-04 21:34:56 +03003979 return get_errno(sys_futex(g2h(uaddr), op, val, NULL, NULL, 0));
pbrookbd0c5662008-05-29 14:34:11 +00003980 case FUTEX_REQUEUE:
Martin Mohringa29ccd62009-05-04 21:34:56 +03003981 return get_errno(sys_futex(g2h(uaddr), op, val,
pbrookbd0c5662008-05-29 14:34:11 +00003982 NULL, g2h(uaddr2), 0));
3983 case FUTEX_CMP_REQUEUE:
Martin Mohringa29ccd62009-05-04 21:34:56 +03003984 return get_errno(sys_futex(g2h(uaddr), op, val,
pbrookbd0c5662008-05-29 14:34:11 +00003985 NULL, g2h(uaddr2), tswap32(val3)));
3986 default:
3987 return -TARGET_ENOSYS;
3988 }
3989}
3990#endif
3991
pbrook1d9d8b52009-04-16 15:17:02 +00003992/* Map host to target signal numbers for the wait family of syscalls.
3993 Assume all other status bits are the same. */
3994static int host_to_target_waitstatus(int status)
3995{
3996 if (WIFSIGNALED(status)) {
3997 return host_to_target_signal(WTERMSIG(status)) | (status & ~0x7f);
3998 }
3999 if (WIFSTOPPED(status)) {
4000 return (host_to_target_signal(WSTOPSIG(status)) << 8)
4001 | (status & 0xff);
4002 }
4003 return status;
4004}
4005
pbrooka745ec62008-05-06 15:36:17 +00004006int get_osversion(void)
4007{
4008 static int osversion;
4009 struct new_utsname buf;
4010 const char *s;
4011 int i, n, tmp;
4012 if (osversion)
4013 return osversion;
4014 if (qemu_uname_release && *qemu_uname_release) {
4015 s = qemu_uname_release;
4016 } else {
4017 if (sys_uname(&buf))
4018 return 0;
4019 s = buf.release;
4020 }
4021 tmp = 0;
4022 for (i = 0; i < 3; i++) {
4023 n = 0;
4024 while (*s >= '0' && *s <= '9') {
4025 n *= 10;
4026 n += *s - '0';
4027 s++;
4028 }
4029 tmp = (tmp << 8) + n;
4030 if (*s == '.')
4031 s++;
4032 }
4033 osversion = tmp;
4034 return osversion;
4035}
4036
ths0da46a62007-10-20 20:23:07 +00004037/* do_syscall() should always have a single exit point at the end so
4038 that actions, such as logging of syscall results, can be performed.
4039 All errnos that do_syscall() returns must be -TARGET_<errcode>. */
blueswir1992f48a2007-10-14 16:27:31 +00004040abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
4041 abi_long arg2, abi_long arg3, abi_long arg4,
4042 abi_long arg5, abi_long arg6)
bellard31e31b82003-02-18 22:55:36 +00004043{
blueswir1992f48a2007-10-14 16:27:31 +00004044 abi_long ret;
bellard31e31b82003-02-18 22:55:36 +00004045 struct stat st;
bellard56c8f682005-11-28 22:28:41 +00004046 struct statfs stfs;
pbrook53a59602006-03-25 19:31:22 +00004047 void *p;
ths3b46e622007-09-17 08:09:54 +00004048
bellard72f03902003-02-18 23:33:18 +00004049#ifdef DEBUG
bellardc573ff62004-01-04 15:51:36 +00004050 gemu_log("syscall %d", num);
bellard72f03902003-02-18 23:33:18 +00004051#endif
thsb92c47c2007-11-01 00:07:38 +00004052 if(do_strace)
4053 print_syscall(num, arg1, arg2, arg3, arg4, arg5, arg6);
4054
bellard31e31b82003-02-18 22:55:36 +00004055 switch(num) {
4056 case TARGET_NR_exit:
pbrookc2764712009-03-07 15:24:59 +00004057#ifdef USE_NPTL
4058 /* In old applications this may be used to implement _exit(2).
4059 However in threaded applictions it is used for thread termination,
4060 and _exit_group is used for application termination.
4061 Do thread termination if we have more then one thread. */
4062 /* FIXME: This probably breaks if a signal arrives. We should probably
4063 be disabling signals. */
4064 if (first_cpu->next_cpu) {
Nathan Froyd1e9fa732009-06-03 11:33:08 -07004065 TaskState *ts;
pbrookc2764712009-03-07 15:24:59 +00004066 CPUState **lastp;
4067 CPUState *p;
4068
4069 cpu_list_lock();
4070 lastp = &first_cpu;
4071 p = first_cpu;
4072 while (p && p != (CPUState *)cpu_env) {
4073 lastp = &p->next_cpu;
4074 p = p->next_cpu;
4075 }
4076 /* If we didn't find the CPU for this thread then something is
4077 horribly wrong. */
4078 if (!p)
4079 abort();
4080 /* Remove the CPU from the list. */
4081 *lastp = p->next_cpu;
4082 cpu_list_unlock();
Nathan Froyd1e9fa732009-06-03 11:33:08 -07004083 ts = ((CPUState *)cpu_env)->opaque;
pbrookc2764712009-03-07 15:24:59 +00004084 if (ts->child_tidptr) {
4085 put_user_u32(0, ts->child_tidptr);
4086 sys_futex(g2h(ts->child_tidptr), FUTEX_WAKE, INT_MAX,
4087 NULL, NULL, 0);
4088 }
4089 /* TODO: Free CPU state. */
4090 pthread_exit(NULL);
4091 }
4092#endif
bellard7d132992003-03-06 23:23:54 +00004093#ifdef HAVE_GPROF
4094 _mcleanup();
4095#endif
bellarde9009672005-04-26 20:42:36 +00004096 gdb_exit(cpu_env, arg1);
pbrookc2764712009-03-07 15:24:59 +00004097 _exit(arg1);
bellard31e31b82003-02-18 22:55:36 +00004098 ret = 0; /* avoid warning */
4099 break;
4100 case TARGET_NR_read:
aurel3238d840e2009-01-30 19:48:17 +00004101 if (arg3 == 0)
4102 ret = 0;
4103 else {
4104 if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
4105 goto efault;
4106 ret = get_errno(read(arg1, p, arg3));
4107 unlock_user(p, arg2, ret);
4108 }
bellard31e31b82003-02-18 22:55:36 +00004109 break;
4110 case TARGET_NR_write:
bellard579a97f2007-11-11 14:26:47 +00004111 if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
4112 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004113 ret = get_errno(write(arg1, p, arg3));
4114 unlock_user(p, arg2, 0);
bellard31e31b82003-02-18 22:55:36 +00004115 break;
4116 case TARGET_NR_open:
bellard2f619692007-11-16 10:46:05 +00004117 if (!(p = lock_user_string(arg1)))
4118 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004119 ret = get_errno(open(path(p),
bellardffa65c32004-01-04 23:57:22 +00004120 target_to_host_bitmask(arg2, fcntl_flags_tbl),
4121 arg3));
pbrook53a59602006-03-25 19:31:22 +00004122 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004123 break;
ths82424832007-09-24 09:21:55 +00004124#if defined(TARGET_NR_openat) && defined(__NR_openat)
4125 case TARGET_NR_openat:
bellard579a97f2007-11-11 14:26:47 +00004126 if (!(p = lock_user_string(arg2)))
4127 goto efault;
4128 ret = get_errno(sys_openat(arg1,
4129 path(p),
4130 target_to_host_bitmask(arg3, fcntl_flags_tbl),
4131 arg4));
4132 unlock_user(p, arg2, 0);
ths82424832007-09-24 09:21:55 +00004133 break;
4134#endif
bellard31e31b82003-02-18 22:55:36 +00004135 case TARGET_NR_close:
4136 ret = get_errno(close(arg1));
4137 break;
4138 case TARGET_NR_brk:
pbrook53a59602006-03-25 19:31:22 +00004139 ret = do_brk(arg1);
bellard31e31b82003-02-18 22:55:36 +00004140 break;
4141 case TARGET_NR_fork:
pbrookd865bab2008-06-07 22:12:17 +00004142 ret = get_errno(do_fork(cpu_env, SIGCHLD, 0, 0, 0, 0));
bellard31e31b82003-02-18 22:55:36 +00004143 break;
thse5febef2007-04-01 18:31:35 +00004144#ifdef TARGET_NR_waitpid
bellard31e31b82003-02-18 22:55:36 +00004145 case TARGET_NR_waitpid:
4146 {
pbrook53a59602006-03-25 19:31:22 +00004147 int status;
4148 ret = get_errno(waitpid(arg1, &status, arg3));
bellard2f619692007-11-16 10:46:05 +00004149 if (!is_error(ret) && arg2
pbrook1d9d8b52009-04-16 15:17:02 +00004150 && put_user_s32(host_to_target_waitstatus(status), arg2))
bellard2f619692007-11-16 10:46:05 +00004151 goto efault;
bellard31e31b82003-02-18 22:55:36 +00004152 }
4153 break;
thse5febef2007-04-01 18:31:35 +00004154#endif
pbrookf0cbb612008-05-30 18:20:05 +00004155#ifdef TARGET_NR_waitid
4156 case TARGET_NR_waitid:
4157 {
4158 siginfo_t info;
4159 info.si_pid = 0;
4160 ret = get_errno(waitid(arg1, arg2, &info, arg4));
4161 if (!is_error(ret) && arg3 && info.si_pid != 0) {
4162 if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_siginfo_t), 0)))
4163 goto efault;
4164 host_to_target_siginfo(p, &info);
4165 unlock_user(p, arg3, sizeof(target_siginfo_t));
4166 }
4167 }
4168 break;
4169#endif
j_mayer7a3148a2007-04-05 07:13:51 +00004170#ifdef TARGET_NR_creat /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00004171 case TARGET_NR_creat:
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(creat(p, arg2));
4175 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004176 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004177#endif
bellard31e31b82003-02-18 22:55:36 +00004178 case TARGET_NR_link:
pbrook53a59602006-03-25 19:31:22 +00004179 {
4180 void * p2;
4181 p = lock_user_string(arg1);
4182 p2 = lock_user_string(arg2);
bellard579a97f2007-11-11 14:26:47 +00004183 if (!p || !p2)
4184 ret = -TARGET_EFAULT;
4185 else
4186 ret = get_errno(link(p, p2));
pbrook53a59602006-03-25 19:31:22 +00004187 unlock_user(p2, arg2, 0);
4188 unlock_user(p, arg1, 0);
4189 }
bellard31e31b82003-02-18 22:55:36 +00004190 break;
ths64f0ce42007-09-24 09:25:06 +00004191#if defined(TARGET_NR_linkat) && defined(__NR_linkat)
4192 case TARGET_NR_linkat:
ths64f0ce42007-09-24 09:25:06 +00004193 {
4194 void * p2 = NULL;
bellard579a97f2007-11-11 14:26:47 +00004195 if (!arg2 || !arg4)
4196 goto efault;
ths64f0ce42007-09-24 09:25:06 +00004197 p = lock_user_string(arg2);
4198 p2 = lock_user_string(arg4);
bellard579a97f2007-11-11 14:26:47 +00004199 if (!p || !p2)
ths0da46a62007-10-20 20:23:07 +00004200 ret = -TARGET_EFAULT;
ths64f0ce42007-09-24 09:25:06 +00004201 else
4202 ret = get_errno(sys_linkat(arg1, p, arg3, p2, arg5));
bellard579a97f2007-11-11 14:26:47 +00004203 unlock_user(p, arg2, 0);
4204 unlock_user(p2, arg4, 0);
ths64f0ce42007-09-24 09:25:06 +00004205 }
4206 break;
4207#endif
bellard31e31b82003-02-18 22:55:36 +00004208 case TARGET_NR_unlink:
bellard579a97f2007-11-11 14:26:47 +00004209 if (!(p = lock_user_string(arg1)))
4210 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004211 ret = get_errno(unlink(p));
4212 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004213 break;
ths8170f562007-09-24 09:24:11 +00004214#if defined(TARGET_NR_unlinkat) && defined(__NR_unlinkat)
4215 case TARGET_NR_unlinkat:
bellard579a97f2007-11-11 14:26:47 +00004216 if (!(p = lock_user_string(arg2)))
4217 goto efault;
4218 ret = get_errno(sys_unlinkat(arg1, p, arg3));
4219 unlock_user(p, arg2, 0);
balroged494d82007-12-11 23:23:52 +00004220 break;
balrogb7d35e62007-12-12 00:40:24 +00004221#endif
bellard31e31b82003-02-18 22:55:36 +00004222 case TARGET_NR_execve:
bellard7854b052003-03-29 17:22:23 +00004223 {
4224 char **argp, **envp;
bellardf7341ff2003-03-30 21:00:25 +00004225 int argc, envc;
blueswir1992f48a2007-10-14 16:27:31 +00004226 abi_ulong gp;
4227 abi_ulong guest_argp;
4228 abi_ulong guest_envp;
4229 abi_ulong addr;
bellard7854b052003-03-29 17:22:23 +00004230 char **q;
4231
bellardf7341ff2003-03-30 21:00:25 +00004232 argc = 0;
pbrook53a59602006-03-25 19:31:22 +00004233 guest_argp = arg2;
pbrookda94d262008-05-30 18:24:00 +00004234 for (gp = guest_argp; gp; gp += sizeof(abi_ulong)) {
ths03aa1972007-12-02 06:28:08 +00004235 if (get_user_ual(addr, gp))
bellard2f619692007-11-16 10:46:05 +00004236 goto efault;
ths03aa1972007-12-02 06:28:08 +00004237 if (!addr)
bellard2f619692007-11-16 10:46:05 +00004238 break;
bellard7854b052003-03-29 17:22:23 +00004239 argc++;
bellard2f619692007-11-16 10:46:05 +00004240 }
bellardf7341ff2003-03-30 21:00:25 +00004241 envc = 0;
pbrook53a59602006-03-25 19:31:22 +00004242 guest_envp = arg3;
pbrookda94d262008-05-30 18:24:00 +00004243 for (gp = guest_envp; gp; gp += sizeof(abi_ulong)) {
ths03aa1972007-12-02 06:28:08 +00004244 if (get_user_ual(addr, gp))
bellard2f619692007-11-16 10:46:05 +00004245 goto efault;
ths03aa1972007-12-02 06:28:08 +00004246 if (!addr)
bellard2f619692007-11-16 10:46:05 +00004247 break;
bellard7854b052003-03-29 17:22:23 +00004248 envc++;
bellard2f619692007-11-16 10:46:05 +00004249 }
bellard7854b052003-03-29 17:22:23 +00004250
bellardf7341ff2003-03-30 21:00:25 +00004251 argp = alloca((argc + 1) * sizeof(void *));
4252 envp = alloca((envc + 1) * sizeof(void *));
bellard7854b052003-03-29 17:22:23 +00004253
pbrookda94d262008-05-30 18:24:00 +00004254 for (gp = guest_argp, q = argp; gp;
blueswir1992f48a2007-10-14 16:27:31 +00004255 gp += sizeof(abi_ulong), q++) {
bellard2f619692007-11-16 10:46:05 +00004256 if (get_user_ual(addr, gp))
4257 goto execve_efault;
pbrook53a59602006-03-25 19:31:22 +00004258 if (!addr)
4259 break;
bellard2f619692007-11-16 10:46:05 +00004260 if (!(*q = lock_user_string(addr)))
4261 goto execve_efault;
pbrook53a59602006-03-25 19:31:22 +00004262 }
bellardf7341ff2003-03-30 21:00:25 +00004263 *q = NULL;
4264
pbrookda94d262008-05-30 18:24:00 +00004265 for (gp = guest_envp, q = envp; gp;
blueswir1992f48a2007-10-14 16:27:31 +00004266 gp += sizeof(abi_ulong), q++) {
bellard2f619692007-11-16 10:46:05 +00004267 if (get_user_ual(addr, gp))
4268 goto execve_efault;
pbrook53a59602006-03-25 19:31:22 +00004269 if (!addr)
4270 break;
bellard2f619692007-11-16 10:46:05 +00004271 if (!(*q = lock_user_string(addr)))
4272 goto execve_efault;
pbrook53a59602006-03-25 19:31:22 +00004273 }
bellardf7341ff2003-03-30 21:00:25 +00004274 *q = NULL;
bellard7854b052003-03-29 17:22:23 +00004275
bellard2f619692007-11-16 10:46:05 +00004276 if (!(p = lock_user_string(arg1)))
4277 goto execve_efault;
pbrook53a59602006-03-25 19:31:22 +00004278 ret = get_errno(execve(p, argp, envp));
4279 unlock_user(p, arg1, 0);
4280
bellard2f619692007-11-16 10:46:05 +00004281 goto execve_end;
4282
4283 execve_efault:
4284 ret = -TARGET_EFAULT;
4285
4286 execve_end:
pbrook53a59602006-03-25 19:31:22 +00004287 for (gp = guest_argp, q = argp; *q;
blueswir1992f48a2007-10-14 16:27:31 +00004288 gp += sizeof(abi_ulong), q++) {
bellard2f619692007-11-16 10:46:05 +00004289 if (get_user_ual(addr, gp)
4290 || !addr)
4291 break;
pbrook53a59602006-03-25 19:31:22 +00004292 unlock_user(*q, addr, 0);
4293 }
4294 for (gp = guest_envp, q = envp; *q;
blueswir1992f48a2007-10-14 16:27:31 +00004295 gp += sizeof(abi_ulong), q++) {
bellard2f619692007-11-16 10:46:05 +00004296 if (get_user_ual(addr, gp)
4297 || !addr)
4298 break;
pbrook53a59602006-03-25 19:31:22 +00004299 unlock_user(*q, addr, 0);
4300 }
bellard7854b052003-03-29 17:22:23 +00004301 }
bellard31e31b82003-02-18 22:55:36 +00004302 break;
4303 case TARGET_NR_chdir:
bellard579a97f2007-11-11 14:26:47 +00004304 if (!(p = lock_user_string(arg1)))
4305 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004306 ret = get_errno(chdir(p));
4307 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004308 break;
bellarda315a142005-01-30 22:59:18 +00004309#ifdef TARGET_NR_time
bellard31e31b82003-02-18 22:55:36 +00004310 case TARGET_NR_time:
4311 {
pbrook53a59602006-03-25 19:31:22 +00004312 time_t host_time;
4313 ret = get_errno(time(&host_time));
bellard2f619692007-11-16 10:46:05 +00004314 if (!is_error(ret)
4315 && arg1
4316 && put_user_sal(host_time, arg1))
4317 goto efault;
bellard31e31b82003-02-18 22:55:36 +00004318 }
4319 break;
bellarda315a142005-01-30 22:59:18 +00004320#endif
bellard31e31b82003-02-18 22:55:36 +00004321 case TARGET_NR_mknod:
bellard579a97f2007-11-11 14:26:47 +00004322 if (!(p = lock_user_string(arg1)))
4323 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004324 ret = get_errno(mknod(p, arg2, arg3));
4325 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004326 break;
ths75ac37a2007-09-24 09:23:05 +00004327#if defined(TARGET_NR_mknodat) && defined(__NR_mknodat)
4328 case TARGET_NR_mknodat:
bellard579a97f2007-11-11 14:26:47 +00004329 if (!(p = lock_user_string(arg2)))
4330 goto efault;
4331 ret = get_errno(sys_mknodat(arg1, p, arg3, arg4));
4332 unlock_user(p, arg2, 0);
ths75ac37a2007-09-24 09:23:05 +00004333 break;
4334#endif
bellard31e31b82003-02-18 22:55:36 +00004335 case TARGET_NR_chmod:
bellard579a97f2007-11-11 14:26:47 +00004336 if (!(p = lock_user_string(arg1)))
4337 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004338 ret = get_errno(chmod(p, arg2));
4339 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004340 break;
bellardebc05482003-09-30 21:08:41 +00004341#ifdef TARGET_NR_break
bellard31e31b82003-02-18 22:55:36 +00004342 case TARGET_NR_break:
4343 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004344#endif
4345#ifdef TARGET_NR_oldstat
bellard31e31b82003-02-18 22:55:36 +00004346 case TARGET_NR_oldstat:
4347 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004348#endif
bellard31e31b82003-02-18 22:55:36 +00004349 case TARGET_NR_lseek:
4350 ret = get_errno(lseek(arg1, arg2, arg3));
4351 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004352#ifdef TARGET_NR_getxpid
4353 case TARGET_NR_getxpid:
4354#else
bellard31e31b82003-02-18 22:55:36 +00004355 case TARGET_NR_getpid:
j_mayer7a3148a2007-04-05 07:13:51 +00004356#endif
bellard31e31b82003-02-18 22:55:36 +00004357 ret = get_errno(getpid());
4358 break;
4359 case TARGET_NR_mount:
ths80265912007-02-17 22:25:41 +00004360 {
4361 /* need to look at the data field */
4362 void *p2, *p3;
4363 p = lock_user_string(arg1);
4364 p2 = lock_user_string(arg2);
4365 p3 = lock_user_string(arg3);
bellard579a97f2007-11-11 14:26:47 +00004366 if (!p || !p2 || !p3)
4367 ret = -TARGET_EFAULT;
4368 else
4369 /* FIXME - arg5 should be locked, but it isn't clear how to
4370 * do that since it's not guaranteed to be a NULL-terminated
4371 * string.
4372 */
4373 ret = get_errno(mount(p, p2, p3, (unsigned long)arg4, g2h(arg5)));
4374 unlock_user(p, arg1, 0);
4375 unlock_user(p2, arg2, 0);
4376 unlock_user(p3, arg3, 0);
ths80265912007-02-17 22:25:41 +00004377 break;
4378 }
thse5febef2007-04-01 18:31:35 +00004379#ifdef TARGET_NR_umount
bellard31e31b82003-02-18 22:55:36 +00004380 case TARGET_NR_umount:
bellard579a97f2007-11-11 14:26:47 +00004381 if (!(p = lock_user_string(arg1)))
4382 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004383 ret = get_errno(umount(p));
4384 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004385 break;
thse5febef2007-04-01 18:31:35 +00004386#endif
j_mayer7a3148a2007-04-05 07:13:51 +00004387#ifdef TARGET_NR_stime /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00004388 case TARGET_NR_stime:
4389 {
pbrook53a59602006-03-25 19:31:22 +00004390 time_t host_time;
bellard2f619692007-11-16 10:46:05 +00004391 if (get_user_sal(host_time, arg1))
4392 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004393 ret = get_errno(stime(&host_time));
bellard31e31b82003-02-18 22:55:36 +00004394 }
4395 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004396#endif
bellard31e31b82003-02-18 22:55:36 +00004397 case TARGET_NR_ptrace:
4398 goto unimplemented;
j_mayer7a3148a2007-04-05 07:13:51 +00004399#ifdef TARGET_NR_alarm /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00004400 case TARGET_NR_alarm:
4401 ret = alarm(arg1);
4402 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004403#endif
bellardebc05482003-09-30 21:08:41 +00004404#ifdef TARGET_NR_oldfstat
bellard31e31b82003-02-18 22:55:36 +00004405 case TARGET_NR_oldfstat:
4406 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004407#endif
j_mayer7a3148a2007-04-05 07:13:51 +00004408#ifdef TARGET_NR_pause /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00004409 case TARGET_NR_pause:
4410 ret = get_errno(pause());
4411 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004412#endif
thse5febef2007-04-01 18:31:35 +00004413#ifdef TARGET_NR_utime
bellard31e31b82003-02-18 22:55:36 +00004414 case TARGET_NR_utime:
bellardebc05482003-09-30 21:08:41 +00004415 {
pbrook53a59602006-03-25 19:31:22 +00004416 struct utimbuf tbuf, *host_tbuf;
4417 struct target_utimbuf *target_tbuf;
4418 if (arg2) {
bellard579a97f2007-11-11 14:26:47 +00004419 if (!lock_user_struct(VERIFY_READ, target_tbuf, arg2, 1))
4420 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004421 tbuf.actime = tswapl(target_tbuf->actime);
4422 tbuf.modtime = tswapl(target_tbuf->modtime);
4423 unlock_user_struct(target_tbuf, arg2, 0);
4424 host_tbuf = &tbuf;
bellardf72e8ff2004-05-03 19:23:07 +00004425 } else {
pbrook53a59602006-03-25 19:31:22 +00004426 host_tbuf = NULL;
bellardf72e8ff2004-05-03 19:23:07 +00004427 }
bellard579a97f2007-11-11 14:26:47 +00004428 if (!(p = lock_user_string(arg1)))
4429 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004430 ret = get_errno(utime(p, host_tbuf));
4431 unlock_user(p, arg1, 0);
bellardebc05482003-09-30 21:08:41 +00004432 }
4433 break;
thse5febef2007-04-01 18:31:35 +00004434#endif
bellard978a66f2004-12-06 22:58:05 +00004435 case TARGET_NR_utimes:
4436 {
bellard978a66f2004-12-06 22:58:05 +00004437 struct timeval *tvp, tv[2];
pbrook53a59602006-03-25 19:31:22 +00004438 if (arg2) {
ths788f5ec2007-12-09 02:37:05 +00004439 if (copy_from_user_timeval(&tv[0], arg2)
4440 || copy_from_user_timeval(&tv[1],
4441 arg2 + sizeof(struct target_timeval)))
4442 goto efault;
bellard978a66f2004-12-06 22:58:05 +00004443 tvp = tv;
4444 } else {
4445 tvp = NULL;
4446 }
bellard579a97f2007-11-11 14:26:47 +00004447 if (!(p = lock_user_string(arg1)))
4448 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004449 ret = get_errno(utimes(p, tvp));
4450 unlock_user(p, arg1, 0);
bellard978a66f2004-12-06 22:58:05 +00004451 }
4452 break;
balrogac8a6552008-09-20 02:25:39 +00004453#if defined(TARGET_NR_futimesat) && defined(__NR_futimesat)
4454 case TARGET_NR_futimesat:
4455 {
4456 struct timeval *tvp, tv[2];
4457 if (arg3) {
4458 if (copy_from_user_timeval(&tv[0], arg3)
4459 || copy_from_user_timeval(&tv[1],
4460 arg3 + sizeof(struct target_timeval)))
4461 goto efault;
4462 tvp = tv;
4463 } else {
4464 tvp = NULL;
4465 }
4466 if (!(p = lock_user_string(arg2)))
4467 goto efault;
4468 ret = get_errno(sys_futimesat(arg1, path(p), tvp));
4469 unlock_user(p, arg2, 0);
4470 }
4471 break;
4472#endif
bellardebc05482003-09-30 21:08:41 +00004473#ifdef TARGET_NR_stty
bellard31e31b82003-02-18 22:55:36 +00004474 case TARGET_NR_stty:
4475 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004476#endif
4477#ifdef TARGET_NR_gtty
bellard31e31b82003-02-18 22:55:36 +00004478 case TARGET_NR_gtty:
4479 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004480#endif
bellard31e31b82003-02-18 22:55:36 +00004481 case TARGET_NR_access:
bellard579a97f2007-11-11 14:26:47 +00004482 if (!(p = lock_user_string(arg1)))
4483 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004484 ret = get_errno(access(p, arg2));
4485 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004486 break;
ths92a34c12007-09-24 09:27:49 +00004487#if defined(TARGET_NR_faccessat) && defined(__NR_faccessat)
4488 case TARGET_NR_faccessat:
bellard579a97f2007-11-11 14:26:47 +00004489 if (!(p = lock_user_string(arg2)))
4490 goto efault;
aurel32465c9f02009-04-19 08:52:17 +00004491 ret = get_errno(sys_faccessat(arg1, p, arg3));
bellard579a97f2007-11-11 14:26:47 +00004492 unlock_user(p, arg2, 0);
ths92a34c12007-09-24 09:27:49 +00004493 break;
4494#endif
j_mayer7a3148a2007-04-05 07:13:51 +00004495#ifdef TARGET_NR_nice /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00004496 case TARGET_NR_nice:
4497 ret = get_errno(nice(arg1));
4498 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004499#endif
bellardebc05482003-09-30 21:08:41 +00004500#ifdef TARGET_NR_ftime
bellard31e31b82003-02-18 22:55:36 +00004501 case TARGET_NR_ftime:
4502 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004503#endif
bellard31e31b82003-02-18 22:55:36 +00004504 case TARGET_NR_sync:
bellard04369ff2003-03-20 22:33:23 +00004505 sync();
4506 ret = 0;
bellard31e31b82003-02-18 22:55:36 +00004507 break;
4508 case TARGET_NR_kill:
pbrook4cb05962008-05-30 18:05:19 +00004509 ret = get_errno(kill(arg1, target_to_host_signal(arg2)));
bellard31e31b82003-02-18 22:55:36 +00004510 break;
4511 case TARGET_NR_rename:
pbrook53a59602006-03-25 19:31:22 +00004512 {
4513 void *p2;
4514 p = lock_user_string(arg1);
4515 p2 = lock_user_string(arg2);
bellard579a97f2007-11-11 14:26:47 +00004516 if (!p || !p2)
4517 ret = -TARGET_EFAULT;
4518 else
4519 ret = get_errno(rename(p, p2));
pbrook53a59602006-03-25 19:31:22 +00004520 unlock_user(p2, arg2, 0);
4521 unlock_user(p, arg1, 0);
4522 }
bellard31e31b82003-02-18 22:55:36 +00004523 break;
ths722183f2007-09-24 09:24:37 +00004524#if defined(TARGET_NR_renameat) && defined(__NR_renameat)
4525 case TARGET_NR_renameat:
ths722183f2007-09-24 09:24:37 +00004526 {
bellard579a97f2007-11-11 14:26:47 +00004527 void *p2;
ths722183f2007-09-24 09:24:37 +00004528 p = lock_user_string(arg2);
4529 p2 = lock_user_string(arg4);
bellard579a97f2007-11-11 14:26:47 +00004530 if (!p || !p2)
ths0da46a62007-10-20 20:23:07 +00004531 ret = -TARGET_EFAULT;
ths722183f2007-09-24 09:24:37 +00004532 else
4533 ret = get_errno(sys_renameat(arg1, p, arg3, p2));
bellard579a97f2007-11-11 14:26:47 +00004534 unlock_user(p2, arg4, 0);
4535 unlock_user(p, arg2, 0);
ths722183f2007-09-24 09:24:37 +00004536 }
4537 break;
4538#endif
bellard31e31b82003-02-18 22:55:36 +00004539 case TARGET_NR_mkdir:
bellard579a97f2007-11-11 14:26:47 +00004540 if (!(p = lock_user_string(arg1)))
4541 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004542 ret = get_errno(mkdir(p, arg2));
4543 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004544 break;
ths4472ad02007-09-24 09:22:32 +00004545#if defined(TARGET_NR_mkdirat) && defined(__NR_mkdirat)
4546 case TARGET_NR_mkdirat:
bellard579a97f2007-11-11 14:26:47 +00004547 if (!(p = lock_user_string(arg2)))
4548 goto efault;
4549 ret = get_errno(sys_mkdirat(arg1, p, arg3));
4550 unlock_user(p, arg2, 0);
ths4472ad02007-09-24 09:22:32 +00004551 break;
4552#endif
bellard31e31b82003-02-18 22:55:36 +00004553 case TARGET_NR_rmdir:
bellard579a97f2007-11-11 14:26:47 +00004554 if (!(p = lock_user_string(arg1)))
4555 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004556 ret = get_errno(rmdir(p));
4557 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004558 break;
4559 case TARGET_NR_dup:
4560 ret = get_errno(dup(arg1));
4561 break;
4562 case TARGET_NR_pipe:
Riku Voipio099d6b02009-05-05 12:10:04 +03004563 ret = do_pipe(cpu_env, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004564 break;
Riku Voipio099d6b02009-05-05 12:10:04 +03004565#ifdef TARGET_NR_pipe2
4566 case TARGET_NR_pipe2:
4567 ret = do_pipe(cpu_env, arg1, arg2);
4568 break;
4569#endif
bellard31e31b82003-02-18 22:55:36 +00004570 case TARGET_NR_times:
bellard32f36bc2003-03-30 21:29:48 +00004571 {
pbrook53a59602006-03-25 19:31:22 +00004572 struct target_tms *tmsp;
bellard32f36bc2003-03-30 21:29:48 +00004573 struct tms tms;
4574 ret = get_errno(times(&tms));
pbrook53a59602006-03-25 19:31:22 +00004575 if (arg1) {
bellard579a97f2007-11-11 14:26:47 +00004576 tmsp = lock_user(VERIFY_WRITE, arg1, sizeof(struct target_tms), 0);
4577 if (!tmsp)
4578 goto efault;
bellardc596ed12003-07-13 17:32:31 +00004579 tmsp->tms_utime = tswapl(host_to_target_clock_t(tms.tms_utime));
4580 tmsp->tms_stime = tswapl(host_to_target_clock_t(tms.tms_stime));
4581 tmsp->tms_cutime = tswapl(host_to_target_clock_t(tms.tms_cutime));
4582 tmsp->tms_cstime = tswapl(host_to_target_clock_t(tms.tms_cstime));
bellard32f36bc2003-03-30 21:29:48 +00004583 }
bellardc596ed12003-07-13 17:32:31 +00004584 if (!is_error(ret))
4585 ret = host_to_target_clock_t(ret);
bellard32f36bc2003-03-30 21:29:48 +00004586 }
4587 break;
bellardebc05482003-09-30 21:08:41 +00004588#ifdef TARGET_NR_prof
bellard31e31b82003-02-18 22:55:36 +00004589 case TARGET_NR_prof:
4590 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004591#endif
thse5febef2007-04-01 18:31:35 +00004592#ifdef TARGET_NR_signal
bellard31e31b82003-02-18 22:55:36 +00004593 case TARGET_NR_signal:
4594 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00004595#endif
bellard31e31b82003-02-18 22:55:36 +00004596 case TARGET_NR_acct:
aurel3238d840e2009-01-30 19:48:17 +00004597 if (arg1 == 0) {
4598 ret = get_errno(acct(NULL));
4599 } else {
4600 if (!(p = lock_user_string(arg1)))
4601 goto efault;
4602 ret = get_errno(acct(path(p)));
4603 unlock_user(p, arg1, 0);
4604 }
pbrook24836682006-04-16 14:14:53 +00004605 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004606#ifdef TARGET_NR_umount2 /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00004607 case TARGET_NR_umount2:
bellard579a97f2007-11-11 14:26:47 +00004608 if (!(p = lock_user_string(arg1)))
4609 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004610 ret = get_errno(umount2(p, arg2));
4611 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004612 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004613#endif
bellardebc05482003-09-30 21:08:41 +00004614#ifdef TARGET_NR_lock
bellard31e31b82003-02-18 22:55:36 +00004615 case TARGET_NR_lock:
4616 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004617#endif
bellard31e31b82003-02-18 22:55:36 +00004618 case TARGET_NR_ioctl:
4619 ret = do_ioctl(arg1, arg2, arg3);
4620 break;
4621 case TARGET_NR_fcntl:
bellard9ee1fa22007-11-11 15:11:19 +00004622 ret = do_fcntl(arg1, arg2, arg3);
bellard31e31b82003-02-18 22:55:36 +00004623 break;
bellardebc05482003-09-30 21:08:41 +00004624#ifdef TARGET_NR_mpx
bellard31e31b82003-02-18 22:55:36 +00004625 case TARGET_NR_mpx:
4626 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004627#endif
bellard31e31b82003-02-18 22:55:36 +00004628 case TARGET_NR_setpgid:
4629 ret = get_errno(setpgid(arg1, arg2));
4630 break;
bellardebc05482003-09-30 21:08:41 +00004631#ifdef TARGET_NR_ulimit
bellard31e31b82003-02-18 22:55:36 +00004632 case TARGET_NR_ulimit:
4633 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004634#endif
4635#ifdef TARGET_NR_oldolduname
bellard31e31b82003-02-18 22:55:36 +00004636 case TARGET_NR_oldolduname:
4637 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004638#endif
bellard31e31b82003-02-18 22:55:36 +00004639 case TARGET_NR_umask:
4640 ret = get_errno(umask(arg1));
4641 break;
4642 case TARGET_NR_chroot:
bellard579a97f2007-11-11 14:26:47 +00004643 if (!(p = lock_user_string(arg1)))
4644 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004645 ret = get_errno(chroot(p));
4646 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004647 break;
4648 case TARGET_NR_ustat:
4649 goto unimplemented;
4650 case TARGET_NR_dup2:
4651 ret = get_errno(dup2(arg1, arg2));
4652 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004653#ifdef TARGET_NR_getppid /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00004654 case TARGET_NR_getppid:
4655 ret = get_errno(getppid());
4656 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004657#endif
bellard31e31b82003-02-18 22:55:36 +00004658 case TARGET_NR_getpgrp:
4659 ret = get_errno(getpgrp());
4660 break;
4661 case TARGET_NR_setsid:
4662 ret = get_errno(setsid());
4663 break;
thse5febef2007-04-01 18:31:35 +00004664#ifdef TARGET_NR_sigaction
bellard31e31b82003-02-18 22:55:36 +00004665 case TARGET_NR_sigaction:
bellard31e31b82003-02-18 22:55:36 +00004666 {
ths388bb212007-05-13 13:58:00 +00004667#if !defined(TARGET_MIPS)
pbrook53a59602006-03-25 19:31:22 +00004668 struct target_old_sigaction *old_act;
bellard66fb9762003-03-23 01:06:05 +00004669 struct target_sigaction act, oact, *pact;
pbrook53a59602006-03-25 19:31:22 +00004670 if (arg2) {
bellard579a97f2007-11-11 14:26:47 +00004671 if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1))
4672 goto efault;
bellard66fb9762003-03-23 01:06:05 +00004673 act._sa_handler = old_act->_sa_handler;
4674 target_siginitset(&act.sa_mask, old_act->sa_mask);
4675 act.sa_flags = old_act->sa_flags;
4676 act.sa_restorer = old_act->sa_restorer;
pbrook53a59602006-03-25 19:31:22 +00004677 unlock_user_struct(old_act, arg2, 0);
bellard66fb9762003-03-23 01:06:05 +00004678 pact = &act;
4679 } else {
4680 pact = NULL;
4681 }
4682 ret = get_errno(do_sigaction(arg1, pact, &oact));
pbrook53a59602006-03-25 19:31:22 +00004683 if (!is_error(ret) && arg3) {
bellard579a97f2007-11-11 14:26:47 +00004684 if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0))
4685 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004686 old_act->_sa_handler = oact._sa_handler;
4687 old_act->sa_mask = oact.sa_mask.sig[0];
4688 old_act->sa_flags = oact.sa_flags;
4689 old_act->sa_restorer = oact.sa_restorer;
4690 unlock_user_struct(old_act, arg3, 1);
bellard66fb9762003-03-23 01:06:05 +00004691 }
ths388bb212007-05-13 13:58:00 +00004692#else
bellard106ec872006-06-27 21:08:10 +00004693 struct target_sigaction act, oact, *pact, *old_act;
4694
4695 if (arg2) {
bellard579a97f2007-11-11 14:26:47 +00004696 if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1))
4697 goto efault;
bellard106ec872006-06-27 21:08:10 +00004698 act._sa_handler = old_act->_sa_handler;
4699 target_siginitset(&act.sa_mask, old_act->sa_mask.sig[0]);
4700 act.sa_flags = old_act->sa_flags;
4701 unlock_user_struct(old_act, arg2, 0);
4702 pact = &act;
4703 } else {
4704 pact = NULL;
4705 }
4706
4707 ret = get_errno(do_sigaction(arg1, pact, &oact));
4708
4709 if (!is_error(ret) && arg3) {
bellard579a97f2007-11-11 14:26:47 +00004710 if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0))
4711 goto efault;
bellard106ec872006-06-27 21:08:10 +00004712 old_act->_sa_handler = oact._sa_handler;
4713 old_act->sa_flags = oact.sa_flags;
4714 old_act->sa_mask.sig[0] = oact.sa_mask.sig[0];
4715 old_act->sa_mask.sig[1] = 0;
4716 old_act->sa_mask.sig[2] = 0;
4717 old_act->sa_mask.sig[3] = 0;
4718 unlock_user_struct(old_act, arg3, 1);
4719 }
ths388bb212007-05-13 13:58:00 +00004720#endif
bellard31e31b82003-02-18 22:55:36 +00004721 }
4722 break;
thse5febef2007-04-01 18:31:35 +00004723#endif
bellard66fb9762003-03-23 01:06:05 +00004724 case TARGET_NR_rt_sigaction:
pbrook53a59602006-03-25 19:31:22 +00004725 {
4726 struct target_sigaction *act;
4727 struct target_sigaction *oact;
4728
bellard579a97f2007-11-11 14:26:47 +00004729 if (arg2) {
4730 if (!lock_user_struct(VERIFY_READ, act, arg2, 1))
4731 goto efault;
4732 } else
pbrook53a59602006-03-25 19:31:22 +00004733 act = NULL;
bellard579a97f2007-11-11 14:26:47 +00004734 if (arg3) {
4735 if (!lock_user_struct(VERIFY_WRITE, oact, arg3, 0)) {
4736 ret = -TARGET_EFAULT;
4737 goto rt_sigaction_fail;
4738 }
4739 } else
pbrook53a59602006-03-25 19:31:22 +00004740 oact = NULL;
4741 ret = get_errno(do_sigaction(arg1, act, oact));
bellard579a97f2007-11-11 14:26:47 +00004742 rt_sigaction_fail:
4743 if (act)
pbrook53a59602006-03-25 19:31:22 +00004744 unlock_user_struct(act, arg2, 0);
bellard579a97f2007-11-11 14:26:47 +00004745 if (oact)
pbrook53a59602006-03-25 19:31:22 +00004746 unlock_user_struct(oact, arg3, 1);
4747 }
bellard66fb9762003-03-23 01:06:05 +00004748 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004749#ifdef TARGET_NR_sgetmask /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00004750 case TARGET_NR_sgetmask:
bellard66fb9762003-03-23 01:06:05 +00004751 {
4752 sigset_t cur_set;
blueswir1992f48a2007-10-14 16:27:31 +00004753 abi_ulong target_set;
bellard66fb9762003-03-23 01:06:05 +00004754 sigprocmask(0, NULL, &cur_set);
4755 host_to_target_old_sigset(&target_set, &cur_set);
4756 ret = target_set;
4757 }
4758 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004759#endif
4760#ifdef TARGET_NR_ssetmask /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00004761 case TARGET_NR_ssetmask:
bellard66fb9762003-03-23 01:06:05 +00004762 {
4763 sigset_t set, oset, cur_set;
blueswir1992f48a2007-10-14 16:27:31 +00004764 abi_ulong target_set = arg1;
bellard66fb9762003-03-23 01:06:05 +00004765 sigprocmask(0, NULL, &cur_set);
4766 target_to_host_old_sigset(&set, &target_set);
4767 sigorset(&set, &set, &cur_set);
4768 sigprocmask(SIG_SETMASK, &set, &oset);
4769 host_to_target_old_sigset(&target_set, &oset);
4770 ret = target_set;
4771 }
4772 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004773#endif
thse5febef2007-04-01 18:31:35 +00004774#ifdef TARGET_NR_sigprocmask
bellard66fb9762003-03-23 01:06:05 +00004775 case TARGET_NR_sigprocmask:
4776 {
4777 int how = arg1;
4778 sigset_t set, oldset, *set_ptr;
ths3b46e622007-09-17 08:09:54 +00004779
pbrook53a59602006-03-25 19:31:22 +00004780 if (arg2) {
bellard66fb9762003-03-23 01:06:05 +00004781 switch(how) {
4782 case TARGET_SIG_BLOCK:
4783 how = SIG_BLOCK;
4784 break;
4785 case TARGET_SIG_UNBLOCK:
4786 how = SIG_UNBLOCK;
4787 break;
4788 case TARGET_SIG_SETMASK:
4789 how = SIG_SETMASK;
4790 break;
4791 default:
ths0da46a62007-10-20 20:23:07 +00004792 ret = -TARGET_EINVAL;
bellard66fb9762003-03-23 01:06:05 +00004793 goto fail;
4794 }
bellard579a97f2007-11-11 14:26:47 +00004795 if (!(p = lock_user(VERIFY_READ, arg2, sizeof(target_sigset_t), 1)))
4796 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004797 target_to_host_old_sigset(&set, p);
4798 unlock_user(p, arg2, 0);
bellard66fb9762003-03-23 01:06:05 +00004799 set_ptr = &set;
4800 } else {
4801 how = 0;
4802 set_ptr = NULL;
4803 }
4804 ret = get_errno(sigprocmask(arg1, set_ptr, &oldset));
pbrook53a59602006-03-25 19:31:22 +00004805 if (!is_error(ret) && arg3) {
bellard579a97f2007-11-11 14:26:47 +00004806 if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0)))
4807 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004808 host_to_target_old_sigset(p, &oldset);
4809 unlock_user(p, arg3, sizeof(target_sigset_t));
bellard66fb9762003-03-23 01:06:05 +00004810 }
4811 }
4812 break;
thse5febef2007-04-01 18:31:35 +00004813#endif
bellard66fb9762003-03-23 01:06:05 +00004814 case TARGET_NR_rt_sigprocmask:
4815 {
4816 int how = arg1;
4817 sigset_t set, oldset, *set_ptr;
ths3b46e622007-09-17 08:09:54 +00004818
pbrook53a59602006-03-25 19:31:22 +00004819 if (arg2) {
bellard66fb9762003-03-23 01:06:05 +00004820 switch(how) {
4821 case TARGET_SIG_BLOCK:
4822 how = SIG_BLOCK;
4823 break;
4824 case TARGET_SIG_UNBLOCK:
4825 how = SIG_UNBLOCK;
4826 break;
4827 case TARGET_SIG_SETMASK:
4828 how = SIG_SETMASK;
4829 break;
4830 default:
ths0da46a62007-10-20 20:23:07 +00004831 ret = -TARGET_EINVAL;
bellard66fb9762003-03-23 01:06:05 +00004832 goto fail;
4833 }
bellard579a97f2007-11-11 14:26:47 +00004834 if (!(p = lock_user(VERIFY_READ, arg2, sizeof(target_sigset_t), 1)))
4835 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004836 target_to_host_sigset(&set, p);
4837 unlock_user(p, arg2, 0);
bellard66fb9762003-03-23 01:06:05 +00004838 set_ptr = &set;
4839 } else {
4840 how = 0;
4841 set_ptr = NULL;
4842 }
4843 ret = get_errno(sigprocmask(how, set_ptr, &oldset));
pbrook53a59602006-03-25 19:31:22 +00004844 if (!is_error(ret) && arg3) {
bellard579a97f2007-11-11 14:26:47 +00004845 if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0)))
4846 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004847 host_to_target_sigset(p, &oldset);
4848 unlock_user(p, arg3, sizeof(target_sigset_t));
bellard66fb9762003-03-23 01:06:05 +00004849 }
4850 }
4851 break;
thse5febef2007-04-01 18:31:35 +00004852#ifdef TARGET_NR_sigpending
bellard66fb9762003-03-23 01:06:05 +00004853 case TARGET_NR_sigpending:
4854 {
4855 sigset_t set;
4856 ret = get_errno(sigpending(&set));
4857 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00004858 if (!(p = lock_user(VERIFY_WRITE, arg1, sizeof(target_sigset_t), 0)))
4859 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004860 host_to_target_old_sigset(p, &set);
4861 unlock_user(p, arg1, sizeof(target_sigset_t));
bellard66fb9762003-03-23 01:06:05 +00004862 }
4863 }
4864 break;
thse5febef2007-04-01 18:31:35 +00004865#endif
bellard66fb9762003-03-23 01:06:05 +00004866 case TARGET_NR_rt_sigpending:
4867 {
4868 sigset_t set;
4869 ret = get_errno(sigpending(&set));
4870 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00004871 if (!(p = lock_user(VERIFY_WRITE, arg1, sizeof(target_sigset_t), 0)))
4872 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004873 host_to_target_sigset(p, &set);
4874 unlock_user(p, arg1, sizeof(target_sigset_t));
bellard66fb9762003-03-23 01:06:05 +00004875 }
4876 }
4877 break;
thse5febef2007-04-01 18:31:35 +00004878#ifdef TARGET_NR_sigsuspend
bellard66fb9762003-03-23 01:06:05 +00004879 case TARGET_NR_sigsuspend:
4880 {
4881 sigset_t set;
bellard579a97f2007-11-11 14:26:47 +00004882 if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
4883 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004884 target_to_host_old_sigset(&set, p);
4885 unlock_user(p, arg1, 0);
bellard66fb9762003-03-23 01:06:05 +00004886 ret = get_errno(sigsuspend(&set));
4887 }
4888 break;
thse5febef2007-04-01 18:31:35 +00004889#endif
bellard66fb9762003-03-23 01:06:05 +00004890 case TARGET_NR_rt_sigsuspend:
4891 {
4892 sigset_t set;
bellard579a97f2007-11-11 14:26:47 +00004893 if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
4894 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004895 target_to_host_sigset(&set, p);
4896 unlock_user(p, arg1, 0);
bellard66fb9762003-03-23 01:06:05 +00004897 ret = get_errno(sigsuspend(&set));
4898 }
4899 break;
4900 case TARGET_NR_rt_sigtimedwait:
4901 {
bellard66fb9762003-03-23 01:06:05 +00004902 sigset_t set;
4903 struct timespec uts, *puts;
4904 siginfo_t uinfo;
ths3b46e622007-09-17 08:09:54 +00004905
bellard579a97f2007-11-11 14:26:47 +00004906 if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
4907 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004908 target_to_host_sigset(&set, p);
4909 unlock_user(p, arg1, 0);
4910 if (arg3) {
bellard66fb9762003-03-23 01:06:05 +00004911 puts = &uts;
pbrook53a59602006-03-25 19:31:22 +00004912 target_to_host_timespec(puts, arg3);
bellard66fb9762003-03-23 01:06:05 +00004913 } else {
4914 puts = NULL;
4915 }
4916 ret = get_errno(sigtimedwait(&set, &uinfo, puts));
pbrook53a59602006-03-25 19:31:22 +00004917 if (!is_error(ret) && arg2) {
pbrooke1e3f302008-05-30 21:53:38 +00004918 if (!(p = lock_user(VERIFY_WRITE, arg2, sizeof(target_siginfo_t), 0)))
bellard579a97f2007-11-11 14:26:47 +00004919 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004920 host_to_target_siginfo(p, &uinfo);
pbrooke1e3f302008-05-30 21:53:38 +00004921 unlock_user(p, arg2, sizeof(target_siginfo_t));
bellard66fb9762003-03-23 01:06:05 +00004922 }
4923 }
4924 break;
4925 case TARGET_NR_rt_sigqueueinfo:
4926 {
4927 siginfo_t uinfo;
bellard579a97f2007-11-11 14:26:47 +00004928 if (!(p = lock_user(VERIFY_READ, arg3, sizeof(target_sigset_t), 1)))
4929 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004930 target_to_host_siginfo(&uinfo, p);
4931 unlock_user(p, arg1, 0);
bellard66fb9762003-03-23 01:06:05 +00004932 ret = get_errno(sys_rt_sigqueueinfo(arg1, arg2, &uinfo));
4933 }
4934 break;
thse5febef2007-04-01 18:31:35 +00004935#ifdef TARGET_NR_sigreturn
bellard66fb9762003-03-23 01:06:05 +00004936 case TARGET_NR_sigreturn:
4937 /* NOTE: ret is eax, so not transcoding must be done */
4938 ret = do_sigreturn(cpu_env);
4939 break;
thse5febef2007-04-01 18:31:35 +00004940#endif
bellard66fb9762003-03-23 01:06:05 +00004941 case TARGET_NR_rt_sigreturn:
4942 /* NOTE: ret is eax, so not transcoding must be done */
4943 ret = do_rt_sigreturn(cpu_env);
4944 break;
bellard31e31b82003-02-18 22:55:36 +00004945 case TARGET_NR_sethostname:
bellard579a97f2007-11-11 14:26:47 +00004946 if (!(p = lock_user_string(arg1)))
4947 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004948 ret = get_errno(sethostname(p, arg2));
4949 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004950 break;
4951 case TARGET_NR_setrlimit:
bellard9de5e442003-03-23 16:49:39 +00004952 {
4953 /* XXX: convert resource ? */
4954 int resource = arg1;
pbrook53a59602006-03-25 19:31:22 +00004955 struct target_rlimit *target_rlim;
bellard9de5e442003-03-23 16:49:39 +00004956 struct rlimit rlim;
bellard579a97f2007-11-11 14:26:47 +00004957 if (!lock_user_struct(VERIFY_READ, target_rlim, arg2, 1))
4958 goto efault;
bellard9de5e442003-03-23 16:49:39 +00004959 rlim.rlim_cur = tswapl(target_rlim->rlim_cur);
4960 rlim.rlim_max = tswapl(target_rlim->rlim_max);
pbrook53a59602006-03-25 19:31:22 +00004961 unlock_user_struct(target_rlim, arg2, 0);
bellard9de5e442003-03-23 16:49:39 +00004962 ret = get_errno(setrlimit(resource, &rlim));
4963 }
4964 break;
bellard31e31b82003-02-18 22:55:36 +00004965 case TARGET_NR_getrlimit:
bellard9de5e442003-03-23 16:49:39 +00004966 {
4967 /* XXX: convert resource ? */
4968 int resource = arg1;
pbrook53a59602006-03-25 19:31:22 +00004969 struct target_rlimit *target_rlim;
bellard9de5e442003-03-23 16:49:39 +00004970 struct rlimit rlim;
ths3b46e622007-09-17 08:09:54 +00004971
bellard9de5e442003-03-23 16:49:39 +00004972 ret = get_errno(getrlimit(resource, &rlim));
4973 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00004974 if (!lock_user_struct(VERIFY_WRITE, target_rlim, arg2, 0))
4975 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004976 rlim.rlim_cur = tswapl(target_rlim->rlim_cur);
4977 rlim.rlim_max = tswapl(target_rlim->rlim_max);
4978 unlock_user_struct(target_rlim, arg2, 1);
bellard9de5e442003-03-23 16:49:39 +00004979 }
4980 }
4981 break;
bellard31e31b82003-02-18 22:55:36 +00004982 case TARGET_NR_getrusage:
bellardb4091862003-05-16 15:39:34 +00004983 {
4984 struct rusage rusage;
bellardb4091862003-05-16 15:39:34 +00004985 ret = get_errno(getrusage(arg1, &rusage));
4986 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00004987 host_to_target_rusage(arg2, &rusage);
bellardb4091862003-05-16 15:39:34 +00004988 }
4989 }
4990 break;
bellard31e31b82003-02-18 22:55:36 +00004991 case TARGET_NR_gettimeofday:
4992 {
bellard31e31b82003-02-18 22:55:36 +00004993 struct timeval tv;
4994 ret = get_errno(gettimeofday(&tv, NULL));
4995 if (!is_error(ret)) {
ths788f5ec2007-12-09 02:37:05 +00004996 if (copy_to_user_timeval(arg1, &tv))
4997 goto efault;
bellard31e31b82003-02-18 22:55:36 +00004998 }
4999 }
5000 break;
5001 case TARGET_NR_settimeofday:
5002 {
bellard31e31b82003-02-18 22:55:36 +00005003 struct timeval tv;
ths788f5ec2007-12-09 02:37:05 +00005004 if (copy_from_user_timeval(&tv, arg1))
5005 goto efault;
bellard31e31b82003-02-18 22:55:36 +00005006 ret = get_errno(settimeofday(&tv, NULL));
5007 }
5008 break;
bellard048f6b42005-11-26 18:47:20 +00005009#ifdef TARGET_NR_select
bellard31e31b82003-02-18 22:55:36 +00005010 case TARGET_NR_select:
bellardf2674e32003-07-09 12:26:09 +00005011 {
pbrook53a59602006-03-25 19:31:22 +00005012 struct target_sel_arg_struct *sel;
blueswir1992f48a2007-10-14 16:27:31 +00005013 abi_ulong inp, outp, exp, tvp;
pbrook53a59602006-03-25 19:31:22 +00005014 long nsel;
5015
bellard579a97f2007-11-11 14:26:47 +00005016 if (!lock_user_struct(VERIFY_READ, sel, arg1, 1))
5017 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005018 nsel = tswapl(sel->n);
5019 inp = tswapl(sel->inp);
5020 outp = tswapl(sel->outp);
5021 exp = tswapl(sel->exp);
5022 tvp = tswapl(sel->tvp);
5023 unlock_user_struct(sel, arg1, 0);
5024 ret = do_select(nsel, inp, outp, exp, tvp);
bellardf2674e32003-07-09 12:26:09 +00005025 }
5026 break;
bellard048f6b42005-11-26 18:47:20 +00005027#endif
bellard31e31b82003-02-18 22:55:36 +00005028 case TARGET_NR_symlink:
pbrook53a59602006-03-25 19:31:22 +00005029 {
5030 void *p2;
5031 p = lock_user_string(arg1);
5032 p2 = lock_user_string(arg2);
bellard579a97f2007-11-11 14:26:47 +00005033 if (!p || !p2)
5034 ret = -TARGET_EFAULT;
5035 else
5036 ret = get_errno(symlink(p, p2));
pbrook53a59602006-03-25 19:31:22 +00005037 unlock_user(p2, arg2, 0);
5038 unlock_user(p, arg1, 0);
5039 }
bellard31e31b82003-02-18 22:55:36 +00005040 break;
thsf0b62432007-09-24 09:25:40 +00005041#if defined(TARGET_NR_symlinkat) && defined(__NR_symlinkat)
5042 case TARGET_NR_symlinkat:
thsf0b62432007-09-24 09:25:40 +00005043 {
bellard579a97f2007-11-11 14:26:47 +00005044 void *p2;
thsf0b62432007-09-24 09:25:40 +00005045 p = lock_user_string(arg1);
5046 p2 = lock_user_string(arg3);
bellard579a97f2007-11-11 14:26:47 +00005047 if (!p || !p2)
ths0da46a62007-10-20 20:23:07 +00005048 ret = -TARGET_EFAULT;
thsf0b62432007-09-24 09:25:40 +00005049 else
5050 ret = get_errno(sys_symlinkat(p, arg2, p2));
bellard579a97f2007-11-11 14:26:47 +00005051 unlock_user(p2, arg3, 0);
5052 unlock_user(p, arg1, 0);
thsf0b62432007-09-24 09:25:40 +00005053 }
5054 break;
5055#endif
bellardebc05482003-09-30 21:08:41 +00005056#ifdef TARGET_NR_oldlstat
bellard31e31b82003-02-18 22:55:36 +00005057 case TARGET_NR_oldlstat:
5058 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00005059#endif
bellard31e31b82003-02-18 22:55:36 +00005060 case TARGET_NR_readlink:
pbrook53a59602006-03-25 19:31:22 +00005061 {
aurel32d088d662009-01-30 20:09:01 +00005062 void *p2, *temp;
pbrook53a59602006-03-25 19:31:22 +00005063 p = lock_user_string(arg1);
bellard579a97f2007-11-11 14:26:47 +00005064 p2 = lock_user(VERIFY_WRITE, arg2, arg3, 0);
5065 if (!p || !p2)
5066 ret = -TARGET_EFAULT;
aurel32d088d662009-01-30 20:09:01 +00005067 else {
5068 if (strncmp((const char *)p, "/proc/self/exe", 14) == 0) {
5069 char real[PATH_MAX];
5070 temp = realpath(exec_path,real);
5071 ret = (temp==NULL) ? get_errno(-1) : strlen(real) ;
5072 snprintf((char *)p2, arg3, "%s", real);
5073 }
5074 else
5075 ret = get_errno(readlink(path(p), p2, arg3));
aurel32d088d662009-01-30 20:09:01 +00005076 }
pbrook53a59602006-03-25 19:31:22 +00005077 unlock_user(p2, arg2, ret);
5078 unlock_user(p, arg1, 0);
5079 }
bellard31e31b82003-02-18 22:55:36 +00005080 break;
ths5e0ccb12007-09-24 09:26:10 +00005081#if defined(TARGET_NR_readlinkat) && defined(__NR_readlinkat)
5082 case TARGET_NR_readlinkat:
ths5e0ccb12007-09-24 09:26:10 +00005083 {
bellard579a97f2007-11-11 14:26:47 +00005084 void *p2;
ths5e0ccb12007-09-24 09:26:10 +00005085 p = lock_user_string(arg2);
bellard579a97f2007-11-11 14:26:47 +00005086 p2 = lock_user(VERIFY_WRITE, arg3, arg4, 0);
5087 if (!p || !p2)
ths0da46a62007-10-20 20:23:07 +00005088 ret = -TARGET_EFAULT;
ths5e0ccb12007-09-24 09:26:10 +00005089 else
5090 ret = get_errno(sys_readlinkat(arg1, path(p), p2, arg4));
bellard579a97f2007-11-11 14:26:47 +00005091 unlock_user(p2, arg3, ret);
5092 unlock_user(p, arg2, 0);
ths5e0ccb12007-09-24 09:26:10 +00005093 }
5094 break;
5095#endif
thse5febef2007-04-01 18:31:35 +00005096#ifdef TARGET_NR_uselib
bellard31e31b82003-02-18 22:55:36 +00005097 case TARGET_NR_uselib:
5098 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00005099#endif
5100#ifdef TARGET_NR_swapon
bellard31e31b82003-02-18 22:55:36 +00005101 case TARGET_NR_swapon:
bellard579a97f2007-11-11 14:26:47 +00005102 if (!(p = lock_user_string(arg1)))
5103 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005104 ret = get_errno(swapon(p, arg2));
5105 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00005106 break;
thse5febef2007-04-01 18:31:35 +00005107#endif
bellard31e31b82003-02-18 22:55:36 +00005108 case TARGET_NR_reboot:
5109 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00005110#ifdef TARGET_NR_readdir
bellard31e31b82003-02-18 22:55:36 +00005111 case TARGET_NR_readdir:
5112 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00005113#endif
5114#ifdef TARGET_NR_mmap
bellard31e31b82003-02-18 22:55:36 +00005115 case TARGET_NR_mmap:
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02005116#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 +00005117 {
blueswir1992f48a2007-10-14 16:27:31 +00005118 abi_ulong *v;
5119 abi_ulong v1, v2, v3, v4, v5, v6;
bellard579a97f2007-11-11 14:26:47 +00005120 if (!(v = lock_user(VERIFY_READ, arg1, 6 * sizeof(abi_ulong), 1)))
5121 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005122 v1 = tswapl(v[0]);
5123 v2 = tswapl(v[1]);
5124 v3 = tswapl(v[2]);
5125 v4 = tswapl(v[3]);
5126 v5 = tswapl(v[4]);
5127 v6 = tswapl(v[5]);
5128 unlock_user(v, arg1, 0);
ths5fafdf22007-09-16 21:08:06 +00005129 ret = get_errno(target_mmap(v1, v2, v3,
bellard5286db72003-06-05 00:57:30 +00005130 target_to_host_bitmask(v4, mmap_flags_tbl),
5131 v5, v6));
bellard31e31b82003-02-18 22:55:36 +00005132 }
bellard31e31b82003-02-18 22:55:36 +00005133#else
ths5fafdf22007-09-16 21:08:06 +00005134 ret = get_errno(target_mmap(arg1, arg2, arg3,
5135 target_to_host_bitmask(arg4, mmap_flags_tbl),
bellard6fb883e2003-07-09 17:12:39 +00005136 arg5,
5137 arg6));
bellard31e31b82003-02-18 22:55:36 +00005138#endif
bellard6fb883e2003-07-09 17:12:39 +00005139 break;
thse5febef2007-04-01 18:31:35 +00005140#endif
bellarda315a142005-01-30 22:59:18 +00005141#ifdef TARGET_NR_mmap2
bellard6fb883e2003-07-09 17:12:39 +00005142 case TARGET_NR_mmap2:
pbrookbb7ec042008-03-25 22:28:25 +00005143#ifndef MMAP_SHIFT
bellardc573ff62004-01-04 15:51:36 +00005144#define MMAP_SHIFT 12
bellardc573ff62004-01-04 15:51:36 +00005145#endif
ths5fafdf22007-09-16 21:08:06 +00005146 ret = get_errno(target_mmap(arg1, arg2, arg3,
5147 target_to_host_bitmask(arg4, mmap_flags_tbl),
bellard5286db72003-06-05 00:57:30 +00005148 arg5,
bellardc573ff62004-01-04 15:51:36 +00005149 arg6 << MMAP_SHIFT));
bellard31e31b82003-02-18 22:55:36 +00005150 break;
bellarda315a142005-01-30 22:59:18 +00005151#endif
bellard31e31b82003-02-18 22:55:36 +00005152 case TARGET_NR_munmap:
bellard54936002003-05-13 00:25:15 +00005153 ret = get_errno(target_munmap(arg1, arg2));
bellard31e31b82003-02-18 22:55:36 +00005154 break;
bellard9de5e442003-03-23 16:49:39 +00005155 case TARGET_NR_mprotect:
bellard54936002003-05-13 00:25:15 +00005156 ret = get_errno(target_mprotect(arg1, arg2, arg3));
bellard9de5e442003-03-23 16:49:39 +00005157 break;
thse5febef2007-04-01 18:31:35 +00005158#ifdef TARGET_NR_mremap
bellard9de5e442003-03-23 16:49:39 +00005159 case TARGET_NR_mremap:
bellard54936002003-05-13 00:25:15 +00005160 ret = get_errno(target_mremap(arg1, arg2, arg3, arg4, arg5));
bellard9de5e442003-03-23 16:49:39 +00005161 break;
thse5febef2007-04-01 18:31:35 +00005162#endif
pbrook53a59602006-03-25 19:31:22 +00005163 /* ??? msync/mlock/munlock are broken for softmmu. */
thse5febef2007-04-01 18:31:35 +00005164#ifdef TARGET_NR_msync
bellard9de5e442003-03-23 16:49:39 +00005165 case TARGET_NR_msync:
pbrook53a59602006-03-25 19:31:22 +00005166 ret = get_errno(msync(g2h(arg1), arg2, arg3));
bellard9de5e442003-03-23 16:49:39 +00005167 break;
thse5febef2007-04-01 18:31:35 +00005168#endif
5169#ifdef TARGET_NR_mlock
bellard9de5e442003-03-23 16:49:39 +00005170 case TARGET_NR_mlock:
pbrook53a59602006-03-25 19:31:22 +00005171 ret = get_errno(mlock(g2h(arg1), arg2));
bellard9de5e442003-03-23 16:49:39 +00005172 break;
thse5febef2007-04-01 18:31:35 +00005173#endif
5174#ifdef TARGET_NR_munlock
bellard9de5e442003-03-23 16:49:39 +00005175 case TARGET_NR_munlock:
pbrook53a59602006-03-25 19:31:22 +00005176 ret = get_errno(munlock(g2h(arg1), arg2));
bellard9de5e442003-03-23 16:49:39 +00005177 break;
thse5febef2007-04-01 18:31:35 +00005178#endif
5179#ifdef TARGET_NR_mlockall
bellard9de5e442003-03-23 16:49:39 +00005180 case TARGET_NR_mlockall:
5181 ret = get_errno(mlockall(arg1));
5182 break;
thse5febef2007-04-01 18:31:35 +00005183#endif
5184#ifdef TARGET_NR_munlockall
bellard9de5e442003-03-23 16:49:39 +00005185 case TARGET_NR_munlockall:
5186 ret = get_errno(munlockall());
5187 break;
thse5febef2007-04-01 18:31:35 +00005188#endif
bellard31e31b82003-02-18 22:55:36 +00005189 case TARGET_NR_truncate:
bellard579a97f2007-11-11 14:26:47 +00005190 if (!(p = lock_user_string(arg1)))
5191 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005192 ret = get_errno(truncate(p, arg2));
5193 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00005194 break;
5195 case TARGET_NR_ftruncate:
5196 ret = get_errno(ftruncate(arg1, arg2));
5197 break;
5198 case TARGET_NR_fchmod:
5199 ret = get_errno(fchmod(arg1, arg2));
5200 break;
ths814d7972007-09-24 09:26:51 +00005201#if defined(TARGET_NR_fchmodat) && defined(__NR_fchmodat)
5202 case TARGET_NR_fchmodat:
bellard579a97f2007-11-11 14:26:47 +00005203 if (!(p = lock_user_string(arg2)))
5204 goto efault;
aurel32465c9f02009-04-19 08:52:17 +00005205 ret = get_errno(sys_fchmodat(arg1, p, arg3));
bellard579a97f2007-11-11 14:26:47 +00005206 unlock_user(p, arg2, 0);
ths814d7972007-09-24 09:26:51 +00005207 break;
5208#endif
bellard31e31b82003-02-18 22:55:36 +00005209 case TARGET_NR_getpriority:
thsc6cda172007-10-09 03:42:34 +00005210 /* libc does special remapping of the return value of
5211 * sys_getpriority() so it's just easiest to call
5212 * sys_getpriority() directly rather than through libc. */
5213 ret = sys_getpriority(arg1, arg2);
bellard31e31b82003-02-18 22:55:36 +00005214 break;
5215 case TARGET_NR_setpriority:
5216 ret = get_errno(setpriority(arg1, arg2, arg3));
5217 break;
bellardebc05482003-09-30 21:08:41 +00005218#ifdef TARGET_NR_profil
bellard31e31b82003-02-18 22:55:36 +00005219 case TARGET_NR_profil:
5220 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00005221#endif
bellard31e31b82003-02-18 22:55:36 +00005222 case TARGET_NR_statfs:
bellard579a97f2007-11-11 14:26:47 +00005223 if (!(p = lock_user_string(arg1)))
5224 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005225 ret = get_errno(statfs(path(p), &stfs));
5226 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00005227 convert_statfs:
5228 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00005229 struct target_statfs *target_stfs;
ths3b46e622007-09-17 08:09:54 +00005230
bellard579a97f2007-11-11 14:26:47 +00005231 if (!lock_user_struct(VERIFY_WRITE, target_stfs, arg2, 0))
5232 goto efault;
5233 __put_user(stfs.f_type, &target_stfs->f_type);
5234 __put_user(stfs.f_bsize, &target_stfs->f_bsize);
5235 __put_user(stfs.f_blocks, &target_stfs->f_blocks);
5236 __put_user(stfs.f_bfree, &target_stfs->f_bfree);
5237 __put_user(stfs.f_bavail, &target_stfs->f_bavail);
5238 __put_user(stfs.f_files, &target_stfs->f_files);
5239 __put_user(stfs.f_ffree, &target_stfs->f_ffree);
5240 __put_user(stfs.f_fsid.__val[0], &target_stfs->f_fsid.val[0]);
5241 __put_user(stfs.f_fsid.__val[1], &target_stfs->f_fsid.val[1]);
5242 __put_user(stfs.f_namelen, &target_stfs->f_namelen);
pbrook53a59602006-03-25 19:31:22 +00005243 unlock_user_struct(target_stfs, arg2, 1);
bellard31e31b82003-02-18 22:55:36 +00005244 }
5245 break;
5246 case TARGET_NR_fstatfs:
bellard56c8f682005-11-28 22:28:41 +00005247 ret = get_errno(fstatfs(arg1, &stfs));
bellard31e31b82003-02-18 22:55:36 +00005248 goto convert_statfs;
bellard56c8f682005-11-28 22:28:41 +00005249#ifdef TARGET_NR_statfs64
5250 case TARGET_NR_statfs64:
bellard579a97f2007-11-11 14:26:47 +00005251 if (!(p = lock_user_string(arg1)))
5252 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005253 ret = get_errno(statfs(path(p), &stfs));
5254 unlock_user(p, arg1, 0);
bellard56c8f682005-11-28 22:28:41 +00005255 convert_statfs64:
5256 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00005257 struct target_statfs64 *target_stfs;
ths3b46e622007-09-17 08:09:54 +00005258
bellard579a97f2007-11-11 14:26:47 +00005259 if (!lock_user_struct(VERIFY_WRITE, target_stfs, arg3, 0))
5260 goto efault;
5261 __put_user(stfs.f_type, &target_stfs->f_type);
5262 __put_user(stfs.f_bsize, &target_stfs->f_bsize);
5263 __put_user(stfs.f_blocks, &target_stfs->f_blocks);
5264 __put_user(stfs.f_bfree, &target_stfs->f_bfree);
5265 __put_user(stfs.f_bavail, &target_stfs->f_bavail);
5266 __put_user(stfs.f_files, &target_stfs->f_files);
5267 __put_user(stfs.f_ffree, &target_stfs->f_ffree);
5268 __put_user(stfs.f_fsid.__val[0], &target_stfs->f_fsid.val[0]);
5269 __put_user(stfs.f_fsid.__val[1], &target_stfs->f_fsid.val[1]);
5270 __put_user(stfs.f_namelen, &target_stfs->f_namelen);
5271 unlock_user_struct(target_stfs, arg3, 1);
bellard56c8f682005-11-28 22:28:41 +00005272 }
5273 break;
5274 case TARGET_NR_fstatfs64:
5275 ret = get_errno(fstatfs(arg1, &stfs));
5276 goto convert_statfs64;
5277#endif
bellardebc05482003-09-30 21:08:41 +00005278#ifdef TARGET_NR_ioperm
bellard31e31b82003-02-18 22:55:36 +00005279 case TARGET_NR_ioperm:
5280 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00005281#endif
thse5febef2007-04-01 18:31:35 +00005282#ifdef TARGET_NR_socketcall
bellard31e31b82003-02-18 22:55:36 +00005283 case TARGET_NR_socketcall:
pbrook53a59602006-03-25 19:31:22 +00005284 ret = do_socketcall(arg1, arg2);
bellard31e31b82003-02-18 22:55:36 +00005285 break;
thse5febef2007-04-01 18:31:35 +00005286#endif
bellard3532fa72006-06-24 15:06:03 +00005287#ifdef TARGET_NR_accept
5288 case TARGET_NR_accept:
pbrook1be9e1d2006-11-19 15:26:04 +00005289 ret = do_accept(arg1, arg2, arg3);
bellard3532fa72006-06-24 15:06:03 +00005290 break;
5291#endif
5292#ifdef TARGET_NR_bind
5293 case TARGET_NR_bind:
5294 ret = do_bind(arg1, arg2, arg3);
5295 break;
5296#endif
5297#ifdef TARGET_NR_connect
5298 case TARGET_NR_connect:
5299 ret = do_connect(arg1, arg2, arg3);
5300 break;
5301#endif
5302#ifdef TARGET_NR_getpeername
5303 case TARGET_NR_getpeername:
pbrook1be9e1d2006-11-19 15:26:04 +00005304 ret = do_getpeername(arg1, arg2, arg3);
bellard3532fa72006-06-24 15:06:03 +00005305 break;
5306#endif
5307#ifdef TARGET_NR_getsockname
5308 case TARGET_NR_getsockname:
pbrook1be9e1d2006-11-19 15:26:04 +00005309 ret = do_getsockname(arg1, arg2, arg3);
bellard3532fa72006-06-24 15:06:03 +00005310 break;
5311#endif
5312#ifdef TARGET_NR_getsockopt
5313 case TARGET_NR_getsockopt:
5314 ret = do_getsockopt(arg1, arg2, arg3, arg4, arg5);
5315 break;
5316#endif
5317#ifdef TARGET_NR_listen
5318 case TARGET_NR_listen:
pbrook1be9e1d2006-11-19 15:26:04 +00005319 ret = get_errno(listen(arg1, arg2));
bellard3532fa72006-06-24 15:06:03 +00005320 break;
5321#endif
5322#ifdef TARGET_NR_recv
5323 case TARGET_NR_recv:
pbrook214201b2007-03-17 01:27:24 +00005324 ret = do_recvfrom(arg1, arg2, arg3, arg4, 0, 0);
bellard3532fa72006-06-24 15:06:03 +00005325 break;
5326#endif
5327#ifdef TARGET_NR_recvfrom
5328 case TARGET_NR_recvfrom:
pbrook214201b2007-03-17 01:27:24 +00005329 ret = do_recvfrom(arg1, arg2, arg3, arg4, arg5, arg6);
bellard3532fa72006-06-24 15:06:03 +00005330 break;
5331#endif
5332#ifdef TARGET_NR_recvmsg
5333 case TARGET_NR_recvmsg:
5334 ret = do_sendrecvmsg(arg1, arg2, arg3, 0);
5335 break;
5336#endif
5337#ifdef TARGET_NR_send
5338 case TARGET_NR_send:
pbrook1be9e1d2006-11-19 15:26:04 +00005339 ret = do_sendto(arg1, arg2, arg3, arg4, 0, 0);
bellard3532fa72006-06-24 15:06:03 +00005340 break;
5341#endif
5342#ifdef TARGET_NR_sendmsg
5343 case TARGET_NR_sendmsg:
5344 ret = do_sendrecvmsg(arg1, arg2, arg3, 1);
5345 break;
5346#endif
5347#ifdef TARGET_NR_sendto
5348 case TARGET_NR_sendto:
pbrook1be9e1d2006-11-19 15:26:04 +00005349 ret = do_sendto(arg1, arg2, arg3, arg4, arg5, arg6);
bellard3532fa72006-06-24 15:06:03 +00005350 break;
5351#endif
5352#ifdef TARGET_NR_shutdown
5353 case TARGET_NR_shutdown:
pbrook1be9e1d2006-11-19 15:26:04 +00005354 ret = get_errno(shutdown(arg1, arg2));
bellard3532fa72006-06-24 15:06:03 +00005355 break;
5356#endif
5357#ifdef TARGET_NR_socket
5358 case TARGET_NR_socket:
5359 ret = do_socket(arg1, arg2, arg3);
5360 break;
5361#endif
5362#ifdef TARGET_NR_socketpair
5363 case TARGET_NR_socketpair:
pbrook1be9e1d2006-11-19 15:26:04 +00005364 ret = do_socketpair(arg1, arg2, arg3, arg4);
bellard3532fa72006-06-24 15:06:03 +00005365 break;
5366#endif
5367#ifdef TARGET_NR_setsockopt
5368 case TARGET_NR_setsockopt:
5369 ret = do_setsockopt(arg1, arg2, arg3, arg4, (socklen_t) arg5);
5370 break;
5371#endif
ths7494b0f2007-02-11 18:26:53 +00005372
bellard31e31b82003-02-18 22:55:36 +00005373 case TARGET_NR_syslog:
bellard579a97f2007-11-11 14:26:47 +00005374 if (!(p = lock_user_string(arg2)))
5375 goto efault;
thse5574482007-02-11 20:03:13 +00005376 ret = get_errno(sys_syslog((int)arg1, p, (int)arg3));
5377 unlock_user(p, arg2, 0);
ths7494b0f2007-02-11 18:26:53 +00005378 break;
5379
bellard31e31b82003-02-18 22:55:36 +00005380 case TARGET_NR_setitimer:
bellard66fb9762003-03-23 01:06:05 +00005381 {
bellard66fb9762003-03-23 01:06:05 +00005382 struct itimerval value, ovalue, *pvalue;
5383
pbrook53a59602006-03-25 19:31:22 +00005384 if (arg2) {
bellard66fb9762003-03-23 01:06:05 +00005385 pvalue = &value;
ths788f5ec2007-12-09 02:37:05 +00005386 if (copy_from_user_timeval(&pvalue->it_interval, arg2)
5387 || copy_from_user_timeval(&pvalue->it_value,
5388 arg2 + sizeof(struct target_timeval)))
5389 goto efault;
bellard66fb9762003-03-23 01:06:05 +00005390 } else {
5391 pvalue = NULL;
5392 }
5393 ret = get_errno(setitimer(arg1, pvalue, &ovalue));
pbrook53a59602006-03-25 19:31:22 +00005394 if (!is_error(ret) && arg3) {
ths788f5ec2007-12-09 02:37:05 +00005395 if (copy_to_user_timeval(arg3,
5396 &ovalue.it_interval)
5397 || copy_to_user_timeval(arg3 + sizeof(struct target_timeval),
5398 &ovalue.it_value))
5399 goto efault;
bellard66fb9762003-03-23 01:06:05 +00005400 }
5401 }
5402 break;
bellard31e31b82003-02-18 22:55:36 +00005403 case TARGET_NR_getitimer:
bellard66fb9762003-03-23 01:06:05 +00005404 {
bellard66fb9762003-03-23 01:06:05 +00005405 struct itimerval value;
ths3b46e622007-09-17 08:09:54 +00005406
bellard66fb9762003-03-23 01:06:05 +00005407 ret = get_errno(getitimer(arg1, &value));
pbrook53a59602006-03-25 19:31:22 +00005408 if (!is_error(ret) && arg2) {
ths788f5ec2007-12-09 02:37:05 +00005409 if (copy_to_user_timeval(arg2,
5410 &value.it_interval)
5411 || copy_to_user_timeval(arg2 + sizeof(struct target_timeval),
5412 &value.it_value))
5413 goto efault;
bellard66fb9762003-03-23 01:06:05 +00005414 }
5415 }
5416 break;
bellard31e31b82003-02-18 22:55:36 +00005417 case TARGET_NR_stat:
bellard579a97f2007-11-11 14:26:47 +00005418 if (!(p = lock_user_string(arg1)))
5419 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005420 ret = get_errno(stat(path(p), &st));
5421 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00005422 goto do_stat;
5423 case TARGET_NR_lstat:
bellard579a97f2007-11-11 14:26:47 +00005424 if (!(p = lock_user_string(arg1)))
5425 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005426 ret = get_errno(lstat(path(p), &st));
5427 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00005428 goto do_stat;
5429 case TARGET_NR_fstat:
5430 {
5431 ret = get_errno(fstat(arg1, &st));
5432 do_stat:
5433 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00005434 struct target_stat *target_st;
thse3584652007-06-01 11:49:38 +00005435
bellard579a97f2007-11-11 14:26:47 +00005436 if (!lock_user_struct(VERIFY_WRITE, target_st, arg2, 0))
5437 goto efault;
bellardd2fd1af2007-11-14 18:08:56 +00005438 __put_user(st.st_dev, &target_st->st_dev);
5439 __put_user(st.st_ino, &target_st->st_ino);
5440 __put_user(st.st_mode, &target_st->st_mode);
5441 __put_user(st.st_uid, &target_st->st_uid);
5442 __put_user(st.st_gid, &target_st->st_gid);
5443 __put_user(st.st_nlink, &target_st->st_nlink);
5444 __put_user(st.st_rdev, &target_st->st_rdev);
5445 __put_user(st.st_size, &target_st->st_size);
5446 __put_user(st.st_blksize, &target_st->st_blksize);
5447 __put_user(st.st_blocks, &target_st->st_blocks);
5448 __put_user(st.st_atime, &target_st->target_st_atime);
5449 __put_user(st.st_mtime, &target_st->target_st_mtime);
5450 __put_user(st.st_ctime, &target_st->target_st_ctime);
pbrook53a59602006-03-25 19:31:22 +00005451 unlock_user_struct(target_st, arg2, 1);
bellard31e31b82003-02-18 22:55:36 +00005452 }
5453 }
5454 break;
bellardebc05482003-09-30 21:08:41 +00005455#ifdef TARGET_NR_olduname
bellard31e31b82003-02-18 22:55:36 +00005456 case TARGET_NR_olduname:
5457 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00005458#endif
5459#ifdef TARGET_NR_iopl
bellard31e31b82003-02-18 22:55:36 +00005460 case TARGET_NR_iopl:
5461 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00005462#endif
bellard31e31b82003-02-18 22:55:36 +00005463 case TARGET_NR_vhangup:
5464 ret = get_errno(vhangup());
5465 break;
bellardebc05482003-09-30 21:08:41 +00005466#ifdef TARGET_NR_idle
bellard31e31b82003-02-18 22:55:36 +00005467 case TARGET_NR_idle:
5468 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00005469#endif
bellard42ad6ae2005-01-03 22:48:11 +00005470#ifdef TARGET_NR_syscall
5471 case TARGET_NR_syscall:
5472 ret = do_syscall(cpu_env,arg1 & 0xffff,arg2,arg3,arg4,arg5,arg6,0);
5473 break;
5474#endif
bellard31e31b82003-02-18 22:55:36 +00005475 case TARGET_NR_wait4:
5476 {
5477 int status;
blueswir1992f48a2007-10-14 16:27:31 +00005478 abi_long status_ptr = arg2;
bellard31e31b82003-02-18 22:55:36 +00005479 struct rusage rusage, *rusage_ptr;
blueswir1992f48a2007-10-14 16:27:31 +00005480 abi_ulong target_rusage = arg4;
bellard31e31b82003-02-18 22:55:36 +00005481 if (target_rusage)
5482 rusage_ptr = &rusage;
5483 else
5484 rusage_ptr = NULL;
5485 ret = get_errno(wait4(arg1, &status, arg3, rusage_ptr));
5486 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +00005487 if (status_ptr) {
pbrook1d9d8b52009-04-16 15:17:02 +00005488 status = host_to_target_waitstatus(status);
bellard2f619692007-11-16 10:46:05 +00005489 if (put_user_s32(status, status_ptr))
5490 goto efault;
bellard31e31b82003-02-18 22:55:36 +00005491 }
bellard2f619692007-11-16 10:46:05 +00005492 if (target_rusage)
5493 host_to_target_rusage(target_rusage, &rusage);
bellard31e31b82003-02-18 22:55:36 +00005494 }
5495 }
5496 break;
thse5febef2007-04-01 18:31:35 +00005497#ifdef TARGET_NR_swapoff
bellard31e31b82003-02-18 22:55:36 +00005498 case TARGET_NR_swapoff:
bellard579a97f2007-11-11 14:26:47 +00005499 if (!(p = lock_user_string(arg1)))
5500 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005501 ret = get_errno(swapoff(p));
5502 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00005503 break;
thse5febef2007-04-01 18:31:35 +00005504#endif
bellard31e31b82003-02-18 22:55:36 +00005505 case TARGET_NR_sysinfo:
bellarda5448a72004-06-19 16:59:03 +00005506 {
pbrook53a59602006-03-25 19:31:22 +00005507 struct target_sysinfo *target_value;
bellarda5448a72004-06-19 16:59:03 +00005508 struct sysinfo value;
5509 ret = get_errno(sysinfo(&value));
pbrook53a59602006-03-25 19:31:22 +00005510 if (!is_error(ret) && arg1)
bellarda5448a72004-06-19 16:59:03 +00005511 {
bellard579a97f2007-11-11 14:26:47 +00005512 if (!lock_user_struct(VERIFY_WRITE, target_value, arg1, 0))
5513 goto efault;
bellarda5448a72004-06-19 16:59:03 +00005514 __put_user(value.uptime, &target_value->uptime);
5515 __put_user(value.loads[0], &target_value->loads[0]);
5516 __put_user(value.loads[1], &target_value->loads[1]);
5517 __put_user(value.loads[2], &target_value->loads[2]);
5518 __put_user(value.totalram, &target_value->totalram);
5519 __put_user(value.freeram, &target_value->freeram);
5520 __put_user(value.sharedram, &target_value->sharedram);
5521 __put_user(value.bufferram, &target_value->bufferram);
5522 __put_user(value.totalswap, &target_value->totalswap);
5523 __put_user(value.freeswap, &target_value->freeswap);
5524 __put_user(value.procs, &target_value->procs);
5525 __put_user(value.totalhigh, &target_value->totalhigh);
5526 __put_user(value.freehigh, &target_value->freehigh);
5527 __put_user(value.mem_unit, &target_value->mem_unit);
pbrook53a59602006-03-25 19:31:22 +00005528 unlock_user_struct(target_value, arg1, 1);
bellarda5448a72004-06-19 16:59:03 +00005529 }
5530 }
5531 break;
thse5febef2007-04-01 18:31:35 +00005532#ifdef TARGET_NR_ipc
bellard31e31b82003-02-18 22:55:36 +00005533 case TARGET_NR_ipc:
bellard8853f862004-02-22 14:57:26 +00005534 ret = do_ipc(arg1, arg2, arg3, arg4, arg5, arg6);
5535 break;
thse5febef2007-04-01 18:31:35 +00005536#endif
aurel32e5289082009-04-18 16:16:12 +00005537#ifdef TARGET_NR_semget
5538 case TARGET_NR_semget:
5539 ret = get_errno(semget(arg1, arg2, arg3));
5540 break;
5541#endif
5542#ifdef TARGET_NR_semop
5543 case TARGET_NR_semop:
5544 ret = get_errno(do_semop(arg1, arg2, arg3));
5545 break;
5546#endif
5547#ifdef TARGET_NR_semctl
5548 case TARGET_NR_semctl:
5549 ret = do_semctl(arg1, arg2, arg3, (union target_semun)(abi_ulong)arg4);
5550 break;
5551#endif
aurel32eeb438c2008-10-13 21:08:55 +00005552#ifdef TARGET_NR_msgctl
5553 case TARGET_NR_msgctl:
5554 ret = do_msgctl(arg1, arg2, arg3);
5555 break;
5556#endif
5557#ifdef TARGET_NR_msgget
5558 case TARGET_NR_msgget:
5559 ret = get_errno(msgget(arg1, arg2));
5560 break;
5561#endif
5562#ifdef TARGET_NR_msgrcv
5563 case TARGET_NR_msgrcv:
5564 ret = do_msgrcv(arg1, arg2, arg3, arg4, arg5);
5565 break;
5566#endif
5567#ifdef TARGET_NR_msgsnd
5568 case TARGET_NR_msgsnd:
5569 ret = do_msgsnd(arg1, arg2, arg3, arg4);
5570 break;
5571#endif
Riku Voipio88a8c982009-04-03 10:42:00 +03005572#ifdef TARGET_NR_shmget
5573 case TARGET_NR_shmget:
5574 ret = get_errno(shmget(arg1, arg2, arg3));
5575 break;
5576#endif
5577#ifdef TARGET_NR_shmctl
5578 case TARGET_NR_shmctl:
5579 ret = do_shmctl(arg1, arg2, arg3);
5580 break;
5581#endif
5582#ifdef TARGET_NR_shmat
5583 case TARGET_NR_shmat:
5584 ret = do_shmat(arg1, arg2, arg3);
5585 break;
5586#endif
5587#ifdef TARGET_NR_shmdt
5588 case TARGET_NR_shmdt:
5589 ret = do_shmdt(arg1);
5590 break;
5591#endif
bellard31e31b82003-02-18 22:55:36 +00005592 case TARGET_NR_fsync:
5593 ret = get_errno(fsync(arg1));
5594 break;
bellard31e31b82003-02-18 22:55:36 +00005595 case TARGET_NR_clone:
aurel320b6d3ae2008-09-15 07:43:43 +00005596#if defined(TARGET_SH4)
5597 ret = get_errno(do_fork(cpu_env, arg1, arg2, arg3, arg5, arg4));
edgar_iglb15ad612009-01-07 19:43:47 +00005598#elif defined(TARGET_CRIS)
5599 ret = get_errno(do_fork(cpu_env, arg2, arg1, arg3, arg4, arg5));
aurel320b6d3ae2008-09-15 07:43:43 +00005600#else
pbrookd865bab2008-06-07 22:12:17 +00005601 ret = get_errno(do_fork(cpu_env, arg1, arg2, arg3, arg4, arg5));
aurel320b6d3ae2008-09-15 07:43:43 +00005602#endif
bellard1b6b0292003-03-22 17:31:38 +00005603 break;
bellardec86b0f2003-04-11 00:15:04 +00005604#ifdef __NR_exit_group
5605 /* new thread calls */
5606 case TARGET_NR_exit_group:
aurel326d946cd2008-11-06 16:15:18 +00005607#ifdef HAVE_GPROF
5608 _mcleanup();
5609#endif
bellarde9009672005-04-26 20:42:36 +00005610 gdb_exit(cpu_env, arg1);
bellardec86b0f2003-04-11 00:15:04 +00005611 ret = get_errno(exit_group(arg1));
5612 break;
5613#endif
bellard31e31b82003-02-18 22:55:36 +00005614 case TARGET_NR_setdomainname:
bellard579a97f2007-11-11 14:26:47 +00005615 if (!(p = lock_user_string(arg1)))
5616 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005617 ret = get_errno(setdomainname(p, arg2));
5618 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00005619 break;
5620 case TARGET_NR_uname:
5621 /* no need to transcode because we use the linux syscall */
bellard29e619b2004-09-13 21:41:04 +00005622 {
5623 struct new_utsname * buf;
ths3b46e622007-09-17 08:09:54 +00005624
bellard579a97f2007-11-11 14:26:47 +00005625 if (!lock_user_struct(VERIFY_WRITE, buf, arg1, 0))
5626 goto efault;
bellard29e619b2004-09-13 21:41:04 +00005627 ret = get_errno(sys_uname(buf));
5628 if (!is_error(ret)) {
5629 /* Overrite the native machine name with whatever is being
5630 emulated. */
5631 strcpy (buf->machine, UNAME_MACHINE);
pbrookc5937222006-05-14 11:30:38 +00005632 /* Allow the user to override the reported release. */
5633 if (qemu_uname_release && *qemu_uname_release)
5634 strcpy (buf->release, qemu_uname_release);
bellard29e619b2004-09-13 21:41:04 +00005635 }
pbrook53a59602006-03-25 19:31:22 +00005636 unlock_user_struct(buf, arg1, 1);
bellard29e619b2004-09-13 21:41:04 +00005637 }
bellard31e31b82003-02-18 22:55:36 +00005638 break;
bellard6dbad632003-03-16 18:05:05 +00005639#ifdef TARGET_I386
bellard31e31b82003-02-18 22:55:36 +00005640 case TARGET_NR_modify_ldt:
bellard03acab62007-11-11 14:57:14 +00005641 ret = do_modify_ldt(cpu_env, arg1, arg2, arg3);
bellard5cd43932003-03-29 16:54:36 +00005642 break;
j_mayer84409dd2007-04-06 08:56:50 +00005643#if !defined(TARGET_X86_64)
bellard5cd43932003-03-29 16:54:36 +00005644 case TARGET_NR_vm86old:
5645 goto unimplemented;
5646 case TARGET_NR_vm86:
pbrook53a59602006-03-25 19:31:22 +00005647 ret = do_vm86(cpu_env, arg1, arg2);
bellard6dbad632003-03-16 18:05:05 +00005648 break;
5649#endif
j_mayer84409dd2007-04-06 08:56:50 +00005650#endif
bellard31e31b82003-02-18 22:55:36 +00005651 case TARGET_NR_adjtimex:
5652 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00005653#ifdef TARGET_NR_create_module
bellard31e31b82003-02-18 22:55:36 +00005654 case TARGET_NR_create_module:
thse5febef2007-04-01 18:31:35 +00005655#endif
bellard31e31b82003-02-18 22:55:36 +00005656 case TARGET_NR_init_module:
5657 case TARGET_NR_delete_module:
thse5febef2007-04-01 18:31:35 +00005658#ifdef TARGET_NR_get_kernel_syms
bellard31e31b82003-02-18 22:55:36 +00005659 case TARGET_NR_get_kernel_syms:
thse5febef2007-04-01 18:31:35 +00005660#endif
bellard31e31b82003-02-18 22:55:36 +00005661 goto unimplemented;
5662 case TARGET_NR_quotactl:
5663 goto unimplemented;
5664 case TARGET_NR_getpgid:
5665 ret = get_errno(getpgid(arg1));
5666 break;
5667 case TARGET_NR_fchdir:
5668 ret = get_errno(fchdir(arg1));
5669 break;
j_mayer84409dd2007-04-06 08:56:50 +00005670#ifdef TARGET_NR_bdflush /* not on x86_64 */
bellard31e31b82003-02-18 22:55:36 +00005671 case TARGET_NR_bdflush:
5672 goto unimplemented;
j_mayer84409dd2007-04-06 08:56:50 +00005673#endif
thse5febef2007-04-01 18:31:35 +00005674#ifdef TARGET_NR_sysfs
bellard31e31b82003-02-18 22:55:36 +00005675 case TARGET_NR_sysfs:
5676 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00005677#endif
bellard31e31b82003-02-18 22:55:36 +00005678 case TARGET_NR_personality:
bellard1b6b0292003-03-22 17:31:38 +00005679 ret = get_errno(personality(arg1));
bellard31e31b82003-02-18 22:55:36 +00005680 break;
thse5febef2007-04-01 18:31:35 +00005681#ifdef TARGET_NR_afs_syscall
bellard31e31b82003-02-18 22:55:36 +00005682 case TARGET_NR_afs_syscall:
5683 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00005684#endif
j_mayer7a3148a2007-04-05 07:13:51 +00005685#ifdef TARGET_NR__llseek /* Not on alpha */
bellard31e31b82003-02-18 22:55:36 +00005686 case TARGET_NR__llseek:
5687 {
bellard4f2ac232004-04-26 19:44:02 +00005688#if defined (__x86_64__)
5689 ret = get_errno(lseek(arg1, ((uint64_t )arg2 << 32) | arg3, arg5));
bellard2f619692007-11-16 10:46:05 +00005690 if (put_user_s64(ret, arg4))
5691 goto efault;
bellard4f2ac232004-04-26 19:44:02 +00005692#else
bellard31e31b82003-02-18 22:55:36 +00005693 int64_t res;
5694 ret = get_errno(_llseek(arg1, arg2, arg3, &res, arg5));
bellard2f619692007-11-16 10:46:05 +00005695 if (put_user_s64(res, arg4))
5696 goto efault;
bellard4f2ac232004-04-26 19:44:02 +00005697#endif
bellard31e31b82003-02-18 22:55:36 +00005698 }
5699 break;
j_mayer7a3148a2007-04-05 07:13:51 +00005700#endif
bellard31e31b82003-02-18 22:55:36 +00005701 case TARGET_NR_getdents:
blueswir1992f48a2007-10-14 16:27:31 +00005702#if TARGET_ABI_BITS != 32
pbrook53a59602006-03-25 19:31:22 +00005703 goto unimplemented;
blueswir1992f48a2007-10-14 16:27:31 +00005704#elif TARGET_ABI_BITS == 32 && HOST_LONG_BITS == 64
bellard4add45b2003-06-05 01:52:59 +00005705 {
pbrook53a59602006-03-25 19:31:22 +00005706 struct target_dirent *target_dirp;
aurel326556a832008-10-13 21:08:17 +00005707 struct linux_dirent *dirp;
blueswir1992f48a2007-10-14 16:27:31 +00005708 abi_long count = arg3;
bellard4add45b2003-06-05 01:52:59 +00005709
5710 dirp = malloc(count);
ths0da46a62007-10-20 20:23:07 +00005711 if (!dirp) {
bellard579a97f2007-11-11 14:26:47 +00005712 ret = -TARGET_ENOMEM;
ths0da46a62007-10-20 20:23:07 +00005713 goto fail;
5714 }
ths3b46e622007-09-17 08:09:54 +00005715
bellard4add45b2003-06-05 01:52:59 +00005716 ret = get_errno(sys_getdents(arg1, dirp, count));
5717 if (!is_error(ret)) {
aurel326556a832008-10-13 21:08:17 +00005718 struct linux_dirent *de;
bellard4add45b2003-06-05 01:52:59 +00005719 struct target_dirent *tde;
5720 int len = ret;
5721 int reclen, treclen;
5722 int count1, tnamelen;
5723
5724 count1 = 0;
5725 de = dirp;
bellard579a97f2007-11-11 14:26:47 +00005726 if (!(target_dirp = lock_user(VERIFY_WRITE, arg2, count, 0)))
5727 goto efault;
bellard4add45b2003-06-05 01:52:59 +00005728 tde = target_dirp;
5729 while (len > 0) {
5730 reclen = de->d_reclen;
blueswir1992f48a2007-10-14 16:27:31 +00005731 treclen = reclen - (2 * (sizeof(long) - sizeof(abi_long)));
bellard4add45b2003-06-05 01:52:59 +00005732 tde->d_reclen = tswap16(treclen);
5733 tde->d_ino = tswapl(de->d_ino);
5734 tde->d_off = tswapl(de->d_off);
blueswir1992f48a2007-10-14 16:27:31 +00005735 tnamelen = treclen - (2 * sizeof(abi_long) + 2);
bellard4add45b2003-06-05 01:52:59 +00005736 if (tnamelen > 256)
5737 tnamelen = 256;
bellard80a9d032005-01-03 23:31:27 +00005738 /* XXX: may not be correct */
blueswir1be15b142008-10-25 11:21:28 +00005739 pstrcpy(tde->d_name, tnamelen, de->d_name);
aurel326556a832008-10-13 21:08:17 +00005740 de = (struct linux_dirent *)((char *)de + reclen);
bellard4add45b2003-06-05 01:52:59 +00005741 len -= reclen;
j_mayer1c5bf3b2007-04-14 12:17:59 +00005742 tde = (struct target_dirent *)((char *)tde + treclen);
bellard4add45b2003-06-05 01:52:59 +00005743 count1 += treclen;
5744 }
5745 ret = count1;
bellard579a97f2007-11-11 14:26:47 +00005746 unlock_user(target_dirp, arg2, ret);
bellard4add45b2003-06-05 01:52:59 +00005747 }
5748 free(dirp);
5749 }
5750#else
bellard31e31b82003-02-18 22:55:36 +00005751 {
aurel326556a832008-10-13 21:08:17 +00005752 struct linux_dirent *dirp;
blueswir1992f48a2007-10-14 16:27:31 +00005753 abi_long count = arg3;
bellarddab2ed92003-03-22 15:23:14 +00005754
bellard579a97f2007-11-11 14:26:47 +00005755 if (!(dirp = lock_user(VERIFY_WRITE, arg2, count, 0)))
5756 goto efault;
bellard72f03902003-02-18 23:33:18 +00005757 ret = get_errno(sys_getdents(arg1, dirp, count));
bellard31e31b82003-02-18 22:55:36 +00005758 if (!is_error(ret)) {
aurel326556a832008-10-13 21:08:17 +00005759 struct linux_dirent *de;
bellard31e31b82003-02-18 22:55:36 +00005760 int len = ret;
5761 int reclen;
5762 de = dirp;
5763 while (len > 0) {
bellard8083a3e2003-03-24 23:12:16 +00005764 reclen = de->d_reclen;
bellard31e31b82003-02-18 22:55:36 +00005765 if (reclen > len)
5766 break;
bellard8083a3e2003-03-24 23:12:16 +00005767 de->d_reclen = tswap16(reclen);
bellard31e31b82003-02-18 22:55:36 +00005768 tswapls(&de->d_ino);
5769 tswapls(&de->d_off);
aurel326556a832008-10-13 21:08:17 +00005770 de = (struct linux_dirent *)((char *)de + reclen);
bellard31e31b82003-02-18 22:55:36 +00005771 len -= reclen;
5772 }
5773 }
pbrook53a59602006-03-25 19:31:22 +00005774 unlock_user(dirp, arg2, ret);
bellard31e31b82003-02-18 22:55:36 +00005775 }
bellard4add45b2003-06-05 01:52:59 +00005776#endif
bellard31e31b82003-02-18 22:55:36 +00005777 break;
ths3ae43202007-09-16 21:39:48 +00005778#if defined(TARGET_NR_getdents64) && defined(__NR_getdents64)
bellarddab2ed92003-03-22 15:23:14 +00005779 case TARGET_NR_getdents64:
5780 {
aurel326556a832008-10-13 21:08:17 +00005781 struct linux_dirent64 *dirp;
blueswir1992f48a2007-10-14 16:27:31 +00005782 abi_long count = arg3;
bellard579a97f2007-11-11 14:26:47 +00005783 if (!(dirp = lock_user(VERIFY_WRITE, arg2, count, 0)))
5784 goto efault;
bellarddab2ed92003-03-22 15:23:14 +00005785 ret = get_errno(sys_getdents64(arg1, dirp, count));
5786 if (!is_error(ret)) {
aurel326556a832008-10-13 21:08:17 +00005787 struct linux_dirent64 *de;
bellarddab2ed92003-03-22 15:23:14 +00005788 int len = ret;
5789 int reclen;
5790 de = dirp;
5791 while (len > 0) {
bellard8083a3e2003-03-24 23:12:16 +00005792 reclen = de->d_reclen;
bellarddab2ed92003-03-22 15:23:14 +00005793 if (reclen > len)
5794 break;
bellard8083a3e2003-03-24 23:12:16 +00005795 de->d_reclen = tswap16(reclen);
bellard8582a532007-11-11 23:11:36 +00005796 tswap64s((uint64_t *)&de->d_ino);
5797 tswap64s((uint64_t *)&de->d_off);
aurel326556a832008-10-13 21:08:17 +00005798 de = (struct linux_dirent64 *)((char *)de + reclen);
bellarddab2ed92003-03-22 15:23:14 +00005799 len -= reclen;
5800 }
5801 }
pbrook53a59602006-03-25 19:31:22 +00005802 unlock_user(dirp, arg2, ret);
bellarddab2ed92003-03-22 15:23:14 +00005803 }
5804 break;
bellarda541f292004-04-12 20:39:29 +00005805#endif /* TARGET_NR_getdents64 */
thse5febef2007-04-01 18:31:35 +00005806#ifdef TARGET_NR__newselect
bellard31e31b82003-02-18 22:55:36 +00005807 case TARGET_NR__newselect:
pbrook53a59602006-03-25 19:31:22 +00005808 ret = do_select(arg1, arg2, arg3, arg4, arg5);
bellard31e31b82003-02-18 22:55:36 +00005809 break;
thse5febef2007-04-01 18:31:35 +00005810#endif
5811#ifdef TARGET_NR_poll
bellard9de5e442003-03-23 16:49:39 +00005812 case TARGET_NR_poll:
5813 {
pbrook53a59602006-03-25 19:31:22 +00005814 struct target_pollfd *target_pfd;
bellard9de5e442003-03-23 16:49:39 +00005815 unsigned int nfds = arg2;
5816 int timeout = arg3;
5817 struct pollfd *pfd;
bellard7854b052003-03-29 17:22:23 +00005818 unsigned int i;
bellard9de5e442003-03-23 16:49:39 +00005819
bellard579a97f2007-11-11 14:26:47 +00005820 target_pfd = lock_user(VERIFY_WRITE, arg1, sizeof(struct target_pollfd) * nfds, 1);
5821 if (!target_pfd)
5822 goto efault;
bellard9de5e442003-03-23 16:49:39 +00005823 pfd = alloca(sizeof(struct pollfd) * nfds);
5824 for(i = 0; i < nfds; i++) {
bellard5cd43932003-03-29 16:54:36 +00005825 pfd[i].fd = tswap32(target_pfd[i].fd);
5826 pfd[i].events = tswap16(target_pfd[i].events);
bellard9de5e442003-03-23 16:49:39 +00005827 }
5828 ret = get_errno(poll(pfd, nfds, timeout));
5829 if (!is_error(ret)) {
5830 for(i = 0; i < nfds; i++) {
bellard5cd43932003-03-29 16:54:36 +00005831 target_pfd[i].revents = tswap16(pfd[i].revents);
bellard9de5e442003-03-23 16:49:39 +00005832 }
pbrook53a59602006-03-25 19:31:22 +00005833 ret += nfds * (sizeof(struct target_pollfd)
5834 - sizeof(struct pollfd));
bellard9de5e442003-03-23 16:49:39 +00005835 }
pbrook53a59602006-03-25 19:31:22 +00005836 unlock_user(target_pfd, arg1, ret);
bellard9de5e442003-03-23 16:49:39 +00005837 }
5838 break;
thse5febef2007-04-01 18:31:35 +00005839#endif
bellard31e31b82003-02-18 22:55:36 +00005840 case TARGET_NR_flock:
bellard9de5e442003-03-23 16:49:39 +00005841 /* NOTE: the flock constant seems to be the same for every
5842 Linux platform */
5843 ret = get_errno(flock(arg1, arg2));
bellard31e31b82003-02-18 22:55:36 +00005844 break;
5845 case TARGET_NR_readv:
5846 {
5847 int count = arg3;
bellard31e31b82003-02-18 22:55:36 +00005848 struct iovec *vec;
bellard31e31b82003-02-18 22:55:36 +00005849
5850 vec = alloca(count * sizeof(struct iovec));
bellard41df8412008-02-04 22:26:57 +00005851 if (lock_iovec(VERIFY_WRITE, vec, arg2, count, 0) < 0)
5852 goto efault;
bellard31e31b82003-02-18 22:55:36 +00005853 ret = get_errno(readv(arg1, vec, count));
pbrook53a59602006-03-25 19:31:22 +00005854 unlock_iovec(vec, arg2, count, 1);
bellard31e31b82003-02-18 22:55:36 +00005855 }
5856 break;
5857 case TARGET_NR_writev:
5858 {
5859 int count = arg3;
bellard31e31b82003-02-18 22:55:36 +00005860 struct iovec *vec;
bellard31e31b82003-02-18 22:55:36 +00005861
5862 vec = alloca(count * sizeof(struct iovec));
bellard41df8412008-02-04 22:26:57 +00005863 if (lock_iovec(VERIFY_READ, vec, arg2, count, 1) < 0)
5864 goto efault;
bellard31e31b82003-02-18 22:55:36 +00005865 ret = get_errno(writev(arg1, vec, count));
pbrook53a59602006-03-25 19:31:22 +00005866 unlock_iovec(vec, arg2, count, 0);
bellard31e31b82003-02-18 22:55:36 +00005867 }
5868 break;
5869 case TARGET_NR_getsid:
5870 ret = get_errno(getsid(arg1));
5871 break;
j_mayer7a3148a2007-04-05 07:13:51 +00005872#if defined(TARGET_NR_fdatasync) /* Not on alpha (osf_datasync ?) */
bellard31e31b82003-02-18 22:55:36 +00005873 case TARGET_NR_fdatasync:
bellard5cd43932003-03-29 16:54:36 +00005874 ret = get_errno(fdatasync(arg1));
5875 break;
j_mayer7a3148a2007-04-05 07:13:51 +00005876#endif
bellard31e31b82003-02-18 22:55:36 +00005877 case TARGET_NR__sysctl:
ths0da46a62007-10-20 20:23:07 +00005878 /* We don't implement this, but ENOTDIR is always a safe
bellard29e619b2004-09-13 21:41:04 +00005879 return value. */
ths0da46a62007-10-20 20:23:07 +00005880 ret = -TARGET_ENOTDIR;
5881 break;
bellard31e31b82003-02-18 22:55:36 +00005882 case TARGET_NR_sched_setparam:
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;
pbrook53a59602006-03-25 19:31:22 +00005886
bellard579a97f2007-11-11 14:26:47 +00005887 if (!lock_user_struct(VERIFY_READ, target_schp, arg2, 1))
5888 goto efault;
bellard5cd43932003-03-29 16:54:36 +00005889 schp.sched_priority = tswap32(target_schp->sched_priority);
pbrook53a59602006-03-25 19:31:22 +00005890 unlock_user_struct(target_schp, arg2, 0);
bellard5cd43932003-03-29 16:54:36 +00005891 ret = get_errno(sched_setparam(arg1, &schp));
5892 }
5893 break;
bellard31e31b82003-02-18 22:55:36 +00005894 case TARGET_NR_sched_getparam:
bellard5cd43932003-03-29 16:54:36 +00005895 {
pbrook53a59602006-03-25 19:31:22 +00005896 struct sched_param *target_schp;
bellard5cd43932003-03-29 16:54:36 +00005897 struct sched_param schp;
5898 ret = get_errno(sched_getparam(arg1, &schp));
5899 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00005900 if (!lock_user_struct(VERIFY_WRITE, target_schp, arg2, 0))
5901 goto efault;
bellard5cd43932003-03-29 16:54:36 +00005902 target_schp->sched_priority = tswap32(schp.sched_priority);
pbrook53a59602006-03-25 19:31:22 +00005903 unlock_user_struct(target_schp, arg2, 1);
bellard5cd43932003-03-29 16:54:36 +00005904 }
5905 }
5906 break;
bellard31e31b82003-02-18 22:55:36 +00005907 case TARGET_NR_sched_setscheduler:
bellard5cd43932003-03-29 16:54:36 +00005908 {
pbrook53a59602006-03-25 19:31:22 +00005909 struct sched_param *target_schp;
bellard5cd43932003-03-29 16:54:36 +00005910 struct sched_param schp;
bellard579a97f2007-11-11 14:26:47 +00005911 if (!lock_user_struct(VERIFY_READ, target_schp, arg3, 1))
5912 goto efault;
bellard5cd43932003-03-29 16:54:36 +00005913 schp.sched_priority = tswap32(target_schp->sched_priority);
pbrook53a59602006-03-25 19:31:22 +00005914 unlock_user_struct(target_schp, arg3, 0);
bellard5cd43932003-03-29 16:54:36 +00005915 ret = get_errno(sched_setscheduler(arg1, arg2, &schp));
5916 }
5917 break;
bellard31e31b82003-02-18 22:55:36 +00005918 case TARGET_NR_sched_getscheduler:
bellard5cd43932003-03-29 16:54:36 +00005919 ret = get_errno(sched_getscheduler(arg1));
5920 break;
bellard31e31b82003-02-18 22:55:36 +00005921 case TARGET_NR_sched_yield:
5922 ret = get_errno(sched_yield());
5923 break;
5924 case TARGET_NR_sched_get_priority_max:
bellard5cd43932003-03-29 16:54:36 +00005925 ret = get_errno(sched_get_priority_max(arg1));
5926 break;
bellard31e31b82003-02-18 22:55:36 +00005927 case TARGET_NR_sched_get_priority_min:
bellard5cd43932003-03-29 16:54:36 +00005928 ret = get_errno(sched_get_priority_min(arg1));
5929 break;
bellard31e31b82003-02-18 22:55:36 +00005930 case TARGET_NR_sched_rr_get_interval:
bellard5cd43932003-03-29 16:54:36 +00005931 {
bellard5cd43932003-03-29 16:54:36 +00005932 struct timespec ts;
5933 ret = get_errno(sched_rr_get_interval(arg1, &ts));
5934 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00005935 host_to_target_timespec(arg2, &ts);
bellard5cd43932003-03-29 16:54:36 +00005936 }
5937 }
5938 break;
bellard31e31b82003-02-18 22:55:36 +00005939 case TARGET_NR_nanosleep:
bellard1b6b0292003-03-22 17:31:38 +00005940 {
bellard1b6b0292003-03-22 17:31:38 +00005941 struct timespec req, rem;
pbrook53a59602006-03-25 19:31:22 +00005942 target_to_host_timespec(&req, arg1);
bellard1b6b0292003-03-22 17:31:38 +00005943 ret = get_errno(nanosleep(&req, &rem));
pbrook53a59602006-03-25 19:31:22 +00005944 if (is_error(ret) && arg2) {
5945 host_to_target_timespec(arg2, &rem);
bellard1b6b0292003-03-22 17:31:38 +00005946 }
5947 }
5948 break;
thse5febef2007-04-01 18:31:35 +00005949#ifdef TARGET_NR_query_module
bellard31e31b82003-02-18 22:55:36 +00005950 case TARGET_NR_query_module:
bellard5cd43932003-03-29 16:54:36 +00005951 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00005952#endif
5953#ifdef TARGET_NR_nfsservctl
bellard31e31b82003-02-18 22:55:36 +00005954 case TARGET_NR_nfsservctl:
bellard5cd43932003-03-29 16:54:36 +00005955 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00005956#endif
bellard31e31b82003-02-18 22:55:36 +00005957 case TARGET_NR_prctl:
thse5574482007-02-11 20:03:13 +00005958 switch (arg1)
5959 {
5960 case PR_GET_PDEATHSIG:
5961 {
5962 int deathsig;
5963 ret = get_errno(prctl(arg1, &deathsig, arg3, arg4, arg5));
bellard2f619692007-11-16 10:46:05 +00005964 if (!is_error(ret) && arg2
5965 && put_user_ual(deathsig, arg2))
5966 goto efault;
thse5574482007-02-11 20:03:13 +00005967 }
5968 break;
5969 default:
5970 ret = get_errno(prctl(arg1, arg2, arg3, arg4, arg5));
5971 break;
5972 }
ths39b9aae2007-02-11 18:36:44 +00005973 break;
bellardd2fd1af2007-11-14 18:08:56 +00005974#ifdef TARGET_NR_arch_prctl
5975 case TARGET_NR_arch_prctl:
5976#if defined(TARGET_I386) && !defined(TARGET_ABI32)
5977 ret = do_arch_prctl(cpu_env, arg1, arg2);
5978 break;
5979#else
5980 goto unimplemented;
5981#endif
5982#endif
bellard67867302003-11-23 17:05:30 +00005983#ifdef TARGET_NR_pread
bellard31e31b82003-02-18 22:55:36 +00005984 case TARGET_NR_pread:
balroga4ae00b2008-09-20 03:14:14 +00005985#ifdef TARGET_ARM
5986 if (((CPUARMState *)cpu_env)->eabi)
5987 arg4 = arg5;
5988#endif
bellard579a97f2007-11-11 14:26:47 +00005989 if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
5990 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005991 ret = get_errno(pread(arg1, p, arg3, arg4));
5992 unlock_user(p, arg2, ret);
bellard206f0fa2003-05-14 19:01:56 +00005993 break;
bellard31e31b82003-02-18 22:55:36 +00005994 case TARGET_NR_pwrite:
balroga4ae00b2008-09-20 03:14:14 +00005995#ifdef TARGET_ARM
5996 if (((CPUARMState *)cpu_env)->eabi)
5997 arg4 = arg5;
5998#endif
bellard579a97f2007-11-11 14:26:47 +00005999 if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
6000 goto efault;
pbrook53a59602006-03-25 19:31:22 +00006001 ret = get_errno(pwrite(arg1, p, arg3, arg4));
6002 unlock_user(p, arg2, 0);
bellard206f0fa2003-05-14 19:01:56 +00006003 break;
bellard67867302003-11-23 17:05:30 +00006004#endif
aurel32f2c7ba12008-03-28 22:32:06 +00006005#ifdef TARGET_NR_pread64
6006 case TARGET_NR_pread64:
6007 if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
6008 goto efault;
6009 ret = get_errno(pread64(arg1, p, arg3, target_offset64(arg4, arg5)));
6010 unlock_user(p, arg2, ret);
6011 break;
6012 case TARGET_NR_pwrite64:
6013 if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
6014 goto efault;
6015 ret = get_errno(pwrite64(arg1, p, arg3, target_offset64(arg4, arg5)));
6016 unlock_user(p, arg2, 0);
6017 break;
6018#endif
bellard31e31b82003-02-18 22:55:36 +00006019 case TARGET_NR_getcwd:
bellard579a97f2007-11-11 14:26:47 +00006020 if (!(p = lock_user(VERIFY_WRITE, arg1, arg2, 0)))
6021 goto efault;
pbrook53a59602006-03-25 19:31:22 +00006022 ret = get_errno(sys_getcwd1(p, arg2));
6023 unlock_user(p, arg1, ret);
bellard31e31b82003-02-18 22:55:36 +00006024 break;
6025 case TARGET_NR_capget:
bellard5cd43932003-03-29 16:54:36 +00006026 goto unimplemented;
bellard31e31b82003-02-18 22:55:36 +00006027 case TARGET_NR_capset:
bellard5cd43932003-03-29 16:54:36 +00006028 goto unimplemented;
bellard31e31b82003-02-18 22:55:36 +00006029 case TARGET_NR_sigaltstack:
ths198a74d2007-09-27 16:44:32 +00006030#if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_MIPS) || \
6031 defined(TARGET_SPARC) || defined(TARGET_PPC) || defined(TARGET_ALPHA)
bellard579a97f2007-11-11 14:26:47 +00006032 ret = do_sigaltstack(arg1, arg2, get_sp_from_cpustate((CPUState *)cpu_env));
thsa04e1342007-09-27 13:57:58 +00006033 break;
6034#else
bellard5cd43932003-03-29 16:54:36 +00006035 goto unimplemented;
thsa04e1342007-09-27 13:57:58 +00006036#endif
bellard31e31b82003-02-18 22:55:36 +00006037 case TARGET_NR_sendfile:
bellard5cd43932003-03-29 16:54:36 +00006038 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00006039#ifdef TARGET_NR_getpmsg
bellard31e31b82003-02-18 22:55:36 +00006040 case TARGET_NR_getpmsg:
bellard5cd43932003-03-29 16:54:36 +00006041 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00006042#endif
6043#ifdef TARGET_NR_putpmsg
bellard31e31b82003-02-18 22:55:36 +00006044 case TARGET_NR_putpmsg:
bellard5cd43932003-03-29 16:54:36 +00006045 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00006046#endif
bellard048f6b42005-11-26 18:47:20 +00006047#ifdef TARGET_NR_vfork
bellard31e31b82003-02-18 22:55:36 +00006048 case TARGET_NR_vfork:
pbrookd865bab2008-06-07 22:12:17 +00006049 ret = get_errno(do_fork(cpu_env, CLONE_VFORK | CLONE_VM | SIGCHLD,
6050 0, 0, 0, 0));
bellard31e31b82003-02-18 22:55:36 +00006051 break;
bellard048f6b42005-11-26 18:47:20 +00006052#endif
bellardebc05482003-09-30 21:08:41 +00006053#ifdef TARGET_NR_ugetrlimit
bellard31e31b82003-02-18 22:55:36 +00006054 case TARGET_NR_ugetrlimit:
bellard728584b2003-04-29 20:43:36 +00006055 {
6056 struct rlimit rlim;
6057 ret = get_errno(getrlimit(arg1, &rlim));
6058 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00006059 struct target_rlimit *target_rlim;
bellard579a97f2007-11-11 14:26:47 +00006060 if (!lock_user_struct(VERIFY_WRITE, target_rlim, arg2, 0))
6061 goto efault;
bellard728584b2003-04-29 20:43:36 +00006062 target_rlim->rlim_cur = tswapl(rlim.rlim_cur);
6063 target_rlim->rlim_max = tswapl(rlim.rlim_max);
pbrook53a59602006-03-25 19:31:22 +00006064 unlock_user_struct(target_rlim, arg2, 1);
bellard728584b2003-04-29 20:43:36 +00006065 }
6066 break;
6067 }
bellardebc05482003-09-30 21:08:41 +00006068#endif
bellarda315a142005-01-30 22:59:18 +00006069#ifdef TARGET_NR_truncate64
bellard31e31b82003-02-18 22:55:36 +00006070 case TARGET_NR_truncate64:
bellard579a97f2007-11-11 14:26:47 +00006071 if (!(p = lock_user_string(arg1)))
6072 goto efault;
pbrook53a59602006-03-25 19:31:22 +00006073 ret = target_truncate64(cpu_env, p, arg2, arg3, arg4);
6074 unlock_user(p, arg1, 0);
bellard667f38b2005-07-23 14:46:27 +00006075 break;
bellarda315a142005-01-30 22:59:18 +00006076#endif
6077#ifdef TARGET_NR_ftruncate64
bellard31e31b82003-02-18 22:55:36 +00006078 case TARGET_NR_ftruncate64:
pbrookce4defa2006-02-09 16:49:55 +00006079 ret = target_ftruncate64(cpu_env, arg1, arg2, arg3, arg4);
bellard667f38b2005-07-23 14:46:27 +00006080 break;
bellarda315a142005-01-30 22:59:18 +00006081#endif
6082#ifdef TARGET_NR_stat64
bellard31e31b82003-02-18 22:55:36 +00006083 case TARGET_NR_stat64:
bellard579a97f2007-11-11 14:26:47 +00006084 if (!(p = lock_user_string(arg1)))
6085 goto efault;
pbrook53a59602006-03-25 19:31:22 +00006086 ret = get_errno(stat(path(p), &st));
6087 unlock_user(p, arg1, 0);
balrog6a24a772008-09-20 02:23:36 +00006088 if (!is_error(ret))
6089 ret = host_to_target_stat64(cpu_env, arg2, &st);
6090 break;
bellarda315a142005-01-30 22:59:18 +00006091#endif
6092#ifdef TARGET_NR_lstat64
bellard31e31b82003-02-18 22:55:36 +00006093 case TARGET_NR_lstat64:
bellard579a97f2007-11-11 14:26:47 +00006094 if (!(p = lock_user_string(arg1)))
6095 goto efault;
pbrook53a59602006-03-25 19:31:22 +00006096 ret = get_errno(lstat(path(p), &st));
6097 unlock_user(p, arg1, 0);
balrog6a24a772008-09-20 02:23:36 +00006098 if (!is_error(ret))
6099 ret = host_to_target_stat64(cpu_env, arg2, &st);
6100 break;
bellarda315a142005-01-30 22:59:18 +00006101#endif
6102#ifdef TARGET_NR_fstat64
bellard31e31b82003-02-18 22:55:36 +00006103 case TARGET_NR_fstat64:
balrog6a24a772008-09-20 02:23:36 +00006104 ret = get_errno(fstat(arg1, &st));
6105 if (!is_error(ret))
6106 ret = host_to_target_stat64(cpu_env, arg2, &st);
6107 break;
bellardec86b0f2003-04-11 00:15:04 +00006108#endif
aurel329d33b762009-04-08 23:07:05 +00006109#if (defined(TARGET_NR_fstatat64) || defined(TARGET_NR_newfstatat)) && \
6110 (defined(__NR_fstatat64) || defined(__NR_newfstatat))
6111#ifdef TARGET_NR_fstatat64
balrog6a24a772008-09-20 02:23:36 +00006112 case TARGET_NR_fstatat64:
aurel329d33b762009-04-08 23:07:05 +00006113#endif
6114#ifdef TARGET_NR_newfstatat
6115 case TARGET_NR_newfstatat:
6116#endif
balrog6a24a772008-09-20 02:23:36 +00006117 if (!(p = lock_user_string(arg2)))
6118 goto efault;
aurel329d33b762009-04-08 23:07:05 +00006119#ifdef __NR_fstatat64
balrog6a24a772008-09-20 02:23:36 +00006120 ret = get_errno(sys_fstatat64(arg1, path(p), &st, arg4));
aurel329d33b762009-04-08 23:07:05 +00006121#else
6122 ret = get_errno(sys_newfstatat(arg1, path(p), &st, arg4));
6123#endif
balrog6a24a772008-09-20 02:23:36 +00006124 if (!is_error(ret))
6125 ret = host_to_target_stat64(cpu_env, arg3, &st);
bellard60cd49d2003-03-16 22:53:56 +00006126 break;
bellarda315a142005-01-30 22:59:18 +00006127#endif
bellard67867302003-11-23 17:05:30 +00006128#ifdef USE_UID16
6129 case TARGET_NR_lchown:
bellard579a97f2007-11-11 14:26:47 +00006130 if (!(p = lock_user_string(arg1)))
6131 goto efault;
pbrook53a59602006-03-25 19:31:22 +00006132 ret = get_errno(lchown(p, low2highuid(arg2), low2highgid(arg3)));
6133 unlock_user(p, arg1, 0);
bellard67867302003-11-23 17:05:30 +00006134 break;
6135 case TARGET_NR_getuid:
6136 ret = get_errno(high2lowuid(getuid()));
6137 break;
6138 case TARGET_NR_getgid:
6139 ret = get_errno(high2lowgid(getgid()));
6140 break;
6141 case TARGET_NR_geteuid:
6142 ret = get_errno(high2lowuid(geteuid()));
6143 break;
6144 case TARGET_NR_getegid:
6145 ret = get_errno(high2lowgid(getegid()));
6146 break;
6147 case TARGET_NR_setreuid:
6148 ret = get_errno(setreuid(low2highuid(arg1), low2highuid(arg2)));
6149 break;
6150 case TARGET_NR_setregid:
6151 ret = get_errno(setregid(low2highgid(arg1), low2highgid(arg2)));
6152 break;
6153 case TARGET_NR_getgroups:
6154 {
6155 int gidsetsize = arg1;
pbrook53a59602006-03-25 19:31:22 +00006156 uint16_t *target_grouplist;
bellard67867302003-11-23 17:05:30 +00006157 gid_t *grouplist;
6158 int i;
6159
6160 grouplist = alloca(gidsetsize * sizeof(gid_t));
6161 ret = get_errno(getgroups(gidsetsize, grouplist));
balrogcb3bc232008-09-20 02:08:13 +00006162 if (gidsetsize == 0)
6163 break;
bellard67867302003-11-23 17:05:30 +00006164 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00006165 target_grouplist = lock_user(VERIFY_WRITE, arg2, gidsetsize * 2, 0);
6166 if (!target_grouplist)
6167 goto efault;
balroga2155fc2008-09-20 02:12:08 +00006168 for(i = 0;i < ret; i++)
bellard67867302003-11-23 17:05:30 +00006169 target_grouplist[i] = tswap16(grouplist[i]);
pbrook53a59602006-03-25 19:31:22 +00006170 unlock_user(target_grouplist, arg2, gidsetsize * 2);
bellard67867302003-11-23 17:05:30 +00006171 }
6172 }
6173 break;
6174 case TARGET_NR_setgroups:
6175 {
6176 int gidsetsize = arg1;
pbrook53a59602006-03-25 19:31:22 +00006177 uint16_t *target_grouplist;
bellard67867302003-11-23 17:05:30 +00006178 gid_t *grouplist;
6179 int i;
6180
6181 grouplist = alloca(gidsetsize * sizeof(gid_t));
bellard579a97f2007-11-11 14:26:47 +00006182 target_grouplist = lock_user(VERIFY_READ, arg2, gidsetsize * 2, 1);
6183 if (!target_grouplist) {
6184 ret = -TARGET_EFAULT;
6185 goto fail;
6186 }
bellard67867302003-11-23 17:05:30 +00006187 for(i = 0;i < gidsetsize; i++)
6188 grouplist[i] = tswap16(target_grouplist[i]);
pbrook53a59602006-03-25 19:31:22 +00006189 unlock_user(target_grouplist, arg2, 0);
bellard67867302003-11-23 17:05:30 +00006190 ret = get_errno(setgroups(gidsetsize, grouplist));
6191 }
6192 break;
6193 case TARGET_NR_fchown:
6194 ret = get_errno(fchown(arg1, low2highuid(arg2), low2highgid(arg3)));
6195 break;
thsccfa72b2007-09-24 09:23:34 +00006196#if defined(TARGET_NR_fchownat) && defined(__NR_fchownat)
6197 case TARGET_NR_fchownat:
bellard579a97f2007-11-11 14:26:47 +00006198 if (!(p = lock_user_string(arg2)))
6199 goto efault;
6200 ret = get_errno(sys_fchownat(arg1, p, low2highuid(arg3), low2highgid(arg4), arg5));
6201 unlock_user(p, arg2, 0);
thsccfa72b2007-09-24 09:23:34 +00006202 break;
6203#endif
bellard67867302003-11-23 17:05:30 +00006204#ifdef TARGET_NR_setresuid
6205 case TARGET_NR_setresuid:
ths5fafdf22007-09-16 21:08:06 +00006206 ret = get_errno(setresuid(low2highuid(arg1),
6207 low2highuid(arg2),
bellard67867302003-11-23 17:05:30 +00006208 low2highuid(arg3)));
6209 break;
6210#endif
6211#ifdef TARGET_NR_getresuid
6212 case TARGET_NR_getresuid:
6213 {
pbrook53a59602006-03-25 19:31:22 +00006214 uid_t ruid, euid, suid;
bellard67867302003-11-23 17:05:30 +00006215 ret = get_errno(getresuid(&ruid, &euid, &suid));
6216 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +00006217 if (put_user_u16(high2lowuid(ruid), arg1)
6218 || put_user_u16(high2lowuid(euid), arg2)
6219 || put_user_u16(high2lowuid(suid), arg3))
6220 goto efault;
bellard67867302003-11-23 17:05:30 +00006221 }
6222 }
6223 break;
6224#endif
6225#ifdef TARGET_NR_getresgid
6226 case TARGET_NR_setresgid:
ths5fafdf22007-09-16 21:08:06 +00006227 ret = get_errno(setresgid(low2highgid(arg1),
6228 low2highgid(arg2),
bellard67867302003-11-23 17:05:30 +00006229 low2highgid(arg3)));
6230 break;
6231#endif
6232#ifdef TARGET_NR_getresgid
6233 case TARGET_NR_getresgid:
6234 {
pbrook53a59602006-03-25 19:31:22 +00006235 gid_t rgid, egid, sgid;
bellard67867302003-11-23 17:05:30 +00006236 ret = get_errno(getresgid(&rgid, &egid, &sgid));
6237 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +00006238 if (put_user_u16(high2lowgid(rgid), arg1)
6239 || put_user_u16(high2lowgid(egid), arg2)
6240 || put_user_u16(high2lowgid(sgid), arg3))
6241 goto efault;
bellard67867302003-11-23 17:05:30 +00006242 }
6243 }
6244 break;
6245#endif
6246 case TARGET_NR_chown:
bellard579a97f2007-11-11 14:26:47 +00006247 if (!(p = lock_user_string(arg1)))
6248 goto efault;
pbrook53a59602006-03-25 19:31:22 +00006249 ret = get_errno(chown(p, low2highuid(arg2), low2highgid(arg3)));
6250 unlock_user(p, arg1, 0);
bellard67867302003-11-23 17:05:30 +00006251 break;
6252 case TARGET_NR_setuid:
6253 ret = get_errno(setuid(low2highuid(arg1)));
6254 break;
6255 case TARGET_NR_setgid:
6256 ret = get_errno(setgid(low2highgid(arg1)));
6257 break;
6258 case TARGET_NR_setfsuid:
6259 ret = get_errno(setfsuid(arg1));
6260 break;
6261 case TARGET_NR_setfsgid:
6262 ret = get_errno(setfsgid(arg1));
6263 break;
6264#endif /* USE_UID16 */
6265
bellarda315a142005-01-30 22:59:18 +00006266#ifdef TARGET_NR_lchown32
bellard31e31b82003-02-18 22:55:36 +00006267 case TARGET_NR_lchown32:
bellard579a97f2007-11-11 14:26:47 +00006268 if (!(p = lock_user_string(arg1)))
6269 goto efault;
pbrook53a59602006-03-25 19:31:22 +00006270 ret = get_errno(lchown(p, arg2, arg3));
6271 unlock_user(p, arg1, 0);
bellardb03c60f2003-03-23 17:19:56 +00006272 break;
bellarda315a142005-01-30 22:59:18 +00006273#endif
6274#ifdef TARGET_NR_getuid32
bellard31e31b82003-02-18 22:55:36 +00006275 case TARGET_NR_getuid32:
bellardb03c60f2003-03-23 17:19:56 +00006276 ret = get_errno(getuid());
6277 break;
bellarda315a142005-01-30 22:59:18 +00006278#endif
aurel3264b4d282008-11-14 17:20:15 +00006279
6280#if defined(TARGET_NR_getxuid) && defined(TARGET_ALPHA)
6281 /* Alpha specific */
6282 case TARGET_NR_getxuid:
6283 {
6284 uid_t euid;
6285 euid=geteuid();
6286 ((CPUAlphaState *)cpu_env)->ir[IR_A4]=euid;
6287 }
6288 ret = get_errno(getuid());
6289 break;
6290#endif
6291#if defined(TARGET_NR_getxgid) && defined(TARGET_ALPHA)
6292 /* Alpha specific */
6293 case TARGET_NR_getxgid:
6294 {
6295 uid_t egid;
6296 egid=getegid();
6297 ((CPUAlphaState *)cpu_env)->ir[IR_A4]=egid;
6298 }
6299 ret = get_errno(getgid());
6300 break;
6301#endif
6302
bellarda315a142005-01-30 22:59:18 +00006303#ifdef TARGET_NR_getgid32
bellard31e31b82003-02-18 22:55:36 +00006304 case TARGET_NR_getgid32:
bellardb03c60f2003-03-23 17:19:56 +00006305 ret = get_errno(getgid());
6306 break;
bellarda315a142005-01-30 22:59:18 +00006307#endif
6308#ifdef TARGET_NR_geteuid32
bellard31e31b82003-02-18 22:55:36 +00006309 case TARGET_NR_geteuid32:
bellardb03c60f2003-03-23 17:19:56 +00006310 ret = get_errno(geteuid());
6311 break;
bellarda315a142005-01-30 22:59:18 +00006312#endif
6313#ifdef TARGET_NR_getegid32
bellard31e31b82003-02-18 22:55:36 +00006314 case TARGET_NR_getegid32:
bellardb03c60f2003-03-23 17:19:56 +00006315 ret = get_errno(getegid());
6316 break;
bellarda315a142005-01-30 22:59:18 +00006317#endif
6318#ifdef TARGET_NR_setreuid32
bellard31e31b82003-02-18 22:55:36 +00006319 case TARGET_NR_setreuid32:
bellardb03c60f2003-03-23 17:19:56 +00006320 ret = get_errno(setreuid(arg1, arg2));
6321 break;
bellarda315a142005-01-30 22:59:18 +00006322#endif
6323#ifdef TARGET_NR_setregid32
bellard31e31b82003-02-18 22:55:36 +00006324 case TARGET_NR_setregid32:
bellardb03c60f2003-03-23 17:19:56 +00006325 ret = get_errno(setregid(arg1, arg2));
6326 break;
bellarda315a142005-01-30 22:59:18 +00006327#endif
6328#ifdef TARGET_NR_getgroups32
bellard31e31b82003-02-18 22:55:36 +00006329 case TARGET_NR_getgroups32:
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;
6335
6336 grouplist = alloca(gidsetsize * sizeof(gid_t));
6337 ret = get_errno(getgroups(gidsetsize, grouplist));
balrogcb3bc232008-09-20 02:08:13 +00006338 if (gidsetsize == 0)
6339 break;
bellard99c475a2005-01-31 20:45:13 +00006340 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00006341 target_grouplist = lock_user(VERIFY_WRITE, arg2, gidsetsize * 4, 0);
6342 if (!target_grouplist) {
6343 ret = -TARGET_EFAULT;
6344 goto fail;
6345 }
balroga2155fc2008-09-20 02:12:08 +00006346 for(i = 0;i < ret; i++)
pbrook53a59602006-03-25 19:31:22 +00006347 target_grouplist[i] = tswap32(grouplist[i]);
6348 unlock_user(target_grouplist, arg2, gidsetsize * 4);
bellard99c475a2005-01-31 20:45:13 +00006349 }
6350 }
6351 break;
bellarda315a142005-01-30 22:59:18 +00006352#endif
6353#ifdef TARGET_NR_setgroups32
bellard31e31b82003-02-18 22:55:36 +00006354 case TARGET_NR_setgroups32:
bellard99c475a2005-01-31 20:45:13 +00006355 {
6356 int gidsetsize = arg1;
pbrook53a59602006-03-25 19:31:22 +00006357 uint32_t *target_grouplist;
bellard99c475a2005-01-31 20:45:13 +00006358 gid_t *grouplist;
6359 int i;
ths3b46e622007-09-17 08:09:54 +00006360
bellard99c475a2005-01-31 20:45:13 +00006361 grouplist = alloca(gidsetsize * sizeof(gid_t));
bellard579a97f2007-11-11 14:26:47 +00006362 target_grouplist = lock_user(VERIFY_READ, arg2, gidsetsize * 4, 1);
6363 if (!target_grouplist) {
6364 ret = -TARGET_EFAULT;
6365 goto fail;
6366 }
bellard99c475a2005-01-31 20:45:13 +00006367 for(i = 0;i < gidsetsize; i++)
pbrook53a59602006-03-25 19:31:22 +00006368 grouplist[i] = tswap32(target_grouplist[i]);
6369 unlock_user(target_grouplist, arg2, 0);
bellard99c475a2005-01-31 20:45:13 +00006370 ret = get_errno(setgroups(gidsetsize, grouplist));
6371 }
6372 break;
bellarda315a142005-01-30 22:59:18 +00006373#endif
6374#ifdef TARGET_NR_fchown32
bellard31e31b82003-02-18 22:55:36 +00006375 case TARGET_NR_fchown32:
bellardb03c60f2003-03-23 17:19:56 +00006376 ret = get_errno(fchown(arg1, arg2, arg3));
6377 break;
bellarda315a142005-01-30 22:59:18 +00006378#endif
6379#ifdef TARGET_NR_setresuid32
bellard31e31b82003-02-18 22:55:36 +00006380 case TARGET_NR_setresuid32:
bellardb03c60f2003-03-23 17:19:56 +00006381 ret = get_errno(setresuid(arg1, arg2, arg3));
6382 break;
bellarda315a142005-01-30 22:59:18 +00006383#endif
6384#ifdef TARGET_NR_getresuid32
bellard31e31b82003-02-18 22:55:36 +00006385 case TARGET_NR_getresuid32:
bellardb03c60f2003-03-23 17:19:56 +00006386 {
pbrook53a59602006-03-25 19:31:22 +00006387 uid_t ruid, euid, suid;
bellardb03c60f2003-03-23 17:19:56 +00006388 ret = get_errno(getresuid(&ruid, &euid, &suid));
6389 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +00006390 if (put_user_u32(ruid, arg1)
6391 || put_user_u32(euid, arg2)
6392 || put_user_u32(suid, arg3))
6393 goto efault;
bellardb03c60f2003-03-23 17:19:56 +00006394 }
6395 }
6396 break;
bellarda315a142005-01-30 22:59:18 +00006397#endif
6398#ifdef TARGET_NR_setresgid32
bellard31e31b82003-02-18 22:55:36 +00006399 case TARGET_NR_setresgid32:
bellardb03c60f2003-03-23 17:19:56 +00006400 ret = get_errno(setresgid(arg1, arg2, arg3));
6401 break;
bellarda315a142005-01-30 22:59:18 +00006402#endif
6403#ifdef TARGET_NR_getresgid32
bellard31e31b82003-02-18 22:55:36 +00006404 case TARGET_NR_getresgid32:
bellardb03c60f2003-03-23 17:19:56 +00006405 {
pbrook53a59602006-03-25 19:31:22 +00006406 gid_t rgid, egid, sgid;
bellardb03c60f2003-03-23 17:19:56 +00006407 ret = get_errno(getresgid(&rgid, &egid, &sgid));
6408 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +00006409 if (put_user_u32(rgid, arg1)
6410 || put_user_u32(egid, arg2)
6411 || put_user_u32(sgid, arg3))
6412 goto efault;
bellardb03c60f2003-03-23 17:19:56 +00006413 }
6414 }
6415 break;
bellarda315a142005-01-30 22:59:18 +00006416#endif
6417#ifdef TARGET_NR_chown32
bellard31e31b82003-02-18 22:55:36 +00006418 case TARGET_NR_chown32:
bellard579a97f2007-11-11 14:26:47 +00006419 if (!(p = lock_user_string(arg1)))
6420 goto efault;
pbrook53a59602006-03-25 19:31:22 +00006421 ret = get_errno(chown(p, arg2, arg3));
6422 unlock_user(p, arg1, 0);
bellardb03c60f2003-03-23 17:19:56 +00006423 break;
bellarda315a142005-01-30 22:59:18 +00006424#endif
6425#ifdef TARGET_NR_setuid32
bellard31e31b82003-02-18 22:55:36 +00006426 case TARGET_NR_setuid32:
bellardb03c60f2003-03-23 17:19:56 +00006427 ret = get_errno(setuid(arg1));
6428 break;
bellarda315a142005-01-30 22:59:18 +00006429#endif
6430#ifdef TARGET_NR_setgid32
bellard31e31b82003-02-18 22:55:36 +00006431 case TARGET_NR_setgid32:
bellardb03c60f2003-03-23 17:19:56 +00006432 ret = get_errno(setgid(arg1));
6433 break;
bellarda315a142005-01-30 22:59:18 +00006434#endif
6435#ifdef TARGET_NR_setfsuid32
bellard31e31b82003-02-18 22:55:36 +00006436 case TARGET_NR_setfsuid32:
bellardb03c60f2003-03-23 17:19:56 +00006437 ret = get_errno(setfsuid(arg1));
6438 break;
bellarda315a142005-01-30 22:59:18 +00006439#endif
6440#ifdef TARGET_NR_setfsgid32
bellard31e31b82003-02-18 22:55:36 +00006441 case TARGET_NR_setfsgid32:
bellardb03c60f2003-03-23 17:19:56 +00006442 ret = get_errno(setfsgid(arg1));
6443 break;
bellarda315a142005-01-30 22:59:18 +00006444#endif
bellard67867302003-11-23 17:05:30 +00006445
bellard31e31b82003-02-18 22:55:36 +00006446 case TARGET_NR_pivot_root:
bellardb03c60f2003-03-23 17:19:56 +00006447 goto unimplemented;
bellardffa65c32004-01-04 23:57:22 +00006448#ifdef TARGET_NR_mincore
bellard31e31b82003-02-18 22:55:36 +00006449 case TARGET_NR_mincore:
aurel3204bb9ac2008-10-01 21:46:41 +00006450 {
6451 void *a;
6452 ret = -TARGET_EFAULT;
6453 if (!(a = lock_user(VERIFY_READ, arg1,arg2, 0)))
6454 goto efault;
6455 if (!(p = lock_user_string(arg3)))
6456 goto mincore_fail;
6457 ret = get_errno(mincore(a, arg2, p));
6458 unlock_user(p, arg3, ret);
6459 mincore_fail:
6460 unlock_user(a, arg1, 0);
6461 }
6462 break;
bellardffa65c32004-01-04 23:57:22 +00006463#endif
aurel32408321b2008-10-01 21:46:32 +00006464#ifdef TARGET_NR_arm_fadvise64_64
6465 case TARGET_NR_arm_fadvise64_64:
6466 {
6467 /*
6468 * arm_fadvise64_64 looks like fadvise64_64 but
6469 * with different argument order
6470 */
6471 abi_long temp;
6472 temp = arg3;
6473 arg3 = arg4;
6474 arg4 = temp;
6475 }
6476#endif
6477#if defined(TARGET_NR_fadvise64_64) || defined(TARGET_NR_arm_fadvise64_64)
6478#ifdef TARGET_NR_fadvise64_64
6479 case TARGET_NR_fadvise64_64:
6480#endif
6481 /* This is a hint, so ignoring and returning success is ok. */
6482 ret = get_errno(0);
6483 break;
6484#endif
bellardffa65c32004-01-04 23:57:22 +00006485#ifdef TARGET_NR_madvise
bellard31e31b82003-02-18 22:55:36 +00006486 case TARGET_NR_madvise:
pbrook24836682006-04-16 14:14:53 +00006487 /* A straight passthrough may not be safe because qemu sometimes
6488 turns private flie-backed mappings into anonymous mappings.
6489 This will break MADV_DONTNEED.
6490 This is a hint, so ignoring and returning success is ok. */
6491 ret = get_errno(0);
6492 break;
bellardffa65c32004-01-04 23:57:22 +00006493#endif
blueswir1992f48a2007-10-14 16:27:31 +00006494#if TARGET_ABI_BITS == 32
bellard31e31b82003-02-18 22:55:36 +00006495 case TARGET_NR_fcntl64:
bellard77e46722003-04-29 20:39:06 +00006496 {
thsb1e341e2007-03-20 21:50:52 +00006497 int cmd;
bellard77e46722003-04-29 20:39:06 +00006498 struct flock64 fl;
pbrook53a59602006-03-25 19:31:22 +00006499 struct target_flock64 *target_fl;
pbrookce4defa2006-02-09 16:49:55 +00006500#ifdef TARGET_ARM
pbrook53a59602006-03-25 19:31:22 +00006501 struct target_eabi_flock64 *target_efl;
pbrookce4defa2006-02-09 16:49:55 +00006502#endif
bellard77e46722003-04-29 20:39:06 +00006503
thsb1e341e2007-03-20 21:50:52 +00006504 switch(arg2){
6505 case TARGET_F_GETLK64:
6506 cmd = F_GETLK64;
thsa7222582007-03-22 15:08:55 +00006507 break;
thsb1e341e2007-03-20 21:50:52 +00006508 case TARGET_F_SETLK64:
6509 cmd = F_SETLK64;
thsa7222582007-03-22 15:08:55 +00006510 break;
thsb1e341e2007-03-20 21:50:52 +00006511 case TARGET_F_SETLKW64:
6512 cmd = F_SETLK64;
thsa7222582007-03-22 15:08:55 +00006513 break;
thsb1e341e2007-03-20 21:50:52 +00006514 default:
6515 cmd = arg2;
thsa7222582007-03-22 15:08:55 +00006516 break;
thsb1e341e2007-03-20 21:50:52 +00006517 }
6518
bellard60cd49d2003-03-16 22:53:56 +00006519 switch(arg2) {
thsb1e341e2007-03-20 21:50:52 +00006520 case TARGET_F_GETLK64:
ths58134272007-03-31 18:59:32 +00006521#ifdef TARGET_ARM
6522 if (((CPUARMState *)cpu_env)->eabi) {
bellard9ee1fa22007-11-11 15:11:19 +00006523 if (!lock_user_struct(VERIFY_READ, target_efl, arg3, 1))
6524 goto efault;
ths58134272007-03-31 18:59:32 +00006525 fl.l_type = tswap16(target_efl->l_type);
6526 fl.l_whence = tswap16(target_efl->l_whence);
6527 fl.l_start = tswap64(target_efl->l_start);
6528 fl.l_len = tswap64(target_efl->l_len);
6529 fl.l_pid = tswapl(target_efl->l_pid);
6530 unlock_user_struct(target_efl, arg3, 0);
6531 } else
6532#endif
6533 {
bellard9ee1fa22007-11-11 15:11:19 +00006534 if (!lock_user_struct(VERIFY_READ, target_fl, arg3, 1))
6535 goto efault;
ths58134272007-03-31 18:59:32 +00006536 fl.l_type = tswap16(target_fl->l_type);
6537 fl.l_whence = tswap16(target_fl->l_whence);
6538 fl.l_start = tswap64(target_fl->l_start);
6539 fl.l_len = tswap64(target_fl->l_len);
6540 fl.l_pid = tswapl(target_fl->l_pid);
6541 unlock_user_struct(target_fl, arg3, 0);
6542 }
thsb1e341e2007-03-20 21:50:52 +00006543 ret = get_errno(fcntl(arg1, cmd, &fl));
bellard77e46722003-04-29 20:39:06 +00006544 if (ret == 0) {
pbrookce4defa2006-02-09 16:49:55 +00006545#ifdef TARGET_ARM
6546 if (((CPUARMState *)cpu_env)->eabi) {
bellard9ee1fa22007-11-11 15:11:19 +00006547 if (!lock_user_struct(VERIFY_WRITE, target_efl, arg3, 0))
6548 goto efault;
pbrookce4defa2006-02-09 16:49:55 +00006549 target_efl->l_type = tswap16(fl.l_type);
6550 target_efl->l_whence = tswap16(fl.l_whence);
6551 target_efl->l_start = tswap64(fl.l_start);
6552 target_efl->l_len = tswap64(fl.l_len);
6553 target_efl->l_pid = tswapl(fl.l_pid);
pbrook53a59602006-03-25 19:31:22 +00006554 unlock_user_struct(target_efl, arg3, 1);
pbrookce4defa2006-02-09 16:49:55 +00006555 } else
6556#endif
6557 {
bellard9ee1fa22007-11-11 15:11:19 +00006558 if (!lock_user_struct(VERIFY_WRITE, target_fl, arg3, 0))
6559 goto efault;
pbrookce4defa2006-02-09 16:49:55 +00006560 target_fl->l_type = tswap16(fl.l_type);
6561 target_fl->l_whence = tswap16(fl.l_whence);
6562 target_fl->l_start = tswap64(fl.l_start);
6563 target_fl->l_len = tswap64(fl.l_len);
6564 target_fl->l_pid = tswapl(fl.l_pid);
pbrook53a59602006-03-25 19:31:22 +00006565 unlock_user_struct(target_fl, arg3, 1);
pbrookce4defa2006-02-09 16:49:55 +00006566 }
bellard77e46722003-04-29 20:39:06 +00006567 }
6568 break;
6569
thsb1e341e2007-03-20 21:50:52 +00006570 case TARGET_F_SETLK64:
6571 case TARGET_F_SETLKW64:
pbrookce4defa2006-02-09 16:49:55 +00006572#ifdef TARGET_ARM
6573 if (((CPUARMState *)cpu_env)->eabi) {
bellard9ee1fa22007-11-11 15:11:19 +00006574 if (!lock_user_struct(VERIFY_READ, target_efl, arg3, 1))
6575 goto efault;
pbrookce4defa2006-02-09 16:49:55 +00006576 fl.l_type = tswap16(target_efl->l_type);
6577 fl.l_whence = tswap16(target_efl->l_whence);
6578 fl.l_start = tswap64(target_efl->l_start);
6579 fl.l_len = tswap64(target_efl->l_len);
6580 fl.l_pid = tswapl(target_efl->l_pid);
pbrook53a59602006-03-25 19:31:22 +00006581 unlock_user_struct(target_efl, arg3, 0);
pbrookce4defa2006-02-09 16:49:55 +00006582 } else
6583#endif
6584 {
bellard9ee1fa22007-11-11 15:11:19 +00006585 if (!lock_user_struct(VERIFY_READ, target_fl, arg3, 1))
6586 goto efault;
pbrookce4defa2006-02-09 16:49:55 +00006587 fl.l_type = tswap16(target_fl->l_type);
6588 fl.l_whence = tswap16(target_fl->l_whence);
6589 fl.l_start = tswap64(target_fl->l_start);
6590 fl.l_len = tswap64(target_fl->l_len);
6591 fl.l_pid = tswapl(target_fl->l_pid);
pbrook53a59602006-03-25 19:31:22 +00006592 unlock_user_struct(target_fl, arg3, 0);
pbrookce4defa2006-02-09 16:49:55 +00006593 }
thsb1e341e2007-03-20 21:50:52 +00006594 ret = get_errno(fcntl(arg1, cmd, &fl));
bellard77e46722003-04-29 20:39:06 +00006595 break;
bellard60cd49d2003-03-16 22:53:56 +00006596 default:
bellard9ee1fa22007-11-11 15:11:19 +00006597 ret = do_fcntl(arg1, cmd, arg3);
bellard60cd49d2003-03-16 22:53:56 +00006598 break;
6599 }
bellard77e46722003-04-29 20:39:06 +00006600 break;
6601 }
bellard60cd49d2003-03-16 22:53:56 +00006602#endif
ths7d600c82006-12-08 01:32:58 +00006603#ifdef TARGET_NR_cacheflush
6604 case TARGET_NR_cacheflush:
6605 /* self-modifying code is handled automatically, so nothing needed */
6606 ret = 0;
6607 break;
6608#endif
bellardebc05482003-09-30 21:08:41 +00006609#ifdef TARGET_NR_security
bellard31e31b82003-02-18 22:55:36 +00006610 case TARGET_NR_security:
6611 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00006612#endif
bellardc573ff62004-01-04 15:51:36 +00006613#ifdef TARGET_NR_getpagesize
6614 case TARGET_NR_getpagesize:
6615 ret = TARGET_PAGE_SIZE;
6616 break;
6617#endif
bellard31e31b82003-02-18 22:55:36 +00006618 case TARGET_NR_gettid:
6619 ret = get_errno(gettid());
6620 break;
thse5febef2007-04-01 18:31:35 +00006621#ifdef TARGET_NR_readahead
bellard31e31b82003-02-18 22:55:36 +00006622 case TARGET_NR_readahead:
aurel322054ac92008-10-13 21:08:07 +00006623#if TARGET_ABI_BITS == 32
6624#ifdef TARGET_ARM
6625 if (((CPUARMState *)cpu_env)->eabi)
6626 {
6627 arg2 = arg3;
6628 arg3 = arg4;
6629 arg4 = arg5;
6630 }
6631#endif
6632 ret = get_errno(readahead(arg1, ((off64_t)arg3 << 32) | arg2, arg4));
6633#else
6634 ret = get_errno(readahead(arg1, arg2, arg3));
6635#endif
6636 break;
thse5febef2007-04-01 18:31:35 +00006637#endif
bellardebc05482003-09-30 21:08:41 +00006638#ifdef TARGET_NR_setxattr
bellard31e31b82003-02-18 22:55:36 +00006639 case TARGET_NR_setxattr:
6640 case TARGET_NR_lsetxattr:
6641 case TARGET_NR_fsetxattr:
6642 case TARGET_NR_getxattr:
6643 case TARGET_NR_lgetxattr:
6644 case TARGET_NR_fgetxattr:
6645 case TARGET_NR_listxattr:
6646 case TARGET_NR_llistxattr:
6647 case TARGET_NR_flistxattr:
6648 case TARGET_NR_removexattr:
6649 case TARGET_NR_lremovexattr:
6650 case TARGET_NR_fremovexattr:
Arnaud Patard6f932f92009-04-21 21:04:18 +03006651 ret = -TARGET_EOPNOTSUPP;
6652 break;
bellardebc05482003-09-30 21:08:41 +00006653#endif
6654#ifdef TARGET_NR_set_thread_area
bellard5cd43932003-03-29 16:54:36 +00006655 case TARGET_NR_set_thread_area:
bellard8d18e892007-11-14 15:18:40 +00006656#if defined(TARGET_MIPS)
ths6f5b89a2007-03-02 20:48:00 +00006657 ((CPUMIPSState *) cpu_env)->tls_value = arg1;
6658 ret = 0;
6659 break;
edgar_iglef967792009-01-07 14:19:38 +00006660#elif defined(TARGET_CRIS)
6661 if (arg1 & 0xff)
6662 ret = -TARGET_EINVAL;
6663 else {
6664 ((CPUCRISState *) cpu_env)->pregs[PR_PID] = arg1;
6665 ret = 0;
6666 }
6667 break;
bellard8d18e892007-11-14 15:18:40 +00006668#elif defined(TARGET_I386) && defined(TARGET_ABI32)
6669 ret = do_set_thread_area(cpu_env, arg1);
6670 break;
ths6f5b89a2007-03-02 20:48:00 +00006671#else
6672 goto unimplemented_nowarn;
6673#endif
6674#endif
6675#ifdef TARGET_NR_get_thread_area
bellard5cd43932003-03-29 16:54:36 +00006676 case TARGET_NR_get_thread_area:
bellard8d18e892007-11-14 15:18:40 +00006677#if defined(TARGET_I386) && defined(TARGET_ABI32)
6678 ret = do_get_thread_area(cpu_env, arg1);
6679#else
bellard5cd43932003-03-29 16:54:36 +00006680 goto unimplemented_nowarn;
bellardebc05482003-09-30 21:08:41 +00006681#endif
bellard8d18e892007-11-14 15:18:40 +00006682#endif
bellard48dc41e2006-06-21 18:15:50 +00006683#ifdef TARGET_NR_getdomainname
6684 case TARGET_NR_getdomainname:
6685 goto unimplemented_nowarn;
6686#endif
ths6f5b89a2007-03-02 20:48:00 +00006687
thsb5906f92007-03-19 13:32:45 +00006688#ifdef TARGET_NR_clock_gettime
6689 case TARGET_NR_clock_gettime:
6690 {
6691 struct timespec ts;
6692 ret = get_errno(clock_gettime(arg1, &ts));
6693 if (!is_error(ret)) {
6694 host_to_target_timespec(arg2, &ts);
6695 }
6696 break;
6697 }
6698#endif
6699#ifdef TARGET_NR_clock_getres
6700 case TARGET_NR_clock_getres:
6701 {
6702 struct timespec ts;
6703 ret = get_errno(clock_getres(arg1, &ts));
6704 if (!is_error(ret)) {
6705 host_to_target_timespec(arg2, &ts);
6706 }
6707 break;
6708 }
6709#endif
pbrook63d76512008-05-29 13:43:29 +00006710#ifdef TARGET_NR_clock_nanosleep
6711 case TARGET_NR_clock_nanosleep:
6712 {
6713 struct timespec ts;
6714 target_to_host_timespec(&ts, arg3);
6715 ret = get_errno(clock_nanosleep(arg1, arg2, &ts, arg4 ? &ts : NULL));
6716 if (arg4)
6717 host_to_target_timespec(arg4, &ts);
6718 break;
6719 }
6720#endif
thsb5906f92007-03-19 13:32:45 +00006721
ths6f5b89a2007-03-02 20:48:00 +00006722#if defined(TARGET_NR_set_tid_address) && defined(__NR_set_tid_address)
6723 case TARGET_NR_set_tid_address:
bellard579a97f2007-11-11 14:26:47 +00006724 ret = get_errno(set_tid_address((int *)g2h(arg1)));
6725 break;
ths6f5b89a2007-03-02 20:48:00 +00006726#endif
6727
ths3ae43202007-09-16 21:39:48 +00006728#if defined(TARGET_NR_tkill) && defined(__NR_tkill)
ths4cae1d12007-07-12 11:06:53 +00006729 case TARGET_NR_tkill:
pbrook4cb05962008-05-30 18:05:19 +00006730 ret = get_errno(sys_tkill((int)arg1, target_to_host_signal(arg2)));
ths4cae1d12007-07-12 11:06:53 +00006731 break;
6732#endif
6733
ths3ae43202007-09-16 21:39:48 +00006734#if defined(TARGET_NR_tgkill) && defined(__NR_tgkill)
ths71455572007-06-21 21:45:30 +00006735 case TARGET_NR_tgkill:
pbrook4cb05962008-05-30 18:05:19 +00006736 ret = get_errno(sys_tgkill((int)arg1, (int)arg2,
6737 target_to_host_signal(arg3)));
ths71455572007-06-21 21:45:30 +00006738 break;
6739#endif
6740
ths4f2b1fe2007-06-21 21:57:12 +00006741#ifdef TARGET_NR_set_robust_list
6742 case TARGET_NR_set_robust_list:
6743 goto unimplemented_nowarn;
6744#endif
6745
ths9007f0e2007-09-25 17:50:37 +00006746#if defined(TARGET_NR_utimensat) && defined(__NR_utimensat)
6747 case TARGET_NR_utimensat:
6748 {
Riku Voipioebc996f2009-04-21 15:01:51 +03006749 struct timespec *tsp, ts[2];
6750 if (!arg3) {
6751 tsp = NULL;
6752 } else {
6753 target_to_host_timespec(ts, arg3);
6754 target_to_host_timespec(ts+1, arg3+sizeof(struct target_timespec));
6755 tsp = ts;
6756 }
ths9007f0e2007-09-25 17:50:37 +00006757 if (!arg2)
Riku Voipioebc996f2009-04-21 15:01:51 +03006758 ret = get_errno(sys_utimensat(arg1, NULL, tsp, arg4));
ths9007f0e2007-09-25 17:50:37 +00006759 else {
bellard579a97f2007-11-11 14:26:47 +00006760 if (!(p = lock_user_string(arg2))) {
ths0da46a62007-10-20 20:23:07 +00006761 ret = -TARGET_EFAULT;
bellard579a97f2007-11-11 14:26:47 +00006762 goto fail;
6763 }
Riku Voipioebc996f2009-04-21 15:01:51 +03006764 ret = get_errno(sys_utimensat(arg1, path(p), tsp, arg4));
bellard579a97f2007-11-11 14:26:47 +00006765 unlock_user(p, arg2, 0);
ths9007f0e2007-09-25 17:50:37 +00006766 }
6767 }
6768 break;
6769#endif
pbrookbd0c5662008-05-29 14:34:11 +00006770#if defined(USE_NPTL)
6771 case TARGET_NR_futex:
6772 ret = do_futex(arg1, arg2, arg3, arg4, arg5, arg6);
6773 break;
6774#endif
aurel32dbfe4c32009-04-08 21:29:30 +00006775#if defined(TARGET_NR_inotify_init) && defined(__NR_inotify_init)
aurel3239b59762008-10-01 21:46:50 +00006776 case TARGET_NR_inotify_init:
6777 ret = get_errno(sys_inotify_init());
6778 break;
6779#endif
aurel32dbfe4c32009-04-08 21:29:30 +00006780#if defined(TARGET_NR_inotify_add_watch) && defined(__NR_inotify_add_watch)
aurel3239b59762008-10-01 21:46:50 +00006781 case TARGET_NR_inotify_add_watch:
6782 p = lock_user_string(arg2);
6783 ret = get_errno(sys_inotify_add_watch(arg1, path(p), arg3));
6784 unlock_user(p, arg2, 0);
6785 break;
6786#endif
aurel32dbfe4c32009-04-08 21:29:30 +00006787#if defined(TARGET_NR_inotify_rm_watch) && defined(__NR_inotify_rm_watch)
aurel3239b59762008-10-01 21:46:50 +00006788 case TARGET_NR_inotify_rm_watch:
6789 ret = get_errno(sys_inotify_rm_watch(arg1, arg2));
6790 break;
6791#endif
ths9007f0e2007-09-25 17:50:37 +00006792
aurel3224e10032009-04-15 16:11:43 +00006793#ifdef TARGET_NR_mq_open
6794 case TARGET_NR_mq_open:
6795 {
6796 struct mq_attr posix_mq_attr;
6797
6798 p = lock_user_string(arg1 - 1);
6799 if (arg4 != 0)
6800 copy_from_user_mq_attr (&posix_mq_attr, arg4);
6801 ret = get_errno(mq_open(p, arg2, arg3, &posix_mq_attr));
6802 unlock_user (p, arg1, 0);
6803 }
6804 break;
6805
6806 case TARGET_NR_mq_unlink:
6807 p = lock_user_string(arg1 - 1);
6808 ret = get_errno(mq_unlink(p));
6809 unlock_user (p, arg1, 0);
6810 break;
6811
6812 case TARGET_NR_mq_timedsend:
6813 {
6814 struct timespec ts;
6815
6816 p = lock_user (VERIFY_READ, arg2, arg3, 1);
6817 if (arg5 != 0) {
6818 target_to_host_timespec(&ts, arg5);
6819 ret = get_errno(mq_timedsend(arg1, p, arg3, arg4, &ts));
6820 host_to_target_timespec(arg5, &ts);
6821 }
6822 else
6823 ret = get_errno(mq_send(arg1, p, arg3, arg4));
6824 unlock_user (p, arg2, arg3);
6825 }
6826 break;
6827
6828 case TARGET_NR_mq_timedreceive:
6829 {
6830 struct timespec ts;
6831 unsigned int prio;
6832
6833 p = lock_user (VERIFY_READ, arg2, arg3, 1);
6834 if (arg5 != 0) {
6835 target_to_host_timespec(&ts, arg5);
6836 ret = get_errno(mq_timedreceive(arg1, p, arg3, &prio, &ts));
6837 host_to_target_timespec(arg5, &ts);
6838 }
6839 else
6840 ret = get_errno(mq_receive(arg1, p, arg3, &prio));
6841 unlock_user (p, arg2, arg3);
6842 if (arg4 != 0)
6843 put_user_u32(prio, arg4);
6844 }
6845 break;
6846
6847 /* Not implemented for now... */
6848/* case TARGET_NR_mq_notify: */
6849/* break; */
6850
6851 case TARGET_NR_mq_getsetattr:
6852 {
6853 struct mq_attr posix_mq_attr_in, posix_mq_attr_out;
6854 ret = 0;
6855 if (arg3 != 0) {
6856 ret = mq_getattr(arg1, &posix_mq_attr_out);
6857 copy_to_user_mq_attr(arg3, &posix_mq_attr_out);
6858 }
6859 if (arg2 != 0) {
6860 copy_from_user_mq_attr(&posix_mq_attr_in, arg2);
6861 ret |= mq_setattr(arg1, &posix_mq_attr_in, &posix_mq_attr_out);
6862 }
6863
6864 }
6865 break;
6866#endif
6867
bellard31e31b82003-02-18 22:55:36 +00006868 default:
6869 unimplemented:
bellard5cd43932003-03-29 16:54:36 +00006870 gemu_log("qemu: Unsupported syscall: %d\n", num);
ths4f2b1fe2007-06-21 21:57:12 +00006871#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 +00006872 unimplemented_nowarn:
bellard80a9d032005-01-03 23:31:27 +00006873#endif
ths0da46a62007-10-20 20:23:07 +00006874 ret = -TARGET_ENOSYS;
bellard31e31b82003-02-18 22:55:36 +00006875 break;
6876 }
bellard579a97f2007-11-11 14:26:47 +00006877fail:
bellardc573ff62004-01-04 15:51:36 +00006878#ifdef DEBUG
6879 gemu_log(" = %ld\n", ret);
6880#endif
thsb92c47c2007-11-01 00:07:38 +00006881 if(do_strace)
6882 print_syscall_ret(num, ret);
bellard31e31b82003-02-18 22:55:36 +00006883 return ret;
bellard579a97f2007-11-11 14:26:47 +00006884efault:
6885 ret = -TARGET_EFAULT;
6886 goto fail;
bellard31e31b82003-02-18 22:55:36 +00006887}