blob: f5875aa1f7e61762c533a9f13aba44bb023550ea [file] [log] [blame]
bellard31e31b82003-02-18 22:55:36 +00001/*
2 * Linux syscalls
ths5fafdf22007-09-16 21:08:06 +00003 *
bellard31e31b82003-02-18 22:55:36 +00004 * Copyright (c) 2003 Fabrice Bellard
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
blueswir1530e7612009-01-05 18:11:53 +000018 * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
19 * MA 02110-1301, USA.
bellard31e31b82003-02-18 22:55:36 +000020 */
21#include <stdlib.h>
22#include <stdio.h>
23#include <stdarg.h>
bellard04369ff2003-03-20 22:33:23 +000024#include <string.h>
bellard31e31b82003-02-18 22:55:36 +000025#include <elf.h>
26#include <endian.h>
27#include <errno.h>
28#include <unistd.h>
29#include <fcntl.h>
bellard7854b052003-03-29 17:22:23 +000030#include <time.h>
pbrook82e671d2008-06-09 12:10:22 +000031#include <limits.h>
aurel3224e10032009-04-15 16:11:43 +000032#include <mqueue.h>
bellard31e31b82003-02-18 22:55:36 +000033#include <sys/types.h>
thsd08d3bb2007-03-19 13:09:22 +000034#include <sys/ipc.h>
35#include <sys/msg.h>
bellard31e31b82003-02-18 22:55:36 +000036#include <sys/wait.h>
37#include <sys/time.h>
38#include <sys/stat.h>
39#include <sys/mount.h>
ths39b9aae2007-02-11 18:36:44 +000040#include <sys/prctl.h>
bellard31e31b82003-02-18 22:55:36 +000041#include <sys/resource.h>
42#include <sys/mman.h>
43#include <sys/swap.h>
44#include <signal.h>
45#include <sched.h>
46#include <sys/socket.h>
aurel32607175e2009-04-15 16:11:59 +000047#include <sys/un.h>
bellard31e31b82003-02-18 22:55:36 +000048#include <sys/uio.h>
bellard9de5e442003-03-23 16:49:39 +000049#include <sys/poll.h>
bellard32f36bc2003-03-30 21:29:48 +000050#include <sys/times.h>
bellard8853f862004-02-22 14:57:26 +000051#include <sys/shm.h>
thsfa294812007-02-02 22:05:00 +000052#include <sys/sem.h>
bellard56c8f682005-11-28 22:28:41 +000053#include <sys/statfs.h>
bellardebc05482003-09-30 21:08:41 +000054#include <utime.h>
bellarda5448a72004-06-19 16:59:03 +000055#include <sys/sysinfo.h>
aurel323b3f24a2009-04-15 16:12:13 +000056#include <sys/utsname.h>
bellard72f03902003-02-18 23:33:18 +000057//#include <sys/user.h>
bellard8853f862004-02-22 14:57:26 +000058#include <netinet/ip.h>
bellard7854b052003-03-29 17:22:23 +000059#include <netinet/tcp.h>
aurel320b6d3ae2008-09-15 07:43:43 +000060#include <qemu-common.h>
aurel326d946cd2008-11-06 16:15:18 +000061#ifdef HAVE_GPROF
62#include <sys/gmon.h>
63#endif
bellard31e31b82003-02-18 22:55:36 +000064
65#define termios host_termios
66#define winsize host_winsize
67#define termio host_termio
bellard04369ff2003-03-20 22:33:23 +000068#define sgttyb host_sgttyb /* same as target */
69#define tchars host_tchars /* same as target */
70#define ltchars host_ltchars /* same as target */
bellard31e31b82003-02-18 22:55:36 +000071
72#include <linux/termios.h>
73#include <linux/unistd.h>
74#include <linux/utsname.h>
75#include <linux/cdrom.h>
76#include <linux/hdreg.h>
77#include <linux/soundcard.h>
bellard19b84f32003-05-08 15:41:49 +000078#include <linux/kd.h>
balrog8fbd6b52008-09-20 03:03:09 +000079#include <linux/mtio.h>
pbrookd7e40362008-05-23 16:06:43 +000080#include "linux_loop.h"
bellard31e31b82003-02-18 22:55:36 +000081
bellard3ef693a2003-03-23 20:17:16 +000082#include "qemu.h"
balrog526ccb72008-07-16 12:13:52 +000083#include "qemu-common.h"
bellard31e31b82003-02-18 22:55:36 +000084
pbrook30813ce2008-06-02 15:45:44 +000085#if defined(USE_NPTL)
86#include <linux/futex.h>
pbrookd865bab2008-06-07 22:12:17 +000087#define CLONE_NPTL_FLAGS2 (CLONE_SETTLS | \
88 CLONE_PARENT_SETTID | CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID)
89#else
90/* XXX: Hardcode the above values. */
91#define CLONE_NPTL_FLAGS2 0
pbrook30813ce2008-06-02 15:45:44 +000092#endif
93
bellard72f03902003-02-18 23:33:18 +000094//#define DEBUG
bellard31e31b82003-02-18 22:55:36 +000095
pbrooke6e59062006-10-22 00:18:54 +000096#if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_SPARC) \
ths48733d12007-10-08 13:36:46 +000097 || defined(TARGET_M68K) || defined(TARGET_SH4) || defined(TARGET_CRIS)
bellard67867302003-11-23 17:05:30 +000098/* 16 bit uid wrappers emulation */
99#define USE_UID16
100#endif
101
bellard1a9353d2003-03-16 20:28:50 +0000102//#include <linux/msdos_fs.h>
aurel326556a832008-10-13 21:08:17 +0000103#define VFAT_IOCTL_READDIR_BOTH _IOR('r', 1, struct linux_dirent [2])
104#define VFAT_IOCTL_READDIR_SHORT _IOR('r', 2, struct linux_dirent [2])
bellard1a9353d2003-03-16 20:28:50 +0000105
bellard70a194b2003-08-11 22:20:16 +0000106
bellard70a194b2003-08-11 22:20:16 +0000107#undef _syscall0
108#undef _syscall1
109#undef _syscall2
110#undef _syscall3
111#undef _syscall4
112#undef _syscall5
bellard83fcb512006-06-14 13:37:16 +0000113#undef _syscall6
bellard70a194b2003-08-11 22:20:16 +0000114
bellard83fcb512006-06-14 13:37:16 +0000115#define _syscall0(type,name) \
blueswir18fcd3692008-08-17 20:26:25 +0000116static type name (void) \
bellard83fcb512006-06-14 13:37:16 +0000117{ \
118 return syscall(__NR_##name); \
bellard70a194b2003-08-11 22:20:16 +0000119}
120
bellard83fcb512006-06-14 13:37:16 +0000121#define _syscall1(type,name,type1,arg1) \
blueswir18fcd3692008-08-17 20:26:25 +0000122static type name (type1 arg1) \
bellard83fcb512006-06-14 13:37:16 +0000123{ \
124 return syscall(__NR_##name, arg1); \
bellard70a194b2003-08-11 22:20:16 +0000125}
126
bellard83fcb512006-06-14 13:37:16 +0000127#define _syscall2(type,name,type1,arg1,type2,arg2) \
blueswir18fcd3692008-08-17 20:26:25 +0000128static type name (type1 arg1,type2 arg2) \
bellard83fcb512006-06-14 13:37:16 +0000129{ \
130 return syscall(__NR_##name, arg1, arg2); \
bellard70a194b2003-08-11 22:20:16 +0000131}
132
bellard83fcb512006-06-14 13:37:16 +0000133#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \
blueswir18fcd3692008-08-17 20:26:25 +0000134static type name (type1 arg1,type2 arg2,type3 arg3) \
bellard83fcb512006-06-14 13:37:16 +0000135{ \
136 return syscall(__NR_##name, arg1, arg2, arg3); \
bellard70a194b2003-08-11 22:20:16 +0000137}
138
bellard83fcb512006-06-14 13:37:16 +0000139#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \
blueswir18fcd3692008-08-17 20:26:25 +0000140static type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4) \
bellard83fcb512006-06-14 13:37:16 +0000141{ \
142 return syscall(__NR_##name, arg1, arg2, arg3, arg4); \
bellard70a194b2003-08-11 22:20:16 +0000143}
144
bellard83fcb512006-06-14 13:37:16 +0000145#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
146 type5,arg5) \
blueswir18fcd3692008-08-17 20:26:25 +0000147static type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \
bellard83fcb512006-06-14 13:37:16 +0000148{ \
149 return syscall(__NR_##name, arg1, arg2, arg3, arg4, arg5); \
bellard70a194b2003-08-11 22:20:16 +0000150}
bellard83fcb512006-06-14 13:37:16 +0000151
152
153#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
154 type5,arg5,type6,arg6) \
blueswir18fcd3692008-08-17 20:26:25 +0000155static type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5, \
156 type6 arg6) \
bellard83fcb512006-06-14 13:37:16 +0000157{ \
158 return syscall(__NR_##name, arg1, arg2, arg3, arg4, arg5, arg6); \
159}
160
bellard70a194b2003-08-11 22:20:16 +0000161
bellard31e31b82003-02-18 22:55:36 +0000162#define __NR_sys_uname __NR_uname
ths92a34c12007-09-24 09:27:49 +0000163#define __NR_sys_faccessat __NR_faccessat
ths814d7972007-09-24 09:26:51 +0000164#define __NR_sys_fchmodat __NR_fchmodat
thsccfa72b2007-09-24 09:23:34 +0000165#define __NR_sys_fchownat __NR_fchownat
balrog6a24a772008-09-20 02:23:36 +0000166#define __NR_sys_fstatat64 __NR_fstatat64
balrogac8a6552008-09-20 02:25:39 +0000167#define __NR_sys_futimesat __NR_futimesat
bellard72f03902003-02-18 23:33:18 +0000168#define __NR_sys_getcwd1 __NR_getcwd
bellard72f03902003-02-18 23:33:18 +0000169#define __NR_sys_getdents __NR_getdents
bellarddab2ed92003-03-22 15:23:14 +0000170#define __NR_sys_getdents64 __NR_getdents64
thsc6cda172007-10-09 03:42:34 +0000171#define __NR_sys_getpriority __NR_getpriority
ths64f0ce42007-09-24 09:25:06 +0000172#define __NR_sys_linkat __NR_linkat
ths4472ad02007-09-24 09:22:32 +0000173#define __NR_sys_mkdirat __NR_mkdirat
ths75ac37a2007-09-24 09:23:05 +0000174#define __NR_sys_mknodat __NR_mknodat
aurel329d33b762009-04-08 23:07:05 +0000175#define __NR_sys_newfstatat __NR_newfstatat
ths82424832007-09-24 09:21:55 +0000176#define __NR_sys_openat __NR_openat
ths5e0ccb12007-09-24 09:26:10 +0000177#define __NR_sys_readlinkat __NR_readlinkat
ths722183f2007-09-24 09:24:37 +0000178#define __NR_sys_renameat __NR_renameat
bellard66fb9762003-03-23 01:06:05 +0000179#define __NR_sys_rt_sigqueueinfo __NR_rt_sigqueueinfo
thsf0b62432007-09-24 09:25:40 +0000180#define __NR_sys_symlinkat __NR_symlinkat
ths7494b0f2007-02-11 18:26:53 +0000181#define __NR_sys_syslog __NR_syslog
ths71455572007-06-21 21:45:30 +0000182#define __NR_sys_tgkill __NR_tgkill
ths4cae1d12007-07-12 11:06:53 +0000183#define __NR_sys_tkill __NR_tkill
ths8170f562007-09-24 09:24:11 +0000184#define __NR_sys_unlinkat __NR_unlinkat
ths9007f0e2007-09-25 17:50:37 +0000185#define __NR_sys_utimensat __NR_utimensat
pbrookbd0c5662008-05-29 14:34:11 +0000186#define __NR_sys_futex __NR_futex
aurel3239b59762008-10-01 21:46:50 +0000187#define __NR_sys_inotify_init __NR_inotify_init
188#define __NR_sys_inotify_add_watch __NR_inotify_add_watch
189#define __NR_sys_inotify_rm_watch __NR_inotify_rm_watch
bellard31e31b82003-02-18 22:55:36 +0000190
bellardbc51c5c2004-03-17 23:46:04 +0000191#if defined(__alpha__) || defined (__ia64__) || defined(__x86_64__)
bellard9af9eaa2003-04-07 21:34:41 +0000192#define __NR__llseek __NR_lseek
193#endif
194
bellard72f03902003-02-18 23:33:18 +0000195#ifdef __NR_gettid
bellard31e31b82003-02-18 22:55:36 +0000196_syscall0(int, gettid)
bellard72f03902003-02-18 23:33:18 +0000197#else
ths0da46a62007-10-20 20:23:07 +0000198/* This is a replacement for the host gettid() and must return a host
199 errno. */
bellard72f03902003-02-18 23:33:18 +0000200static int gettid(void) {
201 return -ENOSYS;
202}
203#endif
aurel323b3f24a2009-04-15 16:12:13 +0000204#if TARGET_ABI_BITS == 32
205_syscall3(int, sys_getdents, uint, fd, struct linux_dirent *, dirp, uint, count);
206#endif
207#if defined(TARGET_NR_getdents64) && defined(__NR_getdents64)
208_syscall3(int, sys_getdents64, uint, fd, struct linux_dirent64 *, dirp, uint, count);
209#endif
210_syscall2(int, sys_getpriority, int, which, int, who);
211#if !defined (__x86_64__)
212_syscall5(int, _llseek, uint, fd, ulong, hi, ulong, lo,
213 loff_t *, res, uint, wh);
214#endif
215_syscall3(int,sys_rt_sigqueueinfo,int,pid,int,sig,siginfo_t *,uinfo)
216_syscall3(int,sys_syslog,int,type,char*,bufp,int,len)
217#if defined(TARGET_NR_tgkill) && defined(__NR_tgkill)
218_syscall3(int,sys_tgkill,int,tgid,int,pid,int,sig)
219#endif
220#if defined(TARGET_NR_tkill) && defined(__NR_tkill)
221_syscall2(int,sys_tkill,int,tid,int,sig)
222#endif
223#ifdef __NR_exit_group
224_syscall1(int,exit_group,int,error_code)
225#endif
226#if defined(TARGET_NR_set_tid_address) && defined(__NR_set_tid_address)
227_syscall1(int,set_tid_address,int *,tidptr)
228#endif
229#if defined(USE_NPTL)
230#if defined(TARGET_NR_futex) && defined(__NR_futex)
231_syscall6(int,sys_futex,int *,uaddr,int,op,int,val,
232 const struct timespec *,timeout,int *,uaddr2,int,val3)
233#endif
234#endif
235
236static bitmask_transtbl fcntl_flags_tbl[] = {
237 { TARGET_O_ACCMODE, TARGET_O_WRONLY, O_ACCMODE, O_WRONLY, },
238 { TARGET_O_ACCMODE, TARGET_O_RDWR, O_ACCMODE, O_RDWR, },
239 { TARGET_O_CREAT, TARGET_O_CREAT, O_CREAT, O_CREAT, },
240 { TARGET_O_EXCL, TARGET_O_EXCL, O_EXCL, O_EXCL, },
241 { TARGET_O_NOCTTY, TARGET_O_NOCTTY, O_NOCTTY, O_NOCTTY, },
242 { TARGET_O_TRUNC, TARGET_O_TRUNC, O_TRUNC, O_TRUNC, },
243 { TARGET_O_APPEND, TARGET_O_APPEND, O_APPEND, O_APPEND, },
244 { TARGET_O_NONBLOCK, TARGET_O_NONBLOCK, O_NONBLOCK, O_NONBLOCK, },
245 { TARGET_O_SYNC, TARGET_O_SYNC, O_SYNC, O_SYNC, },
246 { TARGET_FASYNC, TARGET_FASYNC, FASYNC, FASYNC, },
247 { TARGET_O_DIRECTORY, TARGET_O_DIRECTORY, O_DIRECTORY, O_DIRECTORY, },
248 { TARGET_O_NOFOLLOW, TARGET_O_NOFOLLOW, O_NOFOLLOW, O_NOFOLLOW, },
249 { TARGET_O_LARGEFILE, TARGET_O_LARGEFILE, O_LARGEFILE, O_LARGEFILE, },
250#if defined(O_DIRECT)
251 { TARGET_O_DIRECT, TARGET_O_DIRECT, O_DIRECT, O_DIRECT, },
252#endif
253 { 0, 0, 0, 0 }
254};
255
256#define COPY_UTSNAME_FIELD(dest, src) \
257 do { \
258 /* __NEW_UTS_LEN doesn't include terminating null */ \
259 (void) strncpy((dest), (src), __NEW_UTS_LEN); \
260 (dest)[__NEW_UTS_LEN] = '\0'; \
261 } while (0)
262
263static int sys_uname(struct new_utsname *buf)
264{
265 struct utsname uts_buf;
266
267 if (uname(&uts_buf) < 0)
268 return (-1);
269
270 /*
271 * Just in case these have some differences, we
272 * translate utsname to new_utsname (which is the
273 * struct linux kernel uses).
274 */
275
276 bzero(buf, sizeof (*buf));
277 COPY_UTSNAME_FIELD(buf->sysname, uts_buf.sysname);
278 COPY_UTSNAME_FIELD(buf->nodename, uts_buf.nodename);
279 COPY_UTSNAME_FIELD(buf->release, uts_buf.release);
280 COPY_UTSNAME_FIELD(buf->version, uts_buf.version);
281 COPY_UTSNAME_FIELD(buf->machine, uts_buf.machine);
282#ifdef _GNU_SOURCE
283 COPY_UTSNAME_FIELD(buf->domainname, uts_buf.domainname);
284#endif
285 return (0);
286
287#undef COPY_UTSNAME_FIELD
288}
289
290static int sys_getcwd1(char *buf, size_t size)
291{
292 if (getcwd(buf, size) == NULL) {
293 /* getcwd() sets errno */
294 return (-1);
295 }
aurel32aaf4ad32009-04-16 14:17:14 +0000296 return strlen(buf)+1;
aurel323b3f24a2009-04-15 16:12:13 +0000297}
298
299#ifdef CONFIG_ATFILE
300/*
301 * Host system seems to have atfile syscall stubs available. We
302 * now enable them one by one as specified by target syscall_nr.h.
303 */
304
305#ifdef TARGET_NR_faccessat
306static int sys_faccessat(int dirfd, const char *pathname, int mode, int flags)
307{
308 return (faccessat(dirfd, pathname, mode, flags));
309}
310#endif
311#ifdef TARGET_NR_fchmodat
312static int sys_fchmodat(int dirfd, const char *pathname, mode_t mode, int flags)
313{
314 return (fchmodat(dirfd, pathname, mode, flags));
315}
316#endif
aurel32fda33742009-04-15 17:12:01 +0000317#if defined(TARGET_NR_fchownat) && defined(USE_UID16)
aurel323b3f24a2009-04-15 16:12:13 +0000318static int sys_fchownat(int dirfd, const char *pathname, uid_t owner,
319 gid_t group, int flags)
320{
321 return (fchownat(dirfd, pathname, owner, group, flags));
322}
323#endif
324#ifdef __NR_fstatat64
325static int sys_fstatat64(int dirfd, const char *pathname, struct stat *buf,
326 int flags)
327{
328 return (fstatat(dirfd, pathname, buf, flags));
329}
330#endif
331#ifdef __NR_newfstatat
332static int sys_newfstatat(int dirfd, const char *pathname, struct stat *buf,
333 int flags)
334{
335 return (fstatat(dirfd, pathname, buf, flags));
336}
337#endif
338#ifdef TARGET_NR_futimesat
339static int sys_futimesat(int dirfd, const char *pathname,
340 const struct timeval times[2])
341{
342 return (futimesat(dirfd, pathname, times));
343}
344#endif
345#ifdef TARGET_NR_linkat
346static int sys_linkat(int olddirfd, const char *oldpath,
347 int newdirfd, const char *newpath, int flags)
348{
349 return (linkat(olddirfd, oldpath, newdirfd, newpath, flags));
350}
351#endif
352#ifdef TARGET_NR_mkdirat
353static int sys_mkdirat(int dirfd, const char *pathname, mode_t mode)
354{
355 return (mkdirat(dirfd, pathname, mode));
356}
357#endif
358#ifdef TARGET_NR_mknodat
359static int sys_mknodat(int dirfd, const char *pathname, mode_t mode,
360 dev_t dev)
361{
362 return (mknodat(dirfd, pathname, mode, dev));
363}
364#endif
365#ifdef TARGET_NR_openat
366static int sys_openat(int dirfd, const char *pathname, int flags, ...)
367{
368 /*
369 * open(2) has extra parameter 'mode' when called with
370 * flag O_CREAT.
371 */
372 if ((flags & O_CREAT) != 0) {
373 va_list ap;
374 mode_t mode;
375
376 /*
377 * Get the 'mode' parameter and translate it to
378 * host bits.
379 */
380 va_start(ap, flags);
381 mode = va_arg(ap, mode_t);
382 mode = target_to_host_bitmask(mode, fcntl_flags_tbl);
383 va_end(ap);
384
385 return (openat(dirfd, pathname, flags, mode));
386 }
387 return (openat(dirfd, pathname, flags));
388}
389#endif
390#ifdef TARGET_NR_readlinkat
391static int sys_readlinkat(int dirfd, const char *pathname, char *buf, size_t bufsiz)
392{
393 return (readlinkat(dirfd, pathname, buf, bufsiz));
394}
395#endif
396#ifdef TARGET_NR_renameat
397static int sys_renameat(int olddirfd, const char *oldpath,
398 int newdirfd, const char *newpath)
399{
400 return (renameat(olddirfd, oldpath, newdirfd, newpath));
401}
402#endif
403#ifdef TARGET_NR_symlinkat
404static int sys_symlinkat(const char *oldpath, int newdirfd, const char *newpath)
405{
406 return (symlinkat(oldpath, newdirfd, newpath));
407}
408#endif
409#ifdef TARGET_NR_unlinkat
410static int sys_unlinkat(int dirfd, const char *pathname, int flags)
411{
412 return (unlinkat(dirfd, pathname, flags));
413}
414#endif
415#ifdef TARGET_NR_utimensat
416static int sys_utimensat(int dirfd, const char *pathname,
417 const struct timespec times[2], int flags)
418{
419 return (utimensat(dirfd, pathname, times, flags));
420}
421#endif
422#else /* !CONFIG_ATFILE */
423
424/*
425 * Try direct syscalls instead
426 */
ths92a34c12007-09-24 09:27:49 +0000427#if defined(TARGET_NR_faccessat) && defined(__NR_faccessat)
428_syscall4(int,sys_faccessat,int,dirfd,const char *,pathname,int,mode,int,flags)
429#endif
ths814d7972007-09-24 09:26:51 +0000430#if defined(TARGET_NR_fchmodat) && defined(__NR_fchmodat)
431_syscall4(int,sys_fchmodat,int,dirfd,const char *,pathname,
432 mode_t,mode,int,flags)
433#endif
blueswir14583f582008-08-24 10:35:55 +0000434#if defined(TARGET_NR_fchownat) && defined(__NR_fchownat) && defined(USE_UID16)
thsccfa72b2007-09-24 09:23:34 +0000435_syscall5(int,sys_fchownat,int,dirfd,const char *,pathname,
436 uid_t,owner,gid_t,group,int,flags)
437#endif
aurel329d33b762009-04-08 23:07:05 +0000438#if (defined(TARGET_NR_fstatat64) || defined(TARGET_NR_newfstatat)) && \
439 defined(__NR_fstatat64)
balrog6a24a772008-09-20 02:23:36 +0000440_syscall4(int,sys_fstatat64,int,dirfd,const char *,pathname,
441 struct stat *,buf,int,flags)
442#endif
balrogac8a6552008-09-20 02:25:39 +0000443#if defined(TARGET_NR_futimesat) && defined(__NR_futimesat)
444_syscall3(int,sys_futimesat,int,dirfd,const char *,pathname,
445 const struct timeval *,times)
446#endif
aurel323b3f24a2009-04-15 16:12:13 +0000447#if (defined(TARGET_NR_newfstatat) || defined(TARGET_NR_fstatat64) ) && \
448 defined(__NR_newfstatat)
449_syscall4(int,sys_newfstatat,int,dirfd,const char *,pathname,
450 struct stat *,buf,int,flags)
blueswir18fcd3692008-08-17 20:26:25 +0000451#endif
ths64f0ce42007-09-24 09:25:06 +0000452#if defined(TARGET_NR_linkat) && defined(__NR_linkat)
453_syscall5(int,sys_linkat,int,olddirfd,const char *,oldpath,
aurel323b3f24a2009-04-15 16:12:13 +0000454 int,newdirfd,const char *,newpath,int,flags)
ths64f0ce42007-09-24 09:25:06 +0000455#endif
ths4472ad02007-09-24 09:22:32 +0000456#if defined(TARGET_NR_mkdirat) && defined(__NR_mkdirat)
457_syscall3(int,sys_mkdirat,int,dirfd,const char *,pathname,mode_t,mode)
458#endif
ths75ac37a2007-09-24 09:23:05 +0000459#if defined(TARGET_NR_mknodat) && defined(__NR_mknodat)
460_syscall4(int,sys_mknodat,int,dirfd,const char *,pathname,
461 mode_t,mode,dev_t,dev)
462#endif
ths82424832007-09-24 09:21:55 +0000463#if defined(TARGET_NR_openat) && defined(__NR_openat)
464_syscall4(int,sys_openat,int,dirfd,const char *,pathname,int,flags,mode_t,mode)
465#endif
ths5e0ccb12007-09-24 09:26:10 +0000466#if defined(TARGET_NR_readlinkat) && defined(__NR_readlinkat)
467_syscall4(int,sys_readlinkat,int,dirfd,const char *,pathname,
468 char *,buf,size_t,bufsize)
469#endif
ths722183f2007-09-24 09:24:37 +0000470#if defined(TARGET_NR_renameat) && defined(__NR_renameat)
471_syscall4(int,sys_renameat,int,olddirfd,const char *,oldpath,
472 int,newdirfd,const char *,newpath)
473#endif
thsb51eaa82007-09-25 16:09:22 +0000474#if defined(TARGET_NR_symlinkat) && defined(__NR_symlinkat)
thsf0b62432007-09-24 09:25:40 +0000475_syscall3(int,sys_symlinkat,const char *,oldpath,
476 int,newdirfd,const char *,newpath)
477#endif
ths8170f562007-09-24 09:24:11 +0000478#if defined(TARGET_NR_unlinkat) && defined(__NR_unlinkat)
479_syscall3(int,sys_unlinkat,int,dirfd,const char *,pathname,int,flags)
480#endif
ths9007f0e2007-09-25 17:50:37 +0000481#if defined(TARGET_NR_utimensat) && defined(__NR_utimensat)
482_syscall4(int,sys_utimensat,int,dirfd,const char *,pathname,
483 const struct timespec *,tsp,int,flags)
484#endif
aurel323b3f24a2009-04-15 16:12:13 +0000485
486#endif /* CONFIG_ATFILE */
487
488#ifdef CONFIG_INOTIFY
489
aurel3239b59762008-10-01 21:46:50 +0000490#if defined(TARGET_NR_inotify_init) && defined(__NR_inotify_init)
aurel323b3f24a2009-04-15 16:12:13 +0000491static int sys_inotify_init(void)
492{
493 return (inotify_init());
494}
aurel3239b59762008-10-01 21:46:50 +0000495#endif
496#if defined(TARGET_NR_inotify_add_watch) && defined(__NR_inotify_add_watch)
aurel323b3f24a2009-04-15 16:12:13 +0000497static int sys_inotify_add_watch(int fd,const char *pathname, int32_t mask)
498{
499 return (inotify_add_watch(fd, pathname, mask));
500}
aurel3239b59762008-10-01 21:46:50 +0000501#endif
502#if defined(TARGET_NR_inotify_rm_watch) && defined(__NR_inotify_rm_watch)
aurel323b3f24a2009-04-15 16:12:13 +0000503static int sys_inotify_rm_watch(int fd, int32_t wd)
504{
505 return (inotify_rm_watch(fd,pathname, wd));
506}
aurel3239b59762008-10-01 21:46:50 +0000507#endif
aurel323b3f24a2009-04-15 16:12:13 +0000508#else
509/* Userspace can usually survive runtime without inotify */
510#undef TARGET_NR_inotify_init
511#undef TARGET_NR_inotify_add_watch
512#undef TARGET_NR_inotify_rm_watch
513#endif /* CONFIG_INOTIFY */
514
bellard66fb9762003-03-23 01:06:05 +0000515
516extern int personality(int);
bellard9de5e442003-03-23 16:49:39 +0000517extern int flock(int, int);
518extern int setfsuid(int);
519extern int setfsgid(int);
bellard19b84f32003-05-08 15:41:49 +0000520extern int setgroups(int, gid_t *);
bellard31e31b82003-02-18 22:55:36 +0000521
thsb92c47c2007-11-01 00:07:38 +0000522#define ERRNO_TABLE_SIZE 1200
523
524/* target_to_host_errno_table[] is initialized from
525 * host_to_target_errno_table[] in syscall_init(). */
526static uint16_t target_to_host_errno_table[ERRNO_TABLE_SIZE] = {
527};
528
ths637947f2007-06-01 12:09:19 +0000529/*
thsfe8f0962007-07-12 10:59:21 +0000530 * This list is the union of errno values overridden in asm-<arch>/errno.h
ths637947f2007-06-01 12:09:19 +0000531 * minus the errnos that are not actually generic to all archs.
532 */
thsb92c47c2007-11-01 00:07:38 +0000533static uint16_t host_to_target_errno_table[ERRNO_TABLE_SIZE] = {
ths637947f2007-06-01 12:09:19 +0000534 [EIDRM] = TARGET_EIDRM,
535 [ECHRNG] = TARGET_ECHRNG,
536 [EL2NSYNC] = TARGET_EL2NSYNC,
537 [EL3HLT] = TARGET_EL3HLT,
538 [EL3RST] = TARGET_EL3RST,
539 [ELNRNG] = TARGET_ELNRNG,
540 [EUNATCH] = TARGET_EUNATCH,
541 [ENOCSI] = TARGET_ENOCSI,
542 [EL2HLT] = TARGET_EL2HLT,
543 [EDEADLK] = TARGET_EDEADLK,
544 [ENOLCK] = TARGET_ENOLCK,
545 [EBADE] = TARGET_EBADE,
546 [EBADR] = TARGET_EBADR,
547 [EXFULL] = TARGET_EXFULL,
548 [ENOANO] = TARGET_ENOANO,
549 [EBADRQC] = TARGET_EBADRQC,
550 [EBADSLT] = TARGET_EBADSLT,
551 [EBFONT] = TARGET_EBFONT,
552 [ENOSTR] = TARGET_ENOSTR,
553 [ENODATA] = TARGET_ENODATA,
554 [ETIME] = TARGET_ETIME,
555 [ENOSR] = TARGET_ENOSR,
556 [ENONET] = TARGET_ENONET,
557 [ENOPKG] = TARGET_ENOPKG,
558 [EREMOTE] = TARGET_EREMOTE,
559 [ENOLINK] = TARGET_ENOLINK,
560 [EADV] = TARGET_EADV,
561 [ESRMNT] = TARGET_ESRMNT,
562 [ECOMM] = TARGET_ECOMM,
563 [EPROTO] = TARGET_EPROTO,
564 [EDOTDOT] = TARGET_EDOTDOT,
565 [EMULTIHOP] = TARGET_EMULTIHOP,
566 [EBADMSG] = TARGET_EBADMSG,
567 [ENAMETOOLONG] = TARGET_ENAMETOOLONG,
568 [EOVERFLOW] = TARGET_EOVERFLOW,
569 [ENOTUNIQ] = TARGET_ENOTUNIQ,
570 [EBADFD] = TARGET_EBADFD,
571 [EREMCHG] = TARGET_EREMCHG,
572 [ELIBACC] = TARGET_ELIBACC,
573 [ELIBBAD] = TARGET_ELIBBAD,
574 [ELIBSCN] = TARGET_ELIBSCN,
575 [ELIBMAX] = TARGET_ELIBMAX,
576 [ELIBEXEC] = TARGET_ELIBEXEC,
577 [EILSEQ] = TARGET_EILSEQ,
578 [ENOSYS] = TARGET_ENOSYS,
579 [ELOOP] = TARGET_ELOOP,
580 [ERESTART] = TARGET_ERESTART,
581 [ESTRPIPE] = TARGET_ESTRPIPE,
582 [ENOTEMPTY] = TARGET_ENOTEMPTY,
583 [EUSERS] = TARGET_EUSERS,
584 [ENOTSOCK] = TARGET_ENOTSOCK,
585 [EDESTADDRREQ] = TARGET_EDESTADDRREQ,
586 [EMSGSIZE] = TARGET_EMSGSIZE,
587 [EPROTOTYPE] = TARGET_EPROTOTYPE,
588 [ENOPROTOOPT] = TARGET_ENOPROTOOPT,
589 [EPROTONOSUPPORT] = TARGET_EPROTONOSUPPORT,
590 [ESOCKTNOSUPPORT] = TARGET_ESOCKTNOSUPPORT,
591 [EOPNOTSUPP] = TARGET_EOPNOTSUPP,
592 [EPFNOSUPPORT] = TARGET_EPFNOSUPPORT,
593 [EAFNOSUPPORT] = TARGET_EAFNOSUPPORT,
594 [EADDRINUSE] = TARGET_EADDRINUSE,
595 [EADDRNOTAVAIL] = TARGET_EADDRNOTAVAIL,
596 [ENETDOWN] = TARGET_ENETDOWN,
597 [ENETUNREACH] = TARGET_ENETUNREACH,
598 [ENETRESET] = TARGET_ENETRESET,
599 [ECONNABORTED] = TARGET_ECONNABORTED,
600 [ECONNRESET] = TARGET_ECONNRESET,
601 [ENOBUFS] = TARGET_ENOBUFS,
602 [EISCONN] = TARGET_EISCONN,
603 [ENOTCONN] = TARGET_ENOTCONN,
604 [EUCLEAN] = TARGET_EUCLEAN,
605 [ENOTNAM] = TARGET_ENOTNAM,
606 [ENAVAIL] = TARGET_ENAVAIL,
607 [EISNAM] = TARGET_EISNAM,
608 [EREMOTEIO] = TARGET_EREMOTEIO,
609 [ESHUTDOWN] = TARGET_ESHUTDOWN,
610 [ETOOMANYREFS] = TARGET_ETOOMANYREFS,
611 [ETIMEDOUT] = TARGET_ETIMEDOUT,
612 [ECONNREFUSED] = TARGET_ECONNREFUSED,
613 [EHOSTDOWN] = TARGET_EHOSTDOWN,
614 [EHOSTUNREACH] = TARGET_EHOSTUNREACH,
615 [EALREADY] = TARGET_EALREADY,
616 [EINPROGRESS] = TARGET_EINPROGRESS,
617 [ESTALE] = TARGET_ESTALE,
618 [ECANCELED] = TARGET_ECANCELED,
619 [ENOMEDIUM] = TARGET_ENOMEDIUM,
620 [EMEDIUMTYPE] = TARGET_EMEDIUMTYPE,
thsb7fe5db2007-07-23 15:37:46 +0000621#ifdef ENOKEY
ths637947f2007-06-01 12:09:19 +0000622 [ENOKEY] = TARGET_ENOKEY,
thsb7fe5db2007-07-23 15:37:46 +0000623#endif
624#ifdef EKEYEXPIRED
ths637947f2007-06-01 12:09:19 +0000625 [EKEYEXPIRED] = TARGET_EKEYEXPIRED,
thsb7fe5db2007-07-23 15:37:46 +0000626#endif
627#ifdef EKEYREVOKED
ths637947f2007-06-01 12:09:19 +0000628 [EKEYREVOKED] = TARGET_EKEYREVOKED,
thsb7fe5db2007-07-23 15:37:46 +0000629#endif
630#ifdef EKEYREJECTED
ths637947f2007-06-01 12:09:19 +0000631 [EKEYREJECTED] = TARGET_EKEYREJECTED,
thsb7fe5db2007-07-23 15:37:46 +0000632#endif
633#ifdef EOWNERDEAD
ths637947f2007-06-01 12:09:19 +0000634 [EOWNERDEAD] = TARGET_EOWNERDEAD,
thsb7fe5db2007-07-23 15:37:46 +0000635#endif
636#ifdef ENOTRECOVERABLE
ths637947f2007-06-01 12:09:19 +0000637 [ENOTRECOVERABLE] = TARGET_ENOTRECOVERABLE,
thsb7fe5db2007-07-23 15:37:46 +0000638#endif
thsb92c47c2007-11-01 00:07:38 +0000639};
ths637947f2007-06-01 12:09:19 +0000640
641static inline int host_to_target_errno(int err)
642{
643 if(host_to_target_errno_table[err])
644 return host_to_target_errno_table[err];
645 return err;
646}
647
thsb92c47c2007-11-01 00:07:38 +0000648static inline int target_to_host_errno(int err)
649{
650 if (target_to_host_errno_table[err])
651 return target_to_host_errno_table[err];
652 return err;
653}
654
blueswir1992f48a2007-10-14 16:27:31 +0000655static inline abi_long get_errno(abi_long ret)
bellard31e31b82003-02-18 22:55:36 +0000656{
657 if (ret == -1)
ths637947f2007-06-01 12:09:19 +0000658 return -host_to_target_errno(errno);
bellard31e31b82003-02-18 22:55:36 +0000659 else
660 return ret;
661}
662
blueswir1992f48a2007-10-14 16:27:31 +0000663static inline int is_error(abi_long ret)
bellard31e31b82003-02-18 22:55:36 +0000664{
blueswir1992f48a2007-10-14 16:27:31 +0000665 return (abi_ulong)ret >= (abi_ulong)(-4096);
bellard31e31b82003-02-18 22:55:36 +0000666}
667
thsb92c47c2007-11-01 00:07:38 +0000668char *target_strerror(int err)
669{
670 return strerror(target_to_host_errno(err));
671}
672
blueswir1992f48a2007-10-14 16:27:31 +0000673static abi_ulong target_brk;
674static abi_ulong target_original_brk;
bellard31e31b82003-02-18 22:55:36 +0000675
blueswir1992f48a2007-10-14 16:27:31 +0000676void target_set_brk(abi_ulong new_brk)
bellard31e31b82003-02-18 22:55:36 +0000677{
blueswir14c1de732007-07-07 20:45:44 +0000678 target_original_brk = target_brk = HOST_PAGE_ALIGN(new_brk);
bellard31e31b82003-02-18 22:55:36 +0000679}
680
ths0da46a62007-10-20 20:23:07 +0000681/* do_brk() must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +0000682abi_long do_brk(abi_ulong new_brk)
bellard31e31b82003-02-18 22:55:36 +0000683{
blueswir1992f48a2007-10-14 16:27:31 +0000684 abi_ulong brk_page;
685 abi_long mapped_addr;
bellard31e31b82003-02-18 22:55:36 +0000686 int new_alloc_size;
687
688 if (!new_brk)
pbrook53a59602006-03-25 19:31:22 +0000689 return target_brk;
bellard31e31b82003-02-18 22:55:36 +0000690 if (new_brk < target_original_brk)
balrog7ab240a2008-04-26 12:17:34 +0000691 return target_brk;
ths3b46e622007-09-17 08:09:54 +0000692
pbrook53a59602006-03-25 19:31:22 +0000693 brk_page = HOST_PAGE_ALIGN(target_brk);
bellard31e31b82003-02-18 22:55:36 +0000694
695 /* If the new brk is less than this, set it and we're done... */
696 if (new_brk < brk_page) {
697 target_brk = new_brk;
pbrook53a59602006-03-25 19:31:22 +0000698 return target_brk;
bellard31e31b82003-02-18 22:55:36 +0000699 }
700
701 /* We need to allocate more memory after the brk... */
bellard54936002003-05-13 00:25:15 +0000702 new_alloc_size = HOST_PAGE_ALIGN(new_brk - brk_page + 1);
ths5fafdf22007-09-16 21:08:06 +0000703 mapped_addr = get_errno(target_mmap(brk_page, new_alloc_size,
bellard54936002003-05-13 00:25:15 +0000704 PROT_READ|PROT_WRITE,
705 MAP_ANON|MAP_FIXED|MAP_PRIVATE, 0, 0));
balrog7ab240a2008-04-26 12:17:34 +0000706
707 if (!is_error(mapped_addr))
bellard31e31b82003-02-18 22:55:36 +0000708 target_brk = new_brk;
balrog7ab240a2008-04-26 12:17:34 +0000709
710 return target_brk;
bellard31e31b82003-02-18 22:55:36 +0000711}
712
ths26edcf42007-12-09 02:25:24 +0000713static inline abi_long copy_from_user_fdset(fd_set *fds,
714 abi_ulong target_fds_addr,
715 int n)
bellard31e31b82003-02-18 22:55:36 +0000716{
ths26edcf42007-12-09 02:25:24 +0000717 int i, nw, j, k;
718 abi_ulong b, *target_fds;
719
720 nw = (n + TARGET_ABI_BITS - 1) / TARGET_ABI_BITS;
721 if (!(target_fds = lock_user(VERIFY_READ,
722 target_fds_addr,
723 sizeof(abi_ulong) * nw,
724 1)))
725 return -TARGET_EFAULT;
726
727 FD_ZERO(fds);
728 k = 0;
729 for (i = 0; i < nw; i++) {
730 /* grab the abi_ulong */
731 __get_user(b, &target_fds[i]);
732 for (j = 0; j < TARGET_ABI_BITS; j++) {
733 /* check the bit inside the abi_ulong */
734 if ((b >> j) & 1)
735 FD_SET(k, fds);
736 k++;
bellard31e31b82003-02-18 22:55:36 +0000737 }
bellard31e31b82003-02-18 22:55:36 +0000738 }
ths26edcf42007-12-09 02:25:24 +0000739
740 unlock_user(target_fds, target_fds_addr, 0);
741
742 return 0;
bellard31e31b82003-02-18 22:55:36 +0000743}
744
ths26edcf42007-12-09 02:25:24 +0000745static inline abi_long copy_to_user_fdset(abi_ulong target_fds_addr,
746 const fd_set *fds,
747 int n)
bellard31e31b82003-02-18 22:55:36 +0000748{
bellard31e31b82003-02-18 22:55:36 +0000749 int i, nw, j, k;
blueswir1992f48a2007-10-14 16:27:31 +0000750 abi_long v;
ths26edcf42007-12-09 02:25:24 +0000751 abi_ulong *target_fds;
bellard31e31b82003-02-18 22:55:36 +0000752
ths26edcf42007-12-09 02:25:24 +0000753 nw = (n + TARGET_ABI_BITS - 1) / TARGET_ABI_BITS;
754 if (!(target_fds = lock_user(VERIFY_WRITE,
755 target_fds_addr,
756 sizeof(abi_ulong) * nw,
757 0)))
758 return -TARGET_EFAULT;
759
760 k = 0;
761 for (i = 0; i < nw; i++) {
762 v = 0;
763 for (j = 0; j < TARGET_ABI_BITS; j++) {
764 v |= ((FD_ISSET(k, fds) != 0) << j);
765 k++;
bellard31e31b82003-02-18 22:55:36 +0000766 }
ths26edcf42007-12-09 02:25:24 +0000767 __put_user(v, &target_fds[i]);
bellard31e31b82003-02-18 22:55:36 +0000768 }
ths26edcf42007-12-09 02:25:24 +0000769
770 unlock_user(target_fds, target_fds_addr, sizeof(abi_ulong) * nw);
771
772 return 0;
bellard31e31b82003-02-18 22:55:36 +0000773}
774
bellardc596ed12003-07-13 17:32:31 +0000775#if defined(__alpha__)
776#define HOST_HZ 1024
777#else
778#define HOST_HZ 100
779#endif
780
blueswir1992f48a2007-10-14 16:27:31 +0000781static inline abi_long host_to_target_clock_t(long ticks)
bellardc596ed12003-07-13 17:32:31 +0000782{
783#if HOST_HZ == TARGET_HZ
784 return ticks;
785#else
786 return ((int64_t)ticks * TARGET_HZ) / HOST_HZ;
787#endif
788}
789
bellard579a97f2007-11-11 14:26:47 +0000790static inline abi_long host_to_target_rusage(abi_ulong target_addr,
791 const struct rusage *rusage)
bellardb4091862003-05-16 15:39:34 +0000792{
pbrook53a59602006-03-25 19:31:22 +0000793 struct target_rusage *target_rusage;
794
bellard579a97f2007-11-11 14:26:47 +0000795 if (!lock_user_struct(VERIFY_WRITE, target_rusage, target_addr, 0))
796 return -TARGET_EFAULT;
bellardb4091862003-05-16 15:39:34 +0000797 target_rusage->ru_utime.tv_sec = tswapl(rusage->ru_utime.tv_sec);
798 target_rusage->ru_utime.tv_usec = tswapl(rusage->ru_utime.tv_usec);
799 target_rusage->ru_stime.tv_sec = tswapl(rusage->ru_stime.tv_sec);
800 target_rusage->ru_stime.tv_usec = tswapl(rusage->ru_stime.tv_usec);
801 target_rusage->ru_maxrss = tswapl(rusage->ru_maxrss);
802 target_rusage->ru_ixrss = tswapl(rusage->ru_ixrss);
803 target_rusage->ru_idrss = tswapl(rusage->ru_idrss);
804 target_rusage->ru_isrss = tswapl(rusage->ru_isrss);
805 target_rusage->ru_minflt = tswapl(rusage->ru_minflt);
806 target_rusage->ru_majflt = tswapl(rusage->ru_majflt);
807 target_rusage->ru_nswap = tswapl(rusage->ru_nswap);
808 target_rusage->ru_inblock = tswapl(rusage->ru_inblock);
809 target_rusage->ru_oublock = tswapl(rusage->ru_oublock);
810 target_rusage->ru_msgsnd = tswapl(rusage->ru_msgsnd);
811 target_rusage->ru_msgrcv = tswapl(rusage->ru_msgrcv);
812 target_rusage->ru_nsignals = tswapl(rusage->ru_nsignals);
813 target_rusage->ru_nvcsw = tswapl(rusage->ru_nvcsw);
814 target_rusage->ru_nivcsw = tswapl(rusage->ru_nivcsw);
pbrook53a59602006-03-25 19:31:22 +0000815 unlock_user_struct(target_rusage, target_addr, 1);
bellard579a97f2007-11-11 14:26:47 +0000816
817 return 0;
bellardb4091862003-05-16 15:39:34 +0000818}
819
ths788f5ec2007-12-09 02:37:05 +0000820static inline abi_long copy_from_user_timeval(struct timeval *tv,
821 abi_ulong target_tv_addr)
bellard31e31b82003-02-18 22:55:36 +0000822{
pbrook53a59602006-03-25 19:31:22 +0000823 struct target_timeval *target_tv;
824
ths788f5ec2007-12-09 02:37:05 +0000825 if (!lock_user_struct(VERIFY_READ, target_tv, target_tv_addr, 1))
bellard579a97f2007-11-11 14:26:47 +0000826 return -TARGET_EFAULT;
ths788f5ec2007-12-09 02:37:05 +0000827
828 __get_user(tv->tv_sec, &target_tv->tv_sec);
829 __get_user(tv->tv_usec, &target_tv->tv_usec);
830
831 unlock_user_struct(target_tv, target_tv_addr, 0);
bellard579a97f2007-11-11 14:26:47 +0000832
833 return 0;
bellard31e31b82003-02-18 22:55:36 +0000834}
835
ths788f5ec2007-12-09 02:37:05 +0000836static inline abi_long copy_to_user_timeval(abi_ulong target_tv_addr,
837 const struct timeval *tv)
bellard31e31b82003-02-18 22:55:36 +0000838{
pbrook53a59602006-03-25 19:31:22 +0000839 struct target_timeval *target_tv;
840
ths788f5ec2007-12-09 02:37:05 +0000841 if (!lock_user_struct(VERIFY_WRITE, target_tv, target_tv_addr, 0))
bellard579a97f2007-11-11 14:26:47 +0000842 return -TARGET_EFAULT;
ths788f5ec2007-12-09 02:37:05 +0000843
844 __put_user(tv->tv_sec, &target_tv->tv_sec);
845 __put_user(tv->tv_usec, &target_tv->tv_usec);
846
847 unlock_user_struct(target_tv, target_tv_addr, 1);
bellard579a97f2007-11-11 14:26:47 +0000848
849 return 0;
bellard31e31b82003-02-18 22:55:36 +0000850}
851
aurel3224e10032009-04-15 16:11:43 +0000852static inline abi_long copy_from_user_mq_attr(struct mq_attr *attr,
853 abi_ulong target_mq_attr_addr)
854{
855 struct target_mq_attr *target_mq_attr;
856
857 if (!lock_user_struct(VERIFY_READ, target_mq_attr,
858 target_mq_attr_addr, 1))
859 return -TARGET_EFAULT;
860
861 __get_user(attr->mq_flags, &target_mq_attr->mq_flags);
862 __get_user(attr->mq_maxmsg, &target_mq_attr->mq_maxmsg);
863 __get_user(attr->mq_msgsize, &target_mq_attr->mq_msgsize);
864 __get_user(attr->mq_curmsgs, &target_mq_attr->mq_curmsgs);
865
866 unlock_user_struct(target_mq_attr, target_mq_attr_addr, 0);
867
868 return 0;
869}
870
871static inline abi_long copy_to_user_mq_attr(abi_ulong target_mq_attr_addr,
872 const struct mq_attr *attr)
873{
874 struct target_mq_attr *target_mq_attr;
875
876 if (!lock_user_struct(VERIFY_WRITE, target_mq_attr,
877 target_mq_attr_addr, 0))
878 return -TARGET_EFAULT;
879
880 __put_user(attr->mq_flags, &target_mq_attr->mq_flags);
881 __put_user(attr->mq_maxmsg, &target_mq_attr->mq_maxmsg);
882 __put_user(attr->mq_msgsize, &target_mq_attr->mq_msgsize);
883 __put_user(attr->mq_curmsgs, &target_mq_attr->mq_curmsgs);
884
885 unlock_user_struct(target_mq_attr, target_mq_attr_addr, 1);
886
887 return 0;
888}
bellard31e31b82003-02-18 22:55:36 +0000889
ths0da46a62007-10-20 20:23:07 +0000890/* do_select() must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +0000891static abi_long do_select(int n,
ths26edcf42007-12-09 02:25:24 +0000892 abi_ulong rfd_addr, abi_ulong wfd_addr,
893 abi_ulong efd_addr, abi_ulong target_tv_addr)
bellard31e31b82003-02-18 22:55:36 +0000894{
895 fd_set rfds, wfds, efds;
896 fd_set *rfds_ptr, *wfds_ptr, *efds_ptr;
897 struct timeval tv, *tv_ptr;
blueswir1992f48a2007-10-14 16:27:31 +0000898 abi_long ret;
bellard31e31b82003-02-18 22:55:36 +0000899
ths26edcf42007-12-09 02:25:24 +0000900 if (rfd_addr) {
901 if (copy_from_user_fdset(&rfds, rfd_addr, n))
902 return -TARGET_EFAULT;
903 rfds_ptr = &rfds;
pbrook53a59602006-03-25 19:31:22 +0000904 } else {
pbrook53a59602006-03-25 19:31:22 +0000905 rfds_ptr = NULL;
906 }
ths26edcf42007-12-09 02:25:24 +0000907 if (wfd_addr) {
908 if (copy_from_user_fdset(&wfds, wfd_addr, n))
909 return -TARGET_EFAULT;
910 wfds_ptr = &wfds;
pbrook53a59602006-03-25 19:31:22 +0000911 } else {
pbrook53a59602006-03-25 19:31:22 +0000912 wfds_ptr = NULL;
913 }
ths26edcf42007-12-09 02:25:24 +0000914 if (efd_addr) {
915 if (copy_from_user_fdset(&efds, efd_addr, n))
916 return -TARGET_EFAULT;
917 efds_ptr = &efds;
pbrook53a59602006-03-25 19:31:22 +0000918 } else {
pbrook53a59602006-03-25 19:31:22 +0000919 efds_ptr = NULL;
920 }
ths3b46e622007-09-17 08:09:54 +0000921
ths26edcf42007-12-09 02:25:24 +0000922 if (target_tv_addr) {
ths788f5ec2007-12-09 02:37:05 +0000923 if (copy_from_user_timeval(&tv, target_tv_addr))
924 return -TARGET_EFAULT;
bellard31e31b82003-02-18 22:55:36 +0000925 tv_ptr = &tv;
926 } else {
927 tv_ptr = NULL;
928 }
ths26edcf42007-12-09 02:25:24 +0000929
bellard31e31b82003-02-18 22:55:36 +0000930 ret = get_errno(select(n, rfds_ptr, wfds_ptr, efds_ptr, tv_ptr));
pbrook53a59602006-03-25 19:31:22 +0000931
ths26edcf42007-12-09 02:25:24 +0000932 if (!is_error(ret)) {
933 if (rfd_addr && copy_to_user_fdset(rfd_addr, &rfds, n))
934 return -TARGET_EFAULT;
935 if (wfd_addr && copy_to_user_fdset(wfd_addr, &wfds, n))
936 return -TARGET_EFAULT;
937 if (efd_addr && copy_to_user_fdset(efd_addr, &efds, n))
938 return -TARGET_EFAULT;
bellard31e31b82003-02-18 22:55:36 +0000939
ths788f5ec2007-12-09 02:37:05 +0000940 if (target_tv_addr && copy_to_user_timeval(target_tv_addr, &tv))
941 return -TARGET_EFAULT;
bellard31e31b82003-02-18 22:55:36 +0000942 }
bellard579a97f2007-11-11 14:26:47 +0000943
bellard31e31b82003-02-18 22:55:36 +0000944 return ret;
945}
946
bellard579a97f2007-11-11 14:26:47 +0000947static inline abi_long target_to_host_sockaddr(struct sockaddr *addr,
948 abi_ulong target_addr,
949 socklen_t len)
bellard7854b052003-03-29 17:22:23 +0000950{
aurel32607175e2009-04-15 16:11:59 +0000951 const socklen_t unix_maxlen = sizeof (struct sockaddr_un);
952 sa_family_t sa_family;
pbrook53a59602006-03-25 19:31:22 +0000953 struct target_sockaddr *target_saddr;
954
bellard579a97f2007-11-11 14:26:47 +0000955 target_saddr = lock_user(VERIFY_READ, target_addr, len, 1);
956 if (!target_saddr)
957 return -TARGET_EFAULT;
aurel32607175e2009-04-15 16:11:59 +0000958
959 sa_family = tswap16(target_saddr->sa_family);
960
961 /* Oops. The caller might send a incomplete sun_path; sun_path
962 * must be terminated by \0 (see the manual page), but
963 * unfortunately it is quite common to specify sockaddr_un
964 * length as "strlen(x->sun_path)" while it should be
965 * "strlen(...) + 1". We'll fix that here if needed.
966 * Linux kernel has a similar feature.
967 */
968
969 if (sa_family == AF_UNIX) {
970 if (len < unix_maxlen && len > 0) {
971 char *cp = (char*)target_saddr;
972
973 if ( cp[len-1] && !cp[len] )
974 len++;
975 }
976 if (len > unix_maxlen)
977 len = unix_maxlen;
978 }
979
pbrook53a59602006-03-25 19:31:22 +0000980 memcpy(addr, target_saddr, len);
aurel32607175e2009-04-15 16:11:59 +0000981 addr->sa_family = sa_family;
pbrook53a59602006-03-25 19:31:22 +0000982 unlock_user(target_saddr, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +0000983
984 return 0;
bellard7854b052003-03-29 17:22:23 +0000985}
986
bellard579a97f2007-11-11 14:26:47 +0000987static inline abi_long host_to_target_sockaddr(abi_ulong target_addr,
988 struct sockaddr *addr,
989 socklen_t len)
bellard7854b052003-03-29 17:22:23 +0000990{
pbrook53a59602006-03-25 19:31:22 +0000991 struct target_sockaddr *target_saddr;
992
bellard579a97f2007-11-11 14:26:47 +0000993 target_saddr = lock_user(VERIFY_WRITE, target_addr, len, 0);
994 if (!target_saddr)
995 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +0000996 memcpy(target_saddr, addr, len);
997 target_saddr->sa_family = tswap16(addr->sa_family);
998 unlock_user(target_saddr, target_addr, len);
bellard579a97f2007-11-11 14:26:47 +0000999
1000 return 0;
bellard7854b052003-03-29 17:22:23 +00001001}
1002
pbrook53a59602006-03-25 19:31:22 +00001003/* ??? Should this also swap msgh->name? */
bellard5a4a8982007-11-11 17:39:18 +00001004static inline abi_long target_to_host_cmsg(struct msghdr *msgh,
1005 struct target_msghdr *target_msgh)
bellard7854b052003-03-29 17:22:23 +00001006{
1007 struct cmsghdr *cmsg = CMSG_FIRSTHDR(msgh);
bellard5a4a8982007-11-11 17:39:18 +00001008 abi_long msg_controllen;
1009 abi_ulong target_cmsg_addr;
1010 struct target_cmsghdr *target_cmsg;
bellard7854b052003-03-29 17:22:23 +00001011 socklen_t space = 0;
bellard5a4a8982007-11-11 17:39:18 +00001012
1013 msg_controllen = tswapl(target_msgh->msg_controllen);
1014 if (msg_controllen < sizeof (struct target_cmsghdr))
1015 goto the_end;
1016 target_cmsg_addr = tswapl(target_msgh->msg_control);
1017 target_cmsg = lock_user(VERIFY_READ, target_cmsg_addr, msg_controllen, 1);
1018 if (!target_cmsg)
1019 return -TARGET_EFAULT;
bellard7854b052003-03-29 17:22:23 +00001020
1021 while (cmsg && target_cmsg) {
1022 void *data = CMSG_DATA(cmsg);
1023 void *target_data = TARGET_CMSG_DATA(target_cmsg);
1024
ths5fafdf22007-09-16 21:08:06 +00001025 int len = tswapl(target_cmsg->cmsg_len)
bellard7854b052003-03-29 17:22:23 +00001026 - TARGET_CMSG_ALIGN(sizeof (struct target_cmsghdr));
1027
1028 space += CMSG_SPACE(len);
1029 if (space > msgh->msg_controllen) {
1030 space -= CMSG_SPACE(len);
bellard31febb72005-12-18 20:03:27 +00001031 gemu_log("Host cmsg overflow\n");
bellard7854b052003-03-29 17:22:23 +00001032 break;
1033 }
1034
1035 cmsg->cmsg_level = tswap32(target_cmsg->cmsg_level);
1036 cmsg->cmsg_type = tswap32(target_cmsg->cmsg_type);
1037 cmsg->cmsg_len = CMSG_LEN(len);
1038
bellard3532fa72006-06-24 15:06:03 +00001039 if (cmsg->cmsg_level != TARGET_SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS) {
bellard7854b052003-03-29 17:22:23 +00001040 gemu_log("Unsupported ancillary data: %d/%d\n", cmsg->cmsg_level, cmsg->cmsg_type);
1041 memcpy(data, target_data, len);
1042 } else {
1043 int *fd = (int *)data;
1044 int *target_fd = (int *)target_data;
1045 int i, numfds = len / sizeof(int);
1046
1047 for (i = 0; i < numfds; i++)
1048 fd[i] = tswap32(target_fd[i]);
1049 }
1050
1051 cmsg = CMSG_NXTHDR(msgh, cmsg);
1052 target_cmsg = TARGET_CMSG_NXTHDR(target_msgh, target_cmsg);
1053 }
bellard5a4a8982007-11-11 17:39:18 +00001054 unlock_user(target_cmsg, target_cmsg_addr, 0);
1055 the_end:
bellard7854b052003-03-29 17:22:23 +00001056 msgh->msg_controllen = space;
bellard5a4a8982007-11-11 17:39:18 +00001057 return 0;
bellard7854b052003-03-29 17:22:23 +00001058}
1059
pbrook53a59602006-03-25 19:31:22 +00001060/* ??? Should this also swap msgh->name? */
bellard5a4a8982007-11-11 17:39:18 +00001061static inline abi_long host_to_target_cmsg(struct target_msghdr *target_msgh,
1062 struct msghdr *msgh)
bellard7854b052003-03-29 17:22:23 +00001063{
1064 struct cmsghdr *cmsg = CMSG_FIRSTHDR(msgh);
bellard5a4a8982007-11-11 17:39:18 +00001065 abi_long msg_controllen;
1066 abi_ulong target_cmsg_addr;
1067 struct target_cmsghdr *target_cmsg;
bellard7854b052003-03-29 17:22:23 +00001068 socklen_t space = 0;
1069
bellard5a4a8982007-11-11 17:39:18 +00001070 msg_controllen = tswapl(target_msgh->msg_controllen);
1071 if (msg_controllen < sizeof (struct target_cmsghdr))
1072 goto the_end;
1073 target_cmsg_addr = tswapl(target_msgh->msg_control);
1074 target_cmsg = lock_user(VERIFY_WRITE, target_cmsg_addr, msg_controllen, 0);
1075 if (!target_cmsg)
1076 return -TARGET_EFAULT;
1077
bellard7854b052003-03-29 17:22:23 +00001078 while (cmsg && target_cmsg) {
1079 void *data = CMSG_DATA(cmsg);
1080 void *target_data = TARGET_CMSG_DATA(target_cmsg);
1081
1082 int len = cmsg->cmsg_len - CMSG_ALIGN(sizeof (struct cmsghdr));
1083
1084 space += TARGET_CMSG_SPACE(len);
bellard5a4a8982007-11-11 17:39:18 +00001085 if (space > msg_controllen) {
bellard7854b052003-03-29 17:22:23 +00001086 space -= TARGET_CMSG_SPACE(len);
bellard31febb72005-12-18 20:03:27 +00001087 gemu_log("Target cmsg overflow\n");
bellard7854b052003-03-29 17:22:23 +00001088 break;
1089 }
1090
1091 target_cmsg->cmsg_level = tswap32(cmsg->cmsg_level);
1092 target_cmsg->cmsg_type = tswap32(cmsg->cmsg_type);
1093 target_cmsg->cmsg_len = tswapl(TARGET_CMSG_LEN(len));
1094
bellard3532fa72006-06-24 15:06:03 +00001095 if (cmsg->cmsg_level != TARGET_SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS) {
bellard7854b052003-03-29 17:22:23 +00001096 gemu_log("Unsupported ancillary data: %d/%d\n", cmsg->cmsg_level, cmsg->cmsg_type);
1097 memcpy(target_data, data, len);
1098 } else {
1099 int *fd = (int *)data;
1100 int *target_fd = (int *)target_data;
1101 int i, numfds = len / sizeof(int);
1102
1103 for (i = 0; i < numfds; i++)
1104 target_fd[i] = tswap32(fd[i]);
1105 }
1106
1107 cmsg = CMSG_NXTHDR(msgh, cmsg);
1108 target_cmsg = TARGET_CMSG_NXTHDR(target_msgh, target_cmsg);
1109 }
bellard5a4a8982007-11-11 17:39:18 +00001110 unlock_user(target_cmsg, target_cmsg_addr, space);
1111 the_end:
1112 target_msgh->msg_controllen = tswapl(space);
1113 return 0;
bellard7854b052003-03-29 17:22:23 +00001114}
1115
ths0da46a62007-10-20 20:23:07 +00001116/* do_setsockopt() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001117static abi_long do_setsockopt(int sockfd, int level, int optname,
bellard2f619692007-11-16 10:46:05 +00001118 abi_ulong optval_addr, socklen_t optlen)
bellard7854b052003-03-29 17:22:23 +00001119{
blueswir1992f48a2007-10-14 16:27:31 +00001120 abi_long ret;
j_mayer32407102007-09-26 23:01:49 +00001121 int val;
ths3b46e622007-09-17 08:09:54 +00001122
bellard8853f862004-02-22 14:57:26 +00001123 switch(level) {
1124 case SOL_TCP:
bellard7854b052003-03-29 17:22:23 +00001125 /* TCP options all take an 'int' value. */
bellard7854b052003-03-29 17:22:23 +00001126 if (optlen < sizeof(uint32_t))
ths0da46a62007-10-20 20:23:07 +00001127 return -TARGET_EINVAL;
ths3b46e622007-09-17 08:09:54 +00001128
bellard2f619692007-11-16 10:46:05 +00001129 if (get_user_u32(val, optval_addr))
1130 return -TARGET_EFAULT;
bellard8853f862004-02-22 14:57:26 +00001131 ret = get_errno(setsockopt(sockfd, level, optname, &val, sizeof(val)));
1132 break;
1133 case SOL_IP:
1134 switch(optname) {
bellard2efbe912005-07-23 15:10:20 +00001135 case IP_TOS:
1136 case IP_TTL:
bellard8853f862004-02-22 14:57:26 +00001137 case IP_HDRINCL:
bellard2efbe912005-07-23 15:10:20 +00001138 case IP_ROUTER_ALERT:
1139 case IP_RECVOPTS:
1140 case IP_RETOPTS:
1141 case IP_PKTINFO:
1142 case IP_MTU_DISCOVER:
1143 case IP_RECVERR:
1144 case IP_RECVTOS:
1145#ifdef IP_FREEBIND
1146 case IP_FREEBIND:
1147#endif
1148 case IP_MULTICAST_TTL:
1149 case IP_MULTICAST_LOOP:
bellard8853f862004-02-22 14:57:26 +00001150 val = 0;
1151 if (optlen >= sizeof(uint32_t)) {
bellard2f619692007-11-16 10:46:05 +00001152 if (get_user_u32(val, optval_addr))
1153 return -TARGET_EFAULT;
bellard8853f862004-02-22 14:57:26 +00001154 } else if (optlen >= 1) {
bellard2f619692007-11-16 10:46:05 +00001155 if (get_user_u8(val, optval_addr))
1156 return -TARGET_EFAULT;
bellard8853f862004-02-22 14:57:26 +00001157 }
1158 ret = get_errno(setsockopt(sockfd, level, optname, &val, sizeof(val)));
1159 break;
1160 default:
1161 goto unimplemented;
1162 }
1163 break;
bellard3532fa72006-06-24 15:06:03 +00001164 case TARGET_SOL_SOCKET:
bellard8853f862004-02-22 14:57:26 +00001165 switch (optname) {
1166 /* Options with 'int' argument. */
bellard3532fa72006-06-24 15:06:03 +00001167 case TARGET_SO_DEBUG:
1168 optname = SO_DEBUG;
1169 break;
1170 case TARGET_SO_REUSEADDR:
1171 optname = SO_REUSEADDR;
1172 break;
1173 case TARGET_SO_TYPE:
1174 optname = SO_TYPE;
1175 break;
1176 case TARGET_SO_ERROR:
1177 optname = SO_ERROR;
1178 break;
1179 case TARGET_SO_DONTROUTE:
1180 optname = SO_DONTROUTE;
1181 break;
1182 case TARGET_SO_BROADCAST:
1183 optname = SO_BROADCAST;
1184 break;
1185 case TARGET_SO_SNDBUF:
1186 optname = SO_SNDBUF;
1187 break;
1188 case TARGET_SO_RCVBUF:
1189 optname = SO_RCVBUF;
1190 break;
1191 case TARGET_SO_KEEPALIVE:
1192 optname = SO_KEEPALIVE;
1193 break;
1194 case TARGET_SO_OOBINLINE:
1195 optname = SO_OOBINLINE;
1196 break;
1197 case TARGET_SO_NO_CHECK:
1198 optname = SO_NO_CHECK;
1199 break;
1200 case TARGET_SO_PRIORITY:
1201 optname = SO_PRIORITY;
1202 break;
bellard5e83e8e2005-03-01 22:32:06 +00001203#ifdef SO_BSDCOMPAT
bellard3532fa72006-06-24 15:06:03 +00001204 case TARGET_SO_BSDCOMPAT:
1205 optname = SO_BSDCOMPAT;
1206 break;
bellard5e83e8e2005-03-01 22:32:06 +00001207#endif
bellard3532fa72006-06-24 15:06:03 +00001208 case TARGET_SO_PASSCRED:
1209 optname = SO_PASSCRED;
1210 break;
1211 case TARGET_SO_TIMESTAMP:
1212 optname = SO_TIMESTAMP;
1213 break;
1214 case TARGET_SO_RCVLOWAT:
1215 optname = SO_RCVLOWAT;
1216 break;
1217 case TARGET_SO_RCVTIMEO:
1218 optname = SO_RCVTIMEO;
1219 break;
1220 case TARGET_SO_SNDTIMEO:
1221 optname = SO_SNDTIMEO;
1222 break;
bellard8853f862004-02-22 14:57:26 +00001223 break;
1224 default:
1225 goto unimplemented;
1226 }
bellard3532fa72006-06-24 15:06:03 +00001227 if (optlen < sizeof(uint32_t))
bellard2f619692007-11-16 10:46:05 +00001228 return -TARGET_EINVAL;
bellard3532fa72006-06-24 15:06:03 +00001229
bellard2f619692007-11-16 10:46:05 +00001230 if (get_user_u32(val, optval_addr))
1231 return -TARGET_EFAULT;
bellard3532fa72006-06-24 15:06:03 +00001232 ret = get_errno(setsockopt(sockfd, SOL_SOCKET, optname, &val, sizeof(val)));
bellard8853f862004-02-22 14:57:26 +00001233 break;
bellard7854b052003-03-29 17:22:23 +00001234 default:
bellard8853f862004-02-22 14:57:26 +00001235 unimplemented:
1236 gemu_log("Unsupported setsockopt level=%d optname=%d \n", level, optname);
ths6fa13c12007-12-18 02:41:04 +00001237 ret = -TARGET_ENOPROTOOPT;
bellard7854b052003-03-29 17:22:23 +00001238 }
bellard8853f862004-02-22 14:57:26 +00001239 return ret;
bellard7854b052003-03-29 17:22:23 +00001240}
1241
ths0da46a62007-10-20 20:23:07 +00001242/* do_getsockopt() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001243static abi_long do_getsockopt(int sockfd, int level, int optname,
bellard2f619692007-11-16 10:46:05 +00001244 abi_ulong optval_addr, abi_ulong optlen)
bellard7854b052003-03-29 17:22:23 +00001245{
blueswir1992f48a2007-10-14 16:27:31 +00001246 abi_long ret;
blueswir1b55266b2008-09-20 08:07:15 +00001247 int len, val;
1248 socklen_t lv;
bellard8853f862004-02-22 14:57:26 +00001249
1250 switch(level) {
bellard3532fa72006-06-24 15:06:03 +00001251 case TARGET_SOL_SOCKET:
1252 level = SOL_SOCKET;
bellard8853f862004-02-22 14:57:26 +00001253 switch (optname) {
bellard3532fa72006-06-24 15:06:03 +00001254 case TARGET_SO_LINGER:
1255 case TARGET_SO_RCVTIMEO:
1256 case TARGET_SO_SNDTIMEO:
1257 case TARGET_SO_PEERCRED:
1258 case TARGET_SO_PEERNAME:
bellard8853f862004-02-22 14:57:26 +00001259 /* These don't just return a single integer */
1260 goto unimplemented;
1261 default:
bellard2efbe912005-07-23 15:10:20 +00001262 goto int_case;
1263 }
1264 break;
1265 case SOL_TCP:
1266 /* TCP options all take an 'int' value. */
1267 int_case:
bellard2f619692007-11-16 10:46:05 +00001268 if (get_user_u32(len, optlen))
1269 return -TARGET_EFAULT;
bellard2efbe912005-07-23 15:10:20 +00001270 if (len < 0)
ths0da46a62007-10-20 20:23:07 +00001271 return -TARGET_EINVAL;
bellard2efbe912005-07-23 15:10:20 +00001272 lv = sizeof(int);
1273 ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
1274 if (ret < 0)
1275 return ret;
1276 val = tswap32(val);
1277 if (len > lv)
1278 len = lv;
bellard2f619692007-11-16 10:46:05 +00001279 if (len == 4) {
1280 if (put_user_u32(val, optval_addr))
1281 return -TARGET_EFAULT;
1282 } else {
1283 if (put_user_u8(val, optval_addr))
1284 return -TARGET_EFAULT;
1285 }
1286 if (put_user_u32(len, optlen))
1287 return -TARGET_EFAULT;
bellard2efbe912005-07-23 15:10:20 +00001288 break;
1289 case SOL_IP:
1290 switch(optname) {
1291 case IP_TOS:
1292 case IP_TTL:
1293 case IP_HDRINCL:
1294 case IP_ROUTER_ALERT:
1295 case IP_RECVOPTS:
1296 case IP_RETOPTS:
1297 case IP_PKTINFO:
1298 case IP_MTU_DISCOVER:
1299 case IP_RECVERR:
1300 case IP_RECVTOS:
1301#ifdef IP_FREEBIND
1302 case IP_FREEBIND:
1303#endif
1304 case IP_MULTICAST_TTL:
1305 case IP_MULTICAST_LOOP:
bellard2f619692007-11-16 10:46:05 +00001306 if (get_user_u32(len, optlen))
1307 return -TARGET_EFAULT;
bellard8853f862004-02-22 14:57:26 +00001308 if (len < 0)
ths0da46a62007-10-20 20:23:07 +00001309 return -TARGET_EINVAL;
bellard8853f862004-02-22 14:57:26 +00001310 lv = sizeof(int);
1311 ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
1312 if (ret < 0)
1313 return ret;
bellard2efbe912005-07-23 15:10:20 +00001314 if (len < sizeof(int) && len > 0 && val >= 0 && val < 255) {
bellard2efbe912005-07-23 15:10:20 +00001315 len = 1;
bellard2f619692007-11-16 10:46:05 +00001316 if (put_user_u32(len, optlen)
1317 || put_user_u8(val, optval_addr))
1318 return -TARGET_EFAULT;
bellard2efbe912005-07-23 15:10:20 +00001319 } else {
bellard2efbe912005-07-23 15:10:20 +00001320 if (len > sizeof(int))
1321 len = sizeof(int);
bellard2f619692007-11-16 10:46:05 +00001322 if (put_user_u32(len, optlen)
1323 || put_user_u32(val, optval_addr))
1324 return -TARGET_EFAULT;
bellard2efbe912005-07-23 15:10:20 +00001325 }
bellard8853f862004-02-22 14:57:26 +00001326 break;
bellard2efbe912005-07-23 15:10:20 +00001327 default:
thsc02f4992007-12-18 02:39:59 +00001328 ret = -TARGET_ENOPROTOOPT;
1329 break;
bellard8853f862004-02-22 14:57:26 +00001330 }
1331 break;
1332 default:
1333 unimplemented:
1334 gemu_log("getsockopt level=%d optname=%d not yet supported\n",
1335 level, optname);
thsc02f4992007-12-18 02:39:59 +00001336 ret = -TARGET_EOPNOTSUPP;
bellard8853f862004-02-22 14:57:26 +00001337 break;
1338 }
1339 return ret;
bellard7854b052003-03-29 17:22:23 +00001340}
1341
bellard579a97f2007-11-11 14:26:47 +00001342/* FIXME
1343 * lock_iovec()/unlock_iovec() have a return code of 0 for success where
1344 * other lock functions have a return code of 0 for failure.
1345 */
1346static abi_long lock_iovec(int type, struct iovec *vec, abi_ulong target_addr,
1347 int count, int copy)
pbrook53a59602006-03-25 19:31:22 +00001348{
1349 struct target_iovec *target_vec;
blueswir1992f48a2007-10-14 16:27:31 +00001350 abi_ulong base;
balrogd732dcb2008-10-28 10:21:03 +00001351 int i;
pbrook53a59602006-03-25 19:31:22 +00001352
bellard579a97f2007-11-11 14:26:47 +00001353 target_vec = lock_user(VERIFY_READ, target_addr, count * sizeof(struct target_iovec), 1);
1354 if (!target_vec)
1355 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00001356 for(i = 0;i < count; i++) {
1357 base = tswapl(target_vec[i].iov_base);
1358 vec[i].iov_len = tswapl(target_vec[i].iov_len);
bellard41df8412008-02-04 22:26:57 +00001359 if (vec[i].iov_len != 0) {
1360 vec[i].iov_base = lock_user(type, base, vec[i].iov_len, copy);
balrogd732dcb2008-10-28 10:21:03 +00001361 /* Don't check lock_user return value. We must call writev even
1362 if a element has invalid base address. */
bellard41df8412008-02-04 22:26:57 +00001363 } else {
1364 /* zero length pointer is ignored */
1365 vec[i].iov_base = NULL;
1366 }
pbrook53a59602006-03-25 19:31:22 +00001367 }
1368 unlock_user (target_vec, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00001369 return 0;
pbrook53a59602006-03-25 19:31:22 +00001370}
1371
bellard579a97f2007-11-11 14:26:47 +00001372static abi_long unlock_iovec(struct iovec *vec, abi_ulong target_addr,
1373 int count, int copy)
pbrook53a59602006-03-25 19:31:22 +00001374{
1375 struct target_iovec *target_vec;
blueswir1992f48a2007-10-14 16:27:31 +00001376 abi_ulong base;
pbrook53a59602006-03-25 19:31:22 +00001377 int i;
1378
bellard579a97f2007-11-11 14:26:47 +00001379 target_vec = lock_user(VERIFY_READ, target_addr, count * sizeof(struct target_iovec), 1);
1380 if (!target_vec)
1381 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00001382 for(i = 0;i < count; i++) {
balrogd732dcb2008-10-28 10:21:03 +00001383 if (target_vec[i].iov_base) {
1384 base = tswapl(target_vec[i].iov_base);
1385 unlock_user(vec[i].iov_base, base, copy ? vec[i].iov_len : 0);
1386 }
pbrook53a59602006-03-25 19:31:22 +00001387 }
1388 unlock_user (target_vec, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00001389
1390 return 0;
pbrook53a59602006-03-25 19:31:22 +00001391}
1392
ths0da46a62007-10-20 20:23:07 +00001393/* do_socket() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001394static abi_long do_socket(int domain, int type, int protocol)
bellard3532fa72006-06-24 15:06:03 +00001395{
1396#if defined(TARGET_MIPS)
1397 switch(type) {
1398 case TARGET_SOCK_DGRAM:
1399 type = SOCK_DGRAM;
1400 break;
1401 case TARGET_SOCK_STREAM:
1402 type = SOCK_STREAM;
1403 break;
1404 case TARGET_SOCK_RAW:
1405 type = SOCK_RAW;
1406 break;
1407 case TARGET_SOCK_RDM:
1408 type = SOCK_RDM;
1409 break;
1410 case TARGET_SOCK_SEQPACKET:
1411 type = SOCK_SEQPACKET;
1412 break;
1413 case TARGET_SOCK_PACKET:
1414 type = SOCK_PACKET;
1415 break;
1416 }
1417#endif
balrog12bc92a2007-10-30 21:06:14 +00001418 if (domain == PF_NETLINK)
1419 return -EAFNOSUPPORT; /* do not NETLINK socket connections possible */
bellard3532fa72006-06-24 15:06:03 +00001420 return get_errno(socket(domain, type, protocol));
1421}
1422
ths0da46a62007-10-20 20:23:07 +00001423/* do_bind() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001424static abi_long do_bind(int sockfd, abi_ulong target_addr,
1425 socklen_t addrlen)
bellard3532fa72006-06-24 15:06:03 +00001426{
aurel328f7aeaf2009-01-30 19:47:57 +00001427 void *addr;
1428
aurel32be09ac42009-04-15 16:12:06 +00001429 if (addrlen < 0)
aurel328f7aeaf2009-01-30 19:47:57 +00001430 return -TARGET_EINVAL;
1431
aurel32607175e2009-04-15 16:11:59 +00001432 addr = alloca(addrlen+1);
ths3b46e622007-09-17 08:09:54 +00001433
bellard3532fa72006-06-24 15:06:03 +00001434 target_to_host_sockaddr(addr, target_addr, addrlen);
1435 return get_errno(bind(sockfd, addr, addrlen));
1436}
1437
ths0da46a62007-10-20 20:23:07 +00001438/* do_connect() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001439static abi_long do_connect(int sockfd, abi_ulong target_addr,
1440 socklen_t addrlen)
bellard3532fa72006-06-24 15:06:03 +00001441{
aurel328f7aeaf2009-01-30 19:47:57 +00001442 void *addr;
1443
aurel32be09ac42009-04-15 16:12:06 +00001444 if (addrlen < 0)
aurel328f7aeaf2009-01-30 19:47:57 +00001445 return -TARGET_EINVAL;
1446
1447 addr = alloca(addrlen);
ths3b46e622007-09-17 08:09:54 +00001448
bellard3532fa72006-06-24 15:06:03 +00001449 target_to_host_sockaddr(addr, target_addr, addrlen);
1450 return get_errno(connect(sockfd, addr, addrlen));
1451}
1452
ths0da46a62007-10-20 20:23:07 +00001453/* do_sendrecvmsg() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001454static abi_long do_sendrecvmsg(int fd, abi_ulong target_msg,
1455 int flags, int send)
bellard3532fa72006-06-24 15:06:03 +00001456{
balrog6de645c2008-10-28 10:26:29 +00001457 abi_long ret, len;
bellard3532fa72006-06-24 15:06:03 +00001458 struct target_msghdr *msgp;
1459 struct msghdr msg;
1460 int count;
1461 struct iovec *vec;
blueswir1992f48a2007-10-14 16:27:31 +00001462 abi_ulong target_vec;
bellard3532fa72006-06-24 15:06:03 +00001463
bellard579a97f2007-11-11 14:26:47 +00001464 /* FIXME */
1465 if (!lock_user_struct(send ? VERIFY_READ : VERIFY_WRITE,
1466 msgp,
1467 target_msg,
1468 send ? 1 : 0))
1469 return -TARGET_EFAULT;
bellard3532fa72006-06-24 15:06:03 +00001470 if (msgp->msg_name) {
1471 msg.msg_namelen = tswap32(msgp->msg_namelen);
1472 msg.msg_name = alloca(msg.msg_namelen);
1473 target_to_host_sockaddr(msg.msg_name, tswapl(msgp->msg_name),
1474 msg.msg_namelen);
1475 } else {
1476 msg.msg_name = NULL;
1477 msg.msg_namelen = 0;
1478 }
1479 msg.msg_controllen = 2 * tswapl(msgp->msg_controllen);
1480 msg.msg_control = alloca(msg.msg_controllen);
1481 msg.msg_flags = tswap32(msgp->msg_flags);
ths3b46e622007-09-17 08:09:54 +00001482
bellard3532fa72006-06-24 15:06:03 +00001483 count = tswapl(msgp->msg_iovlen);
1484 vec = alloca(count * sizeof(struct iovec));
1485 target_vec = tswapl(msgp->msg_iov);
bellard579a97f2007-11-11 14:26:47 +00001486 lock_iovec(send ? VERIFY_READ : VERIFY_WRITE, vec, target_vec, count, send);
bellard3532fa72006-06-24 15:06:03 +00001487 msg.msg_iovlen = count;
1488 msg.msg_iov = vec;
ths3b46e622007-09-17 08:09:54 +00001489
bellard3532fa72006-06-24 15:06:03 +00001490 if (send) {
bellard5a4a8982007-11-11 17:39:18 +00001491 ret = target_to_host_cmsg(&msg, msgp);
1492 if (ret == 0)
1493 ret = get_errno(sendmsg(fd, &msg, flags));
bellard3532fa72006-06-24 15:06:03 +00001494 } else {
1495 ret = get_errno(recvmsg(fd, &msg, flags));
balrog6de645c2008-10-28 10:26:29 +00001496 if (!is_error(ret)) {
1497 len = ret;
bellard5a4a8982007-11-11 17:39:18 +00001498 ret = host_to_target_cmsg(msgp, &msg);
balrog6de645c2008-10-28 10:26:29 +00001499 if (!is_error(ret))
1500 ret = len;
1501 }
bellard3532fa72006-06-24 15:06:03 +00001502 }
1503 unlock_iovec(vec, target_vec, count, !send);
bellard579a97f2007-11-11 14:26:47 +00001504 unlock_user_struct(msgp, target_msg, send ? 0 : 1);
bellard3532fa72006-06-24 15:06:03 +00001505 return ret;
1506}
1507
ths0da46a62007-10-20 20:23:07 +00001508/* do_accept() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001509static abi_long do_accept(int fd, abi_ulong target_addr,
bellard2f619692007-11-16 10:46:05 +00001510 abi_ulong target_addrlen_addr)
pbrook1be9e1d2006-11-19 15:26:04 +00001511{
bellard2f619692007-11-16 10:46:05 +00001512 socklen_t addrlen;
1513 void *addr;
blueswir1992f48a2007-10-14 16:27:31 +00001514 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00001515
bellard2f619692007-11-16 10:46:05 +00001516 if (get_user_u32(addrlen, target_addrlen_addr))
1517 return -TARGET_EFAULT;
1518
aurel32be09ac42009-04-15 16:12:06 +00001519 if (addrlen < 0)
aurel328f7aeaf2009-01-30 19:47:57 +00001520 return -TARGET_EINVAL;
1521
bellard2f619692007-11-16 10:46:05 +00001522 addr = alloca(addrlen);
1523
pbrook1be9e1d2006-11-19 15:26:04 +00001524 ret = get_errno(accept(fd, addr, &addrlen));
1525 if (!is_error(ret)) {
1526 host_to_target_sockaddr(target_addr, addr, addrlen);
bellard2f619692007-11-16 10:46:05 +00001527 if (put_user_u32(addrlen, target_addrlen_addr))
1528 ret = -TARGET_EFAULT;
pbrook1be9e1d2006-11-19 15:26:04 +00001529 }
1530 return ret;
1531}
1532
ths0da46a62007-10-20 20:23:07 +00001533/* do_getpeername() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001534static abi_long do_getpeername(int fd, abi_ulong target_addr,
bellard2f619692007-11-16 10:46:05 +00001535 abi_ulong target_addrlen_addr)
pbrook1be9e1d2006-11-19 15:26:04 +00001536{
bellard2f619692007-11-16 10:46:05 +00001537 socklen_t addrlen;
1538 void *addr;
blueswir1992f48a2007-10-14 16:27:31 +00001539 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00001540
bellard2f619692007-11-16 10:46:05 +00001541 if (get_user_u32(addrlen, target_addrlen_addr))
1542 return -TARGET_EFAULT;
1543
aurel32be09ac42009-04-15 16:12:06 +00001544 if (addrlen < 0)
aurel328f7aeaf2009-01-30 19:47:57 +00001545 return -TARGET_EINVAL;
1546
bellard2f619692007-11-16 10:46:05 +00001547 addr = alloca(addrlen);
1548
pbrook1be9e1d2006-11-19 15:26:04 +00001549 ret = get_errno(getpeername(fd, addr, &addrlen));
1550 if (!is_error(ret)) {
1551 host_to_target_sockaddr(target_addr, addr, addrlen);
bellard2f619692007-11-16 10:46:05 +00001552 if (put_user_u32(addrlen, target_addrlen_addr))
1553 ret = -TARGET_EFAULT;
pbrook1be9e1d2006-11-19 15:26:04 +00001554 }
1555 return ret;
1556}
1557
ths0da46a62007-10-20 20:23:07 +00001558/* do_getsockname() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001559static abi_long do_getsockname(int fd, abi_ulong target_addr,
bellard2f619692007-11-16 10:46:05 +00001560 abi_ulong target_addrlen_addr)
pbrook1be9e1d2006-11-19 15:26:04 +00001561{
bellard2f619692007-11-16 10:46:05 +00001562 socklen_t addrlen;
1563 void *addr;
blueswir1992f48a2007-10-14 16:27:31 +00001564 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00001565
aurel328fea3602009-01-30 19:47:47 +00001566 if (target_addr == 0)
1567 return get_errno(accept(fd, NULL, NULL));
1568
bellard2f619692007-11-16 10:46:05 +00001569 if (get_user_u32(addrlen, target_addrlen_addr))
1570 return -TARGET_EFAULT;
1571
aurel32be09ac42009-04-15 16:12:06 +00001572 if (addrlen < 0)
aurel328f7aeaf2009-01-30 19:47:57 +00001573 return -TARGET_EINVAL;
1574
bellard2f619692007-11-16 10:46:05 +00001575 addr = alloca(addrlen);
1576
pbrook1be9e1d2006-11-19 15:26:04 +00001577 ret = get_errno(getsockname(fd, addr, &addrlen));
1578 if (!is_error(ret)) {
1579 host_to_target_sockaddr(target_addr, addr, addrlen);
bellard2f619692007-11-16 10:46:05 +00001580 if (put_user_u32(addrlen, target_addrlen_addr))
1581 ret = -TARGET_EFAULT;
pbrook1be9e1d2006-11-19 15:26:04 +00001582 }
1583 return ret;
1584}
1585
ths0da46a62007-10-20 20:23:07 +00001586/* do_socketpair() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001587static abi_long do_socketpair(int domain, int type, int protocol,
bellard2f619692007-11-16 10:46:05 +00001588 abi_ulong target_tab_addr)
pbrook1be9e1d2006-11-19 15:26:04 +00001589{
1590 int tab[2];
blueswir1992f48a2007-10-14 16:27:31 +00001591 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00001592
1593 ret = get_errno(socketpair(domain, type, protocol, tab));
1594 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +00001595 if (put_user_s32(tab[0], target_tab_addr)
1596 || put_user_s32(tab[1], target_tab_addr + sizeof(tab[0])))
1597 ret = -TARGET_EFAULT;
pbrook1be9e1d2006-11-19 15:26:04 +00001598 }
1599 return ret;
1600}
1601
ths0da46a62007-10-20 20:23:07 +00001602/* do_sendto() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001603static abi_long do_sendto(int fd, abi_ulong msg, size_t len, int flags,
1604 abi_ulong target_addr, socklen_t addrlen)
pbrook1be9e1d2006-11-19 15:26:04 +00001605{
1606 void *addr;
1607 void *host_msg;
blueswir1992f48a2007-10-14 16:27:31 +00001608 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00001609
aurel32be09ac42009-04-15 16:12:06 +00001610 if (addrlen < 0)
aurel328f7aeaf2009-01-30 19:47:57 +00001611 return -TARGET_EINVAL;
1612
bellard579a97f2007-11-11 14:26:47 +00001613 host_msg = lock_user(VERIFY_READ, msg, len, 1);
1614 if (!host_msg)
1615 return -TARGET_EFAULT;
pbrook1be9e1d2006-11-19 15:26:04 +00001616 if (target_addr) {
1617 addr = alloca(addrlen);
1618 target_to_host_sockaddr(addr, target_addr, addrlen);
1619 ret = get_errno(sendto(fd, host_msg, len, flags, addr, addrlen));
1620 } else {
1621 ret = get_errno(send(fd, host_msg, len, flags));
1622 }
1623 unlock_user(host_msg, msg, 0);
1624 return ret;
1625}
1626
ths0da46a62007-10-20 20:23:07 +00001627/* do_recvfrom() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001628static abi_long do_recvfrom(int fd, abi_ulong msg, size_t len, int flags,
1629 abi_ulong target_addr,
1630 abi_ulong target_addrlen)
pbrook1be9e1d2006-11-19 15:26:04 +00001631{
1632 socklen_t addrlen;
1633 void *addr;
1634 void *host_msg;
blueswir1992f48a2007-10-14 16:27:31 +00001635 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00001636
bellard579a97f2007-11-11 14:26:47 +00001637 host_msg = lock_user(VERIFY_WRITE, msg, len, 0);
1638 if (!host_msg)
1639 return -TARGET_EFAULT;
pbrook1be9e1d2006-11-19 15:26:04 +00001640 if (target_addr) {
bellard2f619692007-11-16 10:46:05 +00001641 if (get_user_u32(addrlen, target_addrlen)) {
1642 ret = -TARGET_EFAULT;
1643 goto fail;
1644 }
aurel32be09ac42009-04-15 16:12:06 +00001645 if (addrlen < 0) {
aurel328f7aeaf2009-01-30 19:47:57 +00001646 ret = -TARGET_EINVAL;
1647 goto fail;
1648 }
pbrook1be9e1d2006-11-19 15:26:04 +00001649 addr = alloca(addrlen);
1650 ret = get_errno(recvfrom(fd, host_msg, len, flags, addr, &addrlen));
1651 } else {
1652 addr = NULL; /* To keep compiler quiet. */
1653 ret = get_errno(recv(fd, host_msg, len, flags));
1654 }
1655 if (!is_error(ret)) {
1656 if (target_addr) {
1657 host_to_target_sockaddr(target_addr, addr, addrlen);
bellard2f619692007-11-16 10:46:05 +00001658 if (put_user_u32(addrlen, target_addrlen)) {
1659 ret = -TARGET_EFAULT;
1660 goto fail;
1661 }
pbrook1be9e1d2006-11-19 15:26:04 +00001662 }
1663 unlock_user(host_msg, msg, len);
1664 } else {
bellard2f619692007-11-16 10:46:05 +00001665fail:
pbrook1be9e1d2006-11-19 15:26:04 +00001666 unlock_user(host_msg, msg, 0);
1667 }
1668 return ret;
1669}
1670
j_mayer32407102007-09-26 23:01:49 +00001671#ifdef TARGET_NR_socketcall
ths0da46a62007-10-20 20:23:07 +00001672/* do_socketcall() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001673static abi_long do_socketcall(int num, abi_ulong vptr)
bellard31e31b82003-02-18 22:55:36 +00001674{
blueswir1992f48a2007-10-14 16:27:31 +00001675 abi_long ret;
1676 const int n = sizeof(abi_ulong);
bellard31e31b82003-02-18 22:55:36 +00001677
1678 switch(num) {
1679 case SOCKOP_socket:
bellard7854b052003-03-29 17:22:23 +00001680 {
bellard2f619692007-11-16 10:46:05 +00001681 int domain, type, protocol;
1682
1683 if (get_user_s32(domain, vptr)
1684 || get_user_s32(type, vptr + n)
1685 || get_user_s32(protocol, vptr + 2 * n))
1686 return -TARGET_EFAULT;
1687
bellard3532fa72006-06-24 15:06:03 +00001688 ret = do_socket(domain, type, protocol);
bellard7854b052003-03-29 17:22:23 +00001689 }
bellard31e31b82003-02-18 22:55:36 +00001690 break;
1691 case SOCKOP_bind:
bellard7854b052003-03-29 17:22:23 +00001692 {
bellard2f619692007-11-16 10:46:05 +00001693 int sockfd;
1694 abi_ulong target_addr;
1695 socklen_t addrlen;
1696
1697 if (get_user_s32(sockfd, vptr)
1698 || get_user_ual(target_addr, vptr + n)
1699 || get_user_u32(addrlen, vptr + 2 * n))
1700 return -TARGET_EFAULT;
1701
bellard3532fa72006-06-24 15:06:03 +00001702 ret = do_bind(sockfd, target_addr, addrlen);
bellard7854b052003-03-29 17:22:23 +00001703 }
bellard31e31b82003-02-18 22:55:36 +00001704 break;
1705 case SOCKOP_connect:
bellard7854b052003-03-29 17:22:23 +00001706 {
bellard2f619692007-11-16 10:46:05 +00001707 int sockfd;
1708 abi_ulong target_addr;
1709 socklen_t addrlen;
1710
1711 if (get_user_s32(sockfd, vptr)
1712 || get_user_ual(target_addr, vptr + n)
1713 || get_user_u32(addrlen, vptr + 2 * n))
1714 return -TARGET_EFAULT;
1715
bellard3532fa72006-06-24 15:06:03 +00001716 ret = do_connect(sockfd, target_addr, addrlen);
bellard7854b052003-03-29 17:22:23 +00001717 }
bellard31e31b82003-02-18 22:55:36 +00001718 break;
1719 case SOCKOP_listen:
bellard7854b052003-03-29 17:22:23 +00001720 {
bellard2f619692007-11-16 10:46:05 +00001721 int sockfd, backlog;
1722
1723 if (get_user_s32(sockfd, vptr)
1724 || get_user_s32(backlog, vptr + n))
1725 return -TARGET_EFAULT;
1726
bellard7854b052003-03-29 17:22:23 +00001727 ret = get_errno(listen(sockfd, backlog));
1728 }
bellard31e31b82003-02-18 22:55:36 +00001729 break;
1730 case SOCKOP_accept:
1731 {
bellard2f619692007-11-16 10:46:05 +00001732 int sockfd;
1733 abi_ulong target_addr, target_addrlen;
1734
1735 if (get_user_s32(sockfd, vptr)
1736 || get_user_ual(target_addr, vptr + n)
1737 || get_user_u32(target_addrlen, vptr + 2 * n))
1738 return -TARGET_EFAULT;
1739
pbrook1be9e1d2006-11-19 15:26:04 +00001740 ret = do_accept(sockfd, target_addr, target_addrlen);
bellard31e31b82003-02-18 22:55:36 +00001741 }
1742 break;
1743 case SOCKOP_getsockname:
1744 {
bellard2f619692007-11-16 10:46:05 +00001745 int sockfd;
1746 abi_ulong target_addr, target_addrlen;
1747
1748 if (get_user_s32(sockfd, vptr)
1749 || get_user_ual(target_addr, vptr + n)
1750 || get_user_u32(target_addrlen, vptr + 2 * n))
1751 return -TARGET_EFAULT;
1752
pbrook1be9e1d2006-11-19 15:26:04 +00001753 ret = do_getsockname(sockfd, target_addr, target_addrlen);
bellard31e31b82003-02-18 22:55:36 +00001754 }
1755 break;
1756 case SOCKOP_getpeername:
1757 {
bellard2f619692007-11-16 10:46:05 +00001758 int sockfd;
1759 abi_ulong target_addr, target_addrlen;
1760
1761 if (get_user_s32(sockfd, vptr)
1762 || get_user_ual(target_addr, vptr + n)
1763 || get_user_u32(target_addrlen, vptr + 2 * n))
1764 return -TARGET_EFAULT;
1765
pbrook1be9e1d2006-11-19 15:26:04 +00001766 ret = do_getpeername(sockfd, target_addr, target_addrlen);
bellard31e31b82003-02-18 22:55:36 +00001767 }
1768 break;
1769 case SOCKOP_socketpair:
1770 {
bellard2f619692007-11-16 10:46:05 +00001771 int domain, type, protocol;
1772 abi_ulong tab;
1773
1774 if (get_user_s32(domain, vptr)
1775 || get_user_s32(type, vptr + n)
1776 || get_user_s32(protocol, vptr + 2 * n)
1777 || get_user_ual(tab, vptr + 3 * n))
1778 return -TARGET_EFAULT;
1779
pbrook1be9e1d2006-11-19 15:26:04 +00001780 ret = do_socketpair(domain, type, protocol, tab);
bellard31e31b82003-02-18 22:55:36 +00001781 }
1782 break;
1783 case SOCKOP_send:
bellard7854b052003-03-29 17:22:23 +00001784 {
bellard2f619692007-11-16 10:46:05 +00001785 int sockfd;
1786 abi_ulong msg;
1787 size_t len;
1788 int flags;
1789
1790 if (get_user_s32(sockfd, vptr)
1791 || get_user_ual(msg, vptr + n)
1792 || get_user_ual(len, vptr + 2 * n)
1793 || get_user_s32(flags, vptr + 3 * n))
1794 return -TARGET_EFAULT;
1795
pbrook1be9e1d2006-11-19 15:26:04 +00001796 ret = do_sendto(sockfd, msg, len, flags, 0, 0);
bellard7854b052003-03-29 17:22:23 +00001797 }
bellard31e31b82003-02-18 22:55:36 +00001798 break;
1799 case SOCKOP_recv:
bellard7854b052003-03-29 17:22:23 +00001800 {
bellard2f619692007-11-16 10:46:05 +00001801 int sockfd;
1802 abi_ulong msg;
1803 size_t len;
1804 int flags;
1805
1806 if (get_user_s32(sockfd, vptr)
1807 || get_user_ual(msg, vptr + n)
1808 || get_user_ual(len, vptr + 2 * n)
1809 || get_user_s32(flags, vptr + 3 * n))
1810 return -TARGET_EFAULT;
1811
pbrook1be9e1d2006-11-19 15:26:04 +00001812 ret = do_recvfrom(sockfd, msg, len, flags, 0, 0);
bellard7854b052003-03-29 17:22:23 +00001813 }
bellard31e31b82003-02-18 22:55:36 +00001814 break;
1815 case SOCKOP_sendto:
bellard7854b052003-03-29 17:22:23 +00001816 {
bellard2f619692007-11-16 10:46:05 +00001817 int sockfd;
1818 abi_ulong msg;
1819 size_t len;
1820 int flags;
1821 abi_ulong addr;
1822 socklen_t addrlen;
1823
1824 if (get_user_s32(sockfd, vptr)
1825 || get_user_ual(msg, vptr + n)
1826 || get_user_ual(len, vptr + 2 * n)
1827 || get_user_s32(flags, vptr + 3 * n)
1828 || get_user_ual(addr, vptr + 4 * n)
1829 || get_user_u32(addrlen, vptr + 5 * n))
1830 return -TARGET_EFAULT;
1831
pbrook1be9e1d2006-11-19 15:26:04 +00001832 ret = do_sendto(sockfd, msg, len, flags, addr, addrlen);
bellard7854b052003-03-29 17:22:23 +00001833 }
bellard31e31b82003-02-18 22:55:36 +00001834 break;
1835 case SOCKOP_recvfrom:
1836 {
bellard2f619692007-11-16 10:46:05 +00001837 int sockfd;
1838 abi_ulong msg;
1839 size_t len;
1840 int flags;
1841 abi_ulong addr;
1842 socklen_t addrlen;
1843
1844 if (get_user_s32(sockfd, vptr)
1845 || get_user_ual(msg, vptr + n)
1846 || get_user_ual(len, vptr + 2 * n)
1847 || get_user_s32(flags, vptr + 3 * n)
1848 || get_user_ual(addr, vptr + 4 * n)
1849 || get_user_u32(addrlen, vptr + 5 * n))
1850 return -TARGET_EFAULT;
1851
pbrook1be9e1d2006-11-19 15:26:04 +00001852 ret = do_recvfrom(sockfd, msg, len, flags, addr, addrlen);
bellard31e31b82003-02-18 22:55:36 +00001853 }
1854 break;
1855 case SOCKOP_shutdown:
bellard7854b052003-03-29 17:22:23 +00001856 {
bellard2f619692007-11-16 10:46:05 +00001857 int sockfd, how;
1858
1859 if (get_user_s32(sockfd, vptr)
1860 || get_user_s32(how, vptr + n))
1861 return -TARGET_EFAULT;
bellard7854b052003-03-29 17:22:23 +00001862
1863 ret = get_errno(shutdown(sockfd, how));
1864 }
bellard31e31b82003-02-18 22:55:36 +00001865 break;
1866 case SOCKOP_sendmsg:
1867 case SOCKOP_recvmsg:
bellard1a9353d2003-03-16 20:28:50 +00001868 {
1869 int fd;
blueswir1992f48a2007-10-14 16:27:31 +00001870 abi_ulong target_msg;
bellard3532fa72006-06-24 15:06:03 +00001871 int flags;
bellard1a9353d2003-03-16 20:28:50 +00001872
bellard2f619692007-11-16 10:46:05 +00001873 if (get_user_s32(fd, vptr)
1874 || get_user_ual(target_msg, vptr + n)
1875 || get_user_s32(flags, vptr + 2 * n))
1876 return -TARGET_EFAULT;
bellard3532fa72006-06-24 15:06:03 +00001877
ths5fafdf22007-09-16 21:08:06 +00001878 ret = do_sendrecvmsg(fd, target_msg, flags,
bellard3532fa72006-06-24 15:06:03 +00001879 (num == SOCKOP_sendmsg));
bellard1a9353d2003-03-16 20:28:50 +00001880 }
1881 break;
bellard31e31b82003-02-18 22:55:36 +00001882 case SOCKOP_setsockopt:
bellard7854b052003-03-29 17:22:23 +00001883 {
bellard2f619692007-11-16 10:46:05 +00001884 int sockfd;
1885 int level;
1886 int optname;
1887 abi_ulong optval;
1888 socklen_t optlen;
1889
1890 if (get_user_s32(sockfd, vptr)
1891 || get_user_s32(level, vptr + n)
1892 || get_user_s32(optname, vptr + 2 * n)
1893 || get_user_ual(optval, vptr + 3 * n)
1894 || get_user_u32(optlen, vptr + 4 * n))
1895 return -TARGET_EFAULT;
bellard7854b052003-03-29 17:22:23 +00001896
1897 ret = do_setsockopt(sockfd, level, optname, optval, optlen);
1898 }
1899 break;
bellard31e31b82003-02-18 22:55:36 +00001900 case SOCKOP_getsockopt:
bellard7854b052003-03-29 17:22:23 +00001901 {
bellard2f619692007-11-16 10:46:05 +00001902 int sockfd;
1903 int level;
1904 int optname;
1905 abi_ulong optval;
1906 socklen_t optlen;
bellard7854b052003-03-29 17:22:23 +00001907
bellard2f619692007-11-16 10:46:05 +00001908 if (get_user_s32(sockfd, vptr)
1909 || get_user_s32(level, vptr + n)
1910 || get_user_s32(optname, vptr + 2 * n)
1911 || get_user_ual(optval, vptr + 3 * n)
1912 || get_user_u32(optlen, vptr + 4 * n))
1913 return -TARGET_EFAULT;
1914
1915 ret = do_getsockopt(sockfd, level, optname, optval, optlen);
bellard7854b052003-03-29 17:22:23 +00001916 }
1917 break;
bellard31e31b82003-02-18 22:55:36 +00001918 default:
1919 gemu_log("Unsupported socketcall: %d\n", num);
ths0da46a62007-10-20 20:23:07 +00001920 ret = -TARGET_ENOSYS;
bellard31e31b82003-02-18 22:55:36 +00001921 break;
1922 }
1923 return ret;
1924}
j_mayer32407102007-09-26 23:01:49 +00001925#endif
bellard31e31b82003-02-18 22:55:36 +00001926
blueswir13f911a52008-12-13 11:37:02 +00001927#ifdef TARGET_NR_ipc
bellard8853f862004-02-22 14:57:26 +00001928#define N_SHM_REGIONS 32
1929
1930static struct shm_region {
bellard5a4a8982007-11-11 17:39:18 +00001931 abi_ulong start;
1932 abi_ulong size;
bellard8853f862004-02-22 14:57:26 +00001933} shm_regions[N_SHM_REGIONS];
blueswir13f911a52008-12-13 11:37:02 +00001934#endif
bellard8853f862004-02-22 14:57:26 +00001935
ths3eb6b042007-06-03 14:26:27 +00001936struct target_ipc_perm
1937{
blueswir1992f48a2007-10-14 16:27:31 +00001938 abi_long __key;
1939 abi_ulong uid;
1940 abi_ulong gid;
1941 abi_ulong cuid;
1942 abi_ulong cgid;
ths3eb6b042007-06-03 14:26:27 +00001943 unsigned short int mode;
1944 unsigned short int __pad1;
1945 unsigned short int __seq;
1946 unsigned short int __pad2;
blueswir1992f48a2007-10-14 16:27:31 +00001947 abi_ulong __unused1;
1948 abi_ulong __unused2;
ths3eb6b042007-06-03 14:26:27 +00001949};
1950
1951struct target_semid_ds
1952{
1953 struct target_ipc_perm sem_perm;
blueswir1992f48a2007-10-14 16:27:31 +00001954 abi_ulong sem_otime;
1955 abi_ulong __unused1;
1956 abi_ulong sem_ctime;
1957 abi_ulong __unused2;
1958 abi_ulong sem_nsems;
1959 abi_ulong __unused3;
1960 abi_ulong __unused4;
ths3eb6b042007-06-03 14:26:27 +00001961};
1962
bellard579a97f2007-11-11 14:26:47 +00001963static inline abi_long target_to_host_ipc_perm(struct ipc_perm *host_ip,
1964 abi_ulong target_addr)
ths3eb6b042007-06-03 14:26:27 +00001965{
1966 struct target_ipc_perm *target_ip;
1967 struct target_semid_ds *target_sd;
1968
bellard579a97f2007-11-11 14:26:47 +00001969 if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
1970 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00001971 target_ip=&(target_sd->sem_perm);
1972 host_ip->__key = tswapl(target_ip->__key);
1973 host_ip->uid = tswapl(target_ip->uid);
1974 host_ip->gid = tswapl(target_ip->gid);
1975 host_ip->cuid = tswapl(target_ip->cuid);
1976 host_ip->cgid = tswapl(target_ip->cgid);
1977 host_ip->mode = tswapl(target_ip->mode);
1978 unlock_user_struct(target_sd, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00001979 return 0;
ths3eb6b042007-06-03 14:26:27 +00001980}
1981
bellard579a97f2007-11-11 14:26:47 +00001982static inline abi_long host_to_target_ipc_perm(abi_ulong target_addr,
1983 struct ipc_perm *host_ip)
ths3eb6b042007-06-03 14:26:27 +00001984{
1985 struct target_ipc_perm *target_ip;
1986 struct target_semid_ds *target_sd;
1987
bellard579a97f2007-11-11 14:26:47 +00001988 if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
1989 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00001990 target_ip = &(target_sd->sem_perm);
1991 target_ip->__key = tswapl(host_ip->__key);
1992 target_ip->uid = tswapl(host_ip->uid);
1993 target_ip->gid = tswapl(host_ip->gid);
1994 target_ip->cuid = tswapl(host_ip->cuid);
1995 target_ip->cgid = tswapl(host_ip->cgid);
1996 target_ip->mode = tswapl(host_ip->mode);
1997 unlock_user_struct(target_sd, target_addr, 1);
bellard579a97f2007-11-11 14:26:47 +00001998 return 0;
ths3eb6b042007-06-03 14:26:27 +00001999}
2000
bellard579a97f2007-11-11 14:26:47 +00002001static inline abi_long target_to_host_semid_ds(struct semid_ds *host_sd,
2002 abi_ulong target_addr)
ths3eb6b042007-06-03 14:26:27 +00002003{
2004 struct target_semid_ds *target_sd;
2005
bellard579a97f2007-11-11 14:26:47 +00002006 if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
2007 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00002008 target_to_host_ipc_perm(&(host_sd->sem_perm),target_addr);
2009 host_sd->sem_nsems = tswapl(target_sd->sem_nsems);
2010 host_sd->sem_otime = tswapl(target_sd->sem_otime);
2011 host_sd->sem_ctime = tswapl(target_sd->sem_ctime);
2012 unlock_user_struct(target_sd, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00002013 return 0;
ths3eb6b042007-06-03 14:26:27 +00002014}
2015
bellard579a97f2007-11-11 14:26:47 +00002016static inline abi_long host_to_target_semid_ds(abi_ulong target_addr,
2017 struct semid_ds *host_sd)
ths3eb6b042007-06-03 14:26:27 +00002018{
2019 struct target_semid_ds *target_sd;
2020
bellard579a97f2007-11-11 14:26:47 +00002021 if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
2022 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00002023 host_to_target_ipc_perm(target_addr,&(host_sd->sem_perm));
2024 target_sd->sem_nsems = tswapl(host_sd->sem_nsems);
2025 target_sd->sem_otime = tswapl(host_sd->sem_otime);
2026 target_sd->sem_ctime = tswapl(host_sd->sem_ctime);
2027 unlock_user_struct(target_sd, target_addr, 1);
bellard579a97f2007-11-11 14:26:47 +00002028 return 0;
ths3eb6b042007-06-03 14:26:27 +00002029}
2030
thsfa294812007-02-02 22:05:00 +00002031union semun {
2032 int val;
ths3eb6b042007-06-03 14:26:27 +00002033 struct semid_ds *buf;
thsfa294812007-02-02 22:05:00 +00002034 unsigned short *array;
2035};
2036
ths3eb6b042007-06-03 14:26:27 +00002037union target_semun {
2038 int val;
blueswir1992f48a2007-10-14 16:27:31 +00002039 abi_long buf;
ths3eb6b042007-06-03 14:26:27 +00002040 unsigned short int *array;
2041};
2042
bellard579a97f2007-11-11 14:26:47 +00002043static inline abi_long target_to_host_semun(int cmd,
2044 union semun *host_su,
2045 abi_ulong target_addr,
2046 struct semid_ds *ds)
ths3eb6b042007-06-03 14:26:27 +00002047{
2048 union target_semun *target_su;
2049
2050 switch( cmd ) {
2051 case IPC_STAT:
2052 case IPC_SET:
bellard579a97f2007-11-11 14:26:47 +00002053 if (!lock_user_struct(VERIFY_READ, target_su, target_addr, 1))
2054 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00002055 target_to_host_semid_ds(ds,target_su->buf);
2056 host_su->buf = ds;
2057 unlock_user_struct(target_su, target_addr, 0);
2058 break;
2059 case GETVAL:
2060 case SETVAL:
bellard579a97f2007-11-11 14:26:47 +00002061 if (!lock_user_struct(VERIFY_READ, target_su, target_addr, 1))
2062 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00002063 host_su->val = tswapl(target_su->val);
2064 unlock_user_struct(target_su, target_addr, 0);
2065 break;
2066 case GETALL:
2067 case SETALL:
bellard579a97f2007-11-11 14:26:47 +00002068 if (!lock_user_struct(VERIFY_READ, target_su, target_addr, 1))
2069 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00002070 *host_su->array = tswap16(*target_su->array);
2071 unlock_user_struct(target_su, target_addr, 0);
2072 break;
2073 default:
2074 gemu_log("semun operation not fully supported: %d\n", (int)cmd);
2075 }
bellard579a97f2007-11-11 14:26:47 +00002076 return 0;
ths3eb6b042007-06-03 14:26:27 +00002077}
2078
bellard579a97f2007-11-11 14:26:47 +00002079static inline abi_long host_to_target_semun(int cmd,
2080 abi_ulong target_addr,
2081 union semun *host_su,
2082 struct semid_ds *ds)
ths3eb6b042007-06-03 14:26:27 +00002083{
2084 union target_semun *target_su;
2085
2086 switch( cmd ) {
2087 case IPC_STAT:
2088 case IPC_SET:
bellard579a97f2007-11-11 14:26:47 +00002089 if (lock_user_struct(VERIFY_WRITE, target_su, target_addr, 0))
2090 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00002091 host_to_target_semid_ds(target_su->buf,ds);
2092 unlock_user_struct(target_su, target_addr, 1);
2093 break;
2094 case GETVAL:
2095 case SETVAL:
bellard579a97f2007-11-11 14:26:47 +00002096 if (lock_user_struct(VERIFY_WRITE, target_su, target_addr, 0))
2097 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00002098 target_su->val = tswapl(host_su->val);
2099 unlock_user_struct(target_su, target_addr, 1);
2100 break;
2101 case GETALL:
2102 case SETALL:
bellard579a97f2007-11-11 14:26:47 +00002103 if (lock_user_struct(VERIFY_WRITE, target_su, target_addr, 0))
2104 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00002105 *target_su->array = tswap16(*host_su->array);
2106 unlock_user_struct(target_su, target_addr, 1);
2107 break;
2108 default:
2109 gemu_log("semun operation not fully supported: %d\n", (int)cmd);
2110 }
bellard579a97f2007-11-11 14:26:47 +00002111 return 0;
ths3eb6b042007-06-03 14:26:27 +00002112}
2113
blueswir1992f48a2007-10-14 16:27:31 +00002114static inline abi_long do_semctl(int first, int second, int third,
2115 abi_long ptr)
ths3eb6b042007-06-03 14:26:27 +00002116{
2117 union semun arg;
2118 struct semid_ds dsarg;
2119 int cmd = third&0xff;
blueswir1992f48a2007-10-14 16:27:31 +00002120 abi_long ret = 0;
ths3eb6b042007-06-03 14:26:27 +00002121
2122 switch( cmd ) {
2123 case GETVAL:
2124 target_to_host_semun(cmd,&arg,ptr,&dsarg);
2125 ret = get_errno(semctl(first, second, cmd, arg));
2126 host_to_target_semun(cmd,ptr,&arg,&dsarg);
2127 break;
2128 case SETVAL:
2129 target_to_host_semun(cmd,&arg,ptr,&dsarg);
2130 ret = get_errno(semctl(first, second, cmd, arg));
2131 host_to_target_semun(cmd,ptr,&arg,&dsarg);
2132 break;
2133 case GETALL:
2134 target_to_host_semun(cmd,&arg,ptr,&dsarg);
2135 ret = get_errno(semctl(first, second, cmd, arg));
2136 host_to_target_semun(cmd,ptr,&arg,&dsarg);
2137 break;
2138 case SETALL:
2139 target_to_host_semun(cmd,&arg,ptr,&dsarg);
2140 ret = get_errno(semctl(first, second, cmd, arg));
2141 host_to_target_semun(cmd,ptr,&arg,&dsarg);
2142 break;
2143 case IPC_STAT:
2144 target_to_host_semun(cmd,&arg,ptr,&dsarg);
2145 ret = get_errno(semctl(first, second, cmd, arg));
2146 host_to_target_semun(cmd,ptr,&arg,&dsarg);
2147 break;
2148 case IPC_SET:
2149 target_to_host_semun(cmd,&arg,ptr,&dsarg);
2150 ret = get_errno(semctl(first, second, cmd, arg));
2151 host_to_target_semun(cmd,ptr,&arg,&dsarg);
2152 break;
2153 default:
2154 ret = get_errno(semctl(first, second, cmd, arg));
2155 }
2156
2157 return ret;
2158}
2159
ths1bc012f2007-06-03 14:27:49 +00002160struct target_msqid_ds
2161{
aurel321c54ff92008-10-13 21:08:44 +00002162 struct target_ipc_perm msg_perm;
2163 abi_ulong msg_stime;
2164#if TARGET_ABI_BITS == 32
2165 abi_ulong __unused1;
2166#endif
2167 abi_ulong msg_rtime;
2168#if TARGET_ABI_BITS == 32
2169 abi_ulong __unused2;
2170#endif
2171 abi_ulong msg_ctime;
2172#if TARGET_ABI_BITS == 32
2173 abi_ulong __unused3;
2174#endif
2175 abi_ulong __msg_cbytes;
2176 abi_ulong msg_qnum;
2177 abi_ulong msg_qbytes;
2178 abi_ulong msg_lspid;
2179 abi_ulong msg_lrpid;
2180 abi_ulong __unused4;
2181 abi_ulong __unused5;
ths1bc012f2007-06-03 14:27:49 +00002182};
2183
bellard579a97f2007-11-11 14:26:47 +00002184static inline abi_long target_to_host_msqid_ds(struct msqid_ds *host_md,
2185 abi_ulong target_addr)
ths1bc012f2007-06-03 14:27:49 +00002186{
2187 struct target_msqid_ds *target_md;
2188
bellard579a97f2007-11-11 14:26:47 +00002189 if (!lock_user_struct(VERIFY_READ, target_md, target_addr, 1))
2190 return -TARGET_EFAULT;
aurel321c54ff92008-10-13 21:08:44 +00002191 if (target_to_host_ipc_perm(&(host_md->msg_perm),target_addr))
2192 return -TARGET_EFAULT;
ths1bc012f2007-06-03 14:27:49 +00002193 host_md->msg_stime = tswapl(target_md->msg_stime);
2194 host_md->msg_rtime = tswapl(target_md->msg_rtime);
2195 host_md->msg_ctime = tswapl(target_md->msg_ctime);
2196 host_md->__msg_cbytes = tswapl(target_md->__msg_cbytes);
2197 host_md->msg_qnum = tswapl(target_md->msg_qnum);
2198 host_md->msg_qbytes = tswapl(target_md->msg_qbytes);
2199 host_md->msg_lspid = tswapl(target_md->msg_lspid);
2200 host_md->msg_lrpid = tswapl(target_md->msg_lrpid);
2201 unlock_user_struct(target_md, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00002202 return 0;
ths1bc012f2007-06-03 14:27:49 +00002203}
2204
bellard579a97f2007-11-11 14:26:47 +00002205static inline abi_long host_to_target_msqid_ds(abi_ulong target_addr,
2206 struct msqid_ds *host_md)
ths1bc012f2007-06-03 14:27:49 +00002207{
2208 struct target_msqid_ds *target_md;
2209
bellard579a97f2007-11-11 14:26:47 +00002210 if (!lock_user_struct(VERIFY_WRITE, target_md, target_addr, 0))
2211 return -TARGET_EFAULT;
aurel321c54ff92008-10-13 21:08:44 +00002212 if (host_to_target_ipc_perm(target_addr,&(host_md->msg_perm)))
2213 return -TARGET_EFAULT;
ths1bc012f2007-06-03 14:27:49 +00002214 target_md->msg_stime = tswapl(host_md->msg_stime);
2215 target_md->msg_rtime = tswapl(host_md->msg_rtime);
2216 target_md->msg_ctime = tswapl(host_md->msg_ctime);
2217 target_md->__msg_cbytes = tswapl(host_md->__msg_cbytes);
2218 target_md->msg_qnum = tswapl(host_md->msg_qnum);
2219 target_md->msg_qbytes = tswapl(host_md->msg_qbytes);
2220 target_md->msg_lspid = tswapl(host_md->msg_lspid);
2221 target_md->msg_lrpid = tswapl(host_md->msg_lrpid);
2222 unlock_user_struct(target_md, target_addr, 1);
bellard579a97f2007-11-11 14:26:47 +00002223 return 0;
ths1bc012f2007-06-03 14:27:49 +00002224}
2225
aurel321c54ff92008-10-13 21:08:44 +00002226struct target_msginfo {
2227 int msgpool;
2228 int msgmap;
2229 int msgmax;
2230 int msgmnb;
2231 int msgmni;
2232 int msgssz;
2233 int msgtql;
2234 unsigned short int msgseg;
2235};
2236
2237static inline abi_long host_to_target_msginfo(abi_ulong target_addr,
2238 struct msginfo *host_msginfo)
2239{
2240 struct target_msginfo *target_msginfo;
2241 if (!lock_user_struct(VERIFY_WRITE, target_msginfo, target_addr, 0))
2242 return -TARGET_EFAULT;
2243 __put_user(host_msginfo->msgpool, &target_msginfo->msgpool);
2244 __put_user(host_msginfo->msgmap, &target_msginfo->msgmap);
2245 __put_user(host_msginfo->msgmax, &target_msginfo->msgmax);
2246 __put_user(host_msginfo->msgmnb, &target_msginfo->msgmnb);
2247 __put_user(host_msginfo->msgmni, &target_msginfo->msgmni);
2248 __put_user(host_msginfo->msgssz, &target_msginfo->msgssz);
2249 __put_user(host_msginfo->msgtql, &target_msginfo->msgtql);
2250 __put_user(host_msginfo->msgseg, &target_msginfo->msgseg);
2251 unlock_user_struct(target_msginfo, target_addr, 1);
aurel3200b229a2008-10-24 13:12:52 +00002252 return 0;
aurel321c54ff92008-10-13 21:08:44 +00002253}
2254
2255static inline abi_long do_msgctl(int msgid, int cmd, abi_long ptr)
ths1bc012f2007-06-03 14:27:49 +00002256{
2257 struct msqid_ds dsarg;
aurel321c54ff92008-10-13 21:08:44 +00002258 struct msginfo msginfo;
2259 abi_long ret = -TARGET_EINVAL;
2260
2261 cmd &= 0xff;
2262
2263 switch (cmd) {
ths1bc012f2007-06-03 14:27:49 +00002264 case IPC_STAT:
2265 case IPC_SET:
aurel321c54ff92008-10-13 21:08:44 +00002266 case MSG_STAT:
2267 if (target_to_host_msqid_ds(&dsarg,ptr))
2268 return -TARGET_EFAULT;
2269 ret = get_errno(msgctl(msgid, cmd, &dsarg));
2270 if (host_to_target_msqid_ds(ptr,&dsarg))
2271 return -TARGET_EFAULT;
2272 break;
2273 case IPC_RMID:
2274 ret = get_errno(msgctl(msgid, cmd, NULL));
2275 break;
2276 case IPC_INFO:
2277 case MSG_INFO:
2278 ret = get_errno(msgctl(msgid, cmd, (struct msqid_ds *)&msginfo));
2279 if (host_to_target_msginfo(ptr, &msginfo))
2280 return -TARGET_EFAULT;
2281 break;
ths1bc012f2007-06-03 14:27:49 +00002282 }
aurel321c54ff92008-10-13 21:08:44 +00002283
ths1bc012f2007-06-03 14:27:49 +00002284 return ret;
2285}
2286
2287struct target_msgbuf {
aurel321c54ff92008-10-13 21:08:44 +00002288 abi_long mtype;
2289 char mtext[1];
ths1bc012f2007-06-03 14:27:49 +00002290};
2291
blueswir1992f48a2007-10-14 16:27:31 +00002292static inline abi_long do_msgsnd(int msqid, abi_long msgp,
2293 unsigned int msgsz, int msgflg)
ths1bc012f2007-06-03 14:27:49 +00002294{
2295 struct target_msgbuf *target_mb;
2296 struct msgbuf *host_mb;
blueswir1992f48a2007-10-14 16:27:31 +00002297 abi_long ret = 0;
ths1bc012f2007-06-03 14:27:49 +00002298
bellard579a97f2007-11-11 14:26:47 +00002299 if (!lock_user_struct(VERIFY_READ, target_mb, msgp, 0))
2300 return -TARGET_EFAULT;
ths1bc012f2007-06-03 14:27:49 +00002301 host_mb = malloc(msgsz+sizeof(long));
aurel321c54ff92008-10-13 21:08:44 +00002302 host_mb->mtype = (abi_long) tswapl(target_mb->mtype);
2303 memcpy(host_mb->mtext, target_mb->mtext, msgsz);
ths1bc012f2007-06-03 14:27:49 +00002304 ret = get_errno(msgsnd(msqid, host_mb, msgsz, msgflg));
2305 free(host_mb);
2306 unlock_user_struct(target_mb, msgp, 0);
2307
2308 return ret;
2309}
2310
blueswir1992f48a2007-10-14 16:27:31 +00002311static inline abi_long do_msgrcv(int msqid, abi_long msgp,
aurel321c54ff92008-10-13 21:08:44 +00002312 unsigned int msgsz, abi_long msgtyp,
blueswir1992f48a2007-10-14 16:27:31 +00002313 int msgflg)
ths1bc012f2007-06-03 14:27:49 +00002314{
2315 struct target_msgbuf *target_mb;
bellard579a97f2007-11-11 14:26:47 +00002316 char *target_mtext;
ths1bc012f2007-06-03 14:27:49 +00002317 struct msgbuf *host_mb;
blueswir1992f48a2007-10-14 16:27:31 +00002318 abi_long ret = 0;
ths1bc012f2007-06-03 14:27:49 +00002319
bellard579a97f2007-11-11 14:26:47 +00002320 if (!lock_user_struct(VERIFY_WRITE, target_mb, msgp, 0))
2321 return -TARGET_EFAULT;
aurel321c54ff92008-10-13 21:08:44 +00002322
ths1bc012f2007-06-03 14:27:49 +00002323 host_mb = malloc(msgsz+sizeof(long));
aurel321c54ff92008-10-13 21:08:44 +00002324 ret = get_errno(msgrcv(msqid, host_mb, msgsz, tswapl(msgtyp), msgflg));
2325
bellard579a97f2007-11-11 14:26:47 +00002326 if (ret > 0) {
2327 abi_ulong target_mtext_addr = msgp + sizeof(abi_ulong);
2328 target_mtext = lock_user(VERIFY_WRITE, target_mtext_addr, ret, 0);
2329 if (!target_mtext) {
2330 ret = -TARGET_EFAULT;
2331 goto end;
2332 }
aurel321c54ff92008-10-13 21:08:44 +00002333 memcpy(target_mb->mtext, host_mb->mtext, ret);
bellard579a97f2007-11-11 14:26:47 +00002334 unlock_user(target_mtext, target_mtext_addr, ret);
2335 }
aurel321c54ff92008-10-13 21:08:44 +00002336
ths1bc012f2007-06-03 14:27:49 +00002337 target_mb->mtype = tswapl(host_mb->mtype);
2338 free(host_mb);
ths1bc012f2007-06-03 14:27:49 +00002339
bellard579a97f2007-11-11 14:26:47 +00002340end:
2341 if (target_mb)
2342 unlock_user_struct(target_mb, msgp, 1);
ths1bc012f2007-06-03 14:27:49 +00002343 return ret;
2344}
2345
aurel321c54ff92008-10-13 21:08:44 +00002346#ifdef TARGET_NR_ipc
pbrook53a59602006-03-25 19:31:22 +00002347/* ??? This only works with linear mappings. */
ths0da46a62007-10-20 20:23:07 +00002348/* do_ipc() must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00002349static abi_long do_ipc(unsigned int call, int first,
2350 int second, int third,
2351 abi_long ptr, abi_long fifth)
bellard8853f862004-02-22 14:57:26 +00002352{
2353 int version;
blueswir1992f48a2007-10-14 16:27:31 +00002354 abi_long ret = 0;
bellard8853f862004-02-22 14:57:26 +00002355 struct shmid_ds shm_info;
2356 int i;
2357
2358 version = call >> 16;
2359 call &= 0xffff;
2360
2361 switch (call) {
thsfa294812007-02-02 22:05:00 +00002362 case IPCOP_semop:
bellard579a97f2007-11-11 14:26:47 +00002363 ret = get_errno(semop(first,(struct sembuf *)g2h(ptr), second));
thsfa294812007-02-02 22:05:00 +00002364 break;
2365
2366 case IPCOP_semget:
2367 ret = get_errno(semget(first, second, third));
2368 break;
2369
2370 case IPCOP_semctl:
ths3eb6b042007-06-03 14:26:27 +00002371 ret = do_semctl(first, second, third, ptr);
thsfa294812007-02-02 22:05:00 +00002372 break;
2373
2374 case IPCOP_semtimedop:
j_mayer32407102007-09-26 23:01:49 +00002375 gemu_log("Unsupported ipc call: %d (version %d)\n", call, version);
ths0da46a62007-10-20 20:23:07 +00002376 ret = -TARGET_ENOSYS;
thsfa294812007-02-02 22:05:00 +00002377 break;
thsd96372e2007-02-02 22:05:44 +00002378
aurel321c54ff92008-10-13 21:08:44 +00002379 case IPCOP_msgget:
2380 ret = get_errno(msgget(first, second));
2381 break;
thsd96372e2007-02-02 22:05:44 +00002382
aurel321c54ff92008-10-13 21:08:44 +00002383 case IPCOP_msgsnd:
2384 ret = do_msgsnd(first, ptr, second, third);
2385 break;
thsd96372e2007-02-02 22:05:44 +00002386
aurel321c54ff92008-10-13 21:08:44 +00002387 case IPCOP_msgctl:
2388 ret = do_msgctl(first, second, ptr);
2389 break;
thsd96372e2007-02-02 22:05:44 +00002390
aurel321c54ff92008-10-13 21:08:44 +00002391 case IPCOP_msgrcv:
2392 switch (version) {
2393 case 0:
2394 {
2395 struct target_ipc_kludge {
2396 abi_long msgp;
2397 abi_long msgtyp;
2398 } *tmp;
thsd96372e2007-02-02 22:05:44 +00002399
aurel321c54ff92008-10-13 21:08:44 +00002400 if (!lock_user_struct(VERIFY_READ, tmp, ptr, 1)) {
2401 ret = -TARGET_EFAULT;
2402 break;
ths1bc012f2007-06-03 14:27:49 +00002403 }
aurel321c54ff92008-10-13 21:08:44 +00002404
2405 ret = do_msgrcv(first, tmp->msgp, second, tmp->msgtyp, third);
2406
2407 unlock_user_struct(tmp, ptr, 0);
2408 break;
2409 }
2410 default:
2411 ret = do_msgrcv(first, ptr, second, fifth, third);
2412 }
2413 break;
thsd96372e2007-02-02 22:05:44 +00002414
bellard8853f862004-02-22 14:57:26 +00002415 case IPCOP_shmat:
bellard5a4a8982007-11-11 17:39:18 +00002416 {
2417 abi_ulong raddr;
2418 void *host_addr;
2419 /* SHM_* flags are the same on all linux platforms */
2420 host_addr = shmat(first, (void *)g2h(ptr), second);
2421 if (host_addr == (void *)-1) {
2422 ret = get_errno((long)host_addr);
bellard8853f862004-02-22 14:57:26 +00002423 break;
bellard5a4a8982007-11-11 17:39:18 +00002424 }
2425 raddr = h2g((unsigned long)host_addr);
2426 /* find out the length of the shared memory segment */
2427
2428 ret = get_errno(shmctl(first, IPC_STAT, &shm_info));
2429 if (is_error(ret)) {
2430 /* can't get length, bail out */
2431 shmdt(host_addr);
2432 break;
2433 }
2434 page_set_flags(raddr, raddr + shm_info.shm_segsz,
2435 PAGE_VALID | PAGE_READ |
2436 ((second & SHM_RDONLY)? 0: PAGE_WRITE));
2437 for (i = 0; i < N_SHM_REGIONS; ++i) {
2438 if (shm_regions[i].start == 0) {
2439 shm_regions[i].start = raddr;
2440 shm_regions[i].size = shm_info.shm_segsz;
2441 break;
2442 }
2443 }
bellard2f619692007-11-16 10:46:05 +00002444 if (put_user_ual(raddr, third))
bellard5a4a8982007-11-11 17:39:18 +00002445 return -TARGET_EFAULT;
2446 ret = 0;
2447 }
bellard8853f862004-02-22 14:57:26 +00002448 break;
2449 case IPCOP_shmdt:
2450 for (i = 0; i < N_SHM_REGIONS; ++i) {
2451 if (shm_regions[i].start == ptr) {
2452 shm_regions[i].start = 0;
2453 page_set_flags(ptr, shm_regions[i].size, 0);
2454 break;
2455 }
2456 }
bellard5a4a8982007-11-11 17:39:18 +00002457 ret = get_errno(shmdt((void *)g2h(ptr)));
bellard8853f862004-02-22 14:57:26 +00002458 break;
2459
2460 case IPCOP_shmget:
2461 /* IPC_* flag values are the same on all linux platforms */
2462 ret = get_errno(shmget(first, second, third));
2463 break;
2464
2465 /* IPC_* and SHM_* command values are the same on all linux platforms */
2466 case IPCOP_shmctl:
2467 switch(second) {
2468 case IPC_RMID:
2469 case SHM_LOCK:
2470 case SHM_UNLOCK:
2471 ret = get_errno(shmctl(first, second, NULL));
2472 break;
2473 default:
2474 goto unimplemented;
2475 }
2476 break;
2477 default:
2478 unimplemented:
j_mayer32407102007-09-26 23:01:49 +00002479 gemu_log("Unsupported ipc call: %d (version %d)\n", call, version);
ths0da46a62007-10-20 20:23:07 +00002480 ret = -TARGET_ENOSYS;
bellard8853f862004-02-22 14:57:26 +00002481 break;
2482 }
2483 return ret;
2484}
j_mayer32407102007-09-26 23:01:49 +00002485#endif
bellard8853f862004-02-22 14:57:26 +00002486
bellard31e31b82003-02-18 22:55:36 +00002487/* kernel structure types definitions */
2488#define IFNAMSIZ 16
2489
2490#define STRUCT(name, list...) STRUCT_ ## name,
2491#define STRUCT_SPECIAL(name) STRUCT_ ## name,
2492enum {
2493#include "syscall_types.h"
2494};
2495#undef STRUCT
2496#undef STRUCT_SPECIAL
2497
blueswir160dd3162008-10-05 11:45:25 +00002498#define STRUCT(name, list...) static const argtype struct_ ## name ## _def[] = { list, TYPE_NULL };
bellard31e31b82003-02-18 22:55:36 +00002499#define STRUCT_SPECIAL(name)
2500#include "syscall_types.h"
2501#undef STRUCT
2502#undef STRUCT_SPECIAL
2503
2504typedef struct IOCTLEntry {
bellard2ab83ea2003-06-15 19:56:46 +00002505 unsigned int target_cmd;
2506 unsigned int host_cmd;
bellard31e31b82003-02-18 22:55:36 +00002507 const char *name;
2508 int access;
bellard1a9353d2003-03-16 20:28:50 +00002509 const argtype arg_type[5];
bellard31e31b82003-02-18 22:55:36 +00002510} IOCTLEntry;
2511
2512#define IOC_R 0x0001
2513#define IOC_W 0x0002
2514#define IOC_RW (IOC_R | IOC_W)
2515
2516#define MAX_STRUCT_SIZE 4096
2517
blueswir19f106a72008-10-05 10:52:52 +00002518static IOCTLEntry ioctl_entries[] = {
bellard31e31b82003-02-18 22:55:36 +00002519#define IOCTL(cmd, access, types...) \
2520 { TARGET_ ## cmd, cmd, #cmd, access, { types } },
2521#include "ioctls.h"
2522 { 0, 0, },
2523};
2524
pbrook53a59602006-03-25 19:31:22 +00002525/* ??? Implement proper locking for ioctls. */
ths0da46a62007-10-20 20:23:07 +00002526/* do_ioctl() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00002527static abi_long do_ioctl(int fd, abi_long cmd, abi_long arg)
bellard31e31b82003-02-18 22:55:36 +00002528{
2529 const IOCTLEntry *ie;
2530 const argtype *arg_type;
blueswir1992f48a2007-10-14 16:27:31 +00002531 abi_long ret;
bellard31e31b82003-02-18 22:55:36 +00002532 uint8_t buf_temp[MAX_STRUCT_SIZE];
pbrook53a59602006-03-25 19:31:22 +00002533 int target_size;
2534 void *argptr;
bellard31e31b82003-02-18 22:55:36 +00002535
2536 ie = ioctl_entries;
2537 for(;;) {
2538 if (ie->target_cmd == 0) {
j_mayer32407102007-09-26 23:01:49 +00002539 gemu_log("Unsupported ioctl: cmd=0x%04lx\n", (long)cmd);
ths0da46a62007-10-20 20:23:07 +00002540 return -TARGET_ENOSYS;
bellard31e31b82003-02-18 22:55:36 +00002541 }
2542 if (ie->target_cmd == cmd)
2543 break;
2544 ie++;
2545 }
2546 arg_type = ie->arg_type;
bellard9de5e442003-03-23 16:49:39 +00002547#if defined(DEBUG)
j_mayer32407102007-09-26 23:01:49 +00002548 gemu_log("ioctl: cmd=0x%04lx (%s)\n", (long)cmd, ie->name);
bellard72f03902003-02-18 23:33:18 +00002549#endif
bellard31e31b82003-02-18 22:55:36 +00002550 switch(arg_type[0]) {
2551 case TYPE_NULL:
2552 /* no argument */
2553 ret = get_errno(ioctl(fd, ie->host_cmd));
2554 break;
2555 case TYPE_PTRVOID:
2556 case TYPE_INT:
2557 /* int argment */
2558 ret = get_errno(ioctl(fd, ie->host_cmd, arg));
2559 break;
2560 case TYPE_PTR:
2561 arg_type++;
pbrook53a59602006-03-25 19:31:22 +00002562 target_size = thunk_type_size(arg_type, 0);
bellard31e31b82003-02-18 22:55:36 +00002563 switch(ie->access) {
2564 case IOC_R:
2565 ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
2566 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00002567 argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
2568 if (!argptr)
2569 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00002570 thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
2571 unlock_user(argptr, arg, target_size);
bellard31e31b82003-02-18 22:55:36 +00002572 }
2573 break;
2574 case IOC_W:
bellard579a97f2007-11-11 14:26:47 +00002575 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
2576 if (!argptr)
2577 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00002578 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
2579 unlock_user(argptr, arg, 0);
bellard31e31b82003-02-18 22:55:36 +00002580 ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
2581 break;
2582 default:
2583 case IOC_RW:
bellard579a97f2007-11-11 14:26:47 +00002584 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
2585 if (!argptr)
2586 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00002587 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
2588 unlock_user(argptr, arg, 0);
bellard31e31b82003-02-18 22:55:36 +00002589 ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
2590 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00002591 argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
2592 if (!argptr)
2593 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00002594 thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
2595 unlock_user(argptr, arg, target_size);
bellard31e31b82003-02-18 22:55:36 +00002596 }
2597 break;
2598 }
2599 break;
2600 default:
j_mayer32407102007-09-26 23:01:49 +00002601 gemu_log("Unsupported ioctl type: cmd=0x%04lx type=%d\n",
2602 (long)cmd, arg_type[0]);
ths0da46a62007-10-20 20:23:07 +00002603 ret = -TARGET_ENOSYS;
bellard31e31b82003-02-18 22:55:36 +00002604 break;
2605 }
2606 return ret;
2607}
2608
blueswir1b39bc502008-10-05 10:51:10 +00002609static const bitmask_transtbl iflag_tbl[] = {
bellard31e31b82003-02-18 22:55:36 +00002610 { TARGET_IGNBRK, TARGET_IGNBRK, IGNBRK, IGNBRK },
2611 { TARGET_BRKINT, TARGET_BRKINT, BRKINT, BRKINT },
2612 { TARGET_IGNPAR, TARGET_IGNPAR, IGNPAR, IGNPAR },
2613 { TARGET_PARMRK, TARGET_PARMRK, PARMRK, PARMRK },
2614 { TARGET_INPCK, TARGET_INPCK, INPCK, INPCK },
2615 { TARGET_ISTRIP, TARGET_ISTRIP, ISTRIP, ISTRIP },
2616 { TARGET_INLCR, TARGET_INLCR, INLCR, INLCR },
2617 { TARGET_IGNCR, TARGET_IGNCR, IGNCR, IGNCR },
2618 { TARGET_ICRNL, TARGET_ICRNL, ICRNL, ICRNL },
2619 { TARGET_IUCLC, TARGET_IUCLC, IUCLC, IUCLC },
2620 { TARGET_IXON, TARGET_IXON, IXON, IXON },
2621 { TARGET_IXANY, TARGET_IXANY, IXANY, IXANY },
2622 { TARGET_IXOFF, TARGET_IXOFF, IXOFF, IXOFF },
2623 { TARGET_IMAXBEL, TARGET_IMAXBEL, IMAXBEL, IMAXBEL },
2624 { 0, 0, 0, 0 }
2625};
2626
blueswir1b39bc502008-10-05 10:51:10 +00002627static const bitmask_transtbl oflag_tbl[] = {
bellard31e31b82003-02-18 22:55:36 +00002628 { TARGET_OPOST, TARGET_OPOST, OPOST, OPOST },
2629 { TARGET_OLCUC, TARGET_OLCUC, OLCUC, OLCUC },
2630 { TARGET_ONLCR, TARGET_ONLCR, ONLCR, ONLCR },
2631 { TARGET_OCRNL, TARGET_OCRNL, OCRNL, OCRNL },
2632 { TARGET_ONOCR, TARGET_ONOCR, ONOCR, ONOCR },
2633 { TARGET_ONLRET, TARGET_ONLRET, ONLRET, ONLRET },
2634 { TARGET_OFILL, TARGET_OFILL, OFILL, OFILL },
2635 { TARGET_OFDEL, TARGET_OFDEL, OFDEL, OFDEL },
2636 { TARGET_NLDLY, TARGET_NL0, NLDLY, NL0 },
2637 { TARGET_NLDLY, TARGET_NL1, NLDLY, NL1 },
2638 { TARGET_CRDLY, TARGET_CR0, CRDLY, CR0 },
2639 { TARGET_CRDLY, TARGET_CR1, CRDLY, CR1 },
2640 { TARGET_CRDLY, TARGET_CR2, CRDLY, CR2 },
2641 { TARGET_CRDLY, TARGET_CR3, CRDLY, CR3 },
2642 { TARGET_TABDLY, TARGET_TAB0, TABDLY, TAB0 },
2643 { TARGET_TABDLY, TARGET_TAB1, TABDLY, TAB1 },
2644 { TARGET_TABDLY, TARGET_TAB2, TABDLY, TAB2 },
2645 { TARGET_TABDLY, TARGET_TAB3, TABDLY, TAB3 },
2646 { TARGET_BSDLY, TARGET_BS0, BSDLY, BS0 },
2647 { TARGET_BSDLY, TARGET_BS1, BSDLY, BS1 },
2648 { TARGET_VTDLY, TARGET_VT0, VTDLY, VT0 },
2649 { TARGET_VTDLY, TARGET_VT1, VTDLY, VT1 },
2650 { TARGET_FFDLY, TARGET_FF0, FFDLY, FF0 },
2651 { TARGET_FFDLY, TARGET_FF1, FFDLY, FF1 },
2652 { 0, 0, 0, 0 }
2653};
2654
blueswir1b39bc502008-10-05 10:51:10 +00002655static const bitmask_transtbl cflag_tbl[] = {
bellard31e31b82003-02-18 22:55:36 +00002656 { TARGET_CBAUD, TARGET_B0, CBAUD, B0 },
2657 { TARGET_CBAUD, TARGET_B50, CBAUD, B50 },
2658 { TARGET_CBAUD, TARGET_B75, CBAUD, B75 },
2659 { TARGET_CBAUD, TARGET_B110, CBAUD, B110 },
2660 { TARGET_CBAUD, TARGET_B134, CBAUD, B134 },
2661 { TARGET_CBAUD, TARGET_B150, CBAUD, B150 },
2662 { TARGET_CBAUD, TARGET_B200, CBAUD, B200 },
2663 { TARGET_CBAUD, TARGET_B300, CBAUD, B300 },
2664 { TARGET_CBAUD, TARGET_B600, CBAUD, B600 },
2665 { TARGET_CBAUD, TARGET_B1200, CBAUD, B1200 },
2666 { TARGET_CBAUD, TARGET_B1800, CBAUD, B1800 },
2667 { TARGET_CBAUD, TARGET_B2400, CBAUD, B2400 },
2668 { TARGET_CBAUD, TARGET_B4800, CBAUD, B4800 },
2669 { TARGET_CBAUD, TARGET_B9600, CBAUD, B9600 },
2670 { TARGET_CBAUD, TARGET_B19200, CBAUD, B19200 },
2671 { TARGET_CBAUD, TARGET_B38400, CBAUD, B38400 },
2672 { TARGET_CBAUD, TARGET_B57600, CBAUD, B57600 },
2673 { TARGET_CBAUD, TARGET_B115200, CBAUD, B115200 },
2674 { TARGET_CBAUD, TARGET_B230400, CBAUD, B230400 },
2675 { TARGET_CBAUD, TARGET_B460800, CBAUD, B460800 },
2676 { TARGET_CSIZE, TARGET_CS5, CSIZE, CS5 },
2677 { TARGET_CSIZE, TARGET_CS6, CSIZE, CS6 },
2678 { TARGET_CSIZE, TARGET_CS7, CSIZE, CS7 },
2679 { TARGET_CSIZE, TARGET_CS8, CSIZE, CS8 },
2680 { TARGET_CSTOPB, TARGET_CSTOPB, CSTOPB, CSTOPB },
2681 { TARGET_CREAD, TARGET_CREAD, CREAD, CREAD },
2682 { TARGET_PARENB, TARGET_PARENB, PARENB, PARENB },
2683 { TARGET_PARODD, TARGET_PARODD, PARODD, PARODD },
2684 { TARGET_HUPCL, TARGET_HUPCL, HUPCL, HUPCL },
2685 { TARGET_CLOCAL, TARGET_CLOCAL, CLOCAL, CLOCAL },
2686 { TARGET_CRTSCTS, TARGET_CRTSCTS, CRTSCTS, CRTSCTS },
2687 { 0, 0, 0, 0 }
2688};
2689
blueswir1b39bc502008-10-05 10:51:10 +00002690static const bitmask_transtbl lflag_tbl[] = {
bellard31e31b82003-02-18 22:55:36 +00002691 { TARGET_ISIG, TARGET_ISIG, ISIG, ISIG },
2692 { TARGET_ICANON, TARGET_ICANON, ICANON, ICANON },
2693 { TARGET_XCASE, TARGET_XCASE, XCASE, XCASE },
2694 { TARGET_ECHO, TARGET_ECHO, ECHO, ECHO },
2695 { TARGET_ECHOE, TARGET_ECHOE, ECHOE, ECHOE },
2696 { TARGET_ECHOK, TARGET_ECHOK, ECHOK, ECHOK },
2697 { TARGET_ECHONL, TARGET_ECHONL, ECHONL, ECHONL },
2698 { TARGET_NOFLSH, TARGET_NOFLSH, NOFLSH, NOFLSH },
2699 { TARGET_TOSTOP, TARGET_TOSTOP, TOSTOP, TOSTOP },
2700 { TARGET_ECHOCTL, TARGET_ECHOCTL, ECHOCTL, ECHOCTL },
2701 { TARGET_ECHOPRT, TARGET_ECHOPRT, ECHOPRT, ECHOPRT },
2702 { TARGET_ECHOKE, TARGET_ECHOKE, ECHOKE, ECHOKE },
2703 { TARGET_FLUSHO, TARGET_FLUSHO, FLUSHO, FLUSHO },
2704 { TARGET_PENDIN, TARGET_PENDIN, PENDIN, PENDIN },
2705 { TARGET_IEXTEN, TARGET_IEXTEN, IEXTEN, IEXTEN },
2706 { 0, 0, 0, 0 }
2707};
2708
2709static void target_to_host_termios (void *dst, const void *src)
2710{
2711 struct host_termios *host = dst;
2712 const struct target_termios *target = src;
ths3b46e622007-09-17 08:09:54 +00002713
ths5fafdf22007-09-16 21:08:06 +00002714 host->c_iflag =
bellard31e31b82003-02-18 22:55:36 +00002715 target_to_host_bitmask(tswap32(target->c_iflag), iflag_tbl);
ths5fafdf22007-09-16 21:08:06 +00002716 host->c_oflag =
bellard31e31b82003-02-18 22:55:36 +00002717 target_to_host_bitmask(tswap32(target->c_oflag), oflag_tbl);
ths5fafdf22007-09-16 21:08:06 +00002718 host->c_cflag =
bellard31e31b82003-02-18 22:55:36 +00002719 target_to_host_bitmask(tswap32(target->c_cflag), cflag_tbl);
ths5fafdf22007-09-16 21:08:06 +00002720 host->c_lflag =
bellard31e31b82003-02-18 22:55:36 +00002721 target_to_host_bitmask(tswap32(target->c_lflag), lflag_tbl);
2722 host->c_line = target->c_line;
ths3b46e622007-09-17 08:09:54 +00002723
ths5fafdf22007-09-16 21:08:06 +00002724 host->c_cc[VINTR] = target->c_cc[TARGET_VINTR];
2725 host->c_cc[VQUIT] = target->c_cc[TARGET_VQUIT];
ths3b46e622007-09-17 08:09:54 +00002726 host->c_cc[VERASE] = target->c_cc[TARGET_VERASE];
ths5fafdf22007-09-16 21:08:06 +00002727 host->c_cc[VKILL] = target->c_cc[TARGET_VKILL];
ths3b46e622007-09-17 08:09:54 +00002728 host->c_cc[VEOF] = target->c_cc[TARGET_VEOF];
ths5fafdf22007-09-16 21:08:06 +00002729 host->c_cc[VTIME] = target->c_cc[TARGET_VTIME];
ths3b46e622007-09-17 08:09:54 +00002730 host->c_cc[VMIN] = target->c_cc[TARGET_VMIN];
ths5fafdf22007-09-16 21:08:06 +00002731 host->c_cc[VSWTC] = target->c_cc[TARGET_VSWTC];
ths3b46e622007-09-17 08:09:54 +00002732 host->c_cc[VSTART] = target->c_cc[TARGET_VSTART];
ths5fafdf22007-09-16 21:08:06 +00002733 host->c_cc[VSTOP] = target->c_cc[TARGET_VSTOP];
2734 host->c_cc[VSUSP] = target->c_cc[TARGET_VSUSP];
ths3b46e622007-09-17 08:09:54 +00002735 host->c_cc[VEOL] = target->c_cc[TARGET_VEOL];
2736 host->c_cc[VREPRINT] = target->c_cc[TARGET_VREPRINT];
2737 host->c_cc[VDISCARD] = target->c_cc[TARGET_VDISCARD];
2738 host->c_cc[VWERASE] = target->c_cc[TARGET_VWERASE];
2739 host->c_cc[VLNEXT] = target->c_cc[TARGET_VLNEXT];
ths5fafdf22007-09-16 21:08:06 +00002740 host->c_cc[VEOL2] = target->c_cc[TARGET_VEOL2];
bellard31e31b82003-02-18 22:55:36 +00002741}
ths3b46e622007-09-17 08:09:54 +00002742
bellard31e31b82003-02-18 22:55:36 +00002743static void host_to_target_termios (void *dst, const void *src)
2744{
2745 struct target_termios *target = dst;
2746 const struct host_termios *host = src;
2747
ths5fafdf22007-09-16 21:08:06 +00002748 target->c_iflag =
bellard31e31b82003-02-18 22:55:36 +00002749 tswap32(host_to_target_bitmask(host->c_iflag, iflag_tbl));
ths5fafdf22007-09-16 21:08:06 +00002750 target->c_oflag =
bellard31e31b82003-02-18 22:55:36 +00002751 tswap32(host_to_target_bitmask(host->c_oflag, oflag_tbl));
ths5fafdf22007-09-16 21:08:06 +00002752 target->c_cflag =
bellard31e31b82003-02-18 22:55:36 +00002753 tswap32(host_to_target_bitmask(host->c_cflag, cflag_tbl));
ths5fafdf22007-09-16 21:08:06 +00002754 target->c_lflag =
bellard31e31b82003-02-18 22:55:36 +00002755 tswap32(host_to_target_bitmask(host->c_lflag, lflag_tbl));
2756 target->c_line = host->c_line;
ths3b46e622007-09-17 08:09:54 +00002757
bellard31e31b82003-02-18 22:55:36 +00002758 target->c_cc[TARGET_VINTR] = host->c_cc[VINTR];
2759 target->c_cc[TARGET_VQUIT] = host->c_cc[VQUIT];
2760 target->c_cc[TARGET_VERASE] = host->c_cc[VERASE];
2761 target->c_cc[TARGET_VKILL] = host->c_cc[VKILL];
2762 target->c_cc[TARGET_VEOF] = host->c_cc[VEOF];
2763 target->c_cc[TARGET_VTIME] = host->c_cc[VTIME];
2764 target->c_cc[TARGET_VMIN] = host->c_cc[VMIN];
2765 target->c_cc[TARGET_VSWTC] = host->c_cc[VSWTC];
2766 target->c_cc[TARGET_VSTART] = host->c_cc[VSTART];
2767 target->c_cc[TARGET_VSTOP] = host->c_cc[VSTOP];
2768 target->c_cc[TARGET_VSUSP] = host->c_cc[VSUSP];
2769 target->c_cc[TARGET_VEOL] = host->c_cc[VEOL];
2770 target->c_cc[TARGET_VREPRINT] = host->c_cc[VREPRINT];
2771 target->c_cc[TARGET_VDISCARD] = host->c_cc[VDISCARD];
2772 target->c_cc[TARGET_VWERASE] = host->c_cc[VWERASE];
2773 target->c_cc[TARGET_VLNEXT] = host->c_cc[VLNEXT];
2774 target->c_cc[TARGET_VEOL2] = host->c_cc[VEOL2];
2775}
2776
blueswir18e853dc2008-10-05 10:49:32 +00002777static const StructEntry struct_termios_def = {
bellard31e31b82003-02-18 22:55:36 +00002778 .convert = { host_to_target_termios, target_to_host_termios },
2779 .size = { sizeof(struct target_termios), sizeof(struct host_termios) },
2780 .align = { __alignof__(struct target_termios), __alignof__(struct host_termios) },
2781};
2782
bellard5286db72003-06-05 00:57:30 +00002783static bitmask_transtbl mmap_flags_tbl[] = {
2784 { TARGET_MAP_SHARED, TARGET_MAP_SHARED, MAP_SHARED, MAP_SHARED },
2785 { TARGET_MAP_PRIVATE, TARGET_MAP_PRIVATE, MAP_PRIVATE, MAP_PRIVATE },
2786 { TARGET_MAP_FIXED, TARGET_MAP_FIXED, MAP_FIXED, MAP_FIXED },
2787 { TARGET_MAP_ANONYMOUS, TARGET_MAP_ANONYMOUS, MAP_ANONYMOUS, MAP_ANONYMOUS },
2788 { TARGET_MAP_GROWSDOWN, TARGET_MAP_GROWSDOWN, MAP_GROWSDOWN, MAP_GROWSDOWN },
2789 { TARGET_MAP_DENYWRITE, TARGET_MAP_DENYWRITE, MAP_DENYWRITE, MAP_DENYWRITE },
2790 { TARGET_MAP_EXECUTABLE, TARGET_MAP_EXECUTABLE, MAP_EXECUTABLE, MAP_EXECUTABLE },
2791 { TARGET_MAP_LOCKED, TARGET_MAP_LOCKED, MAP_LOCKED, MAP_LOCKED },
2792 { 0, 0, 0, 0 }
2793};
2794
bellard2ab83ea2003-06-15 19:56:46 +00002795#if defined(TARGET_I386)
bellard6dbad632003-03-16 18:05:05 +00002796
2797/* NOTE: there is really one LDT for all the threads */
blueswir1b1d8e522008-10-26 13:43:07 +00002798static uint8_t *ldt_table;
bellard6dbad632003-03-16 18:05:05 +00002799
bellard03acab62007-11-11 14:57:14 +00002800static abi_long read_ldt(abi_ulong ptr, unsigned long bytecount)
bellard6dbad632003-03-16 18:05:05 +00002801{
2802 int size;
pbrook53a59602006-03-25 19:31:22 +00002803 void *p;
bellard6dbad632003-03-16 18:05:05 +00002804
2805 if (!ldt_table)
2806 return 0;
2807 size = TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE;
2808 if (size > bytecount)
2809 size = bytecount;
bellard579a97f2007-11-11 14:26:47 +00002810 p = lock_user(VERIFY_WRITE, ptr, size, 0);
2811 if (!p)
bellard03acab62007-11-11 14:57:14 +00002812 return -TARGET_EFAULT;
bellard579a97f2007-11-11 14:26:47 +00002813 /* ??? Should this by byteswapped? */
pbrook53a59602006-03-25 19:31:22 +00002814 memcpy(p, ldt_table, size);
2815 unlock_user(p, ptr, size);
bellard6dbad632003-03-16 18:05:05 +00002816 return size;
2817}
2818
2819/* XXX: add locking support */
bellard03acab62007-11-11 14:57:14 +00002820static abi_long write_ldt(CPUX86State *env,
2821 abi_ulong ptr, unsigned long bytecount, int oldmode)
bellard6dbad632003-03-16 18:05:05 +00002822{
2823 struct target_modify_ldt_ldt_s ldt_info;
pbrook53a59602006-03-25 19:31:22 +00002824 struct target_modify_ldt_ldt_s *target_ldt_info;
bellard6dbad632003-03-16 18:05:05 +00002825 int seg_32bit, contents, read_exec_only, limit_in_pages;
bellard8d18e892007-11-14 15:18:40 +00002826 int seg_not_present, useable, lm;
bellard6dbad632003-03-16 18:05:05 +00002827 uint32_t *lp, entry_1, entry_2;
2828
2829 if (bytecount != sizeof(ldt_info))
bellard03acab62007-11-11 14:57:14 +00002830 return -TARGET_EINVAL;
bellard579a97f2007-11-11 14:26:47 +00002831 if (!lock_user_struct(VERIFY_READ, target_ldt_info, ptr, 1))
bellard03acab62007-11-11 14:57:14 +00002832 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00002833 ldt_info.entry_number = tswap32(target_ldt_info->entry_number);
2834 ldt_info.base_addr = tswapl(target_ldt_info->base_addr);
2835 ldt_info.limit = tswap32(target_ldt_info->limit);
2836 ldt_info.flags = tswap32(target_ldt_info->flags);
2837 unlock_user_struct(target_ldt_info, ptr, 0);
ths3b46e622007-09-17 08:09:54 +00002838
bellard6dbad632003-03-16 18:05:05 +00002839 if (ldt_info.entry_number >= TARGET_LDT_ENTRIES)
bellard03acab62007-11-11 14:57:14 +00002840 return -TARGET_EINVAL;
bellard6dbad632003-03-16 18:05:05 +00002841 seg_32bit = ldt_info.flags & 1;
2842 contents = (ldt_info.flags >> 1) & 3;
2843 read_exec_only = (ldt_info.flags >> 3) & 1;
2844 limit_in_pages = (ldt_info.flags >> 4) & 1;
2845 seg_not_present = (ldt_info.flags >> 5) & 1;
2846 useable = (ldt_info.flags >> 6) & 1;
bellard8d18e892007-11-14 15:18:40 +00002847#ifdef TARGET_ABI32
2848 lm = 0;
2849#else
2850 lm = (ldt_info.flags >> 7) & 1;
2851#endif
bellard6dbad632003-03-16 18:05:05 +00002852 if (contents == 3) {
2853 if (oldmode)
bellard03acab62007-11-11 14:57:14 +00002854 return -TARGET_EINVAL;
bellard6dbad632003-03-16 18:05:05 +00002855 if (seg_not_present == 0)
bellard03acab62007-11-11 14:57:14 +00002856 return -TARGET_EINVAL;
bellard6dbad632003-03-16 18:05:05 +00002857 }
2858 /* allocate the LDT */
2859 if (!ldt_table) {
balroge4415702008-11-10 02:55:33 +00002860 env->ldt.base = target_mmap(0,
2861 TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE,
2862 PROT_READ|PROT_WRITE,
2863 MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
2864 if (env->ldt.base == -1)
bellard03acab62007-11-11 14:57:14 +00002865 return -TARGET_ENOMEM;
balroge4415702008-11-10 02:55:33 +00002866 memset(g2h(env->ldt.base), 0,
2867 TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE);
bellard6dbad632003-03-16 18:05:05 +00002868 env->ldt.limit = 0xffff;
balroge4415702008-11-10 02:55:33 +00002869 ldt_table = g2h(env->ldt.base);
bellard6dbad632003-03-16 18:05:05 +00002870 }
2871
2872 /* NOTE: same code as Linux kernel */
2873 /* Allow LDTs to be cleared by the user. */
2874 if (ldt_info.base_addr == 0 && ldt_info.limit == 0) {
2875 if (oldmode ||
2876 (contents == 0 &&
2877 read_exec_only == 1 &&
2878 seg_32bit == 0 &&
2879 limit_in_pages == 0 &&
2880 seg_not_present == 1 &&
2881 useable == 0 )) {
2882 entry_1 = 0;
2883 entry_2 = 0;
2884 goto install;
2885 }
2886 }
ths3b46e622007-09-17 08:09:54 +00002887
bellard6dbad632003-03-16 18:05:05 +00002888 entry_1 = ((ldt_info.base_addr & 0x0000ffff) << 16) |
2889 (ldt_info.limit & 0x0ffff);
2890 entry_2 = (ldt_info.base_addr & 0xff000000) |
2891 ((ldt_info.base_addr & 0x00ff0000) >> 16) |
2892 (ldt_info.limit & 0xf0000) |
2893 ((read_exec_only ^ 1) << 9) |
2894 (contents << 10) |
2895 ((seg_not_present ^ 1) << 15) |
2896 (seg_32bit << 22) |
2897 (limit_in_pages << 23) |
bellard8d18e892007-11-14 15:18:40 +00002898 (lm << 21) |
bellard6dbad632003-03-16 18:05:05 +00002899 0x7000;
2900 if (!oldmode)
2901 entry_2 |= (useable << 20);
bellard14ae3ba2003-05-27 23:25:06 +00002902
bellard6dbad632003-03-16 18:05:05 +00002903 /* Install the new entry ... */
2904install:
2905 lp = (uint32_t *)(ldt_table + (ldt_info.entry_number << 3));
2906 lp[0] = tswap32(entry_1);
2907 lp[1] = tswap32(entry_2);
2908 return 0;
2909}
2910
2911/* specific and weird i386 syscalls */
blueswir18fcd3692008-08-17 20:26:25 +00002912static abi_long do_modify_ldt(CPUX86State *env, int func, abi_ulong ptr,
2913 unsigned long bytecount)
bellard6dbad632003-03-16 18:05:05 +00002914{
bellard03acab62007-11-11 14:57:14 +00002915 abi_long ret;
ths3b46e622007-09-17 08:09:54 +00002916
bellard6dbad632003-03-16 18:05:05 +00002917 switch (func) {
2918 case 0:
2919 ret = read_ldt(ptr, bytecount);
2920 break;
2921 case 1:
2922 ret = write_ldt(env, ptr, bytecount, 1);
2923 break;
2924 case 0x11:
2925 ret = write_ldt(env, ptr, bytecount, 0);
2926 break;
bellard03acab62007-11-11 14:57:14 +00002927 default:
2928 ret = -TARGET_ENOSYS;
2929 break;
bellard6dbad632003-03-16 18:05:05 +00002930 }
2931 return ret;
2932}
bellard1b6b0292003-03-22 17:31:38 +00002933
blueswir14583f582008-08-24 10:35:55 +00002934#if defined(TARGET_I386) && defined(TARGET_ABI32)
blueswir18fcd3692008-08-17 20:26:25 +00002935static abi_long do_set_thread_area(CPUX86State *env, abi_ulong ptr)
bellard8d18e892007-11-14 15:18:40 +00002936{
2937 uint64_t *gdt_table = g2h(env->gdt.base);
2938 struct target_modify_ldt_ldt_s ldt_info;
2939 struct target_modify_ldt_ldt_s *target_ldt_info;
2940 int seg_32bit, contents, read_exec_only, limit_in_pages;
2941 int seg_not_present, useable, lm;
2942 uint32_t *lp, entry_1, entry_2;
2943 int i;
2944
2945 lock_user_struct(VERIFY_WRITE, target_ldt_info, ptr, 1);
2946 if (!target_ldt_info)
2947 return -TARGET_EFAULT;
2948 ldt_info.entry_number = tswap32(target_ldt_info->entry_number);
2949 ldt_info.base_addr = tswapl(target_ldt_info->base_addr);
2950 ldt_info.limit = tswap32(target_ldt_info->limit);
2951 ldt_info.flags = tswap32(target_ldt_info->flags);
2952 if (ldt_info.entry_number == -1) {
2953 for (i=TARGET_GDT_ENTRY_TLS_MIN; i<=TARGET_GDT_ENTRY_TLS_MAX; i++) {
2954 if (gdt_table[i] == 0) {
2955 ldt_info.entry_number = i;
2956 target_ldt_info->entry_number = tswap32(i);
2957 break;
2958 }
2959 }
2960 }
2961 unlock_user_struct(target_ldt_info, ptr, 1);
2962
2963 if (ldt_info.entry_number < TARGET_GDT_ENTRY_TLS_MIN ||
2964 ldt_info.entry_number > TARGET_GDT_ENTRY_TLS_MAX)
2965 return -TARGET_EINVAL;
2966 seg_32bit = ldt_info.flags & 1;
2967 contents = (ldt_info.flags >> 1) & 3;
2968 read_exec_only = (ldt_info.flags >> 3) & 1;
2969 limit_in_pages = (ldt_info.flags >> 4) & 1;
2970 seg_not_present = (ldt_info.flags >> 5) & 1;
2971 useable = (ldt_info.flags >> 6) & 1;
2972#ifdef TARGET_ABI32
2973 lm = 0;
2974#else
2975 lm = (ldt_info.flags >> 7) & 1;
2976#endif
2977
2978 if (contents == 3) {
2979 if (seg_not_present == 0)
2980 return -TARGET_EINVAL;
2981 }
2982
2983 /* NOTE: same code as Linux kernel */
2984 /* Allow LDTs to be cleared by the user. */
2985 if (ldt_info.base_addr == 0 && ldt_info.limit == 0) {
2986 if ((contents == 0 &&
2987 read_exec_only == 1 &&
2988 seg_32bit == 0 &&
2989 limit_in_pages == 0 &&
2990 seg_not_present == 1 &&
2991 useable == 0 )) {
2992 entry_1 = 0;
2993 entry_2 = 0;
2994 goto install;
2995 }
2996 }
2997
2998 entry_1 = ((ldt_info.base_addr & 0x0000ffff) << 16) |
2999 (ldt_info.limit & 0x0ffff);
3000 entry_2 = (ldt_info.base_addr & 0xff000000) |
3001 ((ldt_info.base_addr & 0x00ff0000) >> 16) |
3002 (ldt_info.limit & 0xf0000) |
3003 ((read_exec_only ^ 1) << 9) |
3004 (contents << 10) |
3005 ((seg_not_present ^ 1) << 15) |
3006 (seg_32bit << 22) |
3007 (limit_in_pages << 23) |
3008 (useable << 20) |
3009 (lm << 21) |
3010 0x7000;
3011
3012 /* Install the new entry ... */
3013install:
3014 lp = (uint32_t *)(gdt_table + ldt_info.entry_number);
3015 lp[0] = tswap32(entry_1);
3016 lp[1] = tswap32(entry_2);
3017 return 0;
3018}
3019
blueswir18fcd3692008-08-17 20:26:25 +00003020static abi_long do_get_thread_area(CPUX86State *env, abi_ulong ptr)
bellard8d18e892007-11-14 15:18:40 +00003021{
3022 struct target_modify_ldt_ldt_s *target_ldt_info;
3023 uint64_t *gdt_table = g2h(env->gdt.base);
3024 uint32_t base_addr, limit, flags;
3025 int seg_32bit, contents, read_exec_only, limit_in_pages, idx;
3026 int seg_not_present, useable, lm;
3027 uint32_t *lp, entry_1, entry_2;
3028
3029 lock_user_struct(VERIFY_WRITE, target_ldt_info, ptr, 1);
3030 if (!target_ldt_info)
3031 return -TARGET_EFAULT;
3032 idx = tswap32(target_ldt_info->entry_number);
3033 if (idx < TARGET_GDT_ENTRY_TLS_MIN ||
3034 idx > TARGET_GDT_ENTRY_TLS_MAX) {
3035 unlock_user_struct(target_ldt_info, ptr, 1);
3036 return -TARGET_EINVAL;
3037 }
3038 lp = (uint32_t *)(gdt_table + idx);
3039 entry_1 = tswap32(lp[0]);
3040 entry_2 = tswap32(lp[1]);
3041
3042 read_exec_only = ((entry_2 >> 9) & 1) ^ 1;
3043 contents = (entry_2 >> 10) & 3;
3044 seg_not_present = ((entry_2 >> 15) & 1) ^ 1;
3045 seg_32bit = (entry_2 >> 22) & 1;
3046 limit_in_pages = (entry_2 >> 23) & 1;
3047 useable = (entry_2 >> 20) & 1;
3048#ifdef TARGET_ABI32
3049 lm = 0;
3050#else
3051 lm = (entry_2 >> 21) & 1;
3052#endif
3053 flags = (seg_32bit << 0) | (contents << 1) |
3054 (read_exec_only << 3) | (limit_in_pages << 4) |
3055 (seg_not_present << 5) | (useable << 6) | (lm << 7);
3056 limit = (entry_1 & 0xffff) | (entry_2 & 0xf0000);
3057 base_addr = (entry_1 >> 16) |
3058 (entry_2 & 0xff000000) |
3059 ((entry_2 & 0xff) << 16);
3060 target_ldt_info->base_addr = tswapl(base_addr);
3061 target_ldt_info->limit = tswap32(limit);
3062 target_ldt_info->flags = tswap32(flags);
3063 unlock_user_struct(target_ldt_info, ptr, 1);
3064 return 0;
3065}
blueswir14583f582008-08-24 10:35:55 +00003066#endif /* TARGET_I386 && TARGET_ABI32 */
bellard8d18e892007-11-14 15:18:40 +00003067
bellardd2fd1af2007-11-14 18:08:56 +00003068#ifndef TARGET_ABI32
blueswir18fcd3692008-08-17 20:26:25 +00003069static abi_long do_arch_prctl(CPUX86State *env, int code, abi_ulong addr)
bellardd2fd1af2007-11-14 18:08:56 +00003070{
3071 abi_long ret;
3072 abi_ulong val;
3073 int idx;
3074
3075 switch(code) {
3076 case TARGET_ARCH_SET_GS:
3077 case TARGET_ARCH_SET_FS:
3078 if (code == TARGET_ARCH_SET_GS)
3079 idx = R_GS;
3080 else
3081 idx = R_FS;
3082 cpu_x86_load_seg(env, idx, 0);
3083 env->segs[idx].base = addr;
3084 break;
3085 case TARGET_ARCH_GET_GS:
3086 case TARGET_ARCH_GET_FS:
3087 if (code == TARGET_ARCH_GET_GS)
3088 idx = R_GS;
3089 else
3090 idx = R_FS;
3091 val = env->segs[idx].base;
3092 if (put_user(val, addr, abi_ulong))
3093 return -TARGET_EFAULT;
3094 break;
3095 default:
3096 ret = -TARGET_EINVAL;
3097 break;
3098 }
3099 return 0;
3100}
3101#endif
3102
bellard2ab83ea2003-06-15 19:56:46 +00003103#endif /* defined(TARGET_I386) */
3104
pbrookd865bab2008-06-07 22:12:17 +00003105#if defined(USE_NPTL)
3106
3107#define NEW_STACK_SIZE PTHREAD_STACK_MIN
3108
3109static pthread_mutex_t clone_lock = PTHREAD_MUTEX_INITIALIZER;
3110typedef struct {
3111 CPUState *env;
3112 pthread_mutex_t mutex;
3113 pthread_cond_t cond;
3114 pthread_t thread;
3115 uint32_t tid;
3116 abi_ulong child_tidptr;
3117 abi_ulong parent_tidptr;
3118 sigset_t sigmask;
3119} new_thread_info;
3120
3121static void *clone_func(void *arg)
3122{
3123 new_thread_info *info = arg;
3124 CPUState *env;
3125
3126 env = info->env;
3127 thread_env = env;
3128 info->tid = gettid();
3129 if (info->child_tidptr)
3130 put_user_u32(info->tid, info->child_tidptr);
3131 if (info->parent_tidptr)
3132 put_user_u32(info->tid, info->parent_tidptr);
3133 /* Enable signals. */
3134 sigprocmask(SIG_SETMASK, &info->sigmask, NULL);
3135 /* Signal to the parent that we're ready. */
3136 pthread_mutex_lock(&info->mutex);
3137 pthread_cond_broadcast(&info->cond);
3138 pthread_mutex_unlock(&info->mutex);
3139 /* Wait until the parent has finshed initializing the tls state. */
3140 pthread_mutex_lock(&clone_lock);
3141 pthread_mutex_unlock(&clone_lock);
3142 cpu_loop(env);
3143 /* never exits */
3144 return NULL;
3145}
3146#else
bellard1b6b0292003-03-22 17:31:38 +00003147/* this stack is the equivalent of the kernel stack associated with a
3148 thread/process */
3149#define NEW_STACK_SIZE 8192
3150
3151static int clone_func(void *arg)
3152{
bellard2ab83ea2003-06-15 19:56:46 +00003153 CPUState *env = arg;
bellard1b6b0292003-03-22 17:31:38 +00003154 cpu_loop(env);
3155 /* never exits */
3156 return 0;
3157}
pbrookd865bab2008-06-07 22:12:17 +00003158#endif
bellard1b6b0292003-03-22 17:31:38 +00003159
ths0da46a62007-10-20 20:23:07 +00003160/* do_fork() Must return host values and target errnos (unlike most
3161 do_*() functions). */
pbrookd865bab2008-06-07 22:12:17 +00003162static int do_fork(CPUState *env, unsigned int flags, abi_ulong newsp,
3163 abi_ulong parent_tidptr, target_ulong newtls,
3164 abi_ulong child_tidptr)
bellard1b6b0292003-03-22 17:31:38 +00003165{
3166 int ret;
bellard5cd43932003-03-29 16:54:36 +00003167 TaskState *ts;
bellard1b6b0292003-03-22 17:31:38 +00003168 uint8_t *new_stack;
bellard2ab83ea2003-06-15 19:56:46 +00003169 CPUState *new_env;
pbrookd865bab2008-06-07 22:12:17 +00003170#if defined(USE_NPTL)
3171 unsigned int nptl_flags;
3172 sigset_t sigmask;
3173#endif
ths3b46e622007-09-17 08:09:54 +00003174
balrog436d1242008-09-21 02:39:45 +00003175 /* Emulate vfork() with fork() */
3176 if (flags & CLONE_VFORK)
3177 flags &= ~(CLONE_VFORK | CLONE_VM);
3178
bellard1b6b0292003-03-22 17:31:38 +00003179 if (flags & CLONE_VM) {
pbrookbd0c5662008-05-29 14:34:11 +00003180#if defined(USE_NPTL)
pbrookd865bab2008-06-07 22:12:17 +00003181 new_thread_info info;
3182 pthread_attr_t attr;
pbrookbd0c5662008-05-29 14:34:11 +00003183#endif
pbrookc3a92832008-06-09 14:02:50 +00003184 ts = qemu_mallocz(sizeof(TaskState) + NEW_STACK_SIZE);
pbrook624f7972008-05-31 16:11:38 +00003185 init_task_state(ts);
bellard5cd43932003-03-29 16:54:36 +00003186 new_stack = ts->stack;
bellard1b6b0292003-03-22 17:31:38 +00003187 /* we create a new CPU instance. */
thsc5be9f02007-02-28 20:20:53 +00003188 new_env = cpu_copy(env);
pbrook6e68e072008-05-30 17:22:15 +00003189 /* Init regs that differ from the parent. */
3190 cpu_clone_regs(new_env, newsp);
bellard5cd43932003-03-29 16:54:36 +00003191 new_env->opaque = ts;
pbrookd865bab2008-06-07 22:12:17 +00003192#if defined(USE_NPTL)
3193 nptl_flags = flags;
3194 flags &= ~CLONE_NPTL_FLAGS2;
3195
pbrookc2764712009-03-07 15:24:59 +00003196 if (nptl_flags & CLONE_CHILD_CLEARTID) {
3197 ts->child_tidptr = child_tidptr;
3198 }
3199
pbrookd865bab2008-06-07 22:12:17 +00003200 if (nptl_flags & CLONE_SETTLS)
3201 cpu_set_tls (new_env, newtls);
3202
3203 /* Grab a mutex so that thread setup appears atomic. */
3204 pthread_mutex_lock(&clone_lock);
3205
3206 memset(&info, 0, sizeof(info));
3207 pthread_mutex_init(&info.mutex, NULL);
3208 pthread_mutex_lock(&info.mutex);
3209 pthread_cond_init(&info.cond, NULL);
3210 info.env = new_env;
3211 if (nptl_flags & CLONE_CHILD_SETTID)
3212 info.child_tidptr = child_tidptr;
3213 if (nptl_flags & CLONE_PARENT_SETTID)
3214 info.parent_tidptr = parent_tidptr;
3215
3216 ret = pthread_attr_init(&attr);
3217 ret = pthread_attr_setstack(&attr, new_stack, NEW_STACK_SIZE);
3218 /* It is not safe to deliver signals until the child has finished
3219 initializing, so temporarily block all signals. */
3220 sigfillset(&sigmask);
3221 sigprocmask(SIG_BLOCK, &sigmask, &info.sigmask);
3222
3223 ret = pthread_create(&info.thread, &attr, clone_func, &info);
pbrookc2764712009-03-07 15:24:59 +00003224 /* TODO: Free new CPU state if thread creation failed. */
pbrookd865bab2008-06-07 22:12:17 +00003225
3226 sigprocmask(SIG_SETMASK, &info.sigmask, NULL);
3227 pthread_attr_destroy(&attr);
3228 if (ret == 0) {
3229 /* Wait for the child to initialize. */
3230 pthread_cond_wait(&info.cond, &info.mutex);
3231 ret = info.tid;
3232 if (flags & CLONE_PARENT_SETTID)
3233 put_user_u32(ret, parent_tidptr);
3234 } else {
3235 ret = -1;
3236 }
3237 pthread_mutex_unlock(&info.mutex);
3238 pthread_cond_destroy(&info.cond);
3239 pthread_mutex_destroy(&info.mutex);
3240 pthread_mutex_unlock(&clone_lock);
3241#else
3242 if (flags & CLONE_NPTL_FLAGS2)
3243 return -EINVAL;
3244 /* This is probably going to die very quickly, but do it anyway. */
bellard27725c12003-04-29 21:08:18 +00003245#ifdef __ia64__
bellardfd4a43e2006-04-24 20:32:17 +00003246 ret = __clone2(clone_func, new_stack + NEW_STACK_SIZE, flags, new_env);
bellard27725c12003-04-29 21:08:18 +00003247#else
3248 ret = clone(clone_func, new_stack + NEW_STACK_SIZE, flags, new_env);
3249#endif
pbrookd865bab2008-06-07 22:12:17 +00003250#endif
bellard1b6b0292003-03-22 17:31:38 +00003251 } else {
3252 /* if no CLONE_VM, we consider it is a fork */
pbrookd865bab2008-06-07 22:12:17 +00003253 if ((flags & ~(CSIGNAL | CLONE_NPTL_FLAGS2)) != 0)
bellard1b6b0292003-03-22 17:31:38 +00003254 return -EINVAL;
pbrookd865bab2008-06-07 22:12:17 +00003255 fork_start();
bellard1b6b0292003-03-22 17:31:38 +00003256 ret = fork();
pbrookd865bab2008-06-07 22:12:17 +00003257 if (ret == 0) {
aurel322b1319c2008-12-18 22:44:04 +00003258 /* Child Process. */
pbrookd865bab2008-06-07 22:12:17 +00003259 cpu_clone_regs(env, newsp);
3260 fork_end(1);
aurel322b1319c2008-12-18 22:44:04 +00003261#if defined(USE_NPTL)
3262 /* There is a race condition here. The parent process could
3263 theoretically read the TID in the child process before the child
3264 tid is set. This would require using either ptrace
3265 (not implemented) or having *_tidptr to point at a shared memory
3266 mapping. We can't repeat the spinlock hack used above because
3267 the child process gets its own copy of the lock. */
pbrookd865bab2008-06-07 22:12:17 +00003268 if (flags & CLONE_CHILD_SETTID)
3269 put_user_u32(gettid(), child_tidptr);
3270 if (flags & CLONE_PARENT_SETTID)
3271 put_user_u32(gettid(), parent_tidptr);
3272 ts = (TaskState *)env->opaque;
3273 if (flags & CLONE_SETTLS)
3274 cpu_set_tls (env, newtls);
pbrookc2764712009-03-07 15:24:59 +00003275 if (flags & CLONE_CHILD_CLEARTID)
3276 ts->child_tidptr = child_tidptr;
aurel322b1319c2008-12-18 22:44:04 +00003277#endif
pbrookd865bab2008-06-07 22:12:17 +00003278 } else {
3279 fork_end(0);
3280 }
bellard1b6b0292003-03-22 17:31:38 +00003281 }
3282 return ret;
3283}
3284
blueswir1992f48a2007-10-14 16:27:31 +00003285static abi_long do_fcntl(int fd, int cmd, abi_ulong arg)
bellard7775e9e2003-05-14 22:46:48 +00003286{
3287 struct flock fl;
pbrook53a59602006-03-25 19:31:22 +00003288 struct target_flock *target_fl;
ths43f238d2007-01-05 20:55:49 +00003289 struct flock64 fl64;
3290 struct target_flock64 *target_fl64;
blueswir1992f48a2007-10-14 16:27:31 +00003291 abi_long ret;
pbrook53a59602006-03-25 19:31:22 +00003292
bellard7775e9e2003-05-14 22:46:48 +00003293 switch(cmd) {
3294 case TARGET_F_GETLK:
bellard579a97f2007-11-11 14:26:47 +00003295 if (!lock_user_struct(VERIFY_READ, target_fl, arg, 1))
3296 return -TARGET_EFAULT;
ths58134272007-03-31 18:59:32 +00003297 fl.l_type = tswap16(target_fl->l_type);
3298 fl.l_whence = tswap16(target_fl->l_whence);
3299 fl.l_start = tswapl(target_fl->l_start);
3300 fl.l_len = tswapl(target_fl->l_len);
3301 fl.l_pid = tswapl(target_fl->l_pid);
3302 unlock_user_struct(target_fl, arg, 0);
bellard9ee1fa22007-11-11 15:11:19 +00003303 ret = get_errno(fcntl(fd, cmd, &fl));
bellard7775e9e2003-05-14 22:46:48 +00003304 if (ret == 0) {
bellard579a97f2007-11-11 14:26:47 +00003305 if (!lock_user_struct(VERIFY_WRITE, target_fl, arg, 0))
3306 return -TARGET_EFAULT;
bellard7775e9e2003-05-14 22:46:48 +00003307 target_fl->l_type = tswap16(fl.l_type);
3308 target_fl->l_whence = tswap16(fl.l_whence);
3309 target_fl->l_start = tswapl(fl.l_start);
3310 target_fl->l_len = tswapl(fl.l_len);
3311 target_fl->l_pid = tswapl(fl.l_pid);
pbrook53a59602006-03-25 19:31:22 +00003312 unlock_user_struct(target_fl, arg, 1);
bellard7775e9e2003-05-14 22:46:48 +00003313 }
3314 break;
ths3b46e622007-09-17 08:09:54 +00003315
bellard7775e9e2003-05-14 22:46:48 +00003316 case TARGET_F_SETLK:
3317 case TARGET_F_SETLKW:
bellard579a97f2007-11-11 14:26:47 +00003318 if (!lock_user_struct(VERIFY_READ, target_fl, arg, 1))
3319 return -TARGET_EFAULT;
bellard7775e9e2003-05-14 22:46:48 +00003320 fl.l_type = tswap16(target_fl->l_type);
3321 fl.l_whence = tswap16(target_fl->l_whence);
3322 fl.l_start = tswapl(target_fl->l_start);
3323 fl.l_len = tswapl(target_fl->l_len);
3324 fl.l_pid = tswapl(target_fl->l_pid);
pbrook53a59602006-03-25 19:31:22 +00003325 unlock_user_struct(target_fl, arg, 0);
bellard9ee1fa22007-11-11 15:11:19 +00003326 ret = get_errno(fcntl(fd, cmd, &fl));
bellard7775e9e2003-05-14 22:46:48 +00003327 break;
ths3b46e622007-09-17 08:09:54 +00003328
bellard7775e9e2003-05-14 22:46:48 +00003329 case TARGET_F_GETLK64:
bellard579a97f2007-11-11 14:26:47 +00003330 if (!lock_user_struct(VERIFY_READ, target_fl64, arg, 1))
3331 return -TARGET_EFAULT;
ths58134272007-03-31 18:59:32 +00003332 fl64.l_type = tswap16(target_fl64->l_type) >> 1;
3333 fl64.l_whence = tswap16(target_fl64->l_whence);
3334 fl64.l_start = tswapl(target_fl64->l_start);
3335 fl64.l_len = tswapl(target_fl64->l_len);
3336 fl64.l_pid = tswap16(target_fl64->l_pid);
3337 unlock_user_struct(target_fl64, arg, 0);
bellard9ee1fa22007-11-11 15:11:19 +00003338 ret = get_errno(fcntl(fd, cmd >> 1, &fl64));
ths43f238d2007-01-05 20:55:49 +00003339 if (ret == 0) {
bellard579a97f2007-11-11 14:26:47 +00003340 if (!lock_user_struct(VERIFY_WRITE, target_fl64, arg, 0))
3341 return -TARGET_EFAULT;
ths43f238d2007-01-05 20:55:49 +00003342 target_fl64->l_type = tswap16(fl64.l_type) >> 1;
3343 target_fl64->l_whence = tswap16(fl64.l_whence);
3344 target_fl64->l_start = tswapl(fl64.l_start);
3345 target_fl64->l_len = tswapl(fl64.l_len);
3346 target_fl64->l_pid = tswapl(fl64.l_pid);
3347 unlock_user_struct(target_fl64, arg, 1);
3348 }
bellard9ee1fa22007-11-11 15:11:19 +00003349 break;
bellard7775e9e2003-05-14 22:46:48 +00003350 case TARGET_F_SETLK64:
3351 case TARGET_F_SETLKW64:
bellard579a97f2007-11-11 14:26:47 +00003352 if (!lock_user_struct(VERIFY_READ, target_fl64, arg, 1))
3353 return -TARGET_EFAULT;
ths43f238d2007-01-05 20:55:49 +00003354 fl64.l_type = tswap16(target_fl64->l_type) >> 1;
3355 fl64.l_whence = tswap16(target_fl64->l_whence);
3356 fl64.l_start = tswapl(target_fl64->l_start);
3357 fl64.l_len = tswapl(target_fl64->l_len);
3358 fl64.l_pid = tswap16(target_fl64->l_pid);
3359 unlock_user_struct(target_fl64, arg, 0);
bellard9ee1fa22007-11-11 15:11:19 +00003360 ret = get_errno(fcntl(fd, cmd >> 1, &fl64));
bellard7775e9e2003-05-14 22:46:48 +00003361 break;
3362
bellardffa65c32004-01-04 23:57:22 +00003363 case F_GETFL:
bellard9ee1fa22007-11-11 15:11:19 +00003364 ret = get_errno(fcntl(fd, cmd, arg));
3365 if (ret >= 0) {
3366 ret = host_to_target_bitmask(ret, fcntl_flags_tbl);
3367 }
bellardffa65c32004-01-04 23:57:22 +00003368 break;
3369
3370 case F_SETFL:
bellard9ee1fa22007-11-11 15:11:19 +00003371 ret = get_errno(fcntl(fd, cmd, target_to_host_bitmask(arg, fcntl_flags_tbl)));
bellardffa65c32004-01-04 23:57:22 +00003372 break;
3373
bellard7775e9e2003-05-14 22:46:48 +00003374 default:
bellard9ee1fa22007-11-11 15:11:19 +00003375 ret = get_errno(fcntl(fd, cmd, arg));
bellard7775e9e2003-05-14 22:46:48 +00003376 break;
3377 }
3378 return ret;
3379}
3380
bellard67867302003-11-23 17:05:30 +00003381#ifdef USE_UID16
bellard7775e9e2003-05-14 22:46:48 +00003382
bellard67867302003-11-23 17:05:30 +00003383static inline int high2lowuid(int uid)
3384{
3385 if (uid > 65535)
3386 return 65534;
3387 else
3388 return uid;
3389}
3390
3391static inline int high2lowgid(int gid)
3392{
3393 if (gid > 65535)
3394 return 65534;
3395 else
3396 return gid;
3397}
3398
3399static inline int low2highuid(int uid)
3400{
3401 if ((int16_t)uid == -1)
3402 return -1;
3403 else
3404 return uid;
3405}
3406
3407static inline int low2highgid(int gid)
3408{
3409 if ((int16_t)gid == -1)
3410 return -1;
3411 else
3412 return gid;
3413}
3414
3415#endif /* USE_UID16 */
bellard1b6b0292003-03-22 17:31:38 +00003416
bellard31e31b82003-02-18 22:55:36 +00003417void syscall_init(void)
3418{
bellard2ab83ea2003-06-15 19:56:46 +00003419 IOCTLEntry *ie;
3420 const argtype *arg_type;
3421 int size;
thsb92c47c2007-11-01 00:07:38 +00003422 int i;
bellard2ab83ea2003-06-15 19:56:46 +00003423
ths5fafdf22007-09-16 21:08:06 +00003424#define STRUCT(name, list...) thunk_register_struct(STRUCT_ ## name, #name, struct_ ## name ## _def);
3425#define STRUCT_SPECIAL(name) thunk_register_struct_direct(STRUCT_ ## name, #name, &struct_ ## name ## _def);
bellard31e31b82003-02-18 22:55:36 +00003426#include "syscall_types.h"
3427#undef STRUCT
3428#undef STRUCT_SPECIAL
bellard2ab83ea2003-06-15 19:56:46 +00003429
3430 /* we patch the ioctl size if necessary. We rely on the fact that
3431 no ioctl has all the bits at '1' in the size field */
3432 ie = ioctl_entries;
3433 while (ie->target_cmd != 0) {
3434 if (((ie->target_cmd >> TARGET_IOC_SIZESHIFT) & TARGET_IOC_SIZEMASK) ==
3435 TARGET_IOC_SIZEMASK) {
3436 arg_type = ie->arg_type;
3437 if (arg_type[0] != TYPE_PTR) {
ths5fafdf22007-09-16 21:08:06 +00003438 fprintf(stderr, "cannot patch size for ioctl 0x%x\n",
bellard2ab83ea2003-06-15 19:56:46 +00003439 ie->target_cmd);
3440 exit(1);
3441 }
3442 arg_type++;
3443 size = thunk_type_size(arg_type, 0);
ths5fafdf22007-09-16 21:08:06 +00003444 ie->target_cmd = (ie->target_cmd &
bellard2ab83ea2003-06-15 19:56:46 +00003445 ~(TARGET_IOC_SIZEMASK << TARGET_IOC_SIZESHIFT)) |
3446 (size << TARGET_IOC_SIZESHIFT);
3447 }
thsb92c47c2007-11-01 00:07:38 +00003448
3449 /* Build target_to_host_errno_table[] table from
3450 * host_to_target_errno_table[]. */
3451 for (i=0; i < ERRNO_TABLE_SIZE; i++)
3452 target_to_host_errno_table[host_to_target_errno_table[i]] = i;
3453
bellard2ab83ea2003-06-15 19:56:46 +00003454 /* automatic consistency check if same arch */
balrog872ea0c2008-09-21 02:31:19 +00003455#if (defined(__i386__) && defined(TARGET_I386) && defined(TARGET_ABI32)) || \
3456 (defined(__x86_64__) && defined(TARGET_X86_64))
3457 if (unlikely(ie->target_cmd != ie->host_cmd)) {
3458 fprintf(stderr, "ERROR: ioctl(%s): target=0x%x host=0x%x\n",
3459 ie->name, ie->target_cmd, ie->host_cmd);
bellard2ab83ea2003-06-15 19:56:46 +00003460 }
3461#endif
3462 ie++;
3463 }
bellard31e31b82003-02-18 22:55:36 +00003464}
bellardc573ff62004-01-04 15:51:36 +00003465
blueswir1992f48a2007-10-14 16:27:31 +00003466#if TARGET_ABI_BITS == 32
pbrookce4defa2006-02-09 16:49:55 +00003467static inline uint64_t target_offset64(uint32_t word0, uint32_t word1)
3468{
thsaf325d32008-06-10 15:29:15 +00003469#ifdef TARGET_WORDS_BIGENDIAN
pbrookce4defa2006-02-09 16:49:55 +00003470 return ((uint64_t)word0 << 32) | word1;
3471#else
3472 return ((uint64_t)word1 << 32) | word0;
3473#endif
3474}
blueswir1992f48a2007-10-14 16:27:31 +00003475#else /* TARGET_ABI_BITS == 32 */
j_mayer32407102007-09-26 23:01:49 +00003476static inline uint64_t target_offset64(uint64_t word0, uint64_t word1)
3477{
3478 return word0;
3479}
blueswir1992f48a2007-10-14 16:27:31 +00003480#endif /* TARGET_ABI_BITS != 32 */
pbrookce4defa2006-02-09 16:49:55 +00003481
3482#ifdef TARGET_NR_truncate64
blueswir1992f48a2007-10-14 16:27:31 +00003483static inline abi_long target_truncate64(void *cpu_env, const char *arg1,
3484 abi_long arg2,
3485 abi_long arg3,
3486 abi_long arg4)
pbrookce4defa2006-02-09 16:49:55 +00003487{
3488#ifdef TARGET_ARM
3489 if (((CPUARMState *)cpu_env)->eabi)
3490 {
3491 arg2 = arg3;
3492 arg3 = arg4;
3493 }
3494#endif
3495 return get_errno(truncate64(arg1, target_offset64(arg2, arg3)));
3496}
3497#endif
3498
3499#ifdef TARGET_NR_ftruncate64
blueswir1992f48a2007-10-14 16:27:31 +00003500static inline abi_long target_ftruncate64(void *cpu_env, abi_long arg1,
3501 abi_long arg2,
3502 abi_long arg3,
3503 abi_long arg4)
pbrookce4defa2006-02-09 16:49:55 +00003504{
3505#ifdef TARGET_ARM
3506 if (((CPUARMState *)cpu_env)->eabi)
3507 {
3508 arg2 = arg3;
3509 arg3 = arg4;
3510 }
3511#endif
3512 return get_errno(ftruncate64(arg1, target_offset64(arg2, arg3)));
3513}
3514#endif
3515
bellard579a97f2007-11-11 14:26:47 +00003516static inline abi_long target_to_host_timespec(struct timespec *host_ts,
3517 abi_ulong target_addr)
pbrook53a59602006-03-25 19:31:22 +00003518{
3519 struct target_timespec *target_ts;
3520
bellard579a97f2007-11-11 14:26:47 +00003521 if (!lock_user_struct(VERIFY_READ, target_ts, target_addr, 1))
3522 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00003523 host_ts->tv_sec = tswapl(target_ts->tv_sec);
3524 host_ts->tv_nsec = tswapl(target_ts->tv_nsec);
3525 unlock_user_struct(target_ts, target_addr, 0);
bellardb255bfa2008-05-10 21:51:02 +00003526 return 0;
pbrook53a59602006-03-25 19:31:22 +00003527}
3528
bellard579a97f2007-11-11 14:26:47 +00003529static inline abi_long host_to_target_timespec(abi_ulong target_addr,
3530 struct timespec *host_ts)
pbrook53a59602006-03-25 19:31:22 +00003531{
3532 struct target_timespec *target_ts;
3533
bellard579a97f2007-11-11 14:26:47 +00003534 if (!lock_user_struct(VERIFY_WRITE, target_ts, target_addr, 0))
3535 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00003536 target_ts->tv_sec = tswapl(host_ts->tv_sec);
3537 target_ts->tv_nsec = tswapl(host_ts->tv_nsec);
3538 unlock_user_struct(target_ts, target_addr, 1);
bellardb255bfa2008-05-10 21:51:02 +00003539 return 0;
pbrook53a59602006-03-25 19:31:22 +00003540}
3541
aurel329d33b762009-04-08 23:07:05 +00003542#if defined(TARGET_NR_stat64) || defined(TARGET_NR_newfstatat)
balrog6a24a772008-09-20 02:23:36 +00003543static inline abi_long host_to_target_stat64(void *cpu_env,
3544 abi_ulong target_addr,
3545 struct stat *host_st)
3546{
3547#ifdef TARGET_ARM
3548 if (((CPUARMState *)cpu_env)->eabi) {
3549 struct target_eabi_stat64 *target_st;
3550
3551 if (!lock_user_struct(VERIFY_WRITE, target_st, target_addr, 0))
3552 return -TARGET_EFAULT;
3553 memset(target_st, 0, sizeof(struct target_eabi_stat64));
3554 __put_user(host_st->st_dev, &target_st->st_dev);
3555 __put_user(host_st->st_ino, &target_st->st_ino);
3556#ifdef TARGET_STAT64_HAS_BROKEN_ST_INO
3557 __put_user(host_st->st_ino, &target_st->__st_ino);
3558#endif
3559 __put_user(host_st->st_mode, &target_st->st_mode);
3560 __put_user(host_st->st_nlink, &target_st->st_nlink);
3561 __put_user(host_st->st_uid, &target_st->st_uid);
3562 __put_user(host_st->st_gid, &target_st->st_gid);
3563 __put_user(host_st->st_rdev, &target_st->st_rdev);
3564 __put_user(host_st->st_size, &target_st->st_size);
3565 __put_user(host_st->st_blksize, &target_st->st_blksize);
3566 __put_user(host_st->st_blocks, &target_st->st_blocks);
3567 __put_user(host_st->st_atime, &target_st->target_st_atime);
3568 __put_user(host_st->st_mtime, &target_st->target_st_mtime);
3569 __put_user(host_st->st_ctime, &target_st->target_st_ctime);
3570 unlock_user_struct(target_st, target_addr, 1);
3571 } else
3572#endif
3573 {
aurel329d33b762009-04-08 23:07:05 +00003574#if TARGET_LONG_BITS == 64
3575 struct target_stat *target_st;
3576#else
balrog6a24a772008-09-20 02:23:36 +00003577 struct target_stat64 *target_st;
aurel329d33b762009-04-08 23:07:05 +00003578#endif
balrog6a24a772008-09-20 02:23:36 +00003579
3580 if (!lock_user_struct(VERIFY_WRITE, target_st, target_addr, 0))
3581 return -TARGET_EFAULT;
aurel329d33b762009-04-08 23:07:05 +00003582 memset(target_st, 0, sizeof(*target_st));
balrog6a24a772008-09-20 02:23:36 +00003583 __put_user(host_st->st_dev, &target_st->st_dev);
3584 __put_user(host_st->st_ino, &target_st->st_ino);
3585#ifdef TARGET_STAT64_HAS_BROKEN_ST_INO
3586 __put_user(host_st->st_ino, &target_st->__st_ino);
3587#endif
3588 __put_user(host_st->st_mode, &target_st->st_mode);
3589 __put_user(host_st->st_nlink, &target_st->st_nlink);
3590 __put_user(host_st->st_uid, &target_st->st_uid);
3591 __put_user(host_st->st_gid, &target_st->st_gid);
3592 __put_user(host_st->st_rdev, &target_st->st_rdev);
3593 /* XXX: better use of kernel struct */
3594 __put_user(host_st->st_size, &target_st->st_size);
3595 __put_user(host_st->st_blksize, &target_st->st_blksize);
3596 __put_user(host_st->st_blocks, &target_st->st_blocks);
3597 __put_user(host_st->st_atime, &target_st->target_st_atime);
3598 __put_user(host_st->st_mtime, &target_st->target_st_mtime);
3599 __put_user(host_st->st_ctime, &target_st->target_st_ctime);
3600 unlock_user_struct(target_st, target_addr, 1);
3601 }
3602
3603 return 0;
3604}
3605#endif
3606
pbrookbd0c5662008-05-29 14:34:11 +00003607#if defined(USE_NPTL)
3608/* ??? Using host futex calls even when target atomic operations
3609 are not really atomic probably breaks things. However implementing
3610 futexes locally would make futexes shared between multiple processes
3611 tricky. However they're probably useless because guest atomic
3612 operations won't work either. */
blueswir18fcd3692008-08-17 20:26:25 +00003613static int do_futex(target_ulong uaddr, int op, int val, target_ulong timeout,
3614 target_ulong uaddr2, int val3)
pbrookbd0c5662008-05-29 14:34:11 +00003615{
3616 struct timespec ts, *pts;
3617
3618 /* ??? We assume FUTEX_* constants are the same on both host
3619 and target. */
3620 switch (op) {
3621 case FUTEX_WAIT:
3622 if (timeout) {
3623 pts = &ts;
3624 target_to_host_timespec(pts, timeout);
3625 } else {
3626 pts = NULL;
3627 }
3628 return get_errno(sys_futex(g2h(uaddr), FUTEX_WAIT, tswap32(val),
3629 pts, NULL, 0));
3630 case FUTEX_WAKE:
3631 return get_errno(sys_futex(g2h(uaddr), FUTEX_WAKE, val, NULL, NULL, 0));
3632 case FUTEX_FD:
3633 return get_errno(sys_futex(g2h(uaddr), FUTEX_FD, val, NULL, NULL, 0));
3634 case FUTEX_REQUEUE:
3635 return get_errno(sys_futex(g2h(uaddr), FUTEX_REQUEUE, val,
3636 NULL, g2h(uaddr2), 0));
3637 case FUTEX_CMP_REQUEUE:
3638 return get_errno(sys_futex(g2h(uaddr), FUTEX_CMP_REQUEUE, val,
3639 NULL, g2h(uaddr2), tswap32(val3)));
3640 default:
3641 return -TARGET_ENOSYS;
3642 }
3643}
3644#endif
3645
pbrooka745ec62008-05-06 15:36:17 +00003646int get_osversion(void)
3647{
3648 static int osversion;
3649 struct new_utsname buf;
3650 const char *s;
3651 int i, n, tmp;
3652 if (osversion)
3653 return osversion;
3654 if (qemu_uname_release && *qemu_uname_release) {
3655 s = qemu_uname_release;
3656 } else {
3657 if (sys_uname(&buf))
3658 return 0;
3659 s = buf.release;
3660 }
3661 tmp = 0;
3662 for (i = 0; i < 3; i++) {
3663 n = 0;
3664 while (*s >= '0' && *s <= '9') {
3665 n *= 10;
3666 n += *s - '0';
3667 s++;
3668 }
3669 tmp = (tmp << 8) + n;
3670 if (*s == '.')
3671 s++;
3672 }
3673 osversion = tmp;
3674 return osversion;
3675}
3676
ths0da46a62007-10-20 20:23:07 +00003677/* do_syscall() should always have a single exit point at the end so
3678 that actions, such as logging of syscall results, can be performed.
3679 All errnos that do_syscall() returns must be -TARGET_<errcode>. */
blueswir1992f48a2007-10-14 16:27:31 +00003680abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
3681 abi_long arg2, abi_long arg3, abi_long arg4,
3682 abi_long arg5, abi_long arg6)
bellard31e31b82003-02-18 22:55:36 +00003683{
blueswir1992f48a2007-10-14 16:27:31 +00003684 abi_long ret;
bellard31e31b82003-02-18 22:55:36 +00003685 struct stat st;
bellard56c8f682005-11-28 22:28:41 +00003686 struct statfs stfs;
pbrook53a59602006-03-25 19:31:22 +00003687 void *p;
ths3b46e622007-09-17 08:09:54 +00003688
bellard72f03902003-02-18 23:33:18 +00003689#ifdef DEBUG
bellardc573ff62004-01-04 15:51:36 +00003690 gemu_log("syscall %d", num);
bellard72f03902003-02-18 23:33:18 +00003691#endif
thsb92c47c2007-11-01 00:07:38 +00003692 if(do_strace)
3693 print_syscall(num, arg1, arg2, arg3, arg4, arg5, arg6);
3694
bellard31e31b82003-02-18 22:55:36 +00003695 switch(num) {
3696 case TARGET_NR_exit:
pbrookc2764712009-03-07 15:24:59 +00003697#ifdef USE_NPTL
3698 /* In old applications this may be used to implement _exit(2).
3699 However in threaded applictions it is used for thread termination,
3700 and _exit_group is used for application termination.
3701 Do thread termination if we have more then one thread. */
3702 /* FIXME: This probably breaks if a signal arrives. We should probably
3703 be disabling signals. */
3704 if (first_cpu->next_cpu) {
3705 CPUState **lastp;
3706 CPUState *p;
3707
3708 cpu_list_lock();
3709 lastp = &first_cpu;
3710 p = first_cpu;
3711 while (p && p != (CPUState *)cpu_env) {
3712 lastp = &p->next_cpu;
3713 p = p->next_cpu;
3714 }
3715 /* If we didn't find the CPU for this thread then something is
3716 horribly wrong. */
3717 if (!p)
3718 abort();
3719 /* Remove the CPU from the list. */
3720 *lastp = p->next_cpu;
3721 cpu_list_unlock();
3722 TaskState *ts = ((CPUState *)cpu_env)->opaque;
3723 if (ts->child_tidptr) {
3724 put_user_u32(0, ts->child_tidptr);
3725 sys_futex(g2h(ts->child_tidptr), FUTEX_WAKE, INT_MAX,
3726 NULL, NULL, 0);
3727 }
3728 /* TODO: Free CPU state. */
3729 pthread_exit(NULL);
3730 }
3731#endif
bellard7d132992003-03-06 23:23:54 +00003732#ifdef HAVE_GPROF
3733 _mcleanup();
3734#endif
bellarde9009672005-04-26 20:42:36 +00003735 gdb_exit(cpu_env, arg1);
pbrookc2764712009-03-07 15:24:59 +00003736 _exit(arg1);
bellard31e31b82003-02-18 22:55:36 +00003737 ret = 0; /* avoid warning */
3738 break;
3739 case TARGET_NR_read:
aurel3238d840e2009-01-30 19:48:17 +00003740 if (arg3 == 0)
3741 ret = 0;
3742 else {
3743 if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
3744 goto efault;
3745 ret = get_errno(read(arg1, p, arg3));
3746 unlock_user(p, arg2, ret);
3747 }
bellard31e31b82003-02-18 22:55:36 +00003748 break;
3749 case TARGET_NR_write:
bellard579a97f2007-11-11 14:26:47 +00003750 if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
3751 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003752 ret = get_errno(write(arg1, p, arg3));
3753 unlock_user(p, arg2, 0);
bellard31e31b82003-02-18 22:55:36 +00003754 break;
3755 case TARGET_NR_open:
bellard2f619692007-11-16 10:46:05 +00003756 if (!(p = lock_user_string(arg1)))
3757 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003758 ret = get_errno(open(path(p),
bellardffa65c32004-01-04 23:57:22 +00003759 target_to_host_bitmask(arg2, fcntl_flags_tbl),
3760 arg3));
pbrook53a59602006-03-25 19:31:22 +00003761 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003762 break;
ths82424832007-09-24 09:21:55 +00003763#if defined(TARGET_NR_openat) && defined(__NR_openat)
3764 case TARGET_NR_openat:
bellard579a97f2007-11-11 14:26:47 +00003765 if (!(p = lock_user_string(arg2)))
3766 goto efault;
3767 ret = get_errno(sys_openat(arg1,
3768 path(p),
3769 target_to_host_bitmask(arg3, fcntl_flags_tbl),
3770 arg4));
3771 unlock_user(p, arg2, 0);
ths82424832007-09-24 09:21:55 +00003772 break;
3773#endif
bellard31e31b82003-02-18 22:55:36 +00003774 case TARGET_NR_close:
3775 ret = get_errno(close(arg1));
3776 break;
3777 case TARGET_NR_brk:
pbrook53a59602006-03-25 19:31:22 +00003778 ret = do_brk(arg1);
bellard31e31b82003-02-18 22:55:36 +00003779 break;
3780 case TARGET_NR_fork:
pbrookd865bab2008-06-07 22:12:17 +00003781 ret = get_errno(do_fork(cpu_env, SIGCHLD, 0, 0, 0, 0));
bellard31e31b82003-02-18 22:55:36 +00003782 break;
thse5febef2007-04-01 18:31:35 +00003783#ifdef TARGET_NR_waitpid
bellard31e31b82003-02-18 22:55:36 +00003784 case TARGET_NR_waitpid:
3785 {
pbrook53a59602006-03-25 19:31:22 +00003786 int status;
3787 ret = get_errno(waitpid(arg1, &status, arg3));
bellard2f619692007-11-16 10:46:05 +00003788 if (!is_error(ret) && arg2
3789 && put_user_s32(status, arg2))
3790 goto efault;
bellard31e31b82003-02-18 22:55:36 +00003791 }
3792 break;
thse5febef2007-04-01 18:31:35 +00003793#endif
pbrookf0cbb612008-05-30 18:20:05 +00003794#ifdef TARGET_NR_waitid
3795 case TARGET_NR_waitid:
3796 {
3797 siginfo_t info;
3798 info.si_pid = 0;
3799 ret = get_errno(waitid(arg1, arg2, &info, arg4));
3800 if (!is_error(ret) && arg3 && info.si_pid != 0) {
3801 if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_siginfo_t), 0)))
3802 goto efault;
3803 host_to_target_siginfo(p, &info);
3804 unlock_user(p, arg3, sizeof(target_siginfo_t));
3805 }
3806 }
3807 break;
3808#endif
j_mayer7a3148a2007-04-05 07:13:51 +00003809#ifdef TARGET_NR_creat /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00003810 case TARGET_NR_creat:
bellard579a97f2007-11-11 14:26:47 +00003811 if (!(p = lock_user_string(arg1)))
3812 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003813 ret = get_errno(creat(p, arg2));
3814 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003815 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003816#endif
bellard31e31b82003-02-18 22:55:36 +00003817 case TARGET_NR_link:
pbrook53a59602006-03-25 19:31:22 +00003818 {
3819 void * p2;
3820 p = lock_user_string(arg1);
3821 p2 = lock_user_string(arg2);
bellard579a97f2007-11-11 14:26:47 +00003822 if (!p || !p2)
3823 ret = -TARGET_EFAULT;
3824 else
3825 ret = get_errno(link(p, p2));
pbrook53a59602006-03-25 19:31:22 +00003826 unlock_user(p2, arg2, 0);
3827 unlock_user(p, arg1, 0);
3828 }
bellard31e31b82003-02-18 22:55:36 +00003829 break;
ths64f0ce42007-09-24 09:25:06 +00003830#if defined(TARGET_NR_linkat) && defined(__NR_linkat)
3831 case TARGET_NR_linkat:
ths64f0ce42007-09-24 09:25:06 +00003832 {
3833 void * p2 = NULL;
bellard579a97f2007-11-11 14:26:47 +00003834 if (!arg2 || !arg4)
3835 goto efault;
ths64f0ce42007-09-24 09:25:06 +00003836 p = lock_user_string(arg2);
3837 p2 = lock_user_string(arg4);
bellard579a97f2007-11-11 14:26:47 +00003838 if (!p || !p2)
ths0da46a62007-10-20 20:23:07 +00003839 ret = -TARGET_EFAULT;
ths64f0ce42007-09-24 09:25:06 +00003840 else
3841 ret = get_errno(sys_linkat(arg1, p, arg3, p2, arg5));
bellard579a97f2007-11-11 14:26:47 +00003842 unlock_user(p, arg2, 0);
3843 unlock_user(p2, arg4, 0);
ths64f0ce42007-09-24 09:25:06 +00003844 }
3845 break;
3846#endif
bellard31e31b82003-02-18 22:55:36 +00003847 case TARGET_NR_unlink:
bellard579a97f2007-11-11 14:26:47 +00003848 if (!(p = lock_user_string(arg1)))
3849 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003850 ret = get_errno(unlink(p));
3851 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003852 break;
ths8170f562007-09-24 09:24:11 +00003853#if defined(TARGET_NR_unlinkat) && defined(__NR_unlinkat)
3854 case TARGET_NR_unlinkat:
bellard579a97f2007-11-11 14:26:47 +00003855 if (!(p = lock_user_string(arg2)))
3856 goto efault;
3857 ret = get_errno(sys_unlinkat(arg1, p, arg3));
3858 unlock_user(p, arg2, 0);
balroged494d82007-12-11 23:23:52 +00003859 break;
balrogb7d35e62007-12-12 00:40:24 +00003860#endif
bellard31e31b82003-02-18 22:55:36 +00003861 case TARGET_NR_execve:
bellard7854b052003-03-29 17:22:23 +00003862 {
3863 char **argp, **envp;
bellardf7341ff2003-03-30 21:00:25 +00003864 int argc, envc;
blueswir1992f48a2007-10-14 16:27:31 +00003865 abi_ulong gp;
3866 abi_ulong guest_argp;
3867 abi_ulong guest_envp;
3868 abi_ulong addr;
bellard7854b052003-03-29 17:22:23 +00003869 char **q;
3870
bellardf7341ff2003-03-30 21:00:25 +00003871 argc = 0;
pbrook53a59602006-03-25 19:31:22 +00003872 guest_argp = arg2;
pbrookda94d262008-05-30 18:24:00 +00003873 for (gp = guest_argp; gp; gp += sizeof(abi_ulong)) {
ths03aa1972007-12-02 06:28:08 +00003874 if (get_user_ual(addr, gp))
bellard2f619692007-11-16 10:46:05 +00003875 goto efault;
ths03aa1972007-12-02 06:28:08 +00003876 if (!addr)
bellard2f619692007-11-16 10:46:05 +00003877 break;
bellard7854b052003-03-29 17:22:23 +00003878 argc++;
bellard2f619692007-11-16 10:46:05 +00003879 }
bellardf7341ff2003-03-30 21:00:25 +00003880 envc = 0;
pbrook53a59602006-03-25 19:31:22 +00003881 guest_envp = arg3;
pbrookda94d262008-05-30 18:24:00 +00003882 for (gp = guest_envp; gp; gp += sizeof(abi_ulong)) {
ths03aa1972007-12-02 06:28:08 +00003883 if (get_user_ual(addr, gp))
bellard2f619692007-11-16 10:46:05 +00003884 goto efault;
ths03aa1972007-12-02 06:28:08 +00003885 if (!addr)
bellard2f619692007-11-16 10:46:05 +00003886 break;
bellard7854b052003-03-29 17:22:23 +00003887 envc++;
bellard2f619692007-11-16 10:46:05 +00003888 }
bellard7854b052003-03-29 17:22:23 +00003889
bellardf7341ff2003-03-30 21:00:25 +00003890 argp = alloca((argc + 1) * sizeof(void *));
3891 envp = alloca((envc + 1) * sizeof(void *));
bellard7854b052003-03-29 17:22:23 +00003892
pbrookda94d262008-05-30 18:24:00 +00003893 for (gp = guest_argp, q = argp; gp;
blueswir1992f48a2007-10-14 16:27:31 +00003894 gp += sizeof(abi_ulong), q++) {
bellard2f619692007-11-16 10:46:05 +00003895 if (get_user_ual(addr, gp))
3896 goto execve_efault;
pbrook53a59602006-03-25 19:31:22 +00003897 if (!addr)
3898 break;
bellard2f619692007-11-16 10:46:05 +00003899 if (!(*q = lock_user_string(addr)))
3900 goto execve_efault;
pbrook53a59602006-03-25 19:31:22 +00003901 }
bellardf7341ff2003-03-30 21:00:25 +00003902 *q = NULL;
3903
pbrookda94d262008-05-30 18:24:00 +00003904 for (gp = guest_envp, q = envp; gp;
blueswir1992f48a2007-10-14 16:27:31 +00003905 gp += sizeof(abi_ulong), q++) {
bellard2f619692007-11-16 10:46:05 +00003906 if (get_user_ual(addr, gp))
3907 goto execve_efault;
pbrook53a59602006-03-25 19:31:22 +00003908 if (!addr)
3909 break;
bellard2f619692007-11-16 10:46:05 +00003910 if (!(*q = lock_user_string(addr)))
3911 goto execve_efault;
pbrook53a59602006-03-25 19:31:22 +00003912 }
bellardf7341ff2003-03-30 21:00:25 +00003913 *q = NULL;
bellard7854b052003-03-29 17:22:23 +00003914
bellard2f619692007-11-16 10:46:05 +00003915 if (!(p = lock_user_string(arg1)))
3916 goto execve_efault;
pbrook53a59602006-03-25 19:31:22 +00003917 ret = get_errno(execve(p, argp, envp));
3918 unlock_user(p, arg1, 0);
3919
bellard2f619692007-11-16 10:46:05 +00003920 goto execve_end;
3921
3922 execve_efault:
3923 ret = -TARGET_EFAULT;
3924
3925 execve_end:
pbrook53a59602006-03-25 19:31:22 +00003926 for (gp = guest_argp, q = argp; *q;
blueswir1992f48a2007-10-14 16:27:31 +00003927 gp += sizeof(abi_ulong), q++) {
bellard2f619692007-11-16 10:46:05 +00003928 if (get_user_ual(addr, gp)
3929 || !addr)
3930 break;
pbrook53a59602006-03-25 19:31:22 +00003931 unlock_user(*q, addr, 0);
3932 }
3933 for (gp = guest_envp, q = envp; *q;
blueswir1992f48a2007-10-14 16:27:31 +00003934 gp += sizeof(abi_ulong), q++) {
bellard2f619692007-11-16 10:46:05 +00003935 if (get_user_ual(addr, gp)
3936 || !addr)
3937 break;
pbrook53a59602006-03-25 19:31:22 +00003938 unlock_user(*q, addr, 0);
3939 }
bellard7854b052003-03-29 17:22:23 +00003940 }
bellard31e31b82003-02-18 22:55:36 +00003941 break;
3942 case TARGET_NR_chdir:
bellard579a97f2007-11-11 14:26:47 +00003943 if (!(p = lock_user_string(arg1)))
3944 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003945 ret = get_errno(chdir(p));
3946 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003947 break;
bellarda315a142005-01-30 22:59:18 +00003948#ifdef TARGET_NR_time
bellard31e31b82003-02-18 22:55:36 +00003949 case TARGET_NR_time:
3950 {
pbrook53a59602006-03-25 19:31:22 +00003951 time_t host_time;
3952 ret = get_errno(time(&host_time));
bellard2f619692007-11-16 10:46:05 +00003953 if (!is_error(ret)
3954 && arg1
3955 && put_user_sal(host_time, arg1))
3956 goto efault;
bellard31e31b82003-02-18 22:55:36 +00003957 }
3958 break;
bellarda315a142005-01-30 22:59:18 +00003959#endif
bellard31e31b82003-02-18 22:55:36 +00003960 case TARGET_NR_mknod:
bellard579a97f2007-11-11 14:26:47 +00003961 if (!(p = lock_user_string(arg1)))
3962 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003963 ret = get_errno(mknod(p, arg2, arg3));
3964 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003965 break;
ths75ac37a2007-09-24 09:23:05 +00003966#if defined(TARGET_NR_mknodat) && defined(__NR_mknodat)
3967 case TARGET_NR_mknodat:
bellard579a97f2007-11-11 14:26:47 +00003968 if (!(p = lock_user_string(arg2)))
3969 goto efault;
3970 ret = get_errno(sys_mknodat(arg1, p, arg3, arg4));
3971 unlock_user(p, arg2, 0);
ths75ac37a2007-09-24 09:23:05 +00003972 break;
3973#endif
bellard31e31b82003-02-18 22:55:36 +00003974 case TARGET_NR_chmod:
bellard579a97f2007-11-11 14:26:47 +00003975 if (!(p = lock_user_string(arg1)))
3976 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003977 ret = get_errno(chmod(p, arg2));
3978 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003979 break;
bellardebc05482003-09-30 21:08:41 +00003980#ifdef TARGET_NR_break
bellard31e31b82003-02-18 22:55:36 +00003981 case TARGET_NR_break:
3982 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00003983#endif
3984#ifdef TARGET_NR_oldstat
bellard31e31b82003-02-18 22:55:36 +00003985 case TARGET_NR_oldstat:
3986 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00003987#endif
bellard31e31b82003-02-18 22:55:36 +00003988 case TARGET_NR_lseek:
3989 ret = get_errno(lseek(arg1, arg2, arg3));
3990 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003991#ifdef TARGET_NR_getxpid
3992 case TARGET_NR_getxpid:
3993#else
bellard31e31b82003-02-18 22:55:36 +00003994 case TARGET_NR_getpid:
j_mayer7a3148a2007-04-05 07:13:51 +00003995#endif
bellard31e31b82003-02-18 22:55:36 +00003996 ret = get_errno(getpid());
3997 break;
3998 case TARGET_NR_mount:
ths80265912007-02-17 22:25:41 +00003999 {
4000 /* need to look at the data field */
4001 void *p2, *p3;
4002 p = lock_user_string(arg1);
4003 p2 = lock_user_string(arg2);
4004 p3 = lock_user_string(arg3);
bellard579a97f2007-11-11 14:26:47 +00004005 if (!p || !p2 || !p3)
4006 ret = -TARGET_EFAULT;
4007 else
4008 /* FIXME - arg5 should be locked, but it isn't clear how to
4009 * do that since it's not guaranteed to be a NULL-terminated
4010 * string.
4011 */
4012 ret = get_errno(mount(p, p2, p3, (unsigned long)arg4, g2h(arg5)));
4013 unlock_user(p, arg1, 0);
4014 unlock_user(p2, arg2, 0);
4015 unlock_user(p3, arg3, 0);
ths80265912007-02-17 22:25:41 +00004016 break;
4017 }
thse5febef2007-04-01 18:31:35 +00004018#ifdef TARGET_NR_umount
bellard31e31b82003-02-18 22:55:36 +00004019 case TARGET_NR_umount:
bellard579a97f2007-11-11 14:26:47 +00004020 if (!(p = lock_user_string(arg1)))
4021 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004022 ret = get_errno(umount(p));
4023 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004024 break;
thse5febef2007-04-01 18:31:35 +00004025#endif
j_mayer7a3148a2007-04-05 07:13:51 +00004026#ifdef TARGET_NR_stime /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00004027 case TARGET_NR_stime:
4028 {
pbrook53a59602006-03-25 19:31:22 +00004029 time_t host_time;
bellard2f619692007-11-16 10:46:05 +00004030 if (get_user_sal(host_time, arg1))
4031 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004032 ret = get_errno(stime(&host_time));
bellard31e31b82003-02-18 22:55:36 +00004033 }
4034 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004035#endif
bellard31e31b82003-02-18 22:55:36 +00004036 case TARGET_NR_ptrace:
4037 goto unimplemented;
j_mayer7a3148a2007-04-05 07:13:51 +00004038#ifdef TARGET_NR_alarm /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00004039 case TARGET_NR_alarm:
4040 ret = alarm(arg1);
4041 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004042#endif
bellardebc05482003-09-30 21:08:41 +00004043#ifdef TARGET_NR_oldfstat
bellard31e31b82003-02-18 22:55:36 +00004044 case TARGET_NR_oldfstat:
4045 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004046#endif
j_mayer7a3148a2007-04-05 07:13:51 +00004047#ifdef TARGET_NR_pause /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00004048 case TARGET_NR_pause:
4049 ret = get_errno(pause());
4050 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004051#endif
thse5febef2007-04-01 18:31:35 +00004052#ifdef TARGET_NR_utime
bellard31e31b82003-02-18 22:55:36 +00004053 case TARGET_NR_utime:
bellardebc05482003-09-30 21:08:41 +00004054 {
pbrook53a59602006-03-25 19:31:22 +00004055 struct utimbuf tbuf, *host_tbuf;
4056 struct target_utimbuf *target_tbuf;
4057 if (arg2) {
bellard579a97f2007-11-11 14:26:47 +00004058 if (!lock_user_struct(VERIFY_READ, target_tbuf, arg2, 1))
4059 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004060 tbuf.actime = tswapl(target_tbuf->actime);
4061 tbuf.modtime = tswapl(target_tbuf->modtime);
4062 unlock_user_struct(target_tbuf, arg2, 0);
4063 host_tbuf = &tbuf;
bellardf72e8ff2004-05-03 19:23:07 +00004064 } else {
pbrook53a59602006-03-25 19:31:22 +00004065 host_tbuf = NULL;
bellardf72e8ff2004-05-03 19:23:07 +00004066 }
bellard579a97f2007-11-11 14:26:47 +00004067 if (!(p = lock_user_string(arg1)))
4068 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004069 ret = get_errno(utime(p, host_tbuf));
4070 unlock_user(p, arg1, 0);
bellardebc05482003-09-30 21:08:41 +00004071 }
4072 break;
thse5febef2007-04-01 18:31:35 +00004073#endif
bellard978a66f2004-12-06 22:58:05 +00004074 case TARGET_NR_utimes:
4075 {
bellard978a66f2004-12-06 22:58:05 +00004076 struct timeval *tvp, tv[2];
pbrook53a59602006-03-25 19:31:22 +00004077 if (arg2) {
ths788f5ec2007-12-09 02:37:05 +00004078 if (copy_from_user_timeval(&tv[0], arg2)
4079 || copy_from_user_timeval(&tv[1],
4080 arg2 + sizeof(struct target_timeval)))
4081 goto efault;
bellard978a66f2004-12-06 22:58:05 +00004082 tvp = tv;
4083 } else {
4084 tvp = NULL;
4085 }
bellard579a97f2007-11-11 14:26:47 +00004086 if (!(p = lock_user_string(arg1)))
4087 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004088 ret = get_errno(utimes(p, tvp));
4089 unlock_user(p, arg1, 0);
bellard978a66f2004-12-06 22:58:05 +00004090 }
4091 break;
balrogac8a6552008-09-20 02:25:39 +00004092#if defined(TARGET_NR_futimesat) && defined(__NR_futimesat)
4093 case TARGET_NR_futimesat:
4094 {
4095 struct timeval *tvp, tv[2];
4096 if (arg3) {
4097 if (copy_from_user_timeval(&tv[0], arg3)
4098 || copy_from_user_timeval(&tv[1],
4099 arg3 + sizeof(struct target_timeval)))
4100 goto efault;
4101 tvp = tv;
4102 } else {
4103 tvp = NULL;
4104 }
4105 if (!(p = lock_user_string(arg2)))
4106 goto efault;
4107 ret = get_errno(sys_futimesat(arg1, path(p), tvp));
4108 unlock_user(p, arg2, 0);
4109 }
4110 break;
4111#endif
bellardebc05482003-09-30 21:08:41 +00004112#ifdef TARGET_NR_stty
bellard31e31b82003-02-18 22:55:36 +00004113 case TARGET_NR_stty:
4114 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004115#endif
4116#ifdef TARGET_NR_gtty
bellard31e31b82003-02-18 22:55:36 +00004117 case TARGET_NR_gtty:
4118 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004119#endif
bellard31e31b82003-02-18 22:55:36 +00004120 case TARGET_NR_access:
bellard579a97f2007-11-11 14:26:47 +00004121 if (!(p = lock_user_string(arg1)))
4122 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004123 ret = get_errno(access(p, arg2));
4124 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004125 break;
ths92a34c12007-09-24 09:27:49 +00004126#if defined(TARGET_NR_faccessat) && defined(__NR_faccessat)
4127 case TARGET_NR_faccessat:
bellard579a97f2007-11-11 14:26:47 +00004128 if (!(p = lock_user_string(arg2)))
4129 goto efault;
4130 ret = get_errno(sys_faccessat(arg1, p, arg3, arg4));
4131 unlock_user(p, arg2, 0);
ths92a34c12007-09-24 09:27:49 +00004132 break;
4133#endif
j_mayer7a3148a2007-04-05 07:13:51 +00004134#ifdef TARGET_NR_nice /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00004135 case TARGET_NR_nice:
4136 ret = get_errno(nice(arg1));
4137 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004138#endif
bellardebc05482003-09-30 21:08:41 +00004139#ifdef TARGET_NR_ftime
bellard31e31b82003-02-18 22:55:36 +00004140 case TARGET_NR_ftime:
4141 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004142#endif
bellard31e31b82003-02-18 22:55:36 +00004143 case TARGET_NR_sync:
bellard04369ff2003-03-20 22:33:23 +00004144 sync();
4145 ret = 0;
bellard31e31b82003-02-18 22:55:36 +00004146 break;
4147 case TARGET_NR_kill:
pbrook4cb05962008-05-30 18:05:19 +00004148 ret = get_errno(kill(arg1, target_to_host_signal(arg2)));
bellard31e31b82003-02-18 22:55:36 +00004149 break;
4150 case TARGET_NR_rename:
pbrook53a59602006-03-25 19:31:22 +00004151 {
4152 void *p2;
4153 p = lock_user_string(arg1);
4154 p2 = lock_user_string(arg2);
bellard579a97f2007-11-11 14:26:47 +00004155 if (!p || !p2)
4156 ret = -TARGET_EFAULT;
4157 else
4158 ret = get_errno(rename(p, p2));
pbrook53a59602006-03-25 19:31:22 +00004159 unlock_user(p2, arg2, 0);
4160 unlock_user(p, arg1, 0);
4161 }
bellard31e31b82003-02-18 22:55:36 +00004162 break;
ths722183f2007-09-24 09:24:37 +00004163#if defined(TARGET_NR_renameat) && defined(__NR_renameat)
4164 case TARGET_NR_renameat:
ths722183f2007-09-24 09:24:37 +00004165 {
bellard579a97f2007-11-11 14:26:47 +00004166 void *p2;
ths722183f2007-09-24 09:24:37 +00004167 p = lock_user_string(arg2);
4168 p2 = lock_user_string(arg4);
bellard579a97f2007-11-11 14:26:47 +00004169 if (!p || !p2)
ths0da46a62007-10-20 20:23:07 +00004170 ret = -TARGET_EFAULT;
ths722183f2007-09-24 09:24:37 +00004171 else
4172 ret = get_errno(sys_renameat(arg1, p, arg3, p2));
bellard579a97f2007-11-11 14:26:47 +00004173 unlock_user(p2, arg4, 0);
4174 unlock_user(p, arg2, 0);
ths722183f2007-09-24 09:24:37 +00004175 }
4176 break;
4177#endif
bellard31e31b82003-02-18 22:55:36 +00004178 case TARGET_NR_mkdir:
bellard579a97f2007-11-11 14:26:47 +00004179 if (!(p = lock_user_string(arg1)))
4180 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004181 ret = get_errno(mkdir(p, arg2));
4182 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004183 break;
ths4472ad02007-09-24 09:22:32 +00004184#if defined(TARGET_NR_mkdirat) && defined(__NR_mkdirat)
4185 case TARGET_NR_mkdirat:
bellard579a97f2007-11-11 14:26:47 +00004186 if (!(p = lock_user_string(arg2)))
4187 goto efault;
4188 ret = get_errno(sys_mkdirat(arg1, p, arg3));
4189 unlock_user(p, arg2, 0);
ths4472ad02007-09-24 09:22:32 +00004190 break;
4191#endif
bellard31e31b82003-02-18 22:55:36 +00004192 case TARGET_NR_rmdir:
bellard579a97f2007-11-11 14:26:47 +00004193 if (!(p = lock_user_string(arg1)))
4194 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004195 ret = get_errno(rmdir(p));
4196 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004197 break;
4198 case TARGET_NR_dup:
4199 ret = get_errno(dup(arg1));
4200 break;
4201 case TARGET_NR_pipe:
4202 {
pbrook53a59602006-03-25 19:31:22 +00004203 int host_pipe[2];
4204 ret = get_errno(pipe(host_pipe));
bellard31e31b82003-02-18 22:55:36 +00004205 if (!is_error(ret)) {
thsc12ab052007-06-01 11:50:36 +00004206#if defined(TARGET_MIPS)
thsead93602007-09-06 00:18:15 +00004207 CPUMIPSState *env = (CPUMIPSState*)cpu_env;
thsb5dc7732008-06-27 10:02:35 +00004208 env->active_tc.gpr[3] = host_pipe[1];
thsc12ab052007-06-01 11:50:36 +00004209 ret = host_pipe[0];
aurel32b5eff352008-03-11 23:30:22 +00004210#elif defined(TARGET_SH4)
4211 ((CPUSH4State*)cpu_env)->gregs[1] = host_pipe[1];
4212 ret = host_pipe[0];
thsc12ab052007-06-01 11:50:36 +00004213#else
bellard2f619692007-11-16 10:46:05 +00004214 if (put_user_s32(host_pipe[0], arg1)
4215 || put_user_s32(host_pipe[1], arg1 + sizeof(host_pipe[0])))
4216 goto efault;
thsc12ab052007-06-01 11:50:36 +00004217#endif
bellard31e31b82003-02-18 22:55:36 +00004218 }
4219 }
4220 break;
4221 case TARGET_NR_times:
bellard32f36bc2003-03-30 21:29:48 +00004222 {
pbrook53a59602006-03-25 19:31:22 +00004223 struct target_tms *tmsp;
bellard32f36bc2003-03-30 21:29:48 +00004224 struct tms tms;
4225 ret = get_errno(times(&tms));
pbrook53a59602006-03-25 19:31:22 +00004226 if (arg1) {
bellard579a97f2007-11-11 14:26:47 +00004227 tmsp = lock_user(VERIFY_WRITE, arg1, sizeof(struct target_tms), 0);
4228 if (!tmsp)
4229 goto efault;
bellardc596ed12003-07-13 17:32:31 +00004230 tmsp->tms_utime = tswapl(host_to_target_clock_t(tms.tms_utime));
4231 tmsp->tms_stime = tswapl(host_to_target_clock_t(tms.tms_stime));
4232 tmsp->tms_cutime = tswapl(host_to_target_clock_t(tms.tms_cutime));
4233 tmsp->tms_cstime = tswapl(host_to_target_clock_t(tms.tms_cstime));
bellard32f36bc2003-03-30 21:29:48 +00004234 }
bellardc596ed12003-07-13 17:32:31 +00004235 if (!is_error(ret))
4236 ret = host_to_target_clock_t(ret);
bellard32f36bc2003-03-30 21:29:48 +00004237 }
4238 break;
bellardebc05482003-09-30 21:08:41 +00004239#ifdef TARGET_NR_prof
bellard31e31b82003-02-18 22:55:36 +00004240 case TARGET_NR_prof:
4241 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004242#endif
thse5febef2007-04-01 18:31:35 +00004243#ifdef TARGET_NR_signal
bellard31e31b82003-02-18 22:55:36 +00004244 case TARGET_NR_signal:
4245 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00004246#endif
bellard31e31b82003-02-18 22:55:36 +00004247 case TARGET_NR_acct:
aurel3238d840e2009-01-30 19:48:17 +00004248 if (arg1 == 0) {
4249 ret = get_errno(acct(NULL));
4250 } else {
4251 if (!(p = lock_user_string(arg1)))
4252 goto efault;
4253 ret = get_errno(acct(path(p)));
4254 unlock_user(p, arg1, 0);
4255 }
pbrook24836682006-04-16 14:14:53 +00004256 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004257#ifdef TARGET_NR_umount2 /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00004258 case TARGET_NR_umount2:
bellard579a97f2007-11-11 14:26:47 +00004259 if (!(p = lock_user_string(arg1)))
4260 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004261 ret = get_errno(umount2(p, arg2));
4262 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004263 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004264#endif
bellardebc05482003-09-30 21:08:41 +00004265#ifdef TARGET_NR_lock
bellard31e31b82003-02-18 22:55:36 +00004266 case TARGET_NR_lock:
4267 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004268#endif
bellard31e31b82003-02-18 22:55:36 +00004269 case TARGET_NR_ioctl:
4270 ret = do_ioctl(arg1, arg2, arg3);
4271 break;
4272 case TARGET_NR_fcntl:
bellard9ee1fa22007-11-11 15:11:19 +00004273 ret = do_fcntl(arg1, arg2, arg3);
bellard31e31b82003-02-18 22:55:36 +00004274 break;
bellardebc05482003-09-30 21:08:41 +00004275#ifdef TARGET_NR_mpx
bellard31e31b82003-02-18 22:55:36 +00004276 case TARGET_NR_mpx:
4277 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004278#endif
bellard31e31b82003-02-18 22:55:36 +00004279 case TARGET_NR_setpgid:
4280 ret = get_errno(setpgid(arg1, arg2));
4281 break;
bellardebc05482003-09-30 21:08:41 +00004282#ifdef TARGET_NR_ulimit
bellard31e31b82003-02-18 22:55:36 +00004283 case TARGET_NR_ulimit:
4284 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004285#endif
4286#ifdef TARGET_NR_oldolduname
bellard31e31b82003-02-18 22:55:36 +00004287 case TARGET_NR_oldolduname:
4288 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004289#endif
bellard31e31b82003-02-18 22:55:36 +00004290 case TARGET_NR_umask:
4291 ret = get_errno(umask(arg1));
4292 break;
4293 case TARGET_NR_chroot:
bellard579a97f2007-11-11 14:26:47 +00004294 if (!(p = lock_user_string(arg1)))
4295 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004296 ret = get_errno(chroot(p));
4297 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004298 break;
4299 case TARGET_NR_ustat:
4300 goto unimplemented;
4301 case TARGET_NR_dup2:
4302 ret = get_errno(dup2(arg1, arg2));
4303 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004304#ifdef TARGET_NR_getppid /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00004305 case TARGET_NR_getppid:
4306 ret = get_errno(getppid());
4307 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004308#endif
bellard31e31b82003-02-18 22:55:36 +00004309 case TARGET_NR_getpgrp:
4310 ret = get_errno(getpgrp());
4311 break;
4312 case TARGET_NR_setsid:
4313 ret = get_errno(setsid());
4314 break;
thse5febef2007-04-01 18:31:35 +00004315#ifdef TARGET_NR_sigaction
bellard31e31b82003-02-18 22:55:36 +00004316 case TARGET_NR_sigaction:
bellard31e31b82003-02-18 22:55:36 +00004317 {
ths388bb212007-05-13 13:58:00 +00004318#if !defined(TARGET_MIPS)
pbrook53a59602006-03-25 19:31:22 +00004319 struct target_old_sigaction *old_act;
bellard66fb9762003-03-23 01:06:05 +00004320 struct target_sigaction act, oact, *pact;
pbrook53a59602006-03-25 19:31:22 +00004321 if (arg2) {
bellard579a97f2007-11-11 14:26:47 +00004322 if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1))
4323 goto efault;
bellard66fb9762003-03-23 01:06:05 +00004324 act._sa_handler = old_act->_sa_handler;
4325 target_siginitset(&act.sa_mask, old_act->sa_mask);
4326 act.sa_flags = old_act->sa_flags;
4327 act.sa_restorer = old_act->sa_restorer;
pbrook53a59602006-03-25 19:31:22 +00004328 unlock_user_struct(old_act, arg2, 0);
bellard66fb9762003-03-23 01:06:05 +00004329 pact = &act;
4330 } else {
4331 pact = NULL;
4332 }
4333 ret = get_errno(do_sigaction(arg1, pact, &oact));
pbrook53a59602006-03-25 19:31:22 +00004334 if (!is_error(ret) && arg3) {
bellard579a97f2007-11-11 14:26:47 +00004335 if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0))
4336 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004337 old_act->_sa_handler = oact._sa_handler;
4338 old_act->sa_mask = oact.sa_mask.sig[0];
4339 old_act->sa_flags = oact.sa_flags;
4340 old_act->sa_restorer = oact.sa_restorer;
4341 unlock_user_struct(old_act, arg3, 1);
bellard66fb9762003-03-23 01:06:05 +00004342 }
ths388bb212007-05-13 13:58:00 +00004343#else
bellard106ec872006-06-27 21:08:10 +00004344 struct target_sigaction act, oact, *pact, *old_act;
4345
4346 if (arg2) {
bellard579a97f2007-11-11 14:26:47 +00004347 if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1))
4348 goto efault;
bellard106ec872006-06-27 21:08:10 +00004349 act._sa_handler = old_act->_sa_handler;
4350 target_siginitset(&act.sa_mask, old_act->sa_mask.sig[0]);
4351 act.sa_flags = old_act->sa_flags;
4352 unlock_user_struct(old_act, arg2, 0);
4353 pact = &act;
4354 } else {
4355 pact = NULL;
4356 }
4357
4358 ret = get_errno(do_sigaction(arg1, pact, &oact));
4359
4360 if (!is_error(ret) && arg3) {
bellard579a97f2007-11-11 14:26:47 +00004361 if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0))
4362 goto efault;
bellard106ec872006-06-27 21:08:10 +00004363 old_act->_sa_handler = oact._sa_handler;
4364 old_act->sa_flags = oact.sa_flags;
4365 old_act->sa_mask.sig[0] = oact.sa_mask.sig[0];
4366 old_act->sa_mask.sig[1] = 0;
4367 old_act->sa_mask.sig[2] = 0;
4368 old_act->sa_mask.sig[3] = 0;
4369 unlock_user_struct(old_act, arg3, 1);
4370 }
ths388bb212007-05-13 13:58:00 +00004371#endif
bellard31e31b82003-02-18 22:55:36 +00004372 }
4373 break;
thse5febef2007-04-01 18:31:35 +00004374#endif
bellard66fb9762003-03-23 01:06:05 +00004375 case TARGET_NR_rt_sigaction:
pbrook53a59602006-03-25 19:31:22 +00004376 {
4377 struct target_sigaction *act;
4378 struct target_sigaction *oact;
4379
bellard579a97f2007-11-11 14:26:47 +00004380 if (arg2) {
4381 if (!lock_user_struct(VERIFY_READ, act, arg2, 1))
4382 goto efault;
4383 } else
pbrook53a59602006-03-25 19:31:22 +00004384 act = NULL;
bellard579a97f2007-11-11 14:26:47 +00004385 if (arg3) {
4386 if (!lock_user_struct(VERIFY_WRITE, oact, arg3, 0)) {
4387 ret = -TARGET_EFAULT;
4388 goto rt_sigaction_fail;
4389 }
4390 } else
pbrook53a59602006-03-25 19:31:22 +00004391 oact = NULL;
4392 ret = get_errno(do_sigaction(arg1, act, oact));
bellard579a97f2007-11-11 14:26:47 +00004393 rt_sigaction_fail:
4394 if (act)
pbrook53a59602006-03-25 19:31:22 +00004395 unlock_user_struct(act, arg2, 0);
bellard579a97f2007-11-11 14:26:47 +00004396 if (oact)
pbrook53a59602006-03-25 19:31:22 +00004397 unlock_user_struct(oact, arg3, 1);
4398 }
bellard66fb9762003-03-23 01:06:05 +00004399 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004400#ifdef TARGET_NR_sgetmask /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00004401 case TARGET_NR_sgetmask:
bellard66fb9762003-03-23 01:06:05 +00004402 {
4403 sigset_t cur_set;
blueswir1992f48a2007-10-14 16:27:31 +00004404 abi_ulong target_set;
bellard66fb9762003-03-23 01:06:05 +00004405 sigprocmask(0, NULL, &cur_set);
4406 host_to_target_old_sigset(&target_set, &cur_set);
4407 ret = target_set;
4408 }
4409 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004410#endif
4411#ifdef TARGET_NR_ssetmask /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00004412 case TARGET_NR_ssetmask:
bellard66fb9762003-03-23 01:06:05 +00004413 {
4414 sigset_t set, oset, cur_set;
blueswir1992f48a2007-10-14 16:27:31 +00004415 abi_ulong target_set = arg1;
bellard66fb9762003-03-23 01:06:05 +00004416 sigprocmask(0, NULL, &cur_set);
4417 target_to_host_old_sigset(&set, &target_set);
4418 sigorset(&set, &set, &cur_set);
4419 sigprocmask(SIG_SETMASK, &set, &oset);
4420 host_to_target_old_sigset(&target_set, &oset);
4421 ret = target_set;
4422 }
4423 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004424#endif
thse5febef2007-04-01 18:31:35 +00004425#ifdef TARGET_NR_sigprocmask
bellard66fb9762003-03-23 01:06:05 +00004426 case TARGET_NR_sigprocmask:
4427 {
4428 int how = arg1;
4429 sigset_t set, oldset, *set_ptr;
ths3b46e622007-09-17 08:09:54 +00004430
pbrook53a59602006-03-25 19:31:22 +00004431 if (arg2) {
bellard66fb9762003-03-23 01:06:05 +00004432 switch(how) {
4433 case TARGET_SIG_BLOCK:
4434 how = SIG_BLOCK;
4435 break;
4436 case TARGET_SIG_UNBLOCK:
4437 how = SIG_UNBLOCK;
4438 break;
4439 case TARGET_SIG_SETMASK:
4440 how = SIG_SETMASK;
4441 break;
4442 default:
ths0da46a62007-10-20 20:23:07 +00004443 ret = -TARGET_EINVAL;
bellard66fb9762003-03-23 01:06:05 +00004444 goto fail;
4445 }
bellard579a97f2007-11-11 14:26:47 +00004446 if (!(p = lock_user(VERIFY_READ, arg2, sizeof(target_sigset_t), 1)))
4447 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004448 target_to_host_old_sigset(&set, p);
4449 unlock_user(p, arg2, 0);
bellard66fb9762003-03-23 01:06:05 +00004450 set_ptr = &set;
4451 } else {
4452 how = 0;
4453 set_ptr = NULL;
4454 }
4455 ret = get_errno(sigprocmask(arg1, set_ptr, &oldset));
pbrook53a59602006-03-25 19:31:22 +00004456 if (!is_error(ret) && arg3) {
bellard579a97f2007-11-11 14:26:47 +00004457 if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0)))
4458 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004459 host_to_target_old_sigset(p, &oldset);
4460 unlock_user(p, arg3, sizeof(target_sigset_t));
bellard66fb9762003-03-23 01:06:05 +00004461 }
4462 }
4463 break;
thse5febef2007-04-01 18:31:35 +00004464#endif
bellard66fb9762003-03-23 01:06:05 +00004465 case TARGET_NR_rt_sigprocmask:
4466 {
4467 int how = arg1;
4468 sigset_t set, oldset, *set_ptr;
ths3b46e622007-09-17 08:09:54 +00004469
pbrook53a59602006-03-25 19:31:22 +00004470 if (arg2) {
bellard66fb9762003-03-23 01:06:05 +00004471 switch(how) {
4472 case TARGET_SIG_BLOCK:
4473 how = SIG_BLOCK;
4474 break;
4475 case TARGET_SIG_UNBLOCK:
4476 how = SIG_UNBLOCK;
4477 break;
4478 case TARGET_SIG_SETMASK:
4479 how = SIG_SETMASK;
4480 break;
4481 default:
ths0da46a62007-10-20 20:23:07 +00004482 ret = -TARGET_EINVAL;
bellard66fb9762003-03-23 01:06:05 +00004483 goto fail;
4484 }
bellard579a97f2007-11-11 14:26:47 +00004485 if (!(p = lock_user(VERIFY_READ, arg2, sizeof(target_sigset_t), 1)))
4486 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004487 target_to_host_sigset(&set, p);
4488 unlock_user(p, arg2, 0);
bellard66fb9762003-03-23 01:06:05 +00004489 set_ptr = &set;
4490 } else {
4491 how = 0;
4492 set_ptr = NULL;
4493 }
4494 ret = get_errno(sigprocmask(how, set_ptr, &oldset));
pbrook53a59602006-03-25 19:31:22 +00004495 if (!is_error(ret) && arg3) {
bellard579a97f2007-11-11 14:26:47 +00004496 if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0)))
4497 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004498 host_to_target_sigset(p, &oldset);
4499 unlock_user(p, arg3, sizeof(target_sigset_t));
bellard66fb9762003-03-23 01:06:05 +00004500 }
4501 }
4502 break;
thse5febef2007-04-01 18:31:35 +00004503#ifdef TARGET_NR_sigpending
bellard66fb9762003-03-23 01:06:05 +00004504 case TARGET_NR_sigpending:
4505 {
4506 sigset_t set;
4507 ret = get_errno(sigpending(&set));
4508 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00004509 if (!(p = lock_user(VERIFY_WRITE, arg1, sizeof(target_sigset_t), 0)))
4510 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004511 host_to_target_old_sigset(p, &set);
4512 unlock_user(p, arg1, sizeof(target_sigset_t));
bellard66fb9762003-03-23 01:06:05 +00004513 }
4514 }
4515 break;
thse5febef2007-04-01 18:31:35 +00004516#endif
bellard66fb9762003-03-23 01:06:05 +00004517 case TARGET_NR_rt_sigpending:
4518 {
4519 sigset_t set;
4520 ret = get_errno(sigpending(&set));
4521 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00004522 if (!(p = lock_user(VERIFY_WRITE, arg1, sizeof(target_sigset_t), 0)))
4523 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004524 host_to_target_sigset(p, &set);
4525 unlock_user(p, arg1, sizeof(target_sigset_t));
bellard66fb9762003-03-23 01:06:05 +00004526 }
4527 }
4528 break;
thse5febef2007-04-01 18:31:35 +00004529#ifdef TARGET_NR_sigsuspend
bellard66fb9762003-03-23 01:06:05 +00004530 case TARGET_NR_sigsuspend:
4531 {
4532 sigset_t set;
bellard579a97f2007-11-11 14:26:47 +00004533 if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
4534 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004535 target_to_host_old_sigset(&set, p);
4536 unlock_user(p, arg1, 0);
bellard66fb9762003-03-23 01:06:05 +00004537 ret = get_errno(sigsuspend(&set));
4538 }
4539 break;
thse5febef2007-04-01 18:31:35 +00004540#endif
bellard66fb9762003-03-23 01:06:05 +00004541 case TARGET_NR_rt_sigsuspend:
4542 {
4543 sigset_t set;
bellard579a97f2007-11-11 14:26:47 +00004544 if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
4545 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004546 target_to_host_sigset(&set, p);
4547 unlock_user(p, arg1, 0);
bellard66fb9762003-03-23 01:06:05 +00004548 ret = get_errno(sigsuspend(&set));
4549 }
4550 break;
4551 case TARGET_NR_rt_sigtimedwait:
4552 {
bellard66fb9762003-03-23 01:06:05 +00004553 sigset_t set;
4554 struct timespec uts, *puts;
4555 siginfo_t uinfo;
ths3b46e622007-09-17 08:09:54 +00004556
bellard579a97f2007-11-11 14:26:47 +00004557 if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
4558 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004559 target_to_host_sigset(&set, p);
4560 unlock_user(p, arg1, 0);
4561 if (arg3) {
bellard66fb9762003-03-23 01:06:05 +00004562 puts = &uts;
pbrook53a59602006-03-25 19:31:22 +00004563 target_to_host_timespec(puts, arg3);
bellard66fb9762003-03-23 01:06:05 +00004564 } else {
4565 puts = NULL;
4566 }
4567 ret = get_errno(sigtimedwait(&set, &uinfo, puts));
pbrook53a59602006-03-25 19:31:22 +00004568 if (!is_error(ret) && arg2) {
pbrooke1e3f302008-05-30 21:53:38 +00004569 if (!(p = lock_user(VERIFY_WRITE, arg2, sizeof(target_siginfo_t), 0)))
bellard579a97f2007-11-11 14:26:47 +00004570 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004571 host_to_target_siginfo(p, &uinfo);
pbrooke1e3f302008-05-30 21:53:38 +00004572 unlock_user(p, arg2, sizeof(target_siginfo_t));
bellard66fb9762003-03-23 01:06:05 +00004573 }
4574 }
4575 break;
4576 case TARGET_NR_rt_sigqueueinfo:
4577 {
4578 siginfo_t uinfo;
bellard579a97f2007-11-11 14:26:47 +00004579 if (!(p = lock_user(VERIFY_READ, arg3, sizeof(target_sigset_t), 1)))
4580 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004581 target_to_host_siginfo(&uinfo, p);
4582 unlock_user(p, arg1, 0);
bellard66fb9762003-03-23 01:06:05 +00004583 ret = get_errno(sys_rt_sigqueueinfo(arg1, arg2, &uinfo));
4584 }
4585 break;
thse5febef2007-04-01 18:31:35 +00004586#ifdef TARGET_NR_sigreturn
bellard66fb9762003-03-23 01:06:05 +00004587 case TARGET_NR_sigreturn:
4588 /* NOTE: ret is eax, so not transcoding must be done */
4589 ret = do_sigreturn(cpu_env);
4590 break;
thse5febef2007-04-01 18:31:35 +00004591#endif
bellard66fb9762003-03-23 01:06:05 +00004592 case TARGET_NR_rt_sigreturn:
4593 /* NOTE: ret is eax, so not transcoding must be done */
4594 ret = do_rt_sigreturn(cpu_env);
4595 break;
bellard31e31b82003-02-18 22:55:36 +00004596 case TARGET_NR_sethostname:
bellard579a97f2007-11-11 14:26:47 +00004597 if (!(p = lock_user_string(arg1)))
4598 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004599 ret = get_errno(sethostname(p, arg2));
4600 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004601 break;
4602 case TARGET_NR_setrlimit:
bellard9de5e442003-03-23 16:49:39 +00004603 {
4604 /* XXX: convert resource ? */
4605 int resource = arg1;
pbrook53a59602006-03-25 19:31:22 +00004606 struct target_rlimit *target_rlim;
bellard9de5e442003-03-23 16:49:39 +00004607 struct rlimit rlim;
bellard579a97f2007-11-11 14:26:47 +00004608 if (!lock_user_struct(VERIFY_READ, target_rlim, arg2, 1))
4609 goto efault;
bellard9de5e442003-03-23 16:49:39 +00004610 rlim.rlim_cur = tswapl(target_rlim->rlim_cur);
4611 rlim.rlim_max = tswapl(target_rlim->rlim_max);
pbrook53a59602006-03-25 19:31:22 +00004612 unlock_user_struct(target_rlim, arg2, 0);
bellard9de5e442003-03-23 16:49:39 +00004613 ret = get_errno(setrlimit(resource, &rlim));
4614 }
4615 break;
bellard31e31b82003-02-18 22:55:36 +00004616 case TARGET_NR_getrlimit:
bellard9de5e442003-03-23 16:49:39 +00004617 {
4618 /* XXX: convert resource ? */
4619 int resource = arg1;
pbrook53a59602006-03-25 19:31:22 +00004620 struct target_rlimit *target_rlim;
bellard9de5e442003-03-23 16:49:39 +00004621 struct rlimit rlim;
ths3b46e622007-09-17 08:09:54 +00004622
bellard9de5e442003-03-23 16:49:39 +00004623 ret = get_errno(getrlimit(resource, &rlim));
4624 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00004625 if (!lock_user_struct(VERIFY_WRITE, target_rlim, arg2, 0))
4626 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004627 rlim.rlim_cur = tswapl(target_rlim->rlim_cur);
4628 rlim.rlim_max = tswapl(target_rlim->rlim_max);
4629 unlock_user_struct(target_rlim, arg2, 1);
bellard9de5e442003-03-23 16:49:39 +00004630 }
4631 }
4632 break;
bellard31e31b82003-02-18 22:55:36 +00004633 case TARGET_NR_getrusage:
bellardb4091862003-05-16 15:39:34 +00004634 {
4635 struct rusage rusage;
bellardb4091862003-05-16 15:39:34 +00004636 ret = get_errno(getrusage(arg1, &rusage));
4637 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00004638 host_to_target_rusage(arg2, &rusage);
bellardb4091862003-05-16 15:39:34 +00004639 }
4640 }
4641 break;
bellard31e31b82003-02-18 22:55:36 +00004642 case TARGET_NR_gettimeofday:
4643 {
bellard31e31b82003-02-18 22:55:36 +00004644 struct timeval tv;
4645 ret = get_errno(gettimeofday(&tv, NULL));
4646 if (!is_error(ret)) {
ths788f5ec2007-12-09 02:37:05 +00004647 if (copy_to_user_timeval(arg1, &tv))
4648 goto efault;
bellard31e31b82003-02-18 22:55:36 +00004649 }
4650 }
4651 break;
4652 case TARGET_NR_settimeofday:
4653 {
bellard31e31b82003-02-18 22:55:36 +00004654 struct timeval tv;
ths788f5ec2007-12-09 02:37:05 +00004655 if (copy_from_user_timeval(&tv, arg1))
4656 goto efault;
bellard31e31b82003-02-18 22:55:36 +00004657 ret = get_errno(settimeofday(&tv, NULL));
4658 }
4659 break;
bellard048f6b42005-11-26 18:47:20 +00004660#ifdef TARGET_NR_select
bellard31e31b82003-02-18 22:55:36 +00004661 case TARGET_NR_select:
bellardf2674e32003-07-09 12:26:09 +00004662 {
pbrook53a59602006-03-25 19:31:22 +00004663 struct target_sel_arg_struct *sel;
blueswir1992f48a2007-10-14 16:27:31 +00004664 abi_ulong inp, outp, exp, tvp;
pbrook53a59602006-03-25 19:31:22 +00004665 long nsel;
4666
bellard579a97f2007-11-11 14:26:47 +00004667 if (!lock_user_struct(VERIFY_READ, sel, arg1, 1))
4668 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004669 nsel = tswapl(sel->n);
4670 inp = tswapl(sel->inp);
4671 outp = tswapl(sel->outp);
4672 exp = tswapl(sel->exp);
4673 tvp = tswapl(sel->tvp);
4674 unlock_user_struct(sel, arg1, 0);
4675 ret = do_select(nsel, inp, outp, exp, tvp);
bellardf2674e32003-07-09 12:26:09 +00004676 }
4677 break;
bellard048f6b42005-11-26 18:47:20 +00004678#endif
bellard31e31b82003-02-18 22:55:36 +00004679 case TARGET_NR_symlink:
pbrook53a59602006-03-25 19:31:22 +00004680 {
4681 void *p2;
4682 p = lock_user_string(arg1);
4683 p2 = lock_user_string(arg2);
bellard579a97f2007-11-11 14:26:47 +00004684 if (!p || !p2)
4685 ret = -TARGET_EFAULT;
4686 else
4687 ret = get_errno(symlink(p, p2));
pbrook53a59602006-03-25 19:31:22 +00004688 unlock_user(p2, arg2, 0);
4689 unlock_user(p, arg1, 0);
4690 }
bellard31e31b82003-02-18 22:55:36 +00004691 break;
thsf0b62432007-09-24 09:25:40 +00004692#if defined(TARGET_NR_symlinkat) && defined(__NR_symlinkat)
4693 case TARGET_NR_symlinkat:
thsf0b62432007-09-24 09:25:40 +00004694 {
bellard579a97f2007-11-11 14:26:47 +00004695 void *p2;
thsf0b62432007-09-24 09:25:40 +00004696 p = lock_user_string(arg1);
4697 p2 = lock_user_string(arg3);
bellard579a97f2007-11-11 14:26:47 +00004698 if (!p || !p2)
ths0da46a62007-10-20 20:23:07 +00004699 ret = -TARGET_EFAULT;
thsf0b62432007-09-24 09:25:40 +00004700 else
4701 ret = get_errno(sys_symlinkat(p, arg2, p2));
bellard579a97f2007-11-11 14:26:47 +00004702 unlock_user(p2, arg3, 0);
4703 unlock_user(p, arg1, 0);
thsf0b62432007-09-24 09:25:40 +00004704 }
4705 break;
4706#endif
bellardebc05482003-09-30 21:08:41 +00004707#ifdef TARGET_NR_oldlstat
bellard31e31b82003-02-18 22:55:36 +00004708 case TARGET_NR_oldlstat:
4709 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004710#endif
bellard31e31b82003-02-18 22:55:36 +00004711 case TARGET_NR_readlink:
pbrook53a59602006-03-25 19:31:22 +00004712 {
aurel32d088d662009-01-30 20:09:01 +00004713 void *p2, *temp;
pbrook53a59602006-03-25 19:31:22 +00004714 p = lock_user_string(arg1);
bellard579a97f2007-11-11 14:26:47 +00004715 p2 = lock_user(VERIFY_WRITE, arg2, arg3, 0);
4716 if (!p || !p2)
4717 ret = -TARGET_EFAULT;
aurel32d088d662009-01-30 20:09:01 +00004718 else {
4719 if (strncmp((const char *)p, "/proc/self/exe", 14) == 0) {
4720 char real[PATH_MAX];
4721 temp = realpath(exec_path,real);
4722 ret = (temp==NULL) ? get_errno(-1) : strlen(real) ;
4723 snprintf((char *)p2, arg3, "%s", real);
4724 }
4725 else
4726 ret = get_errno(readlink(path(p), p2, arg3));
aurel32d088d662009-01-30 20:09:01 +00004727 }
pbrook53a59602006-03-25 19:31:22 +00004728 unlock_user(p2, arg2, ret);
4729 unlock_user(p, arg1, 0);
4730 }
bellard31e31b82003-02-18 22:55:36 +00004731 break;
ths5e0ccb12007-09-24 09:26:10 +00004732#if defined(TARGET_NR_readlinkat) && defined(__NR_readlinkat)
4733 case TARGET_NR_readlinkat:
ths5e0ccb12007-09-24 09:26:10 +00004734 {
bellard579a97f2007-11-11 14:26:47 +00004735 void *p2;
ths5e0ccb12007-09-24 09:26:10 +00004736 p = lock_user_string(arg2);
bellard579a97f2007-11-11 14:26:47 +00004737 p2 = lock_user(VERIFY_WRITE, arg3, arg4, 0);
4738 if (!p || !p2)
ths0da46a62007-10-20 20:23:07 +00004739 ret = -TARGET_EFAULT;
ths5e0ccb12007-09-24 09:26:10 +00004740 else
4741 ret = get_errno(sys_readlinkat(arg1, path(p), p2, arg4));
bellard579a97f2007-11-11 14:26:47 +00004742 unlock_user(p2, arg3, ret);
4743 unlock_user(p, arg2, 0);
ths5e0ccb12007-09-24 09:26:10 +00004744 }
4745 break;
4746#endif
thse5febef2007-04-01 18:31:35 +00004747#ifdef TARGET_NR_uselib
bellard31e31b82003-02-18 22:55:36 +00004748 case TARGET_NR_uselib:
4749 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00004750#endif
4751#ifdef TARGET_NR_swapon
bellard31e31b82003-02-18 22:55:36 +00004752 case TARGET_NR_swapon:
bellard579a97f2007-11-11 14:26:47 +00004753 if (!(p = lock_user_string(arg1)))
4754 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004755 ret = get_errno(swapon(p, arg2));
4756 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004757 break;
thse5febef2007-04-01 18:31:35 +00004758#endif
bellard31e31b82003-02-18 22:55:36 +00004759 case TARGET_NR_reboot:
4760 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00004761#ifdef TARGET_NR_readdir
bellard31e31b82003-02-18 22:55:36 +00004762 case TARGET_NR_readdir:
4763 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00004764#endif
4765#ifdef TARGET_NR_mmap
bellard31e31b82003-02-18 22:55:36 +00004766 case TARGET_NR_mmap:
bellardd2fd1af2007-11-14 18:08:56 +00004767#if (defined(TARGET_I386) && defined(TARGET_ABI32)) || defined(TARGET_ARM) || defined(TARGET_M68K) || defined(TARGET_CRIS)
bellard31e31b82003-02-18 22:55:36 +00004768 {
blueswir1992f48a2007-10-14 16:27:31 +00004769 abi_ulong *v;
4770 abi_ulong v1, v2, v3, v4, v5, v6;
bellard579a97f2007-11-11 14:26:47 +00004771 if (!(v = lock_user(VERIFY_READ, arg1, 6 * sizeof(abi_ulong), 1)))
4772 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004773 v1 = tswapl(v[0]);
4774 v2 = tswapl(v[1]);
4775 v3 = tswapl(v[2]);
4776 v4 = tswapl(v[3]);
4777 v5 = tswapl(v[4]);
4778 v6 = tswapl(v[5]);
4779 unlock_user(v, arg1, 0);
ths5fafdf22007-09-16 21:08:06 +00004780 ret = get_errno(target_mmap(v1, v2, v3,
bellard5286db72003-06-05 00:57:30 +00004781 target_to_host_bitmask(v4, mmap_flags_tbl),
4782 v5, v6));
bellard31e31b82003-02-18 22:55:36 +00004783 }
bellard31e31b82003-02-18 22:55:36 +00004784#else
ths5fafdf22007-09-16 21:08:06 +00004785 ret = get_errno(target_mmap(arg1, arg2, arg3,
4786 target_to_host_bitmask(arg4, mmap_flags_tbl),
bellard6fb883e2003-07-09 17:12:39 +00004787 arg5,
4788 arg6));
bellard31e31b82003-02-18 22:55:36 +00004789#endif
bellard6fb883e2003-07-09 17:12:39 +00004790 break;
thse5febef2007-04-01 18:31:35 +00004791#endif
bellarda315a142005-01-30 22:59:18 +00004792#ifdef TARGET_NR_mmap2
bellard6fb883e2003-07-09 17:12:39 +00004793 case TARGET_NR_mmap2:
pbrookbb7ec042008-03-25 22:28:25 +00004794#ifndef MMAP_SHIFT
bellardc573ff62004-01-04 15:51:36 +00004795#define MMAP_SHIFT 12
bellardc573ff62004-01-04 15:51:36 +00004796#endif
ths5fafdf22007-09-16 21:08:06 +00004797 ret = get_errno(target_mmap(arg1, arg2, arg3,
4798 target_to_host_bitmask(arg4, mmap_flags_tbl),
bellard5286db72003-06-05 00:57:30 +00004799 arg5,
bellardc573ff62004-01-04 15:51:36 +00004800 arg6 << MMAP_SHIFT));
bellard31e31b82003-02-18 22:55:36 +00004801 break;
bellarda315a142005-01-30 22:59:18 +00004802#endif
bellard31e31b82003-02-18 22:55:36 +00004803 case TARGET_NR_munmap:
bellard54936002003-05-13 00:25:15 +00004804 ret = get_errno(target_munmap(arg1, arg2));
bellard31e31b82003-02-18 22:55:36 +00004805 break;
bellard9de5e442003-03-23 16:49:39 +00004806 case TARGET_NR_mprotect:
bellard54936002003-05-13 00:25:15 +00004807 ret = get_errno(target_mprotect(arg1, arg2, arg3));
bellard9de5e442003-03-23 16:49:39 +00004808 break;
thse5febef2007-04-01 18:31:35 +00004809#ifdef TARGET_NR_mremap
bellard9de5e442003-03-23 16:49:39 +00004810 case TARGET_NR_mremap:
bellard54936002003-05-13 00:25:15 +00004811 ret = get_errno(target_mremap(arg1, arg2, arg3, arg4, arg5));
bellard9de5e442003-03-23 16:49:39 +00004812 break;
thse5febef2007-04-01 18:31:35 +00004813#endif
pbrook53a59602006-03-25 19:31:22 +00004814 /* ??? msync/mlock/munlock are broken for softmmu. */
thse5febef2007-04-01 18:31:35 +00004815#ifdef TARGET_NR_msync
bellard9de5e442003-03-23 16:49:39 +00004816 case TARGET_NR_msync:
pbrook53a59602006-03-25 19:31:22 +00004817 ret = get_errno(msync(g2h(arg1), arg2, arg3));
bellard9de5e442003-03-23 16:49:39 +00004818 break;
thse5febef2007-04-01 18:31:35 +00004819#endif
4820#ifdef TARGET_NR_mlock
bellard9de5e442003-03-23 16:49:39 +00004821 case TARGET_NR_mlock:
pbrook53a59602006-03-25 19:31:22 +00004822 ret = get_errno(mlock(g2h(arg1), arg2));
bellard9de5e442003-03-23 16:49:39 +00004823 break;
thse5febef2007-04-01 18:31:35 +00004824#endif
4825#ifdef TARGET_NR_munlock
bellard9de5e442003-03-23 16:49:39 +00004826 case TARGET_NR_munlock:
pbrook53a59602006-03-25 19:31:22 +00004827 ret = get_errno(munlock(g2h(arg1), arg2));
bellard9de5e442003-03-23 16:49:39 +00004828 break;
thse5febef2007-04-01 18:31:35 +00004829#endif
4830#ifdef TARGET_NR_mlockall
bellard9de5e442003-03-23 16:49:39 +00004831 case TARGET_NR_mlockall:
4832 ret = get_errno(mlockall(arg1));
4833 break;
thse5febef2007-04-01 18:31:35 +00004834#endif
4835#ifdef TARGET_NR_munlockall
bellard9de5e442003-03-23 16:49:39 +00004836 case TARGET_NR_munlockall:
4837 ret = get_errno(munlockall());
4838 break;
thse5febef2007-04-01 18:31:35 +00004839#endif
bellard31e31b82003-02-18 22:55:36 +00004840 case TARGET_NR_truncate:
bellard579a97f2007-11-11 14:26:47 +00004841 if (!(p = lock_user_string(arg1)))
4842 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004843 ret = get_errno(truncate(p, arg2));
4844 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004845 break;
4846 case TARGET_NR_ftruncate:
4847 ret = get_errno(ftruncate(arg1, arg2));
4848 break;
4849 case TARGET_NR_fchmod:
4850 ret = get_errno(fchmod(arg1, arg2));
4851 break;
ths814d7972007-09-24 09:26:51 +00004852#if defined(TARGET_NR_fchmodat) && defined(__NR_fchmodat)
4853 case TARGET_NR_fchmodat:
bellard579a97f2007-11-11 14:26:47 +00004854 if (!(p = lock_user_string(arg2)))
4855 goto efault;
4856 ret = get_errno(sys_fchmodat(arg1, p, arg3, arg4));
4857 unlock_user(p, arg2, 0);
ths814d7972007-09-24 09:26:51 +00004858 break;
4859#endif
bellard31e31b82003-02-18 22:55:36 +00004860 case TARGET_NR_getpriority:
thsc6cda172007-10-09 03:42:34 +00004861 /* libc does special remapping of the return value of
4862 * sys_getpriority() so it's just easiest to call
4863 * sys_getpriority() directly rather than through libc. */
4864 ret = sys_getpriority(arg1, arg2);
bellard31e31b82003-02-18 22:55:36 +00004865 break;
4866 case TARGET_NR_setpriority:
4867 ret = get_errno(setpriority(arg1, arg2, arg3));
4868 break;
bellardebc05482003-09-30 21:08:41 +00004869#ifdef TARGET_NR_profil
bellard31e31b82003-02-18 22:55:36 +00004870 case TARGET_NR_profil:
4871 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004872#endif
bellard31e31b82003-02-18 22:55:36 +00004873 case TARGET_NR_statfs:
bellard579a97f2007-11-11 14:26:47 +00004874 if (!(p = lock_user_string(arg1)))
4875 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004876 ret = get_errno(statfs(path(p), &stfs));
4877 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004878 convert_statfs:
4879 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00004880 struct target_statfs *target_stfs;
ths3b46e622007-09-17 08:09:54 +00004881
bellard579a97f2007-11-11 14:26:47 +00004882 if (!lock_user_struct(VERIFY_WRITE, target_stfs, arg2, 0))
4883 goto efault;
4884 __put_user(stfs.f_type, &target_stfs->f_type);
4885 __put_user(stfs.f_bsize, &target_stfs->f_bsize);
4886 __put_user(stfs.f_blocks, &target_stfs->f_blocks);
4887 __put_user(stfs.f_bfree, &target_stfs->f_bfree);
4888 __put_user(stfs.f_bavail, &target_stfs->f_bavail);
4889 __put_user(stfs.f_files, &target_stfs->f_files);
4890 __put_user(stfs.f_ffree, &target_stfs->f_ffree);
4891 __put_user(stfs.f_fsid.__val[0], &target_stfs->f_fsid.val[0]);
4892 __put_user(stfs.f_fsid.__val[1], &target_stfs->f_fsid.val[1]);
4893 __put_user(stfs.f_namelen, &target_stfs->f_namelen);
pbrook53a59602006-03-25 19:31:22 +00004894 unlock_user_struct(target_stfs, arg2, 1);
bellard31e31b82003-02-18 22:55:36 +00004895 }
4896 break;
4897 case TARGET_NR_fstatfs:
bellard56c8f682005-11-28 22:28:41 +00004898 ret = get_errno(fstatfs(arg1, &stfs));
bellard31e31b82003-02-18 22:55:36 +00004899 goto convert_statfs;
bellard56c8f682005-11-28 22:28:41 +00004900#ifdef TARGET_NR_statfs64
4901 case TARGET_NR_statfs64:
bellard579a97f2007-11-11 14:26:47 +00004902 if (!(p = lock_user_string(arg1)))
4903 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004904 ret = get_errno(statfs(path(p), &stfs));
4905 unlock_user(p, arg1, 0);
bellard56c8f682005-11-28 22:28:41 +00004906 convert_statfs64:
4907 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00004908 struct target_statfs64 *target_stfs;
ths3b46e622007-09-17 08:09:54 +00004909
bellard579a97f2007-11-11 14:26:47 +00004910 if (!lock_user_struct(VERIFY_WRITE, target_stfs, arg3, 0))
4911 goto efault;
4912 __put_user(stfs.f_type, &target_stfs->f_type);
4913 __put_user(stfs.f_bsize, &target_stfs->f_bsize);
4914 __put_user(stfs.f_blocks, &target_stfs->f_blocks);
4915 __put_user(stfs.f_bfree, &target_stfs->f_bfree);
4916 __put_user(stfs.f_bavail, &target_stfs->f_bavail);
4917 __put_user(stfs.f_files, &target_stfs->f_files);
4918 __put_user(stfs.f_ffree, &target_stfs->f_ffree);
4919 __put_user(stfs.f_fsid.__val[0], &target_stfs->f_fsid.val[0]);
4920 __put_user(stfs.f_fsid.__val[1], &target_stfs->f_fsid.val[1]);
4921 __put_user(stfs.f_namelen, &target_stfs->f_namelen);
4922 unlock_user_struct(target_stfs, arg3, 1);
bellard56c8f682005-11-28 22:28:41 +00004923 }
4924 break;
4925 case TARGET_NR_fstatfs64:
4926 ret = get_errno(fstatfs(arg1, &stfs));
4927 goto convert_statfs64;
4928#endif
bellardebc05482003-09-30 21:08:41 +00004929#ifdef TARGET_NR_ioperm
bellard31e31b82003-02-18 22:55:36 +00004930 case TARGET_NR_ioperm:
4931 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004932#endif
thse5febef2007-04-01 18:31:35 +00004933#ifdef TARGET_NR_socketcall
bellard31e31b82003-02-18 22:55:36 +00004934 case TARGET_NR_socketcall:
pbrook53a59602006-03-25 19:31:22 +00004935 ret = do_socketcall(arg1, arg2);
bellard31e31b82003-02-18 22:55:36 +00004936 break;
thse5febef2007-04-01 18:31:35 +00004937#endif
bellard3532fa72006-06-24 15:06:03 +00004938#ifdef TARGET_NR_accept
4939 case TARGET_NR_accept:
pbrook1be9e1d2006-11-19 15:26:04 +00004940 ret = do_accept(arg1, arg2, arg3);
bellard3532fa72006-06-24 15:06:03 +00004941 break;
4942#endif
4943#ifdef TARGET_NR_bind
4944 case TARGET_NR_bind:
4945 ret = do_bind(arg1, arg2, arg3);
4946 break;
4947#endif
4948#ifdef TARGET_NR_connect
4949 case TARGET_NR_connect:
4950 ret = do_connect(arg1, arg2, arg3);
4951 break;
4952#endif
4953#ifdef TARGET_NR_getpeername
4954 case TARGET_NR_getpeername:
pbrook1be9e1d2006-11-19 15:26:04 +00004955 ret = do_getpeername(arg1, arg2, arg3);
bellard3532fa72006-06-24 15:06:03 +00004956 break;
4957#endif
4958#ifdef TARGET_NR_getsockname
4959 case TARGET_NR_getsockname:
pbrook1be9e1d2006-11-19 15:26:04 +00004960 ret = do_getsockname(arg1, arg2, arg3);
bellard3532fa72006-06-24 15:06:03 +00004961 break;
4962#endif
4963#ifdef TARGET_NR_getsockopt
4964 case TARGET_NR_getsockopt:
4965 ret = do_getsockopt(arg1, arg2, arg3, arg4, arg5);
4966 break;
4967#endif
4968#ifdef TARGET_NR_listen
4969 case TARGET_NR_listen:
pbrook1be9e1d2006-11-19 15:26:04 +00004970 ret = get_errno(listen(arg1, arg2));
bellard3532fa72006-06-24 15:06:03 +00004971 break;
4972#endif
4973#ifdef TARGET_NR_recv
4974 case TARGET_NR_recv:
pbrook214201b2007-03-17 01:27:24 +00004975 ret = do_recvfrom(arg1, arg2, arg3, arg4, 0, 0);
bellard3532fa72006-06-24 15:06:03 +00004976 break;
4977#endif
4978#ifdef TARGET_NR_recvfrom
4979 case TARGET_NR_recvfrom:
pbrook214201b2007-03-17 01:27:24 +00004980 ret = do_recvfrom(arg1, arg2, arg3, arg4, arg5, arg6);
bellard3532fa72006-06-24 15:06:03 +00004981 break;
4982#endif
4983#ifdef TARGET_NR_recvmsg
4984 case TARGET_NR_recvmsg:
4985 ret = do_sendrecvmsg(arg1, arg2, arg3, 0);
4986 break;
4987#endif
4988#ifdef TARGET_NR_send
4989 case TARGET_NR_send:
pbrook1be9e1d2006-11-19 15:26:04 +00004990 ret = do_sendto(arg1, arg2, arg3, arg4, 0, 0);
bellard3532fa72006-06-24 15:06:03 +00004991 break;
4992#endif
4993#ifdef TARGET_NR_sendmsg
4994 case TARGET_NR_sendmsg:
4995 ret = do_sendrecvmsg(arg1, arg2, arg3, 1);
4996 break;
4997#endif
4998#ifdef TARGET_NR_sendto
4999 case TARGET_NR_sendto:
pbrook1be9e1d2006-11-19 15:26:04 +00005000 ret = do_sendto(arg1, arg2, arg3, arg4, arg5, arg6);
bellard3532fa72006-06-24 15:06:03 +00005001 break;
5002#endif
5003#ifdef TARGET_NR_shutdown
5004 case TARGET_NR_shutdown:
pbrook1be9e1d2006-11-19 15:26:04 +00005005 ret = get_errno(shutdown(arg1, arg2));
bellard3532fa72006-06-24 15:06:03 +00005006 break;
5007#endif
5008#ifdef TARGET_NR_socket
5009 case TARGET_NR_socket:
5010 ret = do_socket(arg1, arg2, arg3);
5011 break;
5012#endif
5013#ifdef TARGET_NR_socketpair
5014 case TARGET_NR_socketpair:
pbrook1be9e1d2006-11-19 15:26:04 +00005015 ret = do_socketpair(arg1, arg2, arg3, arg4);
bellard3532fa72006-06-24 15:06:03 +00005016 break;
5017#endif
5018#ifdef TARGET_NR_setsockopt
5019 case TARGET_NR_setsockopt:
5020 ret = do_setsockopt(arg1, arg2, arg3, arg4, (socklen_t) arg5);
5021 break;
5022#endif
ths7494b0f2007-02-11 18:26:53 +00005023
bellard31e31b82003-02-18 22:55:36 +00005024 case TARGET_NR_syslog:
bellard579a97f2007-11-11 14:26:47 +00005025 if (!(p = lock_user_string(arg2)))
5026 goto efault;
thse5574482007-02-11 20:03:13 +00005027 ret = get_errno(sys_syslog((int)arg1, p, (int)arg3));
5028 unlock_user(p, arg2, 0);
ths7494b0f2007-02-11 18:26:53 +00005029 break;
5030
bellard31e31b82003-02-18 22:55:36 +00005031 case TARGET_NR_setitimer:
bellard66fb9762003-03-23 01:06:05 +00005032 {
bellard66fb9762003-03-23 01:06:05 +00005033 struct itimerval value, ovalue, *pvalue;
5034
pbrook53a59602006-03-25 19:31:22 +00005035 if (arg2) {
bellard66fb9762003-03-23 01:06:05 +00005036 pvalue = &value;
ths788f5ec2007-12-09 02:37:05 +00005037 if (copy_from_user_timeval(&pvalue->it_interval, arg2)
5038 || copy_from_user_timeval(&pvalue->it_value,
5039 arg2 + sizeof(struct target_timeval)))
5040 goto efault;
bellard66fb9762003-03-23 01:06:05 +00005041 } else {
5042 pvalue = NULL;
5043 }
5044 ret = get_errno(setitimer(arg1, pvalue, &ovalue));
pbrook53a59602006-03-25 19:31:22 +00005045 if (!is_error(ret) && arg3) {
ths788f5ec2007-12-09 02:37:05 +00005046 if (copy_to_user_timeval(arg3,
5047 &ovalue.it_interval)
5048 || copy_to_user_timeval(arg3 + sizeof(struct target_timeval),
5049 &ovalue.it_value))
5050 goto efault;
bellard66fb9762003-03-23 01:06:05 +00005051 }
5052 }
5053 break;
bellard31e31b82003-02-18 22:55:36 +00005054 case TARGET_NR_getitimer:
bellard66fb9762003-03-23 01:06:05 +00005055 {
bellard66fb9762003-03-23 01:06:05 +00005056 struct itimerval value;
ths3b46e622007-09-17 08:09:54 +00005057
bellard66fb9762003-03-23 01:06:05 +00005058 ret = get_errno(getitimer(arg1, &value));
pbrook53a59602006-03-25 19:31:22 +00005059 if (!is_error(ret) && arg2) {
ths788f5ec2007-12-09 02:37:05 +00005060 if (copy_to_user_timeval(arg2,
5061 &value.it_interval)
5062 || copy_to_user_timeval(arg2 + sizeof(struct target_timeval),
5063 &value.it_value))
5064 goto efault;
bellard66fb9762003-03-23 01:06:05 +00005065 }
5066 }
5067 break;
bellard31e31b82003-02-18 22:55:36 +00005068 case TARGET_NR_stat:
bellard579a97f2007-11-11 14:26:47 +00005069 if (!(p = lock_user_string(arg1)))
5070 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005071 ret = get_errno(stat(path(p), &st));
5072 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00005073 goto do_stat;
5074 case TARGET_NR_lstat:
bellard579a97f2007-11-11 14:26:47 +00005075 if (!(p = lock_user_string(arg1)))
5076 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005077 ret = get_errno(lstat(path(p), &st));
5078 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00005079 goto do_stat;
5080 case TARGET_NR_fstat:
5081 {
5082 ret = get_errno(fstat(arg1, &st));
5083 do_stat:
5084 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00005085 struct target_stat *target_st;
thse3584652007-06-01 11:49:38 +00005086
bellard579a97f2007-11-11 14:26:47 +00005087 if (!lock_user_struct(VERIFY_WRITE, target_st, arg2, 0))
5088 goto efault;
bellardd2fd1af2007-11-14 18:08:56 +00005089 __put_user(st.st_dev, &target_st->st_dev);
5090 __put_user(st.st_ino, &target_st->st_ino);
5091 __put_user(st.st_mode, &target_st->st_mode);
5092 __put_user(st.st_uid, &target_st->st_uid);
5093 __put_user(st.st_gid, &target_st->st_gid);
5094 __put_user(st.st_nlink, &target_st->st_nlink);
5095 __put_user(st.st_rdev, &target_st->st_rdev);
5096 __put_user(st.st_size, &target_st->st_size);
5097 __put_user(st.st_blksize, &target_st->st_blksize);
5098 __put_user(st.st_blocks, &target_st->st_blocks);
5099 __put_user(st.st_atime, &target_st->target_st_atime);
5100 __put_user(st.st_mtime, &target_st->target_st_mtime);
5101 __put_user(st.st_ctime, &target_st->target_st_ctime);
pbrook53a59602006-03-25 19:31:22 +00005102 unlock_user_struct(target_st, arg2, 1);
bellard31e31b82003-02-18 22:55:36 +00005103 }
5104 }
5105 break;
bellardebc05482003-09-30 21:08:41 +00005106#ifdef TARGET_NR_olduname
bellard31e31b82003-02-18 22:55:36 +00005107 case TARGET_NR_olduname:
5108 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00005109#endif
5110#ifdef TARGET_NR_iopl
bellard31e31b82003-02-18 22:55:36 +00005111 case TARGET_NR_iopl:
5112 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00005113#endif
bellard31e31b82003-02-18 22:55:36 +00005114 case TARGET_NR_vhangup:
5115 ret = get_errno(vhangup());
5116 break;
bellardebc05482003-09-30 21:08:41 +00005117#ifdef TARGET_NR_idle
bellard31e31b82003-02-18 22:55:36 +00005118 case TARGET_NR_idle:
5119 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00005120#endif
bellard42ad6ae2005-01-03 22:48:11 +00005121#ifdef TARGET_NR_syscall
5122 case TARGET_NR_syscall:
5123 ret = do_syscall(cpu_env,arg1 & 0xffff,arg2,arg3,arg4,arg5,arg6,0);
5124 break;
5125#endif
bellard31e31b82003-02-18 22:55:36 +00005126 case TARGET_NR_wait4:
5127 {
5128 int status;
blueswir1992f48a2007-10-14 16:27:31 +00005129 abi_long status_ptr = arg2;
bellard31e31b82003-02-18 22:55:36 +00005130 struct rusage rusage, *rusage_ptr;
blueswir1992f48a2007-10-14 16:27:31 +00005131 abi_ulong target_rusage = arg4;
bellard31e31b82003-02-18 22:55:36 +00005132 if (target_rusage)
5133 rusage_ptr = &rusage;
5134 else
5135 rusage_ptr = NULL;
5136 ret = get_errno(wait4(arg1, &status, arg3, rusage_ptr));
5137 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +00005138 if (status_ptr) {
5139 if (put_user_s32(status, status_ptr))
5140 goto efault;
bellard31e31b82003-02-18 22:55:36 +00005141 }
bellard2f619692007-11-16 10:46:05 +00005142 if (target_rusage)
5143 host_to_target_rusage(target_rusage, &rusage);
bellard31e31b82003-02-18 22:55:36 +00005144 }
5145 }
5146 break;
thse5febef2007-04-01 18:31:35 +00005147#ifdef TARGET_NR_swapoff
bellard31e31b82003-02-18 22:55:36 +00005148 case TARGET_NR_swapoff:
bellard579a97f2007-11-11 14:26:47 +00005149 if (!(p = lock_user_string(arg1)))
5150 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005151 ret = get_errno(swapoff(p));
5152 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00005153 break;
thse5febef2007-04-01 18:31:35 +00005154#endif
bellard31e31b82003-02-18 22:55:36 +00005155 case TARGET_NR_sysinfo:
bellarda5448a72004-06-19 16:59:03 +00005156 {
pbrook53a59602006-03-25 19:31:22 +00005157 struct target_sysinfo *target_value;
bellarda5448a72004-06-19 16:59:03 +00005158 struct sysinfo value;
5159 ret = get_errno(sysinfo(&value));
pbrook53a59602006-03-25 19:31:22 +00005160 if (!is_error(ret) && arg1)
bellarda5448a72004-06-19 16:59:03 +00005161 {
bellard579a97f2007-11-11 14:26:47 +00005162 if (!lock_user_struct(VERIFY_WRITE, target_value, arg1, 0))
5163 goto efault;
bellarda5448a72004-06-19 16:59:03 +00005164 __put_user(value.uptime, &target_value->uptime);
5165 __put_user(value.loads[0], &target_value->loads[0]);
5166 __put_user(value.loads[1], &target_value->loads[1]);
5167 __put_user(value.loads[2], &target_value->loads[2]);
5168 __put_user(value.totalram, &target_value->totalram);
5169 __put_user(value.freeram, &target_value->freeram);
5170 __put_user(value.sharedram, &target_value->sharedram);
5171 __put_user(value.bufferram, &target_value->bufferram);
5172 __put_user(value.totalswap, &target_value->totalswap);
5173 __put_user(value.freeswap, &target_value->freeswap);
5174 __put_user(value.procs, &target_value->procs);
5175 __put_user(value.totalhigh, &target_value->totalhigh);
5176 __put_user(value.freehigh, &target_value->freehigh);
5177 __put_user(value.mem_unit, &target_value->mem_unit);
pbrook53a59602006-03-25 19:31:22 +00005178 unlock_user_struct(target_value, arg1, 1);
bellarda5448a72004-06-19 16:59:03 +00005179 }
5180 }
5181 break;
thse5febef2007-04-01 18:31:35 +00005182#ifdef TARGET_NR_ipc
bellard31e31b82003-02-18 22:55:36 +00005183 case TARGET_NR_ipc:
bellard8853f862004-02-22 14:57:26 +00005184 ret = do_ipc(arg1, arg2, arg3, arg4, arg5, arg6);
5185 break;
thse5febef2007-04-01 18:31:35 +00005186#endif
aurel32eeb438c2008-10-13 21:08:55 +00005187
5188#ifdef TARGET_NR_msgctl
5189 case TARGET_NR_msgctl:
5190 ret = do_msgctl(arg1, arg2, arg3);
5191 break;
5192#endif
5193#ifdef TARGET_NR_msgget
5194 case TARGET_NR_msgget:
5195 ret = get_errno(msgget(arg1, arg2));
5196 break;
5197#endif
5198#ifdef TARGET_NR_msgrcv
5199 case TARGET_NR_msgrcv:
5200 ret = do_msgrcv(arg1, arg2, arg3, arg4, arg5);
5201 break;
5202#endif
5203#ifdef TARGET_NR_msgsnd
5204 case TARGET_NR_msgsnd:
5205 ret = do_msgsnd(arg1, arg2, arg3, arg4);
5206 break;
5207#endif
bellard31e31b82003-02-18 22:55:36 +00005208 case TARGET_NR_fsync:
5209 ret = get_errno(fsync(arg1));
5210 break;
bellard31e31b82003-02-18 22:55:36 +00005211 case TARGET_NR_clone:
aurel320b6d3ae2008-09-15 07:43:43 +00005212#if defined(TARGET_SH4)
5213 ret = get_errno(do_fork(cpu_env, arg1, arg2, arg3, arg5, arg4));
edgar_iglb15ad612009-01-07 19:43:47 +00005214#elif defined(TARGET_CRIS)
5215 ret = get_errno(do_fork(cpu_env, arg2, arg1, arg3, arg4, arg5));
aurel320b6d3ae2008-09-15 07:43:43 +00005216#else
pbrookd865bab2008-06-07 22:12:17 +00005217 ret = get_errno(do_fork(cpu_env, arg1, arg2, arg3, arg4, arg5));
aurel320b6d3ae2008-09-15 07:43:43 +00005218#endif
bellard1b6b0292003-03-22 17:31:38 +00005219 break;
bellardec86b0f2003-04-11 00:15:04 +00005220#ifdef __NR_exit_group
5221 /* new thread calls */
5222 case TARGET_NR_exit_group:
aurel326d946cd2008-11-06 16:15:18 +00005223#ifdef HAVE_GPROF
5224 _mcleanup();
5225#endif
bellarde9009672005-04-26 20:42:36 +00005226 gdb_exit(cpu_env, arg1);
bellardec86b0f2003-04-11 00:15:04 +00005227 ret = get_errno(exit_group(arg1));
5228 break;
5229#endif
bellard31e31b82003-02-18 22:55:36 +00005230 case TARGET_NR_setdomainname:
bellard579a97f2007-11-11 14:26:47 +00005231 if (!(p = lock_user_string(arg1)))
5232 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005233 ret = get_errno(setdomainname(p, arg2));
5234 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00005235 break;
5236 case TARGET_NR_uname:
5237 /* no need to transcode because we use the linux syscall */
bellard29e619b2004-09-13 21:41:04 +00005238 {
5239 struct new_utsname * buf;
ths3b46e622007-09-17 08:09:54 +00005240
bellard579a97f2007-11-11 14:26:47 +00005241 if (!lock_user_struct(VERIFY_WRITE, buf, arg1, 0))
5242 goto efault;
bellard29e619b2004-09-13 21:41:04 +00005243 ret = get_errno(sys_uname(buf));
5244 if (!is_error(ret)) {
5245 /* Overrite the native machine name with whatever is being
5246 emulated. */
5247 strcpy (buf->machine, UNAME_MACHINE);
pbrookc5937222006-05-14 11:30:38 +00005248 /* Allow the user to override the reported release. */
5249 if (qemu_uname_release && *qemu_uname_release)
5250 strcpy (buf->release, qemu_uname_release);
bellard29e619b2004-09-13 21:41:04 +00005251 }
pbrook53a59602006-03-25 19:31:22 +00005252 unlock_user_struct(buf, arg1, 1);
bellard29e619b2004-09-13 21:41:04 +00005253 }
bellard31e31b82003-02-18 22:55:36 +00005254 break;
bellard6dbad632003-03-16 18:05:05 +00005255#ifdef TARGET_I386
bellard31e31b82003-02-18 22:55:36 +00005256 case TARGET_NR_modify_ldt:
bellard03acab62007-11-11 14:57:14 +00005257 ret = do_modify_ldt(cpu_env, arg1, arg2, arg3);
bellard5cd43932003-03-29 16:54:36 +00005258 break;
j_mayer84409dd2007-04-06 08:56:50 +00005259#if !defined(TARGET_X86_64)
bellard5cd43932003-03-29 16:54:36 +00005260 case TARGET_NR_vm86old:
5261 goto unimplemented;
5262 case TARGET_NR_vm86:
pbrook53a59602006-03-25 19:31:22 +00005263 ret = do_vm86(cpu_env, arg1, arg2);
bellard6dbad632003-03-16 18:05:05 +00005264 break;
5265#endif
j_mayer84409dd2007-04-06 08:56:50 +00005266#endif
bellard31e31b82003-02-18 22:55:36 +00005267 case TARGET_NR_adjtimex:
5268 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00005269#ifdef TARGET_NR_create_module
bellard31e31b82003-02-18 22:55:36 +00005270 case TARGET_NR_create_module:
thse5febef2007-04-01 18:31:35 +00005271#endif
bellard31e31b82003-02-18 22:55:36 +00005272 case TARGET_NR_init_module:
5273 case TARGET_NR_delete_module:
thse5febef2007-04-01 18:31:35 +00005274#ifdef TARGET_NR_get_kernel_syms
bellard31e31b82003-02-18 22:55:36 +00005275 case TARGET_NR_get_kernel_syms:
thse5febef2007-04-01 18:31:35 +00005276#endif
bellard31e31b82003-02-18 22:55:36 +00005277 goto unimplemented;
5278 case TARGET_NR_quotactl:
5279 goto unimplemented;
5280 case TARGET_NR_getpgid:
5281 ret = get_errno(getpgid(arg1));
5282 break;
5283 case TARGET_NR_fchdir:
5284 ret = get_errno(fchdir(arg1));
5285 break;
j_mayer84409dd2007-04-06 08:56:50 +00005286#ifdef TARGET_NR_bdflush /* not on x86_64 */
bellard31e31b82003-02-18 22:55:36 +00005287 case TARGET_NR_bdflush:
5288 goto unimplemented;
j_mayer84409dd2007-04-06 08:56:50 +00005289#endif
thse5febef2007-04-01 18:31:35 +00005290#ifdef TARGET_NR_sysfs
bellard31e31b82003-02-18 22:55:36 +00005291 case TARGET_NR_sysfs:
5292 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00005293#endif
bellard31e31b82003-02-18 22:55:36 +00005294 case TARGET_NR_personality:
bellard1b6b0292003-03-22 17:31:38 +00005295 ret = get_errno(personality(arg1));
bellard31e31b82003-02-18 22:55:36 +00005296 break;
thse5febef2007-04-01 18:31:35 +00005297#ifdef TARGET_NR_afs_syscall
bellard31e31b82003-02-18 22:55:36 +00005298 case TARGET_NR_afs_syscall:
5299 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00005300#endif
j_mayer7a3148a2007-04-05 07:13:51 +00005301#ifdef TARGET_NR__llseek /* Not on alpha */
bellard31e31b82003-02-18 22:55:36 +00005302 case TARGET_NR__llseek:
5303 {
bellard4f2ac232004-04-26 19:44:02 +00005304#if defined (__x86_64__)
5305 ret = get_errno(lseek(arg1, ((uint64_t )arg2 << 32) | arg3, arg5));
bellard2f619692007-11-16 10:46:05 +00005306 if (put_user_s64(ret, arg4))
5307 goto efault;
bellard4f2ac232004-04-26 19:44:02 +00005308#else
bellard31e31b82003-02-18 22:55:36 +00005309 int64_t res;
5310 ret = get_errno(_llseek(arg1, arg2, arg3, &res, arg5));
bellard2f619692007-11-16 10:46:05 +00005311 if (put_user_s64(res, arg4))
5312 goto efault;
bellard4f2ac232004-04-26 19:44:02 +00005313#endif
bellard31e31b82003-02-18 22:55:36 +00005314 }
5315 break;
j_mayer7a3148a2007-04-05 07:13:51 +00005316#endif
bellard31e31b82003-02-18 22:55:36 +00005317 case TARGET_NR_getdents:
blueswir1992f48a2007-10-14 16:27:31 +00005318#if TARGET_ABI_BITS != 32
pbrook53a59602006-03-25 19:31:22 +00005319 goto unimplemented;
blueswir1992f48a2007-10-14 16:27:31 +00005320#elif TARGET_ABI_BITS == 32 && HOST_LONG_BITS == 64
bellard4add45b2003-06-05 01:52:59 +00005321 {
pbrook53a59602006-03-25 19:31:22 +00005322 struct target_dirent *target_dirp;
aurel326556a832008-10-13 21:08:17 +00005323 struct linux_dirent *dirp;
blueswir1992f48a2007-10-14 16:27:31 +00005324 abi_long count = arg3;
bellard4add45b2003-06-05 01:52:59 +00005325
5326 dirp = malloc(count);
ths0da46a62007-10-20 20:23:07 +00005327 if (!dirp) {
bellard579a97f2007-11-11 14:26:47 +00005328 ret = -TARGET_ENOMEM;
ths0da46a62007-10-20 20:23:07 +00005329 goto fail;
5330 }
ths3b46e622007-09-17 08:09:54 +00005331
bellard4add45b2003-06-05 01:52:59 +00005332 ret = get_errno(sys_getdents(arg1, dirp, count));
5333 if (!is_error(ret)) {
aurel326556a832008-10-13 21:08:17 +00005334 struct linux_dirent *de;
bellard4add45b2003-06-05 01:52:59 +00005335 struct target_dirent *tde;
5336 int len = ret;
5337 int reclen, treclen;
5338 int count1, tnamelen;
5339
5340 count1 = 0;
5341 de = dirp;
bellard579a97f2007-11-11 14:26:47 +00005342 if (!(target_dirp = lock_user(VERIFY_WRITE, arg2, count, 0)))
5343 goto efault;
bellard4add45b2003-06-05 01:52:59 +00005344 tde = target_dirp;
5345 while (len > 0) {
5346 reclen = de->d_reclen;
blueswir1992f48a2007-10-14 16:27:31 +00005347 treclen = reclen - (2 * (sizeof(long) - sizeof(abi_long)));
bellard4add45b2003-06-05 01:52:59 +00005348 tde->d_reclen = tswap16(treclen);
5349 tde->d_ino = tswapl(de->d_ino);
5350 tde->d_off = tswapl(de->d_off);
blueswir1992f48a2007-10-14 16:27:31 +00005351 tnamelen = treclen - (2 * sizeof(abi_long) + 2);
bellard4add45b2003-06-05 01:52:59 +00005352 if (tnamelen > 256)
5353 tnamelen = 256;
bellard80a9d032005-01-03 23:31:27 +00005354 /* XXX: may not be correct */
blueswir1be15b142008-10-25 11:21:28 +00005355 pstrcpy(tde->d_name, tnamelen, de->d_name);
aurel326556a832008-10-13 21:08:17 +00005356 de = (struct linux_dirent *)((char *)de + reclen);
bellard4add45b2003-06-05 01:52:59 +00005357 len -= reclen;
j_mayer1c5bf3b2007-04-14 12:17:59 +00005358 tde = (struct target_dirent *)((char *)tde + treclen);
bellard4add45b2003-06-05 01:52:59 +00005359 count1 += treclen;
5360 }
5361 ret = count1;
bellard579a97f2007-11-11 14:26:47 +00005362 unlock_user(target_dirp, arg2, ret);
bellard4add45b2003-06-05 01:52:59 +00005363 }
5364 free(dirp);
5365 }
5366#else
bellard31e31b82003-02-18 22:55:36 +00005367 {
aurel326556a832008-10-13 21:08:17 +00005368 struct linux_dirent *dirp;
blueswir1992f48a2007-10-14 16:27:31 +00005369 abi_long count = arg3;
bellarddab2ed92003-03-22 15:23:14 +00005370
bellard579a97f2007-11-11 14:26:47 +00005371 if (!(dirp = lock_user(VERIFY_WRITE, arg2, count, 0)))
5372 goto efault;
bellard72f03902003-02-18 23:33:18 +00005373 ret = get_errno(sys_getdents(arg1, dirp, count));
bellard31e31b82003-02-18 22:55:36 +00005374 if (!is_error(ret)) {
aurel326556a832008-10-13 21:08:17 +00005375 struct linux_dirent *de;
bellard31e31b82003-02-18 22:55:36 +00005376 int len = ret;
5377 int reclen;
5378 de = dirp;
5379 while (len > 0) {
bellard8083a3e2003-03-24 23:12:16 +00005380 reclen = de->d_reclen;
bellard31e31b82003-02-18 22:55:36 +00005381 if (reclen > len)
5382 break;
bellard8083a3e2003-03-24 23:12:16 +00005383 de->d_reclen = tswap16(reclen);
bellard31e31b82003-02-18 22:55:36 +00005384 tswapls(&de->d_ino);
5385 tswapls(&de->d_off);
aurel326556a832008-10-13 21:08:17 +00005386 de = (struct linux_dirent *)((char *)de + reclen);
bellard31e31b82003-02-18 22:55:36 +00005387 len -= reclen;
5388 }
5389 }
pbrook53a59602006-03-25 19:31:22 +00005390 unlock_user(dirp, arg2, ret);
bellard31e31b82003-02-18 22:55:36 +00005391 }
bellard4add45b2003-06-05 01:52:59 +00005392#endif
bellard31e31b82003-02-18 22:55:36 +00005393 break;
ths3ae43202007-09-16 21:39:48 +00005394#if defined(TARGET_NR_getdents64) && defined(__NR_getdents64)
bellarddab2ed92003-03-22 15:23:14 +00005395 case TARGET_NR_getdents64:
5396 {
aurel326556a832008-10-13 21:08:17 +00005397 struct linux_dirent64 *dirp;
blueswir1992f48a2007-10-14 16:27:31 +00005398 abi_long count = arg3;
bellard579a97f2007-11-11 14:26:47 +00005399 if (!(dirp = lock_user(VERIFY_WRITE, arg2, count, 0)))
5400 goto efault;
bellarddab2ed92003-03-22 15:23:14 +00005401 ret = get_errno(sys_getdents64(arg1, dirp, count));
5402 if (!is_error(ret)) {
aurel326556a832008-10-13 21:08:17 +00005403 struct linux_dirent64 *de;
bellarddab2ed92003-03-22 15:23:14 +00005404 int len = ret;
5405 int reclen;
5406 de = dirp;
5407 while (len > 0) {
bellard8083a3e2003-03-24 23:12:16 +00005408 reclen = de->d_reclen;
bellarddab2ed92003-03-22 15:23:14 +00005409 if (reclen > len)
5410 break;
bellard8083a3e2003-03-24 23:12:16 +00005411 de->d_reclen = tswap16(reclen);
bellard8582a532007-11-11 23:11:36 +00005412 tswap64s((uint64_t *)&de->d_ino);
5413 tswap64s((uint64_t *)&de->d_off);
aurel326556a832008-10-13 21:08:17 +00005414 de = (struct linux_dirent64 *)((char *)de + reclen);
bellarddab2ed92003-03-22 15:23:14 +00005415 len -= reclen;
5416 }
5417 }
pbrook53a59602006-03-25 19:31:22 +00005418 unlock_user(dirp, arg2, ret);
bellarddab2ed92003-03-22 15:23:14 +00005419 }
5420 break;
bellarda541f292004-04-12 20:39:29 +00005421#endif /* TARGET_NR_getdents64 */
thse5febef2007-04-01 18:31:35 +00005422#ifdef TARGET_NR__newselect
bellard31e31b82003-02-18 22:55:36 +00005423 case TARGET_NR__newselect:
pbrook53a59602006-03-25 19:31:22 +00005424 ret = do_select(arg1, arg2, arg3, arg4, arg5);
bellard31e31b82003-02-18 22:55:36 +00005425 break;
thse5febef2007-04-01 18:31:35 +00005426#endif
5427#ifdef TARGET_NR_poll
bellard9de5e442003-03-23 16:49:39 +00005428 case TARGET_NR_poll:
5429 {
pbrook53a59602006-03-25 19:31:22 +00005430 struct target_pollfd *target_pfd;
bellard9de5e442003-03-23 16:49:39 +00005431 unsigned int nfds = arg2;
5432 int timeout = arg3;
5433 struct pollfd *pfd;
bellard7854b052003-03-29 17:22:23 +00005434 unsigned int i;
bellard9de5e442003-03-23 16:49:39 +00005435
bellard579a97f2007-11-11 14:26:47 +00005436 target_pfd = lock_user(VERIFY_WRITE, arg1, sizeof(struct target_pollfd) * nfds, 1);
5437 if (!target_pfd)
5438 goto efault;
bellard9de5e442003-03-23 16:49:39 +00005439 pfd = alloca(sizeof(struct pollfd) * nfds);
5440 for(i = 0; i < nfds; i++) {
bellard5cd43932003-03-29 16:54:36 +00005441 pfd[i].fd = tswap32(target_pfd[i].fd);
5442 pfd[i].events = tswap16(target_pfd[i].events);
bellard9de5e442003-03-23 16:49:39 +00005443 }
5444 ret = get_errno(poll(pfd, nfds, timeout));
5445 if (!is_error(ret)) {
5446 for(i = 0; i < nfds; i++) {
bellard5cd43932003-03-29 16:54:36 +00005447 target_pfd[i].revents = tswap16(pfd[i].revents);
bellard9de5e442003-03-23 16:49:39 +00005448 }
pbrook53a59602006-03-25 19:31:22 +00005449 ret += nfds * (sizeof(struct target_pollfd)
5450 - sizeof(struct pollfd));
bellard9de5e442003-03-23 16:49:39 +00005451 }
pbrook53a59602006-03-25 19:31:22 +00005452 unlock_user(target_pfd, arg1, ret);
bellard9de5e442003-03-23 16:49:39 +00005453 }
5454 break;
thse5febef2007-04-01 18:31:35 +00005455#endif
bellard31e31b82003-02-18 22:55:36 +00005456 case TARGET_NR_flock:
bellard9de5e442003-03-23 16:49:39 +00005457 /* NOTE: the flock constant seems to be the same for every
5458 Linux platform */
5459 ret = get_errno(flock(arg1, arg2));
bellard31e31b82003-02-18 22:55:36 +00005460 break;
5461 case TARGET_NR_readv:
5462 {
5463 int count = arg3;
bellard31e31b82003-02-18 22:55:36 +00005464 struct iovec *vec;
bellard31e31b82003-02-18 22:55:36 +00005465
5466 vec = alloca(count * sizeof(struct iovec));
bellard41df8412008-02-04 22:26:57 +00005467 if (lock_iovec(VERIFY_WRITE, vec, arg2, count, 0) < 0)
5468 goto efault;
bellard31e31b82003-02-18 22:55:36 +00005469 ret = get_errno(readv(arg1, vec, count));
pbrook53a59602006-03-25 19:31:22 +00005470 unlock_iovec(vec, arg2, count, 1);
bellard31e31b82003-02-18 22:55:36 +00005471 }
5472 break;
5473 case TARGET_NR_writev:
5474 {
5475 int count = arg3;
bellard31e31b82003-02-18 22:55:36 +00005476 struct iovec *vec;
bellard31e31b82003-02-18 22:55:36 +00005477
5478 vec = alloca(count * sizeof(struct iovec));
bellard41df8412008-02-04 22:26:57 +00005479 if (lock_iovec(VERIFY_READ, vec, arg2, count, 1) < 0)
5480 goto efault;
bellard31e31b82003-02-18 22:55:36 +00005481 ret = get_errno(writev(arg1, vec, count));
pbrook53a59602006-03-25 19:31:22 +00005482 unlock_iovec(vec, arg2, count, 0);
bellard31e31b82003-02-18 22:55:36 +00005483 }
5484 break;
5485 case TARGET_NR_getsid:
5486 ret = get_errno(getsid(arg1));
5487 break;
j_mayer7a3148a2007-04-05 07:13:51 +00005488#if defined(TARGET_NR_fdatasync) /* Not on alpha (osf_datasync ?) */
bellard31e31b82003-02-18 22:55:36 +00005489 case TARGET_NR_fdatasync:
bellard5cd43932003-03-29 16:54:36 +00005490 ret = get_errno(fdatasync(arg1));
5491 break;
j_mayer7a3148a2007-04-05 07:13:51 +00005492#endif
bellard31e31b82003-02-18 22:55:36 +00005493 case TARGET_NR__sysctl:
ths0da46a62007-10-20 20:23:07 +00005494 /* We don't implement this, but ENOTDIR is always a safe
bellard29e619b2004-09-13 21:41:04 +00005495 return value. */
ths0da46a62007-10-20 20:23:07 +00005496 ret = -TARGET_ENOTDIR;
5497 break;
bellard31e31b82003-02-18 22:55:36 +00005498 case TARGET_NR_sched_setparam:
bellard5cd43932003-03-29 16:54:36 +00005499 {
pbrook53a59602006-03-25 19:31:22 +00005500 struct sched_param *target_schp;
bellard5cd43932003-03-29 16:54:36 +00005501 struct sched_param schp;
pbrook53a59602006-03-25 19:31:22 +00005502
bellard579a97f2007-11-11 14:26:47 +00005503 if (!lock_user_struct(VERIFY_READ, target_schp, arg2, 1))
5504 goto efault;
bellard5cd43932003-03-29 16:54:36 +00005505 schp.sched_priority = tswap32(target_schp->sched_priority);
pbrook53a59602006-03-25 19:31:22 +00005506 unlock_user_struct(target_schp, arg2, 0);
bellard5cd43932003-03-29 16:54:36 +00005507 ret = get_errno(sched_setparam(arg1, &schp));
5508 }
5509 break;
bellard31e31b82003-02-18 22:55:36 +00005510 case TARGET_NR_sched_getparam:
bellard5cd43932003-03-29 16:54:36 +00005511 {
pbrook53a59602006-03-25 19:31:22 +00005512 struct sched_param *target_schp;
bellard5cd43932003-03-29 16:54:36 +00005513 struct sched_param schp;
5514 ret = get_errno(sched_getparam(arg1, &schp));
5515 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00005516 if (!lock_user_struct(VERIFY_WRITE, target_schp, arg2, 0))
5517 goto efault;
bellard5cd43932003-03-29 16:54:36 +00005518 target_schp->sched_priority = tswap32(schp.sched_priority);
pbrook53a59602006-03-25 19:31:22 +00005519 unlock_user_struct(target_schp, arg2, 1);
bellard5cd43932003-03-29 16:54:36 +00005520 }
5521 }
5522 break;
bellard31e31b82003-02-18 22:55:36 +00005523 case TARGET_NR_sched_setscheduler:
bellard5cd43932003-03-29 16:54:36 +00005524 {
pbrook53a59602006-03-25 19:31:22 +00005525 struct sched_param *target_schp;
bellard5cd43932003-03-29 16:54:36 +00005526 struct sched_param schp;
bellard579a97f2007-11-11 14:26:47 +00005527 if (!lock_user_struct(VERIFY_READ, target_schp, arg3, 1))
5528 goto efault;
bellard5cd43932003-03-29 16:54:36 +00005529 schp.sched_priority = tswap32(target_schp->sched_priority);
pbrook53a59602006-03-25 19:31:22 +00005530 unlock_user_struct(target_schp, arg3, 0);
bellard5cd43932003-03-29 16:54:36 +00005531 ret = get_errno(sched_setscheduler(arg1, arg2, &schp));
5532 }
5533 break;
bellard31e31b82003-02-18 22:55:36 +00005534 case TARGET_NR_sched_getscheduler:
bellard5cd43932003-03-29 16:54:36 +00005535 ret = get_errno(sched_getscheduler(arg1));
5536 break;
bellard31e31b82003-02-18 22:55:36 +00005537 case TARGET_NR_sched_yield:
5538 ret = get_errno(sched_yield());
5539 break;
5540 case TARGET_NR_sched_get_priority_max:
bellard5cd43932003-03-29 16:54:36 +00005541 ret = get_errno(sched_get_priority_max(arg1));
5542 break;
bellard31e31b82003-02-18 22:55:36 +00005543 case TARGET_NR_sched_get_priority_min:
bellard5cd43932003-03-29 16:54:36 +00005544 ret = get_errno(sched_get_priority_min(arg1));
5545 break;
bellard31e31b82003-02-18 22:55:36 +00005546 case TARGET_NR_sched_rr_get_interval:
bellard5cd43932003-03-29 16:54:36 +00005547 {
bellard5cd43932003-03-29 16:54:36 +00005548 struct timespec ts;
5549 ret = get_errno(sched_rr_get_interval(arg1, &ts));
5550 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00005551 host_to_target_timespec(arg2, &ts);
bellard5cd43932003-03-29 16:54:36 +00005552 }
5553 }
5554 break;
bellard31e31b82003-02-18 22:55:36 +00005555 case TARGET_NR_nanosleep:
bellard1b6b0292003-03-22 17:31:38 +00005556 {
bellard1b6b0292003-03-22 17:31:38 +00005557 struct timespec req, rem;
pbrook53a59602006-03-25 19:31:22 +00005558 target_to_host_timespec(&req, arg1);
bellard1b6b0292003-03-22 17:31:38 +00005559 ret = get_errno(nanosleep(&req, &rem));
pbrook53a59602006-03-25 19:31:22 +00005560 if (is_error(ret) && arg2) {
5561 host_to_target_timespec(arg2, &rem);
bellard1b6b0292003-03-22 17:31:38 +00005562 }
5563 }
5564 break;
thse5febef2007-04-01 18:31:35 +00005565#ifdef TARGET_NR_query_module
bellard31e31b82003-02-18 22:55:36 +00005566 case TARGET_NR_query_module:
bellard5cd43932003-03-29 16:54:36 +00005567 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00005568#endif
5569#ifdef TARGET_NR_nfsservctl
bellard31e31b82003-02-18 22:55:36 +00005570 case TARGET_NR_nfsservctl:
bellard5cd43932003-03-29 16:54:36 +00005571 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00005572#endif
bellard31e31b82003-02-18 22:55:36 +00005573 case TARGET_NR_prctl:
thse5574482007-02-11 20:03:13 +00005574 switch (arg1)
5575 {
5576 case PR_GET_PDEATHSIG:
5577 {
5578 int deathsig;
5579 ret = get_errno(prctl(arg1, &deathsig, arg3, arg4, arg5));
bellard2f619692007-11-16 10:46:05 +00005580 if (!is_error(ret) && arg2
5581 && put_user_ual(deathsig, arg2))
5582 goto efault;
thse5574482007-02-11 20:03:13 +00005583 }
5584 break;
5585 default:
5586 ret = get_errno(prctl(arg1, arg2, arg3, arg4, arg5));
5587 break;
5588 }
ths39b9aae2007-02-11 18:36:44 +00005589 break;
bellardd2fd1af2007-11-14 18:08:56 +00005590#ifdef TARGET_NR_arch_prctl
5591 case TARGET_NR_arch_prctl:
5592#if defined(TARGET_I386) && !defined(TARGET_ABI32)
5593 ret = do_arch_prctl(cpu_env, arg1, arg2);
5594 break;
5595#else
5596 goto unimplemented;
5597#endif
5598#endif
bellard67867302003-11-23 17:05:30 +00005599#ifdef TARGET_NR_pread
bellard31e31b82003-02-18 22:55:36 +00005600 case TARGET_NR_pread:
balroga4ae00b2008-09-20 03:14:14 +00005601#ifdef TARGET_ARM
5602 if (((CPUARMState *)cpu_env)->eabi)
5603 arg4 = arg5;
5604#endif
bellard579a97f2007-11-11 14:26:47 +00005605 if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
5606 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005607 ret = get_errno(pread(arg1, p, arg3, arg4));
5608 unlock_user(p, arg2, ret);
bellard206f0fa2003-05-14 19:01:56 +00005609 break;
bellard31e31b82003-02-18 22:55:36 +00005610 case TARGET_NR_pwrite:
balroga4ae00b2008-09-20 03:14:14 +00005611#ifdef TARGET_ARM
5612 if (((CPUARMState *)cpu_env)->eabi)
5613 arg4 = arg5;
5614#endif
bellard579a97f2007-11-11 14:26:47 +00005615 if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
5616 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005617 ret = get_errno(pwrite(arg1, p, arg3, arg4));
5618 unlock_user(p, arg2, 0);
bellard206f0fa2003-05-14 19:01:56 +00005619 break;
bellard67867302003-11-23 17:05:30 +00005620#endif
aurel32f2c7ba12008-03-28 22:32:06 +00005621#ifdef TARGET_NR_pread64
5622 case TARGET_NR_pread64:
5623 if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
5624 goto efault;
5625 ret = get_errno(pread64(arg1, p, arg3, target_offset64(arg4, arg5)));
5626 unlock_user(p, arg2, ret);
5627 break;
5628 case TARGET_NR_pwrite64:
5629 if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
5630 goto efault;
5631 ret = get_errno(pwrite64(arg1, p, arg3, target_offset64(arg4, arg5)));
5632 unlock_user(p, arg2, 0);
5633 break;
5634#endif
bellard31e31b82003-02-18 22:55:36 +00005635 case TARGET_NR_getcwd:
bellard579a97f2007-11-11 14:26:47 +00005636 if (!(p = lock_user(VERIFY_WRITE, arg1, arg2, 0)))
5637 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005638 ret = get_errno(sys_getcwd1(p, arg2));
5639 unlock_user(p, arg1, ret);
bellard31e31b82003-02-18 22:55:36 +00005640 break;
5641 case TARGET_NR_capget:
bellard5cd43932003-03-29 16:54:36 +00005642 goto unimplemented;
bellard31e31b82003-02-18 22:55:36 +00005643 case TARGET_NR_capset:
bellard5cd43932003-03-29 16:54:36 +00005644 goto unimplemented;
bellard31e31b82003-02-18 22:55:36 +00005645 case TARGET_NR_sigaltstack:
ths198a74d2007-09-27 16:44:32 +00005646#if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_MIPS) || \
5647 defined(TARGET_SPARC) || defined(TARGET_PPC) || defined(TARGET_ALPHA)
bellard579a97f2007-11-11 14:26:47 +00005648 ret = do_sigaltstack(arg1, arg2, get_sp_from_cpustate((CPUState *)cpu_env));
thsa04e1342007-09-27 13:57:58 +00005649 break;
5650#else
bellard5cd43932003-03-29 16:54:36 +00005651 goto unimplemented;
thsa04e1342007-09-27 13:57:58 +00005652#endif
bellard31e31b82003-02-18 22:55:36 +00005653 case TARGET_NR_sendfile:
bellard5cd43932003-03-29 16:54:36 +00005654 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00005655#ifdef TARGET_NR_getpmsg
bellard31e31b82003-02-18 22:55:36 +00005656 case TARGET_NR_getpmsg:
bellard5cd43932003-03-29 16:54:36 +00005657 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00005658#endif
5659#ifdef TARGET_NR_putpmsg
bellard31e31b82003-02-18 22:55:36 +00005660 case TARGET_NR_putpmsg:
bellard5cd43932003-03-29 16:54:36 +00005661 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00005662#endif
bellard048f6b42005-11-26 18:47:20 +00005663#ifdef TARGET_NR_vfork
bellard31e31b82003-02-18 22:55:36 +00005664 case TARGET_NR_vfork:
pbrookd865bab2008-06-07 22:12:17 +00005665 ret = get_errno(do_fork(cpu_env, CLONE_VFORK | CLONE_VM | SIGCHLD,
5666 0, 0, 0, 0));
bellard31e31b82003-02-18 22:55:36 +00005667 break;
bellard048f6b42005-11-26 18:47:20 +00005668#endif
bellardebc05482003-09-30 21:08:41 +00005669#ifdef TARGET_NR_ugetrlimit
bellard31e31b82003-02-18 22:55:36 +00005670 case TARGET_NR_ugetrlimit:
bellard728584b2003-04-29 20:43:36 +00005671 {
5672 struct rlimit rlim;
5673 ret = get_errno(getrlimit(arg1, &rlim));
5674 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00005675 struct target_rlimit *target_rlim;
bellard579a97f2007-11-11 14:26:47 +00005676 if (!lock_user_struct(VERIFY_WRITE, target_rlim, arg2, 0))
5677 goto efault;
bellard728584b2003-04-29 20:43:36 +00005678 target_rlim->rlim_cur = tswapl(rlim.rlim_cur);
5679 target_rlim->rlim_max = tswapl(rlim.rlim_max);
pbrook53a59602006-03-25 19:31:22 +00005680 unlock_user_struct(target_rlim, arg2, 1);
bellard728584b2003-04-29 20:43:36 +00005681 }
5682 break;
5683 }
bellardebc05482003-09-30 21:08:41 +00005684#endif
bellarda315a142005-01-30 22:59:18 +00005685#ifdef TARGET_NR_truncate64
bellard31e31b82003-02-18 22:55:36 +00005686 case TARGET_NR_truncate64:
bellard579a97f2007-11-11 14:26:47 +00005687 if (!(p = lock_user_string(arg1)))
5688 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005689 ret = target_truncate64(cpu_env, p, arg2, arg3, arg4);
5690 unlock_user(p, arg1, 0);
bellard667f38b2005-07-23 14:46:27 +00005691 break;
bellarda315a142005-01-30 22:59:18 +00005692#endif
5693#ifdef TARGET_NR_ftruncate64
bellard31e31b82003-02-18 22:55:36 +00005694 case TARGET_NR_ftruncate64:
pbrookce4defa2006-02-09 16:49:55 +00005695 ret = target_ftruncate64(cpu_env, arg1, arg2, arg3, arg4);
bellard667f38b2005-07-23 14:46:27 +00005696 break;
bellarda315a142005-01-30 22:59:18 +00005697#endif
5698#ifdef TARGET_NR_stat64
bellard31e31b82003-02-18 22:55:36 +00005699 case TARGET_NR_stat64:
bellard579a97f2007-11-11 14:26:47 +00005700 if (!(p = lock_user_string(arg1)))
5701 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005702 ret = get_errno(stat(path(p), &st));
5703 unlock_user(p, arg1, 0);
balrog6a24a772008-09-20 02:23:36 +00005704 if (!is_error(ret))
5705 ret = host_to_target_stat64(cpu_env, arg2, &st);
5706 break;
bellarda315a142005-01-30 22:59:18 +00005707#endif
5708#ifdef TARGET_NR_lstat64
bellard31e31b82003-02-18 22:55:36 +00005709 case TARGET_NR_lstat64:
bellard579a97f2007-11-11 14:26:47 +00005710 if (!(p = lock_user_string(arg1)))
5711 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005712 ret = get_errno(lstat(path(p), &st));
5713 unlock_user(p, arg1, 0);
balrog6a24a772008-09-20 02:23:36 +00005714 if (!is_error(ret))
5715 ret = host_to_target_stat64(cpu_env, arg2, &st);
5716 break;
bellarda315a142005-01-30 22:59:18 +00005717#endif
5718#ifdef TARGET_NR_fstat64
bellard31e31b82003-02-18 22:55:36 +00005719 case TARGET_NR_fstat64:
balrog6a24a772008-09-20 02:23:36 +00005720 ret = get_errno(fstat(arg1, &st));
5721 if (!is_error(ret))
5722 ret = host_to_target_stat64(cpu_env, arg2, &st);
5723 break;
bellardec86b0f2003-04-11 00:15:04 +00005724#endif
aurel329d33b762009-04-08 23:07:05 +00005725#if (defined(TARGET_NR_fstatat64) || defined(TARGET_NR_newfstatat)) && \
5726 (defined(__NR_fstatat64) || defined(__NR_newfstatat))
5727#ifdef TARGET_NR_fstatat64
balrog6a24a772008-09-20 02:23:36 +00005728 case TARGET_NR_fstatat64:
aurel329d33b762009-04-08 23:07:05 +00005729#endif
5730#ifdef TARGET_NR_newfstatat
5731 case TARGET_NR_newfstatat:
5732#endif
balrog6a24a772008-09-20 02:23:36 +00005733 if (!(p = lock_user_string(arg2)))
5734 goto efault;
aurel329d33b762009-04-08 23:07:05 +00005735#ifdef __NR_fstatat64
balrog6a24a772008-09-20 02:23:36 +00005736 ret = get_errno(sys_fstatat64(arg1, path(p), &st, arg4));
aurel329d33b762009-04-08 23:07:05 +00005737#else
5738 ret = get_errno(sys_newfstatat(arg1, path(p), &st, arg4));
5739#endif
balrog6a24a772008-09-20 02:23:36 +00005740 if (!is_error(ret))
5741 ret = host_to_target_stat64(cpu_env, arg3, &st);
bellard60cd49d2003-03-16 22:53:56 +00005742 break;
bellarda315a142005-01-30 22:59:18 +00005743#endif
bellard67867302003-11-23 17:05:30 +00005744#ifdef USE_UID16
5745 case TARGET_NR_lchown:
bellard579a97f2007-11-11 14:26:47 +00005746 if (!(p = lock_user_string(arg1)))
5747 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005748 ret = get_errno(lchown(p, low2highuid(arg2), low2highgid(arg3)));
5749 unlock_user(p, arg1, 0);
bellard67867302003-11-23 17:05:30 +00005750 break;
5751 case TARGET_NR_getuid:
5752 ret = get_errno(high2lowuid(getuid()));
5753 break;
5754 case TARGET_NR_getgid:
5755 ret = get_errno(high2lowgid(getgid()));
5756 break;
5757 case TARGET_NR_geteuid:
5758 ret = get_errno(high2lowuid(geteuid()));
5759 break;
5760 case TARGET_NR_getegid:
5761 ret = get_errno(high2lowgid(getegid()));
5762 break;
5763 case TARGET_NR_setreuid:
5764 ret = get_errno(setreuid(low2highuid(arg1), low2highuid(arg2)));
5765 break;
5766 case TARGET_NR_setregid:
5767 ret = get_errno(setregid(low2highgid(arg1), low2highgid(arg2)));
5768 break;
5769 case TARGET_NR_getgroups:
5770 {
5771 int gidsetsize = arg1;
pbrook53a59602006-03-25 19:31:22 +00005772 uint16_t *target_grouplist;
bellard67867302003-11-23 17:05:30 +00005773 gid_t *grouplist;
5774 int i;
5775
5776 grouplist = alloca(gidsetsize * sizeof(gid_t));
5777 ret = get_errno(getgroups(gidsetsize, grouplist));
balrogcb3bc232008-09-20 02:08:13 +00005778 if (gidsetsize == 0)
5779 break;
bellard67867302003-11-23 17:05:30 +00005780 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00005781 target_grouplist = lock_user(VERIFY_WRITE, arg2, gidsetsize * 2, 0);
5782 if (!target_grouplist)
5783 goto efault;
balroga2155fc2008-09-20 02:12:08 +00005784 for(i = 0;i < ret; i++)
bellard67867302003-11-23 17:05:30 +00005785 target_grouplist[i] = tswap16(grouplist[i]);
pbrook53a59602006-03-25 19:31:22 +00005786 unlock_user(target_grouplist, arg2, gidsetsize * 2);
bellard67867302003-11-23 17:05:30 +00005787 }
5788 }
5789 break;
5790 case TARGET_NR_setgroups:
5791 {
5792 int gidsetsize = arg1;
pbrook53a59602006-03-25 19:31:22 +00005793 uint16_t *target_grouplist;
bellard67867302003-11-23 17:05:30 +00005794 gid_t *grouplist;
5795 int i;
5796
5797 grouplist = alloca(gidsetsize * sizeof(gid_t));
bellard579a97f2007-11-11 14:26:47 +00005798 target_grouplist = lock_user(VERIFY_READ, arg2, gidsetsize * 2, 1);
5799 if (!target_grouplist) {
5800 ret = -TARGET_EFAULT;
5801 goto fail;
5802 }
bellard67867302003-11-23 17:05:30 +00005803 for(i = 0;i < gidsetsize; i++)
5804 grouplist[i] = tswap16(target_grouplist[i]);
pbrook53a59602006-03-25 19:31:22 +00005805 unlock_user(target_grouplist, arg2, 0);
bellard67867302003-11-23 17:05:30 +00005806 ret = get_errno(setgroups(gidsetsize, grouplist));
5807 }
5808 break;
5809 case TARGET_NR_fchown:
5810 ret = get_errno(fchown(arg1, low2highuid(arg2), low2highgid(arg3)));
5811 break;
thsccfa72b2007-09-24 09:23:34 +00005812#if defined(TARGET_NR_fchownat) && defined(__NR_fchownat)
5813 case TARGET_NR_fchownat:
bellard579a97f2007-11-11 14:26:47 +00005814 if (!(p = lock_user_string(arg2)))
5815 goto efault;
5816 ret = get_errno(sys_fchownat(arg1, p, low2highuid(arg3), low2highgid(arg4), arg5));
5817 unlock_user(p, arg2, 0);
thsccfa72b2007-09-24 09:23:34 +00005818 break;
5819#endif
bellard67867302003-11-23 17:05:30 +00005820#ifdef TARGET_NR_setresuid
5821 case TARGET_NR_setresuid:
ths5fafdf22007-09-16 21:08:06 +00005822 ret = get_errno(setresuid(low2highuid(arg1),
5823 low2highuid(arg2),
bellard67867302003-11-23 17:05:30 +00005824 low2highuid(arg3)));
5825 break;
5826#endif
5827#ifdef TARGET_NR_getresuid
5828 case TARGET_NR_getresuid:
5829 {
pbrook53a59602006-03-25 19:31:22 +00005830 uid_t ruid, euid, suid;
bellard67867302003-11-23 17:05:30 +00005831 ret = get_errno(getresuid(&ruid, &euid, &suid));
5832 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +00005833 if (put_user_u16(high2lowuid(ruid), arg1)
5834 || put_user_u16(high2lowuid(euid), arg2)
5835 || put_user_u16(high2lowuid(suid), arg3))
5836 goto efault;
bellard67867302003-11-23 17:05:30 +00005837 }
5838 }
5839 break;
5840#endif
5841#ifdef TARGET_NR_getresgid
5842 case TARGET_NR_setresgid:
ths5fafdf22007-09-16 21:08:06 +00005843 ret = get_errno(setresgid(low2highgid(arg1),
5844 low2highgid(arg2),
bellard67867302003-11-23 17:05:30 +00005845 low2highgid(arg3)));
5846 break;
5847#endif
5848#ifdef TARGET_NR_getresgid
5849 case TARGET_NR_getresgid:
5850 {
pbrook53a59602006-03-25 19:31:22 +00005851 gid_t rgid, egid, sgid;
bellard67867302003-11-23 17:05:30 +00005852 ret = get_errno(getresgid(&rgid, &egid, &sgid));
5853 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +00005854 if (put_user_u16(high2lowgid(rgid), arg1)
5855 || put_user_u16(high2lowgid(egid), arg2)
5856 || put_user_u16(high2lowgid(sgid), arg3))
5857 goto efault;
bellard67867302003-11-23 17:05:30 +00005858 }
5859 }
5860 break;
5861#endif
5862 case TARGET_NR_chown:
bellard579a97f2007-11-11 14:26:47 +00005863 if (!(p = lock_user_string(arg1)))
5864 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005865 ret = get_errno(chown(p, low2highuid(arg2), low2highgid(arg3)));
5866 unlock_user(p, arg1, 0);
bellard67867302003-11-23 17:05:30 +00005867 break;
5868 case TARGET_NR_setuid:
5869 ret = get_errno(setuid(low2highuid(arg1)));
5870 break;
5871 case TARGET_NR_setgid:
5872 ret = get_errno(setgid(low2highgid(arg1)));
5873 break;
5874 case TARGET_NR_setfsuid:
5875 ret = get_errno(setfsuid(arg1));
5876 break;
5877 case TARGET_NR_setfsgid:
5878 ret = get_errno(setfsgid(arg1));
5879 break;
5880#endif /* USE_UID16 */
5881
bellarda315a142005-01-30 22:59:18 +00005882#ifdef TARGET_NR_lchown32
bellard31e31b82003-02-18 22:55:36 +00005883 case TARGET_NR_lchown32:
bellard579a97f2007-11-11 14:26:47 +00005884 if (!(p = lock_user_string(arg1)))
5885 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005886 ret = get_errno(lchown(p, arg2, arg3));
5887 unlock_user(p, arg1, 0);
bellardb03c60f2003-03-23 17:19:56 +00005888 break;
bellarda315a142005-01-30 22:59:18 +00005889#endif
5890#ifdef TARGET_NR_getuid32
bellard31e31b82003-02-18 22:55:36 +00005891 case TARGET_NR_getuid32:
bellardb03c60f2003-03-23 17:19:56 +00005892 ret = get_errno(getuid());
5893 break;
bellarda315a142005-01-30 22:59:18 +00005894#endif
aurel3264b4d282008-11-14 17:20:15 +00005895
5896#if defined(TARGET_NR_getxuid) && defined(TARGET_ALPHA)
5897 /* Alpha specific */
5898 case TARGET_NR_getxuid:
5899 {
5900 uid_t euid;
5901 euid=geteuid();
5902 ((CPUAlphaState *)cpu_env)->ir[IR_A4]=euid;
5903 }
5904 ret = get_errno(getuid());
5905 break;
5906#endif
5907#if defined(TARGET_NR_getxgid) && defined(TARGET_ALPHA)
5908 /* Alpha specific */
5909 case TARGET_NR_getxgid:
5910 {
5911 uid_t egid;
5912 egid=getegid();
5913 ((CPUAlphaState *)cpu_env)->ir[IR_A4]=egid;
5914 }
5915 ret = get_errno(getgid());
5916 break;
5917#endif
5918
bellarda315a142005-01-30 22:59:18 +00005919#ifdef TARGET_NR_getgid32
bellard31e31b82003-02-18 22:55:36 +00005920 case TARGET_NR_getgid32:
bellardb03c60f2003-03-23 17:19:56 +00005921 ret = get_errno(getgid());
5922 break;
bellarda315a142005-01-30 22:59:18 +00005923#endif
5924#ifdef TARGET_NR_geteuid32
bellard31e31b82003-02-18 22:55:36 +00005925 case TARGET_NR_geteuid32:
bellardb03c60f2003-03-23 17:19:56 +00005926 ret = get_errno(geteuid());
5927 break;
bellarda315a142005-01-30 22:59:18 +00005928#endif
5929#ifdef TARGET_NR_getegid32
bellard31e31b82003-02-18 22:55:36 +00005930 case TARGET_NR_getegid32:
bellardb03c60f2003-03-23 17:19:56 +00005931 ret = get_errno(getegid());
5932 break;
bellarda315a142005-01-30 22:59:18 +00005933#endif
5934#ifdef TARGET_NR_setreuid32
bellard31e31b82003-02-18 22:55:36 +00005935 case TARGET_NR_setreuid32:
bellardb03c60f2003-03-23 17:19:56 +00005936 ret = get_errno(setreuid(arg1, arg2));
5937 break;
bellarda315a142005-01-30 22:59:18 +00005938#endif
5939#ifdef TARGET_NR_setregid32
bellard31e31b82003-02-18 22:55:36 +00005940 case TARGET_NR_setregid32:
bellardb03c60f2003-03-23 17:19:56 +00005941 ret = get_errno(setregid(arg1, arg2));
5942 break;
bellarda315a142005-01-30 22:59:18 +00005943#endif
5944#ifdef TARGET_NR_getgroups32
bellard31e31b82003-02-18 22:55:36 +00005945 case TARGET_NR_getgroups32:
bellard99c475a2005-01-31 20:45:13 +00005946 {
5947 int gidsetsize = arg1;
pbrook53a59602006-03-25 19:31:22 +00005948 uint32_t *target_grouplist;
bellard99c475a2005-01-31 20:45:13 +00005949 gid_t *grouplist;
5950 int i;
5951
5952 grouplist = alloca(gidsetsize * sizeof(gid_t));
5953 ret = get_errno(getgroups(gidsetsize, grouplist));
balrogcb3bc232008-09-20 02:08:13 +00005954 if (gidsetsize == 0)
5955 break;
bellard99c475a2005-01-31 20:45:13 +00005956 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00005957 target_grouplist = lock_user(VERIFY_WRITE, arg2, gidsetsize * 4, 0);
5958 if (!target_grouplist) {
5959 ret = -TARGET_EFAULT;
5960 goto fail;
5961 }
balroga2155fc2008-09-20 02:12:08 +00005962 for(i = 0;i < ret; i++)
pbrook53a59602006-03-25 19:31:22 +00005963 target_grouplist[i] = tswap32(grouplist[i]);
5964 unlock_user(target_grouplist, arg2, gidsetsize * 4);
bellard99c475a2005-01-31 20:45:13 +00005965 }
5966 }
5967 break;
bellarda315a142005-01-30 22:59:18 +00005968#endif
5969#ifdef TARGET_NR_setgroups32
bellard31e31b82003-02-18 22:55:36 +00005970 case TARGET_NR_setgroups32:
bellard99c475a2005-01-31 20:45:13 +00005971 {
5972 int gidsetsize = arg1;
pbrook53a59602006-03-25 19:31:22 +00005973 uint32_t *target_grouplist;
bellard99c475a2005-01-31 20:45:13 +00005974 gid_t *grouplist;
5975 int i;
ths3b46e622007-09-17 08:09:54 +00005976
bellard99c475a2005-01-31 20:45:13 +00005977 grouplist = alloca(gidsetsize * sizeof(gid_t));
bellard579a97f2007-11-11 14:26:47 +00005978 target_grouplist = lock_user(VERIFY_READ, arg2, gidsetsize * 4, 1);
5979 if (!target_grouplist) {
5980 ret = -TARGET_EFAULT;
5981 goto fail;
5982 }
bellard99c475a2005-01-31 20:45:13 +00005983 for(i = 0;i < gidsetsize; i++)
pbrook53a59602006-03-25 19:31:22 +00005984 grouplist[i] = tswap32(target_grouplist[i]);
5985 unlock_user(target_grouplist, arg2, 0);
bellard99c475a2005-01-31 20:45:13 +00005986 ret = get_errno(setgroups(gidsetsize, grouplist));
5987 }
5988 break;
bellarda315a142005-01-30 22:59:18 +00005989#endif
5990#ifdef TARGET_NR_fchown32
bellard31e31b82003-02-18 22:55:36 +00005991 case TARGET_NR_fchown32:
bellardb03c60f2003-03-23 17:19:56 +00005992 ret = get_errno(fchown(arg1, arg2, arg3));
5993 break;
bellarda315a142005-01-30 22:59:18 +00005994#endif
5995#ifdef TARGET_NR_setresuid32
bellard31e31b82003-02-18 22:55:36 +00005996 case TARGET_NR_setresuid32:
bellardb03c60f2003-03-23 17:19:56 +00005997 ret = get_errno(setresuid(arg1, arg2, arg3));
5998 break;
bellarda315a142005-01-30 22:59:18 +00005999#endif
6000#ifdef TARGET_NR_getresuid32
bellard31e31b82003-02-18 22:55:36 +00006001 case TARGET_NR_getresuid32:
bellardb03c60f2003-03-23 17:19:56 +00006002 {
pbrook53a59602006-03-25 19:31:22 +00006003 uid_t ruid, euid, suid;
bellardb03c60f2003-03-23 17:19:56 +00006004 ret = get_errno(getresuid(&ruid, &euid, &suid));
6005 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +00006006 if (put_user_u32(ruid, arg1)
6007 || put_user_u32(euid, arg2)
6008 || put_user_u32(suid, arg3))
6009 goto efault;
bellardb03c60f2003-03-23 17:19:56 +00006010 }
6011 }
6012 break;
bellarda315a142005-01-30 22:59:18 +00006013#endif
6014#ifdef TARGET_NR_setresgid32
bellard31e31b82003-02-18 22:55:36 +00006015 case TARGET_NR_setresgid32:
bellardb03c60f2003-03-23 17:19:56 +00006016 ret = get_errno(setresgid(arg1, arg2, arg3));
6017 break;
bellarda315a142005-01-30 22:59:18 +00006018#endif
6019#ifdef TARGET_NR_getresgid32
bellard31e31b82003-02-18 22:55:36 +00006020 case TARGET_NR_getresgid32:
bellardb03c60f2003-03-23 17:19:56 +00006021 {
pbrook53a59602006-03-25 19:31:22 +00006022 gid_t rgid, egid, sgid;
bellardb03c60f2003-03-23 17:19:56 +00006023 ret = get_errno(getresgid(&rgid, &egid, &sgid));
6024 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +00006025 if (put_user_u32(rgid, arg1)
6026 || put_user_u32(egid, arg2)
6027 || put_user_u32(sgid, arg3))
6028 goto efault;
bellardb03c60f2003-03-23 17:19:56 +00006029 }
6030 }
6031 break;
bellarda315a142005-01-30 22:59:18 +00006032#endif
6033#ifdef TARGET_NR_chown32
bellard31e31b82003-02-18 22:55:36 +00006034 case TARGET_NR_chown32:
bellard579a97f2007-11-11 14:26:47 +00006035 if (!(p = lock_user_string(arg1)))
6036 goto efault;
pbrook53a59602006-03-25 19:31:22 +00006037 ret = get_errno(chown(p, arg2, arg3));
6038 unlock_user(p, arg1, 0);
bellardb03c60f2003-03-23 17:19:56 +00006039 break;
bellarda315a142005-01-30 22:59:18 +00006040#endif
6041#ifdef TARGET_NR_setuid32
bellard31e31b82003-02-18 22:55:36 +00006042 case TARGET_NR_setuid32:
bellardb03c60f2003-03-23 17:19:56 +00006043 ret = get_errno(setuid(arg1));
6044 break;
bellarda315a142005-01-30 22:59:18 +00006045#endif
6046#ifdef TARGET_NR_setgid32
bellard31e31b82003-02-18 22:55:36 +00006047 case TARGET_NR_setgid32:
bellardb03c60f2003-03-23 17:19:56 +00006048 ret = get_errno(setgid(arg1));
6049 break;
bellarda315a142005-01-30 22:59:18 +00006050#endif
6051#ifdef TARGET_NR_setfsuid32
bellard31e31b82003-02-18 22:55:36 +00006052 case TARGET_NR_setfsuid32:
bellardb03c60f2003-03-23 17:19:56 +00006053 ret = get_errno(setfsuid(arg1));
6054 break;
bellarda315a142005-01-30 22:59:18 +00006055#endif
6056#ifdef TARGET_NR_setfsgid32
bellard31e31b82003-02-18 22:55:36 +00006057 case TARGET_NR_setfsgid32:
bellardb03c60f2003-03-23 17:19:56 +00006058 ret = get_errno(setfsgid(arg1));
6059 break;
bellarda315a142005-01-30 22:59:18 +00006060#endif
bellard67867302003-11-23 17:05:30 +00006061
bellard31e31b82003-02-18 22:55:36 +00006062 case TARGET_NR_pivot_root:
bellardb03c60f2003-03-23 17:19:56 +00006063 goto unimplemented;
bellardffa65c32004-01-04 23:57:22 +00006064#ifdef TARGET_NR_mincore
bellard31e31b82003-02-18 22:55:36 +00006065 case TARGET_NR_mincore:
aurel3204bb9ac2008-10-01 21:46:41 +00006066 {
6067 void *a;
6068 ret = -TARGET_EFAULT;
6069 if (!(a = lock_user(VERIFY_READ, arg1,arg2, 0)))
6070 goto efault;
6071 if (!(p = lock_user_string(arg3)))
6072 goto mincore_fail;
6073 ret = get_errno(mincore(a, arg2, p));
6074 unlock_user(p, arg3, ret);
6075 mincore_fail:
6076 unlock_user(a, arg1, 0);
6077 }
6078 break;
bellardffa65c32004-01-04 23:57:22 +00006079#endif
aurel32408321b2008-10-01 21:46:32 +00006080#ifdef TARGET_NR_arm_fadvise64_64
6081 case TARGET_NR_arm_fadvise64_64:
6082 {
6083 /*
6084 * arm_fadvise64_64 looks like fadvise64_64 but
6085 * with different argument order
6086 */
6087 abi_long temp;
6088 temp = arg3;
6089 arg3 = arg4;
6090 arg4 = temp;
6091 }
6092#endif
6093#if defined(TARGET_NR_fadvise64_64) || defined(TARGET_NR_arm_fadvise64_64)
6094#ifdef TARGET_NR_fadvise64_64
6095 case TARGET_NR_fadvise64_64:
6096#endif
6097 /* This is a hint, so ignoring and returning success is ok. */
6098 ret = get_errno(0);
6099 break;
6100#endif
bellardffa65c32004-01-04 23:57:22 +00006101#ifdef TARGET_NR_madvise
bellard31e31b82003-02-18 22:55:36 +00006102 case TARGET_NR_madvise:
pbrook24836682006-04-16 14:14:53 +00006103 /* A straight passthrough may not be safe because qemu sometimes
6104 turns private flie-backed mappings into anonymous mappings.
6105 This will break MADV_DONTNEED.
6106 This is a hint, so ignoring and returning success is ok. */
6107 ret = get_errno(0);
6108 break;
bellardffa65c32004-01-04 23:57:22 +00006109#endif
blueswir1992f48a2007-10-14 16:27:31 +00006110#if TARGET_ABI_BITS == 32
bellard31e31b82003-02-18 22:55:36 +00006111 case TARGET_NR_fcntl64:
bellard77e46722003-04-29 20:39:06 +00006112 {
thsb1e341e2007-03-20 21:50:52 +00006113 int cmd;
bellard77e46722003-04-29 20:39:06 +00006114 struct flock64 fl;
pbrook53a59602006-03-25 19:31:22 +00006115 struct target_flock64 *target_fl;
pbrookce4defa2006-02-09 16:49:55 +00006116#ifdef TARGET_ARM
pbrook53a59602006-03-25 19:31:22 +00006117 struct target_eabi_flock64 *target_efl;
pbrookce4defa2006-02-09 16:49:55 +00006118#endif
bellard77e46722003-04-29 20:39:06 +00006119
thsb1e341e2007-03-20 21:50:52 +00006120 switch(arg2){
6121 case TARGET_F_GETLK64:
6122 cmd = F_GETLK64;
thsa7222582007-03-22 15:08:55 +00006123 break;
thsb1e341e2007-03-20 21:50:52 +00006124 case TARGET_F_SETLK64:
6125 cmd = F_SETLK64;
thsa7222582007-03-22 15:08:55 +00006126 break;
thsb1e341e2007-03-20 21:50:52 +00006127 case TARGET_F_SETLKW64:
6128 cmd = F_SETLK64;
thsa7222582007-03-22 15:08:55 +00006129 break;
thsb1e341e2007-03-20 21:50:52 +00006130 default:
6131 cmd = arg2;
thsa7222582007-03-22 15:08:55 +00006132 break;
thsb1e341e2007-03-20 21:50:52 +00006133 }
6134
bellard60cd49d2003-03-16 22:53:56 +00006135 switch(arg2) {
thsb1e341e2007-03-20 21:50:52 +00006136 case TARGET_F_GETLK64:
ths58134272007-03-31 18:59:32 +00006137#ifdef TARGET_ARM
6138 if (((CPUARMState *)cpu_env)->eabi) {
bellard9ee1fa22007-11-11 15:11:19 +00006139 if (!lock_user_struct(VERIFY_READ, target_efl, arg3, 1))
6140 goto efault;
ths58134272007-03-31 18:59:32 +00006141 fl.l_type = tswap16(target_efl->l_type);
6142 fl.l_whence = tswap16(target_efl->l_whence);
6143 fl.l_start = tswap64(target_efl->l_start);
6144 fl.l_len = tswap64(target_efl->l_len);
6145 fl.l_pid = tswapl(target_efl->l_pid);
6146 unlock_user_struct(target_efl, arg3, 0);
6147 } else
6148#endif
6149 {
bellard9ee1fa22007-11-11 15:11:19 +00006150 if (!lock_user_struct(VERIFY_READ, target_fl, arg3, 1))
6151 goto efault;
ths58134272007-03-31 18:59:32 +00006152 fl.l_type = tswap16(target_fl->l_type);
6153 fl.l_whence = tswap16(target_fl->l_whence);
6154 fl.l_start = tswap64(target_fl->l_start);
6155 fl.l_len = tswap64(target_fl->l_len);
6156 fl.l_pid = tswapl(target_fl->l_pid);
6157 unlock_user_struct(target_fl, arg3, 0);
6158 }
thsb1e341e2007-03-20 21:50:52 +00006159 ret = get_errno(fcntl(arg1, cmd, &fl));
bellard77e46722003-04-29 20:39:06 +00006160 if (ret == 0) {
pbrookce4defa2006-02-09 16:49:55 +00006161#ifdef TARGET_ARM
6162 if (((CPUARMState *)cpu_env)->eabi) {
bellard9ee1fa22007-11-11 15:11:19 +00006163 if (!lock_user_struct(VERIFY_WRITE, target_efl, arg3, 0))
6164 goto efault;
pbrookce4defa2006-02-09 16:49:55 +00006165 target_efl->l_type = tswap16(fl.l_type);
6166 target_efl->l_whence = tswap16(fl.l_whence);
6167 target_efl->l_start = tswap64(fl.l_start);
6168 target_efl->l_len = tswap64(fl.l_len);
6169 target_efl->l_pid = tswapl(fl.l_pid);
pbrook53a59602006-03-25 19:31:22 +00006170 unlock_user_struct(target_efl, arg3, 1);
pbrookce4defa2006-02-09 16:49:55 +00006171 } else
6172#endif
6173 {
bellard9ee1fa22007-11-11 15:11:19 +00006174 if (!lock_user_struct(VERIFY_WRITE, target_fl, arg3, 0))
6175 goto efault;
pbrookce4defa2006-02-09 16:49:55 +00006176 target_fl->l_type = tswap16(fl.l_type);
6177 target_fl->l_whence = tswap16(fl.l_whence);
6178 target_fl->l_start = tswap64(fl.l_start);
6179 target_fl->l_len = tswap64(fl.l_len);
6180 target_fl->l_pid = tswapl(fl.l_pid);
pbrook53a59602006-03-25 19:31:22 +00006181 unlock_user_struct(target_fl, arg3, 1);
pbrookce4defa2006-02-09 16:49:55 +00006182 }
bellard77e46722003-04-29 20:39:06 +00006183 }
6184 break;
6185
thsb1e341e2007-03-20 21:50:52 +00006186 case TARGET_F_SETLK64:
6187 case TARGET_F_SETLKW64:
pbrookce4defa2006-02-09 16:49:55 +00006188#ifdef TARGET_ARM
6189 if (((CPUARMState *)cpu_env)->eabi) {
bellard9ee1fa22007-11-11 15:11:19 +00006190 if (!lock_user_struct(VERIFY_READ, target_efl, arg3, 1))
6191 goto efault;
pbrookce4defa2006-02-09 16:49:55 +00006192 fl.l_type = tswap16(target_efl->l_type);
6193 fl.l_whence = tswap16(target_efl->l_whence);
6194 fl.l_start = tswap64(target_efl->l_start);
6195 fl.l_len = tswap64(target_efl->l_len);
6196 fl.l_pid = tswapl(target_efl->l_pid);
pbrook53a59602006-03-25 19:31:22 +00006197 unlock_user_struct(target_efl, arg3, 0);
pbrookce4defa2006-02-09 16:49:55 +00006198 } else
6199#endif
6200 {
bellard9ee1fa22007-11-11 15:11:19 +00006201 if (!lock_user_struct(VERIFY_READ, target_fl, arg3, 1))
6202 goto efault;
pbrookce4defa2006-02-09 16:49:55 +00006203 fl.l_type = tswap16(target_fl->l_type);
6204 fl.l_whence = tswap16(target_fl->l_whence);
6205 fl.l_start = tswap64(target_fl->l_start);
6206 fl.l_len = tswap64(target_fl->l_len);
6207 fl.l_pid = tswapl(target_fl->l_pid);
pbrook53a59602006-03-25 19:31:22 +00006208 unlock_user_struct(target_fl, arg3, 0);
pbrookce4defa2006-02-09 16:49:55 +00006209 }
thsb1e341e2007-03-20 21:50:52 +00006210 ret = get_errno(fcntl(arg1, cmd, &fl));
bellard77e46722003-04-29 20:39:06 +00006211 break;
bellard60cd49d2003-03-16 22:53:56 +00006212 default:
bellard9ee1fa22007-11-11 15:11:19 +00006213 ret = do_fcntl(arg1, cmd, arg3);
bellard60cd49d2003-03-16 22:53:56 +00006214 break;
6215 }
bellard77e46722003-04-29 20:39:06 +00006216 break;
6217 }
bellard60cd49d2003-03-16 22:53:56 +00006218#endif
ths7d600c82006-12-08 01:32:58 +00006219#ifdef TARGET_NR_cacheflush
6220 case TARGET_NR_cacheflush:
6221 /* self-modifying code is handled automatically, so nothing needed */
6222 ret = 0;
6223 break;
6224#endif
bellardebc05482003-09-30 21:08:41 +00006225#ifdef TARGET_NR_security
bellard31e31b82003-02-18 22:55:36 +00006226 case TARGET_NR_security:
6227 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00006228#endif
bellardc573ff62004-01-04 15:51:36 +00006229#ifdef TARGET_NR_getpagesize
6230 case TARGET_NR_getpagesize:
6231 ret = TARGET_PAGE_SIZE;
6232 break;
6233#endif
bellard31e31b82003-02-18 22:55:36 +00006234 case TARGET_NR_gettid:
6235 ret = get_errno(gettid());
6236 break;
thse5febef2007-04-01 18:31:35 +00006237#ifdef TARGET_NR_readahead
bellard31e31b82003-02-18 22:55:36 +00006238 case TARGET_NR_readahead:
aurel322054ac92008-10-13 21:08:07 +00006239#if TARGET_ABI_BITS == 32
6240#ifdef TARGET_ARM
6241 if (((CPUARMState *)cpu_env)->eabi)
6242 {
6243 arg2 = arg3;
6244 arg3 = arg4;
6245 arg4 = arg5;
6246 }
6247#endif
6248 ret = get_errno(readahead(arg1, ((off64_t)arg3 << 32) | arg2, arg4));
6249#else
6250 ret = get_errno(readahead(arg1, arg2, arg3));
6251#endif
6252 break;
thse5febef2007-04-01 18:31:35 +00006253#endif
bellardebc05482003-09-30 21:08:41 +00006254#ifdef TARGET_NR_setxattr
bellard31e31b82003-02-18 22:55:36 +00006255 case TARGET_NR_setxattr:
6256 case TARGET_NR_lsetxattr:
6257 case TARGET_NR_fsetxattr:
6258 case TARGET_NR_getxattr:
6259 case TARGET_NR_lgetxattr:
6260 case TARGET_NR_fgetxattr:
6261 case TARGET_NR_listxattr:
6262 case TARGET_NR_llistxattr:
6263 case TARGET_NR_flistxattr:
6264 case TARGET_NR_removexattr:
6265 case TARGET_NR_lremovexattr:
6266 case TARGET_NR_fremovexattr:
bellard5cd43932003-03-29 16:54:36 +00006267 goto unimplemented_nowarn;
bellardebc05482003-09-30 21:08:41 +00006268#endif
6269#ifdef TARGET_NR_set_thread_area
bellard5cd43932003-03-29 16:54:36 +00006270 case TARGET_NR_set_thread_area:
bellard8d18e892007-11-14 15:18:40 +00006271#if defined(TARGET_MIPS)
ths6f5b89a2007-03-02 20:48:00 +00006272 ((CPUMIPSState *) cpu_env)->tls_value = arg1;
6273 ret = 0;
6274 break;
edgar_iglef967792009-01-07 14:19:38 +00006275#elif defined(TARGET_CRIS)
6276 if (arg1 & 0xff)
6277 ret = -TARGET_EINVAL;
6278 else {
6279 ((CPUCRISState *) cpu_env)->pregs[PR_PID] = arg1;
6280 ret = 0;
6281 }
6282 break;
bellard8d18e892007-11-14 15:18:40 +00006283#elif defined(TARGET_I386) && defined(TARGET_ABI32)
6284 ret = do_set_thread_area(cpu_env, arg1);
6285 break;
ths6f5b89a2007-03-02 20:48:00 +00006286#else
6287 goto unimplemented_nowarn;
6288#endif
6289#endif
6290#ifdef TARGET_NR_get_thread_area
bellard5cd43932003-03-29 16:54:36 +00006291 case TARGET_NR_get_thread_area:
bellard8d18e892007-11-14 15:18:40 +00006292#if defined(TARGET_I386) && defined(TARGET_ABI32)
6293 ret = do_get_thread_area(cpu_env, arg1);
6294#else
bellard5cd43932003-03-29 16:54:36 +00006295 goto unimplemented_nowarn;
bellardebc05482003-09-30 21:08:41 +00006296#endif
bellard8d18e892007-11-14 15:18:40 +00006297#endif
bellard48dc41e2006-06-21 18:15:50 +00006298#ifdef TARGET_NR_getdomainname
6299 case TARGET_NR_getdomainname:
6300 goto unimplemented_nowarn;
6301#endif
ths6f5b89a2007-03-02 20:48:00 +00006302
thsb5906f92007-03-19 13:32:45 +00006303#ifdef TARGET_NR_clock_gettime
6304 case TARGET_NR_clock_gettime:
6305 {
6306 struct timespec ts;
6307 ret = get_errno(clock_gettime(arg1, &ts));
6308 if (!is_error(ret)) {
6309 host_to_target_timespec(arg2, &ts);
6310 }
6311 break;
6312 }
6313#endif
6314#ifdef TARGET_NR_clock_getres
6315 case TARGET_NR_clock_getres:
6316 {
6317 struct timespec ts;
6318 ret = get_errno(clock_getres(arg1, &ts));
6319 if (!is_error(ret)) {
6320 host_to_target_timespec(arg2, &ts);
6321 }
6322 break;
6323 }
6324#endif
pbrook63d76512008-05-29 13:43:29 +00006325#ifdef TARGET_NR_clock_nanosleep
6326 case TARGET_NR_clock_nanosleep:
6327 {
6328 struct timespec ts;
6329 target_to_host_timespec(&ts, arg3);
6330 ret = get_errno(clock_nanosleep(arg1, arg2, &ts, arg4 ? &ts : NULL));
6331 if (arg4)
6332 host_to_target_timespec(arg4, &ts);
6333 break;
6334 }
6335#endif
thsb5906f92007-03-19 13:32:45 +00006336
ths6f5b89a2007-03-02 20:48:00 +00006337#if defined(TARGET_NR_set_tid_address) && defined(__NR_set_tid_address)
6338 case TARGET_NR_set_tid_address:
bellard579a97f2007-11-11 14:26:47 +00006339 ret = get_errno(set_tid_address((int *)g2h(arg1)));
6340 break;
ths6f5b89a2007-03-02 20:48:00 +00006341#endif
6342
ths3ae43202007-09-16 21:39:48 +00006343#if defined(TARGET_NR_tkill) && defined(__NR_tkill)
ths4cae1d12007-07-12 11:06:53 +00006344 case TARGET_NR_tkill:
pbrook4cb05962008-05-30 18:05:19 +00006345 ret = get_errno(sys_tkill((int)arg1, target_to_host_signal(arg2)));
ths4cae1d12007-07-12 11:06:53 +00006346 break;
6347#endif
6348
ths3ae43202007-09-16 21:39:48 +00006349#if defined(TARGET_NR_tgkill) && defined(__NR_tgkill)
ths71455572007-06-21 21:45:30 +00006350 case TARGET_NR_tgkill:
pbrook4cb05962008-05-30 18:05:19 +00006351 ret = get_errno(sys_tgkill((int)arg1, (int)arg2,
6352 target_to_host_signal(arg3)));
ths71455572007-06-21 21:45:30 +00006353 break;
6354#endif
6355
ths4f2b1fe2007-06-21 21:57:12 +00006356#ifdef TARGET_NR_set_robust_list
6357 case TARGET_NR_set_robust_list:
6358 goto unimplemented_nowarn;
6359#endif
6360
ths9007f0e2007-09-25 17:50:37 +00006361#if defined(TARGET_NR_utimensat) && defined(__NR_utimensat)
6362 case TARGET_NR_utimensat:
6363 {
6364 struct timespec ts[2];
6365 target_to_host_timespec(ts, arg3);
6366 target_to_host_timespec(ts+1, arg3+sizeof(struct target_timespec));
6367 if (!arg2)
6368 ret = get_errno(sys_utimensat(arg1, NULL, ts, arg4));
6369 else {
bellard579a97f2007-11-11 14:26:47 +00006370 if (!(p = lock_user_string(arg2))) {
ths0da46a62007-10-20 20:23:07 +00006371 ret = -TARGET_EFAULT;
bellard579a97f2007-11-11 14:26:47 +00006372 goto fail;
6373 }
6374 ret = get_errno(sys_utimensat(arg1, path(p), ts, arg4));
6375 unlock_user(p, arg2, 0);
ths9007f0e2007-09-25 17:50:37 +00006376 }
6377 }
6378 break;
6379#endif
pbrookbd0c5662008-05-29 14:34:11 +00006380#if defined(USE_NPTL)
6381 case TARGET_NR_futex:
6382 ret = do_futex(arg1, arg2, arg3, arg4, arg5, arg6);
6383 break;
6384#endif
aurel32dbfe4c32009-04-08 21:29:30 +00006385#if defined(TARGET_NR_inotify_init) && defined(__NR_inotify_init)
aurel3239b59762008-10-01 21:46:50 +00006386 case TARGET_NR_inotify_init:
6387 ret = get_errno(sys_inotify_init());
6388 break;
6389#endif
aurel32dbfe4c32009-04-08 21:29:30 +00006390#if defined(TARGET_NR_inotify_add_watch) && defined(__NR_inotify_add_watch)
aurel3239b59762008-10-01 21:46:50 +00006391 case TARGET_NR_inotify_add_watch:
6392 p = lock_user_string(arg2);
6393 ret = get_errno(sys_inotify_add_watch(arg1, path(p), arg3));
6394 unlock_user(p, arg2, 0);
6395 break;
6396#endif
aurel32dbfe4c32009-04-08 21:29:30 +00006397#if defined(TARGET_NR_inotify_rm_watch) && defined(__NR_inotify_rm_watch)
aurel3239b59762008-10-01 21:46:50 +00006398 case TARGET_NR_inotify_rm_watch:
6399 ret = get_errno(sys_inotify_rm_watch(arg1, arg2));
6400 break;
6401#endif
ths9007f0e2007-09-25 17:50:37 +00006402
aurel3224e10032009-04-15 16:11:43 +00006403#ifdef TARGET_NR_mq_open
6404 case TARGET_NR_mq_open:
6405 {
6406 struct mq_attr posix_mq_attr;
6407
6408 p = lock_user_string(arg1 - 1);
6409 if (arg4 != 0)
6410 copy_from_user_mq_attr (&posix_mq_attr, arg4);
6411 ret = get_errno(mq_open(p, arg2, arg3, &posix_mq_attr));
6412 unlock_user (p, arg1, 0);
6413 }
6414 break;
6415
6416 case TARGET_NR_mq_unlink:
6417 p = lock_user_string(arg1 - 1);
6418 ret = get_errno(mq_unlink(p));
6419 unlock_user (p, arg1, 0);
6420 break;
6421
6422 case TARGET_NR_mq_timedsend:
6423 {
6424 struct timespec ts;
6425
6426 p = lock_user (VERIFY_READ, arg2, arg3, 1);
6427 if (arg5 != 0) {
6428 target_to_host_timespec(&ts, arg5);
6429 ret = get_errno(mq_timedsend(arg1, p, arg3, arg4, &ts));
6430 host_to_target_timespec(arg5, &ts);
6431 }
6432 else
6433 ret = get_errno(mq_send(arg1, p, arg3, arg4));
6434 unlock_user (p, arg2, arg3);
6435 }
6436 break;
6437
6438 case TARGET_NR_mq_timedreceive:
6439 {
6440 struct timespec ts;
6441 unsigned int prio;
6442
6443 p = lock_user (VERIFY_READ, arg2, arg3, 1);
6444 if (arg5 != 0) {
6445 target_to_host_timespec(&ts, arg5);
6446 ret = get_errno(mq_timedreceive(arg1, p, arg3, &prio, &ts));
6447 host_to_target_timespec(arg5, &ts);
6448 }
6449 else
6450 ret = get_errno(mq_receive(arg1, p, arg3, &prio));
6451 unlock_user (p, arg2, arg3);
6452 if (arg4 != 0)
6453 put_user_u32(prio, arg4);
6454 }
6455 break;
6456
6457 /* Not implemented for now... */
6458/* case TARGET_NR_mq_notify: */
6459/* break; */
6460
6461 case TARGET_NR_mq_getsetattr:
6462 {
6463 struct mq_attr posix_mq_attr_in, posix_mq_attr_out;
6464 ret = 0;
6465 if (arg3 != 0) {
6466 ret = mq_getattr(arg1, &posix_mq_attr_out);
6467 copy_to_user_mq_attr(arg3, &posix_mq_attr_out);
6468 }
6469 if (arg2 != 0) {
6470 copy_from_user_mq_attr(&posix_mq_attr_in, arg2);
6471 ret |= mq_setattr(arg1, &posix_mq_attr_in, &posix_mq_attr_out);
6472 }
6473
6474 }
6475 break;
6476#endif
6477
bellard31e31b82003-02-18 22:55:36 +00006478 default:
6479 unimplemented:
bellard5cd43932003-03-29 16:54:36 +00006480 gemu_log("qemu: Unsupported syscall: %d\n", num);
ths4f2b1fe2007-06-21 21:57:12 +00006481#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 +00006482 unimplemented_nowarn:
bellard80a9d032005-01-03 23:31:27 +00006483#endif
ths0da46a62007-10-20 20:23:07 +00006484 ret = -TARGET_ENOSYS;
bellard31e31b82003-02-18 22:55:36 +00006485 break;
6486 }
bellard579a97f2007-11-11 14:26:47 +00006487fail:
bellardc573ff62004-01-04 15:51:36 +00006488#ifdef DEBUG
6489 gemu_log(" = %ld\n", ret);
6490#endif
thsb92c47c2007-11-01 00:07:38 +00006491 if(do_strace)
6492 print_syscall_ret(num, ret);
bellard31e31b82003-02-18 22:55:36 +00006493 return ret;
bellard579a97f2007-11-11 14:26:47 +00006494efault:
6495 ret = -TARGET_EFAULT;
6496 goto fail;
bellard31e31b82003-02-18 22:55:36 +00006497}