blob: 4b230ddfc905fd19aebee45db872b8171e39b800 [file] [log] [blame]
bellard31e31b82003-02-18 22:55:36 +00001/*
2 * Linux syscalls
ths5fafdf22007-09-16 21:08:06 +00003 *
bellard31e31b82003-02-18 22:55:36 +00004 * Copyright (c) 2003 Fabrice Bellard
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
Blue Swirl8167ee82009-07-16 20:47:01 +000017 * along with this program; if not, see <http://www.gnu.org/licenses/>.
bellard31e31b82003-02-18 22:55:36 +000018 */
Eduardo Habkostd5b3a9b2009-06-09 18:26:31 -030019#define _ATFILE_SOURCE
bellard31e31b82003-02-18 22:55:36 +000020#include <stdlib.h>
21#include <stdio.h>
22#include <stdarg.h>
bellard04369ff2003-03-20 22:33:23 +000023#include <string.h>
bellard31e31b82003-02-18 22:55:36 +000024#include <elf.h>
25#include <endian.h>
26#include <errno.h>
27#include <unistd.h>
28#include <fcntl.h>
bellard7854b052003-03-29 17:22:23 +000029#include <time.h>
pbrook82e671d2008-06-09 12:10:22 +000030#include <limits.h>
aurel3224e10032009-04-15 16:11:43 +000031#include <mqueue.h>
bellard31e31b82003-02-18 22:55:36 +000032#include <sys/types.h>
thsd08d3bb2007-03-19 13:09:22 +000033#include <sys/ipc.h>
34#include <sys/msg.h>
bellard31e31b82003-02-18 22:55:36 +000035#include <sys/wait.h>
36#include <sys/time.h>
37#include <sys/stat.h>
38#include <sys/mount.h>
ths39b9aae2007-02-11 18:36:44 +000039#include <sys/prctl.h>
bellard31e31b82003-02-18 22:55:36 +000040#include <sys/resource.h>
41#include <sys/mman.h>
42#include <sys/swap.h>
43#include <signal.h>
44#include <sched.h>
45#include <sys/socket.h>
aurel32607175e2009-04-15 16:11:59 +000046#include <sys/un.h>
bellard31e31b82003-02-18 22:55:36 +000047#include <sys/uio.h>
bellard9de5e442003-03-23 16:49:39 +000048#include <sys/poll.h>
bellard32f36bc2003-03-30 21:29:48 +000049#include <sys/times.h>
bellard8853f862004-02-22 14:57:26 +000050#include <sys/shm.h>
thsfa294812007-02-02 22:05:00 +000051#include <sys/sem.h>
bellard56c8f682005-11-28 22:28:41 +000052#include <sys/statfs.h>
bellardebc05482003-09-30 21:08:41 +000053#include <utime.h>
bellarda5448a72004-06-19 16:59:03 +000054#include <sys/sysinfo.h>
aurel323b3f24a2009-04-15 16:12:13 +000055#include <sys/utsname.h>
bellard72f03902003-02-18 23:33:18 +000056//#include <sys/user.h>
bellard8853f862004-02-22 14:57:26 +000057#include <netinet/ip.h>
bellard7854b052003-03-29 17:22:23 +000058#include <netinet/tcp.h>
aurel320b6d3ae2008-09-15 07:43:43 +000059#include <qemu-common.h>
Juan Quintela9788c9c2009-07-27 16:13:02 +020060#ifdef TARGET_GPROF
aurel326d946cd2008-11-06 16:15:18 +000061#include <sys/gmon.h>
62#endif
bellard31e31b82003-02-18 22:55:36 +000063
64#define termios host_termios
65#define winsize host_winsize
66#define termio host_termio
bellard04369ff2003-03-20 22:33:23 +000067#define sgttyb host_sgttyb /* same as target */
68#define tchars host_tchars /* same as target */
69#define ltchars host_ltchars /* same as target */
bellard31e31b82003-02-18 22:55:36 +000070
71#include <linux/termios.h>
72#include <linux/unistd.h>
73#include <linux/utsname.h>
74#include <linux/cdrom.h>
75#include <linux/hdreg.h>
76#include <linux/soundcard.h>
bellard19b84f32003-05-08 15:41:49 +000077#include <linux/kd.h>
balrog8fbd6b52008-09-20 03:03:09 +000078#include <linux/mtio.h>
Martin Mohring350d1772009-05-04 21:21:41 +030079#include <linux/fs.h>
pbrookd7e40362008-05-23 16:06:43 +000080#include "linux_loop.h"
bellard31e31b82003-02-18 22:55:36 +000081
bellard3ef693a2003-03-23 20:17:16 +000082#include "qemu.h"
balrog526ccb72008-07-16 12:13:52 +000083#include "qemu-common.h"
bellard31e31b82003-02-18 22:55:36 +000084
pbrook30813ce2008-06-02 15:45:44 +000085#if defined(USE_NPTL)
pbrookd865bab2008-06-07 22:12:17 +000086#define CLONE_NPTL_FLAGS2 (CLONE_SETTLS | \
87 CLONE_PARENT_SETTID | CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID)
88#else
89/* XXX: Hardcode the above values. */
90#define CLONE_NPTL_FLAGS2 0
pbrook30813ce2008-06-02 15:45:44 +000091#endif
92
bellard72f03902003-02-18 23:33:18 +000093//#define DEBUG
bellard31e31b82003-02-18 22:55:36 +000094
bellard1a9353d2003-03-16 20:28:50 +000095//#include <linux/msdos_fs.h>
aurel326556a832008-10-13 21:08:17 +000096#define VFAT_IOCTL_READDIR_BOTH _IOR('r', 1, struct linux_dirent [2])
97#define VFAT_IOCTL_READDIR_SHORT _IOR('r', 2, struct linux_dirent [2])
bellard1a9353d2003-03-16 20:28:50 +000098
bellard70a194b2003-08-11 22:20:16 +000099
bellard70a194b2003-08-11 22:20:16 +0000100#undef _syscall0
101#undef _syscall1
102#undef _syscall2
103#undef _syscall3
104#undef _syscall4
105#undef _syscall5
bellard83fcb512006-06-14 13:37:16 +0000106#undef _syscall6
bellard70a194b2003-08-11 22:20:16 +0000107
bellard83fcb512006-06-14 13:37:16 +0000108#define _syscall0(type,name) \
blueswir18fcd3692008-08-17 20:26:25 +0000109static type name (void) \
bellard83fcb512006-06-14 13:37:16 +0000110{ \
111 return syscall(__NR_##name); \
bellard70a194b2003-08-11 22:20:16 +0000112}
113
bellard83fcb512006-06-14 13:37:16 +0000114#define _syscall1(type,name,type1,arg1) \
blueswir18fcd3692008-08-17 20:26:25 +0000115static type name (type1 arg1) \
bellard83fcb512006-06-14 13:37:16 +0000116{ \
117 return syscall(__NR_##name, arg1); \
bellard70a194b2003-08-11 22:20:16 +0000118}
119
bellard83fcb512006-06-14 13:37:16 +0000120#define _syscall2(type,name,type1,arg1,type2,arg2) \
blueswir18fcd3692008-08-17 20:26:25 +0000121static type name (type1 arg1,type2 arg2) \
bellard83fcb512006-06-14 13:37:16 +0000122{ \
123 return syscall(__NR_##name, arg1, arg2); \
bellard70a194b2003-08-11 22:20:16 +0000124}
125
bellard83fcb512006-06-14 13:37:16 +0000126#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \
blueswir18fcd3692008-08-17 20:26:25 +0000127static type name (type1 arg1,type2 arg2,type3 arg3) \
bellard83fcb512006-06-14 13:37:16 +0000128{ \
129 return syscall(__NR_##name, arg1, arg2, arg3); \
bellard70a194b2003-08-11 22:20:16 +0000130}
131
bellard83fcb512006-06-14 13:37:16 +0000132#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \
blueswir18fcd3692008-08-17 20:26:25 +0000133static type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4) \
bellard83fcb512006-06-14 13:37:16 +0000134{ \
135 return syscall(__NR_##name, arg1, arg2, arg3, arg4); \
bellard70a194b2003-08-11 22:20:16 +0000136}
137
bellard83fcb512006-06-14 13:37:16 +0000138#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
139 type5,arg5) \
blueswir18fcd3692008-08-17 20:26:25 +0000140static type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \
bellard83fcb512006-06-14 13:37:16 +0000141{ \
142 return syscall(__NR_##name, arg1, arg2, arg3, arg4, arg5); \
bellard70a194b2003-08-11 22:20:16 +0000143}
bellard83fcb512006-06-14 13:37:16 +0000144
145
146#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
147 type5,arg5,type6,arg6) \
blueswir18fcd3692008-08-17 20:26:25 +0000148static type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5, \
149 type6 arg6) \
bellard83fcb512006-06-14 13:37:16 +0000150{ \
151 return syscall(__NR_##name, arg1, arg2, arg3, arg4, arg5, arg6); \
152}
153
bellard70a194b2003-08-11 22:20:16 +0000154
bellard31e31b82003-02-18 22:55:36 +0000155#define __NR_sys_uname __NR_uname
ths92a34c12007-09-24 09:27:49 +0000156#define __NR_sys_faccessat __NR_faccessat
ths814d7972007-09-24 09:26:51 +0000157#define __NR_sys_fchmodat __NR_fchmodat
thsccfa72b2007-09-24 09:23:34 +0000158#define __NR_sys_fchownat __NR_fchownat
balrog6a24a772008-09-20 02:23:36 +0000159#define __NR_sys_fstatat64 __NR_fstatat64
balrogac8a6552008-09-20 02:25:39 +0000160#define __NR_sys_futimesat __NR_futimesat
bellard72f03902003-02-18 23:33:18 +0000161#define __NR_sys_getcwd1 __NR_getcwd
bellard72f03902003-02-18 23:33:18 +0000162#define __NR_sys_getdents __NR_getdents
bellarddab2ed92003-03-22 15:23:14 +0000163#define __NR_sys_getdents64 __NR_getdents64
thsc6cda172007-10-09 03:42:34 +0000164#define __NR_sys_getpriority __NR_getpriority
ths64f0ce42007-09-24 09:25:06 +0000165#define __NR_sys_linkat __NR_linkat
ths4472ad02007-09-24 09:22:32 +0000166#define __NR_sys_mkdirat __NR_mkdirat
ths75ac37a2007-09-24 09:23:05 +0000167#define __NR_sys_mknodat __NR_mknodat
aurel329d33b762009-04-08 23:07:05 +0000168#define __NR_sys_newfstatat __NR_newfstatat
ths82424832007-09-24 09:21:55 +0000169#define __NR_sys_openat __NR_openat
ths5e0ccb12007-09-24 09:26:10 +0000170#define __NR_sys_readlinkat __NR_readlinkat
ths722183f2007-09-24 09:24:37 +0000171#define __NR_sys_renameat __NR_renameat
bellard66fb9762003-03-23 01:06:05 +0000172#define __NR_sys_rt_sigqueueinfo __NR_rt_sigqueueinfo
thsf0b62432007-09-24 09:25:40 +0000173#define __NR_sys_symlinkat __NR_symlinkat
ths7494b0f2007-02-11 18:26:53 +0000174#define __NR_sys_syslog __NR_syslog
ths71455572007-06-21 21:45:30 +0000175#define __NR_sys_tgkill __NR_tgkill
ths4cae1d12007-07-12 11:06:53 +0000176#define __NR_sys_tkill __NR_tkill
ths8170f562007-09-24 09:24:11 +0000177#define __NR_sys_unlinkat __NR_unlinkat
ths9007f0e2007-09-25 17:50:37 +0000178#define __NR_sys_utimensat __NR_utimensat
pbrookbd0c5662008-05-29 14:34:11 +0000179#define __NR_sys_futex __NR_futex
aurel3239b59762008-10-01 21:46:50 +0000180#define __NR_sys_inotify_init __NR_inotify_init
181#define __NR_sys_inotify_add_watch __NR_inotify_add_watch
182#define __NR_sys_inotify_rm_watch __NR_inotify_rm_watch
bellard31e31b82003-02-18 22:55:36 +0000183
bellardbc51c5c2004-03-17 23:46:04 +0000184#if defined(__alpha__) || defined (__ia64__) || defined(__x86_64__)
bellard9af9eaa2003-04-07 21:34:41 +0000185#define __NR__llseek __NR_lseek
186#endif
187
bellard72f03902003-02-18 23:33:18 +0000188#ifdef __NR_gettid
bellard31e31b82003-02-18 22:55:36 +0000189_syscall0(int, gettid)
bellard72f03902003-02-18 23:33:18 +0000190#else
ths0da46a62007-10-20 20:23:07 +0000191/* This is a replacement for the host gettid() and must return a host
192 errno. */
bellard72f03902003-02-18 23:33:18 +0000193static int gettid(void) {
194 return -ENOSYS;
195}
196#endif
aurel323b3f24a2009-04-15 16:12:13 +0000197#if TARGET_ABI_BITS == 32
198_syscall3(int, sys_getdents, uint, fd, struct linux_dirent *, dirp, uint, count);
199#endif
200#if defined(TARGET_NR_getdents64) && defined(__NR_getdents64)
201_syscall3(int, sys_getdents64, uint, fd, struct linux_dirent64 *, dirp, uint, count);
202#endif
203_syscall2(int, sys_getpriority, int, which, int, who);
Paul Brook909b69c2009-05-19 15:58:52 +0100204#if defined(TARGET_NR__llseek) && !defined (__x86_64__)
aurel323b3f24a2009-04-15 16:12:13 +0000205_syscall5(int, _llseek, uint, fd, ulong, hi, ulong, lo,
206 loff_t *, res, uint, wh);
207#endif
208_syscall3(int,sys_rt_sigqueueinfo,int,pid,int,sig,siginfo_t *,uinfo)
209_syscall3(int,sys_syslog,int,type,char*,bufp,int,len)
210#if defined(TARGET_NR_tgkill) && defined(__NR_tgkill)
211_syscall3(int,sys_tgkill,int,tgid,int,pid,int,sig)
212#endif
213#if defined(TARGET_NR_tkill) && defined(__NR_tkill)
214_syscall2(int,sys_tkill,int,tid,int,sig)
215#endif
216#ifdef __NR_exit_group
217_syscall1(int,exit_group,int,error_code)
218#endif
219#if defined(TARGET_NR_set_tid_address) && defined(__NR_set_tid_address)
220_syscall1(int,set_tid_address,int *,tidptr)
221#endif
222#if defined(USE_NPTL)
223#if defined(TARGET_NR_futex) && defined(__NR_futex)
224_syscall6(int,sys_futex,int *,uaddr,int,op,int,val,
225 const struct timespec *,timeout,int *,uaddr2,int,val3)
226#endif
227#endif
228
229static bitmask_transtbl fcntl_flags_tbl[] = {
230 { TARGET_O_ACCMODE, TARGET_O_WRONLY, O_ACCMODE, O_WRONLY, },
231 { TARGET_O_ACCMODE, TARGET_O_RDWR, O_ACCMODE, O_RDWR, },
232 { TARGET_O_CREAT, TARGET_O_CREAT, O_CREAT, O_CREAT, },
233 { TARGET_O_EXCL, TARGET_O_EXCL, O_EXCL, O_EXCL, },
234 { TARGET_O_NOCTTY, TARGET_O_NOCTTY, O_NOCTTY, O_NOCTTY, },
235 { TARGET_O_TRUNC, TARGET_O_TRUNC, O_TRUNC, O_TRUNC, },
236 { TARGET_O_APPEND, TARGET_O_APPEND, O_APPEND, O_APPEND, },
237 { TARGET_O_NONBLOCK, TARGET_O_NONBLOCK, O_NONBLOCK, O_NONBLOCK, },
238 { TARGET_O_SYNC, TARGET_O_SYNC, O_SYNC, O_SYNC, },
239 { TARGET_FASYNC, TARGET_FASYNC, FASYNC, FASYNC, },
240 { TARGET_O_DIRECTORY, TARGET_O_DIRECTORY, O_DIRECTORY, O_DIRECTORY, },
241 { TARGET_O_NOFOLLOW, TARGET_O_NOFOLLOW, O_NOFOLLOW, O_NOFOLLOW, },
242 { TARGET_O_LARGEFILE, TARGET_O_LARGEFILE, O_LARGEFILE, O_LARGEFILE, },
243#if defined(O_DIRECT)
244 { TARGET_O_DIRECT, TARGET_O_DIRECT, O_DIRECT, O_DIRECT, },
245#endif
246 { 0, 0, 0, 0 }
247};
248
249#define COPY_UTSNAME_FIELD(dest, src) \
250 do { \
251 /* __NEW_UTS_LEN doesn't include terminating null */ \
252 (void) strncpy((dest), (src), __NEW_UTS_LEN); \
253 (dest)[__NEW_UTS_LEN] = '\0'; \
254 } while (0)
255
256static int sys_uname(struct new_utsname *buf)
257{
258 struct utsname uts_buf;
259
260 if (uname(&uts_buf) < 0)
261 return (-1);
262
263 /*
264 * Just in case these have some differences, we
265 * translate utsname to new_utsname (which is the
266 * struct linux kernel uses).
267 */
268
269 bzero(buf, sizeof (*buf));
270 COPY_UTSNAME_FIELD(buf->sysname, uts_buf.sysname);
271 COPY_UTSNAME_FIELD(buf->nodename, uts_buf.nodename);
272 COPY_UTSNAME_FIELD(buf->release, uts_buf.release);
273 COPY_UTSNAME_FIELD(buf->version, uts_buf.version);
274 COPY_UTSNAME_FIELD(buf->machine, uts_buf.machine);
275#ifdef _GNU_SOURCE
276 COPY_UTSNAME_FIELD(buf->domainname, uts_buf.domainname);
277#endif
278 return (0);
279
280#undef COPY_UTSNAME_FIELD
281}
282
283static int sys_getcwd1(char *buf, size_t size)
284{
285 if (getcwd(buf, size) == NULL) {
286 /* getcwd() sets errno */
287 return (-1);
288 }
aurel32aaf4ad32009-04-16 14:17:14 +0000289 return strlen(buf)+1;
aurel323b3f24a2009-04-15 16:12:13 +0000290}
291
292#ifdef CONFIG_ATFILE
293/*
294 * Host system seems to have atfile syscall stubs available. We
295 * now enable them one by one as specified by target syscall_nr.h.
296 */
297
298#ifdef TARGET_NR_faccessat
aurel32465c9f02009-04-19 08:52:17 +0000299static int sys_faccessat(int dirfd, const char *pathname, int mode)
aurel323b3f24a2009-04-15 16:12:13 +0000300{
aurel32465c9f02009-04-19 08:52:17 +0000301 return (faccessat(dirfd, pathname, mode, 0));
aurel323b3f24a2009-04-15 16:12:13 +0000302}
303#endif
304#ifdef TARGET_NR_fchmodat
aurel32465c9f02009-04-19 08:52:17 +0000305static int sys_fchmodat(int dirfd, const char *pathname, mode_t mode)
aurel323b3f24a2009-04-15 16:12:13 +0000306{
aurel32465c9f02009-04-19 08:52:17 +0000307 return (fchmodat(dirfd, pathname, mode, 0));
aurel323b3f24a2009-04-15 16:12:13 +0000308}
309#endif
aurel32fda33742009-04-15 17:12:01 +0000310#if defined(TARGET_NR_fchownat) && defined(USE_UID16)
aurel323b3f24a2009-04-15 16:12:13 +0000311static int sys_fchownat(int dirfd, const char *pathname, uid_t owner,
312 gid_t group, int flags)
313{
314 return (fchownat(dirfd, pathname, owner, group, flags));
315}
316#endif
317#ifdef __NR_fstatat64
318static int sys_fstatat64(int dirfd, const char *pathname, struct stat *buf,
319 int flags)
320{
321 return (fstatat(dirfd, pathname, buf, flags));
322}
323#endif
324#ifdef __NR_newfstatat
325static int sys_newfstatat(int dirfd, const char *pathname, struct stat *buf,
326 int flags)
327{
328 return (fstatat(dirfd, pathname, buf, flags));
329}
330#endif
331#ifdef TARGET_NR_futimesat
332static int sys_futimesat(int dirfd, const char *pathname,
333 const struct timeval times[2])
334{
335 return (futimesat(dirfd, pathname, times));
336}
337#endif
338#ifdef TARGET_NR_linkat
339static int sys_linkat(int olddirfd, const char *oldpath,
340 int newdirfd, const char *newpath, int flags)
341{
342 return (linkat(olddirfd, oldpath, newdirfd, newpath, flags));
343}
344#endif
345#ifdef TARGET_NR_mkdirat
346static int sys_mkdirat(int dirfd, const char *pathname, mode_t mode)
347{
348 return (mkdirat(dirfd, pathname, mode));
349}
350#endif
351#ifdef TARGET_NR_mknodat
352static int sys_mknodat(int dirfd, const char *pathname, mode_t mode,
353 dev_t dev)
354{
355 return (mknodat(dirfd, pathname, mode, dev));
356}
357#endif
358#ifdef TARGET_NR_openat
359static int sys_openat(int dirfd, const char *pathname, int flags, ...)
360{
361 /*
362 * open(2) has extra parameter 'mode' when called with
363 * flag O_CREAT.
364 */
365 if ((flags & O_CREAT) != 0) {
366 va_list ap;
367 mode_t mode;
368
369 /*
370 * Get the 'mode' parameter and translate it to
371 * host bits.
372 */
373 va_start(ap, flags);
374 mode = va_arg(ap, mode_t);
375 mode = target_to_host_bitmask(mode, fcntl_flags_tbl);
376 va_end(ap);
377
378 return (openat(dirfd, pathname, flags, mode));
379 }
380 return (openat(dirfd, pathname, flags));
381}
382#endif
383#ifdef TARGET_NR_readlinkat
384static int sys_readlinkat(int dirfd, const char *pathname, char *buf, size_t bufsiz)
385{
386 return (readlinkat(dirfd, pathname, buf, bufsiz));
387}
388#endif
389#ifdef TARGET_NR_renameat
390static int sys_renameat(int olddirfd, const char *oldpath,
391 int newdirfd, const char *newpath)
392{
393 return (renameat(olddirfd, oldpath, newdirfd, newpath));
394}
395#endif
396#ifdef TARGET_NR_symlinkat
397static int sys_symlinkat(const char *oldpath, int newdirfd, const char *newpath)
398{
399 return (symlinkat(oldpath, newdirfd, newpath));
400}
401#endif
402#ifdef TARGET_NR_unlinkat
403static int sys_unlinkat(int dirfd, const char *pathname, int flags)
404{
405 return (unlinkat(dirfd, pathname, flags));
406}
407#endif
aurel323b3f24a2009-04-15 16:12:13 +0000408#else /* !CONFIG_ATFILE */
409
410/*
411 * Try direct syscalls instead
412 */
ths92a34c12007-09-24 09:27:49 +0000413#if defined(TARGET_NR_faccessat) && defined(__NR_faccessat)
aurel32465c9f02009-04-19 08:52:17 +0000414_syscall3(int,sys_faccessat,int,dirfd,const char *,pathname,int,mode)
ths92a34c12007-09-24 09:27:49 +0000415#endif
ths814d7972007-09-24 09:26:51 +0000416#if defined(TARGET_NR_fchmodat) && defined(__NR_fchmodat)
aurel32465c9f02009-04-19 08:52:17 +0000417_syscall3(int,sys_fchmodat,int,dirfd,const char *,pathname, mode_t,mode)
ths814d7972007-09-24 09:26:51 +0000418#endif
blueswir14583f582008-08-24 10:35:55 +0000419#if defined(TARGET_NR_fchownat) && defined(__NR_fchownat) && defined(USE_UID16)
thsccfa72b2007-09-24 09:23:34 +0000420_syscall5(int,sys_fchownat,int,dirfd,const char *,pathname,
421 uid_t,owner,gid_t,group,int,flags)
422#endif
aurel329d33b762009-04-08 23:07:05 +0000423#if (defined(TARGET_NR_fstatat64) || defined(TARGET_NR_newfstatat)) && \
424 defined(__NR_fstatat64)
balrog6a24a772008-09-20 02:23:36 +0000425_syscall4(int,sys_fstatat64,int,dirfd,const char *,pathname,
426 struct stat *,buf,int,flags)
427#endif
balrogac8a6552008-09-20 02:25:39 +0000428#if defined(TARGET_NR_futimesat) && defined(__NR_futimesat)
429_syscall3(int,sys_futimesat,int,dirfd,const char *,pathname,
430 const struct timeval *,times)
431#endif
aurel323b3f24a2009-04-15 16:12:13 +0000432#if (defined(TARGET_NR_newfstatat) || defined(TARGET_NR_fstatat64) ) && \
433 defined(__NR_newfstatat)
434_syscall4(int,sys_newfstatat,int,dirfd,const char *,pathname,
435 struct stat *,buf,int,flags)
blueswir18fcd3692008-08-17 20:26:25 +0000436#endif
ths64f0ce42007-09-24 09:25:06 +0000437#if defined(TARGET_NR_linkat) && defined(__NR_linkat)
438_syscall5(int,sys_linkat,int,olddirfd,const char *,oldpath,
aurel323b3f24a2009-04-15 16:12:13 +0000439 int,newdirfd,const char *,newpath,int,flags)
ths64f0ce42007-09-24 09:25:06 +0000440#endif
ths4472ad02007-09-24 09:22:32 +0000441#if defined(TARGET_NR_mkdirat) && defined(__NR_mkdirat)
442_syscall3(int,sys_mkdirat,int,dirfd,const char *,pathname,mode_t,mode)
443#endif
ths75ac37a2007-09-24 09:23:05 +0000444#if defined(TARGET_NR_mknodat) && defined(__NR_mknodat)
445_syscall4(int,sys_mknodat,int,dirfd,const char *,pathname,
446 mode_t,mode,dev_t,dev)
447#endif
ths82424832007-09-24 09:21:55 +0000448#if defined(TARGET_NR_openat) && defined(__NR_openat)
449_syscall4(int,sys_openat,int,dirfd,const char *,pathname,int,flags,mode_t,mode)
450#endif
ths5e0ccb12007-09-24 09:26:10 +0000451#if defined(TARGET_NR_readlinkat) && defined(__NR_readlinkat)
452_syscall4(int,sys_readlinkat,int,dirfd,const char *,pathname,
453 char *,buf,size_t,bufsize)
454#endif
ths722183f2007-09-24 09:24:37 +0000455#if defined(TARGET_NR_renameat) && defined(__NR_renameat)
456_syscall4(int,sys_renameat,int,olddirfd,const char *,oldpath,
457 int,newdirfd,const char *,newpath)
458#endif
thsb51eaa82007-09-25 16:09:22 +0000459#if defined(TARGET_NR_symlinkat) && defined(__NR_symlinkat)
thsf0b62432007-09-24 09:25:40 +0000460_syscall3(int,sys_symlinkat,const char *,oldpath,
461 int,newdirfd,const char *,newpath)
462#endif
ths8170f562007-09-24 09:24:11 +0000463#if defined(TARGET_NR_unlinkat) && defined(__NR_unlinkat)
464_syscall3(int,sys_unlinkat,int,dirfd,const char *,pathname,int,flags)
465#endif
Riku Voipioebc996f2009-04-21 15:01:51 +0300466
467#endif /* CONFIG_ATFILE */
468
469#ifdef CONFIG_UTIMENSAT
470static int sys_utimensat(int dirfd, const char *pathname,
471 const struct timespec times[2], int flags)
472{
473 if (pathname == NULL)
474 return futimens(dirfd, times);
475 else
476 return utimensat(dirfd, pathname, times, flags);
477}
478#else
ths9007f0e2007-09-25 17:50:37 +0000479#if defined(TARGET_NR_utimensat) && defined(__NR_utimensat)
480_syscall4(int,sys_utimensat,int,dirfd,const char *,pathname,
481 const struct timespec *,tsp,int,flags)
482#endif
Riku Voipioebc996f2009-04-21 15:01:51 +0300483#endif /* CONFIG_UTIMENSAT */
aurel323b3f24a2009-04-15 16:12:13 +0000484
485#ifdef CONFIG_INOTIFY
aurel328690e422009-04-17 13:50:32 +0000486#include <sys/inotify.h>
aurel323b3f24a2009-04-15 16:12:13 +0000487
aurel3239b59762008-10-01 21:46:50 +0000488#if defined(TARGET_NR_inotify_init) && defined(__NR_inotify_init)
aurel323b3f24a2009-04-15 16:12:13 +0000489static int sys_inotify_init(void)
490{
491 return (inotify_init());
492}
aurel3239b59762008-10-01 21:46:50 +0000493#endif
494#if defined(TARGET_NR_inotify_add_watch) && defined(__NR_inotify_add_watch)
aurel323b3f24a2009-04-15 16:12:13 +0000495static int sys_inotify_add_watch(int fd,const char *pathname, int32_t mask)
496{
497 return (inotify_add_watch(fd, pathname, mask));
498}
aurel3239b59762008-10-01 21:46:50 +0000499#endif
500#if defined(TARGET_NR_inotify_rm_watch) && defined(__NR_inotify_rm_watch)
aurel323b3f24a2009-04-15 16:12:13 +0000501static int sys_inotify_rm_watch(int fd, int32_t wd)
502{
aurel328690e422009-04-17 13:50:32 +0000503 return (inotify_rm_watch(fd, wd));
aurel323b3f24a2009-04-15 16:12:13 +0000504}
aurel3239b59762008-10-01 21:46:50 +0000505#endif
aurel323b3f24a2009-04-15 16:12:13 +0000506#else
507/* Userspace can usually survive runtime without inotify */
508#undef TARGET_NR_inotify_init
509#undef TARGET_NR_inotify_add_watch
510#undef TARGET_NR_inotify_rm_watch
511#endif /* CONFIG_INOTIFY */
512
bellard66fb9762003-03-23 01:06:05 +0000513
514extern int personality(int);
bellard9de5e442003-03-23 16:49:39 +0000515extern int flock(int, int);
516extern int setfsuid(int);
517extern int setfsgid(int);
bellard19b84f32003-05-08 15:41:49 +0000518extern int setgroups(int, gid_t *);
bellard31e31b82003-02-18 22:55:36 +0000519
thsb92c47c2007-11-01 00:07:38 +0000520#define ERRNO_TABLE_SIZE 1200
521
522/* target_to_host_errno_table[] is initialized from
523 * host_to_target_errno_table[] in syscall_init(). */
524static uint16_t target_to_host_errno_table[ERRNO_TABLE_SIZE] = {
525};
526
ths637947f2007-06-01 12:09:19 +0000527/*
thsfe8f0962007-07-12 10:59:21 +0000528 * This list is the union of errno values overridden in asm-<arch>/errno.h
ths637947f2007-06-01 12:09:19 +0000529 * minus the errnos that are not actually generic to all archs.
530 */
thsb92c47c2007-11-01 00:07:38 +0000531static uint16_t host_to_target_errno_table[ERRNO_TABLE_SIZE] = {
ths637947f2007-06-01 12:09:19 +0000532 [EIDRM] = TARGET_EIDRM,
533 [ECHRNG] = TARGET_ECHRNG,
534 [EL2NSYNC] = TARGET_EL2NSYNC,
535 [EL3HLT] = TARGET_EL3HLT,
536 [EL3RST] = TARGET_EL3RST,
537 [ELNRNG] = TARGET_ELNRNG,
538 [EUNATCH] = TARGET_EUNATCH,
539 [ENOCSI] = TARGET_ENOCSI,
540 [EL2HLT] = TARGET_EL2HLT,
541 [EDEADLK] = TARGET_EDEADLK,
542 [ENOLCK] = TARGET_ENOLCK,
543 [EBADE] = TARGET_EBADE,
544 [EBADR] = TARGET_EBADR,
545 [EXFULL] = TARGET_EXFULL,
546 [ENOANO] = TARGET_ENOANO,
547 [EBADRQC] = TARGET_EBADRQC,
548 [EBADSLT] = TARGET_EBADSLT,
549 [EBFONT] = TARGET_EBFONT,
550 [ENOSTR] = TARGET_ENOSTR,
551 [ENODATA] = TARGET_ENODATA,
552 [ETIME] = TARGET_ETIME,
553 [ENOSR] = TARGET_ENOSR,
554 [ENONET] = TARGET_ENONET,
555 [ENOPKG] = TARGET_ENOPKG,
556 [EREMOTE] = TARGET_EREMOTE,
557 [ENOLINK] = TARGET_ENOLINK,
558 [EADV] = TARGET_EADV,
559 [ESRMNT] = TARGET_ESRMNT,
560 [ECOMM] = TARGET_ECOMM,
561 [EPROTO] = TARGET_EPROTO,
562 [EDOTDOT] = TARGET_EDOTDOT,
563 [EMULTIHOP] = TARGET_EMULTIHOP,
564 [EBADMSG] = TARGET_EBADMSG,
565 [ENAMETOOLONG] = TARGET_ENAMETOOLONG,
566 [EOVERFLOW] = TARGET_EOVERFLOW,
567 [ENOTUNIQ] = TARGET_ENOTUNIQ,
568 [EBADFD] = TARGET_EBADFD,
569 [EREMCHG] = TARGET_EREMCHG,
570 [ELIBACC] = TARGET_ELIBACC,
571 [ELIBBAD] = TARGET_ELIBBAD,
572 [ELIBSCN] = TARGET_ELIBSCN,
573 [ELIBMAX] = TARGET_ELIBMAX,
574 [ELIBEXEC] = TARGET_ELIBEXEC,
575 [EILSEQ] = TARGET_EILSEQ,
576 [ENOSYS] = TARGET_ENOSYS,
577 [ELOOP] = TARGET_ELOOP,
578 [ERESTART] = TARGET_ERESTART,
579 [ESTRPIPE] = TARGET_ESTRPIPE,
580 [ENOTEMPTY] = TARGET_ENOTEMPTY,
581 [EUSERS] = TARGET_EUSERS,
582 [ENOTSOCK] = TARGET_ENOTSOCK,
583 [EDESTADDRREQ] = TARGET_EDESTADDRREQ,
584 [EMSGSIZE] = TARGET_EMSGSIZE,
585 [EPROTOTYPE] = TARGET_EPROTOTYPE,
586 [ENOPROTOOPT] = TARGET_ENOPROTOOPT,
587 [EPROTONOSUPPORT] = TARGET_EPROTONOSUPPORT,
588 [ESOCKTNOSUPPORT] = TARGET_ESOCKTNOSUPPORT,
589 [EOPNOTSUPP] = TARGET_EOPNOTSUPP,
590 [EPFNOSUPPORT] = TARGET_EPFNOSUPPORT,
591 [EAFNOSUPPORT] = TARGET_EAFNOSUPPORT,
592 [EADDRINUSE] = TARGET_EADDRINUSE,
593 [EADDRNOTAVAIL] = TARGET_EADDRNOTAVAIL,
594 [ENETDOWN] = TARGET_ENETDOWN,
595 [ENETUNREACH] = TARGET_ENETUNREACH,
596 [ENETRESET] = TARGET_ENETRESET,
597 [ECONNABORTED] = TARGET_ECONNABORTED,
598 [ECONNRESET] = TARGET_ECONNRESET,
599 [ENOBUFS] = TARGET_ENOBUFS,
600 [EISCONN] = TARGET_EISCONN,
601 [ENOTCONN] = TARGET_ENOTCONN,
602 [EUCLEAN] = TARGET_EUCLEAN,
603 [ENOTNAM] = TARGET_ENOTNAM,
604 [ENAVAIL] = TARGET_ENAVAIL,
605 [EISNAM] = TARGET_EISNAM,
606 [EREMOTEIO] = TARGET_EREMOTEIO,
607 [ESHUTDOWN] = TARGET_ESHUTDOWN,
608 [ETOOMANYREFS] = TARGET_ETOOMANYREFS,
609 [ETIMEDOUT] = TARGET_ETIMEDOUT,
610 [ECONNREFUSED] = TARGET_ECONNREFUSED,
611 [EHOSTDOWN] = TARGET_EHOSTDOWN,
612 [EHOSTUNREACH] = TARGET_EHOSTUNREACH,
613 [EALREADY] = TARGET_EALREADY,
614 [EINPROGRESS] = TARGET_EINPROGRESS,
615 [ESTALE] = TARGET_ESTALE,
616 [ECANCELED] = TARGET_ECANCELED,
617 [ENOMEDIUM] = TARGET_ENOMEDIUM,
618 [EMEDIUMTYPE] = TARGET_EMEDIUMTYPE,
thsb7fe5db2007-07-23 15:37:46 +0000619#ifdef ENOKEY
ths637947f2007-06-01 12:09:19 +0000620 [ENOKEY] = TARGET_ENOKEY,
thsb7fe5db2007-07-23 15:37:46 +0000621#endif
622#ifdef EKEYEXPIRED
ths637947f2007-06-01 12:09:19 +0000623 [EKEYEXPIRED] = TARGET_EKEYEXPIRED,
thsb7fe5db2007-07-23 15:37:46 +0000624#endif
625#ifdef EKEYREVOKED
ths637947f2007-06-01 12:09:19 +0000626 [EKEYREVOKED] = TARGET_EKEYREVOKED,
thsb7fe5db2007-07-23 15:37:46 +0000627#endif
628#ifdef EKEYREJECTED
ths637947f2007-06-01 12:09:19 +0000629 [EKEYREJECTED] = TARGET_EKEYREJECTED,
thsb7fe5db2007-07-23 15:37:46 +0000630#endif
631#ifdef EOWNERDEAD
ths637947f2007-06-01 12:09:19 +0000632 [EOWNERDEAD] = TARGET_EOWNERDEAD,
thsb7fe5db2007-07-23 15:37:46 +0000633#endif
634#ifdef ENOTRECOVERABLE
ths637947f2007-06-01 12:09:19 +0000635 [ENOTRECOVERABLE] = TARGET_ENOTRECOVERABLE,
thsb7fe5db2007-07-23 15:37:46 +0000636#endif
thsb92c47c2007-11-01 00:07:38 +0000637};
ths637947f2007-06-01 12:09:19 +0000638
639static inline int host_to_target_errno(int err)
640{
641 if(host_to_target_errno_table[err])
642 return host_to_target_errno_table[err];
643 return err;
644}
645
thsb92c47c2007-11-01 00:07:38 +0000646static inline int target_to_host_errno(int err)
647{
648 if (target_to_host_errno_table[err])
649 return target_to_host_errno_table[err];
650 return err;
651}
652
blueswir1992f48a2007-10-14 16:27:31 +0000653static inline abi_long get_errno(abi_long ret)
bellard31e31b82003-02-18 22:55:36 +0000654{
655 if (ret == -1)
ths637947f2007-06-01 12:09:19 +0000656 return -host_to_target_errno(errno);
bellard31e31b82003-02-18 22:55:36 +0000657 else
658 return ret;
659}
660
blueswir1992f48a2007-10-14 16:27:31 +0000661static inline int is_error(abi_long ret)
bellard31e31b82003-02-18 22:55:36 +0000662{
blueswir1992f48a2007-10-14 16:27:31 +0000663 return (abi_ulong)ret >= (abi_ulong)(-4096);
bellard31e31b82003-02-18 22:55:36 +0000664}
665
thsb92c47c2007-11-01 00:07:38 +0000666char *target_strerror(int err)
667{
668 return strerror(target_to_host_errno(err));
669}
670
blueswir1992f48a2007-10-14 16:27:31 +0000671static abi_ulong target_brk;
672static abi_ulong target_original_brk;
bellard31e31b82003-02-18 22:55:36 +0000673
blueswir1992f48a2007-10-14 16:27:31 +0000674void target_set_brk(abi_ulong new_brk)
bellard31e31b82003-02-18 22:55:36 +0000675{
blueswir14c1de732007-07-07 20:45:44 +0000676 target_original_brk = target_brk = HOST_PAGE_ALIGN(new_brk);
bellard31e31b82003-02-18 22:55:36 +0000677}
678
ths0da46a62007-10-20 20:23:07 +0000679/* do_brk() must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +0000680abi_long do_brk(abi_ulong new_brk)
bellard31e31b82003-02-18 22:55:36 +0000681{
blueswir1992f48a2007-10-14 16:27:31 +0000682 abi_ulong brk_page;
683 abi_long mapped_addr;
bellard31e31b82003-02-18 22:55:36 +0000684 int new_alloc_size;
685
686 if (!new_brk)
pbrook53a59602006-03-25 19:31:22 +0000687 return target_brk;
bellard31e31b82003-02-18 22:55:36 +0000688 if (new_brk < target_original_brk)
balrog7ab240a2008-04-26 12:17:34 +0000689 return target_brk;
ths3b46e622007-09-17 08:09:54 +0000690
pbrook53a59602006-03-25 19:31:22 +0000691 brk_page = HOST_PAGE_ALIGN(target_brk);
bellard31e31b82003-02-18 22:55:36 +0000692
693 /* If the new brk is less than this, set it and we're done... */
694 if (new_brk < brk_page) {
695 target_brk = new_brk;
pbrook53a59602006-03-25 19:31:22 +0000696 return target_brk;
bellard31e31b82003-02-18 22:55:36 +0000697 }
698
699 /* We need to allocate more memory after the brk... */
bellard54936002003-05-13 00:25:15 +0000700 new_alloc_size = HOST_PAGE_ALIGN(new_brk - brk_page + 1);
ths5fafdf22007-09-16 21:08:06 +0000701 mapped_addr = get_errno(target_mmap(brk_page, new_alloc_size,
bellard54936002003-05-13 00:25:15 +0000702 PROT_READ|PROT_WRITE,
703 MAP_ANON|MAP_FIXED|MAP_PRIVATE, 0, 0));
balrog7ab240a2008-04-26 12:17:34 +0000704
705 if (!is_error(mapped_addr))
bellard31e31b82003-02-18 22:55:36 +0000706 target_brk = new_brk;
balrog7ab240a2008-04-26 12:17:34 +0000707
708 return target_brk;
bellard31e31b82003-02-18 22:55:36 +0000709}
710
ths26edcf42007-12-09 02:25:24 +0000711static inline abi_long copy_from_user_fdset(fd_set *fds,
712 abi_ulong target_fds_addr,
713 int n)
bellard31e31b82003-02-18 22:55:36 +0000714{
ths26edcf42007-12-09 02:25:24 +0000715 int i, nw, j, k;
716 abi_ulong b, *target_fds;
717
718 nw = (n + TARGET_ABI_BITS - 1) / TARGET_ABI_BITS;
719 if (!(target_fds = lock_user(VERIFY_READ,
720 target_fds_addr,
721 sizeof(abi_ulong) * nw,
722 1)))
723 return -TARGET_EFAULT;
724
725 FD_ZERO(fds);
726 k = 0;
727 for (i = 0; i < nw; i++) {
728 /* grab the abi_ulong */
729 __get_user(b, &target_fds[i]);
730 for (j = 0; j < TARGET_ABI_BITS; j++) {
731 /* check the bit inside the abi_ulong */
732 if ((b >> j) & 1)
733 FD_SET(k, fds);
734 k++;
bellard31e31b82003-02-18 22:55:36 +0000735 }
bellard31e31b82003-02-18 22:55:36 +0000736 }
ths26edcf42007-12-09 02:25:24 +0000737
738 unlock_user(target_fds, target_fds_addr, 0);
739
740 return 0;
bellard31e31b82003-02-18 22:55:36 +0000741}
742
ths26edcf42007-12-09 02:25:24 +0000743static inline abi_long copy_to_user_fdset(abi_ulong target_fds_addr,
744 const fd_set *fds,
745 int n)
bellard31e31b82003-02-18 22:55:36 +0000746{
bellard31e31b82003-02-18 22:55:36 +0000747 int i, nw, j, k;
blueswir1992f48a2007-10-14 16:27:31 +0000748 abi_long v;
ths26edcf42007-12-09 02:25:24 +0000749 abi_ulong *target_fds;
bellard31e31b82003-02-18 22:55:36 +0000750
ths26edcf42007-12-09 02:25:24 +0000751 nw = (n + TARGET_ABI_BITS - 1) / TARGET_ABI_BITS;
752 if (!(target_fds = lock_user(VERIFY_WRITE,
753 target_fds_addr,
754 sizeof(abi_ulong) * nw,
755 0)))
756 return -TARGET_EFAULT;
757
758 k = 0;
759 for (i = 0; i < nw; i++) {
760 v = 0;
761 for (j = 0; j < TARGET_ABI_BITS; j++) {
762 v |= ((FD_ISSET(k, fds) != 0) << j);
763 k++;
bellard31e31b82003-02-18 22:55:36 +0000764 }
ths26edcf42007-12-09 02:25:24 +0000765 __put_user(v, &target_fds[i]);
bellard31e31b82003-02-18 22:55:36 +0000766 }
ths26edcf42007-12-09 02:25:24 +0000767
768 unlock_user(target_fds, target_fds_addr, sizeof(abi_ulong) * nw);
769
770 return 0;
bellard31e31b82003-02-18 22:55:36 +0000771}
772
bellardc596ed12003-07-13 17:32:31 +0000773#if defined(__alpha__)
774#define HOST_HZ 1024
775#else
776#define HOST_HZ 100
777#endif
778
blueswir1992f48a2007-10-14 16:27:31 +0000779static inline abi_long host_to_target_clock_t(long ticks)
bellardc596ed12003-07-13 17:32:31 +0000780{
781#if HOST_HZ == TARGET_HZ
782 return ticks;
783#else
784 return ((int64_t)ticks * TARGET_HZ) / HOST_HZ;
785#endif
786}
787
bellard579a97f2007-11-11 14:26:47 +0000788static inline abi_long host_to_target_rusage(abi_ulong target_addr,
789 const struct rusage *rusage)
bellardb4091862003-05-16 15:39:34 +0000790{
pbrook53a59602006-03-25 19:31:22 +0000791 struct target_rusage *target_rusage;
792
bellard579a97f2007-11-11 14:26:47 +0000793 if (!lock_user_struct(VERIFY_WRITE, target_rusage, target_addr, 0))
794 return -TARGET_EFAULT;
bellardb4091862003-05-16 15:39:34 +0000795 target_rusage->ru_utime.tv_sec = tswapl(rusage->ru_utime.tv_sec);
796 target_rusage->ru_utime.tv_usec = tswapl(rusage->ru_utime.tv_usec);
797 target_rusage->ru_stime.tv_sec = tswapl(rusage->ru_stime.tv_sec);
798 target_rusage->ru_stime.tv_usec = tswapl(rusage->ru_stime.tv_usec);
799 target_rusage->ru_maxrss = tswapl(rusage->ru_maxrss);
800 target_rusage->ru_ixrss = tswapl(rusage->ru_ixrss);
801 target_rusage->ru_idrss = tswapl(rusage->ru_idrss);
802 target_rusage->ru_isrss = tswapl(rusage->ru_isrss);
803 target_rusage->ru_minflt = tswapl(rusage->ru_minflt);
804 target_rusage->ru_majflt = tswapl(rusage->ru_majflt);
805 target_rusage->ru_nswap = tswapl(rusage->ru_nswap);
806 target_rusage->ru_inblock = tswapl(rusage->ru_inblock);
807 target_rusage->ru_oublock = tswapl(rusage->ru_oublock);
808 target_rusage->ru_msgsnd = tswapl(rusage->ru_msgsnd);
809 target_rusage->ru_msgrcv = tswapl(rusage->ru_msgrcv);
810 target_rusage->ru_nsignals = tswapl(rusage->ru_nsignals);
811 target_rusage->ru_nvcsw = tswapl(rusage->ru_nvcsw);
812 target_rusage->ru_nivcsw = tswapl(rusage->ru_nivcsw);
pbrook53a59602006-03-25 19:31:22 +0000813 unlock_user_struct(target_rusage, target_addr, 1);
bellard579a97f2007-11-11 14:26:47 +0000814
815 return 0;
bellardb4091862003-05-16 15:39:34 +0000816}
817
ths788f5ec2007-12-09 02:37:05 +0000818static inline abi_long copy_from_user_timeval(struct timeval *tv,
819 abi_ulong target_tv_addr)
bellard31e31b82003-02-18 22:55:36 +0000820{
pbrook53a59602006-03-25 19:31:22 +0000821 struct target_timeval *target_tv;
822
ths788f5ec2007-12-09 02:37:05 +0000823 if (!lock_user_struct(VERIFY_READ, target_tv, target_tv_addr, 1))
bellard579a97f2007-11-11 14:26:47 +0000824 return -TARGET_EFAULT;
ths788f5ec2007-12-09 02:37:05 +0000825
826 __get_user(tv->tv_sec, &target_tv->tv_sec);
827 __get_user(tv->tv_usec, &target_tv->tv_usec);
828
829 unlock_user_struct(target_tv, target_tv_addr, 0);
bellard579a97f2007-11-11 14:26:47 +0000830
831 return 0;
bellard31e31b82003-02-18 22:55:36 +0000832}
833
ths788f5ec2007-12-09 02:37:05 +0000834static inline abi_long copy_to_user_timeval(abi_ulong target_tv_addr,
835 const struct timeval *tv)
bellard31e31b82003-02-18 22:55:36 +0000836{
pbrook53a59602006-03-25 19:31:22 +0000837 struct target_timeval *target_tv;
838
ths788f5ec2007-12-09 02:37:05 +0000839 if (!lock_user_struct(VERIFY_WRITE, target_tv, target_tv_addr, 0))
bellard579a97f2007-11-11 14:26:47 +0000840 return -TARGET_EFAULT;
ths788f5ec2007-12-09 02:37:05 +0000841
842 __put_user(tv->tv_sec, &target_tv->tv_sec);
843 __put_user(tv->tv_usec, &target_tv->tv_usec);
844
845 unlock_user_struct(target_tv, target_tv_addr, 1);
bellard579a97f2007-11-11 14:26:47 +0000846
847 return 0;
bellard31e31b82003-02-18 22:55:36 +0000848}
849
aurel3224e10032009-04-15 16:11:43 +0000850static inline abi_long copy_from_user_mq_attr(struct mq_attr *attr,
851 abi_ulong target_mq_attr_addr)
852{
853 struct target_mq_attr *target_mq_attr;
854
855 if (!lock_user_struct(VERIFY_READ, target_mq_attr,
856 target_mq_attr_addr, 1))
857 return -TARGET_EFAULT;
858
859 __get_user(attr->mq_flags, &target_mq_attr->mq_flags);
860 __get_user(attr->mq_maxmsg, &target_mq_attr->mq_maxmsg);
861 __get_user(attr->mq_msgsize, &target_mq_attr->mq_msgsize);
862 __get_user(attr->mq_curmsgs, &target_mq_attr->mq_curmsgs);
863
864 unlock_user_struct(target_mq_attr, target_mq_attr_addr, 0);
865
866 return 0;
867}
868
869static inline abi_long copy_to_user_mq_attr(abi_ulong target_mq_attr_addr,
870 const struct mq_attr *attr)
871{
872 struct target_mq_attr *target_mq_attr;
873
874 if (!lock_user_struct(VERIFY_WRITE, target_mq_attr,
875 target_mq_attr_addr, 0))
876 return -TARGET_EFAULT;
877
878 __put_user(attr->mq_flags, &target_mq_attr->mq_flags);
879 __put_user(attr->mq_maxmsg, &target_mq_attr->mq_maxmsg);
880 __put_user(attr->mq_msgsize, &target_mq_attr->mq_msgsize);
881 __put_user(attr->mq_curmsgs, &target_mq_attr->mq_curmsgs);
882
883 unlock_user_struct(target_mq_attr, target_mq_attr_addr, 1);
884
885 return 0;
886}
bellard31e31b82003-02-18 22:55:36 +0000887
ths0da46a62007-10-20 20:23:07 +0000888/* do_select() must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +0000889static abi_long do_select(int n,
ths26edcf42007-12-09 02:25:24 +0000890 abi_ulong rfd_addr, abi_ulong wfd_addr,
891 abi_ulong efd_addr, abi_ulong target_tv_addr)
bellard31e31b82003-02-18 22:55:36 +0000892{
893 fd_set rfds, wfds, efds;
894 fd_set *rfds_ptr, *wfds_ptr, *efds_ptr;
895 struct timeval tv, *tv_ptr;
blueswir1992f48a2007-10-14 16:27:31 +0000896 abi_long ret;
bellard31e31b82003-02-18 22:55:36 +0000897
ths26edcf42007-12-09 02:25:24 +0000898 if (rfd_addr) {
899 if (copy_from_user_fdset(&rfds, rfd_addr, n))
900 return -TARGET_EFAULT;
901 rfds_ptr = &rfds;
pbrook53a59602006-03-25 19:31:22 +0000902 } else {
pbrook53a59602006-03-25 19:31:22 +0000903 rfds_ptr = NULL;
904 }
ths26edcf42007-12-09 02:25:24 +0000905 if (wfd_addr) {
906 if (copy_from_user_fdset(&wfds, wfd_addr, n))
907 return -TARGET_EFAULT;
908 wfds_ptr = &wfds;
pbrook53a59602006-03-25 19:31:22 +0000909 } else {
pbrook53a59602006-03-25 19:31:22 +0000910 wfds_ptr = NULL;
911 }
ths26edcf42007-12-09 02:25:24 +0000912 if (efd_addr) {
913 if (copy_from_user_fdset(&efds, efd_addr, n))
914 return -TARGET_EFAULT;
915 efds_ptr = &efds;
pbrook53a59602006-03-25 19:31:22 +0000916 } else {
pbrook53a59602006-03-25 19:31:22 +0000917 efds_ptr = NULL;
918 }
ths3b46e622007-09-17 08:09:54 +0000919
ths26edcf42007-12-09 02:25:24 +0000920 if (target_tv_addr) {
ths788f5ec2007-12-09 02:37:05 +0000921 if (copy_from_user_timeval(&tv, target_tv_addr))
922 return -TARGET_EFAULT;
bellard31e31b82003-02-18 22:55:36 +0000923 tv_ptr = &tv;
924 } else {
925 tv_ptr = NULL;
926 }
ths26edcf42007-12-09 02:25:24 +0000927
bellard31e31b82003-02-18 22:55:36 +0000928 ret = get_errno(select(n, rfds_ptr, wfds_ptr, efds_ptr, tv_ptr));
pbrook53a59602006-03-25 19:31:22 +0000929
ths26edcf42007-12-09 02:25:24 +0000930 if (!is_error(ret)) {
931 if (rfd_addr && copy_to_user_fdset(rfd_addr, &rfds, n))
932 return -TARGET_EFAULT;
933 if (wfd_addr && copy_to_user_fdset(wfd_addr, &wfds, n))
934 return -TARGET_EFAULT;
935 if (efd_addr && copy_to_user_fdset(efd_addr, &efds, n))
936 return -TARGET_EFAULT;
bellard31e31b82003-02-18 22:55:36 +0000937
ths788f5ec2007-12-09 02:37:05 +0000938 if (target_tv_addr && copy_to_user_timeval(target_tv_addr, &tv))
939 return -TARGET_EFAULT;
bellard31e31b82003-02-18 22:55:36 +0000940 }
bellard579a97f2007-11-11 14:26:47 +0000941
bellard31e31b82003-02-18 22:55:36 +0000942 return ret;
943}
944
Riku Voipio099d6b02009-05-05 12:10:04 +0300945static abi_long do_pipe2(int host_pipe[], int flags)
946{
947#ifdef CONFIG_PIPE2
948 return pipe2(host_pipe, flags);
949#else
950 return -ENOSYS;
951#endif
952}
953
Ulrich Hecht784ccfd2009-07-03 17:09:26 +0200954static abi_long do_pipe(void *cpu_env, abi_ulong pipedes, int flags)
Riku Voipio099d6b02009-05-05 12:10:04 +0300955{
956 int host_pipe[2];
957 abi_long ret;
958 ret = flags ? do_pipe2(host_pipe, flags) : pipe(host_pipe);
959
960 if (is_error(ret))
961 return get_errno(ret);
962#if defined(TARGET_MIPS)
963 ((CPUMIPSState*)cpu_env)->active_tc.gpr[3] = host_pipe[1];
964 ret = host_pipe[0];
965#elif defined(TARGET_SH4)
966 ((CPUSH4State*)cpu_env)->gregs[1] = host_pipe[1];
967 ret = host_pipe[0];
968#else
969 if (put_user_s32(host_pipe[0], pipedes)
970 || put_user_s32(host_pipe[1], pipedes + sizeof(host_pipe[0])))
971 return -TARGET_EFAULT;
972#endif
973 return get_errno(ret);
974}
975
Lionel Landwerlinb975b832009-04-25 23:30:19 +0200976static inline abi_long target_to_host_ip_mreq(struct ip_mreqn *mreqn,
977 abi_ulong target_addr,
978 socklen_t len)
979{
980 struct target_ip_mreqn *target_smreqn;
981
982 target_smreqn = lock_user(VERIFY_READ, target_addr, len, 1);
983 if (!target_smreqn)
984 return -TARGET_EFAULT;
985 mreqn->imr_multiaddr.s_addr = target_smreqn->imr_multiaddr.s_addr;
986 mreqn->imr_address.s_addr = target_smreqn->imr_address.s_addr;
987 if (len == sizeof(struct target_ip_mreqn))
988 mreqn->imr_ifindex = tswapl(target_smreqn->imr_ifindex);
989 unlock_user(target_smreqn, target_addr, 0);
990
991 return 0;
992}
993
bellard579a97f2007-11-11 14:26:47 +0000994static inline abi_long target_to_host_sockaddr(struct sockaddr *addr,
995 abi_ulong target_addr,
996 socklen_t len)
bellard7854b052003-03-29 17:22:23 +0000997{
aurel32607175e2009-04-15 16:11:59 +0000998 const socklen_t unix_maxlen = sizeof (struct sockaddr_un);
999 sa_family_t sa_family;
pbrook53a59602006-03-25 19:31:22 +00001000 struct target_sockaddr *target_saddr;
1001
bellard579a97f2007-11-11 14:26:47 +00001002 target_saddr = lock_user(VERIFY_READ, target_addr, len, 1);
1003 if (!target_saddr)
1004 return -TARGET_EFAULT;
aurel32607175e2009-04-15 16:11:59 +00001005
1006 sa_family = tswap16(target_saddr->sa_family);
1007
1008 /* Oops. The caller might send a incomplete sun_path; sun_path
1009 * must be terminated by \0 (see the manual page), but
1010 * unfortunately it is quite common to specify sockaddr_un
1011 * length as "strlen(x->sun_path)" while it should be
1012 * "strlen(...) + 1". We'll fix that here if needed.
1013 * Linux kernel has a similar feature.
1014 */
1015
1016 if (sa_family == AF_UNIX) {
1017 if (len < unix_maxlen && len > 0) {
1018 char *cp = (char*)target_saddr;
1019
1020 if ( cp[len-1] && !cp[len] )
1021 len++;
1022 }
1023 if (len > unix_maxlen)
1024 len = unix_maxlen;
1025 }
1026
pbrook53a59602006-03-25 19:31:22 +00001027 memcpy(addr, target_saddr, len);
aurel32607175e2009-04-15 16:11:59 +00001028 addr->sa_family = sa_family;
pbrook53a59602006-03-25 19:31:22 +00001029 unlock_user(target_saddr, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00001030
1031 return 0;
bellard7854b052003-03-29 17:22:23 +00001032}
1033
bellard579a97f2007-11-11 14:26:47 +00001034static inline abi_long host_to_target_sockaddr(abi_ulong target_addr,
1035 struct sockaddr *addr,
1036 socklen_t len)
bellard7854b052003-03-29 17:22:23 +00001037{
pbrook53a59602006-03-25 19:31:22 +00001038 struct target_sockaddr *target_saddr;
1039
bellard579a97f2007-11-11 14:26:47 +00001040 target_saddr = lock_user(VERIFY_WRITE, target_addr, len, 0);
1041 if (!target_saddr)
1042 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00001043 memcpy(target_saddr, addr, len);
1044 target_saddr->sa_family = tswap16(addr->sa_family);
1045 unlock_user(target_saddr, target_addr, len);
bellard579a97f2007-11-11 14:26:47 +00001046
1047 return 0;
bellard7854b052003-03-29 17:22:23 +00001048}
1049
pbrook53a59602006-03-25 19:31:22 +00001050/* ??? Should this also swap msgh->name? */
bellard5a4a8982007-11-11 17:39:18 +00001051static inline abi_long target_to_host_cmsg(struct msghdr *msgh,
1052 struct target_msghdr *target_msgh)
bellard7854b052003-03-29 17:22:23 +00001053{
1054 struct cmsghdr *cmsg = CMSG_FIRSTHDR(msgh);
bellard5a4a8982007-11-11 17:39:18 +00001055 abi_long msg_controllen;
1056 abi_ulong target_cmsg_addr;
1057 struct target_cmsghdr *target_cmsg;
bellard7854b052003-03-29 17:22:23 +00001058 socklen_t space = 0;
bellard5a4a8982007-11-11 17:39:18 +00001059
1060 msg_controllen = tswapl(target_msgh->msg_controllen);
1061 if (msg_controllen < sizeof (struct target_cmsghdr))
1062 goto the_end;
1063 target_cmsg_addr = tswapl(target_msgh->msg_control);
1064 target_cmsg = lock_user(VERIFY_READ, target_cmsg_addr, msg_controllen, 1);
1065 if (!target_cmsg)
1066 return -TARGET_EFAULT;
bellard7854b052003-03-29 17:22:23 +00001067
1068 while (cmsg && target_cmsg) {
1069 void *data = CMSG_DATA(cmsg);
1070 void *target_data = TARGET_CMSG_DATA(target_cmsg);
1071
ths5fafdf22007-09-16 21:08:06 +00001072 int len = tswapl(target_cmsg->cmsg_len)
bellard7854b052003-03-29 17:22:23 +00001073 - TARGET_CMSG_ALIGN(sizeof (struct target_cmsghdr));
1074
1075 space += CMSG_SPACE(len);
1076 if (space > msgh->msg_controllen) {
1077 space -= CMSG_SPACE(len);
bellard31febb72005-12-18 20:03:27 +00001078 gemu_log("Host cmsg overflow\n");
bellard7854b052003-03-29 17:22:23 +00001079 break;
1080 }
1081
1082 cmsg->cmsg_level = tswap32(target_cmsg->cmsg_level);
1083 cmsg->cmsg_type = tswap32(target_cmsg->cmsg_type);
1084 cmsg->cmsg_len = CMSG_LEN(len);
1085
bellard3532fa72006-06-24 15:06:03 +00001086 if (cmsg->cmsg_level != TARGET_SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS) {
bellard7854b052003-03-29 17:22:23 +00001087 gemu_log("Unsupported ancillary data: %d/%d\n", cmsg->cmsg_level, cmsg->cmsg_type);
1088 memcpy(data, target_data, len);
1089 } else {
1090 int *fd = (int *)data;
1091 int *target_fd = (int *)target_data;
1092 int i, numfds = len / sizeof(int);
1093
1094 for (i = 0; i < numfds; i++)
1095 fd[i] = tswap32(target_fd[i]);
1096 }
1097
1098 cmsg = CMSG_NXTHDR(msgh, cmsg);
1099 target_cmsg = TARGET_CMSG_NXTHDR(target_msgh, target_cmsg);
1100 }
bellard5a4a8982007-11-11 17:39:18 +00001101 unlock_user(target_cmsg, target_cmsg_addr, 0);
1102 the_end:
bellard7854b052003-03-29 17:22:23 +00001103 msgh->msg_controllen = space;
bellard5a4a8982007-11-11 17:39:18 +00001104 return 0;
bellard7854b052003-03-29 17:22:23 +00001105}
1106
pbrook53a59602006-03-25 19:31:22 +00001107/* ??? Should this also swap msgh->name? */
bellard5a4a8982007-11-11 17:39:18 +00001108static inline abi_long host_to_target_cmsg(struct target_msghdr *target_msgh,
1109 struct msghdr *msgh)
bellard7854b052003-03-29 17:22:23 +00001110{
1111 struct cmsghdr *cmsg = CMSG_FIRSTHDR(msgh);
bellard5a4a8982007-11-11 17:39:18 +00001112 abi_long msg_controllen;
1113 abi_ulong target_cmsg_addr;
1114 struct target_cmsghdr *target_cmsg;
bellard7854b052003-03-29 17:22:23 +00001115 socklen_t space = 0;
1116
bellard5a4a8982007-11-11 17:39:18 +00001117 msg_controllen = tswapl(target_msgh->msg_controllen);
1118 if (msg_controllen < sizeof (struct target_cmsghdr))
1119 goto the_end;
1120 target_cmsg_addr = tswapl(target_msgh->msg_control);
1121 target_cmsg = lock_user(VERIFY_WRITE, target_cmsg_addr, msg_controllen, 0);
1122 if (!target_cmsg)
1123 return -TARGET_EFAULT;
1124
bellard7854b052003-03-29 17:22:23 +00001125 while (cmsg && target_cmsg) {
1126 void *data = CMSG_DATA(cmsg);
1127 void *target_data = TARGET_CMSG_DATA(target_cmsg);
1128
1129 int len = cmsg->cmsg_len - CMSG_ALIGN(sizeof (struct cmsghdr));
1130
1131 space += TARGET_CMSG_SPACE(len);
bellard5a4a8982007-11-11 17:39:18 +00001132 if (space > msg_controllen) {
bellard7854b052003-03-29 17:22:23 +00001133 space -= TARGET_CMSG_SPACE(len);
bellard31febb72005-12-18 20:03:27 +00001134 gemu_log("Target cmsg overflow\n");
bellard7854b052003-03-29 17:22:23 +00001135 break;
1136 }
1137
1138 target_cmsg->cmsg_level = tswap32(cmsg->cmsg_level);
1139 target_cmsg->cmsg_type = tswap32(cmsg->cmsg_type);
1140 target_cmsg->cmsg_len = tswapl(TARGET_CMSG_LEN(len));
1141
bellard3532fa72006-06-24 15:06:03 +00001142 if (cmsg->cmsg_level != TARGET_SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS) {
bellard7854b052003-03-29 17:22:23 +00001143 gemu_log("Unsupported ancillary data: %d/%d\n", cmsg->cmsg_level, cmsg->cmsg_type);
1144 memcpy(target_data, data, len);
1145 } else {
1146 int *fd = (int *)data;
1147 int *target_fd = (int *)target_data;
1148 int i, numfds = len / sizeof(int);
1149
1150 for (i = 0; i < numfds; i++)
1151 target_fd[i] = tswap32(fd[i]);
1152 }
1153
1154 cmsg = CMSG_NXTHDR(msgh, cmsg);
1155 target_cmsg = TARGET_CMSG_NXTHDR(target_msgh, target_cmsg);
1156 }
bellard5a4a8982007-11-11 17:39:18 +00001157 unlock_user(target_cmsg, target_cmsg_addr, space);
1158 the_end:
1159 target_msgh->msg_controllen = tswapl(space);
1160 return 0;
bellard7854b052003-03-29 17:22:23 +00001161}
1162
ths0da46a62007-10-20 20:23:07 +00001163/* do_setsockopt() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001164static abi_long do_setsockopt(int sockfd, int level, int optname,
bellard2f619692007-11-16 10:46:05 +00001165 abi_ulong optval_addr, socklen_t optlen)
bellard7854b052003-03-29 17:22:23 +00001166{
blueswir1992f48a2007-10-14 16:27:31 +00001167 abi_long ret;
j_mayer32407102007-09-26 23:01:49 +00001168 int val;
Lionel Landwerlinb975b832009-04-25 23:30:19 +02001169 struct ip_mreqn *ip_mreq;
Lionel Landwerlin6e3cb582009-04-25 23:31:18 +02001170 struct ip_mreq_source *ip_mreq_source;
ths3b46e622007-09-17 08:09:54 +00001171
bellard8853f862004-02-22 14:57:26 +00001172 switch(level) {
1173 case SOL_TCP:
bellard7854b052003-03-29 17:22:23 +00001174 /* TCP options all take an 'int' value. */
bellard7854b052003-03-29 17:22:23 +00001175 if (optlen < sizeof(uint32_t))
ths0da46a62007-10-20 20:23:07 +00001176 return -TARGET_EINVAL;
ths3b46e622007-09-17 08:09:54 +00001177
bellard2f619692007-11-16 10:46:05 +00001178 if (get_user_u32(val, optval_addr))
1179 return -TARGET_EFAULT;
bellard8853f862004-02-22 14:57:26 +00001180 ret = get_errno(setsockopt(sockfd, level, optname, &val, sizeof(val)));
1181 break;
1182 case SOL_IP:
1183 switch(optname) {
bellard2efbe912005-07-23 15:10:20 +00001184 case IP_TOS:
1185 case IP_TTL:
bellard8853f862004-02-22 14:57:26 +00001186 case IP_HDRINCL:
bellard2efbe912005-07-23 15:10:20 +00001187 case IP_ROUTER_ALERT:
1188 case IP_RECVOPTS:
1189 case IP_RETOPTS:
1190 case IP_PKTINFO:
1191 case IP_MTU_DISCOVER:
1192 case IP_RECVERR:
1193 case IP_RECVTOS:
1194#ifdef IP_FREEBIND
1195 case IP_FREEBIND:
1196#endif
1197 case IP_MULTICAST_TTL:
1198 case IP_MULTICAST_LOOP:
bellard8853f862004-02-22 14:57:26 +00001199 val = 0;
1200 if (optlen >= sizeof(uint32_t)) {
bellard2f619692007-11-16 10:46:05 +00001201 if (get_user_u32(val, optval_addr))
1202 return -TARGET_EFAULT;
bellard8853f862004-02-22 14:57:26 +00001203 } else if (optlen >= 1) {
bellard2f619692007-11-16 10:46:05 +00001204 if (get_user_u8(val, optval_addr))
1205 return -TARGET_EFAULT;
bellard8853f862004-02-22 14:57:26 +00001206 }
1207 ret = get_errno(setsockopt(sockfd, level, optname, &val, sizeof(val)));
1208 break;
Lionel Landwerlinb975b832009-04-25 23:30:19 +02001209 case IP_ADD_MEMBERSHIP:
1210 case IP_DROP_MEMBERSHIP:
1211 if (optlen < sizeof (struct target_ip_mreq) ||
1212 optlen > sizeof (struct target_ip_mreqn))
1213 return -TARGET_EINVAL;
1214
1215 ip_mreq = (struct ip_mreqn *) alloca(optlen);
1216 target_to_host_ip_mreq(ip_mreq, optval_addr, optlen);
1217 ret = get_errno(setsockopt(sockfd, level, optname, ip_mreq, optlen));
1218 break;
1219
Lionel Landwerlin6e3cb582009-04-25 23:31:18 +02001220 case IP_BLOCK_SOURCE:
1221 case IP_UNBLOCK_SOURCE:
1222 case IP_ADD_SOURCE_MEMBERSHIP:
1223 case IP_DROP_SOURCE_MEMBERSHIP:
1224 if (optlen != sizeof (struct target_ip_mreq_source))
1225 return -TARGET_EINVAL;
1226
1227 ip_mreq_source = lock_user(VERIFY_READ, optval_addr, optlen, 1);
1228 ret = get_errno(setsockopt(sockfd, level, optname, ip_mreq_source, optlen));
1229 unlock_user (ip_mreq_source, optval_addr, 0);
1230 break;
1231
bellard8853f862004-02-22 14:57:26 +00001232 default:
1233 goto unimplemented;
1234 }
1235 break;
bellard3532fa72006-06-24 15:06:03 +00001236 case TARGET_SOL_SOCKET:
bellard8853f862004-02-22 14:57:26 +00001237 switch (optname) {
1238 /* Options with 'int' argument. */
bellard3532fa72006-06-24 15:06:03 +00001239 case TARGET_SO_DEBUG:
1240 optname = SO_DEBUG;
1241 break;
1242 case TARGET_SO_REUSEADDR:
1243 optname = SO_REUSEADDR;
1244 break;
1245 case TARGET_SO_TYPE:
1246 optname = SO_TYPE;
1247 break;
1248 case TARGET_SO_ERROR:
1249 optname = SO_ERROR;
1250 break;
1251 case TARGET_SO_DONTROUTE:
1252 optname = SO_DONTROUTE;
1253 break;
1254 case TARGET_SO_BROADCAST:
1255 optname = SO_BROADCAST;
1256 break;
1257 case TARGET_SO_SNDBUF:
1258 optname = SO_SNDBUF;
1259 break;
1260 case TARGET_SO_RCVBUF:
1261 optname = SO_RCVBUF;
1262 break;
1263 case TARGET_SO_KEEPALIVE:
1264 optname = SO_KEEPALIVE;
1265 break;
1266 case TARGET_SO_OOBINLINE:
1267 optname = SO_OOBINLINE;
1268 break;
1269 case TARGET_SO_NO_CHECK:
1270 optname = SO_NO_CHECK;
1271 break;
1272 case TARGET_SO_PRIORITY:
1273 optname = SO_PRIORITY;
1274 break;
bellard5e83e8e2005-03-01 22:32:06 +00001275#ifdef SO_BSDCOMPAT
bellard3532fa72006-06-24 15:06:03 +00001276 case TARGET_SO_BSDCOMPAT:
1277 optname = SO_BSDCOMPAT;
1278 break;
bellard5e83e8e2005-03-01 22:32:06 +00001279#endif
bellard3532fa72006-06-24 15:06:03 +00001280 case TARGET_SO_PASSCRED:
1281 optname = SO_PASSCRED;
1282 break;
1283 case TARGET_SO_TIMESTAMP:
1284 optname = SO_TIMESTAMP;
1285 break;
1286 case TARGET_SO_RCVLOWAT:
1287 optname = SO_RCVLOWAT;
1288 break;
1289 case TARGET_SO_RCVTIMEO:
1290 optname = SO_RCVTIMEO;
1291 break;
1292 case TARGET_SO_SNDTIMEO:
1293 optname = SO_SNDTIMEO;
1294 break;
bellard8853f862004-02-22 14:57:26 +00001295 break;
1296 default:
1297 goto unimplemented;
1298 }
bellard3532fa72006-06-24 15:06:03 +00001299 if (optlen < sizeof(uint32_t))
bellard2f619692007-11-16 10:46:05 +00001300 return -TARGET_EINVAL;
bellard3532fa72006-06-24 15:06:03 +00001301
bellard2f619692007-11-16 10:46:05 +00001302 if (get_user_u32(val, optval_addr))
1303 return -TARGET_EFAULT;
bellard3532fa72006-06-24 15:06:03 +00001304 ret = get_errno(setsockopt(sockfd, SOL_SOCKET, optname, &val, sizeof(val)));
bellard8853f862004-02-22 14:57:26 +00001305 break;
bellard7854b052003-03-29 17:22:23 +00001306 default:
bellard8853f862004-02-22 14:57:26 +00001307 unimplemented:
1308 gemu_log("Unsupported setsockopt level=%d optname=%d \n", level, optname);
ths6fa13c12007-12-18 02:41:04 +00001309 ret = -TARGET_ENOPROTOOPT;
bellard7854b052003-03-29 17:22:23 +00001310 }
bellard8853f862004-02-22 14:57:26 +00001311 return ret;
bellard7854b052003-03-29 17:22:23 +00001312}
1313
ths0da46a62007-10-20 20:23:07 +00001314/* do_getsockopt() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001315static abi_long do_getsockopt(int sockfd, int level, int optname,
bellard2f619692007-11-16 10:46:05 +00001316 abi_ulong optval_addr, abi_ulong optlen)
bellard7854b052003-03-29 17:22:23 +00001317{
blueswir1992f48a2007-10-14 16:27:31 +00001318 abi_long ret;
blueswir1b55266b2008-09-20 08:07:15 +00001319 int len, val;
1320 socklen_t lv;
bellard8853f862004-02-22 14:57:26 +00001321
1322 switch(level) {
bellard3532fa72006-06-24 15:06:03 +00001323 case TARGET_SOL_SOCKET:
1324 level = SOL_SOCKET;
bellard8853f862004-02-22 14:57:26 +00001325 switch (optname) {
bellard3532fa72006-06-24 15:06:03 +00001326 case TARGET_SO_LINGER:
1327 case TARGET_SO_RCVTIMEO:
1328 case TARGET_SO_SNDTIMEO:
1329 case TARGET_SO_PEERCRED:
1330 case TARGET_SO_PEERNAME:
bellard8853f862004-02-22 14:57:26 +00001331 /* These don't just return a single integer */
1332 goto unimplemented;
1333 default:
bellard2efbe912005-07-23 15:10:20 +00001334 goto int_case;
1335 }
1336 break;
1337 case SOL_TCP:
1338 /* TCP options all take an 'int' value. */
1339 int_case:
bellard2f619692007-11-16 10:46:05 +00001340 if (get_user_u32(len, optlen))
1341 return -TARGET_EFAULT;
bellard2efbe912005-07-23 15:10:20 +00001342 if (len < 0)
ths0da46a62007-10-20 20:23:07 +00001343 return -TARGET_EINVAL;
bellard2efbe912005-07-23 15:10:20 +00001344 lv = sizeof(int);
1345 ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
1346 if (ret < 0)
1347 return ret;
bellard2efbe912005-07-23 15:10:20 +00001348 if (len > lv)
1349 len = lv;
bellard2f619692007-11-16 10:46:05 +00001350 if (len == 4) {
1351 if (put_user_u32(val, optval_addr))
1352 return -TARGET_EFAULT;
1353 } else {
1354 if (put_user_u8(val, optval_addr))
1355 return -TARGET_EFAULT;
1356 }
1357 if (put_user_u32(len, optlen))
1358 return -TARGET_EFAULT;
bellard2efbe912005-07-23 15:10:20 +00001359 break;
1360 case SOL_IP:
1361 switch(optname) {
1362 case IP_TOS:
1363 case IP_TTL:
1364 case IP_HDRINCL:
1365 case IP_ROUTER_ALERT:
1366 case IP_RECVOPTS:
1367 case IP_RETOPTS:
1368 case IP_PKTINFO:
1369 case IP_MTU_DISCOVER:
1370 case IP_RECVERR:
1371 case IP_RECVTOS:
1372#ifdef IP_FREEBIND
1373 case IP_FREEBIND:
1374#endif
1375 case IP_MULTICAST_TTL:
1376 case IP_MULTICAST_LOOP:
bellard2f619692007-11-16 10:46:05 +00001377 if (get_user_u32(len, optlen))
1378 return -TARGET_EFAULT;
bellard8853f862004-02-22 14:57:26 +00001379 if (len < 0)
ths0da46a62007-10-20 20:23:07 +00001380 return -TARGET_EINVAL;
bellard8853f862004-02-22 14:57:26 +00001381 lv = sizeof(int);
1382 ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
1383 if (ret < 0)
1384 return ret;
bellard2efbe912005-07-23 15:10:20 +00001385 if (len < sizeof(int) && len > 0 && val >= 0 && val < 255) {
bellard2efbe912005-07-23 15:10:20 +00001386 len = 1;
bellard2f619692007-11-16 10:46:05 +00001387 if (put_user_u32(len, optlen)
1388 || put_user_u8(val, optval_addr))
1389 return -TARGET_EFAULT;
bellard2efbe912005-07-23 15:10:20 +00001390 } else {
bellard2efbe912005-07-23 15:10:20 +00001391 if (len > sizeof(int))
1392 len = sizeof(int);
bellard2f619692007-11-16 10:46:05 +00001393 if (put_user_u32(len, optlen)
1394 || put_user_u32(val, optval_addr))
1395 return -TARGET_EFAULT;
bellard2efbe912005-07-23 15:10:20 +00001396 }
bellard8853f862004-02-22 14:57:26 +00001397 break;
bellard2efbe912005-07-23 15:10:20 +00001398 default:
thsc02f4992007-12-18 02:39:59 +00001399 ret = -TARGET_ENOPROTOOPT;
1400 break;
bellard8853f862004-02-22 14:57:26 +00001401 }
1402 break;
1403 default:
1404 unimplemented:
1405 gemu_log("getsockopt level=%d optname=%d not yet supported\n",
1406 level, optname);
thsc02f4992007-12-18 02:39:59 +00001407 ret = -TARGET_EOPNOTSUPP;
bellard8853f862004-02-22 14:57:26 +00001408 break;
1409 }
1410 return ret;
bellard7854b052003-03-29 17:22:23 +00001411}
1412
bellard579a97f2007-11-11 14:26:47 +00001413/* FIXME
1414 * lock_iovec()/unlock_iovec() have a return code of 0 for success where
1415 * other lock functions have a return code of 0 for failure.
1416 */
1417static abi_long lock_iovec(int type, struct iovec *vec, abi_ulong target_addr,
1418 int count, int copy)
pbrook53a59602006-03-25 19:31:22 +00001419{
1420 struct target_iovec *target_vec;
blueswir1992f48a2007-10-14 16:27:31 +00001421 abi_ulong base;
balrogd732dcb2008-10-28 10:21:03 +00001422 int i;
pbrook53a59602006-03-25 19:31:22 +00001423
bellard579a97f2007-11-11 14:26:47 +00001424 target_vec = lock_user(VERIFY_READ, target_addr, count * sizeof(struct target_iovec), 1);
1425 if (!target_vec)
1426 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00001427 for(i = 0;i < count; i++) {
1428 base = tswapl(target_vec[i].iov_base);
1429 vec[i].iov_len = tswapl(target_vec[i].iov_len);
bellard41df8412008-02-04 22:26:57 +00001430 if (vec[i].iov_len != 0) {
1431 vec[i].iov_base = lock_user(type, base, vec[i].iov_len, copy);
balrogd732dcb2008-10-28 10:21:03 +00001432 /* Don't check lock_user return value. We must call writev even
1433 if a element has invalid base address. */
bellard41df8412008-02-04 22:26:57 +00001434 } else {
1435 /* zero length pointer is ignored */
1436 vec[i].iov_base = NULL;
1437 }
pbrook53a59602006-03-25 19:31:22 +00001438 }
1439 unlock_user (target_vec, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00001440 return 0;
pbrook53a59602006-03-25 19:31:22 +00001441}
1442
bellard579a97f2007-11-11 14:26:47 +00001443static abi_long unlock_iovec(struct iovec *vec, abi_ulong target_addr,
1444 int count, int copy)
pbrook53a59602006-03-25 19:31:22 +00001445{
1446 struct target_iovec *target_vec;
blueswir1992f48a2007-10-14 16:27:31 +00001447 abi_ulong base;
pbrook53a59602006-03-25 19:31:22 +00001448 int i;
1449
bellard579a97f2007-11-11 14:26:47 +00001450 target_vec = lock_user(VERIFY_READ, target_addr, count * sizeof(struct target_iovec), 1);
1451 if (!target_vec)
1452 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00001453 for(i = 0;i < count; i++) {
balrogd732dcb2008-10-28 10:21:03 +00001454 if (target_vec[i].iov_base) {
1455 base = tswapl(target_vec[i].iov_base);
1456 unlock_user(vec[i].iov_base, base, copy ? vec[i].iov_len : 0);
1457 }
pbrook53a59602006-03-25 19:31:22 +00001458 }
1459 unlock_user (target_vec, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00001460
1461 return 0;
pbrook53a59602006-03-25 19:31:22 +00001462}
1463
ths0da46a62007-10-20 20:23:07 +00001464/* do_socket() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001465static abi_long do_socket(int domain, int type, int protocol)
bellard3532fa72006-06-24 15:06:03 +00001466{
1467#if defined(TARGET_MIPS)
1468 switch(type) {
1469 case TARGET_SOCK_DGRAM:
1470 type = SOCK_DGRAM;
1471 break;
1472 case TARGET_SOCK_STREAM:
1473 type = SOCK_STREAM;
1474 break;
1475 case TARGET_SOCK_RAW:
1476 type = SOCK_RAW;
1477 break;
1478 case TARGET_SOCK_RDM:
1479 type = SOCK_RDM;
1480 break;
1481 case TARGET_SOCK_SEQPACKET:
1482 type = SOCK_SEQPACKET;
1483 break;
1484 case TARGET_SOCK_PACKET:
1485 type = SOCK_PACKET;
1486 break;
1487 }
1488#endif
balrog12bc92a2007-10-30 21:06:14 +00001489 if (domain == PF_NETLINK)
1490 return -EAFNOSUPPORT; /* do not NETLINK socket connections possible */
bellard3532fa72006-06-24 15:06:03 +00001491 return get_errno(socket(domain, type, protocol));
1492}
1493
ths0da46a62007-10-20 20:23:07 +00001494/* do_bind() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001495static abi_long do_bind(int sockfd, abi_ulong target_addr,
1496 socklen_t addrlen)
bellard3532fa72006-06-24 15:06:03 +00001497{
aurel328f7aeaf2009-01-30 19:47:57 +00001498 void *addr;
Arnaud Patard917507b2009-06-19 10:44:45 +03001499 abi_long ret;
aurel328f7aeaf2009-01-30 19:47:57 +00001500
aurel32be09ac42009-04-15 16:12:06 +00001501 if (addrlen < 0)
aurel328f7aeaf2009-01-30 19:47:57 +00001502 return -TARGET_EINVAL;
1503
aurel32607175e2009-04-15 16:11:59 +00001504 addr = alloca(addrlen+1);
ths3b46e622007-09-17 08:09:54 +00001505
Arnaud Patard917507b2009-06-19 10:44:45 +03001506 ret = target_to_host_sockaddr(addr, target_addr, addrlen);
1507 if (ret)
1508 return ret;
1509
bellard3532fa72006-06-24 15:06:03 +00001510 return get_errno(bind(sockfd, addr, addrlen));
1511}
1512
ths0da46a62007-10-20 20:23:07 +00001513/* do_connect() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001514static abi_long do_connect(int sockfd, abi_ulong target_addr,
1515 socklen_t addrlen)
bellard3532fa72006-06-24 15:06:03 +00001516{
aurel328f7aeaf2009-01-30 19:47:57 +00001517 void *addr;
Arnaud Patard917507b2009-06-19 10:44:45 +03001518 abi_long ret;
aurel328f7aeaf2009-01-30 19:47:57 +00001519
aurel32be09ac42009-04-15 16:12:06 +00001520 if (addrlen < 0)
aurel328f7aeaf2009-01-30 19:47:57 +00001521 return -TARGET_EINVAL;
1522
1523 addr = alloca(addrlen);
ths3b46e622007-09-17 08:09:54 +00001524
Arnaud Patard917507b2009-06-19 10:44:45 +03001525 ret = target_to_host_sockaddr(addr, target_addr, addrlen);
1526 if (ret)
1527 return ret;
1528
bellard3532fa72006-06-24 15:06:03 +00001529 return get_errno(connect(sockfd, addr, addrlen));
1530}
1531
ths0da46a62007-10-20 20:23:07 +00001532/* do_sendrecvmsg() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001533static abi_long do_sendrecvmsg(int fd, abi_ulong target_msg,
1534 int flags, int send)
bellard3532fa72006-06-24 15:06:03 +00001535{
balrog6de645c2008-10-28 10:26:29 +00001536 abi_long ret, len;
bellard3532fa72006-06-24 15:06:03 +00001537 struct target_msghdr *msgp;
1538 struct msghdr msg;
1539 int count;
1540 struct iovec *vec;
blueswir1992f48a2007-10-14 16:27:31 +00001541 abi_ulong target_vec;
bellard3532fa72006-06-24 15:06:03 +00001542
bellard579a97f2007-11-11 14:26:47 +00001543 /* FIXME */
1544 if (!lock_user_struct(send ? VERIFY_READ : VERIFY_WRITE,
1545 msgp,
1546 target_msg,
1547 send ? 1 : 0))
1548 return -TARGET_EFAULT;
bellard3532fa72006-06-24 15:06:03 +00001549 if (msgp->msg_name) {
1550 msg.msg_namelen = tswap32(msgp->msg_namelen);
1551 msg.msg_name = alloca(msg.msg_namelen);
Arnaud Patard917507b2009-06-19 10:44:45 +03001552 ret = target_to_host_sockaddr(msg.msg_name, tswapl(msgp->msg_name),
bellard3532fa72006-06-24 15:06:03 +00001553 msg.msg_namelen);
Arnaud Patard917507b2009-06-19 10:44:45 +03001554 if (ret) {
1555 unlock_user_struct(msgp, target_msg, send ? 0 : 1);
1556 return ret;
1557 }
bellard3532fa72006-06-24 15:06:03 +00001558 } else {
1559 msg.msg_name = NULL;
1560 msg.msg_namelen = 0;
1561 }
1562 msg.msg_controllen = 2 * tswapl(msgp->msg_controllen);
1563 msg.msg_control = alloca(msg.msg_controllen);
1564 msg.msg_flags = tswap32(msgp->msg_flags);
ths3b46e622007-09-17 08:09:54 +00001565
bellard3532fa72006-06-24 15:06:03 +00001566 count = tswapl(msgp->msg_iovlen);
1567 vec = alloca(count * sizeof(struct iovec));
1568 target_vec = tswapl(msgp->msg_iov);
bellard579a97f2007-11-11 14:26:47 +00001569 lock_iovec(send ? VERIFY_READ : VERIFY_WRITE, vec, target_vec, count, send);
bellard3532fa72006-06-24 15:06:03 +00001570 msg.msg_iovlen = count;
1571 msg.msg_iov = vec;
ths3b46e622007-09-17 08:09:54 +00001572
bellard3532fa72006-06-24 15:06:03 +00001573 if (send) {
bellard5a4a8982007-11-11 17:39:18 +00001574 ret = target_to_host_cmsg(&msg, msgp);
1575 if (ret == 0)
1576 ret = get_errno(sendmsg(fd, &msg, flags));
bellard3532fa72006-06-24 15:06:03 +00001577 } else {
1578 ret = get_errno(recvmsg(fd, &msg, flags));
balrog6de645c2008-10-28 10:26:29 +00001579 if (!is_error(ret)) {
1580 len = ret;
bellard5a4a8982007-11-11 17:39:18 +00001581 ret = host_to_target_cmsg(msgp, &msg);
balrog6de645c2008-10-28 10:26:29 +00001582 if (!is_error(ret))
1583 ret = len;
1584 }
bellard3532fa72006-06-24 15:06:03 +00001585 }
1586 unlock_iovec(vec, target_vec, count, !send);
bellard579a97f2007-11-11 14:26:47 +00001587 unlock_user_struct(msgp, target_msg, send ? 0 : 1);
bellard3532fa72006-06-24 15:06:03 +00001588 return ret;
1589}
1590
ths0da46a62007-10-20 20:23:07 +00001591/* do_accept() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001592static abi_long do_accept(int fd, abi_ulong target_addr,
bellard2f619692007-11-16 10:46:05 +00001593 abi_ulong target_addrlen_addr)
pbrook1be9e1d2006-11-19 15:26:04 +00001594{
bellard2f619692007-11-16 10:46:05 +00001595 socklen_t addrlen;
1596 void *addr;
blueswir1992f48a2007-10-14 16:27:31 +00001597 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00001598
Arnaud Patard917507b2009-06-19 10:44:45 +03001599 if (target_addr == 0)
1600 return get_errno(accept(fd, NULL, NULL));
1601
1602 /* linux returns EINVAL if addrlen pointer is invalid */
bellard2f619692007-11-16 10:46:05 +00001603 if (get_user_u32(addrlen, target_addrlen_addr))
Arnaud Patard917507b2009-06-19 10:44:45 +03001604 return -TARGET_EINVAL;
bellard2f619692007-11-16 10:46:05 +00001605
aurel32be09ac42009-04-15 16:12:06 +00001606 if (addrlen < 0)
aurel328f7aeaf2009-01-30 19:47:57 +00001607 return -TARGET_EINVAL;
1608
Arnaud Patard917507b2009-06-19 10:44:45 +03001609 if (!access_ok(VERIFY_WRITE, target_addr, addrlen))
1610 return -TARGET_EINVAL;
1611
bellard2f619692007-11-16 10:46:05 +00001612 addr = alloca(addrlen);
1613
pbrook1be9e1d2006-11-19 15:26:04 +00001614 ret = get_errno(accept(fd, addr, &addrlen));
1615 if (!is_error(ret)) {
1616 host_to_target_sockaddr(target_addr, addr, addrlen);
bellard2f619692007-11-16 10:46:05 +00001617 if (put_user_u32(addrlen, target_addrlen_addr))
1618 ret = -TARGET_EFAULT;
pbrook1be9e1d2006-11-19 15:26:04 +00001619 }
1620 return ret;
1621}
1622
ths0da46a62007-10-20 20:23:07 +00001623/* do_getpeername() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001624static abi_long do_getpeername(int fd, abi_ulong target_addr,
bellard2f619692007-11-16 10:46:05 +00001625 abi_ulong target_addrlen_addr)
pbrook1be9e1d2006-11-19 15:26:04 +00001626{
bellard2f619692007-11-16 10:46:05 +00001627 socklen_t addrlen;
1628 void *addr;
blueswir1992f48a2007-10-14 16:27:31 +00001629 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00001630
bellard2f619692007-11-16 10:46:05 +00001631 if (get_user_u32(addrlen, target_addrlen_addr))
1632 return -TARGET_EFAULT;
1633
aurel32be09ac42009-04-15 16:12:06 +00001634 if (addrlen < 0)
aurel328f7aeaf2009-01-30 19:47:57 +00001635 return -TARGET_EINVAL;
1636
Arnaud Patard917507b2009-06-19 10:44:45 +03001637 if (!access_ok(VERIFY_WRITE, target_addr, addrlen))
1638 return -TARGET_EFAULT;
1639
bellard2f619692007-11-16 10:46:05 +00001640 addr = alloca(addrlen);
1641
pbrook1be9e1d2006-11-19 15:26:04 +00001642 ret = get_errno(getpeername(fd, addr, &addrlen));
1643 if (!is_error(ret)) {
1644 host_to_target_sockaddr(target_addr, addr, addrlen);
bellard2f619692007-11-16 10:46:05 +00001645 if (put_user_u32(addrlen, target_addrlen_addr))
1646 ret = -TARGET_EFAULT;
pbrook1be9e1d2006-11-19 15:26:04 +00001647 }
1648 return ret;
1649}
1650
ths0da46a62007-10-20 20:23:07 +00001651/* do_getsockname() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001652static abi_long do_getsockname(int fd, abi_ulong target_addr,
bellard2f619692007-11-16 10:46:05 +00001653 abi_ulong target_addrlen_addr)
pbrook1be9e1d2006-11-19 15:26:04 +00001654{
bellard2f619692007-11-16 10:46:05 +00001655 socklen_t addrlen;
1656 void *addr;
blueswir1992f48a2007-10-14 16:27:31 +00001657 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00001658
bellard2f619692007-11-16 10:46:05 +00001659 if (get_user_u32(addrlen, target_addrlen_addr))
1660 return -TARGET_EFAULT;
1661
aurel32be09ac42009-04-15 16:12:06 +00001662 if (addrlen < 0)
aurel328f7aeaf2009-01-30 19:47:57 +00001663 return -TARGET_EINVAL;
1664
Arnaud Patard917507b2009-06-19 10:44:45 +03001665 if (!access_ok(VERIFY_WRITE, target_addr, addrlen))
1666 return -TARGET_EFAULT;
1667
bellard2f619692007-11-16 10:46:05 +00001668 addr = alloca(addrlen);
1669
pbrook1be9e1d2006-11-19 15:26:04 +00001670 ret = get_errno(getsockname(fd, addr, &addrlen));
1671 if (!is_error(ret)) {
1672 host_to_target_sockaddr(target_addr, addr, addrlen);
bellard2f619692007-11-16 10:46:05 +00001673 if (put_user_u32(addrlen, target_addrlen_addr))
1674 ret = -TARGET_EFAULT;
pbrook1be9e1d2006-11-19 15:26:04 +00001675 }
1676 return ret;
1677}
1678
ths0da46a62007-10-20 20:23:07 +00001679/* do_socketpair() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001680static abi_long do_socketpair(int domain, int type, int protocol,
bellard2f619692007-11-16 10:46:05 +00001681 abi_ulong target_tab_addr)
pbrook1be9e1d2006-11-19 15:26:04 +00001682{
1683 int tab[2];
blueswir1992f48a2007-10-14 16:27:31 +00001684 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00001685
1686 ret = get_errno(socketpair(domain, type, protocol, tab));
1687 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +00001688 if (put_user_s32(tab[0], target_tab_addr)
1689 || put_user_s32(tab[1], target_tab_addr + sizeof(tab[0])))
1690 ret = -TARGET_EFAULT;
pbrook1be9e1d2006-11-19 15:26:04 +00001691 }
1692 return ret;
1693}
1694
ths0da46a62007-10-20 20:23:07 +00001695/* do_sendto() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001696static abi_long do_sendto(int fd, abi_ulong msg, size_t len, int flags,
1697 abi_ulong target_addr, socklen_t addrlen)
pbrook1be9e1d2006-11-19 15:26:04 +00001698{
1699 void *addr;
1700 void *host_msg;
blueswir1992f48a2007-10-14 16:27:31 +00001701 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00001702
aurel32be09ac42009-04-15 16:12:06 +00001703 if (addrlen < 0)
aurel328f7aeaf2009-01-30 19:47:57 +00001704 return -TARGET_EINVAL;
1705
bellard579a97f2007-11-11 14:26:47 +00001706 host_msg = lock_user(VERIFY_READ, msg, len, 1);
1707 if (!host_msg)
1708 return -TARGET_EFAULT;
pbrook1be9e1d2006-11-19 15:26:04 +00001709 if (target_addr) {
1710 addr = alloca(addrlen);
Arnaud Patard917507b2009-06-19 10:44:45 +03001711 ret = target_to_host_sockaddr(addr, target_addr, addrlen);
1712 if (ret) {
1713 unlock_user(host_msg, msg, 0);
1714 return ret;
1715 }
pbrook1be9e1d2006-11-19 15:26:04 +00001716 ret = get_errno(sendto(fd, host_msg, len, flags, addr, addrlen));
1717 } else {
1718 ret = get_errno(send(fd, host_msg, len, flags));
1719 }
1720 unlock_user(host_msg, msg, 0);
1721 return ret;
1722}
1723
ths0da46a62007-10-20 20:23:07 +00001724/* do_recvfrom() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001725static abi_long do_recvfrom(int fd, abi_ulong msg, size_t len, int flags,
1726 abi_ulong target_addr,
1727 abi_ulong target_addrlen)
pbrook1be9e1d2006-11-19 15:26:04 +00001728{
1729 socklen_t addrlen;
1730 void *addr;
1731 void *host_msg;
blueswir1992f48a2007-10-14 16:27:31 +00001732 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00001733
bellard579a97f2007-11-11 14:26:47 +00001734 host_msg = lock_user(VERIFY_WRITE, msg, len, 0);
1735 if (!host_msg)
1736 return -TARGET_EFAULT;
pbrook1be9e1d2006-11-19 15:26:04 +00001737 if (target_addr) {
bellard2f619692007-11-16 10:46:05 +00001738 if (get_user_u32(addrlen, target_addrlen)) {
1739 ret = -TARGET_EFAULT;
1740 goto fail;
1741 }
aurel32be09ac42009-04-15 16:12:06 +00001742 if (addrlen < 0) {
aurel328f7aeaf2009-01-30 19:47:57 +00001743 ret = -TARGET_EINVAL;
1744 goto fail;
1745 }
pbrook1be9e1d2006-11-19 15:26:04 +00001746 addr = alloca(addrlen);
1747 ret = get_errno(recvfrom(fd, host_msg, len, flags, addr, &addrlen));
1748 } else {
1749 addr = NULL; /* To keep compiler quiet. */
1750 ret = get_errno(recv(fd, host_msg, len, flags));
1751 }
1752 if (!is_error(ret)) {
1753 if (target_addr) {
1754 host_to_target_sockaddr(target_addr, addr, addrlen);
bellard2f619692007-11-16 10:46:05 +00001755 if (put_user_u32(addrlen, target_addrlen)) {
1756 ret = -TARGET_EFAULT;
1757 goto fail;
1758 }
pbrook1be9e1d2006-11-19 15:26:04 +00001759 }
1760 unlock_user(host_msg, msg, len);
1761 } else {
bellard2f619692007-11-16 10:46:05 +00001762fail:
pbrook1be9e1d2006-11-19 15:26:04 +00001763 unlock_user(host_msg, msg, 0);
1764 }
1765 return ret;
1766}
1767
j_mayer32407102007-09-26 23:01:49 +00001768#ifdef TARGET_NR_socketcall
ths0da46a62007-10-20 20:23:07 +00001769/* do_socketcall() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001770static abi_long do_socketcall(int num, abi_ulong vptr)
bellard31e31b82003-02-18 22:55:36 +00001771{
blueswir1992f48a2007-10-14 16:27:31 +00001772 abi_long ret;
1773 const int n = sizeof(abi_ulong);
bellard31e31b82003-02-18 22:55:36 +00001774
1775 switch(num) {
1776 case SOCKOP_socket:
bellard7854b052003-03-29 17:22:23 +00001777 {
Ulrich Hecht98818182009-07-03 17:09:28 +02001778 abi_ulong domain, type, protocol;
bellard2f619692007-11-16 10:46:05 +00001779
Ulrich Hecht98818182009-07-03 17:09:28 +02001780 if (get_user_ual(domain, vptr)
1781 || get_user_ual(type, vptr + n)
1782 || get_user_ual(protocol, vptr + 2 * n))
bellard2f619692007-11-16 10:46:05 +00001783 return -TARGET_EFAULT;
1784
bellard3532fa72006-06-24 15:06:03 +00001785 ret = do_socket(domain, type, protocol);
bellard7854b052003-03-29 17:22:23 +00001786 }
bellard31e31b82003-02-18 22:55:36 +00001787 break;
1788 case SOCKOP_bind:
bellard7854b052003-03-29 17:22:23 +00001789 {
Ulrich Hecht98818182009-07-03 17:09:28 +02001790 abi_ulong sockfd;
bellard2f619692007-11-16 10:46:05 +00001791 abi_ulong target_addr;
1792 socklen_t addrlen;
1793
Ulrich Hecht98818182009-07-03 17:09:28 +02001794 if (get_user_ual(sockfd, vptr)
bellard2f619692007-11-16 10:46:05 +00001795 || get_user_ual(target_addr, vptr + n)
Ulrich Hecht98818182009-07-03 17:09:28 +02001796 || get_user_ual(addrlen, vptr + 2 * n))
bellard2f619692007-11-16 10:46:05 +00001797 return -TARGET_EFAULT;
1798
bellard3532fa72006-06-24 15:06:03 +00001799 ret = do_bind(sockfd, target_addr, addrlen);
bellard7854b052003-03-29 17:22:23 +00001800 }
bellard31e31b82003-02-18 22:55:36 +00001801 break;
1802 case SOCKOP_connect:
bellard7854b052003-03-29 17:22:23 +00001803 {
Ulrich Hecht98818182009-07-03 17:09:28 +02001804 abi_ulong sockfd;
bellard2f619692007-11-16 10:46:05 +00001805 abi_ulong target_addr;
1806 socklen_t addrlen;
1807
Ulrich Hecht98818182009-07-03 17:09:28 +02001808 if (get_user_ual(sockfd, vptr)
bellard2f619692007-11-16 10:46:05 +00001809 || get_user_ual(target_addr, vptr + n)
Ulrich Hecht98818182009-07-03 17:09:28 +02001810 || get_user_ual(addrlen, vptr + 2 * n))
bellard2f619692007-11-16 10:46:05 +00001811 return -TARGET_EFAULT;
1812
bellard3532fa72006-06-24 15:06:03 +00001813 ret = do_connect(sockfd, target_addr, addrlen);
bellard7854b052003-03-29 17:22:23 +00001814 }
bellard31e31b82003-02-18 22:55:36 +00001815 break;
1816 case SOCKOP_listen:
bellard7854b052003-03-29 17:22:23 +00001817 {
Ulrich Hecht98818182009-07-03 17:09:28 +02001818 abi_ulong sockfd, backlog;
bellard2f619692007-11-16 10:46:05 +00001819
Ulrich Hecht98818182009-07-03 17:09:28 +02001820 if (get_user_ual(sockfd, vptr)
1821 || get_user_ual(backlog, vptr + n))
bellard2f619692007-11-16 10:46:05 +00001822 return -TARGET_EFAULT;
1823
bellard7854b052003-03-29 17:22:23 +00001824 ret = get_errno(listen(sockfd, backlog));
1825 }
bellard31e31b82003-02-18 22:55:36 +00001826 break;
1827 case SOCKOP_accept:
1828 {
Ulrich Hecht98818182009-07-03 17:09:28 +02001829 abi_ulong sockfd;
bellard2f619692007-11-16 10:46:05 +00001830 abi_ulong target_addr, target_addrlen;
1831
Ulrich Hecht98818182009-07-03 17:09:28 +02001832 if (get_user_ual(sockfd, vptr)
bellard2f619692007-11-16 10:46:05 +00001833 || get_user_ual(target_addr, vptr + n)
Ulrich Hecht98818182009-07-03 17:09:28 +02001834 || get_user_ual(target_addrlen, vptr + 2 * n))
bellard2f619692007-11-16 10:46:05 +00001835 return -TARGET_EFAULT;
1836
pbrook1be9e1d2006-11-19 15:26:04 +00001837 ret = do_accept(sockfd, target_addr, target_addrlen);
bellard31e31b82003-02-18 22:55:36 +00001838 }
1839 break;
1840 case SOCKOP_getsockname:
1841 {
Ulrich Hecht98818182009-07-03 17:09:28 +02001842 abi_ulong sockfd;
bellard2f619692007-11-16 10:46:05 +00001843 abi_ulong target_addr, target_addrlen;
1844
Ulrich Hecht98818182009-07-03 17:09:28 +02001845 if (get_user_ual(sockfd, vptr)
bellard2f619692007-11-16 10:46:05 +00001846 || get_user_ual(target_addr, vptr + n)
Ulrich Hecht98818182009-07-03 17:09:28 +02001847 || get_user_ual(target_addrlen, vptr + 2 * n))
bellard2f619692007-11-16 10:46:05 +00001848 return -TARGET_EFAULT;
1849
pbrook1be9e1d2006-11-19 15:26:04 +00001850 ret = do_getsockname(sockfd, target_addr, target_addrlen);
bellard31e31b82003-02-18 22:55:36 +00001851 }
1852 break;
1853 case SOCKOP_getpeername:
1854 {
Ulrich Hecht98818182009-07-03 17:09:28 +02001855 abi_ulong sockfd;
bellard2f619692007-11-16 10:46:05 +00001856 abi_ulong target_addr, target_addrlen;
1857
Ulrich Hecht98818182009-07-03 17:09:28 +02001858 if (get_user_ual(sockfd, vptr)
bellard2f619692007-11-16 10:46:05 +00001859 || get_user_ual(target_addr, vptr + n)
Ulrich Hecht98818182009-07-03 17:09:28 +02001860 || get_user_ual(target_addrlen, vptr + 2 * n))
bellard2f619692007-11-16 10:46:05 +00001861 return -TARGET_EFAULT;
1862
pbrook1be9e1d2006-11-19 15:26:04 +00001863 ret = do_getpeername(sockfd, target_addr, target_addrlen);
bellard31e31b82003-02-18 22:55:36 +00001864 }
1865 break;
1866 case SOCKOP_socketpair:
1867 {
Ulrich Hecht98818182009-07-03 17:09:28 +02001868 abi_ulong domain, type, protocol;
bellard2f619692007-11-16 10:46:05 +00001869 abi_ulong tab;
1870
Ulrich Hecht98818182009-07-03 17:09:28 +02001871 if (get_user_ual(domain, vptr)
1872 || get_user_ual(type, vptr + n)
1873 || get_user_ual(protocol, vptr + 2 * n)
bellard2f619692007-11-16 10:46:05 +00001874 || get_user_ual(tab, vptr + 3 * n))
1875 return -TARGET_EFAULT;
1876
pbrook1be9e1d2006-11-19 15:26:04 +00001877 ret = do_socketpair(domain, type, protocol, tab);
bellard31e31b82003-02-18 22:55:36 +00001878 }
1879 break;
1880 case SOCKOP_send:
bellard7854b052003-03-29 17:22:23 +00001881 {
Ulrich Hecht98818182009-07-03 17:09:28 +02001882 abi_ulong sockfd;
bellard2f619692007-11-16 10:46:05 +00001883 abi_ulong msg;
1884 size_t len;
Ulrich Hecht98818182009-07-03 17:09:28 +02001885 abi_ulong flags;
bellard2f619692007-11-16 10:46:05 +00001886
Ulrich Hecht98818182009-07-03 17:09:28 +02001887 if (get_user_ual(sockfd, vptr)
bellard2f619692007-11-16 10:46:05 +00001888 || get_user_ual(msg, vptr + n)
1889 || get_user_ual(len, vptr + 2 * n)
Ulrich Hecht98818182009-07-03 17:09:28 +02001890 || get_user_ual(flags, vptr + 3 * n))
bellard2f619692007-11-16 10:46:05 +00001891 return -TARGET_EFAULT;
1892
pbrook1be9e1d2006-11-19 15:26:04 +00001893 ret = do_sendto(sockfd, msg, len, flags, 0, 0);
bellard7854b052003-03-29 17:22:23 +00001894 }
bellard31e31b82003-02-18 22:55:36 +00001895 break;
1896 case SOCKOP_recv:
bellard7854b052003-03-29 17:22:23 +00001897 {
Ulrich Hecht98818182009-07-03 17:09:28 +02001898 abi_ulong sockfd;
bellard2f619692007-11-16 10:46:05 +00001899 abi_ulong msg;
1900 size_t len;
Ulrich Hecht98818182009-07-03 17:09:28 +02001901 abi_ulong flags;
bellard2f619692007-11-16 10:46:05 +00001902
Ulrich Hecht98818182009-07-03 17:09:28 +02001903 if (get_user_ual(sockfd, vptr)
bellard2f619692007-11-16 10:46:05 +00001904 || get_user_ual(msg, vptr + n)
1905 || get_user_ual(len, vptr + 2 * n)
Ulrich Hecht98818182009-07-03 17:09:28 +02001906 || get_user_ual(flags, vptr + 3 * n))
bellard2f619692007-11-16 10:46:05 +00001907 return -TARGET_EFAULT;
1908
pbrook1be9e1d2006-11-19 15:26:04 +00001909 ret = do_recvfrom(sockfd, msg, len, flags, 0, 0);
bellard7854b052003-03-29 17:22:23 +00001910 }
bellard31e31b82003-02-18 22:55:36 +00001911 break;
1912 case SOCKOP_sendto:
bellard7854b052003-03-29 17:22:23 +00001913 {
Ulrich Hecht98818182009-07-03 17:09:28 +02001914 abi_ulong sockfd;
bellard2f619692007-11-16 10:46:05 +00001915 abi_ulong msg;
1916 size_t len;
Ulrich Hecht98818182009-07-03 17:09:28 +02001917 abi_ulong flags;
bellard2f619692007-11-16 10:46:05 +00001918 abi_ulong addr;
1919 socklen_t addrlen;
1920
Ulrich Hecht98818182009-07-03 17:09:28 +02001921 if (get_user_ual(sockfd, vptr)
bellard2f619692007-11-16 10:46:05 +00001922 || get_user_ual(msg, vptr + n)
1923 || get_user_ual(len, vptr + 2 * n)
Ulrich Hecht98818182009-07-03 17:09:28 +02001924 || get_user_ual(flags, vptr + 3 * n)
bellard2f619692007-11-16 10:46:05 +00001925 || get_user_ual(addr, vptr + 4 * n)
Ulrich Hecht98818182009-07-03 17:09:28 +02001926 || get_user_ual(addrlen, vptr + 5 * n))
bellard2f619692007-11-16 10:46:05 +00001927 return -TARGET_EFAULT;
1928
pbrook1be9e1d2006-11-19 15:26:04 +00001929 ret = do_sendto(sockfd, msg, len, flags, addr, addrlen);
bellard7854b052003-03-29 17:22:23 +00001930 }
bellard31e31b82003-02-18 22:55:36 +00001931 break;
1932 case SOCKOP_recvfrom:
1933 {
Ulrich Hecht98818182009-07-03 17:09:28 +02001934 abi_ulong sockfd;
bellard2f619692007-11-16 10:46:05 +00001935 abi_ulong msg;
1936 size_t len;
Ulrich Hecht98818182009-07-03 17:09:28 +02001937 abi_ulong flags;
bellard2f619692007-11-16 10:46:05 +00001938 abi_ulong addr;
1939 socklen_t addrlen;
1940
Ulrich Hecht98818182009-07-03 17:09:28 +02001941 if (get_user_ual(sockfd, vptr)
bellard2f619692007-11-16 10:46:05 +00001942 || get_user_ual(msg, vptr + n)
1943 || get_user_ual(len, vptr + 2 * n)
Ulrich Hecht98818182009-07-03 17:09:28 +02001944 || get_user_ual(flags, vptr + 3 * n)
bellard2f619692007-11-16 10:46:05 +00001945 || get_user_ual(addr, vptr + 4 * n)
Ulrich Hecht98818182009-07-03 17:09:28 +02001946 || get_user_ual(addrlen, vptr + 5 * n))
bellard2f619692007-11-16 10:46:05 +00001947 return -TARGET_EFAULT;
1948
pbrook1be9e1d2006-11-19 15:26:04 +00001949 ret = do_recvfrom(sockfd, msg, len, flags, addr, addrlen);
bellard31e31b82003-02-18 22:55:36 +00001950 }
1951 break;
1952 case SOCKOP_shutdown:
bellard7854b052003-03-29 17:22:23 +00001953 {
Ulrich Hecht98818182009-07-03 17:09:28 +02001954 abi_ulong sockfd, how;
bellard2f619692007-11-16 10:46:05 +00001955
Ulrich Hecht98818182009-07-03 17:09:28 +02001956 if (get_user_ual(sockfd, vptr)
1957 || get_user_ual(how, vptr + n))
bellard2f619692007-11-16 10:46:05 +00001958 return -TARGET_EFAULT;
bellard7854b052003-03-29 17:22:23 +00001959
1960 ret = get_errno(shutdown(sockfd, how));
1961 }
bellard31e31b82003-02-18 22:55:36 +00001962 break;
1963 case SOCKOP_sendmsg:
1964 case SOCKOP_recvmsg:
bellard1a9353d2003-03-16 20:28:50 +00001965 {
Ulrich Hecht98818182009-07-03 17:09:28 +02001966 abi_ulong fd;
blueswir1992f48a2007-10-14 16:27:31 +00001967 abi_ulong target_msg;
Ulrich Hecht98818182009-07-03 17:09:28 +02001968 abi_ulong flags;
bellard1a9353d2003-03-16 20:28:50 +00001969
Ulrich Hecht98818182009-07-03 17:09:28 +02001970 if (get_user_ual(fd, vptr)
bellard2f619692007-11-16 10:46:05 +00001971 || get_user_ual(target_msg, vptr + n)
Ulrich Hecht98818182009-07-03 17:09:28 +02001972 || get_user_ual(flags, vptr + 2 * n))
bellard2f619692007-11-16 10:46:05 +00001973 return -TARGET_EFAULT;
bellard3532fa72006-06-24 15:06:03 +00001974
ths5fafdf22007-09-16 21:08:06 +00001975 ret = do_sendrecvmsg(fd, target_msg, flags,
bellard3532fa72006-06-24 15:06:03 +00001976 (num == SOCKOP_sendmsg));
bellard1a9353d2003-03-16 20:28:50 +00001977 }
1978 break;
bellard31e31b82003-02-18 22:55:36 +00001979 case SOCKOP_setsockopt:
bellard7854b052003-03-29 17:22:23 +00001980 {
Ulrich Hecht98818182009-07-03 17:09:28 +02001981 abi_ulong sockfd;
1982 abi_ulong level;
1983 abi_ulong optname;
bellard2f619692007-11-16 10:46:05 +00001984 abi_ulong optval;
1985 socklen_t optlen;
1986
Ulrich Hecht98818182009-07-03 17:09:28 +02001987 if (get_user_ual(sockfd, vptr)
1988 || get_user_ual(level, vptr + n)
1989 || get_user_ual(optname, vptr + 2 * n)
bellard2f619692007-11-16 10:46:05 +00001990 || get_user_ual(optval, vptr + 3 * n)
Ulrich Hecht98818182009-07-03 17:09:28 +02001991 || get_user_ual(optlen, vptr + 4 * n))
bellard2f619692007-11-16 10:46:05 +00001992 return -TARGET_EFAULT;
bellard7854b052003-03-29 17:22:23 +00001993
1994 ret = do_setsockopt(sockfd, level, optname, optval, optlen);
1995 }
1996 break;
bellard31e31b82003-02-18 22:55:36 +00001997 case SOCKOP_getsockopt:
bellard7854b052003-03-29 17:22:23 +00001998 {
Ulrich Hecht98818182009-07-03 17:09:28 +02001999 abi_ulong sockfd;
2000 abi_ulong level;
2001 abi_ulong optname;
bellard2f619692007-11-16 10:46:05 +00002002 abi_ulong optval;
2003 socklen_t optlen;
bellard7854b052003-03-29 17:22:23 +00002004
Ulrich Hecht98818182009-07-03 17:09:28 +02002005 if (get_user_ual(sockfd, vptr)
2006 || get_user_ual(level, vptr + n)
2007 || get_user_ual(optname, vptr + 2 * n)
bellard2f619692007-11-16 10:46:05 +00002008 || get_user_ual(optval, vptr + 3 * n)
Ulrich Hecht98818182009-07-03 17:09:28 +02002009 || get_user_ual(optlen, vptr + 4 * n))
bellard2f619692007-11-16 10:46:05 +00002010 return -TARGET_EFAULT;
2011
2012 ret = do_getsockopt(sockfd, level, optname, optval, optlen);
bellard7854b052003-03-29 17:22:23 +00002013 }
2014 break;
bellard31e31b82003-02-18 22:55:36 +00002015 default:
2016 gemu_log("Unsupported socketcall: %d\n", num);
ths0da46a62007-10-20 20:23:07 +00002017 ret = -TARGET_ENOSYS;
bellard31e31b82003-02-18 22:55:36 +00002018 break;
2019 }
2020 return ret;
2021}
j_mayer32407102007-09-26 23:01:49 +00002022#endif
bellard31e31b82003-02-18 22:55:36 +00002023
bellard8853f862004-02-22 14:57:26 +00002024#define N_SHM_REGIONS 32
2025
2026static struct shm_region {
bellard5a4a8982007-11-11 17:39:18 +00002027 abi_ulong start;
2028 abi_ulong size;
bellard8853f862004-02-22 14:57:26 +00002029} shm_regions[N_SHM_REGIONS];
2030
ths3eb6b042007-06-03 14:26:27 +00002031struct target_ipc_perm
2032{
blueswir1992f48a2007-10-14 16:27:31 +00002033 abi_long __key;
2034 abi_ulong uid;
2035 abi_ulong gid;
2036 abi_ulong cuid;
2037 abi_ulong cgid;
ths3eb6b042007-06-03 14:26:27 +00002038 unsigned short int mode;
2039 unsigned short int __pad1;
2040 unsigned short int __seq;
2041 unsigned short int __pad2;
blueswir1992f48a2007-10-14 16:27:31 +00002042 abi_ulong __unused1;
2043 abi_ulong __unused2;
ths3eb6b042007-06-03 14:26:27 +00002044};
2045
2046struct target_semid_ds
2047{
2048 struct target_ipc_perm sem_perm;
blueswir1992f48a2007-10-14 16:27:31 +00002049 abi_ulong sem_otime;
2050 abi_ulong __unused1;
2051 abi_ulong sem_ctime;
2052 abi_ulong __unused2;
2053 abi_ulong sem_nsems;
2054 abi_ulong __unused3;
2055 abi_ulong __unused4;
ths3eb6b042007-06-03 14:26:27 +00002056};
2057
bellard579a97f2007-11-11 14:26:47 +00002058static inline abi_long target_to_host_ipc_perm(struct ipc_perm *host_ip,
2059 abi_ulong target_addr)
ths3eb6b042007-06-03 14:26:27 +00002060{
2061 struct target_ipc_perm *target_ip;
2062 struct target_semid_ds *target_sd;
2063
bellard579a97f2007-11-11 14:26:47 +00002064 if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
2065 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00002066 target_ip=&(target_sd->sem_perm);
2067 host_ip->__key = tswapl(target_ip->__key);
2068 host_ip->uid = tswapl(target_ip->uid);
2069 host_ip->gid = tswapl(target_ip->gid);
2070 host_ip->cuid = tswapl(target_ip->cuid);
2071 host_ip->cgid = tswapl(target_ip->cgid);
2072 host_ip->mode = tswapl(target_ip->mode);
2073 unlock_user_struct(target_sd, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00002074 return 0;
ths3eb6b042007-06-03 14:26:27 +00002075}
2076
bellard579a97f2007-11-11 14:26:47 +00002077static inline abi_long host_to_target_ipc_perm(abi_ulong target_addr,
2078 struct ipc_perm *host_ip)
ths3eb6b042007-06-03 14:26:27 +00002079{
2080 struct target_ipc_perm *target_ip;
2081 struct target_semid_ds *target_sd;
2082
bellard579a97f2007-11-11 14:26:47 +00002083 if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
2084 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00002085 target_ip = &(target_sd->sem_perm);
2086 target_ip->__key = tswapl(host_ip->__key);
2087 target_ip->uid = tswapl(host_ip->uid);
2088 target_ip->gid = tswapl(host_ip->gid);
2089 target_ip->cuid = tswapl(host_ip->cuid);
2090 target_ip->cgid = tswapl(host_ip->cgid);
2091 target_ip->mode = tswapl(host_ip->mode);
2092 unlock_user_struct(target_sd, target_addr, 1);
bellard579a97f2007-11-11 14:26:47 +00002093 return 0;
ths3eb6b042007-06-03 14:26:27 +00002094}
2095
bellard579a97f2007-11-11 14:26:47 +00002096static inline abi_long target_to_host_semid_ds(struct semid_ds *host_sd,
2097 abi_ulong target_addr)
ths3eb6b042007-06-03 14:26:27 +00002098{
2099 struct target_semid_ds *target_sd;
2100
bellard579a97f2007-11-11 14:26:47 +00002101 if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
2102 return -TARGET_EFAULT;
aurel32e5289082009-04-18 16:16:12 +00002103 if (target_to_host_ipc_perm(&(host_sd->sem_perm),target_addr))
2104 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00002105 host_sd->sem_nsems = tswapl(target_sd->sem_nsems);
2106 host_sd->sem_otime = tswapl(target_sd->sem_otime);
2107 host_sd->sem_ctime = tswapl(target_sd->sem_ctime);
2108 unlock_user_struct(target_sd, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00002109 return 0;
ths3eb6b042007-06-03 14:26:27 +00002110}
2111
bellard579a97f2007-11-11 14:26:47 +00002112static inline abi_long host_to_target_semid_ds(abi_ulong target_addr,
2113 struct semid_ds *host_sd)
ths3eb6b042007-06-03 14:26:27 +00002114{
2115 struct target_semid_ds *target_sd;
2116
bellard579a97f2007-11-11 14:26:47 +00002117 if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
2118 return -TARGET_EFAULT;
aurel32e5289082009-04-18 16:16:12 +00002119 if (host_to_target_ipc_perm(target_addr,&(host_sd->sem_perm)))
2120 return -TARGET_EFAULT;;
ths3eb6b042007-06-03 14:26:27 +00002121 target_sd->sem_nsems = tswapl(host_sd->sem_nsems);
2122 target_sd->sem_otime = tswapl(host_sd->sem_otime);
2123 target_sd->sem_ctime = tswapl(host_sd->sem_ctime);
2124 unlock_user_struct(target_sd, target_addr, 1);
bellard579a97f2007-11-11 14:26:47 +00002125 return 0;
ths3eb6b042007-06-03 14:26:27 +00002126}
2127
aurel32e5289082009-04-18 16:16:12 +00002128struct target_seminfo {
2129 int semmap;
2130 int semmni;
2131 int semmns;
2132 int semmnu;
2133 int semmsl;
2134 int semopm;
2135 int semume;
2136 int semusz;
2137 int semvmx;
2138 int semaem;
2139};
2140
2141static inline abi_long host_to_target_seminfo(abi_ulong target_addr,
2142 struct seminfo *host_seminfo)
2143{
2144 struct target_seminfo *target_seminfo;
2145 if (!lock_user_struct(VERIFY_WRITE, target_seminfo, target_addr, 0))
2146 return -TARGET_EFAULT;
2147 __put_user(host_seminfo->semmap, &target_seminfo->semmap);
2148 __put_user(host_seminfo->semmni, &target_seminfo->semmni);
2149 __put_user(host_seminfo->semmns, &target_seminfo->semmns);
2150 __put_user(host_seminfo->semmnu, &target_seminfo->semmnu);
2151 __put_user(host_seminfo->semmsl, &target_seminfo->semmsl);
2152 __put_user(host_seminfo->semopm, &target_seminfo->semopm);
2153 __put_user(host_seminfo->semume, &target_seminfo->semume);
2154 __put_user(host_seminfo->semusz, &target_seminfo->semusz);
2155 __put_user(host_seminfo->semvmx, &target_seminfo->semvmx);
2156 __put_user(host_seminfo->semaem, &target_seminfo->semaem);
2157 unlock_user_struct(target_seminfo, target_addr, 1);
2158 return 0;
2159}
2160
thsfa294812007-02-02 22:05:00 +00002161union semun {
2162 int val;
ths3eb6b042007-06-03 14:26:27 +00002163 struct semid_ds *buf;
thsfa294812007-02-02 22:05:00 +00002164 unsigned short *array;
aurel32e5289082009-04-18 16:16:12 +00002165 struct seminfo *__buf;
thsfa294812007-02-02 22:05:00 +00002166};
2167
ths3eb6b042007-06-03 14:26:27 +00002168union target_semun {
2169 int val;
aurel32e5289082009-04-18 16:16:12 +00002170 abi_ulong buf;
2171 abi_ulong array;
2172 abi_ulong __buf;
ths3eb6b042007-06-03 14:26:27 +00002173};
2174
aurel32e5289082009-04-18 16:16:12 +00002175static inline abi_long target_to_host_semarray(int semid, unsigned short **host_array,
2176 abi_ulong target_addr)
ths3eb6b042007-06-03 14:26:27 +00002177{
aurel32e5289082009-04-18 16:16:12 +00002178 int nsems;
2179 unsigned short *array;
2180 union semun semun;
2181 struct semid_ds semid_ds;
2182 int i, ret;
ths3eb6b042007-06-03 14:26:27 +00002183
aurel32e5289082009-04-18 16:16:12 +00002184 semun.buf = &semid_ds;
2185
2186 ret = semctl(semid, 0, IPC_STAT, semun);
2187 if (ret == -1)
2188 return get_errno(ret);
2189
2190 nsems = semid_ds.sem_nsems;
2191
2192 *host_array = malloc(nsems*sizeof(unsigned short));
2193 array = lock_user(VERIFY_READ, target_addr,
2194 nsems*sizeof(unsigned short), 1);
2195 if (!array)
2196 return -TARGET_EFAULT;
2197
2198 for(i=0; i<nsems; i++) {
2199 __get_user((*host_array)[i], &array[i]);
ths3eb6b042007-06-03 14:26:27 +00002200 }
aurel32e5289082009-04-18 16:16:12 +00002201 unlock_user(array, target_addr, 0);
2202
bellard579a97f2007-11-11 14:26:47 +00002203 return 0;
ths3eb6b042007-06-03 14:26:27 +00002204}
2205
aurel32e5289082009-04-18 16:16:12 +00002206static inline abi_long host_to_target_semarray(int semid, abi_ulong target_addr,
2207 unsigned short **host_array)
ths3eb6b042007-06-03 14:26:27 +00002208{
aurel32e5289082009-04-18 16:16:12 +00002209 int nsems;
2210 unsigned short *array;
2211 union semun semun;
2212 struct semid_ds semid_ds;
2213 int i, ret;
ths3eb6b042007-06-03 14:26:27 +00002214
aurel32e5289082009-04-18 16:16:12 +00002215 semun.buf = &semid_ds;
2216
2217 ret = semctl(semid, 0, IPC_STAT, semun);
2218 if (ret == -1)
2219 return get_errno(ret);
2220
2221 nsems = semid_ds.sem_nsems;
2222
2223 array = lock_user(VERIFY_WRITE, target_addr,
2224 nsems*sizeof(unsigned short), 0);
2225 if (!array)
2226 return -TARGET_EFAULT;
2227
2228 for(i=0; i<nsems; i++) {
2229 __put_user((*host_array)[i], &array[i]);
ths3eb6b042007-06-03 14:26:27 +00002230 }
aurel32e5289082009-04-18 16:16:12 +00002231 free(*host_array);
2232 unlock_user(array, target_addr, 1);
2233
bellard579a97f2007-11-11 14:26:47 +00002234 return 0;
ths3eb6b042007-06-03 14:26:27 +00002235}
2236
aurel32e5289082009-04-18 16:16:12 +00002237static inline abi_long do_semctl(int semid, int semnum, int cmd,
2238 union target_semun target_su)
ths3eb6b042007-06-03 14:26:27 +00002239{
2240 union semun arg;
2241 struct semid_ds dsarg;
vibi sreenivasan7b8118e2009-06-19 13:34:39 +05302242 unsigned short *array = NULL;
aurel32e5289082009-04-18 16:16:12 +00002243 struct seminfo seminfo;
2244 abi_long ret = -TARGET_EINVAL;
2245 abi_long err;
2246 cmd &= 0xff;
ths3eb6b042007-06-03 14:26:27 +00002247
2248 switch( cmd ) {
2249 case GETVAL:
ths3eb6b042007-06-03 14:26:27 +00002250 case SETVAL:
aurel32e5289082009-04-18 16:16:12 +00002251 arg.val = tswapl(target_su.val);
2252 ret = get_errno(semctl(semid, semnum, cmd, arg));
2253 target_su.val = tswapl(arg.val);
ths3eb6b042007-06-03 14:26:27 +00002254 break;
2255 case GETALL:
ths3eb6b042007-06-03 14:26:27 +00002256 case SETALL:
aurel32e5289082009-04-18 16:16:12 +00002257 err = target_to_host_semarray(semid, &array, target_su.array);
2258 if (err)
2259 return err;
2260 arg.array = array;
2261 ret = get_errno(semctl(semid, semnum, cmd, arg));
2262 err = host_to_target_semarray(semid, target_su.array, &array);
2263 if (err)
2264 return err;
ths3eb6b042007-06-03 14:26:27 +00002265 break;
2266 case IPC_STAT:
ths3eb6b042007-06-03 14:26:27 +00002267 case IPC_SET:
aurel32e5289082009-04-18 16:16:12 +00002268 case SEM_STAT:
2269 err = target_to_host_semid_ds(&dsarg, target_su.buf);
2270 if (err)
2271 return err;
2272 arg.buf = &dsarg;
2273 ret = get_errno(semctl(semid, semnum, cmd, arg));
2274 err = host_to_target_semid_ds(target_su.buf, &dsarg);
2275 if (err)
2276 return err;
ths3eb6b042007-06-03 14:26:27 +00002277 break;
aurel32e5289082009-04-18 16:16:12 +00002278 case IPC_INFO:
2279 case SEM_INFO:
2280 arg.__buf = &seminfo;
2281 ret = get_errno(semctl(semid, semnum, cmd, arg));
2282 err = host_to_target_seminfo(target_su.__buf, &seminfo);
2283 if (err)
2284 return err;
2285 break;
2286 case IPC_RMID:
2287 case GETPID:
2288 case GETNCNT:
2289 case GETZCNT:
2290 ret = get_errno(semctl(semid, semnum, cmd, NULL));
2291 break;
ths3eb6b042007-06-03 14:26:27 +00002292 }
2293
2294 return ret;
2295}
2296
aurel32e5289082009-04-18 16:16:12 +00002297struct target_sembuf {
2298 unsigned short sem_num;
2299 short sem_op;
2300 short sem_flg;
2301};
2302
2303static inline abi_long target_to_host_sembuf(struct sembuf *host_sembuf,
2304 abi_ulong target_addr,
2305 unsigned nsops)
2306{
2307 struct target_sembuf *target_sembuf;
2308 int i;
2309
2310 target_sembuf = lock_user(VERIFY_READ, target_addr,
2311 nsops*sizeof(struct target_sembuf), 1);
2312 if (!target_sembuf)
2313 return -TARGET_EFAULT;
2314
2315 for(i=0; i<nsops; i++) {
2316 __get_user(host_sembuf[i].sem_num, &target_sembuf[i].sem_num);
2317 __get_user(host_sembuf[i].sem_op, &target_sembuf[i].sem_op);
2318 __get_user(host_sembuf[i].sem_flg, &target_sembuf[i].sem_flg);
2319 }
2320
2321 unlock_user(target_sembuf, target_addr, 0);
2322
2323 return 0;
2324}
2325
2326static inline abi_long do_semop(int semid, abi_long ptr, unsigned nsops)
2327{
2328 struct sembuf sops[nsops];
2329
2330 if (target_to_host_sembuf(sops, ptr, nsops))
2331 return -TARGET_EFAULT;
2332
2333 return semop(semid, sops, nsops);
2334}
2335
ths1bc012f2007-06-03 14:27:49 +00002336struct target_msqid_ds
2337{
aurel321c54ff92008-10-13 21:08:44 +00002338 struct target_ipc_perm msg_perm;
2339 abi_ulong msg_stime;
2340#if TARGET_ABI_BITS == 32
2341 abi_ulong __unused1;
2342#endif
2343 abi_ulong msg_rtime;
2344#if TARGET_ABI_BITS == 32
2345 abi_ulong __unused2;
2346#endif
2347 abi_ulong msg_ctime;
2348#if TARGET_ABI_BITS == 32
2349 abi_ulong __unused3;
2350#endif
2351 abi_ulong __msg_cbytes;
2352 abi_ulong msg_qnum;
2353 abi_ulong msg_qbytes;
2354 abi_ulong msg_lspid;
2355 abi_ulong msg_lrpid;
2356 abi_ulong __unused4;
2357 abi_ulong __unused5;
ths1bc012f2007-06-03 14:27:49 +00002358};
2359
bellard579a97f2007-11-11 14:26:47 +00002360static inline abi_long target_to_host_msqid_ds(struct msqid_ds *host_md,
2361 abi_ulong target_addr)
ths1bc012f2007-06-03 14:27:49 +00002362{
2363 struct target_msqid_ds *target_md;
2364
bellard579a97f2007-11-11 14:26:47 +00002365 if (!lock_user_struct(VERIFY_READ, target_md, target_addr, 1))
2366 return -TARGET_EFAULT;
aurel321c54ff92008-10-13 21:08:44 +00002367 if (target_to_host_ipc_perm(&(host_md->msg_perm),target_addr))
2368 return -TARGET_EFAULT;
ths1bc012f2007-06-03 14:27:49 +00002369 host_md->msg_stime = tswapl(target_md->msg_stime);
2370 host_md->msg_rtime = tswapl(target_md->msg_rtime);
2371 host_md->msg_ctime = tswapl(target_md->msg_ctime);
2372 host_md->__msg_cbytes = tswapl(target_md->__msg_cbytes);
2373 host_md->msg_qnum = tswapl(target_md->msg_qnum);
2374 host_md->msg_qbytes = tswapl(target_md->msg_qbytes);
2375 host_md->msg_lspid = tswapl(target_md->msg_lspid);
2376 host_md->msg_lrpid = tswapl(target_md->msg_lrpid);
2377 unlock_user_struct(target_md, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00002378 return 0;
ths1bc012f2007-06-03 14:27:49 +00002379}
2380
bellard579a97f2007-11-11 14:26:47 +00002381static inline abi_long host_to_target_msqid_ds(abi_ulong target_addr,
2382 struct msqid_ds *host_md)
ths1bc012f2007-06-03 14:27:49 +00002383{
2384 struct target_msqid_ds *target_md;
2385
bellard579a97f2007-11-11 14:26:47 +00002386 if (!lock_user_struct(VERIFY_WRITE, target_md, target_addr, 0))
2387 return -TARGET_EFAULT;
aurel321c54ff92008-10-13 21:08:44 +00002388 if (host_to_target_ipc_perm(target_addr,&(host_md->msg_perm)))
2389 return -TARGET_EFAULT;
ths1bc012f2007-06-03 14:27:49 +00002390 target_md->msg_stime = tswapl(host_md->msg_stime);
2391 target_md->msg_rtime = tswapl(host_md->msg_rtime);
2392 target_md->msg_ctime = tswapl(host_md->msg_ctime);
2393 target_md->__msg_cbytes = tswapl(host_md->__msg_cbytes);
2394 target_md->msg_qnum = tswapl(host_md->msg_qnum);
2395 target_md->msg_qbytes = tswapl(host_md->msg_qbytes);
2396 target_md->msg_lspid = tswapl(host_md->msg_lspid);
2397 target_md->msg_lrpid = tswapl(host_md->msg_lrpid);
2398 unlock_user_struct(target_md, target_addr, 1);
bellard579a97f2007-11-11 14:26:47 +00002399 return 0;
ths1bc012f2007-06-03 14:27:49 +00002400}
2401
aurel321c54ff92008-10-13 21:08:44 +00002402struct target_msginfo {
2403 int msgpool;
2404 int msgmap;
2405 int msgmax;
2406 int msgmnb;
2407 int msgmni;
2408 int msgssz;
2409 int msgtql;
2410 unsigned short int msgseg;
2411};
2412
2413static inline abi_long host_to_target_msginfo(abi_ulong target_addr,
2414 struct msginfo *host_msginfo)
2415{
2416 struct target_msginfo *target_msginfo;
2417 if (!lock_user_struct(VERIFY_WRITE, target_msginfo, target_addr, 0))
2418 return -TARGET_EFAULT;
2419 __put_user(host_msginfo->msgpool, &target_msginfo->msgpool);
2420 __put_user(host_msginfo->msgmap, &target_msginfo->msgmap);
2421 __put_user(host_msginfo->msgmax, &target_msginfo->msgmax);
2422 __put_user(host_msginfo->msgmnb, &target_msginfo->msgmnb);
2423 __put_user(host_msginfo->msgmni, &target_msginfo->msgmni);
2424 __put_user(host_msginfo->msgssz, &target_msginfo->msgssz);
2425 __put_user(host_msginfo->msgtql, &target_msginfo->msgtql);
2426 __put_user(host_msginfo->msgseg, &target_msginfo->msgseg);
2427 unlock_user_struct(target_msginfo, target_addr, 1);
aurel3200b229a2008-10-24 13:12:52 +00002428 return 0;
aurel321c54ff92008-10-13 21:08:44 +00002429}
2430
2431static inline abi_long do_msgctl(int msgid, int cmd, abi_long ptr)
ths1bc012f2007-06-03 14:27:49 +00002432{
2433 struct msqid_ds dsarg;
aurel321c54ff92008-10-13 21:08:44 +00002434 struct msginfo msginfo;
2435 abi_long ret = -TARGET_EINVAL;
2436
2437 cmd &= 0xff;
2438
2439 switch (cmd) {
ths1bc012f2007-06-03 14:27:49 +00002440 case IPC_STAT:
2441 case IPC_SET:
aurel321c54ff92008-10-13 21:08:44 +00002442 case MSG_STAT:
2443 if (target_to_host_msqid_ds(&dsarg,ptr))
2444 return -TARGET_EFAULT;
2445 ret = get_errno(msgctl(msgid, cmd, &dsarg));
2446 if (host_to_target_msqid_ds(ptr,&dsarg))
2447 return -TARGET_EFAULT;
2448 break;
2449 case IPC_RMID:
2450 ret = get_errno(msgctl(msgid, cmd, NULL));
2451 break;
2452 case IPC_INFO:
2453 case MSG_INFO:
2454 ret = get_errno(msgctl(msgid, cmd, (struct msqid_ds *)&msginfo));
2455 if (host_to_target_msginfo(ptr, &msginfo))
2456 return -TARGET_EFAULT;
2457 break;
ths1bc012f2007-06-03 14:27:49 +00002458 }
aurel321c54ff92008-10-13 21:08:44 +00002459
ths1bc012f2007-06-03 14:27:49 +00002460 return ret;
2461}
2462
2463struct target_msgbuf {
aurel321c54ff92008-10-13 21:08:44 +00002464 abi_long mtype;
2465 char mtext[1];
ths1bc012f2007-06-03 14:27:49 +00002466};
2467
blueswir1992f48a2007-10-14 16:27:31 +00002468static inline abi_long do_msgsnd(int msqid, abi_long msgp,
2469 unsigned int msgsz, int msgflg)
ths1bc012f2007-06-03 14:27:49 +00002470{
2471 struct target_msgbuf *target_mb;
2472 struct msgbuf *host_mb;
blueswir1992f48a2007-10-14 16:27:31 +00002473 abi_long ret = 0;
ths1bc012f2007-06-03 14:27:49 +00002474
bellard579a97f2007-11-11 14:26:47 +00002475 if (!lock_user_struct(VERIFY_READ, target_mb, msgp, 0))
2476 return -TARGET_EFAULT;
ths1bc012f2007-06-03 14:27:49 +00002477 host_mb = malloc(msgsz+sizeof(long));
aurel321c54ff92008-10-13 21:08:44 +00002478 host_mb->mtype = (abi_long) tswapl(target_mb->mtype);
2479 memcpy(host_mb->mtext, target_mb->mtext, msgsz);
ths1bc012f2007-06-03 14:27:49 +00002480 ret = get_errno(msgsnd(msqid, host_mb, msgsz, msgflg));
2481 free(host_mb);
2482 unlock_user_struct(target_mb, msgp, 0);
2483
2484 return ret;
2485}
2486
blueswir1992f48a2007-10-14 16:27:31 +00002487static inline abi_long do_msgrcv(int msqid, abi_long msgp,
aurel321c54ff92008-10-13 21:08:44 +00002488 unsigned int msgsz, abi_long msgtyp,
blueswir1992f48a2007-10-14 16:27:31 +00002489 int msgflg)
ths1bc012f2007-06-03 14:27:49 +00002490{
2491 struct target_msgbuf *target_mb;
bellard579a97f2007-11-11 14:26:47 +00002492 char *target_mtext;
ths1bc012f2007-06-03 14:27:49 +00002493 struct msgbuf *host_mb;
blueswir1992f48a2007-10-14 16:27:31 +00002494 abi_long ret = 0;
ths1bc012f2007-06-03 14:27:49 +00002495
bellard579a97f2007-11-11 14:26:47 +00002496 if (!lock_user_struct(VERIFY_WRITE, target_mb, msgp, 0))
2497 return -TARGET_EFAULT;
aurel321c54ff92008-10-13 21:08:44 +00002498
ths1bc012f2007-06-03 14:27:49 +00002499 host_mb = malloc(msgsz+sizeof(long));
aurel321c54ff92008-10-13 21:08:44 +00002500 ret = get_errno(msgrcv(msqid, host_mb, msgsz, tswapl(msgtyp), msgflg));
2501
bellard579a97f2007-11-11 14:26:47 +00002502 if (ret > 0) {
2503 abi_ulong target_mtext_addr = msgp + sizeof(abi_ulong);
2504 target_mtext = lock_user(VERIFY_WRITE, target_mtext_addr, ret, 0);
2505 if (!target_mtext) {
2506 ret = -TARGET_EFAULT;
2507 goto end;
2508 }
aurel321c54ff92008-10-13 21:08:44 +00002509 memcpy(target_mb->mtext, host_mb->mtext, ret);
bellard579a97f2007-11-11 14:26:47 +00002510 unlock_user(target_mtext, target_mtext_addr, ret);
2511 }
aurel321c54ff92008-10-13 21:08:44 +00002512
ths1bc012f2007-06-03 14:27:49 +00002513 target_mb->mtype = tswapl(host_mb->mtype);
2514 free(host_mb);
ths1bc012f2007-06-03 14:27:49 +00002515
bellard579a97f2007-11-11 14:26:47 +00002516end:
2517 if (target_mb)
2518 unlock_user_struct(target_mb, msgp, 1);
ths1bc012f2007-06-03 14:27:49 +00002519 return ret;
2520}
2521
Riku Voipio88a8c982009-04-03 10:42:00 +03002522struct target_shmid_ds
2523{
2524 struct target_ipc_perm shm_perm;
2525 abi_ulong shm_segsz;
2526 abi_ulong shm_atime;
2527#if TARGET_ABI_BITS == 32
2528 abi_ulong __unused1;
2529#endif
2530 abi_ulong shm_dtime;
2531#if TARGET_ABI_BITS == 32
2532 abi_ulong __unused2;
2533#endif
2534 abi_ulong shm_ctime;
2535#if TARGET_ABI_BITS == 32
2536 abi_ulong __unused3;
2537#endif
2538 int shm_cpid;
2539 int shm_lpid;
2540 abi_ulong shm_nattch;
2541 unsigned long int __unused4;
2542 unsigned long int __unused5;
2543};
2544
2545static inline abi_long target_to_host_shmid_ds(struct shmid_ds *host_sd,
2546 abi_ulong target_addr)
2547{
2548 struct target_shmid_ds *target_sd;
2549
2550 if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
2551 return -TARGET_EFAULT;
2552 if (target_to_host_ipc_perm(&(host_sd->shm_perm), target_addr))
2553 return -TARGET_EFAULT;
2554 __get_user(host_sd->shm_segsz, &target_sd->shm_segsz);
2555 __get_user(host_sd->shm_atime, &target_sd->shm_atime);
2556 __get_user(host_sd->shm_dtime, &target_sd->shm_dtime);
2557 __get_user(host_sd->shm_ctime, &target_sd->shm_ctime);
2558 __get_user(host_sd->shm_cpid, &target_sd->shm_cpid);
2559 __get_user(host_sd->shm_lpid, &target_sd->shm_lpid);
2560 __get_user(host_sd->shm_nattch, &target_sd->shm_nattch);
2561 unlock_user_struct(target_sd, target_addr, 0);
2562 return 0;
2563}
2564
2565static inline abi_long host_to_target_shmid_ds(abi_ulong target_addr,
2566 struct shmid_ds *host_sd)
2567{
2568 struct target_shmid_ds *target_sd;
2569
2570 if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
2571 return -TARGET_EFAULT;
2572 if (host_to_target_ipc_perm(target_addr, &(host_sd->shm_perm)))
2573 return -TARGET_EFAULT;
2574 __put_user(host_sd->shm_segsz, &target_sd->shm_segsz);
2575 __put_user(host_sd->shm_atime, &target_sd->shm_atime);
2576 __put_user(host_sd->shm_dtime, &target_sd->shm_dtime);
2577 __put_user(host_sd->shm_ctime, &target_sd->shm_ctime);
2578 __put_user(host_sd->shm_cpid, &target_sd->shm_cpid);
2579 __put_user(host_sd->shm_lpid, &target_sd->shm_lpid);
2580 __put_user(host_sd->shm_nattch, &target_sd->shm_nattch);
2581 unlock_user_struct(target_sd, target_addr, 1);
2582 return 0;
2583}
2584
2585struct target_shminfo {
2586 abi_ulong shmmax;
2587 abi_ulong shmmin;
2588 abi_ulong shmmni;
2589 abi_ulong shmseg;
2590 abi_ulong shmall;
2591};
2592
2593static inline abi_long host_to_target_shminfo(abi_ulong target_addr,
2594 struct shminfo *host_shminfo)
2595{
2596 struct target_shminfo *target_shminfo;
2597 if (!lock_user_struct(VERIFY_WRITE, target_shminfo, target_addr, 0))
2598 return -TARGET_EFAULT;
2599 __put_user(host_shminfo->shmmax, &target_shminfo->shmmax);
2600 __put_user(host_shminfo->shmmin, &target_shminfo->shmmin);
2601 __put_user(host_shminfo->shmmni, &target_shminfo->shmmni);
2602 __put_user(host_shminfo->shmseg, &target_shminfo->shmseg);
2603 __put_user(host_shminfo->shmall, &target_shminfo->shmall);
2604 unlock_user_struct(target_shminfo, target_addr, 1);
2605 return 0;
2606}
2607
2608struct target_shm_info {
2609 int used_ids;
2610 abi_ulong shm_tot;
2611 abi_ulong shm_rss;
2612 abi_ulong shm_swp;
2613 abi_ulong swap_attempts;
2614 abi_ulong swap_successes;
2615};
2616
2617static inline abi_long host_to_target_shm_info(abi_ulong target_addr,
2618 struct shm_info *host_shm_info)
2619{
2620 struct target_shm_info *target_shm_info;
2621 if (!lock_user_struct(VERIFY_WRITE, target_shm_info, target_addr, 0))
2622 return -TARGET_EFAULT;
2623 __put_user(host_shm_info->used_ids, &target_shm_info->used_ids);
2624 __put_user(host_shm_info->shm_tot, &target_shm_info->shm_tot);
2625 __put_user(host_shm_info->shm_rss, &target_shm_info->shm_rss);
2626 __put_user(host_shm_info->shm_swp, &target_shm_info->shm_swp);
2627 __put_user(host_shm_info->swap_attempts, &target_shm_info->swap_attempts);
2628 __put_user(host_shm_info->swap_successes, &target_shm_info->swap_successes);
2629 unlock_user_struct(target_shm_info, target_addr, 1);
2630 return 0;
2631}
2632
2633static inline abi_long do_shmctl(int shmid, int cmd, abi_long buf)
2634{
2635 struct shmid_ds dsarg;
2636 struct shminfo shminfo;
2637 struct shm_info shm_info;
2638 abi_long ret = -TARGET_EINVAL;
2639
2640 cmd &= 0xff;
2641
2642 switch(cmd) {
2643 case IPC_STAT:
2644 case IPC_SET:
2645 case SHM_STAT:
2646 if (target_to_host_shmid_ds(&dsarg, buf))
2647 return -TARGET_EFAULT;
2648 ret = get_errno(shmctl(shmid, cmd, &dsarg));
2649 if (host_to_target_shmid_ds(buf, &dsarg))
2650 return -TARGET_EFAULT;
2651 break;
2652 case IPC_INFO:
2653 ret = get_errno(shmctl(shmid, cmd, (struct shmid_ds *)&shminfo));
2654 if (host_to_target_shminfo(buf, &shminfo))
2655 return -TARGET_EFAULT;
2656 break;
2657 case SHM_INFO:
2658 ret = get_errno(shmctl(shmid, cmd, (struct shmid_ds *)&shm_info));
2659 if (host_to_target_shm_info(buf, &shm_info))
2660 return -TARGET_EFAULT;
2661 break;
2662 case IPC_RMID:
2663 case SHM_LOCK:
2664 case SHM_UNLOCK:
2665 ret = get_errno(shmctl(shmid, cmd, NULL));
2666 break;
2667 }
2668
2669 return ret;
2670}
2671
2672static inline abi_ulong do_shmat(int shmid, abi_ulong shmaddr, int shmflg)
2673{
2674 abi_long raddr;
2675 void *host_raddr;
2676 struct shmid_ds shm_info;
2677 int i,ret;
2678
2679 /* find out the length of the shared memory segment */
2680 ret = get_errno(shmctl(shmid, IPC_STAT, &shm_info));
2681 if (is_error(ret)) {
2682 /* can't get length, bail out */
2683 return ret;
2684 }
2685
2686 mmap_lock();
2687
2688 if (shmaddr)
2689 host_raddr = shmat(shmid, (void *)g2h(shmaddr), shmflg);
2690 else {
2691 abi_ulong mmap_start;
2692
2693 mmap_start = mmap_find_vma(0, shm_info.shm_segsz);
2694
2695 if (mmap_start == -1) {
2696 errno = ENOMEM;
2697 host_raddr = (void *)-1;
2698 } else
2699 host_raddr = shmat(shmid, g2h(mmap_start), shmflg | SHM_REMAP);
2700 }
2701
2702 if (host_raddr == (void *)-1) {
2703 mmap_unlock();
2704 return get_errno((long)host_raddr);
2705 }
2706 raddr=h2g((unsigned long)host_raddr);
2707
2708 page_set_flags(raddr, raddr + shm_info.shm_segsz,
2709 PAGE_VALID | PAGE_READ |
2710 ((shmflg & SHM_RDONLY)? 0 : PAGE_WRITE));
2711
2712 for (i = 0; i < N_SHM_REGIONS; i++) {
2713 if (shm_regions[i].start == 0) {
2714 shm_regions[i].start = raddr;
2715 shm_regions[i].size = shm_info.shm_segsz;
2716 break;
2717 }
2718 }
2719
2720 mmap_unlock();
2721 return raddr;
2722
2723}
2724
2725static inline abi_long do_shmdt(abi_ulong shmaddr)
2726{
2727 int i;
2728
2729 for (i = 0; i < N_SHM_REGIONS; ++i) {
2730 if (shm_regions[i].start == shmaddr) {
2731 shm_regions[i].start = 0;
2732 page_set_flags(shmaddr, shm_regions[i].size, 0);
2733 break;
2734 }
2735 }
2736
2737 return get_errno(shmdt(g2h(shmaddr)));
2738}
2739
aurel321c54ff92008-10-13 21:08:44 +00002740#ifdef TARGET_NR_ipc
pbrook53a59602006-03-25 19:31:22 +00002741/* ??? This only works with linear mappings. */
ths0da46a62007-10-20 20:23:07 +00002742/* do_ipc() must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00002743static abi_long do_ipc(unsigned int call, int first,
2744 int second, int third,
2745 abi_long ptr, abi_long fifth)
bellard8853f862004-02-22 14:57:26 +00002746{
2747 int version;
blueswir1992f48a2007-10-14 16:27:31 +00002748 abi_long ret = 0;
bellard8853f862004-02-22 14:57:26 +00002749
2750 version = call >> 16;
2751 call &= 0xffff;
2752
2753 switch (call) {
thsfa294812007-02-02 22:05:00 +00002754 case IPCOP_semop:
aurel32e5289082009-04-18 16:16:12 +00002755 ret = do_semop(first, ptr, second);
thsfa294812007-02-02 22:05:00 +00002756 break;
2757
2758 case IPCOP_semget:
2759 ret = get_errno(semget(first, second, third));
2760 break;
2761
2762 case IPCOP_semctl:
aurel32e5289082009-04-18 16:16:12 +00002763 ret = do_semctl(first, second, third, (union target_semun)(abi_ulong) ptr);
thsfa294812007-02-02 22:05:00 +00002764 break;
thsd96372e2007-02-02 22:05:44 +00002765
aurel321c54ff92008-10-13 21:08:44 +00002766 case IPCOP_msgget:
2767 ret = get_errno(msgget(first, second));
2768 break;
thsd96372e2007-02-02 22:05:44 +00002769
aurel321c54ff92008-10-13 21:08:44 +00002770 case IPCOP_msgsnd:
2771 ret = do_msgsnd(first, ptr, second, third);
2772 break;
thsd96372e2007-02-02 22:05:44 +00002773
aurel321c54ff92008-10-13 21:08:44 +00002774 case IPCOP_msgctl:
2775 ret = do_msgctl(first, second, ptr);
2776 break;
thsd96372e2007-02-02 22:05:44 +00002777
aurel321c54ff92008-10-13 21:08:44 +00002778 case IPCOP_msgrcv:
2779 switch (version) {
2780 case 0:
2781 {
2782 struct target_ipc_kludge {
2783 abi_long msgp;
2784 abi_long msgtyp;
2785 } *tmp;
thsd96372e2007-02-02 22:05:44 +00002786
aurel321c54ff92008-10-13 21:08:44 +00002787 if (!lock_user_struct(VERIFY_READ, tmp, ptr, 1)) {
2788 ret = -TARGET_EFAULT;
2789 break;
ths1bc012f2007-06-03 14:27:49 +00002790 }
aurel321c54ff92008-10-13 21:08:44 +00002791
2792 ret = do_msgrcv(first, tmp->msgp, second, tmp->msgtyp, third);
2793
2794 unlock_user_struct(tmp, ptr, 0);
2795 break;
2796 }
2797 default:
2798 ret = do_msgrcv(first, ptr, second, fifth, third);
2799 }
2800 break;
thsd96372e2007-02-02 22:05:44 +00002801
bellard8853f862004-02-22 14:57:26 +00002802 case IPCOP_shmat:
Riku Voipio88a8c982009-04-03 10:42:00 +03002803 switch (version) {
2804 default:
bellard5a4a8982007-11-11 17:39:18 +00002805 {
2806 abi_ulong raddr;
Riku Voipio88a8c982009-04-03 10:42:00 +03002807 raddr = do_shmat(first, ptr, second);
2808 if (is_error(raddr))
2809 return get_errno(raddr);
bellard2f619692007-11-16 10:46:05 +00002810 if (put_user_ual(raddr, third))
bellard5a4a8982007-11-11 17:39:18 +00002811 return -TARGET_EFAULT;
Riku Voipio88a8c982009-04-03 10:42:00 +03002812 break;
2813 }
2814 case 1:
2815 ret = -TARGET_EINVAL;
2816 break;
bellard5a4a8982007-11-11 17:39:18 +00002817 }
bellard8853f862004-02-22 14:57:26 +00002818 break;
2819 case IPCOP_shmdt:
Riku Voipio88a8c982009-04-03 10:42:00 +03002820 ret = do_shmdt(ptr);
bellard8853f862004-02-22 14:57:26 +00002821 break;
2822
2823 case IPCOP_shmget:
2824 /* IPC_* flag values are the same on all linux platforms */
2825 ret = get_errno(shmget(first, second, third));
2826 break;
2827
2828 /* IPC_* and SHM_* command values are the same on all linux platforms */
2829 case IPCOP_shmctl:
Riku Voipio88a8c982009-04-03 10:42:00 +03002830 ret = do_shmctl(first, second, third);
bellard8853f862004-02-22 14:57:26 +00002831 break;
2832 default:
j_mayer32407102007-09-26 23:01:49 +00002833 gemu_log("Unsupported ipc call: %d (version %d)\n", call, version);
ths0da46a62007-10-20 20:23:07 +00002834 ret = -TARGET_ENOSYS;
bellard8853f862004-02-22 14:57:26 +00002835 break;
2836 }
2837 return ret;
2838}
j_mayer32407102007-09-26 23:01:49 +00002839#endif
bellard8853f862004-02-22 14:57:26 +00002840
bellard31e31b82003-02-18 22:55:36 +00002841/* kernel structure types definitions */
2842#define IFNAMSIZ 16
2843
Blue Swirl001faf32009-05-13 17:53:17 +00002844#define STRUCT(name, ...) STRUCT_ ## name,
bellard31e31b82003-02-18 22:55:36 +00002845#define STRUCT_SPECIAL(name) STRUCT_ ## name,
2846enum {
2847#include "syscall_types.h"
2848};
2849#undef STRUCT
2850#undef STRUCT_SPECIAL
2851
Blue Swirl001faf32009-05-13 17:53:17 +00002852#define STRUCT(name, ...) static const argtype struct_ ## name ## _def[] = { __VA_ARGS__, TYPE_NULL };
bellard31e31b82003-02-18 22:55:36 +00002853#define STRUCT_SPECIAL(name)
2854#include "syscall_types.h"
2855#undef STRUCT
2856#undef STRUCT_SPECIAL
2857
2858typedef struct IOCTLEntry {
bellard2ab83ea2003-06-15 19:56:46 +00002859 unsigned int target_cmd;
2860 unsigned int host_cmd;
bellard31e31b82003-02-18 22:55:36 +00002861 const char *name;
2862 int access;
bellard1a9353d2003-03-16 20:28:50 +00002863 const argtype arg_type[5];
bellard31e31b82003-02-18 22:55:36 +00002864} IOCTLEntry;
2865
2866#define IOC_R 0x0001
2867#define IOC_W 0x0002
2868#define IOC_RW (IOC_R | IOC_W)
2869
2870#define MAX_STRUCT_SIZE 4096
2871
blueswir19f106a72008-10-05 10:52:52 +00002872static IOCTLEntry ioctl_entries[] = {
Blue Swirl001faf32009-05-13 17:53:17 +00002873#define IOCTL(cmd, access, ...) \
2874 { TARGET_ ## cmd, cmd, #cmd, access, { __VA_ARGS__ } },
bellard31e31b82003-02-18 22:55:36 +00002875#include "ioctls.h"
2876 { 0, 0, },
2877};
2878
pbrook53a59602006-03-25 19:31:22 +00002879/* ??? Implement proper locking for ioctls. */
ths0da46a62007-10-20 20:23:07 +00002880/* do_ioctl() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00002881static abi_long do_ioctl(int fd, abi_long cmd, abi_long arg)
bellard31e31b82003-02-18 22:55:36 +00002882{
2883 const IOCTLEntry *ie;
2884 const argtype *arg_type;
blueswir1992f48a2007-10-14 16:27:31 +00002885 abi_long ret;
bellard31e31b82003-02-18 22:55:36 +00002886 uint8_t buf_temp[MAX_STRUCT_SIZE];
pbrook53a59602006-03-25 19:31:22 +00002887 int target_size;
2888 void *argptr;
bellard31e31b82003-02-18 22:55:36 +00002889
2890 ie = ioctl_entries;
2891 for(;;) {
2892 if (ie->target_cmd == 0) {
j_mayer32407102007-09-26 23:01:49 +00002893 gemu_log("Unsupported ioctl: cmd=0x%04lx\n", (long)cmd);
ths0da46a62007-10-20 20:23:07 +00002894 return -TARGET_ENOSYS;
bellard31e31b82003-02-18 22:55:36 +00002895 }
2896 if (ie->target_cmd == cmd)
2897 break;
2898 ie++;
2899 }
2900 arg_type = ie->arg_type;
bellard9de5e442003-03-23 16:49:39 +00002901#if defined(DEBUG)
j_mayer32407102007-09-26 23:01:49 +00002902 gemu_log("ioctl: cmd=0x%04lx (%s)\n", (long)cmd, ie->name);
bellard72f03902003-02-18 23:33:18 +00002903#endif
bellard31e31b82003-02-18 22:55:36 +00002904 switch(arg_type[0]) {
2905 case TYPE_NULL:
2906 /* no argument */
2907 ret = get_errno(ioctl(fd, ie->host_cmd));
2908 break;
2909 case TYPE_PTRVOID:
2910 case TYPE_INT:
2911 /* int argment */
2912 ret = get_errno(ioctl(fd, ie->host_cmd, arg));
2913 break;
2914 case TYPE_PTR:
2915 arg_type++;
pbrook53a59602006-03-25 19:31:22 +00002916 target_size = thunk_type_size(arg_type, 0);
bellard31e31b82003-02-18 22:55:36 +00002917 switch(ie->access) {
2918 case IOC_R:
2919 ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
2920 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00002921 argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
2922 if (!argptr)
2923 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00002924 thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
2925 unlock_user(argptr, arg, target_size);
bellard31e31b82003-02-18 22:55:36 +00002926 }
2927 break;
2928 case IOC_W:
bellard579a97f2007-11-11 14:26:47 +00002929 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
2930 if (!argptr)
2931 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00002932 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
2933 unlock_user(argptr, arg, 0);
bellard31e31b82003-02-18 22:55:36 +00002934 ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
2935 break;
2936 default:
2937 case IOC_RW:
bellard579a97f2007-11-11 14:26:47 +00002938 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
2939 if (!argptr)
2940 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00002941 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
2942 unlock_user(argptr, arg, 0);
bellard31e31b82003-02-18 22:55:36 +00002943 ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
2944 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00002945 argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
2946 if (!argptr)
2947 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00002948 thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
2949 unlock_user(argptr, arg, target_size);
bellard31e31b82003-02-18 22:55:36 +00002950 }
2951 break;
2952 }
2953 break;
2954 default:
j_mayer32407102007-09-26 23:01:49 +00002955 gemu_log("Unsupported ioctl type: cmd=0x%04lx type=%d\n",
2956 (long)cmd, arg_type[0]);
ths0da46a62007-10-20 20:23:07 +00002957 ret = -TARGET_ENOSYS;
bellard31e31b82003-02-18 22:55:36 +00002958 break;
2959 }
2960 return ret;
2961}
2962
blueswir1b39bc502008-10-05 10:51:10 +00002963static const bitmask_transtbl iflag_tbl[] = {
bellard31e31b82003-02-18 22:55:36 +00002964 { TARGET_IGNBRK, TARGET_IGNBRK, IGNBRK, IGNBRK },
2965 { TARGET_BRKINT, TARGET_BRKINT, BRKINT, BRKINT },
2966 { TARGET_IGNPAR, TARGET_IGNPAR, IGNPAR, IGNPAR },
2967 { TARGET_PARMRK, TARGET_PARMRK, PARMRK, PARMRK },
2968 { TARGET_INPCK, TARGET_INPCK, INPCK, INPCK },
2969 { TARGET_ISTRIP, TARGET_ISTRIP, ISTRIP, ISTRIP },
2970 { TARGET_INLCR, TARGET_INLCR, INLCR, INLCR },
2971 { TARGET_IGNCR, TARGET_IGNCR, IGNCR, IGNCR },
2972 { TARGET_ICRNL, TARGET_ICRNL, ICRNL, ICRNL },
2973 { TARGET_IUCLC, TARGET_IUCLC, IUCLC, IUCLC },
2974 { TARGET_IXON, TARGET_IXON, IXON, IXON },
2975 { TARGET_IXANY, TARGET_IXANY, IXANY, IXANY },
2976 { TARGET_IXOFF, TARGET_IXOFF, IXOFF, IXOFF },
2977 { TARGET_IMAXBEL, TARGET_IMAXBEL, IMAXBEL, IMAXBEL },
2978 { 0, 0, 0, 0 }
2979};
2980
blueswir1b39bc502008-10-05 10:51:10 +00002981static const bitmask_transtbl oflag_tbl[] = {
bellard31e31b82003-02-18 22:55:36 +00002982 { TARGET_OPOST, TARGET_OPOST, OPOST, OPOST },
2983 { TARGET_OLCUC, TARGET_OLCUC, OLCUC, OLCUC },
2984 { TARGET_ONLCR, TARGET_ONLCR, ONLCR, ONLCR },
2985 { TARGET_OCRNL, TARGET_OCRNL, OCRNL, OCRNL },
2986 { TARGET_ONOCR, TARGET_ONOCR, ONOCR, ONOCR },
2987 { TARGET_ONLRET, TARGET_ONLRET, ONLRET, ONLRET },
2988 { TARGET_OFILL, TARGET_OFILL, OFILL, OFILL },
2989 { TARGET_OFDEL, TARGET_OFDEL, OFDEL, OFDEL },
2990 { TARGET_NLDLY, TARGET_NL0, NLDLY, NL0 },
2991 { TARGET_NLDLY, TARGET_NL1, NLDLY, NL1 },
2992 { TARGET_CRDLY, TARGET_CR0, CRDLY, CR0 },
2993 { TARGET_CRDLY, TARGET_CR1, CRDLY, CR1 },
2994 { TARGET_CRDLY, TARGET_CR2, CRDLY, CR2 },
2995 { TARGET_CRDLY, TARGET_CR3, CRDLY, CR3 },
2996 { TARGET_TABDLY, TARGET_TAB0, TABDLY, TAB0 },
2997 { TARGET_TABDLY, TARGET_TAB1, TABDLY, TAB1 },
2998 { TARGET_TABDLY, TARGET_TAB2, TABDLY, TAB2 },
2999 { TARGET_TABDLY, TARGET_TAB3, TABDLY, TAB3 },
3000 { TARGET_BSDLY, TARGET_BS0, BSDLY, BS0 },
3001 { TARGET_BSDLY, TARGET_BS1, BSDLY, BS1 },
3002 { TARGET_VTDLY, TARGET_VT0, VTDLY, VT0 },
3003 { TARGET_VTDLY, TARGET_VT1, VTDLY, VT1 },
3004 { TARGET_FFDLY, TARGET_FF0, FFDLY, FF0 },
3005 { TARGET_FFDLY, TARGET_FF1, FFDLY, FF1 },
3006 { 0, 0, 0, 0 }
3007};
3008
blueswir1b39bc502008-10-05 10:51:10 +00003009static const bitmask_transtbl cflag_tbl[] = {
bellard31e31b82003-02-18 22:55:36 +00003010 { TARGET_CBAUD, TARGET_B0, CBAUD, B0 },
3011 { TARGET_CBAUD, TARGET_B50, CBAUD, B50 },
3012 { TARGET_CBAUD, TARGET_B75, CBAUD, B75 },
3013 { TARGET_CBAUD, TARGET_B110, CBAUD, B110 },
3014 { TARGET_CBAUD, TARGET_B134, CBAUD, B134 },
3015 { TARGET_CBAUD, TARGET_B150, CBAUD, B150 },
3016 { TARGET_CBAUD, TARGET_B200, CBAUD, B200 },
3017 { TARGET_CBAUD, TARGET_B300, CBAUD, B300 },
3018 { TARGET_CBAUD, TARGET_B600, CBAUD, B600 },
3019 { TARGET_CBAUD, TARGET_B1200, CBAUD, B1200 },
3020 { TARGET_CBAUD, TARGET_B1800, CBAUD, B1800 },
3021 { TARGET_CBAUD, TARGET_B2400, CBAUD, B2400 },
3022 { TARGET_CBAUD, TARGET_B4800, CBAUD, B4800 },
3023 { TARGET_CBAUD, TARGET_B9600, CBAUD, B9600 },
3024 { TARGET_CBAUD, TARGET_B19200, CBAUD, B19200 },
3025 { TARGET_CBAUD, TARGET_B38400, CBAUD, B38400 },
3026 { TARGET_CBAUD, TARGET_B57600, CBAUD, B57600 },
3027 { TARGET_CBAUD, TARGET_B115200, CBAUD, B115200 },
3028 { TARGET_CBAUD, TARGET_B230400, CBAUD, B230400 },
3029 { TARGET_CBAUD, TARGET_B460800, CBAUD, B460800 },
3030 { TARGET_CSIZE, TARGET_CS5, CSIZE, CS5 },
3031 { TARGET_CSIZE, TARGET_CS6, CSIZE, CS6 },
3032 { TARGET_CSIZE, TARGET_CS7, CSIZE, CS7 },
3033 { TARGET_CSIZE, TARGET_CS8, CSIZE, CS8 },
3034 { TARGET_CSTOPB, TARGET_CSTOPB, CSTOPB, CSTOPB },
3035 { TARGET_CREAD, TARGET_CREAD, CREAD, CREAD },
3036 { TARGET_PARENB, TARGET_PARENB, PARENB, PARENB },
3037 { TARGET_PARODD, TARGET_PARODD, PARODD, PARODD },
3038 { TARGET_HUPCL, TARGET_HUPCL, HUPCL, HUPCL },
3039 { TARGET_CLOCAL, TARGET_CLOCAL, CLOCAL, CLOCAL },
3040 { TARGET_CRTSCTS, TARGET_CRTSCTS, CRTSCTS, CRTSCTS },
3041 { 0, 0, 0, 0 }
3042};
3043
blueswir1b39bc502008-10-05 10:51:10 +00003044static const bitmask_transtbl lflag_tbl[] = {
bellard31e31b82003-02-18 22:55:36 +00003045 { TARGET_ISIG, TARGET_ISIG, ISIG, ISIG },
3046 { TARGET_ICANON, TARGET_ICANON, ICANON, ICANON },
3047 { TARGET_XCASE, TARGET_XCASE, XCASE, XCASE },
3048 { TARGET_ECHO, TARGET_ECHO, ECHO, ECHO },
3049 { TARGET_ECHOE, TARGET_ECHOE, ECHOE, ECHOE },
3050 { TARGET_ECHOK, TARGET_ECHOK, ECHOK, ECHOK },
3051 { TARGET_ECHONL, TARGET_ECHONL, ECHONL, ECHONL },
3052 { TARGET_NOFLSH, TARGET_NOFLSH, NOFLSH, NOFLSH },
3053 { TARGET_TOSTOP, TARGET_TOSTOP, TOSTOP, TOSTOP },
3054 { TARGET_ECHOCTL, TARGET_ECHOCTL, ECHOCTL, ECHOCTL },
3055 { TARGET_ECHOPRT, TARGET_ECHOPRT, ECHOPRT, ECHOPRT },
3056 { TARGET_ECHOKE, TARGET_ECHOKE, ECHOKE, ECHOKE },
3057 { TARGET_FLUSHO, TARGET_FLUSHO, FLUSHO, FLUSHO },
3058 { TARGET_PENDIN, TARGET_PENDIN, PENDIN, PENDIN },
3059 { TARGET_IEXTEN, TARGET_IEXTEN, IEXTEN, IEXTEN },
3060 { 0, 0, 0, 0 }
3061};
3062
3063static void target_to_host_termios (void *dst, const void *src)
3064{
3065 struct host_termios *host = dst;
3066 const struct target_termios *target = src;
ths3b46e622007-09-17 08:09:54 +00003067
ths5fafdf22007-09-16 21:08:06 +00003068 host->c_iflag =
bellard31e31b82003-02-18 22:55:36 +00003069 target_to_host_bitmask(tswap32(target->c_iflag), iflag_tbl);
ths5fafdf22007-09-16 21:08:06 +00003070 host->c_oflag =
bellard31e31b82003-02-18 22:55:36 +00003071 target_to_host_bitmask(tswap32(target->c_oflag), oflag_tbl);
ths5fafdf22007-09-16 21:08:06 +00003072 host->c_cflag =
bellard31e31b82003-02-18 22:55:36 +00003073 target_to_host_bitmask(tswap32(target->c_cflag), cflag_tbl);
ths5fafdf22007-09-16 21:08:06 +00003074 host->c_lflag =
bellard31e31b82003-02-18 22:55:36 +00003075 target_to_host_bitmask(tswap32(target->c_lflag), lflag_tbl);
3076 host->c_line = target->c_line;
ths3b46e622007-09-17 08:09:54 +00003077
Arnaud Patard44607122009-04-21 17:39:08 +03003078 memset(host->c_cc, 0, sizeof(host->c_cc));
ths5fafdf22007-09-16 21:08:06 +00003079 host->c_cc[VINTR] = target->c_cc[TARGET_VINTR];
3080 host->c_cc[VQUIT] = target->c_cc[TARGET_VQUIT];
ths3b46e622007-09-17 08:09:54 +00003081 host->c_cc[VERASE] = target->c_cc[TARGET_VERASE];
ths5fafdf22007-09-16 21:08:06 +00003082 host->c_cc[VKILL] = target->c_cc[TARGET_VKILL];
ths3b46e622007-09-17 08:09:54 +00003083 host->c_cc[VEOF] = target->c_cc[TARGET_VEOF];
ths5fafdf22007-09-16 21:08:06 +00003084 host->c_cc[VTIME] = target->c_cc[TARGET_VTIME];
ths3b46e622007-09-17 08:09:54 +00003085 host->c_cc[VMIN] = target->c_cc[TARGET_VMIN];
ths5fafdf22007-09-16 21:08:06 +00003086 host->c_cc[VSWTC] = target->c_cc[TARGET_VSWTC];
ths3b46e622007-09-17 08:09:54 +00003087 host->c_cc[VSTART] = target->c_cc[TARGET_VSTART];
ths5fafdf22007-09-16 21:08:06 +00003088 host->c_cc[VSTOP] = target->c_cc[TARGET_VSTOP];
3089 host->c_cc[VSUSP] = target->c_cc[TARGET_VSUSP];
ths3b46e622007-09-17 08:09:54 +00003090 host->c_cc[VEOL] = target->c_cc[TARGET_VEOL];
3091 host->c_cc[VREPRINT] = target->c_cc[TARGET_VREPRINT];
3092 host->c_cc[VDISCARD] = target->c_cc[TARGET_VDISCARD];
3093 host->c_cc[VWERASE] = target->c_cc[TARGET_VWERASE];
3094 host->c_cc[VLNEXT] = target->c_cc[TARGET_VLNEXT];
ths5fafdf22007-09-16 21:08:06 +00003095 host->c_cc[VEOL2] = target->c_cc[TARGET_VEOL2];
bellard31e31b82003-02-18 22:55:36 +00003096}
ths3b46e622007-09-17 08:09:54 +00003097
bellard31e31b82003-02-18 22:55:36 +00003098static void host_to_target_termios (void *dst, const void *src)
3099{
3100 struct target_termios *target = dst;
3101 const struct host_termios *host = src;
3102
ths5fafdf22007-09-16 21:08:06 +00003103 target->c_iflag =
bellard31e31b82003-02-18 22:55:36 +00003104 tswap32(host_to_target_bitmask(host->c_iflag, iflag_tbl));
ths5fafdf22007-09-16 21:08:06 +00003105 target->c_oflag =
bellard31e31b82003-02-18 22:55:36 +00003106 tswap32(host_to_target_bitmask(host->c_oflag, oflag_tbl));
ths5fafdf22007-09-16 21:08:06 +00003107 target->c_cflag =
bellard31e31b82003-02-18 22:55:36 +00003108 tswap32(host_to_target_bitmask(host->c_cflag, cflag_tbl));
ths5fafdf22007-09-16 21:08:06 +00003109 target->c_lflag =
bellard31e31b82003-02-18 22:55:36 +00003110 tswap32(host_to_target_bitmask(host->c_lflag, lflag_tbl));
3111 target->c_line = host->c_line;
ths3b46e622007-09-17 08:09:54 +00003112
Arnaud Patard44607122009-04-21 17:39:08 +03003113 memset(target->c_cc, 0, sizeof(target->c_cc));
bellard31e31b82003-02-18 22:55:36 +00003114 target->c_cc[TARGET_VINTR] = host->c_cc[VINTR];
3115 target->c_cc[TARGET_VQUIT] = host->c_cc[VQUIT];
3116 target->c_cc[TARGET_VERASE] = host->c_cc[VERASE];
3117 target->c_cc[TARGET_VKILL] = host->c_cc[VKILL];
3118 target->c_cc[TARGET_VEOF] = host->c_cc[VEOF];
3119 target->c_cc[TARGET_VTIME] = host->c_cc[VTIME];
3120 target->c_cc[TARGET_VMIN] = host->c_cc[VMIN];
3121 target->c_cc[TARGET_VSWTC] = host->c_cc[VSWTC];
3122 target->c_cc[TARGET_VSTART] = host->c_cc[VSTART];
3123 target->c_cc[TARGET_VSTOP] = host->c_cc[VSTOP];
3124 target->c_cc[TARGET_VSUSP] = host->c_cc[VSUSP];
3125 target->c_cc[TARGET_VEOL] = host->c_cc[VEOL];
3126 target->c_cc[TARGET_VREPRINT] = host->c_cc[VREPRINT];
3127 target->c_cc[TARGET_VDISCARD] = host->c_cc[VDISCARD];
3128 target->c_cc[TARGET_VWERASE] = host->c_cc[VWERASE];
3129 target->c_cc[TARGET_VLNEXT] = host->c_cc[VLNEXT];
3130 target->c_cc[TARGET_VEOL2] = host->c_cc[VEOL2];
3131}
3132
blueswir18e853dc2008-10-05 10:49:32 +00003133static const StructEntry struct_termios_def = {
bellard31e31b82003-02-18 22:55:36 +00003134 .convert = { host_to_target_termios, target_to_host_termios },
3135 .size = { sizeof(struct target_termios), sizeof(struct host_termios) },
3136 .align = { __alignof__(struct target_termios), __alignof__(struct host_termios) },
3137};
3138
bellard5286db72003-06-05 00:57:30 +00003139static bitmask_transtbl mmap_flags_tbl[] = {
3140 { TARGET_MAP_SHARED, TARGET_MAP_SHARED, MAP_SHARED, MAP_SHARED },
3141 { TARGET_MAP_PRIVATE, TARGET_MAP_PRIVATE, MAP_PRIVATE, MAP_PRIVATE },
3142 { TARGET_MAP_FIXED, TARGET_MAP_FIXED, MAP_FIXED, MAP_FIXED },
3143 { TARGET_MAP_ANONYMOUS, TARGET_MAP_ANONYMOUS, MAP_ANONYMOUS, MAP_ANONYMOUS },
3144 { TARGET_MAP_GROWSDOWN, TARGET_MAP_GROWSDOWN, MAP_GROWSDOWN, MAP_GROWSDOWN },
3145 { TARGET_MAP_DENYWRITE, TARGET_MAP_DENYWRITE, MAP_DENYWRITE, MAP_DENYWRITE },
3146 { TARGET_MAP_EXECUTABLE, TARGET_MAP_EXECUTABLE, MAP_EXECUTABLE, MAP_EXECUTABLE },
3147 { TARGET_MAP_LOCKED, TARGET_MAP_LOCKED, MAP_LOCKED, MAP_LOCKED },
3148 { 0, 0, 0, 0 }
3149};
3150
bellard2ab83ea2003-06-15 19:56:46 +00003151#if defined(TARGET_I386)
bellard6dbad632003-03-16 18:05:05 +00003152
3153/* NOTE: there is really one LDT for all the threads */
blueswir1b1d8e522008-10-26 13:43:07 +00003154static uint8_t *ldt_table;
bellard6dbad632003-03-16 18:05:05 +00003155
bellard03acab62007-11-11 14:57:14 +00003156static abi_long read_ldt(abi_ulong ptr, unsigned long bytecount)
bellard6dbad632003-03-16 18:05:05 +00003157{
3158 int size;
pbrook53a59602006-03-25 19:31:22 +00003159 void *p;
bellard6dbad632003-03-16 18:05:05 +00003160
3161 if (!ldt_table)
3162 return 0;
3163 size = TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE;
3164 if (size > bytecount)
3165 size = bytecount;
bellard579a97f2007-11-11 14:26:47 +00003166 p = lock_user(VERIFY_WRITE, ptr, size, 0);
3167 if (!p)
bellard03acab62007-11-11 14:57:14 +00003168 return -TARGET_EFAULT;
bellard579a97f2007-11-11 14:26:47 +00003169 /* ??? Should this by byteswapped? */
pbrook53a59602006-03-25 19:31:22 +00003170 memcpy(p, ldt_table, size);
3171 unlock_user(p, ptr, size);
bellard6dbad632003-03-16 18:05:05 +00003172 return size;
3173}
3174
3175/* XXX: add locking support */
bellard03acab62007-11-11 14:57:14 +00003176static abi_long write_ldt(CPUX86State *env,
3177 abi_ulong ptr, unsigned long bytecount, int oldmode)
bellard6dbad632003-03-16 18:05:05 +00003178{
3179 struct target_modify_ldt_ldt_s ldt_info;
pbrook53a59602006-03-25 19:31:22 +00003180 struct target_modify_ldt_ldt_s *target_ldt_info;
bellard6dbad632003-03-16 18:05:05 +00003181 int seg_32bit, contents, read_exec_only, limit_in_pages;
bellard8d18e892007-11-14 15:18:40 +00003182 int seg_not_present, useable, lm;
bellard6dbad632003-03-16 18:05:05 +00003183 uint32_t *lp, entry_1, entry_2;
3184
3185 if (bytecount != sizeof(ldt_info))
bellard03acab62007-11-11 14:57:14 +00003186 return -TARGET_EINVAL;
bellard579a97f2007-11-11 14:26:47 +00003187 if (!lock_user_struct(VERIFY_READ, target_ldt_info, ptr, 1))
bellard03acab62007-11-11 14:57:14 +00003188 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00003189 ldt_info.entry_number = tswap32(target_ldt_info->entry_number);
3190 ldt_info.base_addr = tswapl(target_ldt_info->base_addr);
3191 ldt_info.limit = tswap32(target_ldt_info->limit);
3192 ldt_info.flags = tswap32(target_ldt_info->flags);
3193 unlock_user_struct(target_ldt_info, ptr, 0);
ths3b46e622007-09-17 08:09:54 +00003194
bellard6dbad632003-03-16 18:05:05 +00003195 if (ldt_info.entry_number >= TARGET_LDT_ENTRIES)
bellard03acab62007-11-11 14:57:14 +00003196 return -TARGET_EINVAL;
bellard6dbad632003-03-16 18:05:05 +00003197 seg_32bit = ldt_info.flags & 1;
3198 contents = (ldt_info.flags >> 1) & 3;
3199 read_exec_only = (ldt_info.flags >> 3) & 1;
3200 limit_in_pages = (ldt_info.flags >> 4) & 1;
3201 seg_not_present = (ldt_info.flags >> 5) & 1;
3202 useable = (ldt_info.flags >> 6) & 1;
bellard8d18e892007-11-14 15:18:40 +00003203#ifdef TARGET_ABI32
3204 lm = 0;
3205#else
3206 lm = (ldt_info.flags >> 7) & 1;
3207#endif
bellard6dbad632003-03-16 18:05:05 +00003208 if (contents == 3) {
3209 if (oldmode)
bellard03acab62007-11-11 14:57:14 +00003210 return -TARGET_EINVAL;
bellard6dbad632003-03-16 18:05:05 +00003211 if (seg_not_present == 0)
bellard03acab62007-11-11 14:57:14 +00003212 return -TARGET_EINVAL;
bellard6dbad632003-03-16 18:05:05 +00003213 }
3214 /* allocate the LDT */
3215 if (!ldt_table) {
balroge4415702008-11-10 02:55:33 +00003216 env->ldt.base = target_mmap(0,
3217 TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE,
3218 PROT_READ|PROT_WRITE,
3219 MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
3220 if (env->ldt.base == -1)
bellard03acab62007-11-11 14:57:14 +00003221 return -TARGET_ENOMEM;
balroge4415702008-11-10 02:55:33 +00003222 memset(g2h(env->ldt.base), 0,
3223 TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE);
bellard6dbad632003-03-16 18:05:05 +00003224 env->ldt.limit = 0xffff;
balroge4415702008-11-10 02:55:33 +00003225 ldt_table = g2h(env->ldt.base);
bellard6dbad632003-03-16 18:05:05 +00003226 }
3227
3228 /* NOTE: same code as Linux kernel */
3229 /* Allow LDTs to be cleared by the user. */
3230 if (ldt_info.base_addr == 0 && ldt_info.limit == 0) {
3231 if (oldmode ||
3232 (contents == 0 &&
3233 read_exec_only == 1 &&
3234 seg_32bit == 0 &&
3235 limit_in_pages == 0 &&
3236 seg_not_present == 1 &&
3237 useable == 0 )) {
3238 entry_1 = 0;
3239 entry_2 = 0;
3240 goto install;
3241 }
3242 }
ths3b46e622007-09-17 08:09:54 +00003243
bellard6dbad632003-03-16 18:05:05 +00003244 entry_1 = ((ldt_info.base_addr & 0x0000ffff) << 16) |
3245 (ldt_info.limit & 0x0ffff);
3246 entry_2 = (ldt_info.base_addr & 0xff000000) |
3247 ((ldt_info.base_addr & 0x00ff0000) >> 16) |
3248 (ldt_info.limit & 0xf0000) |
3249 ((read_exec_only ^ 1) << 9) |
3250 (contents << 10) |
3251 ((seg_not_present ^ 1) << 15) |
3252 (seg_32bit << 22) |
3253 (limit_in_pages << 23) |
bellard8d18e892007-11-14 15:18:40 +00003254 (lm << 21) |
bellard6dbad632003-03-16 18:05:05 +00003255 0x7000;
3256 if (!oldmode)
3257 entry_2 |= (useable << 20);
bellard14ae3ba2003-05-27 23:25:06 +00003258
bellard6dbad632003-03-16 18:05:05 +00003259 /* Install the new entry ... */
3260install:
3261 lp = (uint32_t *)(ldt_table + (ldt_info.entry_number << 3));
3262 lp[0] = tswap32(entry_1);
3263 lp[1] = tswap32(entry_2);
3264 return 0;
3265}
3266
3267/* specific and weird i386 syscalls */
blueswir18fcd3692008-08-17 20:26:25 +00003268static abi_long do_modify_ldt(CPUX86State *env, int func, abi_ulong ptr,
3269 unsigned long bytecount)
bellard6dbad632003-03-16 18:05:05 +00003270{
bellard03acab62007-11-11 14:57:14 +00003271 abi_long ret;
ths3b46e622007-09-17 08:09:54 +00003272
bellard6dbad632003-03-16 18:05:05 +00003273 switch (func) {
3274 case 0:
3275 ret = read_ldt(ptr, bytecount);
3276 break;
3277 case 1:
3278 ret = write_ldt(env, ptr, bytecount, 1);
3279 break;
3280 case 0x11:
3281 ret = write_ldt(env, ptr, bytecount, 0);
3282 break;
bellard03acab62007-11-11 14:57:14 +00003283 default:
3284 ret = -TARGET_ENOSYS;
3285 break;
bellard6dbad632003-03-16 18:05:05 +00003286 }
3287 return ret;
3288}
bellard1b6b0292003-03-22 17:31:38 +00003289
blueswir14583f582008-08-24 10:35:55 +00003290#if defined(TARGET_I386) && defined(TARGET_ABI32)
blueswir18fcd3692008-08-17 20:26:25 +00003291static abi_long do_set_thread_area(CPUX86State *env, abi_ulong ptr)
bellard8d18e892007-11-14 15:18:40 +00003292{
3293 uint64_t *gdt_table = g2h(env->gdt.base);
3294 struct target_modify_ldt_ldt_s ldt_info;
3295 struct target_modify_ldt_ldt_s *target_ldt_info;
3296 int seg_32bit, contents, read_exec_only, limit_in_pages;
3297 int seg_not_present, useable, lm;
3298 uint32_t *lp, entry_1, entry_2;
3299 int i;
3300
3301 lock_user_struct(VERIFY_WRITE, target_ldt_info, ptr, 1);
3302 if (!target_ldt_info)
3303 return -TARGET_EFAULT;
3304 ldt_info.entry_number = tswap32(target_ldt_info->entry_number);
3305 ldt_info.base_addr = tswapl(target_ldt_info->base_addr);
3306 ldt_info.limit = tswap32(target_ldt_info->limit);
3307 ldt_info.flags = tswap32(target_ldt_info->flags);
3308 if (ldt_info.entry_number == -1) {
3309 for (i=TARGET_GDT_ENTRY_TLS_MIN; i<=TARGET_GDT_ENTRY_TLS_MAX; i++) {
3310 if (gdt_table[i] == 0) {
3311 ldt_info.entry_number = i;
3312 target_ldt_info->entry_number = tswap32(i);
3313 break;
3314 }
3315 }
3316 }
3317 unlock_user_struct(target_ldt_info, ptr, 1);
3318
3319 if (ldt_info.entry_number < TARGET_GDT_ENTRY_TLS_MIN ||
3320 ldt_info.entry_number > TARGET_GDT_ENTRY_TLS_MAX)
3321 return -TARGET_EINVAL;
3322 seg_32bit = ldt_info.flags & 1;
3323 contents = (ldt_info.flags >> 1) & 3;
3324 read_exec_only = (ldt_info.flags >> 3) & 1;
3325 limit_in_pages = (ldt_info.flags >> 4) & 1;
3326 seg_not_present = (ldt_info.flags >> 5) & 1;
3327 useable = (ldt_info.flags >> 6) & 1;
3328#ifdef TARGET_ABI32
3329 lm = 0;
3330#else
3331 lm = (ldt_info.flags >> 7) & 1;
3332#endif
3333
3334 if (contents == 3) {
3335 if (seg_not_present == 0)
3336 return -TARGET_EINVAL;
3337 }
3338
3339 /* NOTE: same code as Linux kernel */
3340 /* Allow LDTs to be cleared by the user. */
3341 if (ldt_info.base_addr == 0 && ldt_info.limit == 0) {
3342 if ((contents == 0 &&
3343 read_exec_only == 1 &&
3344 seg_32bit == 0 &&
3345 limit_in_pages == 0 &&
3346 seg_not_present == 1 &&
3347 useable == 0 )) {
3348 entry_1 = 0;
3349 entry_2 = 0;
3350 goto install;
3351 }
3352 }
3353
3354 entry_1 = ((ldt_info.base_addr & 0x0000ffff) << 16) |
3355 (ldt_info.limit & 0x0ffff);
3356 entry_2 = (ldt_info.base_addr & 0xff000000) |
3357 ((ldt_info.base_addr & 0x00ff0000) >> 16) |
3358 (ldt_info.limit & 0xf0000) |
3359 ((read_exec_only ^ 1) << 9) |
3360 (contents << 10) |
3361 ((seg_not_present ^ 1) << 15) |
3362 (seg_32bit << 22) |
3363 (limit_in_pages << 23) |
3364 (useable << 20) |
3365 (lm << 21) |
3366 0x7000;
3367
3368 /* Install the new entry ... */
3369install:
3370 lp = (uint32_t *)(gdt_table + ldt_info.entry_number);
3371 lp[0] = tswap32(entry_1);
3372 lp[1] = tswap32(entry_2);
3373 return 0;
3374}
3375
blueswir18fcd3692008-08-17 20:26:25 +00003376static abi_long do_get_thread_area(CPUX86State *env, abi_ulong ptr)
bellard8d18e892007-11-14 15:18:40 +00003377{
3378 struct target_modify_ldt_ldt_s *target_ldt_info;
3379 uint64_t *gdt_table = g2h(env->gdt.base);
3380 uint32_t base_addr, limit, flags;
3381 int seg_32bit, contents, read_exec_only, limit_in_pages, idx;
3382 int seg_not_present, useable, lm;
3383 uint32_t *lp, entry_1, entry_2;
3384
3385 lock_user_struct(VERIFY_WRITE, target_ldt_info, ptr, 1);
3386 if (!target_ldt_info)
3387 return -TARGET_EFAULT;
3388 idx = tswap32(target_ldt_info->entry_number);
3389 if (idx < TARGET_GDT_ENTRY_TLS_MIN ||
3390 idx > TARGET_GDT_ENTRY_TLS_MAX) {
3391 unlock_user_struct(target_ldt_info, ptr, 1);
3392 return -TARGET_EINVAL;
3393 }
3394 lp = (uint32_t *)(gdt_table + idx);
3395 entry_1 = tswap32(lp[0]);
3396 entry_2 = tswap32(lp[1]);
3397
3398 read_exec_only = ((entry_2 >> 9) & 1) ^ 1;
3399 contents = (entry_2 >> 10) & 3;
3400 seg_not_present = ((entry_2 >> 15) & 1) ^ 1;
3401 seg_32bit = (entry_2 >> 22) & 1;
3402 limit_in_pages = (entry_2 >> 23) & 1;
3403 useable = (entry_2 >> 20) & 1;
3404#ifdef TARGET_ABI32
3405 lm = 0;
3406#else
3407 lm = (entry_2 >> 21) & 1;
3408#endif
3409 flags = (seg_32bit << 0) | (contents << 1) |
3410 (read_exec_only << 3) | (limit_in_pages << 4) |
3411 (seg_not_present << 5) | (useable << 6) | (lm << 7);
3412 limit = (entry_1 & 0xffff) | (entry_2 & 0xf0000);
3413 base_addr = (entry_1 >> 16) |
3414 (entry_2 & 0xff000000) |
3415 ((entry_2 & 0xff) << 16);
3416 target_ldt_info->base_addr = tswapl(base_addr);
3417 target_ldt_info->limit = tswap32(limit);
3418 target_ldt_info->flags = tswap32(flags);
3419 unlock_user_struct(target_ldt_info, ptr, 1);
3420 return 0;
3421}
blueswir14583f582008-08-24 10:35:55 +00003422#endif /* TARGET_I386 && TARGET_ABI32 */
bellard8d18e892007-11-14 15:18:40 +00003423
bellardd2fd1af2007-11-14 18:08:56 +00003424#ifndef TARGET_ABI32
blueswir18fcd3692008-08-17 20:26:25 +00003425static abi_long do_arch_prctl(CPUX86State *env, int code, abi_ulong addr)
bellardd2fd1af2007-11-14 18:08:56 +00003426{
3427 abi_long ret;
3428 abi_ulong val;
3429 int idx;
3430
3431 switch(code) {
3432 case TARGET_ARCH_SET_GS:
3433 case TARGET_ARCH_SET_FS:
3434 if (code == TARGET_ARCH_SET_GS)
3435 idx = R_GS;
3436 else
3437 idx = R_FS;
3438 cpu_x86_load_seg(env, idx, 0);
3439 env->segs[idx].base = addr;
3440 break;
3441 case TARGET_ARCH_GET_GS:
3442 case TARGET_ARCH_GET_FS:
3443 if (code == TARGET_ARCH_GET_GS)
3444 idx = R_GS;
3445 else
3446 idx = R_FS;
3447 val = env->segs[idx].base;
3448 if (put_user(val, addr, abi_ulong))
3449 return -TARGET_EFAULT;
3450 break;
3451 default:
3452 ret = -TARGET_EINVAL;
3453 break;
3454 }
3455 return 0;
3456}
3457#endif
3458
bellard2ab83ea2003-06-15 19:56:46 +00003459#endif /* defined(TARGET_I386) */
3460
pbrookd865bab2008-06-07 22:12:17 +00003461#if defined(USE_NPTL)
3462
3463#define NEW_STACK_SIZE PTHREAD_STACK_MIN
3464
3465static pthread_mutex_t clone_lock = PTHREAD_MUTEX_INITIALIZER;
3466typedef struct {
3467 CPUState *env;
3468 pthread_mutex_t mutex;
3469 pthread_cond_t cond;
3470 pthread_t thread;
3471 uint32_t tid;
3472 abi_ulong child_tidptr;
3473 abi_ulong parent_tidptr;
3474 sigset_t sigmask;
3475} new_thread_info;
3476
3477static void *clone_func(void *arg)
3478{
3479 new_thread_info *info = arg;
3480 CPUState *env;
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03003481 TaskState *ts;
pbrookd865bab2008-06-07 22:12:17 +00003482
3483 env = info->env;
3484 thread_env = env;
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03003485 ts = (TaskState *)thread_env->opaque;
pbrookd865bab2008-06-07 22:12:17 +00003486 info->tid = gettid();
Nathan Froyd1e9fa732009-06-03 11:33:08 -07003487 env->host_tid = info->tid;
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03003488 task_settid(ts);
pbrookd865bab2008-06-07 22:12:17 +00003489 if (info->child_tidptr)
3490 put_user_u32(info->tid, info->child_tidptr);
3491 if (info->parent_tidptr)
3492 put_user_u32(info->tid, info->parent_tidptr);
3493 /* Enable signals. */
3494 sigprocmask(SIG_SETMASK, &info->sigmask, NULL);
3495 /* Signal to the parent that we're ready. */
3496 pthread_mutex_lock(&info->mutex);
3497 pthread_cond_broadcast(&info->cond);
3498 pthread_mutex_unlock(&info->mutex);
3499 /* Wait until the parent has finshed initializing the tls state. */
3500 pthread_mutex_lock(&clone_lock);
3501 pthread_mutex_unlock(&clone_lock);
3502 cpu_loop(env);
3503 /* never exits */
3504 return NULL;
3505}
3506#else
bellard1b6b0292003-03-22 17:31:38 +00003507/* this stack is the equivalent of the kernel stack associated with a
3508 thread/process */
3509#define NEW_STACK_SIZE 8192
3510
3511static int clone_func(void *arg)
3512{
bellard2ab83ea2003-06-15 19:56:46 +00003513 CPUState *env = arg;
bellard1b6b0292003-03-22 17:31:38 +00003514 cpu_loop(env);
3515 /* never exits */
3516 return 0;
3517}
pbrookd865bab2008-06-07 22:12:17 +00003518#endif
bellard1b6b0292003-03-22 17:31:38 +00003519
ths0da46a62007-10-20 20:23:07 +00003520/* do_fork() Must return host values and target errnos (unlike most
3521 do_*() functions). */
pbrookd865bab2008-06-07 22:12:17 +00003522static int do_fork(CPUState *env, unsigned int flags, abi_ulong newsp,
3523 abi_ulong parent_tidptr, target_ulong newtls,
3524 abi_ulong child_tidptr)
bellard1b6b0292003-03-22 17:31:38 +00003525{
3526 int ret;
bellard5cd43932003-03-29 16:54:36 +00003527 TaskState *ts;
bellard1b6b0292003-03-22 17:31:38 +00003528 uint8_t *new_stack;
bellard2ab83ea2003-06-15 19:56:46 +00003529 CPUState *new_env;
pbrookd865bab2008-06-07 22:12:17 +00003530#if defined(USE_NPTL)
3531 unsigned int nptl_flags;
3532 sigset_t sigmask;
3533#endif
ths3b46e622007-09-17 08:09:54 +00003534
balrog436d1242008-09-21 02:39:45 +00003535 /* Emulate vfork() with fork() */
3536 if (flags & CLONE_VFORK)
3537 flags &= ~(CLONE_VFORK | CLONE_VM);
3538
bellard1b6b0292003-03-22 17:31:38 +00003539 if (flags & CLONE_VM) {
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03003540 TaskState *parent_ts = (TaskState *)env->opaque;
pbrookbd0c5662008-05-29 14:34:11 +00003541#if defined(USE_NPTL)
pbrookd865bab2008-06-07 22:12:17 +00003542 new_thread_info info;
3543 pthread_attr_t attr;
pbrookbd0c5662008-05-29 14:34:11 +00003544#endif
pbrookc3a92832008-06-09 14:02:50 +00003545 ts = qemu_mallocz(sizeof(TaskState) + NEW_STACK_SIZE);
pbrook624f7972008-05-31 16:11:38 +00003546 init_task_state(ts);
bellard5cd43932003-03-29 16:54:36 +00003547 new_stack = ts->stack;
bellard1b6b0292003-03-22 17:31:38 +00003548 /* we create a new CPU instance. */
thsc5be9f02007-02-28 20:20:53 +00003549 new_env = cpu_copy(env);
pbrook6e68e072008-05-30 17:22:15 +00003550 /* Init regs that differ from the parent. */
3551 cpu_clone_regs(new_env, newsp);
bellard5cd43932003-03-29 16:54:36 +00003552 new_env->opaque = ts;
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03003553 ts->bprm = parent_ts->bprm;
3554 ts->info = parent_ts->info;
pbrookd865bab2008-06-07 22:12:17 +00003555#if defined(USE_NPTL)
3556 nptl_flags = flags;
3557 flags &= ~CLONE_NPTL_FLAGS2;
3558
pbrookc2764712009-03-07 15:24:59 +00003559 if (nptl_flags & CLONE_CHILD_CLEARTID) {
3560 ts->child_tidptr = child_tidptr;
3561 }
3562
pbrookd865bab2008-06-07 22:12:17 +00003563 if (nptl_flags & CLONE_SETTLS)
3564 cpu_set_tls (new_env, newtls);
3565
3566 /* Grab a mutex so that thread setup appears atomic. */
3567 pthread_mutex_lock(&clone_lock);
3568
3569 memset(&info, 0, sizeof(info));
3570 pthread_mutex_init(&info.mutex, NULL);
3571 pthread_mutex_lock(&info.mutex);
3572 pthread_cond_init(&info.cond, NULL);
3573 info.env = new_env;
3574 if (nptl_flags & CLONE_CHILD_SETTID)
3575 info.child_tidptr = child_tidptr;
3576 if (nptl_flags & CLONE_PARENT_SETTID)
3577 info.parent_tidptr = parent_tidptr;
3578
3579 ret = pthread_attr_init(&attr);
3580 ret = pthread_attr_setstack(&attr, new_stack, NEW_STACK_SIZE);
3581 /* It is not safe to deliver signals until the child has finished
3582 initializing, so temporarily block all signals. */
3583 sigfillset(&sigmask);
3584 sigprocmask(SIG_BLOCK, &sigmask, &info.sigmask);
3585
3586 ret = pthread_create(&info.thread, &attr, clone_func, &info);
pbrookc2764712009-03-07 15:24:59 +00003587 /* TODO: Free new CPU state if thread creation failed. */
pbrookd865bab2008-06-07 22:12:17 +00003588
3589 sigprocmask(SIG_SETMASK, &info.sigmask, NULL);
3590 pthread_attr_destroy(&attr);
3591 if (ret == 0) {
3592 /* Wait for the child to initialize. */
3593 pthread_cond_wait(&info.cond, &info.mutex);
3594 ret = info.tid;
3595 if (flags & CLONE_PARENT_SETTID)
3596 put_user_u32(ret, parent_tidptr);
3597 } else {
3598 ret = -1;
3599 }
3600 pthread_mutex_unlock(&info.mutex);
3601 pthread_cond_destroy(&info.cond);
3602 pthread_mutex_destroy(&info.mutex);
3603 pthread_mutex_unlock(&clone_lock);
3604#else
3605 if (flags & CLONE_NPTL_FLAGS2)
3606 return -EINVAL;
3607 /* This is probably going to die very quickly, but do it anyway. */
bellard27725c12003-04-29 21:08:18 +00003608#ifdef __ia64__
bellardfd4a43e2006-04-24 20:32:17 +00003609 ret = __clone2(clone_func, new_stack + NEW_STACK_SIZE, flags, new_env);
bellard27725c12003-04-29 21:08:18 +00003610#else
3611 ret = clone(clone_func, new_stack + NEW_STACK_SIZE, flags, new_env);
3612#endif
pbrookd865bab2008-06-07 22:12:17 +00003613#endif
bellard1b6b0292003-03-22 17:31:38 +00003614 } else {
3615 /* if no CLONE_VM, we consider it is a fork */
pbrookd865bab2008-06-07 22:12:17 +00003616 if ((flags & ~(CSIGNAL | CLONE_NPTL_FLAGS2)) != 0)
bellard1b6b0292003-03-22 17:31:38 +00003617 return -EINVAL;
pbrookd865bab2008-06-07 22:12:17 +00003618 fork_start();
bellard1b6b0292003-03-22 17:31:38 +00003619 ret = fork();
pbrookd865bab2008-06-07 22:12:17 +00003620 if (ret == 0) {
aurel322b1319c2008-12-18 22:44:04 +00003621 /* Child Process. */
pbrookd865bab2008-06-07 22:12:17 +00003622 cpu_clone_regs(env, newsp);
3623 fork_end(1);
aurel322b1319c2008-12-18 22:44:04 +00003624#if defined(USE_NPTL)
3625 /* There is a race condition here. The parent process could
3626 theoretically read the TID in the child process before the child
3627 tid is set. This would require using either ptrace
3628 (not implemented) or having *_tidptr to point at a shared memory
3629 mapping. We can't repeat the spinlock hack used above because
3630 the child process gets its own copy of the lock. */
pbrookd865bab2008-06-07 22:12:17 +00003631 if (flags & CLONE_CHILD_SETTID)
3632 put_user_u32(gettid(), child_tidptr);
3633 if (flags & CLONE_PARENT_SETTID)
3634 put_user_u32(gettid(), parent_tidptr);
3635 ts = (TaskState *)env->opaque;
3636 if (flags & CLONE_SETTLS)
3637 cpu_set_tls (env, newtls);
pbrookc2764712009-03-07 15:24:59 +00003638 if (flags & CLONE_CHILD_CLEARTID)
3639 ts->child_tidptr = child_tidptr;
aurel322b1319c2008-12-18 22:44:04 +00003640#endif
pbrookd865bab2008-06-07 22:12:17 +00003641 } else {
3642 fork_end(0);
3643 }
bellard1b6b0292003-03-22 17:31:38 +00003644 }
3645 return ret;
3646}
3647
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02003648/* warning : doesn't handle linux specific flags... */
3649static int target_to_host_fcntl_cmd(int cmd)
3650{
3651 switch(cmd) {
3652 case TARGET_F_DUPFD:
3653 case TARGET_F_GETFD:
3654 case TARGET_F_SETFD:
3655 case TARGET_F_GETFL:
3656 case TARGET_F_SETFL:
3657 return cmd;
3658 case TARGET_F_GETLK:
3659 return F_GETLK;
3660 case TARGET_F_SETLK:
3661 return F_SETLK;
3662 case TARGET_F_SETLKW:
3663 return F_SETLKW;
3664 case TARGET_F_GETOWN:
3665 return F_GETOWN;
3666 case TARGET_F_SETOWN:
3667 return F_SETOWN;
3668 case TARGET_F_GETSIG:
3669 return F_GETSIG;
3670 case TARGET_F_SETSIG:
3671 return F_SETSIG;
3672#if TARGET_ABI_BITS == 32
3673 case TARGET_F_GETLK64:
3674 return F_GETLK64;
3675 case TARGET_F_SETLK64:
3676 return F_SETLK64;
3677 case TARGET_F_SETLKW64:
3678 return F_SETLKW64;
3679#endif
3680 default:
3681 return -TARGET_EINVAL;
3682 }
3683 return -TARGET_EINVAL;
3684}
3685
blueswir1992f48a2007-10-14 16:27:31 +00003686static abi_long do_fcntl(int fd, int cmd, abi_ulong arg)
bellard7775e9e2003-05-14 22:46:48 +00003687{
3688 struct flock fl;
pbrook53a59602006-03-25 19:31:22 +00003689 struct target_flock *target_fl;
ths43f238d2007-01-05 20:55:49 +00003690 struct flock64 fl64;
3691 struct target_flock64 *target_fl64;
blueswir1992f48a2007-10-14 16:27:31 +00003692 abi_long ret;
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02003693 int host_cmd = target_to_host_fcntl_cmd(cmd);
3694
3695 if (host_cmd == -TARGET_EINVAL)
3696 return host_cmd;
pbrook53a59602006-03-25 19:31:22 +00003697
bellard7775e9e2003-05-14 22:46:48 +00003698 switch(cmd) {
3699 case TARGET_F_GETLK:
bellard579a97f2007-11-11 14:26:47 +00003700 if (!lock_user_struct(VERIFY_READ, target_fl, arg, 1))
3701 return -TARGET_EFAULT;
ths58134272007-03-31 18:59:32 +00003702 fl.l_type = tswap16(target_fl->l_type);
3703 fl.l_whence = tswap16(target_fl->l_whence);
3704 fl.l_start = tswapl(target_fl->l_start);
3705 fl.l_len = tswapl(target_fl->l_len);
3706 fl.l_pid = tswapl(target_fl->l_pid);
3707 unlock_user_struct(target_fl, arg, 0);
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02003708 ret = get_errno(fcntl(fd, host_cmd, &fl));
bellard7775e9e2003-05-14 22:46:48 +00003709 if (ret == 0) {
bellard579a97f2007-11-11 14:26:47 +00003710 if (!lock_user_struct(VERIFY_WRITE, target_fl, arg, 0))
3711 return -TARGET_EFAULT;
bellard7775e9e2003-05-14 22:46:48 +00003712 target_fl->l_type = tswap16(fl.l_type);
3713 target_fl->l_whence = tswap16(fl.l_whence);
3714 target_fl->l_start = tswapl(fl.l_start);
3715 target_fl->l_len = tswapl(fl.l_len);
3716 target_fl->l_pid = tswapl(fl.l_pid);
pbrook53a59602006-03-25 19:31:22 +00003717 unlock_user_struct(target_fl, arg, 1);
bellard7775e9e2003-05-14 22:46:48 +00003718 }
3719 break;
ths3b46e622007-09-17 08:09:54 +00003720
bellard7775e9e2003-05-14 22:46:48 +00003721 case TARGET_F_SETLK:
3722 case TARGET_F_SETLKW:
bellard579a97f2007-11-11 14:26:47 +00003723 if (!lock_user_struct(VERIFY_READ, target_fl, arg, 1))
3724 return -TARGET_EFAULT;
bellard7775e9e2003-05-14 22:46:48 +00003725 fl.l_type = tswap16(target_fl->l_type);
3726 fl.l_whence = tswap16(target_fl->l_whence);
3727 fl.l_start = tswapl(target_fl->l_start);
3728 fl.l_len = tswapl(target_fl->l_len);
3729 fl.l_pid = tswapl(target_fl->l_pid);
pbrook53a59602006-03-25 19:31:22 +00003730 unlock_user_struct(target_fl, arg, 0);
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02003731 ret = get_errno(fcntl(fd, host_cmd, &fl));
bellard7775e9e2003-05-14 22:46:48 +00003732 break;
ths3b46e622007-09-17 08:09:54 +00003733
bellard7775e9e2003-05-14 22:46:48 +00003734 case TARGET_F_GETLK64:
bellard579a97f2007-11-11 14:26:47 +00003735 if (!lock_user_struct(VERIFY_READ, target_fl64, arg, 1))
3736 return -TARGET_EFAULT;
ths58134272007-03-31 18:59:32 +00003737 fl64.l_type = tswap16(target_fl64->l_type) >> 1;
3738 fl64.l_whence = tswap16(target_fl64->l_whence);
3739 fl64.l_start = tswapl(target_fl64->l_start);
3740 fl64.l_len = tswapl(target_fl64->l_len);
3741 fl64.l_pid = tswap16(target_fl64->l_pid);
3742 unlock_user_struct(target_fl64, arg, 0);
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02003743 ret = get_errno(fcntl(fd, host_cmd, &fl64));
ths43f238d2007-01-05 20:55:49 +00003744 if (ret == 0) {
bellard579a97f2007-11-11 14:26:47 +00003745 if (!lock_user_struct(VERIFY_WRITE, target_fl64, arg, 0))
3746 return -TARGET_EFAULT;
ths43f238d2007-01-05 20:55:49 +00003747 target_fl64->l_type = tswap16(fl64.l_type) >> 1;
3748 target_fl64->l_whence = tswap16(fl64.l_whence);
3749 target_fl64->l_start = tswapl(fl64.l_start);
3750 target_fl64->l_len = tswapl(fl64.l_len);
3751 target_fl64->l_pid = tswapl(fl64.l_pid);
3752 unlock_user_struct(target_fl64, arg, 1);
3753 }
bellard9ee1fa22007-11-11 15:11:19 +00003754 break;
bellard7775e9e2003-05-14 22:46:48 +00003755 case TARGET_F_SETLK64:
3756 case TARGET_F_SETLKW64:
bellard579a97f2007-11-11 14:26:47 +00003757 if (!lock_user_struct(VERIFY_READ, target_fl64, arg, 1))
3758 return -TARGET_EFAULT;
ths43f238d2007-01-05 20:55:49 +00003759 fl64.l_type = tswap16(target_fl64->l_type) >> 1;
3760 fl64.l_whence = tswap16(target_fl64->l_whence);
3761 fl64.l_start = tswapl(target_fl64->l_start);
3762 fl64.l_len = tswapl(target_fl64->l_len);
3763 fl64.l_pid = tswap16(target_fl64->l_pid);
3764 unlock_user_struct(target_fl64, arg, 0);
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02003765 ret = get_errno(fcntl(fd, host_cmd, &fl64));
bellard7775e9e2003-05-14 22:46:48 +00003766 break;
3767
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02003768 case TARGET_F_GETFL:
3769 ret = get_errno(fcntl(fd, host_cmd, arg));
bellard9ee1fa22007-11-11 15:11:19 +00003770 if (ret >= 0) {
3771 ret = host_to_target_bitmask(ret, fcntl_flags_tbl);
3772 }
bellardffa65c32004-01-04 23:57:22 +00003773 break;
3774
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02003775 case TARGET_F_SETFL:
3776 ret = get_errno(fcntl(fd, host_cmd, target_to_host_bitmask(arg, fcntl_flags_tbl)));
3777 break;
3778
3779 case TARGET_F_SETOWN:
3780 case TARGET_F_GETOWN:
3781 case TARGET_F_SETSIG:
3782 case TARGET_F_GETSIG:
3783 ret = get_errno(fcntl(fd, host_cmd, arg));
bellardffa65c32004-01-04 23:57:22 +00003784 break;
3785
bellard7775e9e2003-05-14 22:46:48 +00003786 default:
bellard9ee1fa22007-11-11 15:11:19 +00003787 ret = get_errno(fcntl(fd, cmd, arg));
bellard7775e9e2003-05-14 22:46:48 +00003788 break;
3789 }
3790 return ret;
3791}
3792
bellard67867302003-11-23 17:05:30 +00003793#ifdef USE_UID16
bellard7775e9e2003-05-14 22:46:48 +00003794
bellard67867302003-11-23 17:05:30 +00003795static inline int high2lowuid(int uid)
3796{
3797 if (uid > 65535)
3798 return 65534;
3799 else
3800 return uid;
3801}
3802
3803static inline int high2lowgid(int gid)
3804{
3805 if (gid > 65535)
3806 return 65534;
3807 else
3808 return gid;
3809}
3810
3811static inline int low2highuid(int uid)
3812{
3813 if ((int16_t)uid == -1)
3814 return -1;
3815 else
3816 return uid;
3817}
3818
3819static inline int low2highgid(int gid)
3820{
3821 if ((int16_t)gid == -1)
3822 return -1;
3823 else
3824 return gid;
3825}
3826
3827#endif /* USE_UID16 */
bellard1b6b0292003-03-22 17:31:38 +00003828
bellard31e31b82003-02-18 22:55:36 +00003829void syscall_init(void)
3830{
bellard2ab83ea2003-06-15 19:56:46 +00003831 IOCTLEntry *ie;
3832 const argtype *arg_type;
3833 int size;
thsb92c47c2007-11-01 00:07:38 +00003834 int i;
bellard2ab83ea2003-06-15 19:56:46 +00003835
Blue Swirl001faf32009-05-13 17:53:17 +00003836#define STRUCT(name, ...) thunk_register_struct(STRUCT_ ## name, #name, struct_ ## name ## _def);
ths5fafdf22007-09-16 21:08:06 +00003837#define STRUCT_SPECIAL(name) thunk_register_struct_direct(STRUCT_ ## name, #name, &struct_ ## name ## _def);
bellard31e31b82003-02-18 22:55:36 +00003838#include "syscall_types.h"
3839#undef STRUCT
3840#undef STRUCT_SPECIAL
bellard2ab83ea2003-06-15 19:56:46 +00003841
3842 /* we patch the ioctl size if necessary. We rely on the fact that
3843 no ioctl has all the bits at '1' in the size field */
3844 ie = ioctl_entries;
3845 while (ie->target_cmd != 0) {
3846 if (((ie->target_cmd >> TARGET_IOC_SIZESHIFT) & TARGET_IOC_SIZEMASK) ==
3847 TARGET_IOC_SIZEMASK) {
3848 arg_type = ie->arg_type;
3849 if (arg_type[0] != TYPE_PTR) {
ths5fafdf22007-09-16 21:08:06 +00003850 fprintf(stderr, "cannot patch size for ioctl 0x%x\n",
bellard2ab83ea2003-06-15 19:56:46 +00003851 ie->target_cmd);
3852 exit(1);
3853 }
3854 arg_type++;
3855 size = thunk_type_size(arg_type, 0);
ths5fafdf22007-09-16 21:08:06 +00003856 ie->target_cmd = (ie->target_cmd &
bellard2ab83ea2003-06-15 19:56:46 +00003857 ~(TARGET_IOC_SIZEMASK << TARGET_IOC_SIZESHIFT)) |
3858 (size << TARGET_IOC_SIZESHIFT);
3859 }
thsb92c47c2007-11-01 00:07:38 +00003860
3861 /* Build target_to_host_errno_table[] table from
3862 * host_to_target_errno_table[]. */
3863 for (i=0; i < ERRNO_TABLE_SIZE; i++)
3864 target_to_host_errno_table[host_to_target_errno_table[i]] = i;
3865
bellard2ab83ea2003-06-15 19:56:46 +00003866 /* automatic consistency check if same arch */
balrog872ea0c2008-09-21 02:31:19 +00003867#if (defined(__i386__) && defined(TARGET_I386) && defined(TARGET_ABI32)) || \
3868 (defined(__x86_64__) && defined(TARGET_X86_64))
3869 if (unlikely(ie->target_cmd != ie->host_cmd)) {
3870 fprintf(stderr, "ERROR: ioctl(%s): target=0x%x host=0x%x\n",
3871 ie->name, ie->target_cmd, ie->host_cmd);
bellard2ab83ea2003-06-15 19:56:46 +00003872 }
3873#endif
3874 ie++;
3875 }
bellard31e31b82003-02-18 22:55:36 +00003876}
bellardc573ff62004-01-04 15:51:36 +00003877
blueswir1992f48a2007-10-14 16:27:31 +00003878#if TARGET_ABI_BITS == 32
pbrookce4defa2006-02-09 16:49:55 +00003879static inline uint64_t target_offset64(uint32_t word0, uint32_t word1)
3880{
thsaf325d32008-06-10 15:29:15 +00003881#ifdef TARGET_WORDS_BIGENDIAN
pbrookce4defa2006-02-09 16:49:55 +00003882 return ((uint64_t)word0 << 32) | word1;
3883#else
3884 return ((uint64_t)word1 << 32) | word0;
3885#endif
3886}
blueswir1992f48a2007-10-14 16:27:31 +00003887#else /* TARGET_ABI_BITS == 32 */
j_mayer32407102007-09-26 23:01:49 +00003888static inline uint64_t target_offset64(uint64_t word0, uint64_t word1)
3889{
3890 return word0;
3891}
blueswir1992f48a2007-10-14 16:27:31 +00003892#endif /* TARGET_ABI_BITS != 32 */
pbrookce4defa2006-02-09 16:49:55 +00003893
3894#ifdef TARGET_NR_truncate64
blueswir1992f48a2007-10-14 16:27:31 +00003895static inline abi_long target_truncate64(void *cpu_env, const char *arg1,
3896 abi_long arg2,
3897 abi_long arg3,
3898 abi_long arg4)
pbrookce4defa2006-02-09 16:49:55 +00003899{
3900#ifdef TARGET_ARM
3901 if (((CPUARMState *)cpu_env)->eabi)
3902 {
3903 arg2 = arg3;
3904 arg3 = arg4;
3905 }
3906#endif
3907 return get_errno(truncate64(arg1, target_offset64(arg2, arg3)));
3908}
3909#endif
3910
3911#ifdef TARGET_NR_ftruncate64
blueswir1992f48a2007-10-14 16:27:31 +00003912static inline abi_long target_ftruncate64(void *cpu_env, abi_long arg1,
3913 abi_long arg2,
3914 abi_long arg3,
3915 abi_long arg4)
pbrookce4defa2006-02-09 16:49:55 +00003916{
3917#ifdef TARGET_ARM
3918 if (((CPUARMState *)cpu_env)->eabi)
3919 {
3920 arg2 = arg3;
3921 arg3 = arg4;
3922 }
3923#endif
3924 return get_errno(ftruncate64(arg1, target_offset64(arg2, arg3)));
3925}
3926#endif
3927
bellard579a97f2007-11-11 14:26:47 +00003928static inline abi_long target_to_host_timespec(struct timespec *host_ts,
3929 abi_ulong target_addr)
pbrook53a59602006-03-25 19:31:22 +00003930{
3931 struct target_timespec *target_ts;
3932
bellard579a97f2007-11-11 14:26:47 +00003933 if (!lock_user_struct(VERIFY_READ, target_ts, target_addr, 1))
3934 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00003935 host_ts->tv_sec = tswapl(target_ts->tv_sec);
3936 host_ts->tv_nsec = tswapl(target_ts->tv_nsec);
3937 unlock_user_struct(target_ts, target_addr, 0);
bellardb255bfa2008-05-10 21:51:02 +00003938 return 0;
pbrook53a59602006-03-25 19:31:22 +00003939}
3940
bellard579a97f2007-11-11 14:26:47 +00003941static inline abi_long host_to_target_timespec(abi_ulong target_addr,
3942 struct timespec *host_ts)
pbrook53a59602006-03-25 19:31:22 +00003943{
3944 struct target_timespec *target_ts;
3945
bellard579a97f2007-11-11 14:26:47 +00003946 if (!lock_user_struct(VERIFY_WRITE, target_ts, target_addr, 0))
3947 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00003948 target_ts->tv_sec = tswapl(host_ts->tv_sec);
3949 target_ts->tv_nsec = tswapl(host_ts->tv_nsec);
3950 unlock_user_struct(target_ts, target_addr, 1);
bellardb255bfa2008-05-10 21:51:02 +00003951 return 0;
pbrook53a59602006-03-25 19:31:22 +00003952}
3953
aurel329d33b762009-04-08 23:07:05 +00003954#if defined(TARGET_NR_stat64) || defined(TARGET_NR_newfstatat)
balrog6a24a772008-09-20 02:23:36 +00003955static inline abi_long host_to_target_stat64(void *cpu_env,
3956 abi_ulong target_addr,
3957 struct stat *host_st)
3958{
3959#ifdef TARGET_ARM
3960 if (((CPUARMState *)cpu_env)->eabi) {
3961 struct target_eabi_stat64 *target_st;
3962
3963 if (!lock_user_struct(VERIFY_WRITE, target_st, target_addr, 0))
3964 return -TARGET_EFAULT;
3965 memset(target_st, 0, sizeof(struct target_eabi_stat64));
3966 __put_user(host_st->st_dev, &target_st->st_dev);
3967 __put_user(host_st->st_ino, &target_st->st_ino);
3968#ifdef TARGET_STAT64_HAS_BROKEN_ST_INO
3969 __put_user(host_st->st_ino, &target_st->__st_ino);
3970#endif
3971 __put_user(host_st->st_mode, &target_st->st_mode);
3972 __put_user(host_st->st_nlink, &target_st->st_nlink);
3973 __put_user(host_st->st_uid, &target_st->st_uid);
3974 __put_user(host_st->st_gid, &target_st->st_gid);
3975 __put_user(host_st->st_rdev, &target_st->st_rdev);
3976 __put_user(host_st->st_size, &target_st->st_size);
3977 __put_user(host_st->st_blksize, &target_st->st_blksize);
3978 __put_user(host_st->st_blocks, &target_st->st_blocks);
3979 __put_user(host_st->st_atime, &target_st->target_st_atime);
3980 __put_user(host_st->st_mtime, &target_st->target_st_mtime);
3981 __put_user(host_st->st_ctime, &target_st->target_st_ctime);
3982 unlock_user_struct(target_st, target_addr, 1);
3983 } else
3984#endif
3985 {
aurel329d33b762009-04-08 23:07:05 +00003986#if TARGET_LONG_BITS == 64
3987 struct target_stat *target_st;
3988#else
balrog6a24a772008-09-20 02:23:36 +00003989 struct target_stat64 *target_st;
aurel329d33b762009-04-08 23:07:05 +00003990#endif
balrog6a24a772008-09-20 02:23:36 +00003991
3992 if (!lock_user_struct(VERIFY_WRITE, target_st, target_addr, 0))
3993 return -TARGET_EFAULT;
aurel329d33b762009-04-08 23:07:05 +00003994 memset(target_st, 0, sizeof(*target_st));
balrog6a24a772008-09-20 02:23:36 +00003995 __put_user(host_st->st_dev, &target_st->st_dev);
3996 __put_user(host_st->st_ino, &target_st->st_ino);
3997#ifdef TARGET_STAT64_HAS_BROKEN_ST_INO
3998 __put_user(host_st->st_ino, &target_st->__st_ino);
3999#endif
4000 __put_user(host_st->st_mode, &target_st->st_mode);
4001 __put_user(host_st->st_nlink, &target_st->st_nlink);
4002 __put_user(host_st->st_uid, &target_st->st_uid);
4003 __put_user(host_st->st_gid, &target_st->st_gid);
4004 __put_user(host_st->st_rdev, &target_st->st_rdev);
4005 /* XXX: better use of kernel struct */
4006 __put_user(host_st->st_size, &target_st->st_size);
4007 __put_user(host_st->st_blksize, &target_st->st_blksize);
4008 __put_user(host_st->st_blocks, &target_st->st_blocks);
4009 __put_user(host_st->st_atime, &target_st->target_st_atime);
4010 __put_user(host_st->st_mtime, &target_st->target_st_mtime);
4011 __put_user(host_st->st_ctime, &target_st->target_st_ctime);
4012 unlock_user_struct(target_st, target_addr, 1);
4013 }
4014
4015 return 0;
4016}
4017#endif
4018
pbrookbd0c5662008-05-29 14:34:11 +00004019#if defined(USE_NPTL)
4020/* ??? Using host futex calls even when target atomic operations
4021 are not really atomic probably breaks things. However implementing
4022 futexes locally would make futexes shared between multiple processes
4023 tricky. However they're probably useless because guest atomic
4024 operations won't work either. */
blueswir18fcd3692008-08-17 20:26:25 +00004025static int do_futex(target_ulong uaddr, int op, int val, target_ulong timeout,
4026 target_ulong uaddr2, int val3)
pbrookbd0c5662008-05-29 14:34:11 +00004027{
4028 struct timespec ts, *pts;
4029
4030 /* ??? We assume FUTEX_* constants are the same on both host
4031 and target. */
Martin Mohringa29ccd62009-05-04 21:34:56 +03004032#ifdef FUTEX_CMD_MASK
4033 switch ((op&FUTEX_CMD_MASK)) {
4034#else
pbrookbd0c5662008-05-29 14:34:11 +00004035 switch (op) {
Martin Mohringa29ccd62009-05-04 21:34:56 +03004036#endif
pbrookbd0c5662008-05-29 14:34:11 +00004037 case FUTEX_WAIT:
4038 if (timeout) {
4039 pts = &ts;
4040 target_to_host_timespec(pts, timeout);
4041 } else {
4042 pts = NULL;
4043 }
Martin Mohringa29ccd62009-05-04 21:34:56 +03004044 return get_errno(sys_futex(g2h(uaddr), op, tswap32(val),
pbrookbd0c5662008-05-29 14:34:11 +00004045 pts, NULL, 0));
4046 case FUTEX_WAKE:
Martin Mohringa29ccd62009-05-04 21:34:56 +03004047 return get_errno(sys_futex(g2h(uaddr), op, val, NULL, NULL, 0));
Riku Voipioc4d23022009-05-28 12:13:41 +03004048 case FUTEX_WAKE_OP:
4049 return get_errno(sys_futex(g2h(uaddr), op, val, NULL, g2h(uaddr2), val3 ));
pbrookbd0c5662008-05-29 14:34:11 +00004050 case FUTEX_FD:
Martin Mohringa29ccd62009-05-04 21:34:56 +03004051 return get_errno(sys_futex(g2h(uaddr), op, val, NULL, NULL, 0));
pbrookbd0c5662008-05-29 14:34:11 +00004052 case FUTEX_REQUEUE:
Martin Mohringa29ccd62009-05-04 21:34:56 +03004053 return get_errno(sys_futex(g2h(uaddr), op, val,
pbrookbd0c5662008-05-29 14:34:11 +00004054 NULL, g2h(uaddr2), 0));
4055 case FUTEX_CMP_REQUEUE:
Martin Mohringa29ccd62009-05-04 21:34:56 +03004056 return get_errno(sys_futex(g2h(uaddr), op, val,
pbrookbd0c5662008-05-29 14:34:11 +00004057 NULL, g2h(uaddr2), tswap32(val3)));
4058 default:
4059 return -TARGET_ENOSYS;
4060 }
4061}
4062#endif
4063
pbrook1d9d8b52009-04-16 15:17:02 +00004064/* Map host to target signal numbers for the wait family of syscalls.
4065 Assume all other status bits are the same. */
4066static int host_to_target_waitstatus(int status)
4067{
4068 if (WIFSIGNALED(status)) {
4069 return host_to_target_signal(WTERMSIG(status)) | (status & ~0x7f);
4070 }
4071 if (WIFSTOPPED(status)) {
4072 return (host_to_target_signal(WSTOPSIG(status)) << 8)
4073 | (status & 0xff);
4074 }
4075 return status;
4076}
4077
pbrooka745ec62008-05-06 15:36:17 +00004078int get_osversion(void)
4079{
4080 static int osversion;
4081 struct new_utsname buf;
4082 const char *s;
4083 int i, n, tmp;
4084 if (osversion)
4085 return osversion;
4086 if (qemu_uname_release && *qemu_uname_release) {
4087 s = qemu_uname_release;
4088 } else {
4089 if (sys_uname(&buf))
4090 return 0;
4091 s = buf.release;
4092 }
4093 tmp = 0;
4094 for (i = 0; i < 3; i++) {
4095 n = 0;
4096 while (*s >= '0' && *s <= '9') {
4097 n *= 10;
4098 n += *s - '0';
4099 s++;
4100 }
4101 tmp = (tmp << 8) + n;
4102 if (*s == '.')
4103 s++;
4104 }
4105 osversion = tmp;
4106 return osversion;
4107}
4108
ths0da46a62007-10-20 20:23:07 +00004109/* do_syscall() should always have a single exit point at the end so
4110 that actions, such as logging of syscall results, can be performed.
4111 All errnos that do_syscall() returns must be -TARGET_<errcode>. */
blueswir1992f48a2007-10-14 16:27:31 +00004112abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
4113 abi_long arg2, abi_long arg3, abi_long arg4,
4114 abi_long arg5, abi_long arg6)
bellard31e31b82003-02-18 22:55:36 +00004115{
blueswir1992f48a2007-10-14 16:27:31 +00004116 abi_long ret;
bellard31e31b82003-02-18 22:55:36 +00004117 struct stat st;
bellard56c8f682005-11-28 22:28:41 +00004118 struct statfs stfs;
pbrook53a59602006-03-25 19:31:22 +00004119 void *p;
ths3b46e622007-09-17 08:09:54 +00004120
bellard72f03902003-02-18 23:33:18 +00004121#ifdef DEBUG
bellardc573ff62004-01-04 15:51:36 +00004122 gemu_log("syscall %d", num);
bellard72f03902003-02-18 23:33:18 +00004123#endif
thsb92c47c2007-11-01 00:07:38 +00004124 if(do_strace)
4125 print_syscall(num, arg1, arg2, arg3, arg4, arg5, arg6);
4126
bellard31e31b82003-02-18 22:55:36 +00004127 switch(num) {
4128 case TARGET_NR_exit:
pbrookc2764712009-03-07 15:24:59 +00004129#ifdef USE_NPTL
4130 /* In old applications this may be used to implement _exit(2).
4131 However in threaded applictions it is used for thread termination,
4132 and _exit_group is used for application termination.
4133 Do thread termination if we have more then one thread. */
4134 /* FIXME: This probably breaks if a signal arrives. We should probably
4135 be disabling signals. */
4136 if (first_cpu->next_cpu) {
Nathan Froyd1e9fa732009-06-03 11:33:08 -07004137 TaskState *ts;
pbrookc2764712009-03-07 15:24:59 +00004138 CPUState **lastp;
4139 CPUState *p;
4140
4141 cpu_list_lock();
4142 lastp = &first_cpu;
4143 p = first_cpu;
4144 while (p && p != (CPUState *)cpu_env) {
4145 lastp = &p->next_cpu;
4146 p = p->next_cpu;
4147 }
4148 /* If we didn't find the CPU for this thread then something is
4149 horribly wrong. */
4150 if (!p)
4151 abort();
4152 /* Remove the CPU from the list. */
4153 *lastp = p->next_cpu;
4154 cpu_list_unlock();
Nathan Froyd1e9fa732009-06-03 11:33:08 -07004155 ts = ((CPUState *)cpu_env)->opaque;
pbrookc2764712009-03-07 15:24:59 +00004156 if (ts->child_tidptr) {
4157 put_user_u32(0, ts->child_tidptr);
4158 sys_futex(g2h(ts->child_tidptr), FUTEX_WAKE, INT_MAX,
4159 NULL, NULL, 0);
4160 }
4161 /* TODO: Free CPU state. */
4162 pthread_exit(NULL);
4163 }
4164#endif
Juan Quintela9788c9c2009-07-27 16:13:02 +02004165#ifdef TARGET_GPROF
bellard7d132992003-03-06 23:23:54 +00004166 _mcleanup();
4167#endif
bellarde9009672005-04-26 20:42:36 +00004168 gdb_exit(cpu_env, arg1);
pbrookc2764712009-03-07 15:24:59 +00004169 _exit(arg1);
bellard31e31b82003-02-18 22:55:36 +00004170 ret = 0; /* avoid warning */
4171 break;
4172 case TARGET_NR_read:
aurel3238d840e2009-01-30 19:48:17 +00004173 if (arg3 == 0)
4174 ret = 0;
4175 else {
4176 if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
4177 goto efault;
4178 ret = get_errno(read(arg1, p, arg3));
4179 unlock_user(p, arg2, ret);
4180 }
bellard31e31b82003-02-18 22:55:36 +00004181 break;
4182 case TARGET_NR_write:
bellard579a97f2007-11-11 14:26:47 +00004183 if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
4184 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004185 ret = get_errno(write(arg1, p, arg3));
4186 unlock_user(p, arg2, 0);
bellard31e31b82003-02-18 22:55:36 +00004187 break;
4188 case TARGET_NR_open:
bellard2f619692007-11-16 10:46:05 +00004189 if (!(p = lock_user_string(arg1)))
4190 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004191 ret = get_errno(open(path(p),
bellardffa65c32004-01-04 23:57:22 +00004192 target_to_host_bitmask(arg2, fcntl_flags_tbl),
4193 arg3));
pbrook53a59602006-03-25 19:31:22 +00004194 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004195 break;
ths82424832007-09-24 09:21:55 +00004196#if defined(TARGET_NR_openat) && defined(__NR_openat)
4197 case TARGET_NR_openat:
bellard579a97f2007-11-11 14:26:47 +00004198 if (!(p = lock_user_string(arg2)))
4199 goto efault;
4200 ret = get_errno(sys_openat(arg1,
4201 path(p),
4202 target_to_host_bitmask(arg3, fcntl_flags_tbl),
4203 arg4));
4204 unlock_user(p, arg2, 0);
ths82424832007-09-24 09:21:55 +00004205 break;
4206#endif
bellard31e31b82003-02-18 22:55:36 +00004207 case TARGET_NR_close:
4208 ret = get_errno(close(arg1));
4209 break;
4210 case TARGET_NR_brk:
pbrook53a59602006-03-25 19:31:22 +00004211 ret = do_brk(arg1);
bellard31e31b82003-02-18 22:55:36 +00004212 break;
4213 case TARGET_NR_fork:
pbrookd865bab2008-06-07 22:12:17 +00004214 ret = get_errno(do_fork(cpu_env, SIGCHLD, 0, 0, 0, 0));
bellard31e31b82003-02-18 22:55:36 +00004215 break;
thse5febef2007-04-01 18:31:35 +00004216#ifdef TARGET_NR_waitpid
bellard31e31b82003-02-18 22:55:36 +00004217 case TARGET_NR_waitpid:
4218 {
pbrook53a59602006-03-25 19:31:22 +00004219 int status;
4220 ret = get_errno(waitpid(arg1, &status, arg3));
bellard2f619692007-11-16 10:46:05 +00004221 if (!is_error(ret) && arg2
pbrook1d9d8b52009-04-16 15:17:02 +00004222 && put_user_s32(host_to_target_waitstatus(status), arg2))
bellard2f619692007-11-16 10:46:05 +00004223 goto efault;
bellard31e31b82003-02-18 22:55:36 +00004224 }
4225 break;
thse5febef2007-04-01 18:31:35 +00004226#endif
pbrookf0cbb612008-05-30 18:20:05 +00004227#ifdef TARGET_NR_waitid
4228 case TARGET_NR_waitid:
4229 {
4230 siginfo_t info;
4231 info.si_pid = 0;
4232 ret = get_errno(waitid(arg1, arg2, &info, arg4));
4233 if (!is_error(ret) && arg3 && info.si_pid != 0) {
4234 if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_siginfo_t), 0)))
4235 goto efault;
4236 host_to_target_siginfo(p, &info);
4237 unlock_user(p, arg3, sizeof(target_siginfo_t));
4238 }
4239 }
4240 break;
4241#endif
j_mayer7a3148a2007-04-05 07:13:51 +00004242#ifdef TARGET_NR_creat /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00004243 case TARGET_NR_creat:
bellard579a97f2007-11-11 14:26:47 +00004244 if (!(p = lock_user_string(arg1)))
4245 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004246 ret = get_errno(creat(p, arg2));
4247 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004248 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004249#endif
bellard31e31b82003-02-18 22:55:36 +00004250 case TARGET_NR_link:
pbrook53a59602006-03-25 19:31:22 +00004251 {
4252 void * p2;
4253 p = lock_user_string(arg1);
4254 p2 = lock_user_string(arg2);
bellard579a97f2007-11-11 14:26:47 +00004255 if (!p || !p2)
4256 ret = -TARGET_EFAULT;
4257 else
4258 ret = get_errno(link(p, p2));
pbrook53a59602006-03-25 19:31:22 +00004259 unlock_user(p2, arg2, 0);
4260 unlock_user(p, arg1, 0);
4261 }
bellard31e31b82003-02-18 22:55:36 +00004262 break;
ths64f0ce42007-09-24 09:25:06 +00004263#if defined(TARGET_NR_linkat) && defined(__NR_linkat)
4264 case TARGET_NR_linkat:
ths64f0ce42007-09-24 09:25:06 +00004265 {
4266 void * p2 = NULL;
bellard579a97f2007-11-11 14:26:47 +00004267 if (!arg2 || !arg4)
4268 goto efault;
ths64f0ce42007-09-24 09:25:06 +00004269 p = lock_user_string(arg2);
4270 p2 = lock_user_string(arg4);
bellard579a97f2007-11-11 14:26:47 +00004271 if (!p || !p2)
ths0da46a62007-10-20 20:23:07 +00004272 ret = -TARGET_EFAULT;
ths64f0ce42007-09-24 09:25:06 +00004273 else
4274 ret = get_errno(sys_linkat(arg1, p, arg3, p2, arg5));
bellard579a97f2007-11-11 14:26:47 +00004275 unlock_user(p, arg2, 0);
4276 unlock_user(p2, arg4, 0);
ths64f0ce42007-09-24 09:25:06 +00004277 }
4278 break;
4279#endif
bellard31e31b82003-02-18 22:55:36 +00004280 case TARGET_NR_unlink:
bellard579a97f2007-11-11 14:26:47 +00004281 if (!(p = lock_user_string(arg1)))
4282 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004283 ret = get_errno(unlink(p));
4284 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004285 break;
ths8170f562007-09-24 09:24:11 +00004286#if defined(TARGET_NR_unlinkat) && defined(__NR_unlinkat)
4287 case TARGET_NR_unlinkat:
bellard579a97f2007-11-11 14:26:47 +00004288 if (!(p = lock_user_string(arg2)))
4289 goto efault;
4290 ret = get_errno(sys_unlinkat(arg1, p, arg3));
4291 unlock_user(p, arg2, 0);
balroged494d82007-12-11 23:23:52 +00004292 break;
balrogb7d35e62007-12-12 00:40:24 +00004293#endif
bellard31e31b82003-02-18 22:55:36 +00004294 case TARGET_NR_execve:
bellard7854b052003-03-29 17:22:23 +00004295 {
4296 char **argp, **envp;
bellardf7341ff2003-03-30 21:00:25 +00004297 int argc, envc;
blueswir1992f48a2007-10-14 16:27:31 +00004298 abi_ulong gp;
4299 abi_ulong guest_argp;
4300 abi_ulong guest_envp;
4301 abi_ulong addr;
bellard7854b052003-03-29 17:22:23 +00004302 char **q;
4303
bellardf7341ff2003-03-30 21:00:25 +00004304 argc = 0;
pbrook53a59602006-03-25 19:31:22 +00004305 guest_argp = arg2;
pbrookda94d262008-05-30 18:24:00 +00004306 for (gp = guest_argp; gp; gp += sizeof(abi_ulong)) {
ths03aa1972007-12-02 06:28:08 +00004307 if (get_user_ual(addr, gp))
bellard2f619692007-11-16 10:46:05 +00004308 goto efault;
ths03aa1972007-12-02 06:28:08 +00004309 if (!addr)
bellard2f619692007-11-16 10:46:05 +00004310 break;
bellard7854b052003-03-29 17:22:23 +00004311 argc++;
bellard2f619692007-11-16 10:46:05 +00004312 }
bellardf7341ff2003-03-30 21:00:25 +00004313 envc = 0;
pbrook53a59602006-03-25 19:31:22 +00004314 guest_envp = arg3;
pbrookda94d262008-05-30 18:24:00 +00004315 for (gp = guest_envp; gp; gp += sizeof(abi_ulong)) {
ths03aa1972007-12-02 06:28:08 +00004316 if (get_user_ual(addr, gp))
bellard2f619692007-11-16 10:46:05 +00004317 goto efault;
ths03aa1972007-12-02 06:28:08 +00004318 if (!addr)
bellard2f619692007-11-16 10:46:05 +00004319 break;
bellard7854b052003-03-29 17:22:23 +00004320 envc++;
bellard2f619692007-11-16 10:46:05 +00004321 }
bellard7854b052003-03-29 17:22:23 +00004322
bellardf7341ff2003-03-30 21:00:25 +00004323 argp = alloca((argc + 1) * sizeof(void *));
4324 envp = alloca((envc + 1) * sizeof(void *));
bellard7854b052003-03-29 17:22:23 +00004325
pbrookda94d262008-05-30 18:24:00 +00004326 for (gp = guest_argp, q = argp; gp;
blueswir1992f48a2007-10-14 16:27:31 +00004327 gp += sizeof(abi_ulong), q++) {
bellard2f619692007-11-16 10:46:05 +00004328 if (get_user_ual(addr, gp))
4329 goto execve_efault;
pbrook53a59602006-03-25 19:31:22 +00004330 if (!addr)
4331 break;
bellard2f619692007-11-16 10:46:05 +00004332 if (!(*q = lock_user_string(addr)))
4333 goto execve_efault;
pbrook53a59602006-03-25 19:31:22 +00004334 }
bellardf7341ff2003-03-30 21:00:25 +00004335 *q = NULL;
4336
pbrookda94d262008-05-30 18:24:00 +00004337 for (gp = guest_envp, q = envp; gp;
blueswir1992f48a2007-10-14 16:27:31 +00004338 gp += sizeof(abi_ulong), q++) {
bellard2f619692007-11-16 10:46:05 +00004339 if (get_user_ual(addr, gp))
4340 goto execve_efault;
pbrook53a59602006-03-25 19:31:22 +00004341 if (!addr)
4342 break;
bellard2f619692007-11-16 10:46:05 +00004343 if (!(*q = lock_user_string(addr)))
4344 goto execve_efault;
pbrook53a59602006-03-25 19:31:22 +00004345 }
bellardf7341ff2003-03-30 21:00:25 +00004346 *q = NULL;
bellard7854b052003-03-29 17:22:23 +00004347
bellard2f619692007-11-16 10:46:05 +00004348 if (!(p = lock_user_string(arg1)))
4349 goto execve_efault;
pbrook53a59602006-03-25 19:31:22 +00004350 ret = get_errno(execve(p, argp, envp));
4351 unlock_user(p, arg1, 0);
4352
bellard2f619692007-11-16 10:46:05 +00004353 goto execve_end;
4354
4355 execve_efault:
4356 ret = -TARGET_EFAULT;
4357
4358 execve_end:
pbrook53a59602006-03-25 19:31:22 +00004359 for (gp = guest_argp, q = argp; *q;
blueswir1992f48a2007-10-14 16:27:31 +00004360 gp += sizeof(abi_ulong), q++) {
bellard2f619692007-11-16 10:46:05 +00004361 if (get_user_ual(addr, gp)
4362 || !addr)
4363 break;
pbrook53a59602006-03-25 19:31:22 +00004364 unlock_user(*q, addr, 0);
4365 }
4366 for (gp = guest_envp, q = envp; *q;
blueswir1992f48a2007-10-14 16:27:31 +00004367 gp += sizeof(abi_ulong), q++) {
bellard2f619692007-11-16 10:46:05 +00004368 if (get_user_ual(addr, gp)
4369 || !addr)
4370 break;
pbrook53a59602006-03-25 19:31:22 +00004371 unlock_user(*q, addr, 0);
4372 }
bellard7854b052003-03-29 17:22:23 +00004373 }
bellard31e31b82003-02-18 22:55:36 +00004374 break;
4375 case TARGET_NR_chdir:
bellard579a97f2007-11-11 14:26:47 +00004376 if (!(p = lock_user_string(arg1)))
4377 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004378 ret = get_errno(chdir(p));
4379 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004380 break;
bellarda315a142005-01-30 22:59:18 +00004381#ifdef TARGET_NR_time
bellard31e31b82003-02-18 22:55:36 +00004382 case TARGET_NR_time:
4383 {
pbrook53a59602006-03-25 19:31:22 +00004384 time_t host_time;
4385 ret = get_errno(time(&host_time));
bellard2f619692007-11-16 10:46:05 +00004386 if (!is_error(ret)
4387 && arg1
4388 && put_user_sal(host_time, arg1))
4389 goto efault;
bellard31e31b82003-02-18 22:55:36 +00004390 }
4391 break;
bellarda315a142005-01-30 22:59:18 +00004392#endif
bellard31e31b82003-02-18 22:55:36 +00004393 case TARGET_NR_mknod:
bellard579a97f2007-11-11 14:26:47 +00004394 if (!(p = lock_user_string(arg1)))
4395 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004396 ret = get_errno(mknod(p, arg2, arg3));
4397 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004398 break;
ths75ac37a2007-09-24 09:23:05 +00004399#if defined(TARGET_NR_mknodat) && defined(__NR_mknodat)
4400 case TARGET_NR_mknodat:
bellard579a97f2007-11-11 14:26:47 +00004401 if (!(p = lock_user_string(arg2)))
4402 goto efault;
4403 ret = get_errno(sys_mknodat(arg1, p, arg3, arg4));
4404 unlock_user(p, arg2, 0);
ths75ac37a2007-09-24 09:23:05 +00004405 break;
4406#endif
bellard31e31b82003-02-18 22:55:36 +00004407 case TARGET_NR_chmod:
bellard579a97f2007-11-11 14:26:47 +00004408 if (!(p = lock_user_string(arg1)))
4409 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004410 ret = get_errno(chmod(p, arg2));
4411 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004412 break;
bellardebc05482003-09-30 21:08:41 +00004413#ifdef TARGET_NR_break
bellard31e31b82003-02-18 22:55:36 +00004414 case TARGET_NR_break:
4415 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004416#endif
4417#ifdef TARGET_NR_oldstat
bellard31e31b82003-02-18 22:55:36 +00004418 case TARGET_NR_oldstat:
4419 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004420#endif
bellard31e31b82003-02-18 22:55:36 +00004421 case TARGET_NR_lseek:
4422 ret = get_errno(lseek(arg1, arg2, arg3));
4423 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004424#ifdef TARGET_NR_getxpid
4425 case TARGET_NR_getxpid:
4426#else
bellard31e31b82003-02-18 22:55:36 +00004427 case TARGET_NR_getpid:
j_mayer7a3148a2007-04-05 07:13:51 +00004428#endif
bellard31e31b82003-02-18 22:55:36 +00004429 ret = get_errno(getpid());
4430 break;
4431 case TARGET_NR_mount:
ths80265912007-02-17 22:25:41 +00004432 {
4433 /* need to look at the data field */
4434 void *p2, *p3;
4435 p = lock_user_string(arg1);
4436 p2 = lock_user_string(arg2);
4437 p3 = lock_user_string(arg3);
bellard579a97f2007-11-11 14:26:47 +00004438 if (!p || !p2 || !p3)
4439 ret = -TARGET_EFAULT;
4440 else
4441 /* FIXME - arg5 should be locked, but it isn't clear how to
4442 * do that since it's not guaranteed to be a NULL-terminated
4443 * string.
4444 */
4445 ret = get_errno(mount(p, p2, p3, (unsigned long)arg4, g2h(arg5)));
4446 unlock_user(p, arg1, 0);
4447 unlock_user(p2, arg2, 0);
4448 unlock_user(p3, arg3, 0);
ths80265912007-02-17 22:25:41 +00004449 break;
4450 }
thse5febef2007-04-01 18:31:35 +00004451#ifdef TARGET_NR_umount
bellard31e31b82003-02-18 22:55:36 +00004452 case TARGET_NR_umount:
bellard579a97f2007-11-11 14:26:47 +00004453 if (!(p = lock_user_string(arg1)))
4454 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004455 ret = get_errno(umount(p));
4456 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004457 break;
thse5febef2007-04-01 18:31:35 +00004458#endif
j_mayer7a3148a2007-04-05 07:13:51 +00004459#ifdef TARGET_NR_stime /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00004460 case TARGET_NR_stime:
4461 {
pbrook53a59602006-03-25 19:31:22 +00004462 time_t host_time;
bellard2f619692007-11-16 10:46:05 +00004463 if (get_user_sal(host_time, arg1))
4464 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004465 ret = get_errno(stime(&host_time));
bellard31e31b82003-02-18 22:55:36 +00004466 }
4467 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004468#endif
bellard31e31b82003-02-18 22:55:36 +00004469 case TARGET_NR_ptrace:
4470 goto unimplemented;
j_mayer7a3148a2007-04-05 07:13:51 +00004471#ifdef TARGET_NR_alarm /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00004472 case TARGET_NR_alarm:
4473 ret = alarm(arg1);
4474 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004475#endif
bellardebc05482003-09-30 21:08:41 +00004476#ifdef TARGET_NR_oldfstat
bellard31e31b82003-02-18 22:55:36 +00004477 case TARGET_NR_oldfstat:
4478 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004479#endif
j_mayer7a3148a2007-04-05 07:13:51 +00004480#ifdef TARGET_NR_pause /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00004481 case TARGET_NR_pause:
4482 ret = get_errno(pause());
4483 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004484#endif
thse5febef2007-04-01 18:31:35 +00004485#ifdef TARGET_NR_utime
bellard31e31b82003-02-18 22:55:36 +00004486 case TARGET_NR_utime:
bellardebc05482003-09-30 21:08:41 +00004487 {
pbrook53a59602006-03-25 19:31:22 +00004488 struct utimbuf tbuf, *host_tbuf;
4489 struct target_utimbuf *target_tbuf;
4490 if (arg2) {
bellard579a97f2007-11-11 14:26:47 +00004491 if (!lock_user_struct(VERIFY_READ, target_tbuf, arg2, 1))
4492 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004493 tbuf.actime = tswapl(target_tbuf->actime);
4494 tbuf.modtime = tswapl(target_tbuf->modtime);
4495 unlock_user_struct(target_tbuf, arg2, 0);
4496 host_tbuf = &tbuf;
bellardf72e8ff2004-05-03 19:23:07 +00004497 } else {
pbrook53a59602006-03-25 19:31:22 +00004498 host_tbuf = NULL;
bellardf72e8ff2004-05-03 19:23:07 +00004499 }
bellard579a97f2007-11-11 14:26:47 +00004500 if (!(p = lock_user_string(arg1)))
4501 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004502 ret = get_errno(utime(p, host_tbuf));
4503 unlock_user(p, arg1, 0);
bellardebc05482003-09-30 21:08:41 +00004504 }
4505 break;
thse5febef2007-04-01 18:31:35 +00004506#endif
bellard978a66f2004-12-06 22:58:05 +00004507 case TARGET_NR_utimes:
4508 {
bellard978a66f2004-12-06 22:58:05 +00004509 struct timeval *tvp, tv[2];
pbrook53a59602006-03-25 19:31:22 +00004510 if (arg2) {
ths788f5ec2007-12-09 02:37:05 +00004511 if (copy_from_user_timeval(&tv[0], arg2)
4512 || copy_from_user_timeval(&tv[1],
4513 arg2 + sizeof(struct target_timeval)))
4514 goto efault;
bellard978a66f2004-12-06 22:58:05 +00004515 tvp = tv;
4516 } else {
4517 tvp = NULL;
4518 }
bellard579a97f2007-11-11 14:26:47 +00004519 if (!(p = lock_user_string(arg1)))
4520 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004521 ret = get_errno(utimes(p, tvp));
4522 unlock_user(p, arg1, 0);
bellard978a66f2004-12-06 22:58:05 +00004523 }
4524 break;
balrogac8a6552008-09-20 02:25:39 +00004525#if defined(TARGET_NR_futimesat) && defined(__NR_futimesat)
4526 case TARGET_NR_futimesat:
4527 {
4528 struct timeval *tvp, tv[2];
4529 if (arg3) {
4530 if (copy_from_user_timeval(&tv[0], arg3)
4531 || copy_from_user_timeval(&tv[1],
4532 arg3 + sizeof(struct target_timeval)))
4533 goto efault;
4534 tvp = tv;
4535 } else {
4536 tvp = NULL;
4537 }
4538 if (!(p = lock_user_string(arg2)))
4539 goto efault;
4540 ret = get_errno(sys_futimesat(arg1, path(p), tvp));
4541 unlock_user(p, arg2, 0);
4542 }
4543 break;
4544#endif
bellardebc05482003-09-30 21:08:41 +00004545#ifdef TARGET_NR_stty
bellard31e31b82003-02-18 22:55:36 +00004546 case TARGET_NR_stty:
4547 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004548#endif
4549#ifdef TARGET_NR_gtty
bellard31e31b82003-02-18 22:55:36 +00004550 case TARGET_NR_gtty:
4551 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004552#endif
bellard31e31b82003-02-18 22:55:36 +00004553 case TARGET_NR_access:
bellard579a97f2007-11-11 14:26:47 +00004554 if (!(p = lock_user_string(arg1)))
4555 goto efault;
Ulrich Hecht719f9082009-07-03 17:09:29 +02004556 ret = get_errno(access(path(p), arg2));
pbrook53a59602006-03-25 19:31:22 +00004557 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004558 break;
ths92a34c12007-09-24 09:27:49 +00004559#if defined(TARGET_NR_faccessat) && defined(__NR_faccessat)
4560 case TARGET_NR_faccessat:
bellard579a97f2007-11-11 14:26:47 +00004561 if (!(p = lock_user_string(arg2)))
4562 goto efault;
aurel32465c9f02009-04-19 08:52:17 +00004563 ret = get_errno(sys_faccessat(arg1, p, arg3));
bellard579a97f2007-11-11 14:26:47 +00004564 unlock_user(p, arg2, 0);
ths92a34c12007-09-24 09:27:49 +00004565 break;
4566#endif
j_mayer7a3148a2007-04-05 07:13:51 +00004567#ifdef TARGET_NR_nice /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00004568 case TARGET_NR_nice:
4569 ret = get_errno(nice(arg1));
4570 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004571#endif
bellardebc05482003-09-30 21:08:41 +00004572#ifdef TARGET_NR_ftime
bellard31e31b82003-02-18 22:55:36 +00004573 case TARGET_NR_ftime:
4574 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004575#endif
bellard31e31b82003-02-18 22:55:36 +00004576 case TARGET_NR_sync:
bellard04369ff2003-03-20 22:33:23 +00004577 sync();
4578 ret = 0;
bellard31e31b82003-02-18 22:55:36 +00004579 break;
4580 case TARGET_NR_kill:
pbrook4cb05962008-05-30 18:05:19 +00004581 ret = get_errno(kill(arg1, target_to_host_signal(arg2)));
bellard31e31b82003-02-18 22:55:36 +00004582 break;
4583 case TARGET_NR_rename:
pbrook53a59602006-03-25 19:31:22 +00004584 {
4585 void *p2;
4586 p = lock_user_string(arg1);
4587 p2 = lock_user_string(arg2);
bellard579a97f2007-11-11 14:26:47 +00004588 if (!p || !p2)
4589 ret = -TARGET_EFAULT;
4590 else
4591 ret = get_errno(rename(p, p2));
pbrook53a59602006-03-25 19:31:22 +00004592 unlock_user(p2, arg2, 0);
4593 unlock_user(p, arg1, 0);
4594 }
bellard31e31b82003-02-18 22:55:36 +00004595 break;
ths722183f2007-09-24 09:24:37 +00004596#if defined(TARGET_NR_renameat) && defined(__NR_renameat)
4597 case TARGET_NR_renameat:
ths722183f2007-09-24 09:24:37 +00004598 {
bellard579a97f2007-11-11 14:26:47 +00004599 void *p2;
ths722183f2007-09-24 09:24:37 +00004600 p = lock_user_string(arg2);
4601 p2 = lock_user_string(arg4);
bellard579a97f2007-11-11 14:26:47 +00004602 if (!p || !p2)
ths0da46a62007-10-20 20:23:07 +00004603 ret = -TARGET_EFAULT;
ths722183f2007-09-24 09:24:37 +00004604 else
4605 ret = get_errno(sys_renameat(arg1, p, arg3, p2));
bellard579a97f2007-11-11 14:26:47 +00004606 unlock_user(p2, arg4, 0);
4607 unlock_user(p, arg2, 0);
ths722183f2007-09-24 09:24:37 +00004608 }
4609 break;
4610#endif
bellard31e31b82003-02-18 22:55:36 +00004611 case TARGET_NR_mkdir:
bellard579a97f2007-11-11 14:26:47 +00004612 if (!(p = lock_user_string(arg1)))
4613 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004614 ret = get_errno(mkdir(p, arg2));
4615 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004616 break;
ths4472ad02007-09-24 09:22:32 +00004617#if defined(TARGET_NR_mkdirat) && defined(__NR_mkdirat)
4618 case TARGET_NR_mkdirat:
bellard579a97f2007-11-11 14:26:47 +00004619 if (!(p = lock_user_string(arg2)))
4620 goto efault;
4621 ret = get_errno(sys_mkdirat(arg1, p, arg3));
4622 unlock_user(p, arg2, 0);
ths4472ad02007-09-24 09:22:32 +00004623 break;
4624#endif
bellard31e31b82003-02-18 22:55:36 +00004625 case TARGET_NR_rmdir:
bellard579a97f2007-11-11 14:26:47 +00004626 if (!(p = lock_user_string(arg1)))
4627 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004628 ret = get_errno(rmdir(p));
4629 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004630 break;
4631 case TARGET_NR_dup:
4632 ret = get_errno(dup(arg1));
4633 break;
4634 case TARGET_NR_pipe:
Riku Voipio099d6b02009-05-05 12:10:04 +03004635 ret = do_pipe(cpu_env, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004636 break;
Riku Voipio099d6b02009-05-05 12:10:04 +03004637#ifdef TARGET_NR_pipe2
4638 case TARGET_NR_pipe2:
4639 ret = do_pipe(cpu_env, arg1, arg2);
4640 break;
4641#endif
bellard31e31b82003-02-18 22:55:36 +00004642 case TARGET_NR_times:
bellard32f36bc2003-03-30 21:29:48 +00004643 {
pbrook53a59602006-03-25 19:31:22 +00004644 struct target_tms *tmsp;
bellard32f36bc2003-03-30 21:29:48 +00004645 struct tms tms;
4646 ret = get_errno(times(&tms));
pbrook53a59602006-03-25 19:31:22 +00004647 if (arg1) {
bellard579a97f2007-11-11 14:26:47 +00004648 tmsp = lock_user(VERIFY_WRITE, arg1, sizeof(struct target_tms), 0);
4649 if (!tmsp)
4650 goto efault;
bellardc596ed12003-07-13 17:32:31 +00004651 tmsp->tms_utime = tswapl(host_to_target_clock_t(tms.tms_utime));
4652 tmsp->tms_stime = tswapl(host_to_target_clock_t(tms.tms_stime));
4653 tmsp->tms_cutime = tswapl(host_to_target_clock_t(tms.tms_cutime));
4654 tmsp->tms_cstime = tswapl(host_to_target_clock_t(tms.tms_cstime));
bellard32f36bc2003-03-30 21:29:48 +00004655 }
bellardc596ed12003-07-13 17:32:31 +00004656 if (!is_error(ret))
4657 ret = host_to_target_clock_t(ret);
bellard32f36bc2003-03-30 21:29:48 +00004658 }
4659 break;
bellardebc05482003-09-30 21:08:41 +00004660#ifdef TARGET_NR_prof
bellard31e31b82003-02-18 22:55:36 +00004661 case TARGET_NR_prof:
4662 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004663#endif
thse5febef2007-04-01 18:31:35 +00004664#ifdef TARGET_NR_signal
bellard31e31b82003-02-18 22:55:36 +00004665 case TARGET_NR_signal:
4666 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00004667#endif
bellard31e31b82003-02-18 22:55:36 +00004668 case TARGET_NR_acct:
aurel3238d840e2009-01-30 19:48:17 +00004669 if (arg1 == 0) {
4670 ret = get_errno(acct(NULL));
4671 } else {
4672 if (!(p = lock_user_string(arg1)))
4673 goto efault;
4674 ret = get_errno(acct(path(p)));
4675 unlock_user(p, arg1, 0);
4676 }
pbrook24836682006-04-16 14:14:53 +00004677 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004678#ifdef TARGET_NR_umount2 /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00004679 case TARGET_NR_umount2:
bellard579a97f2007-11-11 14:26:47 +00004680 if (!(p = lock_user_string(arg1)))
4681 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004682 ret = get_errno(umount2(p, arg2));
4683 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004684 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004685#endif
bellardebc05482003-09-30 21:08:41 +00004686#ifdef TARGET_NR_lock
bellard31e31b82003-02-18 22:55:36 +00004687 case TARGET_NR_lock:
4688 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004689#endif
bellard31e31b82003-02-18 22:55:36 +00004690 case TARGET_NR_ioctl:
4691 ret = do_ioctl(arg1, arg2, arg3);
4692 break;
4693 case TARGET_NR_fcntl:
bellard9ee1fa22007-11-11 15:11:19 +00004694 ret = do_fcntl(arg1, arg2, arg3);
bellard31e31b82003-02-18 22:55:36 +00004695 break;
bellardebc05482003-09-30 21:08:41 +00004696#ifdef TARGET_NR_mpx
bellard31e31b82003-02-18 22:55:36 +00004697 case TARGET_NR_mpx:
4698 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004699#endif
bellard31e31b82003-02-18 22:55:36 +00004700 case TARGET_NR_setpgid:
4701 ret = get_errno(setpgid(arg1, arg2));
4702 break;
bellardebc05482003-09-30 21:08:41 +00004703#ifdef TARGET_NR_ulimit
bellard31e31b82003-02-18 22:55:36 +00004704 case TARGET_NR_ulimit:
4705 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004706#endif
4707#ifdef TARGET_NR_oldolduname
bellard31e31b82003-02-18 22:55:36 +00004708 case TARGET_NR_oldolduname:
4709 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004710#endif
bellard31e31b82003-02-18 22:55:36 +00004711 case TARGET_NR_umask:
4712 ret = get_errno(umask(arg1));
4713 break;
4714 case TARGET_NR_chroot:
bellard579a97f2007-11-11 14:26:47 +00004715 if (!(p = lock_user_string(arg1)))
4716 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004717 ret = get_errno(chroot(p));
4718 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004719 break;
4720 case TARGET_NR_ustat:
4721 goto unimplemented;
4722 case TARGET_NR_dup2:
4723 ret = get_errno(dup2(arg1, arg2));
4724 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004725#ifdef TARGET_NR_getppid /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00004726 case TARGET_NR_getppid:
4727 ret = get_errno(getppid());
4728 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004729#endif
bellard31e31b82003-02-18 22:55:36 +00004730 case TARGET_NR_getpgrp:
4731 ret = get_errno(getpgrp());
4732 break;
4733 case TARGET_NR_setsid:
4734 ret = get_errno(setsid());
4735 break;
thse5febef2007-04-01 18:31:35 +00004736#ifdef TARGET_NR_sigaction
bellard31e31b82003-02-18 22:55:36 +00004737 case TARGET_NR_sigaction:
bellard31e31b82003-02-18 22:55:36 +00004738 {
ths388bb212007-05-13 13:58:00 +00004739#if !defined(TARGET_MIPS)
pbrook53a59602006-03-25 19:31:22 +00004740 struct target_old_sigaction *old_act;
bellard66fb9762003-03-23 01:06:05 +00004741 struct target_sigaction act, oact, *pact;
pbrook53a59602006-03-25 19:31:22 +00004742 if (arg2) {
bellard579a97f2007-11-11 14:26:47 +00004743 if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1))
4744 goto efault;
bellard66fb9762003-03-23 01:06:05 +00004745 act._sa_handler = old_act->_sa_handler;
4746 target_siginitset(&act.sa_mask, old_act->sa_mask);
4747 act.sa_flags = old_act->sa_flags;
4748 act.sa_restorer = old_act->sa_restorer;
pbrook53a59602006-03-25 19:31:22 +00004749 unlock_user_struct(old_act, arg2, 0);
bellard66fb9762003-03-23 01:06:05 +00004750 pact = &act;
4751 } else {
4752 pact = NULL;
4753 }
4754 ret = get_errno(do_sigaction(arg1, pact, &oact));
pbrook53a59602006-03-25 19:31:22 +00004755 if (!is_error(ret) && arg3) {
bellard579a97f2007-11-11 14:26:47 +00004756 if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0))
4757 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004758 old_act->_sa_handler = oact._sa_handler;
4759 old_act->sa_mask = oact.sa_mask.sig[0];
4760 old_act->sa_flags = oact.sa_flags;
4761 old_act->sa_restorer = oact.sa_restorer;
4762 unlock_user_struct(old_act, arg3, 1);
bellard66fb9762003-03-23 01:06:05 +00004763 }
ths388bb212007-05-13 13:58:00 +00004764#else
bellard106ec872006-06-27 21:08:10 +00004765 struct target_sigaction act, oact, *pact, *old_act;
4766
4767 if (arg2) {
bellard579a97f2007-11-11 14:26:47 +00004768 if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1))
4769 goto efault;
bellard106ec872006-06-27 21:08:10 +00004770 act._sa_handler = old_act->_sa_handler;
4771 target_siginitset(&act.sa_mask, old_act->sa_mask.sig[0]);
4772 act.sa_flags = old_act->sa_flags;
4773 unlock_user_struct(old_act, arg2, 0);
4774 pact = &act;
4775 } else {
4776 pact = NULL;
4777 }
4778
4779 ret = get_errno(do_sigaction(arg1, pact, &oact));
4780
4781 if (!is_error(ret) && arg3) {
bellard579a97f2007-11-11 14:26:47 +00004782 if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0))
4783 goto efault;
bellard106ec872006-06-27 21:08:10 +00004784 old_act->_sa_handler = oact._sa_handler;
4785 old_act->sa_flags = oact.sa_flags;
4786 old_act->sa_mask.sig[0] = oact.sa_mask.sig[0];
4787 old_act->sa_mask.sig[1] = 0;
4788 old_act->sa_mask.sig[2] = 0;
4789 old_act->sa_mask.sig[3] = 0;
4790 unlock_user_struct(old_act, arg3, 1);
4791 }
ths388bb212007-05-13 13:58:00 +00004792#endif
bellard31e31b82003-02-18 22:55:36 +00004793 }
4794 break;
thse5febef2007-04-01 18:31:35 +00004795#endif
bellard66fb9762003-03-23 01:06:05 +00004796 case TARGET_NR_rt_sigaction:
pbrook53a59602006-03-25 19:31:22 +00004797 {
4798 struct target_sigaction *act;
4799 struct target_sigaction *oact;
4800
bellard579a97f2007-11-11 14:26:47 +00004801 if (arg2) {
4802 if (!lock_user_struct(VERIFY_READ, act, arg2, 1))
4803 goto efault;
4804 } else
pbrook53a59602006-03-25 19:31:22 +00004805 act = NULL;
bellard579a97f2007-11-11 14:26:47 +00004806 if (arg3) {
4807 if (!lock_user_struct(VERIFY_WRITE, oact, arg3, 0)) {
4808 ret = -TARGET_EFAULT;
4809 goto rt_sigaction_fail;
4810 }
4811 } else
pbrook53a59602006-03-25 19:31:22 +00004812 oact = NULL;
4813 ret = get_errno(do_sigaction(arg1, act, oact));
bellard579a97f2007-11-11 14:26:47 +00004814 rt_sigaction_fail:
4815 if (act)
pbrook53a59602006-03-25 19:31:22 +00004816 unlock_user_struct(act, arg2, 0);
bellard579a97f2007-11-11 14:26:47 +00004817 if (oact)
pbrook53a59602006-03-25 19:31:22 +00004818 unlock_user_struct(oact, arg3, 1);
4819 }
bellard66fb9762003-03-23 01:06:05 +00004820 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004821#ifdef TARGET_NR_sgetmask /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00004822 case TARGET_NR_sgetmask:
bellard66fb9762003-03-23 01:06:05 +00004823 {
4824 sigset_t cur_set;
blueswir1992f48a2007-10-14 16:27:31 +00004825 abi_ulong target_set;
bellard66fb9762003-03-23 01:06:05 +00004826 sigprocmask(0, NULL, &cur_set);
4827 host_to_target_old_sigset(&target_set, &cur_set);
4828 ret = target_set;
4829 }
4830 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004831#endif
4832#ifdef TARGET_NR_ssetmask /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00004833 case TARGET_NR_ssetmask:
bellard66fb9762003-03-23 01:06:05 +00004834 {
4835 sigset_t set, oset, cur_set;
blueswir1992f48a2007-10-14 16:27:31 +00004836 abi_ulong target_set = arg1;
bellard66fb9762003-03-23 01:06:05 +00004837 sigprocmask(0, NULL, &cur_set);
4838 target_to_host_old_sigset(&set, &target_set);
4839 sigorset(&set, &set, &cur_set);
4840 sigprocmask(SIG_SETMASK, &set, &oset);
4841 host_to_target_old_sigset(&target_set, &oset);
4842 ret = target_set;
4843 }
4844 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004845#endif
thse5febef2007-04-01 18:31:35 +00004846#ifdef TARGET_NR_sigprocmask
bellard66fb9762003-03-23 01:06:05 +00004847 case TARGET_NR_sigprocmask:
4848 {
4849 int how = arg1;
4850 sigset_t set, oldset, *set_ptr;
ths3b46e622007-09-17 08:09:54 +00004851
pbrook53a59602006-03-25 19:31:22 +00004852 if (arg2) {
bellard66fb9762003-03-23 01:06:05 +00004853 switch(how) {
4854 case TARGET_SIG_BLOCK:
4855 how = SIG_BLOCK;
4856 break;
4857 case TARGET_SIG_UNBLOCK:
4858 how = SIG_UNBLOCK;
4859 break;
4860 case TARGET_SIG_SETMASK:
4861 how = SIG_SETMASK;
4862 break;
4863 default:
ths0da46a62007-10-20 20:23:07 +00004864 ret = -TARGET_EINVAL;
bellard66fb9762003-03-23 01:06:05 +00004865 goto fail;
4866 }
bellard579a97f2007-11-11 14:26:47 +00004867 if (!(p = lock_user(VERIFY_READ, arg2, sizeof(target_sigset_t), 1)))
4868 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004869 target_to_host_old_sigset(&set, p);
4870 unlock_user(p, arg2, 0);
bellard66fb9762003-03-23 01:06:05 +00004871 set_ptr = &set;
4872 } else {
4873 how = 0;
4874 set_ptr = NULL;
4875 }
4876 ret = get_errno(sigprocmask(arg1, set_ptr, &oldset));
pbrook53a59602006-03-25 19:31:22 +00004877 if (!is_error(ret) && arg3) {
bellard579a97f2007-11-11 14:26:47 +00004878 if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0)))
4879 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004880 host_to_target_old_sigset(p, &oldset);
4881 unlock_user(p, arg3, sizeof(target_sigset_t));
bellard66fb9762003-03-23 01:06:05 +00004882 }
4883 }
4884 break;
thse5febef2007-04-01 18:31:35 +00004885#endif
bellard66fb9762003-03-23 01:06:05 +00004886 case TARGET_NR_rt_sigprocmask:
4887 {
4888 int how = arg1;
4889 sigset_t set, oldset, *set_ptr;
ths3b46e622007-09-17 08:09:54 +00004890
pbrook53a59602006-03-25 19:31:22 +00004891 if (arg2) {
bellard66fb9762003-03-23 01:06:05 +00004892 switch(how) {
4893 case TARGET_SIG_BLOCK:
4894 how = SIG_BLOCK;
4895 break;
4896 case TARGET_SIG_UNBLOCK:
4897 how = SIG_UNBLOCK;
4898 break;
4899 case TARGET_SIG_SETMASK:
4900 how = SIG_SETMASK;
4901 break;
4902 default:
ths0da46a62007-10-20 20:23:07 +00004903 ret = -TARGET_EINVAL;
bellard66fb9762003-03-23 01:06:05 +00004904 goto fail;
4905 }
bellard579a97f2007-11-11 14:26:47 +00004906 if (!(p = lock_user(VERIFY_READ, arg2, 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, arg2, 0);
bellard66fb9762003-03-23 01:06:05 +00004910 set_ptr = &set;
4911 } else {
4912 how = 0;
4913 set_ptr = NULL;
4914 }
4915 ret = get_errno(sigprocmask(how, set_ptr, &oldset));
pbrook53a59602006-03-25 19:31:22 +00004916 if (!is_error(ret) && arg3) {
bellard579a97f2007-11-11 14:26:47 +00004917 if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0)))
4918 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004919 host_to_target_sigset(p, &oldset);
4920 unlock_user(p, arg3, sizeof(target_sigset_t));
bellard66fb9762003-03-23 01:06:05 +00004921 }
4922 }
4923 break;
thse5febef2007-04-01 18:31:35 +00004924#ifdef TARGET_NR_sigpending
bellard66fb9762003-03-23 01:06:05 +00004925 case TARGET_NR_sigpending:
4926 {
4927 sigset_t set;
4928 ret = get_errno(sigpending(&set));
4929 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00004930 if (!(p = lock_user(VERIFY_WRITE, arg1, sizeof(target_sigset_t), 0)))
4931 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004932 host_to_target_old_sigset(p, &set);
4933 unlock_user(p, arg1, sizeof(target_sigset_t));
bellard66fb9762003-03-23 01:06:05 +00004934 }
4935 }
4936 break;
thse5febef2007-04-01 18:31:35 +00004937#endif
bellard66fb9762003-03-23 01:06:05 +00004938 case TARGET_NR_rt_sigpending:
4939 {
4940 sigset_t set;
4941 ret = get_errno(sigpending(&set));
4942 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00004943 if (!(p = lock_user(VERIFY_WRITE, arg1, sizeof(target_sigset_t), 0)))
4944 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004945 host_to_target_sigset(p, &set);
4946 unlock_user(p, arg1, sizeof(target_sigset_t));
bellard66fb9762003-03-23 01:06:05 +00004947 }
4948 }
4949 break;
thse5febef2007-04-01 18:31:35 +00004950#ifdef TARGET_NR_sigsuspend
bellard66fb9762003-03-23 01:06:05 +00004951 case TARGET_NR_sigsuspend:
4952 {
4953 sigset_t set;
bellard579a97f2007-11-11 14:26:47 +00004954 if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
4955 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004956 target_to_host_old_sigset(&set, p);
4957 unlock_user(p, arg1, 0);
bellard66fb9762003-03-23 01:06:05 +00004958 ret = get_errno(sigsuspend(&set));
4959 }
4960 break;
thse5febef2007-04-01 18:31:35 +00004961#endif
bellard66fb9762003-03-23 01:06:05 +00004962 case TARGET_NR_rt_sigsuspend:
4963 {
4964 sigset_t set;
bellard579a97f2007-11-11 14:26:47 +00004965 if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
4966 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004967 target_to_host_sigset(&set, p);
4968 unlock_user(p, arg1, 0);
bellard66fb9762003-03-23 01:06:05 +00004969 ret = get_errno(sigsuspend(&set));
4970 }
4971 break;
4972 case TARGET_NR_rt_sigtimedwait:
4973 {
bellard66fb9762003-03-23 01:06:05 +00004974 sigset_t set;
4975 struct timespec uts, *puts;
4976 siginfo_t uinfo;
ths3b46e622007-09-17 08:09:54 +00004977
bellard579a97f2007-11-11 14:26:47 +00004978 if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
4979 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004980 target_to_host_sigset(&set, p);
4981 unlock_user(p, arg1, 0);
4982 if (arg3) {
bellard66fb9762003-03-23 01:06:05 +00004983 puts = &uts;
pbrook53a59602006-03-25 19:31:22 +00004984 target_to_host_timespec(puts, arg3);
bellard66fb9762003-03-23 01:06:05 +00004985 } else {
4986 puts = NULL;
4987 }
4988 ret = get_errno(sigtimedwait(&set, &uinfo, puts));
pbrook53a59602006-03-25 19:31:22 +00004989 if (!is_error(ret) && arg2) {
pbrooke1e3f302008-05-30 21:53:38 +00004990 if (!(p = lock_user(VERIFY_WRITE, arg2, sizeof(target_siginfo_t), 0)))
bellard579a97f2007-11-11 14:26:47 +00004991 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004992 host_to_target_siginfo(p, &uinfo);
pbrooke1e3f302008-05-30 21:53:38 +00004993 unlock_user(p, arg2, sizeof(target_siginfo_t));
bellard66fb9762003-03-23 01:06:05 +00004994 }
4995 }
4996 break;
4997 case TARGET_NR_rt_sigqueueinfo:
4998 {
4999 siginfo_t uinfo;
bellard579a97f2007-11-11 14:26:47 +00005000 if (!(p = lock_user(VERIFY_READ, arg3, sizeof(target_sigset_t), 1)))
5001 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005002 target_to_host_siginfo(&uinfo, p);
5003 unlock_user(p, arg1, 0);
bellard66fb9762003-03-23 01:06:05 +00005004 ret = get_errno(sys_rt_sigqueueinfo(arg1, arg2, &uinfo));
5005 }
5006 break;
thse5febef2007-04-01 18:31:35 +00005007#ifdef TARGET_NR_sigreturn
bellard66fb9762003-03-23 01:06:05 +00005008 case TARGET_NR_sigreturn:
5009 /* NOTE: ret is eax, so not transcoding must be done */
5010 ret = do_sigreturn(cpu_env);
5011 break;
thse5febef2007-04-01 18:31:35 +00005012#endif
bellard66fb9762003-03-23 01:06:05 +00005013 case TARGET_NR_rt_sigreturn:
5014 /* NOTE: ret is eax, so not transcoding must be done */
5015 ret = do_rt_sigreturn(cpu_env);
5016 break;
bellard31e31b82003-02-18 22:55:36 +00005017 case TARGET_NR_sethostname:
bellard579a97f2007-11-11 14:26:47 +00005018 if (!(p = lock_user_string(arg1)))
5019 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005020 ret = get_errno(sethostname(p, arg2));
5021 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00005022 break;
5023 case TARGET_NR_setrlimit:
bellard9de5e442003-03-23 16:49:39 +00005024 {
5025 /* XXX: convert resource ? */
5026 int resource = arg1;
pbrook53a59602006-03-25 19:31:22 +00005027 struct target_rlimit *target_rlim;
bellard9de5e442003-03-23 16:49:39 +00005028 struct rlimit rlim;
bellard579a97f2007-11-11 14:26:47 +00005029 if (!lock_user_struct(VERIFY_READ, target_rlim, arg2, 1))
5030 goto efault;
bellard9de5e442003-03-23 16:49:39 +00005031 rlim.rlim_cur = tswapl(target_rlim->rlim_cur);
5032 rlim.rlim_max = tswapl(target_rlim->rlim_max);
pbrook53a59602006-03-25 19:31:22 +00005033 unlock_user_struct(target_rlim, arg2, 0);
bellard9de5e442003-03-23 16:49:39 +00005034 ret = get_errno(setrlimit(resource, &rlim));
5035 }
5036 break;
bellard31e31b82003-02-18 22:55:36 +00005037 case TARGET_NR_getrlimit:
bellard9de5e442003-03-23 16:49:39 +00005038 {
5039 /* XXX: convert resource ? */
5040 int resource = arg1;
pbrook53a59602006-03-25 19:31:22 +00005041 struct target_rlimit *target_rlim;
bellard9de5e442003-03-23 16:49:39 +00005042 struct rlimit rlim;
ths3b46e622007-09-17 08:09:54 +00005043
bellard9de5e442003-03-23 16:49:39 +00005044 ret = get_errno(getrlimit(resource, &rlim));
5045 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00005046 if (!lock_user_struct(VERIFY_WRITE, target_rlim, arg2, 0))
5047 goto efault;
Ulrich Hecht666bcd92009-07-03 17:09:30 +02005048 target_rlim->rlim_cur = tswapl(rlim.rlim_cur);
5049 target_rlim->rlim_max = tswapl(rlim.rlim_max);
pbrook53a59602006-03-25 19:31:22 +00005050 unlock_user_struct(target_rlim, arg2, 1);
bellard9de5e442003-03-23 16:49:39 +00005051 }
5052 }
5053 break;
bellard31e31b82003-02-18 22:55:36 +00005054 case TARGET_NR_getrusage:
bellardb4091862003-05-16 15:39:34 +00005055 {
5056 struct rusage rusage;
bellardb4091862003-05-16 15:39:34 +00005057 ret = get_errno(getrusage(arg1, &rusage));
5058 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00005059 host_to_target_rusage(arg2, &rusage);
bellardb4091862003-05-16 15:39:34 +00005060 }
5061 }
5062 break;
bellard31e31b82003-02-18 22:55:36 +00005063 case TARGET_NR_gettimeofday:
5064 {
bellard31e31b82003-02-18 22:55:36 +00005065 struct timeval tv;
5066 ret = get_errno(gettimeofday(&tv, NULL));
5067 if (!is_error(ret)) {
ths788f5ec2007-12-09 02:37:05 +00005068 if (copy_to_user_timeval(arg1, &tv))
5069 goto efault;
bellard31e31b82003-02-18 22:55:36 +00005070 }
5071 }
5072 break;
5073 case TARGET_NR_settimeofday:
5074 {
bellard31e31b82003-02-18 22:55:36 +00005075 struct timeval tv;
ths788f5ec2007-12-09 02:37:05 +00005076 if (copy_from_user_timeval(&tv, arg1))
5077 goto efault;
bellard31e31b82003-02-18 22:55:36 +00005078 ret = get_errno(settimeofday(&tv, NULL));
5079 }
5080 break;
bellard048f6b42005-11-26 18:47:20 +00005081#ifdef TARGET_NR_select
bellard31e31b82003-02-18 22:55:36 +00005082 case TARGET_NR_select:
bellardf2674e32003-07-09 12:26:09 +00005083 {
pbrook53a59602006-03-25 19:31:22 +00005084 struct target_sel_arg_struct *sel;
blueswir1992f48a2007-10-14 16:27:31 +00005085 abi_ulong inp, outp, exp, tvp;
pbrook53a59602006-03-25 19:31:22 +00005086 long nsel;
5087
bellard579a97f2007-11-11 14:26:47 +00005088 if (!lock_user_struct(VERIFY_READ, sel, arg1, 1))
5089 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005090 nsel = tswapl(sel->n);
5091 inp = tswapl(sel->inp);
5092 outp = tswapl(sel->outp);
5093 exp = tswapl(sel->exp);
5094 tvp = tswapl(sel->tvp);
5095 unlock_user_struct(sel, arg1, 0);
5096 ret = do_select(nsel, inp, outp, exp, tvp);
bellardf2674e32003-07-09 12:26:09 +00005097 }
5098 break;
bellard048f6b42005-11-26 18:47:20 +00005099#endif
bellard31e31b82003-02-18 22:55:36 +00005100 case TARGET_NR_symlink:
pbrook53a59602006-03-25 19:31:22 +00005101 {
5102 void *p2;
5103 p = lock_user_string(arg1);
5104 p2 = lock_user_string(arg2);
bellard579a97f2007-11-11 14:26:47 +00005105 if (!p || !p2)
5106 ret = -TARGET_EFAULT;
5107 else
5108 ret = get_errno(symlink(p, p2));
pbrook53a59602006-03-25 19:31:22 +00005109 unlock_user(p2, arg2, 0);
5110 unlock_user(p, arg1, 0);
5111 }
bellard31e31b82003-02-18 22:55:36 +00005112 break;
thsf0b62432007-09-24 09:25:40 +00005113#if defined(TARGET_NR_symlinkat) && defined(__NR_symlinkat)
5114 case TARGET_NR_symlinkat:
thsf0b62432007-09-24 09:25:40 +00005115 {
bellard579a97f2007-11-11 14:26:47 +00005116 void *p2;
thsf0b62432007-09-24 09:25:40 +00005117 p = lock_user_string(arg1);
5118 p2 = lock_user_string(arg3);
bellard579a97f2007-11-11 14:26:47 +00005119 if (!p || !p2)
ths0da46a62007-10-20 20:23:07 +00005120 ret = -TARGET_EFAULT;
thsf0b62432007-09-24 09:25:40 +00005121 else
5122 ret = get_errno(sys_symlinkat(p, arg2, p2));
bellard579a97f2007-11-11 14:26:47 +00005123 unlock_user(p2, arg3, 0);
5124 unlock_user(p, arg1, 0);
thsf0b62432007-09-24 09:25:40 +00005125 }
5126 break;
5127#endif
bellardebc05482003-09-30 21:08:41 +00005128#ifdef TARGET_NR_oldlstat
bellard31e31b82003-02-18 22:55:36 +00005129 case TARGET_NR_oldlstat:
5130 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00005131#endif
bellard31e31b82003-02-18 22:55:36 +00005132 case TARGET_NR_readlink:
pbrook53a59602006-03-25 19:31:22 +00005133 {
aurel32d088d662009-01-30 20:09:01 +00005134 void *p2, *temp;
pbrook53a59602006-03-25 19:31:22 +00005135 p = lock_user_string(arg1);
bellard579a97f2007-11-11 14:26:47 +00005136 p2 = lock_user(VERIFY_WRITE, arg2, arg3, 0);
5137 if (!p || !p2)
5138 ret = -TARGET_EFAULT;
aurel32d088d662009-01-30 20:09:01 +00005139 else {
5140 if (strncmp((const char *)p, "/proc/self/exe", 14) == 0) {
5141 char real[PATH_MAX];
5142 temp = realpath(exec_path,real);
5143 ret = (temp==NULL) ? get_errno(-1) : strlen(real) ;
5144 snprintf((char *)p2, arg3, "%s", real);
5145 }
5146 else
5147 ret = get_errno(readlink(path(p), p2, arg3));
aurel32d088d662009-01-30 20:09:01 +00005148 }
pbrook53a59602006-03-25 19:31:22 +00005149 unlock_user(p2, arg2, ret);
5150 unlock_user(p, arg1, 0);
5151 }
bellard31e31b82003-02-18 22:55:36 +00005152 break;
ths5e0ccb12007-09-24 09:26:10 +00005153#if defined(TARGET_NR_readlinkat) && defined(__NR_readlinkat)
5154 case TARGET_NR_readlinkat:
ths5e0ccb12007-09-24 09:26:10 +00005155 {
bellard579a97f2007-11-11 14:26:47 +00005156 void *p2;
ths5e0ccb12007-09-24 09:26:10 +00005157 p = lock_user_string(arg2);
bellard579a97f2007-11-11 14:26:47 +00005158 p2 = lock_user(VERIFY_WRITE, arg3, arg4, 0);
5159 if (!p || !p2)
ths0da46a62007-10-20 20:23:07 +00005160 ret = -TARGET_EFAULT;
ths5e0ccb12007-09-24 09:26:10 +00005161 else
5162 ret = get_errno(sys_readlinkat(arg1, path(p), p2, arg4));
bellard579a97f2007-11-11 14:26:47 +00005163 unlock_user(p2, arg3, ret);
5164 unlock_user(p, arg2, 0);
ths5e0ccb12007-09-24 09:26:10 +00005165 }
5166 break;
5167#endif
thse5febef2007-04-01 18:31:35 +00005168#ifdef TARGET_NR_uselib
bellard31e31b82003-02-18 22:55:36 +00005169 case TARGET_NR_uselib:
5170 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00005171#endif
5172#ifdef TARGET_NR_swapon
bellard31e31b82003-02-18 22:55:36 +00005173 case TARGET_NR_swapon:
bellard579a97f2007-11-11 14:26:47 +00005174 if (!(p = lock_user_string(arg1)))
5175 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005176 ret = get_errno(swapon(p, arg2));
5177 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00005178 break;
thse5febef2007-04-01 18:31:35 +00005179#endif
bellard31e31b82003-02-18 22:55:36 +00005180 case TARGET_NR_reboot:
5181 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00005182#ifdef TARGET_NR_readdir
bellard31e31b82003-02-18 22:55:36 +00005183 case TARGET_NR_readdir:
5184 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00005185#endif
5186#ifdef TARGET_NR_mmap
bellard31e31b82003-02-18 22:55:36 +00005187 case TARGET_NR_mmap:
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02005188#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 +00005189 {
blueswir1992f48a2007-10-14 16:27:31 +00005190 abi_ulong *v;
5191 abi_ulong v1, v2, v3, v4, v5, v6;
bellard579a97f2007-11-11 14:26:47 +00005192 if (!(v = lock_user(VERIFY_READ, arg1, 6 * sizeof(abi_ulong), 1)))
5193 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005194 v1 = tswapl(v[0]);
5195 v2 = tswapl(v[1]);
5196 v3 = tswapl(v[2]);
5197 v4 = tswapl(v[3]);
5198 v5 = tswapl(v[4]);
5199 v6 = tswapl(v[5]);
5200 unlock_user(v, arg1, 0);
ths5fafdf22007-09-16 21:08:06 +00005201 ret = get_errno(target_mmap(v1, v2, v3,
bellard5286db72003-06-05 00:57:30 +00005202 target_to_host_bitmask(v4, mmap_flags_tbl),
5203 v5, v6));
bellard31e31b82003-02-18 22:55:36 +00005204 }
bellard31e31b82003-02-18 22:55:36 +00005205#else
ths5fafdf22007-09-16 21:08:06 +00005206 ret = get_errno(target_mmap(arg1, arg2, arg3,
5207 target_to_host_bitmask(arg4, mmap_flags_tbl),
bellard6fb883e2003-07-09 17:12:39 +00005208 arg5,
5209 arg6));
bellard31e31b82003-02-18 22:55:36 +00005210#endif
bellard6fb883e2003-07-09 17:12:39 +00005211 break;
thse5febef2007-04-01 18:31:35 +00005212#endif
bellarda315a142005-01-30 22:59:18 +00005213#ifdef TARGET_NR_mmap2
bellard6fb883e2003-07-09 17:12:39 +00005214 case TARGET_NR_mmap2:
pbrookbb7ec042008-03-25 22:28:25 +00005215#ifndef MMAP_SHIFT
bellardc573ff62004-01-04 15:51:36 +00005216#define MMAP_SHIFT 12
bellardc573ff62004-01-04 15:51:36 +00005217#endif
ths5fafdf22007-09-16 21:08:06 +00005218 ret = get_errno(target_mmap(arg1, arg2, arg3,
5219 target_to_host_bitmask(arg4, mmap_flags_tbl),
bellard5286db72003-06-05 00:57:30 +00005220 arg5,
bellardc573ff62004-01-04 15:51:36 +00005221 arg6 << MMAP_SHIFT));
bellard31e31b82003-02-18 22:55:36 +00005222 break;
bellarda315a142005-01-30 22:59:18 +00005223#endif
bellard31e31b82003-02-18 22:55:36 +00005224 case TARGET_NR_munmap:
bellard54936002003-05-13 00:25:15 +00005225 ret = get_errno(target_munmap(arg1, arg2));
bellard31e31b82003-02-18 22:55:36 +00005226 break;
bellard9de5e442003-03-23 16:49:39 +00005227 case TARGET_NR_mprotect:
bellard54936002003-05-13 00:25:15 +00005228 ret = get_errno(target_mprotect(arg1, arg2, arg3));
bellard9de5e442003-03-23 16:49:39 +00005229 break;
thse5febef2007-04-01 18:31:35 +00005230#ifdef TARGET_NR_mremap
bellard9de5e442003-03-23 16:49:39 +00005231 case TARGET_NR_mremap:
bellard54936002003-05-13 00:25:15 +00005232 ret = get_errno(target_mremap(arg1, arg2, arg3, arg4, arg5));
bellard9de5e442003-03-23 16:49:39 +00005233 break;
thse5febef2007-04-01 18:31:35 +00005234#endif
pbrook53a59602006-03-25 19:31:22 +00005235 /* ??? msync/mlock/munlock are broken for softmmu. */
thse5febef2007-04-01 18:31:35 +00005236#ifdef TARGET_NR_msync
bellard9de5e442003-03-23 16:49:39 +00005237 case TARGET_NR_msync:
pbrook53a59602006-03-25 19:31:22 +00005238 ret = get_errno(msync(g2h(arg1), arg2, arg3));
bellard9de5e442003-03-23 16:49:39 +00005239 break;
thse5febef2007-04-01 18:31:35 +00005240#endif
5241#ifdef TARGET_NR_mlock
bellard9de5e442003-03-23 16:49:39 +00005242 case TARGET_NR_mlock:
pbrook53a59602006-03-25 19:31:22 +00005243 ret = get_errno(mlock(g2h(arg1), arg2));
bellard9de5e442003-03-23 16:49:39 +00005244 break;
thse5febef2007-04-01 18:31:35 +00005245#endif
5246#ifdef TARGET_NR_munlock
bellard9de5e442003-03-23 16:49:39 +00005247 case TARGET_NR_munlock:
pbrook53a59602006-03-25 19:31:22 +00005248 ret = get_errno(munlock(g2h(arg1), arg2));
bellard9de5e442003-03-23 16:49:39 +00005249 break;
thse5febef2007-04-01 18:31:35 +00005250#endif
5251#ifdef TARGET_NR_mlockall
bellard9de5e442003-03-23 16:49:39 +00005252 case TARGET_NR_mlockall:
5253 ret = get_errno(mlockall(arg1));
5254 break;
thse5febef2007-04-01 18:31:35 +00005255#endif
5256#ifdef TARGET_NR_munlockall
bellard9de5e442003-03-23 16:49:39 +00005257 case TARGET_NR_munlockall:
5258 ret = get_errno(munlockall());
5259 break;
thse5febef2007-04-01 18:31:35 +00005260#endif
bellard31e31b82003-02-18 22:55:36 +00005261 case TARGET_NR_truncate:
bellard579a97f2007-11-11 14:26:47 +00005262 if (!(p = lock_user_string(arg1)))
5263 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005264 ret = get_errno(truncate(p, arg2));
5265 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00005266 break;
5267 case TARGET_NR_ftruncate:
5268 ret = get_errno(ftruncate(arg1, arg2));
5269 break;
5270 case TARGET_NR_fchmod:
5271 ret = get_errno(fchmod(arg1, arg2));
5272 break;
ths814d7972007-09-24 09:26:51 +00005273#if defined(TARGET_NR_fchmodat) && defined(__NR_fchmodat)
5274 case TARGET_NR_fchmodat:
bellard579a97f2007-11-11 14:26:47 +00005275 if (!(p = lock_user_string(arg2)))
5276 goto efault;
aurel32465c9f02009-04-19 08:52:17 +00005277 ret = get_errno(sys_fchmodat(arg1, p, arg3));
bellard579a97f2007-11-11 14:26:47 +00005278 unlock_user(p, arg2, 0);
ths814d7972007-09-24 09:26:51 +00005279 break;
5280#endif
bellard31e31b82003-02-18 22:55:36 +00005281 case TARGET_NR_getpriority:
thsc6cda172007-10-09 03:42:34 +00005282 /* libc does special remapping of the return value of
5283 * sys_getpriority() so it's just easiest to call
5284 * sys_getpriority() directly rather than through libc. */
5285 ret = sys_getpriority(arg1, arg2);
bellard31e31b82003-02-18 22:55:36 +00005286 break;
5287 case TARGET_NR_setpriority:
5288 ret = get_errno(setpriority(arg1, arg2, arg3));
5289 break;
bellardebc05482003-09-30 21:08:41 +00005290#ifdef TARGET_NR_profil
bellard31e31b82003-02-18 22:55:36 +00005291 case TARGET_NR_profil:
5292 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00005293#endif
bellard31e31b82003-02-18 22:55:36 +00005294 case TARGET_NR_statfs:
bellard579a97f2007-11-11 14:26:47 +00005295 if (!(p = lock_user_string(arg1)))
5296 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005297 ret = get_errno(statfs(path(p), &stfs));
5298 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00005299 convert_statfs:
5300 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00005301 struct target_statfs *target_stfs;
ths3b46e622007-09-17 08:09:54 +00005302
bellard579a97f2007-11-11 14:26:47 +00005303 if (!lock_user_struct(VERIFY_WRITE, target_stfs, arg2, 0))
5304 goto efault;
5305 __put_user(stfs.f_type, &target_stfs->f_type);
5306 __put_user(stfs.f_bsize, &target_stfs->f_bsize);
5307 __put_user(stfs.f_blocks, &target_stfs->f_blocks);
5308 __put_user(stfs.f_bfree, &target_stfs->f_bfree);
5309 __put_user(stfs.f_bavail, &target_stfs->f_bavail);
5310 __put_user(stfs.f_files, &target_stfs->f_files);
5311 __put_user(stfs.f_ffree, &target_stfs->f_ffree);
5312 __put_user(stfs.f_fsid.__val[0], &target_stfs->f_fsid.val[0]);
5313 __put_user(stfs.f_fsid.__val[1], &target_stfs->f_fsid.val[1]);
5314 __put_user(stfs.f_namelen, &target_stfs->f_namelen);
pbrook53a59602006-03-25 19:31:22 +00005315 unlock_user_struct(target_stfs, arg2, 1);
bellard31e31b82003-02-18 22:55:36 +00005316 }
5317 break;
5318 case TARGET_NR_fstatfs:
bellard56c8f682005-11-28 22:28:41 +00005319 ret = get_errno(fstatfs(arg1, &stfs));
bellard31e31b82003-02-18 22:55:36 +00005320 goto convert_statfs;
bellard56c8f682005-11-28 22:28:41 +00005321#ifdef TARGET_NR_statfs64
5322 case TARGET_NR_statfs64:
bellard579a97f2007-11-11 14:26:47 +00005323 if (!(p = lock_user_string(arg1)))
5324 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005325 ret = get_errno(statfs(path(p), &stfs));
5326 unlock_user(p, arg1, 0);
bellard56c8f682005-11-28 22:28:41 +00005327 convert_statfs64:
5328 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00005329 struct target_statfs64 *target_stfs;
ths3b46e622007-09-17 08:09:54 +00005330
bellard579a97f2007-11-11 14:26:47 +00005331 if (!lock_user_struct(VERIFY_WRITE, target_stfs, arg3, 0))
5332 goto efault;
5333 __put_user(stfs.f_type, &target_stfs->f_type);
5334 __put_user(stfs.f_bsize, &target_stfs->f_bsize);
5335 __put_user(stfs.f_blocks, &target_stfs->f_blocks);
5336 __put_user(stfs.f_bfree, &target_stfs->f_bfree);
5337 __put_user(stfs.f_bavail, &target_stfs->f_bavail);
5338 __put_user(stfs.f_files, &target_stfs->f_files);
5339 __put_user(stfs.f_ffree, &target_stfs->f_ffree);
5340 __put_user(stfs.f_fsid.__val[0], &target_stfs->f_fsid.val[0]);
5341 __put_user(stfs.f_fsid.__val[1], &target_stfs->f_fsid.val[1]);
5342 __put_user(stfs.f_namelen, &target_stfs->f_namelen);
5343 unlock_user_struct(target_stfs, arg3, 1);
bellard56c8f682005-11-28 22:28:41 +00005344 }
5345 break;
5346 case TARGET_NR_fstatfs64:
5347 ret = get_errno(fstatfs(arg1, &stfs));
5348 goto convert_statfs64;
5349#endif
bellardebc05482003-09-30 21:08:41 +00005350#ifdef TARGET_NR_ioperm
bellard31e31b82003-02-18 22:55:36 +00005351 case TARGET_NR_ioperm:
5352 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00005353#endif
thse5febef2007-04-01 18:31:35 +00005354#ifdef TARGET_NR_socketcall
bellard31e31b82003-02-18 22:55:36 +00005355 case TARGET_NR_socketcall:
pbrook53a59602006-03-25 19:31:22 +00005356 ret = do_socketcall(arg1, arg2);
bellard31e31b82003-02-18 22:55:36 +00005357 break;
thse5febef2007-04-01 18:31:35 +00005358#endif
bellard3532fa72006-06-24 15:06:03 +00005359#ifdef TARGET_NR_accept
5360 case TARGET_NR_accept:
pbrook1be9e1d2006-11-19 15:26:04 +00005361 ret = do_accept(arg1, arg2, arg3);
bellard3532fa72006-06-24 15:06:03 +00005362 break;
5363#endif
5364#ifdef TARGET_NR_bind
5365 case TARGET_NR_bind:
5366 ret = do_bind(arg1, arg2, arg3);
5367 break;
5368#endif
5369#ifdef TARGET_NR_connect
5370 case TARGET_NR_connect:
5371 ret = do_connect(arg1, arg2, arg3);
5372 break;
5373#endif
5374#ifdef TARGET_NR_getpeername
5375 case TARGET_NR_getpeername:
pbrook1be9e1d2006-11-19 15:26:04 +00005376 ret = do_getpeername(arg1, arg2, arg3);
bellard3532fa72006-06-24 15:06:03 +00005377 break;
5378#endif
5379#ifdef TARGET_NR_getsockname
5380 case TARGET_NR_getsockname:
pbrook1be9e1d2006-11-19 15:26:04 +00005381 ret = do_getsockname(arg1, arg2, arg3);
bellard3532fa72006-06-24 15:06:03 +00005382 break;
5383#endif
5384#ifdef TARGET_NR_getsockopt
5385 case TARGET_NR_getsockopt:
5386 ret = do_getsockopt(arg1, arg2, arg3, arg4, arg5);
5387 break;
5388#endif
5389#ifdef TARGET_NR_listen
5390 case TARGET_NR_listen:
pbrook1be9e1d2006-11-19 15:26:04 +00005391 ret = get_errno(listen(arg1, arg2));
bellard3532fa72006-06-24 15:06:03 +00005392 break;
5393#endif
5394#ifdef TARGET_NR_recv
5395 case TARGET_NR_recv:
pbrook214201b2007-03-17 01:27:24 +00005396 ret = do_recvfrom(arg1, arg2, arg3, arg4, 0, 0);
bellard3532fa72006-06-24 15:06:03 +00005397 break;
5398#endif
5399#ifdef TARGET_NR_recvfrom
5400 case TARGET_NR_recvfrom:
pbrook214201b2007-03-17 01:27:24 +00005401 ret = do_recvfrom(arg1, arg2, arg3, arg4, arg5, arg6);
bellard3532fa72006-06-24 15:06:03 +00005402 break;
5403#endif
5404#ifdef TARGET_NR_recvmsg
5405 case TARGET_NR_recvmsg:
5406 ret = do_sendrecvmsg(arg1, arg2, arg3, 0);
5407 break;
5408#endif
5409#ifdef TARGET_NR_send
5410 case TARGET_NR_send:
pbrook1be9e1d2006-11-19 15:26:04 +00005411 ret = do_sendto(arg1, arg2, arg3, arg4, 0, 0);
bellard3532fa72006-06-24 15:06:03 +00005412 break;
5413#endif
5414#ifdef TARGET_NR_sendmsg
5415 case TARGET_NR_sendmsg:
5416 ret = do_sendrecvmsg(arg1, arg2, arg3, 1);
5417 break;
5418#endif
5419#ifdef TARGET_NR_sendto
5420 case TARGET_NR_sendto:
pbrook1be9e1d2006-11-19 15:26:04 +00005421 ret = do_sendto(arg1, arg2, arg3, arg4, arg5, arg6);
bellard3532fa72006-06-24 15:06:03 +00005422 break;
5423#endif
5424#ifdef TARGET_NR_shutdown
5425 case TARGET_NR_shutdown:
pbrook1be9e1d2006-11-19 15:26:04 +00005426 ret = get_errno(shutdown(arg1, arg2));
bellard3532fa72006-06-24 15:06:03 +00005427 break;
5428#endif
5429#ifdef TARGET_NR_socket
5430 case TARGET_NR_socket:
5431 ret = do_socket(arg1, arg2, arg3);
5432 break;
5433#endif
5434#ifdef TARGET_NR_socketpair
5435 case TARGET_NR_socketpair:
pbrook1be9e1d2006-11-19 15:26:04 +00005436 ret = do_socketpair(arg1, arg2, arg3, arg4);
bellard3532fa72006-06-24 15:06:03 +00005437 break;
5438#endif
5439#ifdef TARGET_NR_setsockopt
5440 case TARGET_NR_setsockopt:
5441 ret = do_setsockopt(arg1, arg2, arg3, arg4, (socklen_t) arg5);
5442 break;
5443#endif
ths7494b0f2007-02-11 18:26:53 +00005444
bellard31e31b82003-02-18 22:55:36 +00005445 case TARGET_NR_syslog:
bellard579a97f2007-11-11 14:26:47 +00005446 if (!(p = lock_user_string(arg2)))
5447 goto efault;
thse5574482007-02-11 20:03:13 +00005448 ret = get_errno(sys_syslog((int)arg1, p, (int)arg3));
5449 unlock_user(p, arg2, 0);
ths7494b0f2007-02-11 18:26:53 +00005450 break;
5451
bellard31e31b82003-02-18 22:55:36 +00005452 case TARGET_NR_setitimer:
bellard66fb9762003-03-23 01:06:05 +00005453 {
bellard66fb9762003-03-23 01:06:05 +00005454 struct itimerval value, ovalue, *pvalue;
5455
pbrook53a59602006-03-25 19:31:22 +00005456 if (arg2) {
bellard66fb9762003-03-23 01:06:05 +00005457 pvalue = &value;
ths788f5ec2007-12-09 02:37:05 +00005458 if (copy_from_user_timeval(&pvalue->it_interval, arg2)
5459 || copy_from_user_timeval(&pvalue->it_value,
5460 arg2 + sizeof(struct target_timeval)))
5461 goto efault;
bellard66fb9762003-03-23 01:06:05 +00005462 } else {
5463 pvalue = NULL;
5464 }
5465 ret = get_errno(setitimer(arg1, pvalue, &ovalue));
pbrook53a59602006-03-25 19:31:22 +00005466 if (!is_error(ret) && arg3) {
ths788f5ec2007-12-09 02:37:05 +00005467 if (copy_to_user_timeval(arg3,
5468 &ovalue.it_interval)
5469 || copy_to_user_timeval(arg3 + sizeof(struct target_timeval),
5470 &ovalue.it_value))
5471 goto efault;
bellard66fb9762003-03-23 01:06:05 +00005472 }
5473 }
5474 break;
bellard31e31b82003-02-18 22:55:36 +00005475 case TARGET_NR_getitimer:
bellard66fb9762003-03-23 01:06:05 +00005476 {
bellard66fb9762003-03-23 01:06:05 +00005477 struct itimerval value;
ths3b46e622007-09-17 08:09:54 +00005478
bellard66fb9762003-03-23 01:06:05 +00005479 ret = get_errno(getitimer(arg1, &value));
pbrook53a59602006-03-25 19:31:22 +00005480 if (!is_error(ret) && arg2) {
ths788f5ec2007-12-09 02:37:05 +00005481 if (copy_to_user_timeval(arg2,
5482 &value.it_interval)
5483 || copy_to_user_timeval(arg2 + sizeof(struct target_timeval),
5484 &value.it_value))
5485 goto efault;
bellard66fb9762003-03-23 01:06:05 +00005486 }
5487 }
5488 break;
bellard31e31b82003-02-18 22:55:36 +00005489 case TARGET_NR_stat:
bellard579a97f2007-11-11 14:26:47 +00005490 if (!(p = lock_user_string(arg1)))
5491 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005492 ret = get_errno(stat(path(p), &st));
5493 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00005494 goto do_stat;
5495 case TARGET_NR_lstat:
bellard579a97f2007-11-11 14:26:47 +00005496 if (!(p = lock_user_string(arg1)))
5497 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005498 ret = get_errno(lstat(path(p), &st));
5499 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00005500 goto do_stat;
5501 case TARGET_NR_fstat:
5502 {
5503 ret = get_errno(fstat(arg1, &st));
5504 do_stat:
5505 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00005506 struct target_stat *target_st;
thse3584652007-06-01 11:49:38 +00005507
bellard579a97f2007-11-11 14:26:47 +00005508 if (!lock_user_struct(VERIFY_WRITE, target_st, arg2, 0))
5509 goto efault;
bellardd2fd1af2007-11-14 18:08:56 +00005510 __put_user(st.st_dev, &target_st->st_dev);
5511 __put_user(st.st_ino, &target_st->st_ino);
5512 __put_user(st.st_mode, &target_st->st_mode);
5513 __put_user(st.st_uid, &target_st->st_uid);
5514 __put_user(st.st_gid, &target_st->st_gid);
5515 __put_user(st.st_nlink, &target_st->st_nlink);
5516 __put_user(st.st_rdev, &target_st->st_rdev);
5517 __put_user(st.st_size, &target_st->st_size);
5518 __put_user(st.st_blksize, &target_st->st_blksize);
5519 __put_user(st.st_blocks, &target_st->st_blocks);
5520 __put_user(st.st_atime, &target_st->target_st_atime);
5521 __put_user(st.st_mtime, &target_st->target_st_mtime);
5522 __put_user(st.st_ctime, &target_st->target_st_ctime);
pbrook53a59602006-03-25 19:31:22 +00005523 unlock_user_struct(target_st, arg2, 1);
bellard31e31b82003-02-18 22:55:36 +00005524 }
5525 }
5526 break;
bellardebc05482003-09-30 21:08:41 +00005527#ifdef TARGET_NR_olduname
bellard31e31b82003-02-18 22:55:36 +00005528 case TARGET_NR_olduname:
5529 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00005530#endif
5531#ifdef TARGET_NR_iopl
bellard31e31b82003-02-18 22:55:36 +00005532 case TARGET_NR_iopl:
5533 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00005534#endif
bellard31e31b82003-02-18 22:55:36 +00005535 case TARGET_NR_vhangup:
5536 ret = get_errno(vhangup());
5537 break;
bellardebc05482003-09-30 21:08:41 +00005538#ifdef TARGET_NR_idle
bellard31e31b82003-02-18 22:55:36 +00005539 case TARGET_NR_idle:
5540 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00005541#endif
bellard42ad6ae2005-01-03 22:48:11 +00005542#ifdef TARGET_NR_syscall
5543 case TARGET_NR_syscall:
5544 ret = do_syscall(cpu_env,arg1 & 0xffff,arg2,arg3,arg4,arg5,arg6,0);
5545 break;
5546#endif
bellard31e31b82003-02-18 22:55:36 +00005547 case TARGET_NR_wait4:
5548 {
5549 int status;
blueswir1992f48a2007-10-14 16:27:31 +00005550 abi_long status_ptr = arg2;
bellard31e31b82003-02-18 22:55:36 +00005551 struct rusage rusage, *rusage_ptr;
blueswir1992f48a2007-10-14 16:27:31 +00005552 abi_ulong target_rusage = arg4;
bellard31e31b82003-02-18 22:55:36 +00005553 if (target_rusage)
5554 rusage_ptr = &rusage;
5555 else
5556 rusage_ptr = NULL;
5557 ret = get_errno(wait4(arg1, &status, arg3, rusage_ptr));
5558 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +00005559 if (status_ptr) {
pbrook1d9d8b52009-04-16 15:17:02 +00005560 status = host_to_target_waitstatus(status);
bellard2f619692007-11-16 10:46:05 +00005561 if (put_user_s32(status, status_ptr))
5562 goto efault;
bellard31e31b82003-02-18 22:55:36 +00005563 }
bellard2f619692007-11-16 10:46:05 +00005564 if (target_rusage)
5565 host_to_target_rusage(target_rusage, &rusage);
bellard31e31b82003-02-18 22:55:36 +00005566 }
5567 }
5568 break;
thse5febef2007-04-01 18:31:35 +00005569#ifdef TARGET_NR_swapoff
bellard31e31b82003-02-18 22:55:36 +00005570 case TARGET_NR_swapoff:
bellard579a97f2007-11-11 14:26:47 +00005571 if (!(p = lock_user_string(arg1)))
5572 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005573 ret = get_errno(swapoff(p));
5574 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00005575 break;
thse5febef2007-04-01 18:31:35 +00005576#endif
bellard31e31b82003-02-18 22:55:36 +00005577 case TARGET_NR_sysinfo:
bellarda5448a72004-06-19 16:59:03 +00005578 {
pbrook53a59602006-03-25 19:31:22 +00005579 struct target_sysinfo *target_value;
bellarda5448a72004-06-19 16:59:03 +00005580 struct sysinfo value;
5581 ret = get_errno(sysinfo(&value));
pbrook53a59602006-03-25 19:31:22 +00005582 if (!is_error(ret) && arg1)
bellarda5448a72004-06-19 16:59:03 +00005583 {
bellard579a97f2007-11-11 14:26:47 +00005584 if (!lock_user_struct(VERIFY_WRITE, target_value, arg1, 0))
5585 goto efault;
bellarda5448a72004-06-19 16:59:03 +00005586 __put_user(value.uptime, &target_value->uptime);
5587 __put_user(value.loads[0], &target_value->loads[0]);
5588 __put_user(value.loads[1], &target_value->loads[1]);
5589 __put_user(value.loads[2], &target_value->loads[2]);
5590 __put_user(value.totalram, &target_value->totalram);
5591 __put_user(value.freeram, &target_value->freeram);
5592 __put_user(value.sharedram, &target_value->sharedram);
5593 __put_user(value.bufferram, &target_value->bufferram);
5594 __put_user(value.totalswap, &target_value->totalswap);
5595 __put_user(value.freeswap, &target_value->freeswap);
5596 __put_user(value.procs, &target_value->procs);
5597 __put_user(value.totalhigh, &target_value->totalhigh);
5598 __put_user(value.freehigh, &target_value->freehigh);
5599 __put_user(value.mem_unit, &target_value->mem_unit);
pbrook53a59602006-03-25 19:31:22 +00005600 unlock_user_struct(target_value, arg1, 1);
bellarda5448a72004-06-19 16:59:03 +00005601 }
5602 }
5603 break;
thse5febef2007-04-01 18:31:35 +00005604#ifdef TARGET_NR_ipc
bellard31e31b82003-02-18 22:55:36 +00005605 case TARGET_NR_ipc:
bellard8853f862004-02-22 14:57:26 +00005606 ret = do_ipc(arg1, arg2, arg3, arg4, arg5, arg6);
5607 break;
thse5febef2007-04-01 18:31:35 +00005608#endif
aurel32e5289082009-04-18 16:16:12 +00005609#ifdef TARGET_NR_semget
5610 case TARGET_NR_semget:
5611 ret = get_errno(semget(arg1, arg2, arg3));
5612 break;
5613#endif
5614#ifdef TARGET_NR_semop
5615 case TARGET_NR_semop:
5616 ret = get_errno(do_semop(arg1, arg2, arg3));
5617 break;
5618#endif
5619#ifdef TARGET_NR_semctl
5620 case TARGET_NR_semctl:
5621 ret = do_semctl(arg1, arg2, arg3, (union target_semun)(abi_ulong)arg4);
5622 break;
5623#endif
aurel32eeb438c2008-10-13 21:08:55 +00005624#ifdef TARGET_NR_msgctl
5625 case TARGET_NR_msgctl:
5626 ret = do_msgctl(arg1, arg2, arg3);
5627 break;
5628#endif
5629#ifdef TARGET_NR_msgget
5630 case TARGET_NR_msgget:
5631 ret = get_errno(msgget(arg1, arg2));
5632 break;
5633#endif
5634#ifdef TARGET_NR_msgrcv
5635 case TARGET_NR_msgrcv:
5636 ret = do_msgrcv(arg1, arg2, arg3, arg4, arg5);
5637 break;
5638#endif
5639#ifdef TARGET_NR_msgsnd
5640 case TARGET_NR_msgsnd:
5641 ret = do_msgsnd(arg1, arg2, arg3, arg4);
5642 break;
5643#endif
Riku Voipio88a8c982009-04-03 10:42:00 +03005644#ifdef TARGET_NR_shmget
5645 case TARGET_NR_shmget:
5646 ret = get_errno(shmget(arg1, arg2, arg3));
5647 break;
5648#endif
5649#ifdef TARGET_NR_shmctl
5650 case TARGET_NR_shmctl:
5651 ret = do_shmctl(arg1, arg2, arg3);
5652 break;
5653#endif
5654#ifdef TARGET_NR_shmat
5655 case TARGET_NR_shmat:
5656 ret = do_shmat(arg1, arg2, arg3);
5657 break;
5658#endif
5659#ifdef TARGET_NR_shmdt
5660 case TARGET_NR_shmdt:
5661 ret = do_shmdt(arg1);
5662 break;
5663#endif
bellard31e31b82003-02-18 22:55:36 +00005664 case TARGET_NR_fsync:
5665 ret = get_errno(fsync(arg1));
5666 break;
bellard31e31b82003-02-18 22:55:36 +00005667 case TARGET_NR_clone:
aurel320b6d3ae2008-09-15 07:43:43 +00005668#if defined(TARGET_SH4)
5669 ret = get_errno(do_fork(cpu_env, arg1, arg2, arg3, arg5, arg4));
edgar_iglb15ad612009-01-07 19:43:47 +00005670#elif defined(TARGET_CRIS)
5671 ret = get_errno(do_fork(cpu_env, arg2, arg1, arg3, arg4, arg5));
aurel320b6d3ae2008-09-15 07:43:43 +00005672#else
pbrookd865bab2008-06-07 22:12:17 +00005673 ret = get_errno(do_fork(cpu_env, arg1, arg2, arg3, arg4, arg5));
aurel320b6d3ae2008-09-15 07:43:43 +00005674#endif
bellard1b6b0292003-03-22 17:31:38 +00005675 break;
bellardec86b0f2003-04-11 00:15:04 +00005676#ifdef __NR_exit_group
5677 /* new thread calls */
5678 case TARGET_NR_exit_group:
Juan Quintela9788c9c2009-07-27 16:13:02 +02005679#ifdef TARGET_GPROF
aurel326d946cd2008-11-06 16:15:18 +00005680 _mcleanup();
5681#endif
bellarde9009672005-04-26 20:42:36 +00005682 gdb_exit(cpu_env, arg1);
bellardec86b0f2003-04-11 00:15:04 +00005683 ret = get_errno(exit_group(arg1));
5684 break;
5685#endif
bellard31e31b82003-02-18 22:55:36 +00005686 case TARGET_NR_setdomainname:
bellard579a97f2007-11-11 14:26:47 +00005687 if (!(p = lock_user_string(arg1)))
5688 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005689 ret = get_errno(setdomainname(p, arg2));
5690 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00005691 break;
5692 case TARGET_NR_uname:
5693 /* no need to transcode because we use the linux syscall */
bellard29e619b2004-09-13 21:41:04 +00005694 {
5695 struct new_utsname * buf;
ths3b46e622007-09-17 08:09:54 +00005696
bellard579a97f2007-11-11 14:26:47 +00005697 if (!lock_user_struct(VERIFY_WRITE, buf, arg1, 0))
5698 goto efault;
bellard29e619b2004-09-13 21:41:04 +00005699 ret = get_errno(sys_uname(buf));
5700 if (!is_error(ret)) {
5701 /* Overrite the native machine name with whatever is being
5702 emulated. */
5703 strcpy (buf->machine, UNAME_MACHINE);
pbrookc5937222006-05-14 11:30:38 +00005704 /* Allow the user to override the reported release. */
5705 if (qemu_uname_release && *qemu_uname_release)
5706 strcpy (buf->release, qemu_uname_release);
bellard29e619b2004-09-13 21:41:04 +00005707 }
pbrook53a59602006-03-25 19:31:22 +00005708 unlock_user_struct(buf, arg1, 1);
bellard29e619b2004-09-13 21:41:04 +00005709 }
bellard31e31b82003-02-18 22:55:36 +00005710 break;
bellard6dbad632003-03-16 18:05:05 +00005711#ifdef TARGET_I386
bellard31e31b82003-02-18 22:55:36 +00005712 case TARGET_NR_modify_ldt:
bellard03acab62007-11-11 14:57:14 +00005713 ret = do_modify_ldt(cpu_env, arg1, arg2, arg3);
bellard5cd43932003-03-29 16:54:36 +00005714 break;
j_mayer84409dd2007-04-06 08:56:50 +00005715#if !defined(TARGET_X86_64)
bellard5cd43932003-03-29 16:54:36 +00005716 case TARGET_NR_vm86old:
5717 goto unimplemented;
5718 case TARGET_NR_vm86:
pbrook53a59602006-03-25 19:31:22 +00005719 ret = do_vm86(cpu_env, arg1, arg2);
bellard6dbad632003-03-16 18:05:05 +00005720 break;
5721#endif
j_mayer84409dd2007-04-06 08:56:50 +00005722#endif
bellard31e31b82003-02-18 22:55:36 +00005723 case TARGET_NR_adjtimex:
5724 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00005725#ifdef TARGET_NR_create_module
bellard31e31b82003-02-18 22:55:36 +00005726 case TARGET_NR_create_module:
thse5febef2007-04-01 18:31:35 +00005727#endif
bellard31e31b82003-02-18 22:55:36 +00005728 case TARGET_NR_init_module:
5729 case TARGET_NR_delete_module:
thse5febef2007-04-01 18:31:35 +00005730#ifdef TARGET_NR_get_kernel_syms
bellard31e31b82003-02-18 22:55:36 +00005731 case TARGET_NR_get_kernel_syms:
thse5febef2007-04-01 18:31:35 +00005732#endif
bellard31e31b82003-02-18 22:55:36 +00005733 goto unimplemented;
5734 case TARGET_NR_quotactl:
5735 goto unimplemented;
5736 case TARGET_NR_getpgid:
5737 ret = get_errno(getpgid(arg1));
5738 break;
5739 case TARGET_NR_fchdir:
5740 ret = get_errno(fchdir(arg1));
5741 break;
j_mayer84409dd2007-04-06 08:56:50 +00005742#ifdef TARGET_NR_bdflush /* not on x86_64 */
bellard31e31b82003-02-18 22:55:36 +00005743 case TARGET_NR_bdflush:
5744 goto unimplemented;
j_mayer84409dd2007-04-06 08:56:50 +00005745#endif
thse5febef2007-04-01 18:31:35 +00005746#ifdef TARGET_NR_sysfs
bellard31e31b82003-02-18 22:55:36 +00005747 case TARGET_NR_sysfs:
5748 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00005749#endif
bellard31e31b82003-02-18 22:55:36 +00005750 case TARGET_NR_personality:
bellard1b6b0292003-03-22 17:31:38 +00005751 ret = get_errno(personality(arg1));
bellard31e31b82003-02-18 22:55:36 +00005752 break;
thse5febef2007-04-01 18:31:35 +00005753#ifdef TARGET_NR_afs_syscall
bellard31e31b82003-02-18 22:55:36 +00005754 case TARGET_NR_afs_syscall:
5755 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00005756#endif
j_mayer7a3148a2007-04-05 07:13:51 +00005757#ifdef TARGET_NR__llseek /* Not on alpha */
bellard31e31b82003-02-18 22:55:36 +00005758 case TARGET_NR__llseek:
5759 {
bellard4f2ac232004-04-26 19:44:02 +00005760#if defined (__x86_64__)
5761 ret = get_errno(lseek(arg1, ((uint64_t )arg2 << 32) | arg3, arg5));
bellard2f619692007-11-16 10:46:05 +00005762 if (put_user_s64(ret, arg4))
5763 goto efault;
bellard4f2ac232004-04-26 19:44:02 +00005764#else
bellard31e31b82003-02-18 22:55:36 +00005765 int64_t res;
5766 ret = get_errno(_llseek(arg1, arg2, arg3, &res, arg5));
bellard2f619692007-11-16 10:46:05 +00005767 if (put_user_s64(res, arg4))
5768 goto efault;
bellard4f2ac232004-04-26 19:44:02 +00005769#endif
bellard31e31b82003-02-18 22:55:36 +00005770 }
5771 break;
j_mayer7a3148a2007-04-05 07:13:51 +00005772#endif
bellard31e31b82003-02-18 22:55:36 +00005773 case TARGET_NR_getdents:
blueswir1992f48a2007-10-14 16:27:31 +00005774#if TARGET_ABI_BITS != 32
pbrook53a59602006-03-25 19:31:22 +00005775 goto unimplemented;
blueswir1992f48a2007-10-14 16:27:31 +00005776#elif TARGET_ABI_BITS == 32 && HOST_LONG_BITS == 64
bellard4add45b2003-06-05 01:52:59 +00005777 {
pbrook53a59602006-03-25 19:31:22 +00005778 struct target_dirent *target_dirp;
aurel326556a832008-10-13 21:08:17 +00005779 struct linux_dirent *dirp;
blueswir1992f48a2007-10-14 16:27:31 +00005780 abi_long count = arg3;
bellard4add45b2003-06-05 01:52:59 +00005781
5782 dirp = malloc(count);
ths0da46a62007-10-20 20:23:07 +00005783 if (!dirp) {
bellard579a97f2007-11-11 14:26:47 +00005784 ret = -TARGET_ENOMEM;
ths0da46a62007-10-20 20:23:07 +00005785 goto fail;
5786 }
ths3b46e622007-09-17 08:09:54 +00005787
bellard4add45b2003-06-05 01:52:59 +00005788 ret = get_errno(sys_getdents(arg1, dirp, count));
5789 if (!is_error(ret)) {
aurel326556a832008-10-13 21:08:17 +00005790 struct linux_dirent *de;
bellard4add45b2003-06-05 01:52:59 +00005791 struct target_dirent *tde;
5792 int len = ret;
5793 int reclen, treclen;
5794 int count1, tnamelen;
5795
5796 count1 = 0;
5797 de = dirp;
bellard579a97f2007-11-11 14:26:47 +00005798 if (!(target_dirp = lock_user(VERIFY_WRITE, arg2, count, 0)))
5799 goto efault;
bellard4add45b2003-06-05 01:52:59 +00005800 tde = target_dirp;
5801 while (len > 0) {
5802 reclen = de->d_reclen;
blueswir1992f48a2007-10-14 16:27:31 +00005803 treclen = reclen - (2 * (sizeof(long) - sizeof(abi_long)));
bellard4add45b2003-06-05 01:52:59 +00005804 tde->d_reclen = tswap16(treclen);
5805 tde->d_ino = tswapl(de->d_ino);
5806 tde->d_off = tswapl(de->d_off);
blueswir1992f48a2007-10-14 16:27:31 +00005807 tnamelen = treclen - (2 * sizeof(abi_long) + 2);
bellard4add45b2003-06-05 01:52:59 +00005808 if (tnamelen > 256)
5809 tnamelen = 256;
bellard80a9d032005-01-03 23:31:27 +00005810 /* XXX: may not be correct */
blueswir1be15b142008-10-25 11:21:28 +00005811 pstrcpy(tde->d_name, tnamelen, de->d_name);
aurel326556a832008-10-13 21:08:17 +00005812 de = (struct linux_dirent *)((char *)de + reclen);
bellard4add45b2003-06-05 01:52:59 +00005813 len -= reclen;
j_mayer1c5bf3b2007-04-14 12:17:59 +00005814 tde = (struct target_dirent *)((char *)tde + treclen);
bellard4add45b2003-06-05 01:52:59 +00005815 count1 += treclen;
5816 }
5817 ret = count1;
bellard579a97f2007-11-11 14:26:47 +00005818 unlock_user(target_dirp, arg2, ret);
bellard4add45b2003-06-05 01:52:59 +00005819 }
5820 free(dirp);
5821 }
5822#else
bellard31e31b82003-02-18 22:55:36 +00005823 {
aurel326556a832008-10-13 21:08:17 +00005824 struct linux_dirent *dirp;
blueswir1992f48a2007-10-14 16:27:31 +00005825 abi_long count = arg3;
bellarddab2ed92003-03-22 15:23:14 +00005826
bellard579a97f2007-11-11 14:26:47 +00005827 if (!(dirp = lock_user(VERIFY_WRITE, arg2, count, 0)))
5828 goto efault;
bellard72f03902003-02-18 23:33:18 +00005829 ret = get_errno(sys_getdents(arg1, dirp, count));
bellard31e31b82003-02-18 22:55:36 +00005830 if (!is_error(ret)) {
aurel326556a832008-10-13 21:08:17 +00005831 struct linux_dirent *de;
bellard31e31b82003-02-18 22:55:36 +00005832 int len = ret;
5833 int reclen;
5834 de = dirp;
5835 while (len > 0) {
bellard8083a3e2003-03-24 23:12:16 +00005836 reclen = de->d_reclen;
bellard31e31b82003-02-18 22:55:36 +00005837 if (reclen > len)
5838 break;
bellard8083a3e2003-03-24 23:12:16 +00005839 de->d_reclen = tswap16(reclen);
bellard31e31b82003-02-18 22:55:36 +00005840 tswapls(&de->d_ino);
5841 tswapls(&de->d_off);
aurel326556a832008-10-13 21:08:17 +00005842 de = (struct linux_dirent *)((char *)de + reclen);
bellard31e31b82003-02-18 22:55:36 +00005843 len -= reclen;
5844 }
5845 }
pbrook53a59602006-03-25 19:31:22 +00005846 unlock_user(dirp, arg2, ret);
bellard31e31b82003-02-18 22:55:36 +00005847 }
bellard4add45b2003-06-05 01:52:59 +00005848#endif
bellard31e31b82003-02-18 22:55:36 +00005849 break;
ths3ae43202007-09-16 21:39:48 +00005850#if defined(TARGET_NR_getdents64) && defined(__NR_getdents64)
bellarddab2ed92003-03-22 15:23:14 +00005851 case TARGET_NR_getdents64:
5852 {
aurel326556a832008-10-13 21:08:17 +00005853 struct linux_dirent64 *dirp;
blueswir1992f48a2007-10-14 16:27:31 +00005854 abi_long count = arg3;
bellard579a97f2007-11-11 14:26:47 +00005855 if (!(dirp = lock_user(VERIFY_WRITE, arg2, count, 0)))
5856 goto efault;
bellarddab2ed92003-03-22 15:23:14 +00005857 ret = get_errno(sys_getdents64(arg1, dirp, count));
5858 if (!is_error(ret)) {
aurel326556a832008-10-13 21:08:17 +00005859 struct linux_dirent64 *de;
bellarddab2ed92003-03-22 15:23:14 +00005860 int len = ret;
5861 int reclen;
5862 de = dirp;
5863 while (len > 0) {
bellard8083a3e2003-03-24 23:12:16 +00005864 reclen = de->d_reclen;
bellarddab2ed92003-03-22 15:23:14 +00005865 if (reclen > len)
5866 break;
bellard8083a3e2003-03-24 23:12:16 +00005867 de->d_reclen = tswap16(reclen);
bellard8582a532007-11-11 23:11:36 +00005868 tswap64s((uint64_t *)&de->d_ino);
5869 tswap64s((uint64_t *)&de->d_off);
aurel326556a832008-10-13 21:08:17 +00005870 de = (struct linux_dirent64 *)((char *)de + reclen);
bellarddab2ed92003-03-22 15:23:14 +00005871 len -= reclen;
5872 }
5873 }
pbrook53a59602006-03-25 19:31:22 +00005874 unlock_user(dirp, arg2, ret);
bellarddab2ed92003-03-22 15:23:14 +00005875 }
5876 break;
bellarda541f292004-04-12 20:39:29 +00005877#endif /* TARGET_NR_getdents64 */
thse5febef2007-04-01 18:31:35 +00005878#ifdef TARGET_NR__newselect
bellard31e31b82003-02-18 22:55:36 +00005879 case TARGET_NR__newselect:
pbrook53a59602006-03-25 19:31:22 +00005880 ret = do_select(arg1, arg2, arg3, arg4, arg5);
bellard31e31b82003-02-18 22:55:36 +00005881 break;
thse5febef2007-04-01 18:31:35 +00005882#endif
5883#ifdef TARGET_NR_poll
bellard9de5e442003-03-23 16:49:39 +00005884 case TARGET_NR_poll:
5885 {
pbrook53a59602006-03-25 19:31:22 +00005886 struct target_pollfd *target_pfd;
bellard9de5e442003-03-23 16:49:39 +00005887 unsigned int nfds = arg2;
5888 int timeout = arg3;
5889 struct pollfd *pfd;
bellard7854b052003-03-29 17:22:23 +00005890 unsigned int i;
bellard9de5e442003-03-23 16:49:39 +00005891
bellard579a97f2007-11-11 14:26:47 +00005892 target_pfd = lock_user(VERIFY_WRITE, arg1, sizeof(struct target_pollfd) * nfds, 1);
5893 if (!target_pfd)
5894 goto efault;
bellard9de5e442003-03-23 16:49:39 +00005895 pfd = alloca(sizeof(struct pollfd) * nfds);
5896 for(i = 0; i < nfds; i++) {
bellard5cd43932003-03-29 16:54:36 +00005897 pfd[i].fd = tswap32(target_pfd[i].fd);
5898 pfd[i].events = tswap16(target_pfd[i].events);
bellard9de5e442003-03-23 16:49:39 +00005899 }
5900 ret = get_errno(poll(pfd, nfds, timeout));
5901 if (!is_error(ret)) {
5902 for(i = 0; i < nfds; i++) {
bellard5cd43932003-03-29 16:54:36 +00005903 target_pfd[i].revents = tswap16(pfd[i].revents);
bellard9de5e442003-03-23 16:49:39 +00005904 }
pbrook53a59602006-03-25 19:31:22 +00005905 ret += nfds * (sizeof(struct target_pollfd)
5906 - sizeof(struct pollfd));
bellard9de5e442003-03-23 16:49:39 +00005907 }
pbrook53a59602006-03-25 19:31:22 +00005908 unlock_user(target_pfd, arg1, ret);
bellard9de5e442003-03-23 16:49:39 +00005909 }
5910 break;
thse5febef2007-04-01 18:31:35 +00005911#endif
bellard31e31b82003-02-18 22:55:36 +00005912 case TARGET_NR_flock:
bellard9de5e442003-03-23 16:49:39 +00005913 /* NOTE: the flock constant seems to be the same for every
5914 Linux platform */
5915 ret = get_errno(flock(arg1, arg2));
bellard31e31b82003-02-18 22:55:36 +00005916 break;
5917 case TARGET_NR_readv:
5918 {
5919 int count = arg3;
bellard31e31b82003-02-18 22:55:36 +00005920 struct iovec *vec;
bellard31e31b82003-02-18 22:55:36 +00005921
5922 vec = alloca(count * sizeof(struct iovec));
bellard41df8412008-02-04 22:26:57 +00005923 if (lock_iovec(VERIFY_WRITE, vec, arg2, count, 0) < 0)
5924 goto efault;
bellard31e31b82003-02-18 22:55:36 +00005925 ret = get_errno(readv(arg1, vec, count));
pbrook53a59602006-03-25 19:31:22 +00005926 unlock_iovec(vec, arg2, count, 1);
bellard31e31b82003-02-18 22:55:36 +00005927 }
5928 break;
5929 case TARGET_NR_writev:
5930 {
5931 int count = arg3;
bellard31e31b82003-02-18 22:55:36 +00005932 struct iovec *vec;
bellard31e31b82003-02-18 22:55:36 +00005933
5934 vec = alloca(count * sizeof(struct iovec));
bellard41df8412008-02-04 22:26:57 +00005935 if (lock_iovec(VERIFY_READ, vec, arg2, count, 1) < 0)
5936 goto efault;
bellard31e31b82003-02-18 22:55:36 +00005937 ret = get_errno(writev(arg1, vec, count));
pbrook53a59602006-03-25 19:31:22 +00005938 unlock_iovec(vec, arg2, count, 0);
bellard31e31b82003-02-18 22:55:36 +00005939 }
5940 break;
5941 case TARGET_NR_getsid:
5942 ret = get_errno(getsid(arg1));
5943 break;
j_mayer7a3148a2007-04-05 07:13:51 +00005944#if defined(TARGET_NR_fdatasync) /* Not on alpha (osf_datasync ?) */
bellard31e31b82003-02-18 22:55:36 +00005945 case TARGET_NR_fdatasync:
bellard5cd43932003-03-29 16:54:36 +00005946 ret = get_errno(fdatasync(arg1));
5947 break;
j_mayer7a3148a2007-04-05 07:13:51 +00005948#endif
bellard31e31b82003-02-18 22:55:36 +00005949 case TARGET_NR__sysctl:
ths0da46a62007-10-20 20:23:07 +00005950 /* We don't implement this, but ENOTDIR is always a safe
bellard29e619b2004-09-13 21:41:04 +00005951 return value. */
ths0da46a62007-10-20 20:23:07 +00005952 ret = -TARGET_ENOTDIR;
5953 break;
bellard31e31b82003-02-18 22:55:36 +00005954 case TARGET_NR_sched_setparam:
bellard5cd43932003-03-29 16:54:36 +00005955 {
pbrook53a59602006-03-25 19:31:22 +00005956 struct sched_param *target_schp;
bellard5cd43932003-03-29 16:54:36 +00005957 struct sched_param schp;
pbrook53a59602006-03-25 19:31:22 +00005958
bellard579a97f2007-11-11 14:26:47 +00005959 if (!lock_user_struct(VERIFY_READ, target_schp, arg2, 1))
5960 goto efault;
bellard5cd43932003-03-29 16:54:36 +00005961 schp.sched_priority = tswap32(target_schp->sched_priority);
pbrook53a59602006-03-25 19:31:22 +00005962 unlock_user_struct(target_schp, arg2, 0);
bellard5cd43932003-03-29 16:54:36 +00005963 ret = get_errno(sched_setparam(arg1, &schp));
5964 }
5965 break;
bellard31e31b82003-02-18 22:55:36 +00005966 case TARGET_NR_sched_getparam:
bellard5cd43932003-03-29 16:54:36 +00005967 {
pbrook53a59602006-03-25 19:31:22 +00005968 struct sched_param *target_schp;
bellard5cd43932003-03-29 16:54:36 +00005969 struct sched_param schp;
5970 ret = get_errno(sched_getparam(arg1, &schp));
5971 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00005972 if (!lock_user_struct(VERIFY_WRITE, target_schp, arg2, 0))
5973 goto efault;
bellard5cd43932003-03-29 16:54:36 +00005974 target_schp->sched_priority = tswap32(schp.sched_priority);
pbrook53a59602006-03-25 19:31:22 +00005975 unlock_user_struct(target_schp, arg2, 1);
bellard5cd43932003-03-29 16:54:36 +00005976 }
5977 }
5978 break;
bellard31e31b82003-02-18 22:55:36 +00005979 case TARGET_NR_sched_setscheduler:
bellard5cd43932003-03-29 16:54:36 +00005980 {
pbrook53a59602006-03-25 19:31:22 +00005981 struct sched_param *target_schp;
bellard5cd43932003-03-29 16:54:36 +00005982 struct sched_param schp;
bellard579a97f2007-11-11 14:26:47 +00005983 if (!lock_user_struct(VERIFY_READ, target_schp, arg3, 1))
5984 goto efault;
bellard5cd43932003-03-29 16:54:36 +00005985 schp.sched_priority = tswap32(target_schp->sched_priority);
pbrook53a59602006-03-25 19:31:22 +00005986 unlock_user_struct(target_schp, arg3, 0);
bellard5cd43932003-03-29 16:54:36 +00005987 ret = get_errno(sched_setscheduler(arg1, arg2, &schp));
5988 }
5989 break;
bellard31e31b82003-02-18 22:55:36 +00005990 case TARGET_NR_sched_getscheduler:
bellard5cd43932003-03-29 16:54:36 +00005991 ret = get_errno(sched_getscheduler(arg1));
5992 break;
bellard31e31b82003-02-18 22:55:36 +00005993 case TARGET_NR_sched_yield:
5994 ret = get_errno(sched_yield());
5995 break;
5996 case TARGET_NR_sched_get_priority_max:
bellard5cd43932003-03-29 16:54:36 +00005997 ret = get_errno(sched_get_priority_max(arg1));
5998 break;
bellard31e31b82003-02-18 22:55:36 +00005999 case TARGET_NR_sched_get_priority_min:
bellard5cd43932003-03-29 16:54:36 +00006000 ret = get_errno(sched_get_priority_min(arg1));
6001 break;
bellard31e31b82003-02-18 22:55:36 +00006002 case TARGET_NR_sched_rr_get_interval:
bellard5cd43932003-03-29 16:54:36 +00006003 {
bellard5cd43932003-03-29 16:54:36 +00006004 struct timespec ts;
6005 ret = get_errno(sched_rr_get_interval(arg1, &ts));
6006 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00006007 host_to_target_timespec(arg2, &ts);
bellard5cd43932003-03-29 16:54:36 +00006008 }
6009 }
6010 break;
bellard31e31b82003-02-18 22:55:36 +00006011 case TARGET_NR_nanosleep:
bellard1b6b0292003-03-22 17:31:38 +00006012 {
bellard1b6b0292003-03-22 17:31:38 +00006013 struct timespec req, rem;
pbrook53a59602006-03-25 19:31:22 +00006014 target_to_host_timespec(&req, arg1);
bellard1b6b0292003-03-22 17:31:38 +00006015 ret = get_errno(nanosleep(&req, &rem));
pbrook53a59602006-03-25 19:31:22 +00006016 if (is_error(ret) && arg2) {
6017 host_to_target_timespec(arg2, &rem);
bellard1b6b0292003-03-22 17:31:38 +00006018 }
6019 }
6020 break;
thse5febef2007-04-01 18:31:35 +00006021#ifdef TARGET_NR_query_module
bellard31e31b82003-02-18 22:55:36 +00006022 case TARGET_NR_query_module:
bellard5cd43932003-03-29 16:54:36 +00006023 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00006024#endif
6025#ifdef TARGET_NR_nfsservctl
bellard31e31b82003-02-18 22:55:36 +00006026 case TARGET_NR_nfsservctl:
bellard5cd43932003-03-29 16:54:36 +00006027 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00006028#endif
bellard31e31b82003-02-18 22:55:36 +00006029 case TARGET_NR_prctl:
thse5574482007-02-11 20:03:13 +00006030 switch (arg1)
6031 {
6032 case PR_GET_PDEATHSIG:
6033 {
6034 int deathsig;
6035 ret = get_errno(prctl(arg1, &deathsig, arg3, arg4, arg5));
bellard2f619692007-11-16 10:46:05 +00006036 if (!is_error(ret) && arg2
6037 && put_user_ual(deathsig, arg2))
6038 goto efault;
thse5574482007-02-11 20:03:13 +00006039 }
6040 break;
6041 default:
6042 ret = get_errno(prctl(arg1, arg2, arg3, arg4, arg5));
6043 break;
6044 }
ths39b9aae2007-02-11 18:36:44 +00006045 break;
bellardd2fd1af2007-11-14 18:08:56 +00006046#ifdef TARGET_NR_arch_prctl
6047 case TARGET_NR_arch_prctl:
6048#if defined(TARGET_I386) && !defined(TARGET_ABI32)
6049 ret = do_arch_prctl(cpu_env, arg1, arg2);
6050 break;
6051#else
6052 goto unimplemented;
6053#endif
6054#endif
bellard67867302003-11-23 17:05:30 +00006055#ifdef TARGET_NR_pread
bellard31e31b82003-02-18 22:55:36 +00006056 case TARGET_NR_pread:
balroga4ae00b2008-09-20 03:14:14 +00006057#ifdef TARGET_ARM
6058 if (((CPUARMState *)cpu_env)->eabi)
6059 arg4 = arg5;
6060#endif
bellard579a97f2007-11-11 14:26:47 +00006061 if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
6062 goto efault;
pbrook53a59602006-03-25 19:31:22 +00006063 ret = get_errno(pread(arg1, p, arg3, arg4));
6064 unlock_user(p, arg2, ret);
bellard206f0fa2003-05-14 19:01:56 +00006065 break;
bellard31e31b82003-02-18 22:55:36 +00006066 case TARGET_NR_pwrite:
balroga4ae00b2008-09-20 03:14:14 +00006067#ifdef TARGET_ARM
6068 if (((CPUARMState *)cpu_env)->eabi)
6069 arg4 = arg5;
6070#endif
bellard579a97f2007-11-11 14:26:47 +00006071 if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
6072 goto efault;
pbrook53a59602006-03-25 19:31:22 +00006073 ret = get_errno(pwrite(arg1, p, arg3, arg4));
6074 unlock_user(p, arg2, 0);
bellard206f0fa2003-05-14 19:01:56 +00006075 break;
bellard67867302003-11-23 17:05:30 +00006076#endif
aurel32f2c7ba12008-03-28 22:32:06 +00006077#ifdef TARGET_NR_pread64
6078 case TARGET_NR_pread64:
6079 if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
6080 goto efault;
6081 ret = get_errno(pread64(arg1, p, arg3, target_offset64(arg4, arg5)));
6082 unlock_user(p, arg2, ret);
6083 break;
6084 case TARGET_NR_pwrite64:
6085 if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
6086 goto efault;
6087 ret = get_errno(pwrite64(arg1, p, arg3, target_offset64(arg4, arg5)));
6088 unlock_user(p, arg2, 0);
6089 break;
6090#endif
bellard31e31b82003-02-18 22:55:36 +00006091 case TARGET_NR_getcwd:
bellard579a97f2007-11-11 14:26:47 +00006092 if (!(p = lock_user(VERIFY_WRITE, arg1, arg2, 0)))
6093 goto efault;
pbrook53a59602006-03-25 19:31:22 +00006094 ret = get_errno(sys_getcwd1(p, arg2));
6095 unlock_user(p, arg1, ret);
bellard31e31b82003-02-18 22:55:36 +00006096 break;
6097 case TARGET_NR_capget:
bellard5cd43932003-03-29 16:54:36 +00006098 goto unimplemented;
bellard31e31b82003-02-18 22:55:36 +00006099 case TARGET_NR_capset:
bellard5cd43932003-03-29 16:54:36 +00006100 goto unimplemented;
bellard31e31b82003-02-18 22:55:36 +00006101 case TARGET_NR_sigaltstack:
ths198a74d2007-09-27 16:44:32 +00006102#if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_MIPS) || \
6103 defined(TARGET_SPARC) || defined(TARGET_PPC) || defined(TARGET_ALPHA)
bellard579a97f2007-11-11 14:26:47 +00006104 ret = do_sigaltstack(arg1, arg2, get_sp_from_cpustate((CPUState *)cpu_env));
thsa04e1342007-09-27 13:57:58 +00006105 break;
6106#else
bellard5cd43932003-03-29 16:54:36 +00006107 goto unimplemented;
thsa04e1342007-09-27 13:57:58 +00006108#endif
bellard31e31b82003-02-18 22:55:36 +00006109 case TARGET_NR_sendfile:
bellard5cd43932003-03-29 16:54:36 +00006110 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00006111#ifdef TARGET_NR_getpmsg
bellard31e31b82003-02-18 22:55:36 +00006112 case TARGET_NR_getpmsg:
bellard5cd43932003-03-29 16:54:36 +00006113 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00006114#endif
6115#ifdef TARGET_NR_putpmsg
bellard31e31b82003-02-18 22:55:36 +00006116 case TARGET_NR_putpmsg:
bellard5cd43932003-03-29 16:54:36 +00006117 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00006118#endif
bellard048f6b42005-11-26 18:47:20 +00006119#ifdef TARGET_NR_vfork
bellard31e31b82003-02-18 22:55:36 +00006120 case TARGET_NR_vfork:
pbrookd865bab2008-06-07 22:12:17 +00006121 ret = get_errno(do_fork(cpu_env, CLONE_VFORK | CLONE_VM | SIGCHLD,
6122 0, 0, 0, 0));
bellard31e31b82003-02-18 22:55:36 +00006123 break;
bellard048f6b42005-11-26 18:47:20 +00006124#endif
bellardebc05482003-09-30 21:08:41 +00006125#ifdef TARGET_NR_ugetrlimit
bellard31e31b82003-02-18 22:55:36 +00006126 case TARGET_NR_ugetrlimit:
bellard728584b2003-04-29 20:43:36 +00006127 {
6128 struct rlimit rlim;
6129 ret = get_errno(getrlimit(arg1, &rlim));
6130 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00006131 struct target_rlimit *target_rlim;
bellard579a97f2007-11-11 14:26:47 +00006132 if (!lock_user_struct(VERIFY_WRITE, target_rlim, arg2, 0))
6133 goto efault;
bellard728584b2003-04-29 20:43:36 +00006134 target_rlim->rlim_cur = tswapl(rlim.rlim_cur);
6135 target_rlim->rlim_max = tswapl(rlim.rlim_max);
pbrook53a59602006-03-25 19:31:22 +00006136 unlock_user_struct(target_rlim, arg2, 1);
bellard728584b2003-04-29 20:43:36 +00006137 }
6138 break;
6139 }
bellardebc05482003-09-30 21:08:41 +00006140#endif
bellarda315a142005-01-30 22:59:18 +00006141#ifdef TARGET_NR_truncate64
bellard31e31b82003-02-18 22:55:36 +00006142 case TARGET_NR_truncate64:
bellard579a97f2007-11-11 14:26:47 +00006143 if (!(p = lock_user_string(arg1)))
6144 goto efault;
pbrook53a59602006-03-25 19:31:22 +00006145 ret = target_truncate64(cpu_env, p, arg2, arg3, arg4);
6146 unlock_user(p, arg1, 0);
bellard667f38b2005-07-23 14:46:27 +00006147 break;
bellarda315a142005-01-30 22:59:18 +00006148#endif
6149#ifdef TARGET_NR_ftruncate64
bellard31e31b82003-02-18 22:55:36 +00006150 case TARGET_NR_ftruncate64:
pbrookce4defa2006-02-09 16:49:55 +00006151 ret = target_ftruncate64(cpu_env, arg1, arg2, arg3, arg4);
bellard667f38b2005-07-23 14:46:27 +00006152 break;
bellarda315a142005-01-30 22:59:18 +00006153#endif
6154#ifdef TARGET_NR_stat64
bellard31e31b82003-02-18 22:55:36 +00006155 case TARGET_NR_stat64:
bellard579a97f2007-11-11 14:26:47 +00006156 if (!(p = lock_user_string(arg1)))
6157 goto efault;
pbrook53a59602006-03-25 19:31:22 +00006158 ret = get_errno(stat(path(p), &st));
6159 unlock_user(p, arg1, 0);
balrog6a24a772008-09-20 02:23:36 +00006160 if (!is_error(ret))
6161 ret = host_to_target_stat64(cpu_env, arg2, &st);
6162 break;
bellarda315a142005-01-30 22:59:18 +00006163#endif
6164#ifdef TARGET_NR_lstat64
bellard31e31b82003-02-18 22:55:36 +00006165 case TARGET_NR_lstat64:
bellard579a97f2007-11-11 14:26:47 +00006166 if (!(p = lock_user_string(arg1)))
6167 goto efault;
pbrook53a59602006-03-25 19:31:22 +00006168 ret = get_errno(lstat(path(p), &st));
6169 unlock_user(p, arg1, 0);
balrog6a24a772008-09-20 02:23:36 +00006170 if (!is_error(ret))
6171 ret = host_to_target_stat64(cpu_env, arg2, &st);
6172 break;
bellarda315a142005-01-30 22:59:18 +00006173#endif
6174#ifdef TARGET_NR_fstat64
bellard31e31b82003-02-18 22:55:36 +00006175 case TARGET_NR_fstat64:
balrog6a24a772008-09-20 02:23:36 +00006176 ret = get_errno(fstat(arg1, &st));
6177 if (!is_error(ret))
6178 ret = host_to_target_stat64(cpu_env, arg2, &st);
6179 break;
bellardec86b0f2003-04-11 00:15:04 +00006180#endif
aurel329d33b762009-04-08 23:07:05 +00006181#if (defined(TARGET_NR_fstatat64) || defined(TARGET_NR_newfstatat)) && \
6182 (defined(__NR_fstatat64) || defined(__NR_newfstatat))
6183#ifdef TARGET_NR_fstatat64
balrog6a24a772008-09-20 02:23:36 +00006184 case TARGET_NR_fstatat64:
aurel329d33b762009-04-08 23:07:05 +00006185#endif
6186#ifdef TARGET_NR_newfstatat
6187 case TARGET_NR_newfstatat:
6188#endif
balrog6a24a772008-09-20 02:23:36 +00006189 if (!(p = lock_user_string(arg2)))
6190 goto efault;
aurel329d33b762009-04-08 23:07:05 +00006191#ifdef __NR_fstatat64
balrog6a24a772008-09-20 02:23:36 +00006192 ret = get_errno(sys_fstatat64(arg1, path(p), &st, arg4));
aurel329d33b762009-04-08 23:07:05 +00006193#else
6194 ret = get_errno(sys_newfstatat(arg1, path(p), &st, arg4));
6195#endif
balrog6a24a772008-09-20 02:23:36 +00006196 if (!is_error(ret))
6197 ret = host_to_target_stat64(cpu_env, arg3, &st);
bellard60cd49d2003-03-16 22:53:56 +00006198 break;
bellarda315a142005-01-30 22:59:18 +00006199#endif
bellard67867302003-11-23 17:05:30 +00006200#ifdef USE_UID16
6201 case TARGET_NR_lchown:
bellard579a97f2007-11-11 14:26:47 +00006202 if (!(p = lock_user_string(arg1)))
6203 goto efault;
pbrook53a59602006-03-25 19:31:22 +00006204 ret = get_errno(lchown(p, low2highuid(arg2), low2highgid(arg3)));
6205 unlock_user(p, arg1, 0);
bellard67867302003-11-23 17:05:30 +00006206 break;
6207 case TARGET_NR_getuid:
6208 ret = get_errno(high2lowuid(getuid()));
6209 break;
6210 case TARGET_NR_getgid:
6211 ret = get_errno(high2lowgid(getgid()));
6212 break;
6213 case TARGET_NR_geteuid:
6214 ret = get_errno(high2lowuid(geteuid()));
6215 break;
6216 case TARGET_NR_getegid:
6217 ret = get_errno(high2lowgid(getegid()));
6218 break;
6219 case TARGET_NR_setreuid:
6220 ret = get_errno(setreuid(low2highuid(arg1), low2highuid(arg2)));
6221 break;
6222 case TARGET_NR_setregid:
6223 ret = get_errno(setregid(low2highgid(arg1), low2highgid(arg2)));
6224 break;
6225 case TARGET_NR_getgroups:
6226 {
6227 int gidsetsize = arg1;
pbrook53a59602006-03-25 19:31:22 +00006228 uint16_t *target_grouplist;
bellard67867302003-11-23 17:05:30 +00006229 gid_t *grouplist;
6230 int i;
6231
6232 grouplist = alloca(gidsetsize * sizeof(gid_t));
6233 ret = get_errno(getgroups(gidsetsize, grouplist));
balrogcb3bc232008-09-20 02:08:13 +00006234 if (gidsetsize == 0)
6235 break;
bellard67867302003-11-23 17:05:30 +00006236 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00006237 target_grouplist = lock_user(VERIFY_WRITE, arg2, gidsetsize * 2, 0);
6238 if (!target_grouplist)
6239 goto efault;
balroga2155fc2008-09-20 02:12:08 +00006240 for(i = 0;i < ret; i++)
bellard67867302003-11-23 17:05:30 +00006241 target_grouplist[i] = tswap16(grouplist[i]);
pbrook53a59602006-03-25 19:31:22 +00006242 unlock_user(target_grouplist, arg2, gidsetsize * 2);
bellard67867302003-11-23 17:05:30 +00006243 }
6244 }
6245 break;
6246 case TARGET_NR_setgroups:
6247 {
6248 int gidsetsize = arg1;
pbrook53a59602006-03-25 19:31:22 +00006249 uint16_t *target_grouplist;
bellard67867302003-11-23 17:05:30 +00006250 gid_t *grouplist;
6251 int i;
6252
6253 grouplist = alloca(gidsetsize * sizeof(gid_t));
bellard579a97f2007-11-11 14:26:47 +00006254 target_grouplist = lock_user(VERIFY_READ, arg2, gidsetsize * 2, 1);
6255 if (!target_grouplist) {
6256 ret = -TARGET_EFAULT;
6257 goto fail;
6258 }
bellard67867302003-11-23 17:05:30 +00006259 for(i = 0;i < gidsetsize; i++)
6260 grouplist[i] = tswap16(target_grouplist[i]);
pbrook53a59602006-03-25 19:31:22 +00006261 unlock_user(target_grouplist, arg2, 0);
bellard67867302003-11-23 17:05:30 +00006262 ret = get_errno(setgroups(gidsetsize, grouplist));
6263 }
6264 break;
6265 case TARGET_NR_fchown:
6266 ret = get_errno(fchown(arg1, low2highuid(arg2), low2highgid(arg3)));
6267 break;
thsccfa72b2007-09-24 09:23:34 +00006268#if defined(TARGET_NR_fchownat) && defined(__NR_fchownat)
6269 case TARGET_NR_fchownat:
bellard579a97f2007-11-11 14:26:47 +00006270 if (!(p = lock_user_string(arg2)))
6271 goto efault;
6272 ret = get_errno(sys_fchownat(arg1, p, low2highuid(arg3), low2highgid(arg4), arg5));
6273 unlock_user(p, arg2, 0);
thsccfa72b2007-09-24 09:23:34 +00006274 break;
6275#endif
bellard67867302003-11-23 17:05:30 +00006276#ifdef TARGET_NR_setresuid
6277 case TARGET_NR_setresuid:
ths5fafdf22007-09-16 21:08:06 +00006278 ret = get_errno(setresuid(low2highuid(arg1),
6279 low2highuid(arg2),
bellard67867302003-11-23 17:05:30 +00006280 low2highuid(arg3)));
6281 break;
6282#endif
6283#ifdef TARGET_NR_getresuid
6284 case TARGET_NR_getresuid:
6285 {
pbrook53a59602006-03-25 19:31:22 +00006286 uid_t ruid, euid, suid;
bellard67867302003-11-23 17:05:30 +00006287 ret = get_errno(getresuid(&ruid, &euid, &suid));
6288 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +00006289 if (put_user_u16(high2lowuid(ruid), arg1)
6290 || put_user_u16(high2lowuid(euid), arg2)
6291 || put_user_u16(high2lowuid(suid), arg3))
6292 goto efault;
bellard67867302003-11-23 17:05:30 +00006293 }
6294 }
6295 break;
6296#endif
6297#ifdef TARGET_NR_getresgid
6298 case TARGET_NR_setresgid:
ths5fafdf22007-09-16 21:08:06 +00006299 ret = get_errno(setresgid(low2highgid(arg1),
6300 low2highgid(arg2),
bellard67867302003-11-23 17:05:30 +00006301 low2highgid(arg3)));
6302 break;
6303#endif
6304#ifdef TARGET_NR_getresgid
6305 case TARGET_NR_getresgid:
6306 {
pbrook53a59602006-03-25 19:31:22 +00006307 gid_t rgid, egid, sgid;
bellard67867302003-11-23 17:05:30 +00006308 ret = get_errno(getresgid(&rgid, &egid, &sgid));
6309 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +00006310 if (put_user_u16(high2lowgid(rgid), arg1)
6311 || put_user_u16(high2lowgid(egid), arg2)
6312 || put_user_u16(high2lowgid(sgid), arg3))
6313 goto efault;
bellard67867302003-11-23 17:05:30 +00006314 }
6315 }
6316 break;
6317#endif
6318 case TARGET_NR_chown:
bellard579a97f2007-11-11 14:26:47 +00006319 if (!(p = lock_user_string(arg1)))
6320 goto efault;
pbrook53a59602006-03-25 19:31:22 +00006321 ret = get_errno(chown(p, low2highuid(arg2), low2highgid(arg3)));
6322 unlock_user(p, arg1, 0);
bellard67867302003-11-23 17:05:30 +00006323 break;
6324 case TARGET_NR_setuid:
6325 ret = get_errno(setuid(low2highuid(arg1)));
6326 break;
6327 case TARGET_NR_setgid:
6328 ret = get_errno(setgid(low2highgid(arg1)));
6329 break;
6330 case TARGET_NR_setfsuid:
6331 ret = get_errno(setfsuid(arg1));
6332 break;
6333 case TARGET_NR_setfsgid:
6334 ret = get_errno(setfsgid(arg1));
6335 break;
6336#endif /* USE_UID16 */
6337
bellarda315a142005-01-30 22:59:18 +00006338#ifdef TARGET_NR_lchown32
bellard31e31b82003-02-18 22:55:36 +00006339 case TARGET_NR_lchown32:
bellard579a97f2007-11-11 14:26:47 +00006340 if (!(p = lock_user_string(arg1)))
6341 goto efault;
pbrook53a59602006-03-25 19:31:22 +00006342 ret = get_errno(lchown(p, arg2, arg3));
6343 unlock_user(p, arg1, 0);
bellardb03c60f2003-03-23 17:19:56 +00006344 break;
bellarda315a142005-01-30 22:59:18 +00006345#endif
6346#ifdef TARGET_NR_getuid32
bellard31e31b82003-02-18 22:55:36 +00006347 case TARGET_NR_getuid32:
bellardb03c60f2003-03-23 17:19:56 +00006348 ret = get_errno(getuid());
6349 break;
bellarda315a142005-01-30 22:59:18 +00006350#endif
aurel3264b4d282008-11-14 17:20:15 +00006351
6352#if defined(TARGET_NR_getxuid) && defined(TARGET_ALPHA)
6353 /* Alpha specific */
6354 case TARGET_NR_getxuid:
6355 {
6356 uid_t euid;
6357 euid=geteuid();
6358 ((CPUAlphaState *)cpu_env)->ir[IR_A4]=euid;
6359 }
6360 ret = get_errno(getuid());
6361 break;
6362#endif
6363#if defined(TARGET_NR_getxgid) && defined(TARGET_ALPHA)
6364 /* Alpha specific */
6365 case TARGET_NR_getxgid:
6366 {
6367 uid_t egid;
6368 egid=getegid();
6369 ((CPUAlphaState *)cpu_env)->ir[IR_A4]=egid;
6370 }
6371 ret = get_errno(getgid());
6372 break;
6373#endif
6374
bellarda315a142005-01-30 22:59:18 +00006375#ifdef TARGET_NR_getgid32
bellard31e31b82003-02-18 22:55:36 +00006376 case TARGET_NR_getgid32:
bellardb03c60f2003-03-23 17:19:56 +00006377 ret = get_errno(getgid());
6378 break;
bellarda315a142005-01-30 22:59:18 +00006379#endif
6380#ifdef TARGET_NR_geteuid32
bellard31e31b82003-02-18 22:55:36 +00006381 case TARGET_NR_geteuid32:
bellardb03c60f2003-03-23 17:19:56 +00006382 ret = get_errno(geteuid());
6383 break;
bellarda315a142005-01-30 22:59:18 +00006384#endif
6385#ifdef TARGET_NR_getegid32
bellard31e31b82003-02-18 22:55:36 +00006386 case TARGET_NR_getegid32:
bellardb03c60f2003-03-23 17:19:56 +00006387 ret = get_errno(getegid());
6388 break;
bellarda315a142005-01-30 22:59:18 +00006389#endif
6390#ifdef TARGET_NR_setreuid32
bellard31e31b82003-02-18 22:55:36 +00006391 case TARGET_NR_setreuid32:
bellardb03c60f2003-03-23 17:19:56 +00006392 ret = get_errno(setreuid(arg1, arg2));
6393 break;
bellarda315a142005-01-30 22:59:18 +00006394#endif
6395#ifdef TARGET_NR_setregid32
bellard31e31b82003-02-18 22:55:36 +00006396 case TARGET_NR_setregid32:
bellardb03c60f2003-03-23 17:19:56 +00006397 ret = get_errno(setregid(arg1, arg2));
6398 break;
bellarda315a142005-01-30 22:59:18 +00006399#endif
6400#ifdef TARGET_NR_getgroups32
bellard31e31b82003-02-18 22:55:36 +00006401 case TARGET_NR_getgroups32:
bellard99c475a2005-01-31 20:45:13 +00006402 {
6403 int gidsetsize = arg1;
pbrook53a59602006-03-25 19:31:22 +00006404 uint32_t *target_grouplist;
bellard99c475a2005-01-31 20:45:13 +00006405 gid_t *grouplist;
6406 int i;
6407
6408 grouplist = alloca(gidsetsize * sizeof(gid_t));
6409 ret = get_errno(getgroups(gidsetsize, grouplist));
balrogcb3bc232008-09-20 02:08:13 +00006410 if (gidsetsize == 0)
6411 break;
bellard99c475a2005-01-31 20:45:13 +00006412 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00006413 target_grouplist = lock_user(VERIFY_WRITE, arg2, gidsetsize * 4, 0);
6414 if (!target_grouplist) {
6415 ret = -TARGET_EFAULT;
6416 goto fail;
6417 }
balroga2155fc2008-09-20 02:12:08 +00006418 for(i = 0;i < ret; i++)
pbrook53a59602006-03-25 19:31:22 +00006419 target_grouplist[i] = tswap32(grouplist[i]);
6420 unlock_user(target_grouplist, arg2, gidsetsize * 4);
bellard99c475a2005-01-31 20:45:13 +00006421 }
6422 }
6423 break;
bellarda315a142005-01-30 22:59:18 +00006424#endif
6425#ifdef TARGET_NR_setgroups32
bellard31e31b82003-02-18 22:55:36 +00006426 case TARGET_NR_setgroups32:
bellard99c475a2005-01-31 20:45:13 +00006427 {
6428 int gidsetsize = arg1;
pbrook53a59602006-03-25 19:31:22 +00006429 uint32_t *target_grouplist;
bellard99c475a2005-01-31 20:45:13 +00006430 gid_t *grouplist;
6431 int i;
ths3b46e622007-09-17 08:09:54 +00006432
bellard99c475a2005-01-31 20:45:13 +00006433 grouplist = alloca(gidsetsize * sizeof(gid_t));
bellard579a97f2007-11-11 14:26:47 +00006434 target_grouplist = lock_user(VERIFY_READ, arg2, gidsetsize * 4, 1);
6435 if (!target_grouplist) {
6436 ret = -TARGET_EFAULT;
6437 goto fail;
6438 }
bellard99c475a2005-01-31 20:45:13 +00006439 for(i = 0;i < gidsetsize; i++)
pbrook53a59602006-03-25 19:31:22 +00006440 grouplist[i] = tswap32(target_grouplist[i]);
6441 unlock_user(target_grouplist, arg2, 0);
bellard99c475a2005-01-31 20:45:13 +00006442 ret = get_errno(setgroups(gidsetsize, grouplist));
6443 }
6444 break;
bellarda315a142005-01-30 22:59:18 +00006445#endif
6446#ifdef TARGET_NR_fchown32
bellard31e31b82003-02-18 22:55:36 +00006447 case TARGET_NR_fchown32:
bellardb03c60f2003-03-23 17:19:56 +00006448 ret = get_errno(fchown(arg1, arg2, arg3));
6449 break;
bellarda315a142005-01-30 22:59:18 +00006450#endif
6451#ifdef TARGET_NR_setresuid32
bellard31e31b82003-02-18 22:55:36 +00006452 case TARGET_NR_setresuid32:
bellardb03c60f2003-03-23 17:19:56 +00006453 ret = get_errno(setresuid(arg1, arg2, arg3));
6454 break;
bellarda315a142005-01-30 22:59:18 +00006455#endif
6456#ifdef TARGET_NR_getresuid32
bellard31e31b82003-02-18 22:55:36 +00006457 case TARGET_NR_getresuid32:
bellardb03c60f2003-03-23 17:19:56 +00006458 {
pbrook53a59602006-03-25 19:31:22 +00006459 uid_t ruid, euid, suid;
bellardb03c60f2003-03-23 17:19:56 +00006460 ret = get_errno(getresuid(&ruid, &euid, &suid));
6461 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +00006462 if (put_user_u32(ruid, arg1)
6463 || put_user_u32(euid, arg2)
6464 || put_user_u32(suid, arg3))
6465 goto efault;
bellardb03c60f2003-03-23 17:19:56 +00006466 }
6467 }
6468 break;
bellarda315a142005-01-30 22:59:18 +00006469#endif
6470#ifdef TARGET_NR_setresgid32
bellard31e31b82003-02-18 22:55:36 +00006471 case TARGET_NR_setresgid32:
bellardb03c60f2003-03-23 17:19:56 +00006472 ret = get_errno(setresgid(arg1, arg2, arg3));
6473 break;
bellarda315a142005-01-30 22:59:18 +00006474#endif
6475#ifdef TARGET_NR_getresgid32
bellard31e31b82003-02-18 22:55:36 +00006476 case TARGET_NR_getresgid32:
bellardb03c60f2003-03-23 17:19:56 +00006477 {
pbrook53a59602006-03-25 19:31:22 +00006478 gid_t rgid, egid, sgid;
bellardb03c60f2003-03-23 17:19:56 +00006479 ret = get_errno(getresgid(&rgid, &egid, &sgid));
6480 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +00006481 if (put_user_u32(rgid, arg1)
6482 || put_user_u32(egid, arg2)
6483 || put_user_u32(sgid, arg3))
6484 goto efault;
bellardb03c60f2003-03-23 17:19:56 +00006485 }
6486 }
6487 break;
bellarda315a142005-01-30 22:59:18 +00006488#endif
6489#ifdef TARGET_NR_chown32
bellard31e31b82003-02-18 22:55:36 +00006490 case TARGET_NR_chown32:
bellard579a97f2007-11-11 14:26:47 +00006491 if (!(p = lock_user_string(arg1)))
6492 goto efault;
pbrook53a59602006-03-25 19:31:22 +00006493 ret = get_errno(chown(p, arg2, arg3));
6494 unlock_user(p, arg1, 0);
bellardb03c60f2003-03-23 17:19:56 +00006495 break;
bellarda315a142005-01-30 22:59:18 +00006496#endif
6497#ifdef TARGET_NR_setuid32
bellard31e31b82003-02-18 22:55:36 +00006498 case TARGET_NR_setuid32:
bellardb03c60f2003-03-23 17:19:56 +00006499 ret = get_errno(setuid(arg1));
6500 break;
bellarda315a142005-01-30 22:59:18 +00006501#endif
6502#ifdef TARGET_NR_setgid32
bellard31e31b82003-02-18 22:55:36 +00006503 case TARGET_NR_setgid32:
bellardb03c60f2003-03-23 17:19:56 +00006504 ret = get_errno(setgid(arg1));
6505 break;
bellarda315a142005-01-30 22:59:18 +00006506#endif
6507#ifdef TARGET_NR_setfsuid32
bellard31e31b82003-02-18 22:55:36 +00006508 case TARGET_NR_setfsuid32:
bellardb03c60f2003-03-23 17:19:56 +00006509 ret = get_errno(setfsuid(arg1));
6510 break;
bellarda315a142005-01-30 22:59:18 +00006511#endif
6512#ifdef TARGET_NR_setfsgid32
bellard31e31b82003-02-18 22:55:36 +00006513 case TARGET_NR_setfsgid32:
bellardb03c60f2003-03-23 17:19:56 +00006514 ret = get_errno(setfsgid(arg1));
6515 break;
bellarda315a142005-01-30 22:59:18 +00006516#endif
bellard67867302003-11-23 17:05:30 +00006517
bellard31e31b82003-02-18 22:55:36 +00006518 case TARGET_NR_pivot_root:
bellardb03c60f2003-03-23 17:19:56 +00006519 goto unimplemented;
bellardffa65c32004-01-04 23:57:22 +00006520#ifdef TARGET_NR_mincore
bellard31e31b82003-02-18 22:55:36 +00006521 case TARGET_NR_mincore:
aurel3204bb9ac2008-10-01 21:46:41 +00006522 {
6523 void *a;
6524 ret = -TARGET_EFAULT;
6525 if (!(a = lock_user(VERIFY_READ, arg1,arg2, 0)))
6526 goto efault;
6527 if (!(p = lock_user_string(arg3)))
6528 goto mincore_fail;
6529 ret = get_errno(mincore(a, arg2, p));
6530 unlock_user(p, arg3, ret);
6531 mincore_fail:
6532 unlock_user(a, arg1, 0);
6533 }
6534 break;
bellardffa65c32004-01-04 23:57:22 +00006535#endif
aurel32408321b2008-10-01 21:46:32 +00006536#ifdef TARGET_NR_arm_fadvise64_64
6537 case TARGET_NR_arm_fadvise64_64:
6538 {
6539 /*
6540 * arm_fadvise64_64 looks like fadvise64_64 but
6541 * with different argument order
6542 */
6543 abi_long temp;
6544 temp = arg3;
6545 arg3 = arg4;
6546 arg4 = temp;
6547 }
6548#endif
6549#if defined(TARGET_NR_fadvise64_64) || defined(TARGET_NR_arm_fadvise64_64)
6550#ifdef TARGET_NR_fadvise64_64
6551 case TARGET_NR_fadvise64_64:
6552#endif
6553 /* This is a hint, so ignoring and returning success is ok. */
6554 ret = get_errno(0);
6555 break;
6556#endif
bellardffa65c32004-01-04 23:57:22 +00006557#ifdef TARGET_NR_madvise
bellard31e31b82003-02-18 22:55:36 +00006558 case TARGET_NR_madvise:
pbrook24836682006-04-16 14:14:53 +00006559 /* A straight passthrough may not be safe because qemu sometimes
6560 turns private flie-backed mappings into anonymous mappings.
6561 This will break MADV_DONTNEED.
6562 This is a hint, so ignoring and returning success is ok. */
6563 ret = get_errno(0);
6564 break;
bellardffa65c32004-01-04 23:57:22 +00006565#endif
blueswir1992f48a2007-10-14 16:27:31 +00006566#if TARGET_ABI_BITS == 32
bellard31e31b82003-02-18 22:55:36 +00006567 case TARGET_NR_fcntl64:
bellard77e46722003-04-29 20:39:06 +00006568 {
thsb1e341e2007-03-20 21:50:52 +00006569 int cmd;
bellard77e46722003-04-29 20:39:06 +00006570 struct flock64 fl;
pbrook53a59602006-03-25 19:31:22 +00006571 struct target_flock64 *target_fl;
pbrookce4defa2006-02-09 16:49:55 +00006572#ifdef TARGET_ARM
pbrook53a59602006-03-25 19:31:22 +00006573 struct target_eabi_flock64 *target_efl;
pbrookce4defa2006-02-09 16:49:55 +00006574#endif
bellard77e46722003-04-29 20:39:06 +00006575
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02006576 cmd = target_to_host_fcntl_cmd(arg2);
6577 if (cmd == -TARGET_EINVAL)
6578 return cmd;
thsb1e341e2007-03-20 21:50:52 +00006579
bellard60cd49d2003-03-16 22:53:56 +00006580 switch(arg2) {
thsb1e341e2007-03-20 21:50:52 +00006581 case TARGET_F_GETLK64:
ths58134272007-03-31 18:59:32 +00006582#ifdef TARGET_ARM
6583 if (((CPUARMState *)cpu_env)->eabi) {
bellard9ee1fa22007-11-11 15:11:19 +00006584 if (!lock_user_struct(VERIFY_READ, target_efl, arg3, 1))
6585 goto efault;
ths58134272007-03-31 18:59:32 +00006586 fl.l_type = tswap16(target_efl->l_type);
6587 fl.l_whence = tswap16(target_efl->l_whence);
6588 fl.l_start = tswap64(target_efl->l_start);
6589 fl.l_len = tswap64(target_efl->l_len);
6590 fl.l_pid = tswapl(target_efl->l_pid);
6591 unlock_user_struct(target_efl, arg3, 0);
6592 } else
6593#endif
6594 {
bellard9ee1fa22007-11-11 15:11:19 +00006595 if (!lock_user_struct(VERIFY_READ, target_fl, arg3, 1))
6596 goto efault;
ths58134272007-03-31 18:59:32 +00006597 fl.l_type = tswap16(target_fl->l_type);
6598 fl.l_whence = tswap16(target_fl->l_whence);
6599 fl.l_start = tswap64(target_fl->l_start);
6600 fl.l_len = tswap64(target_fl->l_len);
6601 fl.l_pid = tswapl(target_fl->l_pid);
6602 unlock_user_struct(target_fl, arg3, 0);
6603 }
thsb1e341e2007-03-20 21:50:52 +00006604 ret = get_errno(fcntl(arg1, cmd, &fl));
bellard77e46722003-04-29 20:39:06 +00006605 if (ret == 0) {
pbrookce4defa2006-02-09 16:49:55 +00006606#ifdef TARGET_ARM
6607 if (((CPUARMState *)cpu_env)->eabi) {
bellard9ee1fa22007-11-11 15:11:19 +00006608 if (!lock_user_struct(VERIFY_WRITE, target_efl, arg3, 0))
6609 goto efault;
pbrookce4defa2006-02-09 16:49:55 +00006610 target_efl->l_type = tswap16(fl.l_type);
6611 target_efl->l_whence = tswap16(fl.l_whence);
6612 target_efl->l_start = tswap64(fl.l_start);
6613 target_efl->l_len = tswap64(fl.l_len);
6614 target_efl->l_pid = tswapl(fl.l_pid);
pbrook53a59602006-03-25 19:31:22 +00006615 unlock_user_struct(target_efl, arg3, 1);
pbrookce4defa2006-02-09 16:49:55 +00006616 } else
6617#endif
6618 {
bellard9ee1fa22007-11-11 15:11:19 +00006619 if (!lock_user_struct(VERIFY_WRITE, target_fl, arg3, 0))
6620 goto efault;
pbrookce4defa2006-02-09 16:49:55 +00006621 target_fl->l_type = tswap16(fl.l_type);
6622 target_fl->l_whence = tswap16(fl.l_whence);
6623 target_fl->l_start = tswap64(fl.l_start);
6624 target_fl->l_len = tswap64(fl.l_len);
6625 target_fl->l_pid = tswapl(fl.l_pid);
pbrook53a59602006-03-25 19:31:22 +00006626 unlock_user_struct(target_fl, arg3, 1);
pbrookce4defa2006-02-09 16:49:55 +00006627 }
bellard77e46722003-04-29 20:39:06 +00006628 }
6629 break;
6630
thsb1e341e2007-03-20 21:50:52 +00006631 case TARGET_F_SETLK64:
6632 case TARGET_F_SETLKW64:
pbrookce4defa2006-02-09 16:49:55 +00006633#ifdef TARGET_ARM
6634 if (((CPUARMState *)cpu_env)->eabi) {
bellard9ee1fa22007-11-11 15:11:19 +00006635 if (!lock_user_struct(VERIFY_READ, target_efl, arg3, 1))
6636 goto efault;
pbrookce4defa2006-02-09 16:49:55 +00006637 fl.l_type = tswap16(target_efl->l_type);
6638 fl.l_whence = tswap16(target_efl->l_whence);
6639 fl.l_start = tswap64(target_efl->l_start);
6640 fl.l_len = tswap64(target_efl->l_len);
6641 fl.l_pid = tswapl(target_efl->l_pid);
pbrook53a59602006-03-25 19:31:22 +00006642 unlock_user_struct(target_efl, arg3, 0);
pbrookce4defa2006-02-09 16:49:55 +00006643 } else
6644#endif
6645 {
bellard9ee1fa22007-11-11 15:11:19 +00006646 if (!lock_user_struct(VERIFY_READ, target_fl, arg3, 1))
6647 goto efault;
pbrookce4defa2006-02-09 16:49:55 +00006648 fl.l_type = tswap16(target_fl->l_type);
6649 fl.l_whence = tswap16(target_fl->l_whence);
6650 fl.l_start = tswap64(target_fl->l_start);
6651 fl.l_len = tswap64(target_fl->l_len);
6652 fl.l_pid = tswapl(target_fl->l_pid);
pbrook53a59602006-03-25 19:31:22 +00006653 unlock_user_struct(target_fl, arg3, 0);
pbrookce4defa2006-02-09 16:49:55 +00006654 }
thsb1e341e2007-03-20 21:50:52 +00006655 ret = get_errno(fcntl(arg1, cmd, &fl));
bellard77e46722003-04-29 20:39:06 +00006656 break;
bellard60cd49d2003-03-16 22:53:56 +00006657 default:
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02006658 ret = do_fcntl(arg1, arg2, arg3);
bellard60cd49d2003-03-16 22:53:56 +00006659 break;
6660 }
bellard77e46722003-04-29 20:39:06 +00006661 break;
6662 }
bellard60cd49d2003-03-16 22:53:56 +00006663#endif
ths7d600c82006-12-08 01:32:58 +00006664#ifdef TARGET_NR_cacheflush
6665 case TARGET_NR_cacheflush:
6666 /* self-modifying code is handled automatically, so nothing needed */
6667 ret = 0;
6668 break;
6669#endif
bellardebc05482003-09-30 21:08:41 +00006670#ifdef TARGET_NR_security
bellard31e31b82003-02-18 22:55:36 +00006671 case TARGET_NR_security:
6672 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00006673#endif
bellardc573ff62004-01-04 15:51:36 +00006674#ifdef TARGET_NR_getpagesize
6675 case TARGET_NR_getpagesize:
6676 ret = TARGET_PAGE_SIZE;
6677 break;
6678#endif
bellard31e31b82003-02-18 22:55:36 +00006679 case TARGET_NR_gettid:
6680 ret = get_errno(gettid());
6681 break;
thse5febef2007-04-01 18:31:35 +00006682#ifdef TARGET_NR_readahead
bellard31e31b82003-02-18 22:55:36 +00006683 case TARGET_NR_readahead:
aurel322054ac92008-10-13 21:08:07 +00006684#if TARGET_ABI_BITS == 32
6685#ifdef TARGET_ARM
6686 if (((CPUARMState *)cpu_env)->eabi)
6687 {
6688 arg2 = arg3;
6689 arg3 = arg4;
6690 arg4 = arg5;
6691 }
6692#endif
6693 ret = get_errno(readahead(arg1, ((off64_t)arg3 << 32) | arg2, arg4));
6694#else
6695 ret = get_errno(readahead(arg1, arg2, arg3));
6696#endif
6697 break;
thse5febef2007-04-01 18:31:35 +00006698#endif
bellardebc05482003-09-30 21:08:41 +00006699#ifdef TARGET_NR_setxattr
bellard31e31b82003-02-18 22:55:36 +00006700 case TARGET_NR_setxattr:
6701 case TARGET_NR_lsetxattr:
6702 case TARGET_NR_fsetxattr:
6703 case TARGET_NR_getxattr:
6704 case TARGET_NR_lgetxattr:
6705 case TARGET_NR_fgetxattr:
6706 case TARGET_NR_listxattr:
6707 case TARGET_NR_llistxattr:
6708 case TARGET_NR_flistxattr:
6709 case TARGET_NR_removexattr:
6710 case TARGET_NR_lremovexattr:
6711 case TARGET_NR_fremovexattr:
Arnaud Patard6f932f92009-04-21 21:04:18 +03006712 ret = -TARGET_EOPNOTSUPP;
6713 break;
bellardebc05482003-09-30 21:08:41 +00006714#endif
6715#ifdef TARGET_NR_set_thread_area
bellard5cd43932003-03-29 16:54:36 +00006716 case TARGET_NR_set_thread_area:
bellard8d18e892007-11-14 15:18:40 +00006717#if defined(TARGET_MIPS)
ths6f5b89a2007-03-02 20:48:00 +00006718 ((CPUMIPSState *) cpu_env)->tls_value = arg1;
6719 ret = 0;
6720 break;
edgar_iglef967792009-01-07 14:19:38 +00006721#elif defined(TARGET_CRIS)
6722 if (arg1 & 0xff)
6723 ret = -TARGET_EINVAL;
6724 else {
6725 ((CPUCRISState *) cpu_env)->pregs[PR_PID] = arg1;
6726 ret = 0;
6727 }
6728 break;
bellard8d18e892007-11-14 15:18:40 +00006729#elif defined(TARGET_I386) && defined(TARGET_ABI32)
6730 ret = do_set_thread_area(cpu_env, arg1);
6731 break;
ths6f5b89a2007-03-02 20:48:00 +00006732#else
6733 goto unimplemented_nowarn;
6734#endif
6735#endif
6736#ifdef TARGET_NR_get_thread_area
bellard5cd43932003-03-29 16:54:36 +00006737 case TARGET_NR_get_thread_area:
bellard8d18e892007-11-14 15:18:40 +00006738#if defined(TARGET_I386) && defined(TARGET_ABI32)
6739 ret = do_get_thread_area(cpu_env, arg1);
6740#else
bellard5cd43932003-03-29 16:54:36 +00006741 goto unimplemented_nowarn;
bellardebc05482003-09-30 21:08:41 +00006742#endif
bellard8d18e892007-11-14 15:18:40 +00006743#endif
bellard48dc41e2006-06-21 18:15:50 +00006744#ifdef TARGET_NR_getdomainname
6745 case TARGET_NR_getdomainname:
6746 goto unimplemented_nowarn;
6747#endif
ths6f5b89a2007-03-02 20:48:00 +00006748
thsb5906f92007-03-19 13:32:45 +00006749#ifdef TARGET_NR_clock_gettime
6750 case TARGET_NR_clock_gettime:
6751 {
6752 struct timespec ts;
6753 ret = get_errno(clock_gettime(arg1, &ts));
6754 if (!is_error(ret)) {
6755 host_to_target_timespec(arg2, &ts);
6756 }
6757 break;
6758 }
6759#endif
6760#ifdef TARGET_NR_clock_getres
6761 case TARGET_NR_clock_getres:
6762 {
6763 struct timespec ts;
6764 ret = get_errno(clock_getres(arg1, &ts));
6765 if (!is_error(ret)) {
6766 host_to_target_timespec(arg2, &ts);
6767 }
6768 break;
6769 }
6770#endif
pbrook63d76512008-05-29 13:43:29 +00006771#ifdef TARGET_NR_clock_nanosleep
6772 case TARGET_NR_clock_nanosleep:
6773 {
6774 struct timespec ts;
6775 target_to_host_timespec(&ts, arg3);
6776 ret = get_errno(clock_nanosleep(arg1, arg2, &ts, arg4 ? &ts : NULL));
6777 if (arg4)
6778 host_to_target_timespec(arg4, &ts);
6779 break;
6780 }
6781#endif
thsb5906f92007-03-19 13:32:45 +00006782
ths6f5b89a2007-03-02 20:48:00 +00006783#if defined(TARGET_NR_set_tid_address) && defined(__NR_set_tid_address)
6784 case TARGET_NR_set_tid_address:
bellard579a97f2007-11-11 14:26:47 +00006785 ret = get_errno(set_tid_address((int *)g2h(arg1)));
6786 break;
ths6f5b89a2007-03-02 20:48:00 +00006787#endif
6788
ths3ae43202007-09-16 21:39:48 +00006789#if defined(TARGET_NR_tkill) && defined(__NR_tkill)
ths4cae1d12007-07-12 11:06:53 +00006790 case TARGET_NR_tkill:
pbrook4cb05962008-05-30 18:05:19 +00006791 ret = get_errno(sys_tkill((int)arg1, target_to_host_signal(arg2)));
ths4cae1d12007-07-12 11:06:53 +00006792 break;
6793#endif
6794
ths3ae43202007-09-16 21:39:48 +00006795#if defined(TARGET_NR_tgkill) && defined(__NR_tgkill)
ths71455572007-06-21 21:45:30 +00006796 case TARGET_NR_tgkill:
pbrook4cb05962008-05-30 18:05:19 +00006797 ret = get_errno(sys_tgkill((int)arg1, (int)arg2,
6798 target_to_host_signal(arg3)));
ths71455572007-06-21 21:45:30 +00006799 break;
6800#endif
6801
ths4f2b1fe2007-06-21 21:57:12 +00006802#ifdef TARGET_NR_set_robust_list
6803 case TARGET_NR_set_robust_list:
6804 goto unimplemented_nowarn;
6805#endif
6806
ths9007f0e2007-09-25 17:50:37 +00006807#if defined(TARGET_NR_utimensat) && defined(__NR_utimensat)
6808 case TARGET_NR_utimensat:
6809 {
Riku Voipioebc996f2009-04-21 15:01:51 +03006810 struct timespec *tsp, ts[2];
6811 if (!arg3) {
6812 tsp = NULL;
6813 } else {
6814 target_to_host_timespec(ts, arg3);
6815 target_to_host_timespec(ts+1, arg3+sizeof(struct target_timespec));
6816 tsp = ts;
6817 }
ths9007f0e2007-09-25 17:50:37 +00006818 if (!arg2)
Riku Voipioebc996f2009-04-21 15:01:51 +03006819 ret = get_errno(sys_utimensat(arg1, NULL, tsp, arg4));
ths9007f0e2007-09-25 17:50:37 +00006820 else {
bellard579a97f2007-11-11 14:26:47 +00006821 if (!(p = lock_user_string(arg2))) {
ths0da46a62007-10-20 20:23:07 +00006822 ret = -TARGET_EFAULT;
bellard579a97f2007-11-11 14:26:47 +00006823 goto fail;
6824 }
Riku Voipioebc996f2009-04-21 15:01:51 +03006825 ret = get_errno(sys_utimensat(arg1, path(p), tsp, arg4));
bellard579a97f2007-11-11 14:26:47 +00006826 unlock_user(p, arg2, 0);
ths9007f0e2007-09-25 17:50:37 +00006827 }
6828 }
6829 break;
6830#endif
pbrookbd0c5662008-05-29 14:34:11 +00006831#if defined(USE_NPTL)
6832 case TARGET_NR_futex:
6833 ret = do_futex(arg1, arg2, arg3, arg4, arg5, arg6);
6834 break;
6835#endif
aurel32dbfe4c32009-04-08 21:29:30 +00006836#if defined(TARGET_NR_inotify_init) && defined(__NR_inotify_init)
aurel3239b59762008-10-01 21:46:50 +00006837 case TARGET_NR_inotify_init:
6838 ret = get_errno(sys_inotify_init());
6839 break;
6840#endif
aurel32dbfe4c32009-04-08 21:29:30 +00006841#if defined(TARGET_NR_inotify_add_watch) && defined(__NR_inotify_add_watch)
aurel3239b59762008-10-01 21:46:50 +00006842 case TARGET_NR_inotify_add_watch:
6843 p = lock_user_string(arg2);
6844 ret = get_errno(sys_inotify_add_watch(arg1, path(p), arg3));
6845 unlock_user(p, arg2, 0);
6846 break;
6847#endif
aurel32dbfe4c32009-04-08 21:29:30 +00006848#if defined(TARGET_NR_inotify_rm_watch) && defined(__NR_inotify_rm_watch)
aurel3239b59762008-10-01 21:46:50 +00006849 case TARGET_NR_inotify_rm_watch:
6850 ret = get_errno(sys_inotify_rm_watch(arg1, arg2));
6851 break;
6852#endif
ths9007f0e2007-09-25 17:50:37 +00006853
aurel3224e10032009-04-15 16:11:43 +00006854#ifdef TARGET_NR_mq_open
6855 case TARGET_NR_mq_open:
6856 {
6857 struct mq_attr posix_mq_attr;
6858
6859 p = lock_user_string(arg1 - 1);
6860 if (arg4 != 0)
6861 copy_from_user_mq_attr (&posix_mq_attr, arg4);
6862 ret = get_errno(mq_open(p, arg2, arg3, &posix_mq_attr));
6863 unlock_user (p, arg1, 0);
6864 }
6865 break;
6866
6867 case TARGET_NR_mq_unlink:
6868 p = lock_user_string(arg1 - 1);
6869 ret = get_errno(mq_unlink(p));
6870 unlock_user (p, arg1, 0);
6871 break;
6872
6873 case TARGET_NR_mq_timedsend:
6874 {
6875 struct timespec ts;
6876
6877 p = lock_user (VERIFY_READ, arg2, arg3, 1);
6878 if (arg5 != 0) {
6879 target_to_host_timespec(&ts, arg5);
6880 ret = get_errno(mq_timedsend(arg1, p, arg3, arg4, &ts));
6881 host_to_target_timespec(arg5, &ts);
6882 }
6883 else
6884 ret = get_errno(mq_send(arg1, p, arg3, arg4));
6885 unlock_user (p, arg2, arg3);
6886 }
6887 break;
6888
6889 case TARGET_NR_mq_timedreceive:
6890 {
6891 struct timespec ts;
6892 unsigned int prio;
6893
6894 p = lock_user (VERIFY_READ, arg2, arg3, 1);
6895 if (arg5 != 0) {
6896 target_to_host_timespec(&ts, arg5);
6897 ret = get_errno(mq_timedreceive(arg1, p, arg3, &prio, &ts));
6898 host_to_target_timespec(arg5, &ts);
6899 }
6900 else
6901 ret = get_errno(mq_receive(arg1, p, arg3, &prio));
6902 unlock_user (p, arg2, arg3);
6903 if (arg4 != 0)
6904 put_user_u32(prio, arg4);
6905 }
6906 break;
6907
6908 /* Not implemented for now... */
6909/* case TARGET_NR_mq_notify: */
6910/* break; */
6911
6912 case TARGET_NR_mq_getsetattr:
6913 {
6914 struct mq_attr posix_mq_attr_in, posix_mq_attr_out;
6915 ret = 0;
6916 if (arg3 != 0) {
6917 ret = mq_getattr(arg1, &posix_mq_attr_out);
6918 copy_to_user_mq_attr(arg3, &posix_mq_attr_out);
6919 }
6920 if (arg2 != 0) {
6921 copy_from_user_mq_attr(&posix_mq_attr_in, arg2);
6922 ret |= mq_setattr(arg1, &posix_mq_attr_in, &posix_mq_attr_out);
6923 }
6924
6925 }
6926 break;
6927#endif
6928
vibisreenivasan3ce34df2009-05-16 18:32:41 +05306929#ifdef CONFIG_SPLICE
6930#ifdef TARGET_NR_tee
6931 case TARGET_NR_tee:
6932 {
6933 ret = get_errno(tee(arg1,arg2,arg3,arg4));
6934 }
6935 break;
6936#endif
6937#ifdef TARGET_NR_splice
6938 case TARGET_NR_splice:
6939 {
6940 loff_t loff_in, loff_out;
6941 loff_t *ploff_in = NULL, *ploff_out = NULL;
6942 if(arg2) {
6943 get_user_u64(loff_in, arg2);
6944 ploff_in = &loff_in;
6945 }
6946 if(arg4) {
6947 get_user_u64(loff_out, arg2);
6948 ploff_out = &loff_out;
6949 }
6950 ret = get_errno(splice(arg1, ploff_in, arg3, ploff_out, arg5, arg6));
6951 }
6952 break;
6953#endif
6954#ifdef TARGET_NR_vmsplice
6955 case TARGET_NR_vmsplice:
6956 {
6957 int count = arg3;
6958 struct iovec *vec;
6959
6960 vec = alloca(count * sizeof(struct iovec));
6961 if (lock_iovec(VERIFY_READ, vec, arg2, count, 1) < 0)
6962 goto efault;
6963 ret = get_errno(vmsplice(arg1, vec, count, arg4));
6964 unlock_iovec(vec, arg2, count, 0);
6965 }
6966 break;
6967#endif
6968#endif /* CONFIG_SPLICE */
bellard31e31b82003-02-18 22:55:36 +00006969 default:
6970 unimplemented:
bellard5cd43932003-03-29 16:54:36 +00006971 gemu_log("qemu: Unsupported syscall: %d\n", num);
ths4f2b1fe2007-06-21 21:57:12 +00006972#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 +00006973 unimplemented_nowarn:
bellard80a9d032005-01-03 23:31:27 +00006974#endif
ths0da46a62007-10-20 20:23:07 +00006975 ret = -TARGET_ENOSYS;
bellard31e31b82003-02-18 22:55:36 +00006976 break;
6977 }
bellard579a97f2007-11-11 14:26:47 +00006978fail:
bellardc573ff62004-01-04 15:51:36 +00006979#ifdef DEBUG
Blue Swirl0bf9e312009-07-20 17:19:25 +00006980 gemu_log(" = " TARGET_ABI_FMT_ld "\n", ret);
bellardc573ff62004-01-04 15:51:36 +00006981#endif
thsb92c47c2007-11-01 00:07:38 +00006982 if(do_strace)
6983 print_syscall_ret(num, ret);
bellard31e31b82003-02-18 22:55:36 +00006984 return ret;
bellard579a97f2007-11-11 14:26:47 +00006985efault:
6986 ret = -TARGET_EFAULT;
6987 goto fail;
bellard31e31b82003-02-18 22:55:36 +00006988}