blob: ec04170b984516e2df40f5efcd573a7b1f41ad37 [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
pbrook1d9d8b52009-04-16 15:17:02 +00003646/* Map host to target signal numbers for the wait family of syscalls.
3647 Assume all other status bits are the same. */
3648static int host_to_target_waitstatus(int status)
3649{
3650 if (WIFSIGNALED(status)) {
3651 return host_to_target_signal(WTERMSIG(status)) | (status & ~0x7f);
3652 }
3653 if (WIFSTOPPED(status)) {
3654 return (host_to_target_signal(WSTOPSIG(status)) << 8)
3655 | (status & 0xff);
3656 }
3657 return status;
3658}
3659
pbrooka745ec62008-05-06 15:36:17 +00003660int get_osversion(void)
3661{
3662 static int osversion;
3663 struct new_utsname buf;
3664 const char *s;
3665 int i, n, tmp;
3666 if (osversion)
3667 return osversion;
3668 if (qemu_uname_release && *qemu_uname_release) {
3669 s = qemu_uname_release;
3670 } else {
3671 if (sys_uname(&buf))
3672 return 0;
3673 s = buf.release;
3674 }
3675 tmp = 0;
3676 for (i = 0; i < 3; i++) {
3677 n = 0;
3678 while (*s >= '0' && *s <= '9') {
3679 n *= 10;
3680 n += *s - '0';
3681 s++;
3682 }
3683 tmp = (tmp << 8) + n;
3684 if (*s == '.')
3685 s++;
3686 }
3687 osversion = tmp;
3688 return osversion;
3689}
3690
ths0da46a62007-10-20 20:23:07 +00003691/* do_syscall() should always have a single exit point at the end so
3692 that actions, such as logging of syscall results, can be performed.
3693 All errnos that do_syscall() returns must be -TARGET_<errcode>. */
blueswir1992f48a2007-10-14 16:27:31 +00003694abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
3695 abi_long arg2, abi_long arg3, abi_long arg4,
3696 abi_long arg5, abi_long arg6)
bellard31e31b82003-02-18 22:55:36 +00003697{
blueswir1992f48a2007-10-14 16:27:31 +00003698 abi_long ret;
bellard31e31b82003-02-18 22:55:36 +00003699 struct stat st;
bellard56c8f682005-11-28 22:28:41 +00003700 struct statfs stfs;
pbrook53a59602006-03-25 19:31:22 +00003701 void *p;
ths3b46e622007-09-17 08:09:54 +00003702
bellard72f03902003-02-18 23:33:18 +00003703#ifdef DEBUG
bellardc573ff62004-01-04 15:51:36 +00003704 gemu_log("syscall %d", num);
bellard72f03902003-02-18 23:33:18 +00003705#endif
thsb92c47c2007-11-01 00:07:38 +00003706 if(do_strace)
3707 print_syscall(num, arg1, arg2, arg3, arg4, arg5, arg6);
3708
bellard31e31b82003-02-18 22:55:36 +00003709 switch(num) {
3710 case TARGET_NR_exit:
pbrookc2764712009-03-07 15:24:59 +00003711#ifdef USE_NPTL
3712 /* In old applications this may be used to implement _exit(2).
3713 However in threaded applictions it is used for thread termination,
3714 and _exit_group is used for application termination.
3715 Do thread termination if we have more then one thread. */
3716 /* FIXME: This probably breaks if a signal arrives. We should probably
3717 be disabling signals. */
3718 if (first_cpu->next_cpu) {
3719 CPUState **lastp;
3720 CPUState *p;
3721
3722 cpu_list_lock();
3723 lastp = &first_cpu;
3724 p = first_cpu;
3725 while (p && p != (CPUState *)cpu_env) {
3726 lastp = &p->next_cpu;
3727 p = p->next_cpu;
3728 }
3729 /* If we didn't find the CPU for this thread then something is
3730 horribly wrong. */
3731 if (!p)
3732 abort();
3733 /* Remove the CPU from the list. */
3734 *lastp = p->next_cpu;
3735 cpu_list_unlock();
3736 TaskState *ts = ((CPUState *)cpu_env)->opaque;
3737 if (ts->child_tidptr) {
3738 put_user_u32(0, ts->child_tidptr);
3739 sys_futex(g2h(ts->child_tidptr), FUTEX_WAKE, INT_MAX,
3740 NULL, NULL, 0);
3741 }
3742 /* TODO: Free CPU state. */
3743 pthread_exit(NULL);
3744 }
3745#endif
bellard7d132992003-03-06 23:23:54 +00003746#ifdef HAVE_GPROF
3747 _mcleanup();
3748#endif
bellarde9009672005-04-26 20:42:36 +00003749 gdb_exit(cpu_env, arg1);
pbrookc2764712009-03-07 15:24:59 +00003750 _exit(arg1);
bellard31e31b82003-02-18 22:55:36 +00003751 ret = 0; /* avoid warning */
3752 break;
3753 case TARGET_NR_read:
aurel3238d840e2009-01-30 19:48:17 +00003754 if (arg3 == 0)
3755 ret = 0;
3756 else {
3757 if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
3758 goto efault;
3759 ret = get_errno(read(arg1, p, arg3));
3760 unlock_user(p, arg2, ret);
3761 }
bellard31e31b82003-02-18 22:55:36 +00003762 break;
3763 case TARGET_NR_write:
bellard579a97f2007-11-11 14:26:47 +00003764 if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
3765 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003766 ret = get_errno(write(arg1, p, arg3));
3767 unlock_user(p, arg2, 0);
bellard31e31b82003-02-18 22:55:36 +00003768 break;
3769 case TARGET_NR_open:
bellard2f619692007-11-16 10:46:05 +00003770 if (!(p = lock_user_string(arg1)))
3771 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003772 ret = get_errno(open(path(p),
bellardffa65c32004-01-04 23:57:22 +00003773 target_to_host_bitmask(arg2, fcntl_flags_tbl),
3774 arg3));
pbrook53a59602006-03-25 19:31:22 +00003775 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003776 break;
ths82424832007-09-24 09:21:55 +00003777#if defined(TARGET_NR_openat) && defined(__NR_openat)
3778 case TARGET_NR_openat:
bellard579a97f2007-11-11 14:26:47 +00003779 if (!(p = lock_user_string(arg2)))
3780 goto efault;
3781 ret = get_errno(sys_openat(arg1,
3782 path(p),
3783 target_to_host_bitmask(arg3, fcntl_flags_tbl),
3784 arg4));
3785 unlock_user(p, arg2, 0);
ths82424832007-09-24 09:21:55 +00003786 break;
3787#endif
bellard31e31b82003-02-18 22:55:36 +00003788 case TARGET_NR_close:
3789 ret = get_errno(close(arg1));
3790 break;
3791 case TARGET_NR_brk:
pbrook53a59602006-03-25 19:31:22 +00003792 ret = do_brk(arg1);
bellard31e31b82003-02-18 22:55:36 +00003793 break;
3794 case TARGET_NR_fork:
pbrookd865bab2008-06-07 22:12:17 +00003795 ret = get_errno(do_fork(cpu_env, SIGCHLD, 0, 0, 0, 0));
bellard31e31b82003-02-18 22:55:36 +00003796 break;
thse5febef2007-04-01 18:31:35 +00003797#ifdef TARGET_NR_waitpid
bellard31e31b82003-02-18 22:55:36 +00003798 case TARGET_NR_waitpid:
3799 {
pbrook53a59602006-03-25 19:31:22 +00003800 int status;
3801 ret = get_errno(waitpid(arg1, &status, arg3));
bellard2f619692007-11-16 10:46:05 +00003802 if (!is_error(ret) && arg2
pbrook1d9d8b52009-04-16 15:17:02 +00003803 && put_user_s32(host_to_target_waitstatus(status), arg2))
bellard2f619692007-11-16 10:46:05 +00003804 goto efault;
bellard31e31b82003-02-18 22:55:36 +00003805 }
3806 break;
thse5febef2007-04-01 18:31:35 +00003807#endif
pbrookf0cbb612008-05-30 18:20:05 +00003808#ifdef TARGET_NR_waitid
3809 case TARGET_NR_waitid:
3810 {
3811 siginfo_t info;
3812 info.si_pid = 0;
3813 ret = get_errno(waitid(arg1, arg2, &info, arg4));
3814 if (!is_error(ret) && arg3 && info.si_pid != 0) {
3815 if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_siginfo_t), 0)))
3816 goto efault;
3817 host_to_target_siginfo(p, &info);
3818 unlock_user(p, arg3, sizeof(target_siginfo_t));
3819 }
3820 }
3821 break;
3822#endif
j_mayer7a3148a2007-04-05 07:13:51 +00003823#ifdef TARGET_NR_creat /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00003824 case TARGET_NR_creat:
bellard579a97f2007-11-11 14:26:47 +00003825 if (!(p = lock_user_string(arg1)))
3826 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003827 ret = get_errno(creat(p, arg2));
3828 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003829 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003830#endif
bellard31e31b82003-02-18 22:55:36 +00003831 case TARGET_NR_link:
pbrook53a59602006-03-25 19:31:22 +00003832 {
3833 void * p2;
3834 p = lock_user_string(arg1);
3835 p2 = lock_user_string(arg2);
bellard579a97f2007-11-11 14:26:47 +00003836 if (!p || !p2)
3837 ret = -TARGET_EFAULT;
3838 else
3839 ret = get_errno(link(p, p2));
pbrook53a59602006-03-25 19:31:22 +00003840 unlock_user(p2, arg2, 0);
3841 unlock_user(p, arg1, 0);
3842 }
bellard31e31b82003-02-18 22:55:36 +00003843 break;
ths64f0ce42007-09-24 09:25:06 +00003844#if defined(TARGET_NR_linkat) && defined(__NR_linkat)
3845 case TARGET_NR_linkat:
ths64f0ce42007-09-24 09:25:06 +00003846 {
3847 void * p2 = NULL;
bellard579a97f2007-11-11 14:26:47 +00003848 if (!arg2 || !arg4)
3849 goto efault;
ths64f0ce42007-09-24 09:25:06 +00003850 p = lock_user_string(arg2);
3851 p2 = lock_user_string(arg4);
bellard579a97f2007-11-11 14:26:47 +00003852 if (!p || !p2)
ths0da46a62007-10-20 20:23:07 +00003853 ret = -TARGET_EFAULT;
ths64f0ce42007-09-24 09:25:06 +00003854 else
3855 ret = get_errno(sys_linkat(arg1, p, arg3, p2, arg5));
bellard579a97f2007-11-11 14:26:47 +00003856 unlock_user(p, arg2, 0);
3857 unlock_user(p2, arg4, 0);
ths64f0ce42007-09-24 09:25:06 +00003858 }
3859 break;
3860#endif
bellard31e31b82003-02-18 22:55:36 +00003861 case TARGET_NR_unlink:
bellard579a97f2007-11-11 14:26:47 +00003862 if (!(p = lock_user_string(arg1)))
3863 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003864 ret = get_errno(unlink(p));
3865 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003866 break;
ths8170f562007-09-24 09:24:11 +00003867#if defined(TARGET_NR_unlinkat) && defined(__NR_unlinkat)
3868 case TARGET_NR_unlinkat:
bellard579a97f2007-11-11 14:26:47 +00003869 if (!(p = lock_user_string(arg2)))
3870 goto efault;
3871 ret = get_errno(sys_unlinkat(arg1, p, arg3));
3872 unlock_user(p, arg2, 0);
balroged494d82007-12-11 23:23:52 +00003873 break;
balrogb7d35e62007-12-12 00:40:24 +00003874#endif
bellard31e31b82003-02-18 22:55:36 +00003875 case TARGET_NR_execve:
bellard7854b052003-03-29 17:22:23 +00003876 {
3877 char **argp, **envp;
bellardf7341ff2003-03-30 21:00:25 +00003878 int argc, envc;
blueswir1992f48a2007-10-14 16:27:31 +00003879 abi_ulong gp;
3880 abi_ulong guest_argp;
3881 abi_ulong guest_envp;
3882 abi_ulong addr;
bellard7854b052003-03-29 17:22:23 +00003883 char **q;
3884
bellardf7341ff2003-03-30 21:00:25 +00003885 argc = 0;
pbrook53a59602006-03-25 19:31:22 +00003886 guest_argp = arg2;
pbrookda94d262008-05-30 18:24:00 +00003887 for (gp = guest_argp; gp; gp += sizeof(abi_ulong)) {
ths03aa1972007-12-02 06:28:08 +00003888 if (get_user_ual(addr, gp))
bellard2f619692007-11-16 10:46:05 +00003889 goto efault;
ths03aa1972007-12-02 06:28:08 +00003890 if (!addr)
bellard2f619692007-11-16 10:46:05 +00003891 break;
bellard7854b052003-03-29 17:22:23 +00003892 argc++;
bellard2f619692007-11-16 10:46:05 +00003893 }
bellardf7341ff2003-03-30 21:00:25 +00003894 envc = 0;
pbrook53a59602006-03-25 19:31:22 +00003895 guest_envp = arg3;
pbrookda94d262008-05-30 18:24:00 +00003896 for (gp = guest_envp; gp; gp += sizeof(abi_ulong)) {
ths03aa1972007-12-02 06:28:08 +00003897 if (get_user_ual(addr, gp))
bellard2f619692007-11-16 10:46:05 +00003898 goto efault;
ths03aa1972007-12-02 06:28:08 +00003899 if (!addr)
bellard2f619692007-11-16 10:46:05 +00003900 break;
bellard7854b052003-03-29 17:22:23 +00003901 envc++;
bellard2f619692007-11-16 10:46:05 +00003902 }
bellard7854b052003-03-29 17:22:23 +00003903
bellardf7341ff2003-03-30 21:00:25 +00003904 argp = alloca((argc + 1) * sizeof(void *));
3905 envp = alloca((envc + 1) * sizeof(void *));
bellard7854b052003-03-29 17:22:23 +00003906
pbrookda94d262008-05-30 18:24:00 +00003907 for (gp = guest_argp, q = argp; gp;
blueswir1992f48a2007-10-14 16:27:31 +00003908 gp += sizeof(abi_ulong), q++) {
bellard2f619692007-11-16 10:46:05 +00003909 if (get_user_ual(addr, gp))
3910 goto execve_efault;
pbrook53a59602006-03-25 19:31:22 +00003911 if (!addr)
3912 break;
bellard2f619692007-11-16 10:46:05 +00003913 if (!(*q = lock_user_string(addr)))
3914 goto execve_efault;
pbrook53a59602006-03-25 19:31:22 +00003915 }
bellardf7341ff2003-03-30 21:00:25 +00003916 *q = NULL;
3917
pbrookda94d262008-05-30 18:24:00 +00003918 for (gp = guest_envp, q = envp; gp;
blueswir1992f48a2007-10-14 16:27:31 +00003919 gp += sizeof(abi_ulong), q++) {
bellard2f619692007-11-16 10:46:05 +00003920 if (get_user_ual(addr, gp))
3921 goto execve_efault;
pbrook53a59602006-03-25 19:31:22 +00003922 if (!addr)
3923 break;
bellard2f619692007-11-16 10:46:05 +00003924 if (!(*q = lock_user_string(addr)))
3925 goto execve_efault;
pbrook53a59602006-03-25 19:31:22 +00003926 }
bellardf7341ff2003-03-30 21:00:25 +00003927 *q = NULL;
bellard7854b052003-03-29 17:22:23 +00003928
bellard2f619692007-11-16 10:46:05 +00003929 if (!(p = lock_user_string(arg1)))
3930 goto execve_efault;
pbrook53a59602006-03-25 19:31:22 +00003931 ret = get_errno(execve(p, argp, envp));
3932 unlock_user(p, arg1, 0);
3933
bellard2f619692007-11-16 10:46:05 +00003934 goto execve_end;
3935
3936 execve_efault:
3937 ret = -TARGET_EFAULT;
3938
3939 execve_end:
pbrook53a59602006-03-25 19:31:22 +00003940 for (gp = guest_argp, q = argp; *q;
blueswir1992f48a2007-10-14 16:27:31 +00003941 gp += sizeof(abi_ulong), q++) {
bellard2f619692007-11-16 10:46:05 +00003942 if (get_user_ual(addr, gp)
3943 || !addr)
3944 break;
pbrook53a59602006-03-25 19:31:22 +00003945 unlock_user(*q, addr, 0);
3946 }
3947 for (gp = guest_envp, q = envp; *q;
blueswir1992f48a2007-10-14 16:27:31 +00003948 gp += sizeof(abi_ulong), q++) {
bellard2f619692007-11-16 10:46:05 +00003949 if (get_user_ual(addr, gp)
3950 || !addr)
3951 break;
pbrook53a59602006-03-25 19:31:22 +00003952 unlock_user(*q, addr, 0);
3953 }
bellard7854b052003-03-29 17:22:23 +00003954 }
bellard31e31b82003-02-18 22:55:36 +00003955 break;
3956 case TARGET_NR_chdir:
bellard579a97f2007-11-11 14:26:47 +00003957 if (!(p = lock_user_string(arg1)))
3958 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003959 ret = get_errno(chdir(p));
3960 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003961 break;
bellarda315a142005-01-30 22:59:18 +00003962#ifdef TARGET_NR_time
bellard31e31b82003-02-18 22:55:36 +00003963 case TARGET_NR_time:
3964 {
pbrook53a59602006-03-25 19:31:22 +00003965 time_t host_time;
3966 ret = get_errno(time(&host_time));
bellard2f619692007-11-16 10:46:05 +00003967 if (!is_error(ret)
3968 && arg1
3969 && put_user_sal(host_time, arg1))
3970 goto efault;
bellard31e31b82003-02-18 22:55:36 +00003971 }
3972 break;
bellarda315a142005-01-30 22:59:18 +00003973#endif
bellard31e31b82003-02-18 22:55:36 +00003974 case TARGET_NR_mknod:
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(mknod(p, arg2, arg3));
3978 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003979 break;
ths75ac37a2007-09-24 09:23:05 +00003980#if defined(TARGET_NR_mknodat) && defined(__NR_mknodat)
3981 case TARGET_NR_mknodat:
bellard579a97f2007-11-11 14:26:47 +00003982 if (!(p = lock_user_string(arg2)))
3983 goto efault;
3984 ret = get_errno(sys_mknodat(arg1, p, arg3, arg4));
3985 unlock_user(p, arg2, 0);
ths75ac37a2007-09-24 09:23:05 +00003986 break;
3987#endif
bellard31e31b82003-02-18 22:55:36 +00003988 case TARGET_NR_chmod:
bellard579a97f2007-11-11 14:26:47 +00003989 if (!(p = lock_user_string(arg1)))
3990 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003991 ret = get_errno(chmod(p, arg2));
3992 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003993 break;
bellardebc05482003-09-30 21:08:41 +00003994#ifdef TARGET_NR_break
bellard31e31b82003-02-18 22:55:36 +00003995 case TARGET_NR_break:
3996 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00003997#endif
3998#ifdef TARGET_NR_oldstat
bellard31e31b82003-02-18 22:55:36 +00003999 case TARGET_NR_oldstat:
4000 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004001#endif
bellard31e31b82003-02-18 22:55:36 +00004002 case TARGET_NR_lseek:
4003 ret = get_errno(lseek(arg1, arg2, arg3));
4004 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004005#ifdef TARGET_NR_getxpid
4006 case TARGET_NR_getxpid:
4007#else
bellard31e31b82003-02-18 22:55:36 +00004008 case TARGET_NR_getpid:
j_mayer7a3148a2007-04-05 07:13:51 +00004009#endif
bellard31e31b82003-02-18 22:55:36 +00004010 ret = get_errno(getpid());
4011 break;
4012 case TARGET_NR_mount:
ths80265912007-02-17 22:25:41 +00004013 {
4014 /* need to look at the data field */
4015 void *p2, *p3;
4016 p = lock_user_string(arg1);
4017 p2 = lock_user_string(arg2);
4018 p3 = lock_user_string(arg3);
bellard579a97f2007-11-11 14:26:47 +00004019 if (!p || !p2 || !p3)
4020 ret = -TARGET_EFAULT;
4021 else
4022 /* FIXME - arg5 should be locked, but it isn't clear how to
4023 * do that since it's not guaranteed to be a NULL-terminated
4024 * string.
4025 */
4026 ret = get_errno(mount(p, p2, p3, (unsigned long)arg4, g2h(arg5)));
4027 unlock_user(p, arg1, 0);
4028 unlock_user(p2, arg2, 0);
4029 unlock_user(p3, arg3, 0);
ths80265912007-02-17 22:25:41 +00004030 break;
4031 }
thse5febef2007-04-01 18:31:35 +00004032#ifdef TARGET_NR_umount
bellard31e31b82003-02-18 22:55:36 +00004033 case TARGET_NR_umount:
bellard579a97f2007-11-11 14:26:47 +00004034 if (!(p = lock_user_string(arg1)))
4035 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004036 ret = get_errno(umount(p));
4037 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004038 break;
thse5febef2007-04-01 18:31:35 +00004039#endif
j_mayer7a3148a2007-04-05 07:13:51 +00004040#ifdef TARGET_NR_stime /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00004041 case TARGET_NR_stime:
4042 {
pbrook53a59602006-03-25 19:31:22 +00004043 time_t host_time;
bellard2f619692007-11-16 10:46:05 +00004044 if (get_user_sal(host_time, arg1))
4045 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004046 ret = get_errno(stime(&host_time));
bellard31e31b82003-02-18 22:55:36 +00004047 }
4048 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004049#endif
bellard31e31b82003-02-18 22:55:36 +00004050 case TARGET_NR_ptrace:
4051 goto unimplemented;
j_mayer7a3148a2007-04-05 07:13:51 +00004052#ifdef TARGET_NR_alarm /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00004053 case TARGET_NR_alarm:
4054 ret = alarm(arg1);
4055 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004056#endif
bellardebc05482003-09-30 21:08:41 +00004057#ifdef TARGET_NR_oldfstat
bellard31e31b82003-02-18 22:55:36 +00004058 case TARGET_NR_oldfstat:
4059 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004060#endif
j_mayer7a3148a2007-04-05 07:13:51 +00004061#ifdef TARGET_NR_pause /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00004062 case TARGET_NR_pause:
4063 ret = get_errno(pause());
4064 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004065#endif
thse5febef2007-04-01 18:31:35 +00004066#ifdef TARGET_NR_utime
bellard31e31b82003-02-18 22:55:36 +00004067 case TARGET_NR_utime:
bellardebc05482003-09-30 21:08:41 +00004068 {
pbrook53a59602006-03-25 19:31:22 +00004069 struct utimbuf tbuf, *host_tbuf;
4070 struct target_utimbuf *target_tbuf;
4071 if (arg2) {
bellard579a97f2007-11-11 14:26:47 +00004072 if (!lock_user_struct(VERIFY_READ, target_tbuf, arg2, 1))
4073 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004074 tbuf.actime = tswapl(target_tbuf->actime);
4075 tbuf.modtime = tswapl(target_tbuf->modtime);
4076 unlock_user_struct(target_tbuf, arg2, 0);
4077 host_tbuf = &tbuf;
bellardf72e8ff2004-05-03 19:23:07 +00004078 } else {
pbrook53a59602006-03-25 19:31:22 +00004079 host_tbuf = NULL;
bellardf72e8ff2004-05-03 19:23:07 +00004080 }
bellard579a97f2007-11-11 14:26:47 +00004081 if (!(p = lock_user_string(arg1)))
4082 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004083 ret = get_errno(utime(p, host_tbuf));
4084 unlock_user(p, arg1, 0);
bellardebc05482003-09-30 21:08:41 +00004085 }
4086 break;
thse5febef2007-04-01 18:31:35 +00004087#endif
bellard978a66f2004-12-06 22:58:05 +00004088 case TARGET_NR_utimes:
4089 {
bellard978a66f2004-12-06 22:58:05 +00004090 struct timeval *tvp, tv[2];
pbrook53a59602006-03-25 19:31:22 +00004091 if (arg2) {
ths788f5ec2007-12-09 02:37:05 +00004092 if (copy_from_user_timeval(&tv[0], arg2)
4093 || copy_from_user_timeval(&tv[1],
4094 arg2 + sizeof(struct target_timeval)))
4095 goto efault;
bellard978a66f2004-12-06 22:58:05 +00004096 tvp = tv;
4097 } else {
4098 tvp = NULL;
4099 }
bellard579a97f2007-11-11 14:26:47 +00004100 if (!(p = lock_user_string(arg1)))
4101 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004102 ret = get_errno(utimes(p, tvp));
4103 unlock_user(p, arg1, 0);
bellard978a66f2004-12-06 22:58:05 +00004104 }
4105 break;
balrogac8a6552008-09-20 02:25:39 +00004106#if defined(TARGET_NR_futimesat) && defined(__NR_futimesat)
4107 case TARGET_NR_futimesat:
4108 {
4109 struct timeval *tvp, tv[2];
4110 if (arg3) {
4111 if (copy_from_user_timeval(&tv[0], arg3)
4112 || copy_from_user_timeval(&tv[1],
4113 arg3 + sizeof(struct target_timeval)))
4114 goto efault;
4115 tvp = tv;
4116 } else {
4117 tvp = NULL;
4118 }
4119 if (!(p = lock_user_string(arg2)))
4120 goto efault;
4121 ret = get_errno(sys_futimesat(arg1, path(p), tvp));
4122 unlock_user(p, arg2, 0);
4123 }
4124 break;
4125#endif
bellardebc05482003-09-30 21:08:41 +00004126#ifdef TARGET_NR_stty
bellard31e31b82003-02-18 22:55:36 +00004127 case TARGET_NR_stty:
4128 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004129#endif
4130#ifdef TARGET_NR_gtty
bellard31e31b82003-02-18 22:55:36 +00004131 case TARGET_NR_gtty:
4132 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004133#endif
bellard31e31b82003-02-18 22:55:36 +00004134 case TARGET_NR_access:
bellard579a97f2007-11-11 14:26:47 +00004135 if (!(p = lock_user_string(arg1)))
4136 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004137 ret = get_errno(access(p, arg2));
4138 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004139 break;
ths92a34c12007-09-24 09:27:49 +00004140#if defined(TARGET_NR_faccessat) && defined(__NR_faccessat)
4141 case TARGET_NR_faccessat:
bellard579a97f2007-11-11 14:26:47 +00004142 if (!(p = lock_user_string(arg2)))
4143 goto efault;
4144 ret = get_errno(sys_faccessat(arg1, p, arg3, arg4));
4145 unlock_user(p, arg2, 0);
ths92a34c12007-09-24 09:27:49 +00004146 break;
4147#endif
j_mayer7a3148a2007-04-05 07:13:51 +00004148#ifdef TARGET_NR_nice /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00004149 case TARGET_NR_nice:
4150 ret = get_errno(nice(arg1));
4151 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004152#endif
bellardebc05482003-09-30 21:08:41 +00004153#ifdef TARGET_NR_ftime
bellard31e31b82003-02-18 22:55:36 +00004154 case TARGET_NR_ftime:
4155 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004156#endif
bellard31e31b82003-02-18 22:55:36 +00004157 case TARGET_NR_sync:
bellard04369ff2003-03-20 22:33:23 +00004158 sync();
4159 ret = 0;
bellard31e31b82003-02-18 22:55:36 +00004160 break;
4161 case TARGET_NR_kill:
pbrook4cb05962008-05-30 18:05:19 +00004162 ret = get_errno(kill(arg1, target_to_host_signal(arg2)));
bellard31e31b82003-02-18 22:55:36 +00004163 break;
4164 case TARGET_NR_rename:
pbrook53a59602006-03-25 19:31:22 +00004165 {
4166 void *p2;
4167 p = lock_user_string(arg1);
4168 p2 = lock_user_string(arg2);
bellard579a97f2007-11-11 14:26:47 +00004169 if (!p || !p2)
4170 ret = -TARGET_EFAULT;
4171 else
4172 ret = get_errno(rename(p, p2));
pbrook53a59602006-03-25 19:31:22 +00004173 unlock_user(p2, arg2, 0);
4174 unlock_user(p, arg1, 0);
4175 }
bellard31e31b82003-02-18 22:55:36 +00004176 break;
ths722183f2007-09-24 09:24:37 +00004177#if defined(TARGET_NR_renameat) && defined(__NR_renameat)
4178 case TARGET_NR_renameat:
ths722183f2007-09-24 09:24:37 +00004179 {
bellard579a97f2007-11-11 14:26:47 +00004180 void *p2;
ths722183f2007-09-24 09:24:37 +00004181 p = lock_user_string(arg2);
4182 p2 = lock_user_string(arg4);
bellard579a97f2007-11-11 14:26:47 +00004183 if (!p || !p2)
ths0da46a62007-10-20 20:23:07 +00004184 ret = -TARGET_EFAULT;
ths722183f2007-09-24 09:24:37 +00004185 else
4186 ret = get_errno(sys_renameat(arg1, p, arg3, p2));
bellard579a97f2007-11-11 14:26:47 +00004187 unlock_user(p2, arg4, 0);
4188 unlock_user(p, arg2, 0);
ths722183f2007-09-24 09:24:37 +00004189 }
4190 break;
4191#endif
bellard31e31b82003-02-18 22:55:36 +00004192 case TARGET_NR_mkdir:
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(mkdir(p, arg2));
4196 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004197 break;
ths4472ad02007-09-24 09:22:32 +00004198#if defined(TARGET_NR_mkdirat) && defined(__NR_mkdirat)
4199 case TARGET_NR_mkdirat:
bellard579a97f2007-11-11 14:26:47 +00004200 if (!(p = lock_user_string(arg2)))
4201 goto efault;
4202 ret = get_errno(sys_mkdirat(arg1, p, arg3));
4203 unlock_user(p, arg2, 0);
ths4472ad02007-09-24 09:22:32 +00004204 break;
4205#endif
bellard31e31b82003-02-18 22:55:36 +00004206 case TARGET_NR_rmdir:
bellard579a97f2007-11-11 14:26:47 +00004207 if (!(p = lock_user_string(arg1)))
4208 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004209 ret = get_errno(rmdir(p));
4210 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004211 break;
4212 case TARGET_NR_dup:
4213 ret = get_errno(dup(arg1));
4214 break;
4215 case TARGET_NR_pipe:
4216 {
pbrook53a59602006-03-25 19:31:22 +00004217 int host_pipe[2];
4218 ret = get_errno(pipe(host_pipe));
bellard31e31b82003-02-18 22:55:36 +00004219 if (!is_error(ret)) {
thsc12ab052007-06-01 11:50:36 +00004220#if defined(TARGET_MIPS)
thsead93602007-09-06 00:18:15 +00004221 CPUMIPSState *env = (CPUMIPSState*)cpu_env;
thsb5dc7732008-06-27 10:02:35 +00004222 env->active_tc.gpr[3] = host_pipe[1];
thsc12ab052007-06-01 11:50:36 +00004223 ret = host_pipe[0];
aurel32b5eff352008-03-11 23:30:22 +00004224#elif defined(TARGET_SH4)
4225 ((CPUSH4State*)cpu_env)->gregs[1] = host_pipe[1];
4226 ret = host_pipe[0];
thsc12ab052007-06-01 11:50:36 +00004227#else
bellard2f619692007-11-16 10:46:05 +00004228 if (put_user_s32(host_pipe[0], arg1)
4229 || put_user_s32(host_pipe[1], arg1 + sizeof(host_pipe[0])))
4230 goto efault;
thsc12ab052007-06-01 11:50:36 +00004231#endif
bellard31e31b82003-02-18 22:55:36 +00004232 }
4233 }
4234 break;
4235 case TARGET_NR_times:
bellard32f36bc2003-03-30 21:29:48 +00004236 {
pbrook53a59602006-03-25 19:31:22 +00004237 struct target_tms *tmsp;
bellard32f36bc2003-03-30 21:29:48 +00004238 struct tms tms;
4239 ret = get_errno(times(&tms));
pbrook53a59602006-03-25 19:31:22 +00004240 if (arg1) {
bellard579a97f2007-11-11 14:26:47 +00004241 tmsp = lock_user(VERIFY_WRITE, arg1, sizeof(struct target_tms), 0);
4242 if (!tmsp)
4243 goto efault;
bellardc596ed12003-07-13 17:32:31 +00004244 tmsp->tms_utime = tswapl(host_to_target_clock_t(tms.tms_utime));
4245 tmsp->tms_stime = tswapl(host_to_target_clock_t(tms.tms_stime));
4246 tmsp->tms_cutime = tswapl(host_to_target_clock_t(tms.tms_cutime));
4247 tmsp->tms_cstime = tswapl(host_to_target_clock_t(tms.tms_cstime));
bellard32f36bc2003-03-30 21:29:48 +00004248 }
bellardc596ed12003-07-13 17:32:31 +00004249 if (!is_error(ret))
4250 ret = host_to_target_clock_t(ret);
bellard32f36bc2003-03-30 21:29:48 +00004251 }
4252 break;
bellardebc05482003-09-30 21:08:41 +00004253#ifdef TARGET_NR_prof
bellard31e31b82003-02-18 22:55:36 +00004254 case TARGET_NR_prof:
4255 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004256#endif
thse5febef2007-04-01 18:31:35 +00004257#ifdef TARGET_NR_signal
bellard31e31b82003-02-18 22:55:36 +00004258 case TARGET_NR_signal:
4259 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00004260#endif
bellard31e31b82003-02-18 22:55:36 +00004261 case TARGET_NR_acct:
aurel3238d840e2009-01-30 19:48:17 +00004262 if (arg1 == 0) {
4263 ret = get_errno(acct(NULL));
4264 } else {
4265 if (!(p = lock_user_string(arg1)))
4266 goto efault;
4267 ret = get_errno(acct(path(p)));
4268 unlock_user(p, arg1, 0);
4269 }
pbrook24836682006-04-16 14:14:53 +00004270 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004271#ifdef TARGET_NR_umount2 /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00004272 case TARGET_NR_umount2:
bellard579a97f2007-11-11 14:26:47 +00004273 if (!(p = lock_user_string(arg1)))
4274 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004275 ret = get_errno(umount2(p, arg2));
4276 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004277 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004278#endif
bellardebc05482003-09-30 21:08:41 +00004279#ifdef TARGET_NR_lock
bellard31e31b82003-02-18 22:55:36 +00004280 case TARGET_NR_lock:
4281 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004282#endif
bellard31e31b82003-02-18 22:55:36 +00004283 case TARGET_NR_ioctl:
4284 ret = do_ioctl(arg1, arg2, arg3);
4285 break;
4286 case TARGET_NR_fcntl:
bellard9ee1fa22007-11-11 15:11:19 +00004287 ret = do_fcntl(arg1, arg2, arg3);
bellard31e31b82003-02-18 22:55:36 +00004288 break;
bellardebc05482003-09-30 21:08:41 +00004289#ifdef TARGET_NR_mpx
bellard31e31b82003-02-18 22:55:36 +00004290 case TARGET_NR_mpx:
4291 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004292#endif
bellard31e31b82003-02-18 22:55:36 +00004293 case TARGET_NR_setpgid:
4294 ret = get_errno(setpgid(arg1, arg2));
4295 break;
bellardebc05482003-09-30 21:08:41 +00004296#ifdef TARGET_NR_ulimit
bellard31e31b82003-02-18 22:55:36 +00004297 case TARGET_NR_ulimit:
4298 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004299#endif
4300#ifdef TARGET_NR_oldolduname
bellard31e31b82003-02-18 22:55:36 +00004301 case TARGET_NR_oldolduname:
4302 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004303#endif
bellard31e31b82003-02-18 22:55:36 +00004304 case TARGET_NR_umask:
4305 ret = get_errno(umask(arg1));
4306 break;
4307 case TARGET_NR_chroot:
bellard579a97f2007-11-11 14:26:47 +00004308 if (!(p = lock_user_string(arg1)))
4309 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004310 ret = get_errno(chroot(p));
4311 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004312 break;
4313 case TARGET_NR_ustat:
4314 goto unimplemented;
4315 case TARGET_NR_dup2:
4316 ret = get_errno(dup2(arg1, arg2));
4317 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004318#ifdef TARGET_NR_getppid /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00004319 case TARGET_NR_getppid:
4320 ret = get_errno(getppid());
4321 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004322#endif
bellard31e31b82003-02-18 22:55:36 +00004323 case TARGET_NR_getpgrp:
4324 ret = get_errno(getpgrp());
4325 break;
4326 case TARGET_NR_setsid:
4327 ret = get_errno(setsid());
4328 break;
thse5febef2007-04-01 18:31:35 +00004329#ifdef TARGET_NR_sigaction
bellard31e31b82003-02-18 22:55:36 +00004330 case TARGET_NR_sigaction:
bellard31e31b82003-02-18 22:55:36 +00004331 {
ths388bb212007-05-13 13:58:00 +00004332#if !defined(TARGET_MIPS)
pbrook53a59602006-03-25 19:31:22 +00004333 struct target_old_sigaction *old_act;
bellard66fb9762003-03-23 01:06:05 +00004334 struct target_sigaction act, oact, *pact;
pbrook53a59602006-03-25 19:31:22 +00004335 if (arg2) {
bellard579a97f2007-11-11 14:26:47 +00004336 if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1))
4337 goto efault;
bellard66fb9762003-03-23 01:06:05 +00004338 act._sa_handler = old_act->_sa_handler;
4339 target_siginitset(&act.sa_mask, old_act->sa_mask);
4340 act.sa_flags = old_act->sa_flags;
4341 act.sa_restorer = old_act->sa_restorer;
pbrook53a59602006-03-25 19:31:22 +00004342 unlock_user_struct(old_act, arg2, 0);
bellard66fb9762003-03-23 01:06:05 +00004343 pact = &act;
4344 } else {
4345 pact = NULL;
4346 }
4347 ret = get_errno(do_sigaction(arg1, pact, &oact));
pbrook53a59602006-03-25 19:31:22 +00004348 if (!is_error(ret) && arg3) {
bellard579a97f2007-11-11 14:26:47 +00004349 if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0))
4350 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004351 old_act->_sa_handler = oact._sa_handler;
4352 old_act->sa_mask = oact.sa_mask.sig[0];
4353 old_act->sa_flags = oact.sa_flags;
4354 old_act->sa_restorer = oact.sa_restorer;
4355 unlock_user_struct(old_act, arg3, 1);
bellard66fb9762003-03-23 01:06:05 +00004356 }
ths388bb212007-05-13 13:58:00 +00004357#else
bellard106ec872006-06-27 21:08:10 +00004358 struct target_sigaction act, oact, *pact, *old_act;
4359
4360 if (arg2) {
bellard579a97f2007-11-11 14:26:47 +00004361 if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1))
4362 goto efault;
bellard106ec872006-06-27 21:08:10 +00004363 act._sa_handler = old_act->_sa_handler;
4364 target_siginitset(&act.sa_mask, old_act->sa_mask.sig[0]);
4365 act.sa_flags = old_act->sa_flags;
4366 unlock_user_struct(old_act, arg2, 0);
4367 pact = &act;
4368 } else {
4369 pact = NULL;
4370 }
4371
4372 ret = get_errno(do_sigaction(arg1, pact, &oact));
4373
4374 if (!is_error(ret) && arg3) {
bellard579a97f2007-11-11 14:26:47 +00004375 if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0))
4376 goto efault;
bellard106ec872006-06-27 21:08:10 +00004377 old_act->_sa_handler = oact._sa_handler;
4378 old_act->sa_flags = oact.sa_flags;
4379 old_act->sa_mask.sig[0] = oact.sa_mask.sig[0];
4380 old_act->sa_mask.sig[1] = 0;
4381 old_act->sa_mask.sig[2] = 0;
4382 old_act->sa_mask.sig[3] = 0;
4383 unlock_user_struct(old_act, arg3, 1);
4384 }
ths388bb212007-05-13 13:58:00 +00004385#endif
bellard31e31b82003-02-18 22:55:36 +00004386 }
4387 break;
thse5febef2007-04-01 18:31:35 +00004388#endif
bellard66fb9762003-03-23 01:06:05 +00004389 case TARGET_NR_rt_sigaction:
pbrook53a59602006-03-25 19:31:22 +00004390 {
4391 struct target_sigaction *act;
4392 struct target_sigaction *oact;
4393
bellard579a97f2007-11-11 14:26:47 +00004394 if (arg2) {
4395 if (!lock_user_struct(VERIFY_READ, act, arg2, 1))
4396 goto efault;
4397 } else
pbrook53a59602006-03-25 19:31:22 +00004398 act = NULL;
bellard579a97f2007-11-11 14:26:47 +00004399 if (arg3) {
4400 if (!lock_user_struct(VERIFY_WRITE, oact, arg3, 0)) {
4401 ret = -TARGET_EFAULT;
4402 goto rt_sigaction_fail;
4403 }
4404 } else
pbrook53a59602006-03-25 19:31:22 +00004405 oact = NULL;
4406 ret = get_errno(do_sigaction(arg1, act, oact));
bellard579a97f2007-11-11 14:26:47 +00004407 rt_sigaction_fail:
4408 if (act)
pbrook53a59602006-03-25 19:31:22 +00004409 unlock_user_struct(act, arg2, 0);
bellard579a97f2007-11-11 14:26:47 +00004410 if (oact)
pbrook53a59602006-03-25 19:31:22 +00004411 unlock_user_struct(oact, arg3, 1);
4412 }
bellard66fb9762003-03-23 01:06:05 +00004413 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004414#ifdef TARGET_NR_sgetmask /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00004415 case TARGET_NR_sgetmask:
bellard66fb9762003-03-23 01:06:05 +00004416 {
4417 sigset_t cur_set;
blueswir1992f48a2007-10-14 16:27:31 +00004418 abi_ulong target_set;
bellard66fb9762003-03-23 01:06:05 +00004419 sigprocmask(0, NULL, &cur_set);
4420 host_to_target_old_sigset(&target_set, &cur_set);
4421 ret = target_set;
4422 }
4423 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004424#endif
4425#ifdef TARGET_NR_ssetmask /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00004426 case TARGET_NR_ssetmask:
bellard66fb9762003-03-23 01:06:05 +00004427 {
4428 sigset_t set, oset, cur_set;
blueswir1992f48a2007-10-14 16:27:31 +00004429 abi_ulong target_set = arg1;
bellard66fb9762003-03-23 01:06:05 +00004430 sigprocmask(0, NULL, &cur_set);
4431 target_to_host_old_sigset(&set, &target_set);
4432 sigorset(&set, &set, &cur_set);
4433 sigprocmask(SIG_SETMASK, &set, &oset);
4434 host_to_target_old_sigset(&target_set, &oset);
4435 ret = target_set;
4436 }
4437 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004438#endif
thse5febef2007-04-01 18:31:35 +00004439#ifdef TARGET_NR_sigprocmask
bellard66fb9762003-03-23 01:06:05 +00004440 case TARGET_NR_sigprocmask:
4441 {
4442 int how = arg1;
4443 sigset_t set, oldset, *set_ptr;
ths3b46e622007-09-17 08:09:54 +00004444
pbrook53a59602006-03-25 19:31:22 +00004445 if (arg2) {
bellard66fb9762003-03-23 01:06:05 +00004446 switch(how) {
4447 case TARGET_SIG_BLOCK:
4448 how = SIG_BLOCK;
4449 break;
4450 case TARGET_SIG_UNBLOCK:
4451 how = SIG_UNBLOCK;
4452 break;
4453 case TARGET_SIG_SETMASK:
4454 how = SIG_SETMASK;
4455 break;
4456 default:
ths0da46a62007-10-20 20:23:07 +00004457 ret = -TARGET_EINVAL;
bellard66fb9762003-03-23 01:06:05 +00004458 goto fail;
4459 }
bellard579a97f2007-11-11 14:26:47 +00004460 if (!(p = lock_user(VERIFY_READ, arg2, sizeof(target_sigset_t), 1)))
4461 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004462 target_to_host_old_sigset(&set, p);
4463 unlock_user(p, arg2, 0);
bellard66fb9762003-03-23 01:06:05 +00004464 set_ptr = &set;
4465 } else {
4466 how = 0;
4467 set_ptr = NULL;
4468 }
4469 ret = get_errno(sigprocmask(arg1, set_ptr, &oldset));
pbrook53a59602006-03-25 19:31:22 +00004470 if (!is_error(ret) && arg3) {
bellard579a97f2007-11-11 14:26:47 +00004471 if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0)))
4472 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004473 host_to_target_old_sigset(p, &oldset);
4474 unlock_user(p, arg3, sizeof(target_sigset_t));
bellard66fb9762003-03-23 01:06:05 +00004475 }
4476 }
4477 break;
thse5febef2007-04-01 18:31:35 +00004478#endif
bellard66fb9762003-03-23 01:06:05 +00004479 case TARGET_NR_rt_sigprocmask:
4480 {
4481 int how = arg1;
4482 sigset_t set, oldset, *set_ptr;
ths3b46e622007-09-17 08:09:54 +00004483
pbrook53a59602006-03-25 19:31:22 +00004484 if (arg2) {
bellard66fb9762003-03-23 01:06:05 +00004485 switch(how) {
4486 case TARGET_SIG_BLOCK:
4487 how = SIG_BLOCK;
4488 break;
4489 case TARGET_SIG_UNBLOCK:
4490 how = SIG_UNBLOCK;
4491 break;
4492 case TARGET_SIG_SETMASK:
4493 how = SIG_SETMASK;
4494 break;
4495 default:
ths0da46a62007-10-20 20:23:07 +00004496 ret = -TARGET_EINVAL;
bellard66fb9762003-03-23 01:06:05 +00004497 goto fail;
4498 }
bellard579a97f2007-11-11 14:26:47 +00004499 if (!(p = lock_user(VERIFY_READ, arg2, sizeof(target_sigset_t), 1)))
4500 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004501 target_to_host_sigset(&set, p);
4502 unlock_user(p, arg2, 0);
bellard66fb9762003-03-23 01:06:05 +00004503 set_ptr = &set;
4504 } else {
4505 how = 0;
4506 set_ptr = NULL;
4507 }
4508 ret = get_errno(sigprocmask(how, set_ptr, &oldset));
pbrook53a59602006-03-25 19:31:22 +00004509 if (!is_error(ret) && arg3) {
bellard579a97f2007-11-11 14:26:47 +00004510 if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0)))
4511 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004512 host_to_target_sigset(p, &oldset);
4513 unlock_user(p, arg3, sizeof(target_sigset_t));
bellard66fb9762003-03-23 01:06:05 +00004514 }
4515 }
4516 break;
thse5febef2007-04-01 18:31:35 +00004517#ifdef TARGET_NR_sigpending
bellard66fb9762003-03-23 01:06:05 +00004518 case TARGET_NR_sigpending:
4519 {
4520 sigset_t set;
4521 ret = get_errno(sigpending(&set));
4522 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00004523 if (!(p = lock_user(VERIFY_WRITE, arg1, sizeof(target_sigset_t), 0)))
4524 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004525 host_to_target_old_sigset(p, &set);
4526 unlock_user(p, arg1, sizeof(target_sigset_t));
bellard66fb9762003-03-23 01:06:05 +00004527 }
4528 }
4529 break;
thse5febef2007-04-01 18:31:35 +00004530#endif
bellard66fb9762003-03-23 01:06:05 +00004531 case TARGET_NR_rt_sigpending:
4532 {
4533 sigset_t set;
4534 ret = get_errno(sigpending(&set));
4535 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00004536 if (!(p = lock_user(VERIFY_WRITE, arg1, sizeof(target_sigset_t), 0)))
4537 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004538 host_to_target_sigset(p, &set);
4539 unlock_user(p, arg1, sizeof(target_sigset_t));
bellard66fb9762003-03-23 01:06:05 +00004540 }
4541 }
4542 break;
thse5febef2007-04-01 18:31:35 +00004543#ifdef TARGET_NR_sigsuspend
bellard66fb9762003-03-23 01:06:05 +00004544 case TARGET_NR_sigsuspend:
4545 {
4546 sigset_t set;
bellard579a97f2007-11-11 14:26:47 +00004547 if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
4548 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004549 target_to_host_old_sigset(&set, p);
4550 unlock_user(p, arg1, 0);
bellard66fb9762003-03-23 01:06:05 +00004551 ret = get_errno(sigsuspend(&set));
4552 }
4553 break;
thse5febef2007-04-01 18:31:35 +00004554#endif
bellard66fb9762003-03-23 01:06:05 +00004555 case TARGET_NR_rt_sigsuspend:
4556 {
4557 sigset_t set;
bellard579a97f2007-11-11 14:26:47 +00004558 if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
4559 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004560 target_to_host_sigset(&set, p);
4561 unlock_user(p, arg1, 0);
bellard66fb9762003-03-23 01:06:05 +00004562 ret = get_errno(sigsuspend(&set));
4563 }
4564 break;
4565 case TARGET_NR_rt_sigtimedwait:
4566 {
bellard66fb9762003-03-23 01:06:05 +00004567 sigset_t set;
4568 struct timespec uts, *puts;
4569 siginfo_t uinfo;
ths3b46e622007-09-17 08:09:54 +00004570
bellard579a97f2007-11-11 14:26:47 +00004571 if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
4572 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004573 target_to_host_sigset(&set, p);
4574 unlock_user(p, arg1, 0);
4575 if (arg3) {
bellard66fb9762003-03-23 01:06:05 +00004576 puts = &uts;
pbrook53a59602006-03-25 19:31:22 +00004577 target_to_host_timespec(puts, arg3);
bellard66fb9762003-03-23 01:06:05 +00004578 } else {
4579 puts = NULL;
4580 }
4581 ret = get_errno(sigtimedwait(&set, &uinfo, puts));
pbrook53a59602006-03-25 19:31:22 +00004582 if (!is_error(ret) && arg2) {
pbrooke1e3f302008-05-30 21:53:38 +00004583 if (!(p = lock_user(VERIFY_WRITE, arg2, sizeof(target_siginfo_t), 0)))
bellard579a97f2007-11-11 14:26:47 +00004584 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004585 host_to_target_siginfo(p, &uinfo);
pbrooke1e3f302008-05-30 21:53:38 +00004586 unlock_user(p, arg2, sizeof(target_siginfo_t));
bellard66fb9762003-03-23 01:06:05 +00004587 }
4588 }
4589 break;
4590 case TARGET_NR_rt_sigqueueinfo:
4591 {
4592 siginfo_t uinfo;
bellard579a97f2007-11-11 14:26:47 +00004593 if (!(p = lock_user(VERIFY_READ, arg3, sizeof(target_sigset_t), 1)))
4594 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004595 target_to_host_siginfo(&uinfo, p);
4596 unlock_user(p, arg1, 0);
bellard66fb9762003-03-23 01:06:05 +00004597 ret = get_errno(sys_rt_sigqueueinfo(arg1, arg2, &uinfo));
4598 }
4599 break;
thse5febef2007-04-01 18:31:35 +00004600#ifdef TARGET_NR_sigreturn
bellard66fb9762003-03-23 01:06:05 +00004601 case TARGET_NR_sigreturn:
4602 /* NOTE: ret is eax, so not transcoding must be done */
4603 ret = do_sigreturn(cpu_env);
4604 break;
thse5febef2007-04-01 18:31:35 +00004605#endif
bellard66fb9762003-03-23 01:06:05 +00004606 case TARGET_NR_rt_sigreturn:
4607 /* NOTE: ret is eax, so not transcoding must be done */
4608 ret = do_rt_sigreturn(cpu_env);
4609 break;
bellard31e31b82003-02-18 22:55:36 +00004610 case TARGET_NR_sethostname:
bellard579a97f2007-11-11 14:26:47 +00004611 if (!(p = lock_user_string(arg1)))
4612 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004613 ret = get_errno(sethostname(p, arg2));
4614 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004615 break;
4616 case TARGET_NR_setrlimit:
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;
bellard579a97f2007-11-11 14:26:47 +00004622 if (!lock_user_struct(VERIFY_READ, target_rlim, arg2, 1))
4623 goto efault;
bellard9de5e442003-03-23 16:49:39 +00004624 rlim.rlim_cur = tswapl(target_rlim->rlim_cur);
4625 rlim.rlim_max = tswapl(target_rlim->rlim_max);
pbrook53a59602006-03-25 19:31:22 +00004626 unlock_user_struct(target_rlim, arg2, 0);
bellard9de5e442003-03-23 16:49:39 +00004627 ret = get_errno(setrlimit(resource, &rlim));
4628 }
4629 break;
bellard31e31b82003-02-18 22:55:36 +00004630 case TARGET_NR_getrlimit:
bellard9de5e442003-03-23 16:49:39 +00004631 {
4632 /* XXX: convert resource ? */
4633 int resource = arg1;
pbrook53a59602006-03-25 19:31:22 +00004634 struct target_rlimit *target_rlim;
bellard9de5e442003-03-23 16:49:39 +00004635 struct rlimit rlim;
ths3b46e622007-09-17 08:09:54 +00004636
bellard9de5e442003-03-23 16:49:39 +00004637 ret = get_errno(getrlimit(resource, &rlim));
4638 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00004639 if (!lock_user_struct(VERIFY_WRITE, target_rlim, arg2, 0))
4640 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004641 rlim.rlim_cur = tswapl(target_rlim->rlim_cur);
4642 rlim.rlim_max = tswapl(target_rlim->rlim_max);
4643 unlock_user_struct(target_rlim, arg2, 1);
bellard9de5e442003-03-23 16:49:39 +00004644 }
4645 }
4646 break;
bellard31e31b82003-02-18 22:55:36 +00004647 case TARGET_NR_getrusage:
bellardb4091862003-05-16 15:39:34 +00004648 {
4649 struct rusage rusage;
bellardb4091862003-05-16 15:39:34 +00004650 ret = get_errno(getrusage(arg1, &rusage));
4651 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00004652 host_to_target_rusage(arg2, &rusage);
bellardb4091862003-05-16 15:39:34 +00004653 }
4654 }
4655 break;
bellard31e31b82003-02-18 22:55:36 +00004656 case TARGET_NR_gettimeofday:
4657 {
bellard31e31b82003-02-18 22:55:36 +00004658 struct timeval tv;
4659 ret = get_errno(gettimeofday(&tv, NULL));
4660 if (!is_error(ret)) {
ths788f5ec2007-12-09 02:37:05 +00004661 if (copy_to_user_timeval(arg1, &tv))
4662 goto efault;
bellard31e31b82003-02-18 22:55:36 +00004663 }
4664 }
4665 break;
4666 case TARGET_NR_settimeofday:
4667 {
bellard31e31b82003-02-18 22:55:36 +00004668 struct timeval tv;
ths788f5ec2007-12-09 02:37:05 +00004669 if (copy_from_user_timeval(&tv, arg1))
4670 goto efault;
bellard31e31b82003-02-18 22:55:36 +00004671 ret = get_errno(settimeofday(&tv, NULL));
4672 }
4673 break;
bellard048f6b42005-11-26 18:47:20 +00004674#ifdef TARGET_NR_select
bellard31e31b82003-02-18 22:55:36 +00004675 case TARGET_NR_select:
bellardf2674e32003-07-09 12:26:09 +00004676 {
pbrook53a59602006-03-25 19:31:22 +00004677 struct target_sel_arg_struct *sel;
blueswir1992f48a2007-10-14 16:27:31 +00004678 abi_ulong inp, outp, exp, tvp;
pbrook53a59602006-03-25 19:31:22 +00004679 long nsel;
4680
bellard579a97f2007-11-11 14:26:47 +00004681 if (!lock_user_struct(VERIFY_READ, sel, arg1, 1))
4682 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004683 nsel = tswapl(sel->n);
4684 inp = tswapl(sel->inp);
4685 outp = tswapl(sel->outp);
4686 exp = tswapl(sel->exp);
4687 tvp = tswapl(sel->tvp);
4688 unlock_user_struct(sel, arg1, 0);
4689 ret = do_select(nsel, inp, outp, exp, tvp);
bellardf2674e32003-07-09 12:26:09 +00004690 }
4691 break;
bellard048f6b42005-11-26 18:47:20 +00004692#endif
bellard31e31b82003-02-18 22:55:36 +00004693 case TARGET_NR_symlink:
pbrook53a59602006-03-25 19:31:22 +00004694 {
4695 void *p2;
4696 p = lock_user_string(arg1);
4697 p2 = lock_user_string(arg2);
bellard579a97f2007-11-11 14:26:47 +00004698 if (!p || !p2)
4699 ret = -TARGET_EFAULT;
4700 else
4701 ret = get_errno(symlink(p, p2));
pbrook53a59602006-03-25 19:31:22 +00004702 unlock_user(p2, arg2, 0);
4703 unlock_user(p, arg1, 0);
4704 }
bellard31e31b82003-02-18 22:55:36 +00004705 break;
thsf0b62432007-09-24 09:25:40 +00004706#if defined(TARGET_NR_symlinkat) && defined(__NR_symlinkat)
4707 case TARGET_NR_symlinkat:
thsf0b62432007-09-24 09:25:40 +00004708 {
bellard579a97f2007-11-11 14:26:47 +00004709 void *p2;
thsf0b62432007-09-24 09:25:40 +00004710 p = lock_user_string(arg1);
4711 p2 = lock_user_string(arg3);
bellard579a97f2007-11-11 14:26:47 +00004712 if (!p || !p2)
ths0da46a62007-10-20 20:23:07 +00004713 ret = -TARGET_EFAULT;
thsf0b62432007-09-24 09:25:40 +00004714 else
4715 ret = get_errno(sys_symlinkat(p, arg2, p2));
bellard579a97f2007-11-11 14:26:47 +00004716 unlock_user(p2, arg3, 0);
4717 unlock_user(p, arg1, 0);
thsf0b62432007-09-24 09:25:40 +00004718 }
4719 break;
4720#endif
bellardebc05482003-09-30 21:08:41 +00004721#ifdef TARGET_NR_oldlstat
bellard31e31b82003-02-18 22:55:36 +00004722 case TARGET_NR_oldlstat:
4723 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004724#endif
bellard31e31b82003-02-18 22:55:36 +00004725 case TARGET_NR_readlink:
pbrook53a59602006-03-25 19:31:22 +00004726 {
aurel32d088d662009-01-30 20:09:01 +00004727 void *p2, *temp;
pbrook53a59602006-03-25 19:31:22 +00004728 p = lock_user_string(arg1);
bellard579a97f2007-11-11 14:26:47 +00004729 p2 = lock_user(VERIFY_WRITE, arg2, arg3, 0);
4730 if (!p || !p2)
4731 ret = -TARGET_EFAULT;
aurel32d088d662009-01-30 20:09:01 +00004732 else {
4733 if (strncmp((const char *)p, "/proc/self/exe", 14) == 0) {
4734 char real[PATH_MAX];
4735 temp = realpath(exec_path,real);
4736 ret = (temp==NULL) ? get_errno(-1) : strlen(real) ;
4737 snprintf((char *)p2, arg3, "%s", real);
4738 }
4739 else
4740 ret = get_errno(readlink(path(p), p2, arg3));
aurel32d088d662009-01-30 20:09:01 +00004741 }
pbrook53a59602006-03-25 19:31:22 +00004742 unlock_user(p2, arg2, ret);
4743 unlock_user(p, arg1, 0);
4744 }
bellard31e31b82003-02-18 22:55:36 +00004745 break;
ths5e0ccb12007-09-24 09:26:10 +00004746#if defined(TARGET_NR_readlinkat) && defined(__NR_readlinkat)
4747 case TARGET_NR_readlinkat:
ths5e0ccb12007-09-24 09:26:10 +00004748 {
bellard579a97f2007-11-11 14:26:47 +00004749 void *p2;
ths5e0ccb12007-09-24 09:26:10 +00004750 p = lock_user_string(arg2);
bellard579a97f2007-11-11 14:26:47 +00004751 p2 = lock_user(VERIFY_WRITE, arg3, arg4, 0);
4752 if (!p || !p2)
ths0da46a62007-10-20 20:23:07 +00004753 ret = -TARGET_EFAULT;
ths5e0ccb12007-09-24 09:26:10 +00004754 else
4755 ret = get_errno(sys_readlinkat(arg1, path(p), p2, arg4));
bellard579a97f2007-11-11 14:26:47 +00004756 unlock_user(p2, arg3, ret);
4757 unlock_user(p, arg2, 0);
ths5e0ccb12007-09-24 09:26:10 +00004758 }
4759 break;
4760#endif
thse5febef2007-04-01 18:31:35 +00004761#ifdef TARGET_NR_uselib
bellard31e31b82003-02-18 22:55:36 +00004762 case TARGET_NR_uselib:
4763 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00004764#endif
4765#ifdef TARGET_NR_swapon
bellard31e31b82003-02-18 22:55:36 +00004766 case TARGET_NR_swapon:
bellard579a97f2007-11-11 14:26:47 +00004767 if (!(p = lock_user_string(arg1)))
4768 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004769 ret = get_errno(swapon(p, arg2));
4770 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004771 break;
thse5febef2007-04-01 18:31:35 +00004772#endif
bellard31e31b82003-02-18 22:55:36 +00004773 case TARGET_NR_reboot:
4774 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00004775#ifdef TARGET_NR_readdir
bellard31e31b82003-02-18 22:55:36 +00004776 case TARGET_NR_readdir:
4777 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00004778#endif
4779#ifdef TARGET_NR_mmap
bellard31e31b82003-02-18 22:55:36 +00004780 case TARGET_NR_mmap:
bellardd2fd1af2007-11-14 18:08:56 +00004781#if (defined(TARGET_I386) && defined(TARGET_ABI32)) || defined(TARGET_ARM) || defined(TARGET_M68K) || defined(TARGET_CRIS)
bellard31e31b82003-02-18 22:55:36 +00004782 {
blueswir1992f48a2007-10-14 16:27:31 +00004783 abi_ulong *v;
4784 abi_ulong v1, v2, v3, v4, v5, v6;
bellard579a97f2007-11-11 14:26:47 +00004785 if (!(v = lock_user(VERIFY_READ, arg1, 6 * sizeof(abi_ulong), 1)))
4786 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004787 v1 = tswapl(v[0]);
4788 v2 = tswapl(v[1]);
4789 v3 = tswapl(v[2]);
4790 v4 = tswapl(v[3]);
4791 v5 = tswapl(v[4]);
4792 v6 = tswapl(v[5]);
4793 unlock_user(v, arg1, 0);
ths5fafdf22007-09-16 21:08:06 +00004794 ret = get_errno(target_mmap(v1, v2, v3,
bellard5286db72003-06-05 00:57:30 +00004795 target_to_host_bitmask(v4, mmap_flags_tbl),
4796 v5, v6));
bellard31e31b82003-02-18 22:55:36 +00004797 }
bellard31e31b82003-02-18 22:55:36 +00004798#else
ths5fafdf22007-09-16 21:08:06 +00004799 ret = get_errno(target_mmap(arg1, arg2, arg3,
4800 target_to_host_bitmask(arg4, mmap_flags_tbl),
bellard6fb883e2003-07-09 17:12:39 +00004801 arg5,
4802 arg6));
bellard31e31b82003-02-18 22:55:36 +00004803#endif
bellard6fb883e2003-07-09 17:12:39 +00004804 break;
thse5febef2007-04-01 18:31:35 +00004805#endif
bellarda315a142005-01-30 22:59:18 +00004806#ifdef TARGET_NR_mmap2
bellard6fb883e2003-07-09 17:12:39 +00004807 case TARGET_NR_mmap2:
pbrookbb7ec042008-03-25 22:28:25 +00004808#ifndef MMAP_SHIFT
bellardc573ff62004-01-04 15:51:36 +00004809#define MMAP_SHIFT 12
bellardc573ff62004-01-04 15:51:36 +00004810#endif
ths5fafdf22007-09-16 21:08:06 +00004811 ret = get_errno(target_mmap(arg1, arg2, arg3,
4812 target_to_host_bitmask(arg4, mmap_flags_tbl),
bellard5286db72003-06-05 00:57:30 +00004813 arg5,
bellardc573ff62004-01-04 15:51:36 +00004814 arg6 << MMAP_SHIFT));
bellard31e31b82003-02-18 22:55:36 +00004815 break;
bellarda315a142005-01-30 22:59:18 +00004816#endif
bellard31e31b82003-02-18 22:55:36 +00004817 case TARGET_NR_munmap:
bellard54936002003-05-13 00:25:15 +00004818 ret = get_errno(target_munmap(arg1, arg2));
bellard31e31b82003-02-18 22:55:36 +00004819 break;
bellard9de5e442003-03-23 16:49:39 +00004820 case TARGET_NR_mprotect:
bellard54936002003-05-13 00:25:15 +00004821 ret = get_errno(target_mprotect(arg1, arg2, arg3));
bellard9de5e442003-03-23 16:49:39 +00004822 break;
thse5febef2007-04-01 18:31:35 +00004823#ifdef TARGET_NR_mremap
bellard9de5e442003-03-23 16:49:39 +00004824 case TARGET_NR_mremap:
bellard54936002003-05-13 00:25:15 +00004825 ret = get_errno(target_mremap(arg1, arg2, arg3, arg4, arg5));
bellard9de5e442003-03-23 16:49:39 +00004826 break;
thse5febef2007-04-01 18:31:35 +00004827#endif
pbrook53a59602006-03-25 19:31:22 +00004828 /* ??? msync/mlock/munlock are broken for softmmu. */
thse5febef2007-04-01 18:31:35 +00004829#ifdef TARGET_NR_msync
bellard9de5e442003-03-23 16:49:39 +00004830 case TARGET_NR_msync:
pbrook53a59602006-03-25 19:31:22 +00004831 ret = get_errno(msync(g2h(arg1), arg2, arg3));
bellard9de5e442003-03-23 16:49:39 +00004832 break;
thse5febef2007-04-01 18:31:35 +00004833#endif
4834#ifdef TARGET_NR_mlock
bellard9de5e442003-03-23 16:49:39 +00004835 case TARGET_NR_mlock:
pbrook53a59602006-03-25 19:31:22 +00004836 ret = get_errno(mlock(g2h(arg1), arg2));
bellard9de5e442003-03-23 16:49:39 +00004837 break;
thse5febef2007-04-01 18:31:35 +00004838#endif
4839#ifdef TARGET_NR_munlock
bellard9de5e442003-03-23 16:49:39 +00004840 case TARGET_NR_munlock:
pbrook53a59602006-03-25 19:31:22 +00004841 ret = get_errno(munlock(g2h(arg1), arg2));
bellard9de5e442003-03-23 16:49:39 +00004842 break;
thse5febef2007-04-01 18:31:35 +00004843#endif
4844#ifdef TARGET_NR_mlockall
bellard9de5e442003-03-23 16:49:39 +00004845 case TARGET_NR_mlockall:
4846 ret = get_errno(mlockall(arg1));
4847 break;
thse5febef2007-04-01 18:31:35 +00004848#endif
4849#ifdef TARGET_NR_munlockall
bellard9de5e442003-03-23 16:49:39 +00004850 case TARGET_NR_munlockall:
4851 ret = get_errno(munlockall());
4852 break;
thse5febef2007-04-01 18:31:35 +00004853#endif
bellard31e31b82003-02-18 22:55:36 +00004854 case TARGET_NR_truncate:
bellard579a97f2007-11-11 14:26:47 +00004855 if (!(p = lock_user_string(arg1)))
4856 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004857 ret = get_errno(truncate(p, arg2));
4858 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004859 break;
4860 case TARGET_NR_ftruncate:
4861 ret = get_errno(ftruncate(arg1, arg2));
4862 break;
4863 case TARGET_NR_fchmod:
4864 ret = get_errno(fchmod(arg1, arg2));
4865 break;
ths814d7972007-09-24 09:26:51 +00004866#if defined(TARGET_NR_fchmodat) && defined(__NR_fchmodat)
4867 case TARGET_NR_fchmodat:
bellard579a97f2007-11-11 14:26:47 +00004868 if (!(p = lock_user_string(arg2)))
4869 goto efault;
4870 ret = get_errno(sys_fchmodat(arg1, p, arg3, arg4));
4871 unlock_user(p, arg2, 0);
ths814d7972007-09-24 09:26:51 +00004872 break;
4873#endif
bellard31e31b82003-02-18 22:55:36 +00004874 case TARGET_NR_getpriority:
thsc6cda172007-10-09 03:42:34 +00004875 /* libc does special remapping of the return value of
4876 * sys_getpriority() so it's just easiest to call
4877 * sys_getpriority() directly rather than through libc. */
4878 ret = sys_getpriority(arg1, arg2);
bellard31e31b82003-02-18 22:55:36 +00004879 break;
4880 case TARGET_NR_setpriority:
4881 ret = get_errno(setpriority(arg1, arg2, arg3));
4882 break;
bellardebc05482003-09-30 21:08:41 +00004883#ifdef TARGET_NR_profil
bellard31e31b82003-02-18 22:55:36 +00004884 case TARGET_NR_profil:
4885 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004886#endif
bellard31e31b82003-02-18 22:55:36 +00004887 case TARGET_NR_statfs:
bellard579a97f2007-11-11 14:26:47 +00004888 if (!(p = lock_user_string(arg1)))
4889 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004890 ret = get_errno(statfs(path(p), &stfs));
4891 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004892 convert_statfs:
4893 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00004894 struct target_statfs *target_stfs;
ths3b46e622007-09-17 08:09:54 +00004895
bellard579a97f2007-11-11 14:26:47 +00004896 if (!lock_user_struct(VERIFY_WRITE, target_stfs, arg2, 0))
4897 goto efault;
4898 __put_user(stfs.f_type, &target_stfs->f_type);
4899 __put_user(stfs.f_bsize, &target_stfs->f_bsize);
4900 __put_user(stfs.f_blocks, &target_stfs->f_blocks);
4901 __put_user(stfs.f_bfree, &target_stfs->f_bfree);
4902 __put_user(stfs.f_bavail, &target_stfs->f_bavail);
4903 __put_user(stfs.f_files, &target_stfs->f_files);
4904 __put_user(stfs.f_ffree, &target_stfs->f_ffree);
4905 __put_user(stfs.f_fsid.__val[0], &target_stfs->f_fsid.val[0]);
4906 __put_user(stfs.f_fsid.__val[1], &target_stfs->f_fsid.val[1]);
4907 __put_user(stfs.f_namelen, &target_stfs->f_namelen);
pbrook53a59602006-03-25 19:31:22 +00004908 unlock_user_struct(target_stfs, arg2, 1);
bellard31e31b82003-02-18 22:55:36 +00004909 }
4910 break;
4911 case TARGET_NR_fstatfs:
bellard56c8f682005-11-28 22:28:41 +00004912 ret = get_errno(fstatfs(arg1, &stfs));
bellard31e31b82003-02-18 22:55:36 +00004913 goto convert_statfs;
bellard56c8f682005-11-28 22:28:41 +00004914#ifdef TARGET_NR_statfs64
4915 case TARGET_NR_statfs64:
bellard579a97f2007-11-11 14:26:47 +00004916 if (!(p = lock_user_string(arg1)))
4917 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004918 ret = get_errno(statfs(path(p), &stfs));
4919 unlock_user(p, arg1, 0);
bellard56c8f682005-11-28 22:28:41 +00004920 convert_statfs64:
4921 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00004922 struct target_statfs64 *target_stfs;
ths3b46e622007-09-17 08:09:54 +00004923
bellard579a97f2007-11-11 14:26:47 +00004924 if (!lock_user_struct(VERIFY_WRITE, target_stfs, arg3, 0))
4925 goto efault;
4926 __put_user(stfs.f_type, &target_stfs->f_type);
4927 __put_user(stfs.f_bsize, &target_stfs->f_bsize);
4928 __put_user(stfs.f_blocks, &target_stfs->f_blocks);
4929 __put_user(stfs.f_bfree, &target_stfs->f_bfree);
4930 __put_user(stfs.f_bavail, &target_stfs->f_bavail);
4931 __put_user(stfs.f_files, &target_stfs->f_files);
4932 __put_user(stfs.f_ffree, &target_stfs->f_ffree);
4933 __put_user(stfs.f_fsid.__val[0], &target_stfs->f_fsid.val[0]);
4934 __put_user(stfs.f_fsid.__val[1], &target_stfs->f_fsid.val[1]);
4935 __put_user(stfs.f_namelen, &target_stfs->f_namelen);
4936 unlock_user_struct(target_stfs, arg3, 1);
bellard56c8f682005-11-28 22:28:41 +00004937 }
4938 break;
4939 case TARGET_NR_fstatfs64:
4940 ret = get_errno(fstatfs(arg1, &stfs));
4941 goto convert_statfs64;
4942#endif
bellardebc05482003-09-30 21:08:41 +00004943#ifdef TARGET_NR_ioperm
bellard31e31b82003-02-18 22:55:36 +00004944 case TARGET_NR_ioperm:
4945 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004946#endif
thse5febef2007-04-01 18:31:35 +00004947#ifdef TARGET_NR_socketcall
bellard31e31b82003-02-18 22:55:36 +00004948 case TARGET_NR_socketcall:
pbrook53a59602006-03-25 19:31:22 +00004949 ret = do_socketcall(arg1, arg2);
bellard31e31b82003-02-18 22:55:36 +00004950 break;
thse5febef2007-04-01 18:31:35 +00004951#endif
bellard3532fa72006-06-24 15:06:03 +00004952#ifdef TARGET_NR_accept
4953 case TARGET_NR_accept:
pbrook1be9e1d2006-11-19 15:26:04 +00004954 ret = do_accept(arg1, arg2, arg3);
bellard3532fa72006-06-24 15:06:03 +00004955 break;
4956#endif
4957#ifdef TARGET_NR_bind
4958 case TARGET_NR_bind:
4959 ret = do_bind(arg1, arg2, arg3);
4960 break;
4961#endif
4962#ifdef TARGET_NR_connect
4963 case TARGET_NR_connect:
4964 ret = do_connect(arg1, arg2, arg3);
4965 break;
4966#endif
4967#ifdef TARGET_NR_getpeername
4968 case TARGET_NR_getpeername:
pbrook1be9e1d2006-11-19 15:26:04 +00004969 ret = do_getpeername(arg1, arg2, arg3);
bellard3532fa72006-06-24 15:06:03 +00004970 break;
4971#endif
4972#ifdef TARGET_NR_getsockname
4973 case TARGET_NR_getsockname:
pbrook1be9e1d2006-11-19 15:26:04 +00004974 ret = do_getsockname(arg1, arg2, arg3);
bellard3532fa72006-06-24 15:06:03 +00004975 break;
4976#endif
4977#ifdef TARGET_NR_getsockopt
4978 case TARGET_NR_getsockopt:
4979 ret = do_getsockopt(arg1, arg2, arg3, arg4, arg5);
4980 break;
4981#endif
4982#ifdef TARGET_NR_listen
4983 case TARGET_NR_listen:
pbrook1be9e1d2006-11-19 15:26:04 +00004984 ret = get_errno(listen(arg1, arg2));
bellard3532fa72006-06-24 15:06:03 +00004985 break;
4986#endif
4987#ifdef TARGET_NR_recv
4988 case TARGET_NR_recv:
pbrook214201b2007-03-17 01:27:24 +00004989 ret = do_recvfrom(arg1, arg2, arg3, arg4, 0, 0);
bellard3532fa72006-06-24 15:06:03 +00004990 break;
4991#endif
4992#ifdef TARGET_NR_recvfrom
4993 case TARGET_NR_recvfrom:
pbrook214201b2007-03-17 01:27:24 +00004994 ret = do_recvfrom(arg1, arg2, arg3, arg4, arg5, arg6);
bellard3532fa72006-06-24 15:06:03 +00004995 break;
4996#endif
4997#ifdef TARGET_NR_recvmsg
4998 case TARGET_NR_recvmsg:
4999 ret = do_sendrecvmsg(arg1, arg2, arg3, 0);
5000 break;
5001#endif
5002#ifdef TARGET_NR_send
5003 case TARGET_NR_send:
pbrook1be9e1d2006-11-19 15:26:04 +00005004 ret = do_sendto(arg1, arg2, arg3, arg4, 0, 0);
bellard3532fa72006-06-24 15:06:03 +00005005 break;
5006#endif
5007#ifdef TARGET_NR_sendmsg
5008 case TARGET_NR_sendmsg:
5009 ret = do_sendrecvmsg(arg1, arg2, arg3, 1);
5010 break;
5011#endif
5012#ifdef TARGET_NR_sendto
5013 case TARGET_NR_sendto:
pbrook1be9e1d2006-11-19 15:26:04 +00005014 ret = do_sendto(arg1, arg2, arg3, arg4, arg5, arg6);
bellard3532fa72006-06-24 15:06:03 +00005015 break;
5016#endif
5017#ifdef TARGET_NR_shutdown
5018 case TARGET_NR_shutdown:
pbrook1be9e1d2006-11-19 15:26:04 +00005019 ret = get_errno(shutdown(arg1, arg2));
bellard3532fa72006-06-24 15:06:03 +00005020 break;
5021#endif
5022#ifdef TARGET_NR_socket
5023 case TARGET_NR_socket:
5024 ret = do_socket(arg1, arg2, arg3);
5025 break;
5026#endif
5027#ifdef TARGET_NR_socketpair
5028 case TARGET_NR_socketpair:
pbrook1be9e1d2006-11-19 15:26:04 +00005029 ret = do_socketpair(arg1, arg2, arg3, arg4);
bellard3532fa72006-06-24 15:06:03 +00005030 break;
5031#endif
5032#ifdef TARGET_NR_setsockopt
5033 case TARGET_NR_setsockopt:
5034 ret = do_setsockopt(arg1, arg2, arg3, arg4, (socklen_t) arg5);
5035 break;
5036#endif
ths7494b0f2007-02-11 18:26:53 +00005037
bellard31e31b82003-02-18 22:55:36 +00005038 case TARGET_NR_syslog:
bellard579a97f2007-11-11 14:26:47 +00005039 if (!(p = lock_user_string(arg2)))
5040 goto efault;
thse5574482007-02-11 20:03:13 +00005041 ret = get_errno(sys_syslog((int)arg1, p, (int)arg3));
5042 unlock_user(p, arg2, 0);
ths7494b0f2007-02-11 18:26:53 +00005043 break;
5044
bellard31e31b82003-02-18 22:55:36 +00005045 case TARGET_NR_setitimer:
bellard66fb9762003-03-23 01:06:05 +00005046 {
bellard66fb9762003-03-23 01:06:05 +00005047 struct itimerval value, ovalue, *pvalue;
5048
pbrook53a59602006-03-25 19:31:22 +00005049 if (arg2) {
bellard66fb9762003-03-23 01:06:05 +00005050 pvalue = &value;
ths788f5ec2007-12-09 02:37:05 +00005051 if (copy_from_user_timeval(&pvalue->it_interval, arg2)
5052 || copy_from_user_timeval(&pvalue->it_value,
5053 arg2 + sizeof(struct target_timeval)))
5054 goto efault;
bellard66fb9762003-03-23 01:06:05 +00005055 } else {
5056 pvalue = NULL;
5057 }
5058 ret = get_errno(setitimer(arg1, pvalue, &ovalue));
pbrook53a59602006-03-25 19:31:22 +00005059 if (!is_error(ret) && arg3) {
ths788f5ec2007-12-09 02:37:05 +00005060 if (copy_to_user_timeval(arg3,
5061 &ovalue.it_interval)
5062 || copy_to_user_timeval(arg3 + sizeof(struct target_timeval),
5063 &ovalue.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_getitimer:
bellard66fb9762003-03-23 01:06:05 +00005069 {
bellard66fb9762003-03-23 01:06:05 +00005070 struct itimerval value;
ths3b46e622007-09-17 08:09:54 +00005071
bellard66fb9762003-03-23 01:06:05 +00005072 ret = get_errno(getitimer(arg1, &value));
pbrook53a59602006-03-25 19:31:22 +00005073 if (!is_error(ret) && arg2) {
ths788f5ec2007-12-09 02:37:05 +00005074 if (copy_to_user_timeval(arg2,
5075 &value.it_interval)
5076 || copy_to_user_timeval(arg2 + sizeof(struct target_timeval),
5077 &value.it_value))
5078 goto efault;
bellard66fb9762003-03-23 01:06:05 +00005079 }
5080 }
5081 break;
bellard31e31b82003-02-18 22:55:36 +00005082 case TARGET_NR_stat:
bellard579a97f2007-11-11 14:26:47 +00005083 if (!(p = lock_user_string(arg1)))
5084 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005085 ret = get_errno(stat(path(p), &st));
5086 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00005087 goto do_stat;
5088 case TARGET_NR_lstat:
bellard579a97f2007-11-11 14:26:47 +00005089 if (!(p = lock_user_string(arg1)))
5090 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005091 ret = get_errno(lstat(path(p), &st));
5092 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00005093 goto do_stat;
5094 case TARGET_NR_fstat:
5095 {
5096 ret = get_errno(fstat(arg1, &st));
5097 do_stat:
5098 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00005099 struct target_stat *target_st;
thse3584652007-06-01 11:49:38 +00005100
bellard579a97f2007-11-11 14:26:47 +00005101 if (!lock_user_struct(VERIFY_WRITE, target_st, arg2, 0))
5102 goto efault;
bellardd2fd1af2007-11-14 18:08:56 +00005103 __put_user(st.st_dev, &target_st->st_dev);
5104 __put_user(st.st_ino, &target_st->st_ino);
5105 __put_user(st.st_mode, &target_st->st_mode);
5106 __put_user(st.st_uid, &target_st->st_uid);
5107 __put_user(st.st_gid, &target_st->st_gid);
5108 __put_user(st.st_nlink, &target_st->st_nlink);
5109 __put_user(st.st_rdev, &target_st->st_rdev);
5110 __put_user(st.st_size, &target_st->st_size);
5111 __put_user(st.st_blksize, &target_st->st_blksize);
5112 __put_user(st.st_blocks, &target_st->st_blocks);
5113 __put_user(st.st_atime, &target_st->target_st_atime);
5114 __put_user(st.st_mtime, &target_st->target_st_mtime);
5115 __put_user(st.st_ctime, &target_st->target_st_ctime);
pbrook53a59602006-03-25 19:31:22 +00005116 unlock_user_struct(target_st, arg2, 1);
bellard31e31b82003-02-18 22:55:36 +00005117 }
5118 }
5119 break;
bellardebc05482003-09-30 21:08:41 +00005120#ifdef TARGET_NR_olduname
bellard31e31b82003-02-18 22:55:36 +00005121 case TARGET_NR_olduname:
5122 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00005123#endif
5124#ifdef TARGET_NR_iopl
bellard31e31b82003-02-18 22:55:36 +00005125 case TARGET_NR_iopl:
5126 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00005127#endif
bellard31e31b82003-02-18 22:55:36 +00005128 case TARGET_NR_vhangup:
5129 ret = get_errno(vhangup());
5130 break;
bellardebc05482003-09-30 21:08:41 +00005131#ifdef TARGET_NR_idle
bellard31e31b82003-02-18 22:55:36 +00005132 case TARGET_NR_idle:
5133 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00005134#endif
bellard42ad6ae2005-01-03 22:48:11 +00005135#ifdef TARGET_NR_syscall
5136 case TARGET_NR_syscall:
5137 ret = do_syscall(cpu_env,arg1 & 0xffff,arg2,arg3,arg4,arg5,arg6,0);
5138 break;
5139#endif
bellard31e31b82003-02-18 22:55:36 +00005140 case TARGET_NR_wait4:
5141 {
5142 int status;
blueswir1992f48a2007-10-14 16:27:31 +00005143 abi_long status_ptr = arg2;
bellard31e31b82003-02-18 22:55:36 +00005144 struct rusage rusage, *rusage_ptr;
blueswir1992f48a2007-10-14 16:27:31 +00005145 abi_ulong target_rusage = arg4;
bellard31e31b82003-02-18 22:55:36 +00005146 if (target_rusage)
5147 rusage_ptr = &rusage;
5148 else
5149 rusage_ptr = NULL;
5150 ret = get_errno(wait4(arg1, &status, arg3, rusage_ptr));
5151 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +00005152 if (status_ptr) {
pbrook1d9d8b52009-04-16 15:17:02 +00005153 status = host_to_target_waitstatus(status);
bellard2f619692007-11-16 10:46:05 +00005154 if (put_user_s32(status, status_ptr))
5155 goto efault;
bellard31e31b82003-02-18 22:55:36 +00005156 }
bellard2f619692007-11-16 10:46:05 +00005157 if (target_rusage)
5158 host_to_target_rusage(target_rusage, &rusage);
bellard31e31b82003-02-18 22:55:36 +00005159 }
5160 }
5161 break;
thse5febef2007-04-01 18:31:35 +00005162#ifdef TARGET_NR_swapoff
bellard31e31b82003-02-18 22:55:36 +00005163 case TARGET_NR_swapoff:
bellard579a97f2007-11-11 14:26:47 +00005164 if (!(p = lock_user_string(arg1)))
5165 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005166 ret = get_errno(swapoff(p));
5167 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00005168 break;
thse5febef2007-04-01 18:31:35 +00005169#endif
bellard31e31b82003-02-18 22:55:36 +00005170 case TARGET_NR_sysinfo:
bellarda5448a72004-06-19 16:59:03 +00005171 {
pbrook53a59602006-03-25 19:31:22 +00005172 struct target_sysinfo *target_value;
bellarda5448a72004-06-19 16:59:03 +00005173 struct sysinfo value;
5174 ret = get_errno(sysinfo(&value));
pbrook53a59602006-03-25 19:31:22 +00005175 if (!is_error(ret) && arg1)
bellarda5448a72004-06-19 16:59:03 +00005176 {
bellard579a97f2007-11-11 14:26:47 +00005177 if (!lock_user_struct(VERIFY_WRITE, target_value, arg1, 0))
5178 goto efault;
bellarda5448a72004-06-19 16:59:03 +00005179 __put_user(value.uptime, &target_value->uptime);
5180 __put_user(value.loads[0], &target_value->loads[0]);
5181 __put_user(value.loads[1], &target_value->loads[1]);
5182 __put_user(value.loads[2], &target_value->loads[2]);
5183 __put_user(value.totalram, &target_value->totalram);
5184 __put_user(value.freeram, &target_value->freeram);
5185 __put_user(value.sharedram, &target_value->sharedram);
5186 __put_user(value.bufferram, &target_value->bufferram);
5187 __put_user(value.totalswap, &target_value->totalswap);
5188 __put_user(value.freeswap, &target_value->freeswap);
5189 __put_user(value.procs, &target_value->procs);
5190 __put_user(value.totalhigh, &target_value->totalhigh);
5191 __put_user(value.freehigh, &target_value->freehigh);
5192 __put_user(value.mem_unit, &target_value->mem_unit);
pbrook53a59602006-03-25 19:31:22 +00005193 unlock_user_struct(target_value, arg1, 1);
bellarda5448a72004-06-19 16:59:03 +00005194 }
5195 }
5196 break;
thse5febef2007-04-01 18:31:35 +00005197#ifdef TARGET_NR_ipc
bellard31e31b82003-02-18 22:55:36 +00005198 case TARGET_NR_ipc:
bellard8853f862004-02-22 14:57:26 +00005199 ret = do_ipc(arg1, arg2, arg3, arg4, arg5, arg6);
5200 break;
thse5febef2007-04-01 18:31:35 +00005201#endif
aurel32eeb438c2008-10-13 21:08:55 +00005202
5203#ifdef TARGET_NR_msgctl
5204 case TARGET_NR_msgctl:
5205 ret = do_msgctl(arg1, arg2, arg3);
5206 break;
5207#endif
5208#ifdef TARGET_NR_msgget
5209 case TARGET_NR_msgget:
5210 ret = get_errno(msgget(arg1, arg2));
5211 break;
5212#endif
5213#ifdef TARGET_NR_msgrcv
5214 case TARGET_NR_msgrcv:
5215 ret = do_msgrcv(arg1, arg2, arg3, arg4, arg5);
5216 break;
5217#endif
5218#ifdef TARGET_NR_msgsnd
5219 case TARGET_NR_msgsnd:
5220 ret = do_msgsnd(arg1, arg2, arg3, arg4);
5221 break;
5222#endif
bellard31e31b82003-02-18 22:55:36 +00005223 case TARGET_NR_fsync:
5224 ret = get_errno(fsync(arg1));
5225 break;
bellard31e31b82003-02-18 22:55:36 +00005226 case TARGET_NR_clone:
aurel320b6d3ae2008-09-15 07:43:43 +00005227#if defined(TARGET_SH4)
5228 ret = get_errno(do_fork(cpu_env, arg1, arg2, arg3, arg5, arg4));
edgar_iglb15ad612009-01-07 19:43:47 +00005229#elif defined(TARGET_CRIS)
5230 ret = get_errno(do_fork(cpu_env, arg2, arg1, arg3, arg4, arg5));
aurel320b6d3ae2008-09-15 07:43:43 +00005231#else
pbrookd865bab2008-06-07 22:12:17 +00005232 ret = get_errno(do_fork(cpu_env, arg1, arg2, arg3, arg4, arg5));
aurel320b6d3ae2008-09-15 07:43:43 +00005233#endif
bellard1b6b0292003-03-22 17:31:38 +00005234 break;
bellardec86b0f2003-04-11 00:15:04 +00005235#ifdef __NR_exit_group
5236 /* new thread calls */
5237 case TARGET_NR_exit_group:
aurel326d946cd2008-11-06 16:15:18 +00005238#ifdef HAVE_GPROF
5239 _mcleanup();
5240#endif
bellarde9009672005-04-26 20:42:36 +00005241 gdb_exit(cpu_env, arg1);
bellardec86b0f2003-04-11 00:15:04 +00005242 ret = get_errno(exit_group(arg1));
5243 break;
5244#endif
bellard31e31b82003-02-18 22:55:36 +00005245 case TARGET_NR_setdomainname:
bellard579a97f2007-11-11 14:26:47 +00005246 if (!(p = lock_user_string(arg1)))
5247 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005248 ret = get_errno(setdomainname(p, arg2));
5249 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00005250 break;
5251 case TARGET_NR_uname:
5252 /* no need to transcode because we use the linux syscall */
bellard29e619b2004-09-13 21:41:04 +00005253 {
5254 struct new_utsname * buf;
ths3b46e622007-09-17 08:09:54 +00005255
bellard579a97f2007-11-11 14:26:47 +00005256 if (!lock_user_struct(VERIFY_WRITE, buf, arg1, 0))
5257 goto efault;
bellard29e619b2004-09-13 21:41:04 +00005258 ret = get_errno(sys_uname(buf));
5259 if (!is_error(ret)) {
5260 /* Overrite the native machine name with whatever is being
5261 emulated. */
5262 strcpy (buf->machine, UNAME_MACHINE);
pbrookc5937222006-05-14 11:30:38 +00005263 /* Allow the user to override the reported release. */
5264 if (qemu_uname_release && *qemu_uname_release)
5265 strcpy (buf->release, qemu_uname_release);
bellard29e619b2004-09-13 21:41:04 +00005266 }
pbrook53a59602006-03-25 19:31:22 +00005267 unlock_user_struct(buf, arg1, 1);
bellard29e619b2004-09-13 21:41:04 +00005268 }
bellard31e31b82003-02-18 22:55:36 +00005269 break;
bellard6dbad632003-03-16 18:05:05 +00005270#ifdef TARGET_I386
bellard31e31b82003-02-18 22:55:36 +00005271 case TARGET_NR_modify_ldt:
bellard03acab62007-11-11 14:57:14 +00005272 ret = do_modify_ldt(cpu_env, arg1, arg2, arg3);
bellard5cd43932003-03-29 16:54:36 +00005273 break;
j_mayer84409dd2007-04-06 08:56:50 +00005274#if !defined(TARGET_X86_64)
bellard5cd43932003-03-29 16:54:36 +00005275 case TARGET_NR_vm86old:
5276 goto unimplemented;
5277 case TARGET_NR_vm86:
pbrook53a59602006-03-25 19:31:22 +00005278 ret = do_vm86(cpu_env, arg1, arg2);
bellard6dbad632003-03-16 18:05:05 +00005279 break;
5280#endif
j_mayer84409dd2007-04-06 08:56:50 +00005281#endif
bellard31e31b82003-02-18 22:55:36 +00005282 case TARGET_NR_adjtimex:
5283 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00005284#ifdef TARGET_NR_create_module
bellard31e31b82003-02-18 22:55:36 +00005285 case TARGET_NR_create_module:
thse5febef2007-04-01 18:31:35 +00005286#endif
bellard31e31b82003-02-18 22:55:36 +00005287 case TARGET_NR_init_module:
5288 case TARGET_NR_delete_module:
thse5febef2007-04-01 18:31:35 +00005289#ifdef TARGET_NR_get_kernel_syms
bellard31e31b82003-02-18 22:55:36 +00005290 case TARGET_NR_get_kernel_syms:
thse5febef2007-04-01 18:31:35 +00005291#endif
bellard31e31b82003-02-18 22:55:36 +00005292 goto unimplemented;
5293 case TARGET_NR_quotactl:
5294 goto unimplemented;
5295 case TARGET_NR_getpgid:
5296 ret = get_errno(getpgid(arg1));
5297 break;
5298 case TARGET_NR_fchdir:
5299 ret = get_errno(fchdir(arg1));
5300 break;
j_mayer84409dd2007-04-06 08:56:50 +00005301#ifdef TARGET_NR_bdflush /* not on x86_64 */
bellard31e31b82003-02-18 22:55:36 +00005302 case TARGET_NR_bdflush:
5303 goto unimplemented;
j_mayer84409dd2007-04-06 08:56:50 +00005304#endif
thse5febef2007-04-01 18:31:35 +00005305#ifdef TARGET_NR_sysfs
bellard31e31b82003-02-18 22:55:36 +00005306 case TARGET_NR_sysfs:
5307 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00005308#endif
bellard31e31b82003-02-18 22:55:36 +00005309 case TARGET_NR_personality:
bellard1b6b0292003-03-22 17:31:38 +00005310 ret = get_errno(personality(arg1));
bellard31e31b82003-02-18 22:55:36 +00005311 break;
thse5febef2007-04-01 18:31:35 +00005312#ifdef TARGET_NR_afs_syscall
bellard31e31b82003-02-18 22:55:36 +00005313 case TARGET_NR_afs_syscall:
5314 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00005315#endif
j_mayer7a3148a2007-04-05 07:13:51 +00005316#ifdef TARGET_NR__llseek /* Not on alpha */
bellard31e31b82003-02-18 22:55:36 +00005317 case TARGET_NR__llseek:
5318 {
bellard4f2ac232004-04-26 19:44:02 +00005319#if defined (__x86_64__)
5320 ret = get_errno(lseek(arg1, ((uint64_t )arg2 << 32) | arg3, arg5));
bellard2f619692007-11-16 10:46:05 +00005321 if (put_user_s64(ret, arg4))
5322 goto efault;
bellard4f2ac232004-04-26 19:44:02 +00005323#else
bellard31e31b82003-02-18 22:55:36 +00005324 int64_t res;
5325 ret = get_errno(_llseek(arg1, arg2, arg3, &res, arg5));
bellard2f619692007-11-16 10:46:05 +00005326 if (put_user_s64(res, arg4))
5327 goto efault;
bellard4f2ac232004-04-26 19:44:02 +00005328#endif
bellard31e31b82003-02-18 22:55:36 +00005329 }
5330 break;
j_mayer7a3148a2007-04-05 07:13:51 +00005331#endif
bellard31e31b82003-02-18 22:55:36 +00005332 case TARGET_NR_getdents:
blueswir1992f48a2007-10-14 16:27:31 +00005333#if TARGET_ABI_BITS != 32
pbrook53a59602006-03-25 19:31:22 +00005334 goto unimplemented;
blueswir1992f48a2007-10-14 16:27:31 +00005335#elif TARGET_ABI_BITS == 32 && HOST_LONG_BITS == 64
bellard4add45b2003-06-05 01:52:59 +00005336 {
pbrook53a59602006-03-25 19:31:22 +00005337 struct target_dirent *target_dirp;
aurel326556a832008-10-13 21:08:17 +00005338 struct linux_dirent *dirp;
blueswir1992f48a2007-10-14 16:27:31 +00005339 abi_long count = arg3;
bellard4add45b2003-06-05 01:52:59 +00005340
5341 dirp = malloc(count);
ths0da46a62007-10-20 20:23:07 +00005342 if (!dirp) {
bellard579a97f2007-11-11 14:26:47 +00005343 ret = -TARGET_ENOMEM;
ths0da46a62007-10-20 20:23:07 +00005344 goto fail;
5345 }
ths3b46e622007-09-17 08:09:54 +00005346
bellard4add45b2003-06-05 01:52:59 +00005347 ret = get_errno(sys_getdents(arg1, dirp, count));
5348 if (!is_error(ret)) {
aurel326556a832008-10-13 21:08:17 +00005349 struct linux_dirent *de;
bellard4add45b2003-06-05 01:52:59 +00005350 struct target_dirent *tde;
5351 int len = ret;
5352 int reclen, treclen;
5353 int count1, tnamelen;
5354
5355 count1 = 0;
5356 de = dirp;
bellard579a97f2007-11-11 14:26:47 +00005357 if (!(target_dirp = lock_user(VERIFY_WRITE, arg2, count, 0)))
5358 goto efault;
bellard4add45b2003-06-05 01:52:59 +00005359 tde = target_dirp;
5360 while (len > 0) {
5361 reclen = de->d_reclen;
blueswir1992f48a2007-10-14 16:27:31 +00005362 treclen = reclen - (2 * (sizeof(long) - sizeof(abi_long)));
bellard4add45b2003-06-05 01:52:59 +00005363 tde->d_reclen = tswap16(treclen);
5364 tde->d_ino = tswapl(de->d_ino);
5365 tde->d_off = tswapl(de->d_off);
blueswir1992f48a2007-10-14 16:27:31 +00005366 tnamelen = treclen - (2 * sizeof(abi_long) + 2);
bellard4add45b2003-06-05 01:52:59 +00005367 if (tnamelen > 256)
5368 tnamelen = 256;
bellard80a9d032005-01-03 23:31:27 +00005369 /* XXX: may not be correct */
blueswir1be15b142008-10-25 11:21:28 +00005370 pstrcpy(tde->d_name, tnamelen, de->d_name);
aurel326556a832008-10-13 21:08:17 +00005371 de = (struct linux_dirent *)((char *)de + reclen);
bellard4add45b2003-06-05 01:52:59 +00005372 len -= reclen;
j_mayer1c5bf3b2007-04-14 12:17:59 +00005373 tde = (struct target_dirent *)((char *)tde + treclen);
bellard4add45b2003-06-05 01:52:59 +00005374 count1 += treclen;
5375 }
5376 ret = count1;
bellard579a97f2007-11-11 14:26:47 +00005377 unlock_user(target_dirp, arg2, ret);
bellard4add45b2003-06-05 01:52:59 +00005378 }
5379 free(dirp);
5380 }
5381#else
bellard31e31b82003-02-18 22:55:36 +00005382 {
aurel326556a832008-10-13 21:08:17 +00005383 struct linux_dirent *dirp;
blueswir1992f48a2007-10-14 16:27:31 +00005384 abi_long count = arg3;
bellarddab2ed92003-03-22 15:23:14 +00005385
bellard579a97f2007-11-11 14:26:47 +00005386 if (!(dirp = lock_user(VERIFY_WRITE, arg2, count, 0)))
5387 goto efault;
bellard72f03902003-02-18 23:33:18 +00005388 ret = get_errno(sys_getdents(arg1, dirp, count));
bellard31e31b82003-02-18 22:55:36 +00005389 if (!is_error(ret)) {
aurel326556a832008-10-13 21:08:17 +00005390 struct linux_dirent *de;
bellard31e31b82003-02-18 22:55:36 +00005391 int len = ret;
5392 int reclen;
5393 de = dirp;
5394 while (len > 0) {
bellard8083a3e2003-03-24 23:12:16 +00005395 reclen = de->d_reclen;
bellard31e31b82003-02-18 22:55:36 +00005396 if (reclen > len)
5397 break;
bellard8083a3e2003-03-24 23:12:16 +00005398 de->d_reclen = tswap16(reclen);
bellard31e31b82003-02-18 22:55:36 +00005399 tswapls(&de->d_ino);
5400 tswapls(&de->d_off);
aurel326556a832008-10-13 21:08:17 +00005401 de = (struct linux_dirent *)((char *)de + reclen);
bellard31e31b82003-02-18 22:55:36 +00005402 len -= reclen;
5403 }
5404 }
pbrook53a59602006-03-25 19:31:22 +00005405 unlock_user(dirp, arg2, ret);
bellard31e31b82003-02-18 22:55:36 +00005406 }
bellard4add45b2003-06-05 01:52:59 +00005407#endif
bellard31e31b82003-02-18 22:55:36 +00005408 break;
ths3ae43202007-09-16 21:39:48 +00005409#if defined(TARGET_NR_getdents64) && defined(__NR_getdents64)
bellarddab2ed92003-03-22 15:23:14 +00005410 case TARGET_NR_getdents64:
5411 {
aurel326556a832008-10-13 21:08:17 +00005412 struct linux_dirent64 *dirp;
blueswir1992f48a2007-10-14 16:27:31 +00005413 abi_long count = arg3;
bellard579a97f2007-11-11 14:26:47 +00005414 if (!(dirp = lock_user(VERIFY_WRITE, arg2, count, 0)))
5415 goto efault;
bellarddab2ed92003-03-22 15:23:14 +00005416 ret = get_errno(sys_getdents64(arg1, dirp, count));
5417 if (!is_error(ret)) {
aurel326556a832008-10-13 21:08:17 +00005418 struct linux_dirent64 *de;
bellarddab2ed92003-03-22 15:23:14 +00005419 int len = ret;
5420 int reclen;
5421 de = dirp;
5422 while (len > 0) {
bellard8083a3e2003-03-24 23:12:16 +00005423 reclen = de->d_reclen;
bellarddab2ed92003-03-22 15:23:14 +00005424 if (reclen > len)
5425 break;
bellard8083a3e2003-03-24 23:12:16 +00005426 de->d_reclen = tswap16(reclen);
bellard8582a532007-11-11 23:11:36 +00005427 tswap64s((uint64_t *)&de->d_ino);
5428 tswap64s((uint64_t *)&de->d_off);
aurel326556a832008-10-13 21:08:17 +00005429 de = (struct linux_dirent64 *)((char *)de + reclen);
bellarddab2ed92003-03-22 15:23:14 +00005430 len -= reclen;
5431 }
5432 }
pbrook53a59602006-03-25 19:31:22 +00005433 unlock_user(dirp, arg2, ret);
bellarddab2ed92003-03-22 15:23:14 +00005434 }
5435 break;
bellarda541f292004-04-12 20:39:29 +00005436#endif /* TARGET_NR_getdents64 */
thse5febef2007-04-01 18:31:35 +00005437#ifdef TARGET_NR__newselect
bellard31e31b82003-02-18 22:55:36 +00005438 case TARGET_NR__newselect:
pbrook53a59602006-03-25 19:31:22 +00005439 ret = do_select(arg1, arg2, arg3, arg4, arg5);
bellard31e31b82003-02-18 22:55:36 +00005440 break;
thse5febef2007-04-01 18:31:35 +00005441#endif
5442#ifdef TARGET_NR_poll
bellard9de5e442003-03-23 16:49:39 +00005443 case TARGET_NR_poll:
5444 {
pbrook53a59602006-03-25 19:31:22 +00005445 struct target_pollfd *target_pfd;
bellard9de5e442003-03-23 16:49:39 +00005446 unsigned int nfds = arg2;
5447 int timeout = arg3;
5448 struct pollfd *pfd;
bellard7854b052003-03-29 17:22:23 +00005449 unsigned int i;
bellard9de5e442003-03-23 16:49:39 +00005450
bellard579a97f2007-11-11 14:26:47 +00005451 target_pfd = lock_user(VERIFY_WRITE, arg1, sizeof(struct target_pollfd) * nfds, 1);
5452 if (!target_pfd)
5453 goto efault;
bellard9de5e442003-03-23 16:49:39 +00005454 pfd = alloca(sizeof(struct pollfd) * nfds);
5455 for(i = 0; i < nfds; i++) {
bellard5cd43932003-03-29 16:54:36 +00005456 pfd[i].fd = tswap32(target_pfd[i].fd);
5457 pfd[i].events = tswap16(target_pfd[i].events);
bellard9de5e442003-03-23 16:49:39 +00005458 }
5459 ret = get_errno(poll(pfd, nfds, timeout));
5460 if (!is_error(ret)) {
5461 for(i = 0; i < nfds; i++) {
bellard5cd43932003-03-29 16:54:36 +00005462 target_pfd[i].revents = tswap16(pfd[i].revents);
bellard9de5e442003-03-23 16:49:39 +00005463 }
pbrook53a59602006-03-25 19:31:22 +00005464 ret += nfds * (sizeof(struct target_pollfd)
5465 - sizeof(struct pollfd));
bellard9de5e442003-03-23 16:49:39 +00005466 }
pbrook53a59602006-03-25 19:31:22 +00005467 unlock_user(target_pfd, arg1, ret);
bellard9de5e442003-03-23 16:49:39 +00005468 }
5469 break;
thse5febef2007-04-01 18:31:35 +00005470#endif
bellard31e31b82003-02-18 22:55:36 +00005471 case TARGET_NR_flock:
bellard9de5e442003-03-23 16:49:39 +00005472 /* NOTE: the flock constant seems to be the same for every
5473 Linux platform */
5474 ret = get_errno(flock(arg1, arg2));
bellard31e31b82003-02-18 22:55:36 +00005475 break;
5476 case TARGET_NR_readv:
5477 {
5478 int count = arg3;
bellard31e31b82003-02-18 22:55:36 +00005479 struct iovec *vec;
bellard31e31b82003-02-18 22:55:36 +00005480
5481 vec = alloca(count * sizeof(struct iovec));
bellard41df8412008-02-04 22:26:57 +00005482 if (lock_iovec(VERIFY_WRITE, vec, arg2, count, 0) < 0)
5483 goto efault;
bellard31e31b82003-02-18 22:55:36 +00005484 ret = get_errno(readv(arg1, vec, count));
pbrook53a59602006-03-25 19:31:22 +00005485 unlock_iovec(vec, arg2, count, 1);
bellard31e31b82003-02-18 22:55:36 +00005486 }
5487 break;
5488 case TARGET_NR_writev:
5489 {
5490 int count = arg3;
bellard31e31b82003-02-18 22:55:36 +00005491 struct iovec *vec;
bellard31e31b82003-02-18 22:55:36 +00005492
5493 vec = alloca(count * sizeof(struct iovec));
bellard41df8412008-02-04 22:26:57 +00005494 if (lock_iovec(VERIFY_READ, vec, arg2, count, 1) < 0)
5495 goto efault;
bellard31e31b82003-02-18 22:55:36 +00005496 ret = get_errno(writev(arg1, vec, count));
pbrook53a59602006-03-25 19:31:22 +00005497 unlock_iovec(vec, arg2, count, 0);
bellard31e31b82003-02-18 22:55:36 +00005498 }
5499 break;
5500 case TARGET_NR_getsid:
5501 ret = get_errno(getsid(arg1));
5502 break;
j_mayer7a3148a2007-04-05 07:13:51 +00005503#if defined(TARGET_NR_fdatasync) /* Not on alpha (osf_datasync ?) */
bellard31e31b82003-02-18 22:55:36 +00005504 case TARGET_NR_fdatasync:
bellard5cd43932003-03-29 16:54:36 +00005505 ret = get_errno(fdatasync(arg1));
5506 break;
j_mayer7a3148a2007-04-05 07:13:51 +00005507#endif
bellard31e31b82003-02-18 22:55:36 +00005508 case TARGET_NR__sysctl:
ths0da46a62007-10-20 20:23:07 +00005509 /* We don't implement this, but ENOTDIR is always a safe
bellard29e619b2004-09-13 21:41:04 +00005510 return value. */
ths0da46a62007-10-20 20:23:07 +00005511 ret = -TARGET_ENOTDIR;
5512 break;
bellard31e31b82003-02-18 22:55:36 +00005513 case TARGET_NR_sched_setparam:
bellard5cd43932003-03-29 16:54:36 +00005514 {
pbrook53a59602006-03-25 19:31:22 +00005515 struct sched_param *target_schp;
bellard5cd43932003-03-29 16:54:36 +00005516 struct sched_param schp;
pbrook53a59602006-03-25 19:31:22 +00005517
bellard579a97f2007-11-11 14:26:47 +00005518 if (!lock_user_struct(VERIFY_READ, target_schp, arg2, 1))
5519 goto efault;
bellard5cd43932003-03-29 16:54:36 +00005520 schp.sched_priority = tswap32(target_schp->sched_priority);
pbrook53a59602006-03-25 19:31:22 +00005521 unlock_user_struct(target_schp, arg2, 0);
bellard5cd43932003-03-29 16:54:36 +00005522 ret = get_errno(sched_setparam(arg1, &schp));
5523 }
5524 break;
bellard31e31b82003-02-18 22:55:36 +00005525 case TARGET_NR_sched_getparam:
bellard5cd43932003-03-29 16:54:36 +00005526 {
pbrook53a59602006-03-25 19:31:22 +00005527 struct sched_param *target_schp;
bellard5cd43932003-03-29 16:54:36 +00005528 struct sched_param schp;
5529 ret = get_errno(sched_getparam(arg1, &schp));
5530 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00005531 if (!lock_user_struct(VERIFY_WRITE, target_schp, arg2, 0))
5532 goto efault;
bellard5cd43932003-03-29 16:54:36 +00005533 target_schp->sched_priority = tswap32(schp.sched_priority);
pbrook53a59602006-03-25 19:31:22 +00005534 unlock_user_struct(target_schp, arg2, 1);
bellard5cd43932003-03-29 16:54:36 +00005535 }
5536 }
5537 break;
bellard31e31b82003-02-18 22:55:36 +00005538 case TARGET_NR_sched_setscheduler:
bellard5cd43932003-03-29 16:54:36 +00005539 {
pbrook53a59602006-03-25 19:31:22 +00005540 struct sched_param *target_schp;
bellard5cd43932003-03-29 16:54:36 +00005541 struct sched_param schp;
bellard579a97f2007-11-11 14:26:47 +00005542 if (!lock_user_struct(VERIFY_READ, target_schp, arg3, 1))
5543 goto efault;
bellard5cd43932003-03-29 16:54:36 +00005544 schp.sched_priority = tswap32(target_schp->sched_priority);
pbrook53a59602006-03-25 19:31:22 +00005545 unlock_user_struct(target_schp, arg3, 0);
bellard5cd43932003-03-29 16:54:36 +00005546 ret = get_errno(sched_setscheduler(arg1, arg2, &schp));
5547 }
5548 break;
bellard31e31b82003-02-18 22:55:36 +00005549 case TARGET_NR_sched_getscheduler:
bellard5cd43932003-03-29 16:54:36 +00005550 ret = get_errno(sched_getscheduler(arg1));
5551 break;
bellard31e31b82003-02-18 22:55:36 +00005552 case TARGET_NR_sched_yield:
5553 ret = get_errno(sched_yield());
5554 break;
5555 case TARGET_NR_sched_get_priority_max:
bellard5cd43932003-03-29 16:54:36 +00005556 ret = get_errno(sched_get_priority_max(arg1));
5557 break;
bellard31e31b82003-02-18 22:55:36 +00005558 case TARGET_NR_sched_get_priority_min:
bellard5cd43932003-03-29 16:54:36 +00005559 ret = get_errno(sched_get_priority_min(arg1));
5560 break;
bellard31e31b82003-02-18 22:55:36 +00005561 case TARGET_NR_sched_rr_get_interval:
bellard5cd43932003-03-29 16:54:36 +00005562 {
bellard5cd43932003-03-29 16:54:36 +00005563 struct timespec ts;
5564 ret = get_errno(sched_rr_get_interval(arg1, &ts));
5565 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00005566 host_to_target_timespec(arg2, &ts);
bellard5cd43932003-03-29 16:54:36 +00005567 }
5568 }
5569 break;
bellard31e31b82003-02-18 22:55:36 +00005570 case TARGET_NR_nanosleep:
bellard1b6b0292003-03-22 17:31:38 +00005571 {
bellard1b6b0292003-03-22 17:31:38 +00005572 struct timespec req, rem;
pbrook53a59602006-03-25 19:31:22 +00005573 target_to_host_timespec(&req, arg1);
bellard1b6b0292003-03-22 17:31:38 +00005574 ret = get_errno(nanosleep(&req, &rem));
pbrook53a59602006-03-25 19:31:22 +00005575 if (is_error(ret) && arg2) {
5576 host_to_target_timespec(arg2, &rem);
bellard1b6b0292003-03-22 17:31:38 +00005577 }
5578 }
5579 break;
thse5febef2007-04-01 18:31:35 +00005580#ifdef TARGET_NR_query_module
bellard31e31b82003-02-18 22:55:36 +00005581 case TARGET_NR_query_module:
bellard5cd43932003-03-29 16:54:36 +00005582 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00005583#endif
5584#ifdef TARGET_NR_nfsservctl
bellard31e31b82003-02-18 22:55:36 +00005585 case TARGET_NR_nfsservctl:
bellard5cd43932003-03-29 16:54:36 +00005586 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00005587#endif
bellard31e31b82003-02-18 22:55:36 +00005588 case TARGET_NR_prctl:
thse5574482007-02-11 20:03:13 +00005589 switch (arg1)
5590 {
5591 case PR_GET_PDEATHSIG:
5592 {
5593 int deathsig;
5594 ret = get_errno(prctl(arg1, &deathsig, arg3, arg4, arg5));
bellard2f619692007-11-16 10:46:05 +00005595 if (!is_error(ret) && arg2
5596 && put_user_ual(deathsig, arg2))
5597 goto efault;
thse5574482007-02-11 20:03:13 +00005598 }
5599 break;
5600 default:
5601 ret = get_errno(prctl(arg1, arg2, arg3, arg4, arg5));
5602 break;
5603 }
ths39b9aae2007-02-11 18:36:44 +00005604 break;
bellardd2fd1af2007-11-14 18:08:56 +00005605#ifdef TARGET_NR_arch_prctl
5606 case TARGET_NR_arch_prctl:
5607#if defined(TARGET_I386) && !defined(TARGET_ABI32)
5608 ret = do_arch_prctl(cpu_env, arg1, arg2);
5609 break;
5610#else
5611 goto unimplemented;
5612#endif
5613#endif
bellard67867302003-11-23 17:05:30 +00005614#ifdef TARGET_NR_pread
bellard31e31b82003-02-18 22:55:36 +00005615 case TARGET_NR_pread:
balroga4ae00b2008-09-20 03:14:14 +00005616#ifdef TARGET_ARM
5617 if (((CPUARMState *)cpu_env)->eabi)
5618 arg4 = arg5;
5619#endif
bellard579a97f2007-11-11 14:26:47 +00005620 if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
5621 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005622 ret = get_errno(pread(arg1, p, arg3, arg4));
5623 unlock_user(p, arg2, ret);
bellard206f0fa2003-05-14 19:01:56 +00005624 break;
bellard31e31b82003-02-18 22:55:36 +00005625 case TARGET_NR_pwrite:
balroga4ae00b2008-09-20 03:14:14 +00005626#ifdef TARGET_ARM
5627 if (((CPUARMState *)cpu_env)->eabi)
5628 arg4 = arg5;
5629#endif
bellard579a97f2007-11-11 14:26:47 +00005630 if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
5631 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005632 ret = get_errno(pwrite(arg1, p, arg3, arg4));
5633 unlock_user(p, arg2, 0);
bellard206f0fa2003-05-14 19:01:56 +00005634 break;
bellard67867302003-11-23 17:05:30 +00005635#endif
aurel32f2c7ba12008-03-28 22:32:06 +00005636#ifdef TARGET_NR_pread64
5637 case TARGET_NR_pread64:
5638 if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
5639 goto efault;
5640 ret = get_errno(pread64(arg1, p, arg3, target_offset64(arg4, arg5)));
5641 unlock_user(p, arg2, ret);
5642 break;
5643 case TARGET_NR_pwrite64:
5644 if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
5645 goto efault;
5646 ret = get_errno(pwrite64(arg1, p, arg3, target_offset64(arg4, arg5)));
5647 unlock_user(p, arg2, 0);
5648 break;
5649#endif
bellard31e31b82003-02-18 22:55:36 +00005650 case TARGET_NR_getcwd:
bellard579a97f2007-11-11 14:26:47 +00005651 if (!(p = lock_user(VERIFY_WRITE, arg1, arg2, 0)))
5652 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005653 ret = get_errno(sys_getcwd1(p, arg2));
5654 unlock_user(p, arg1, ret);
bellard31e31b82003-02-18 22:55:36 +00005655 break;
5656 case TARGET_NR_capget:
bellard5cd43932003-03-29 16:54:36 +00005657 goto unimplemented;
bellard31e31b82003-02-18 22:55:36 +00005658 case TARGET_NR_capset:
bellard5cd43932003-03-29 16:54:36 +00005659 goto unimplemented;
bellard31e31b82003-02-18 22:55:36 +00005660 case TARGET_NR_sigaltstack:
ths198a74d2007-09-27 16:44:32 +00005661#if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_MIPS) || \
5662 defined(TARGET_SPARC) || defined(TARGET_PPC) || defined(TARGET_ALPHA)
bellard579a97f2007-11-11 14:26:47 +00005663 ret = do_sigaltstack(arg1, arg2, get_sp_from_cpustate((CPUState *)cpu_env));
thsa04e1342007-09-27 13:57:58 +00005664 break;
5665#else
bellard5cd43932003-03-29 16:54:36 +00005666 goto unimplemented;
thsa04e1342007-09-27 13:57:58 +00005667#endif
bellard31e31b82003-02-18 22:55:36 +00005668 case TARGET_NR_sendfile:
bellard5cd43932003-03-29 16:54:36 +00005669 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00005670#ifdef TARGET_NR_getpmsg
bellard31e31b82003-02-18 22:55:36 +00005671 case TARGET_NR_getpmsg:
bellard5cd43932003-03-29 16:54:36 +00005672 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00005673#endif
5674#ifdef TARGET_NR_putpmsg
bellard31e31b82003-02-18 22:55:36 +00005675 case TARGET_NR_putpmsg:
bellard5cd43932003-03-29 16:54:36 +00005676 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00005677#endif
bellard048f6b42005-11-26 18:47:20 +00005678#ifdef TARGET_NR_vfork
bellard31e31b82003-02-18 22:55:36 +00005679 case TARGET_NR_vfork:
pbrookd865bab2008-06-07 22:12:17 +00005680 ret = get_errno(do_fork(cpu_env, CLONE_VFORK | CLONE_VM | SIGCHLD,
5681 0, 0, 0, 0));
bellard31e31b82003-02-18 22:55:36 +00005682 break;
bellard048f6b42005-11-26 18:47:20 +00005683#endif
bellardebc05482003-09-30 21:08:41 +00005684#ifdef TARGET_NR_ugetrlimit
bellard31e31b82003-02-18 22:55:36 +00005685 case TARGET_NR_ugetrlimit:
bellard728584b2003-04-29 20:43:36 +00005686 {
5687 struct rlimit rlim;
5688 ret = get_errno(getrlimit(arg1, &rlim));
5689 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00005690 struct target_rlimit *target_rlim;
bellard579a97f2007-11-11 14:26:47 +00005691 if (!lock_user_struct(VERIFY_WRITE, target_rlim, arg2, 0))
5692 goto efault;
bellard728584b2003-04-29 20:43:36 +00005693 target_rlim->rlim_cur = tswapl(rlim.rlim_cur);
5694 target_rlim->rlim_max = tswapl(rlim.rlim_max);
pbrook53a59602006-03-25 19:31:22 +00005695 unlock_user_struct(target_rlim, arg2, 1);
bellard728584b2003-04-29 20:43:36 +00005696 }
5697 break;
5698 }
bellardebc05482003-09-30 21:08:41 +00005699#endif
bellarda315a142005-01-30 22:59:18 +00005700#ifdef TARGET_NR_truncate64
bellard31e31b82003-02-18 22:55:36 +00005701 case TARGET_NR_truncate64:
bellard579a97f2007-11-11 14:26:47 +00005702 if (!(p = lock_user_string(arg1)))
5703 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005704 ret = target_truncate64(cpu_env, p, arg2, arg3, arg4);
5705 unlock_user(p, arg1, 0);
bellard667f38b2005-07-23 14:46:27 +00005706 break;
bellarda315a142005-01-30 22:59:18 +00005707#endif
5708#ifdef TARGET_NR_ftruncate64
bellard31e31b82003-02-18 22:55:36 +00005709 case TARGET_NR_ftruncate64:
pbrookce4defa2006-02-09 16:49:55 +00005710 ret = target_ftruncate64(cpu_env, arg1, arg2, arg3, arg4);
bellard667f38b2005-07-23 14:46:27 +00005711 break;
bellarda315a142005-01-30 22:59:18 +00005712#endif
5713#ifdef TARGET_NR_stat64
bellard31e31b82003-02-18 22:55:36 +00005714 case TARGET_NR_stat64:
bellard579a97f2007-11-11 14:26:47 +00005715 if (!(p = lock_user_string(arg1)))
5716 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005717 ret = get_errno(stat(path(p), &st));
5718 unlock_user(p, arg1, 0);
balrog6a24a772008-09-20 02:23:36 +00005719 if (!is_error(ret))
5720 ret = host_to_target_stat64(cpu_env, arg2, &st);
5721 break;
bellarda315a142005-01-30 22:59:18 +00005722#endif
5723#ifdef TARGET_NR_lstat64
bellard31e31b82003-02-18 22:55:36 +00005724 case TARGET_NR_lstat64:
bellard579a97f2007-11-11 14:26:47 +00005725 if (!(p = lock_user_string(arg1)))
5726 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005727 ret = get_errno(lstat(path(p), &st));
5728 unlock_user(p, arg1, 0);
balrog6a24a772008-09-20 02:23:36 +00005729 if (!is_error(ret))
5730 ret = host_to_target_stat64(cpu_env, arg2, &st);
5731 break;
bellarda315a142005-01-30 22:59:18 +00005732#endif
5733#ifdef TARGET_NR_fstat64
bellard31e31b82003-02-18 22:55:36 +00005734 case TARGET_NR_fstat64:
balrog6a24a772008-09-20 02:23:36 +00005735 ret = get_errno(fstat(arg1, &st));
5736 if (!is_error(ret))
5737 ret = host_to_target_stat64(cpu_env, arg2, &st);
5738 break;
bellardec86b0f2003-04-11 00:15:04 +00005739#endif
aurel329d33b762009-04-08 23:07:05 +00005740#if (defined(TARGET_NR_fstatat64) || defined(TARGET_NR_newfstatat)) && \
5741 (defined(__NR_fstatat64) || defined(__NR_newfstatat))
5742#ifdef TARGET_NR_fstatat64
balrog6a24a772008-09-20 02:23:36 +00005743 case TARGET_NR_fstatat64:
aurel329d33b762009-04-08 23:07:05 +00005744#endif
5745#ifdef TARGET_NR_newfstatat
5746 case TARGET_NR_newfstatat:
5747#endif
balrog6a24a772008-09-20 02:23:36 +00005748 if (!(p = lock_user_string(arg2)))
5749 goto efault;
aurel329d33b762009-04-08 23:07:05 +00005750#ifdef __NR_fstatat64
balrog6a24a772008-09-20 02:23:36 +00005751 ret = get_errno(sys_fstatat64(arg1, path(p), &st, arg4));
aurel329d33b762009-04-08 23:07:05 +00005752#else
5753 ret = get_errno(sys_newfstatat(arg1, path(p), &st, arg4));
5754#endif
balrog6a24a772008-09-20 02:23:36 +00005755 if (!is_error(ret))
5756 ret = host_to_target_stat64(cpu_env, arg3, &st);
bellard60cd49d2003-03-16 22:53:56 +00005757 break;
bellarda315a142005-01-30 22:59:18 +00005758#endif
bellard67867302003-11-23 17:05:30 +00005759#ifdef USE_UID16
5760 case TARGET_NR_lchown:
bellard579a97f2007-11-11 14:26:47 +00005761 if (!(p = lock_user_string(arg1)))
5762 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005763 ret = get_errno(lchown(p, low2highuid(arg2), low2highgid(arg3)));
5764 unlock_user(p, arg1, 0);
bellard67867302003-11-23 17:05:30 +00005765 break;
5766 case TARGET_NR_getuid:
5767 ret = get_errno(high2lowuid(getuid()));
5768 break;
5769 case TARGET_NR_getgid:
5770 ret = get_errno(high2lowgid(getgid()));
5771 break;
5772 case TARGET_NR_geteuid:
5773 ret = get_errno(high2lowuid(geteuid()));
5774 break;
5775 case TARGET_NR_getegid:
5776 ret = get_errno(high2lowgid(getegid()));
5777 break;
5778 case TARGET_NR_setreuid:
5779 ret = get_errno(setreuid(low2highuid(arg1), low2highuid(arg2)));
5780 break;
5781 case TARGET_NR_setregid:
5782 ret = get_errno(setregid(low2highgid(arg1), low2highgid(arg2)));
5783 break;
5784 case TARGET_NR_getgroups:
5785 {
5786 int gidsetsize = arg1;
pbrook53a59602006-03-25 19:31:22 +00005787 uint16_t *target_grouplist;
bellard67867302003-11-23 17:05:30 +00005788 gid_t *grouplist;
5789 int i;
5790
5791 grouplist = alloca(gidsetsize * sizeof(gid_t));
5792 ret = get_errno(getgroups(gidsetsize, grouplist));
balrogcb3bc232008-09-20 02:08:13 +00005793 if (gidsetsize == 0)
5794 break;
bellard67867302003-11-23 17:05:30 +00005795 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00005796 target_grouplist = lock_user(VERIFY_WRITE, arg2, gidsetsize * 2, 0);
5797 if (!target_grouplist)
5798 goto efault;
balroga2155fc2008-09-20 02:12:08 +00005799 for(i = 0;i < ret; i++)
bellard67867302003-11-23 17:05:30 +00005800 target_grouplist[i] = tswap16(grouplist[i]);
pbrook53a59602006-03-25 19:31:22 +00005801 unlock_user(target_grouplist, arg2, gidsetsize * 2);
bellard67867302003-11-23 17:05:30 +00005802 }
5803 }
5804 break;
5805 case TARGET_NR_setgroups:
5806 {
5807 int gidsetsize = arg1;
pbrook53a59602006-03-25 19:31:22 +00005808 uint16_t *target_grouplist;
bellard67867302003-11-23 17:05:30 +00005809 gid_t *grouplist;
5810 int i;
5811
5812 grouplist = alloca(gidsetsize * sizeof(gid_t));
bellard579a97f2007-11-11 14:26:47 +00005813 target_grouplist = lock_user(VERIFY_READ, arg2, gidsetsize * 2, 1);
5814 if (!target_grouplist) {
5815 ret = -TARGET_EFAULT;
5816 goto fail;
5817 }
bellard67867302003-11-23 17:05:30 +00005818 for(i = 0;i < gidsetsize; i++)
5819 grouplist[i] = tswap16(target_grouplist[i]);
pbrook53a59602006-03-25 19:31:22 +00005820 unlock_user(target_grouplist, arg2, 0);
bellard67867302003-11-23 17:05:30 +00005821 ret = get_errno(setgroups(gidsetsize, grouplist));
5822 }
5823 break;
5824 case TARGET_NR_fchown:
5825 ret = get_errno(fchown(arg1, low2highuid(arg2), low2highgid(arg3)));
5826 break;
thsccfa72b2007-09-24 09:23:34 +00005827#if defined(TARGET_NR_fchownat) && defined(__NR_fchownat)
5828 case TARGET_NR_fchownat:
bellard579a97f2007-11-11 14:26:47 +00005829 if (!(p = lock_user_string(arg2)))
5830 goto efault;
5831 ret = get_errno(sys_fchownat(arg1, p, low2highuid(arg3), low2highgid(arg4), arg5));
5832 unlock_user(p, arg2, 0);
thsccfa72b2007-09-24 09:23:34 +00005833 break;
5834#endif
bellard67867302003-11-23 17:05:30 +00005835#ifdef TARGET_NR_setresuid
5836 case TARGET_NR_setresuid:
ths5fafdf22007-09-16 21:08:06 +00005837 ret = get_errno(setresuid(low2highuid(arg1),
5838 low2highuid(arg2),
bellard67867302003-11-23 17:05:30 +00005839 low2highuid(arg3)));
5840 break;
5841#endif
5842#ifdef TARGET_NR_getresuid
5843 case TARGET_NR_getresuid:
5844 {
pbrook53a59602006-03-25 19:31:22 +00005845 uid_t ruid, euid, suid;
bellard67867302003-11-23 17:05:30 +00005846 ret = get_errno(getresuid(&ruid, &euid, &suid));
5847 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +00005848 if (put_user_u16(high2lowuid(ruid), arg1)
5849 || put_user_u16(high2lowuid(euid), arg2)
5850 || put_user_u16(high2lowuid(suid), arg3))
5851 goto efault;
bellard67867302003-11-23 17:05:30 +00005852 }
5853 }
5854 break;
5855#endif
5856#ifdef TARGET_NR_getresgid
5857 case TARGET_NR_setresgid:
ths5fafdf22007-09-16 21:08:06 +00005858 ret = get_errno(setresgid(low2highgid(arg1),
5859 low2highgid(arg2),
bellard67867302003-11-23 17:05:30 +00005860 low2highgid(arg3)));
5861 break;
5862#endif
5863#ifdef TARGET_NR_getresgid
5864 case TARGET_NR_getresgid:
5865 {
pbrook53a59602006-03-25 19:31:22 +00005866 gid_t rgid, egid, sgid;
bellard67867302003-11-23 17:05:30 +00005867 ret = get_errno(getresgid(&rgid, &egid, &sgid));
5868 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +00005869 if (put_user_u16(high2lowgid(rgid), arg1)
5870 || put_user_u16(high2lowgid(egid), arg2)
5871 || put_user_u16(high2lowgid(sgid), arg3))
5872 goto efault;
bellard67867302003-11-23 17:05:30 +00005873 }
5874 }
5875 break;
5876#endif
5877 case TARGET_NR_chown:
bellard579a97f2007-11-11 14:26:47 +00005878 if (!(p = lock_user_string(arg1)))
5879 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005880 ret = get_errno(chown(p, low2highuid(arg2), low2highgid(arg3)));
5881 unlock_user(p, arg1, 0);
bellard67867302003-11-23 17:05:30 +00005882 break;
5883 case TARGET_NR_setuid:
5884 ret = get_errno(setuid(low2highuid(arg1)));
5885 break;
5886 case TARGET_NR_setgid:
5887 ret = get_errno(setgid(low2highgid(arg1)));
5888 break;
5889 case TARGET_NR_setfsuid:
5890 ret = get_errno(setfsuid(arg1));
5891 break;
5892 case TARGET_NR_setfsgid:
5893 ret = get_errno(setfsgid(arg1));
5894 break;
5895#endif /* USE_UID16 */
5896
bellarda315a142005-01-30 22:59:18 +00005897#ifdef TARGET_NR_lchown32
bellard31e31b82003-02-18 22:55:36 +00005898 case TARGET_NR_lchown32:
bellard579a97f2007-11-11 14:26:47 +00005899 if (!(p = lock_user_string(arg1)))
5900 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005901 ret = get_errno(lchown(p, arg2, arg3));
5902 unlock_user(p, arg1, 0);
bellardb03c60f2003-03-23 17:19:56 +00005903 break;
bellarda315a142005-01-30 22:59:18 +00005904#endif
5905#ifdef TARGET_NR_getuid32
bellard31e31b82003-02-18 22:55:36 +00005906 case TARGET_NR_getuid32:
bellardb03c60f2003-03-23 17:19:56 +00005907 ret = get_errno(getuid());
5908 break;
bellarda315a142005-01-30 22:59:18 +00005909#endif
aurel3264b4d282008-11-14 17:20:15 +00005910
5911#if defined(TARGET_NR_getxuid) && defined(TARGET_ALPHA)
5912 /* Alpha specific */
5913 case TARGET_NR_getxuid:
5914 {
5915 uid_t euid;
5916 euid=geteuid();
5917 ((CPUAlphaState *)cpu_env)->ir[IR_A4]=euid;
5918 }
5919 ret = get_errno(getuid());
5920 break;
5921#endif
5922#if defined(TARGET_NR_getxgid) && defined(TARGET_ALPHA)
5923 /* Alpha specific */
5924 case TARGET_NR_getxgid:
5925 {
5926 uid_t egid;
5927 egid=getegid();
5928 ((CPUAlphaState *)cpu_env)->ir[IR_A4]=egid;
5929 }
5930 ret = get_errno(getgid());
5931 break;
5932#endif
5933
bellarda315a142005-01-30 22:59:18 +00005934#ifdef TARGET_NR_getgid32
bellard31e31b82003-02-18 22:55:36 +00005935 case TARGET_NR_getgid32:
bellardb03c60f2003-03-23 17:19:56 +00005936 ret = get_errno(getgid());
5937 break;
bellarda315a142005-01-30 22:59:18 +00005938#endif
5939#ifdef TARGET_NR_geteuid32
bellard31e31b82003-02-18 22:55:36 +00005940 case TARGET_NR_geteuid32:
bellardb03c60f2003-03-23 17:19:56 +00005941 ret = get_errno(geteuid());
5942 break;
bellarda315a142005-01-30 22:59:18 +00005943#endif
5944#ifdef TARGET_NR_getegid32
bellard31e31b82003-02-18 22:55:36 +00005945 case TARGET_NR_getegid32:
bellardb03c60f2003-03-23 17:19:56 +00005946 ret = get_errno(getegid());
5947 break;
bellarda315a142005-01-30 22:59:18 +00005948#endif
5949#ifdef TARGET_NR_setreuid32
bellard31e31b82003-02-18 22:55:36 +00005950 case TARGET_NR_setreuid32:
bellardb03c60f2003-03-23 17:19:56 +00005951 ret = get_errno(setreuid(arg1, arg2));
5952 break;
bellarda315a142005-01-30 22:59:18 +00005953#endif
5954#ifdef TARGET_NR_setregid32
bellard31e31b82003-02-18 22:55:36 +00005955 case TARGET_NR_setregid32:
bellardb03c60f2003-03-23 17:19:56 +00005956 ret = get_errno(setregid(arg1, arg2));
5957 break;
bellarda315a142005-01-30 22:59:18 +00005958#endif
5959#ifdef TARGET_NR_getgroups32
bellard31e31b82003-02-18 22:55:36 +00005960 case TARGET_NR_getgroups32:
bellard99c475a2005-01-31 20:45:13 +00005961 {
5962 int gidsetsize = arg1;
pbrook53a59602006-03-25 19:31:22 +00005963 uint32_t *target_grouplist;
bellard99c475a2005-01-31 20:45:13 +00005964 gid_t *grouplist;
5965 int i;
5966
5967 grouplist = alloca(gidsetsize * sizeof(gid_t));
5968 ret = get_errno(getgroups(gidsetsize, grouplist));
balrogcb3bc232008-09-20 02:08:13 +00005969 if (gidsetsize == 0)
5970 break;
bellard99c475a2005-01-31 20:45:13 +00005971 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00005972 target_grouplist = lock_user(VERIFY_WRITE, arg2, gidsetsize * 4, 0);
5973 if (!target_grouplist) {
5974 ret = -TARGET_EFAULT;
5975 goto fail;
5976 }
balroga2155fc2008-09-20 02:12:08 +00005977 for(i = 0;i < ret; i++)
pbrook53a59602006-03-25 19:31:22 +00005978 target_grouplist[i] = tswap32(grouplist[i]);
5979 unlock_user(target_grouplist, arg2, gidsetsize * 4);
bellard99c475a2005-01-31 20:45:13 +00005980 }
5981 }
5982 break;
bellarda315a142005-01-30 22:59:18 +00005983#endif
5984#ifdef TARGET_NR_setgroups32
bellard31e31b82003-02-18 22:55:36 +00005985 case TARGET_NR_setgroups32:
bellard99c475a2005-01-31 20:45:13 +00005986 {
5987 int gidsetsize = arg1;
pbrook53a59602006-03-25 19:31:22 +00005988 uint32_t *target_grouplist;
bellard99c475a2005-01-31 20:45:13 +00005989 gid_t *grouplist;
5990 int i;
ths3b46e622007-09-17 08:09:54 +00005991
bellard99c475a2005-01-31 20:45:13 +00005992 grouplist = alloca(gidsetsize * sizeof(gid_t));
bellard579a97f2007-11-11 14:26:47 +00005993 target_grouplist = lock_user(VERIFY_READ, arg2, gidsetsize * 4, 1);
5994 if (!target_grouplist) {
5995 ret = -TARGET_EFAULT;
5996 goto fail;
5997 }
bellard99c475a2005-01-31 20:45:13 +00005998 for(i = 0;i < gidsetsize; i++)
pbrook53a59602006-03-25 19:31:22 +00005999 grouplist[i] = tswap32(target_grouplist[i]);
6000 unlock_user(target_grouplist, arg2, 0);
bellard99c475a2005-01-31 20:45:13 +00006001 ret = get_errno(setgroups(gidsetsize, grouplist));
6002 }
6003 break;
bellarda315a142005-01-30 22:59:18 +00006004#endif
6005#ifdef TARGET_NR_fchown32
bellard31e31b82003-02-18 22:55:36 +00006006 case TARGET_NR_fchown32:
bellardb03c60f2003-03-23 17:19:56 +00006007 ret = get_errno(fchown(arg1, arg2, arg3));
6008 break;
bellarda315a142005-01-30 22:59:18 +00006009#endif
6010#ifdef TARGET_NR_setresuid32
bellard31e31b82003-02-18 22:55:36 +00006011 case TARGET_NR_setresuid32:
bellardb03c60f2003-03-23 17:19:56 +00006012 ret = get_errno(setresuid(arg1, arg2, arg3));
6013 break;
bellarda315a142005-01-30 22:59:18 +00006014#endif
6015#ifdef TARGET_NR_getresuid32
bellard31e31b82003-02-18 22:55:36 +00006016 case TARGET_NR_getresuid32:
bellardb03c60f2003-03-23 17:19:56 +00006017 {
pbrook53a59602006-03-25 19:31:22 +00006018 uid_t ruid, euid, suid;
bellardb03c60f2003-03-23 17:19:56 +00006019 ret = get_errno(getresuid(&ruid, &euid, &suid));
6020 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +00006021 if (put_user_u32(ruid, arg1)
6022 || put_user_u32(euid, arg2)
6023 || put_user_u32(suid, arg3))
6024 goto efault;
bellardb03c60f2003-03-23 17:19:56 +00006025 }
6026 }
6027 break;
bellarda315a142005-01-30 22:59:18 +00006028#endif
6029#ifdef TARGET_NR_setresgid32
bellard31e31b82003-02-18 22:55:36 +00006030 case TARGET_NR_setresgid32:
bellardb03c60f2003-03-23 17:19:56 +00006031 ret = get_errno(setresgid(arg1, arg2, arg3));
6032 break;
bellarda315a142005-01-30 22:59:18 +00006033#endif
6034#ifdef TARGET_NR_getresgid32
bellard31e31b82003-02-18 22:55:36 +00006035 case TARGET_NR_getresgid32:
bellardb03c60f2003-03-23 17:19:56 +00006036 {
pbrook53a59602006-03-25 19:31:22 +00006037 gid_t rgid, egid, sgid;
bellardb03c60f2003-03-23 17:19:56 +00006038 ret = get_errno(getresgid(&rgid, &egid, &sgid));
6039 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +00006040 if (put_user_u32(rgid, arg1)
6041 || put_user_u32(egid, arg2)
6042 || put_user_u32(sgid, arg3))
6043 goto efault;
bellardb03c60f2003-03-23 17:19:56 +00006044 }
6045 }
6046 break;
bellarda315a142005-01-30 22:59:18 +00006047#endif
6048#ifdef TARGET_NR_chown32
bellard31e31b82003-02-18 22:55:36 +00006049 case TARGET_NR_chown32:
bellard579a97f2007-11-11 14:26:47 +00006050 if (!(p = lock_user_string(arg1)))
6051 goto efault;
pbrook53a59602006-03-25 19:31:22 +00006052 ret = get_errno(chown(p, arg2, arg3));
6053 unlock_user(p, arg1, 0);
bellardb03c60f2003-03-23 17:19:56 +00006054 break;
bellarda315a142005-01-30 22:59:18 +00006055#endif
6056#ifdef TARGET_NR_setuid32
bellard31e31b82003-02-18 22:55:36 +00006057 case TARGET_NR_setuid32:
bellardb03c60f2003-03-23 17:19:56 +00006058 ret = get_errno(setuid(arg1));
6059 break;
bellarda315a142005-01-30 22:59:18 +00006060#endif
6061#ifdef TARGET_NR_setgid32
bellard31e31b82003-02-18 22:55:36 +00006062 case TARGET_NR_setgid32:
bellardb03c60f2003-03-23 17:19:56 +00006063 ret = get_errno(setgid(arg1));
6064 break;
bellarda315a142005-01-30 22:59:18 +00006065#endif
6066#ifdef TARGET_NR_setfsuid32
bellard31e31b82003-02-18 22:55:36 +00006067 case TARGET_NR_setfsuid32:
bellardb03c60f2003-03-23 17:19:56 +00006068 ret = get_errno(setfsuid(arg1));
6069 break;
bellarda315a142005-01-30 22:59:18 +00006070#endif
6071#ifdef TARGET_NR_setfsgid32
bellard31e31b82003-02-18 22:55:36 +00006072 case TARGET_NR_setfsgid32:
bellardb03c60f2003-03-23 17:19:56 +00006073 ret = get_errno(setfsgid(arg1));
6074 break;
bellarda315a142005-01-30 22:59:18 +00006075#endif
bellard67867302003-11-23 17:05:30 +00006076
bellard31e31b82003-02-18 22:55:36 +00006077 case TARGET_NR_pivot_root:
bellardb03c60f2003-03-23 17:19:56 +00006078 goto unimplemented;
bellardffa65c32004-01-04 23:57:22 +00006079#ifdef TARGET_NR_mincore
bellard31e31b82003-02-18 22:55:36 +00006080 case TARGET_NR_mincore:
aurel3204bb9ac2008-10-01 21:46:41 +00006081 {
6082 void *a;
6083 ret = -TARGET_EFAULT;
6084 if (!(a = lock_user(VERIFY_READ, arg1,arg2, 0)))
6085 goto efault;
6086 if (!(p = lock_user_string(arg3)))
6087 goto mincore_fail;
6088 ret = get_errno(mincore(a, arg2, p));
6089 unlock_user(p, arg3, ret);
6090 mincore_fail:
6091 unlock_user(a, arg1, 0);
6092 }
6093 break;
bellardffa65c32004-01-04 23:57:22 +00006094#endif
aurel32408321b2008-10-01 21:46:32 +00006095#ifdef TARGET_NR_arm_fadvise64_64
6096 case TARGET_NR_arm_fadvise64_64:
6097 {
6098 /*
6099 * arm_fadvise64_64 looks like fadvise64_64 but
6100 * with different argument order
6101 */
6102 abi_long temp;
6103 temp = arg3;
6104 arg3 = arg4;
6105 arg4 = temp;
6106 }
6107#endif
6108#if defined(TARGET_NR_fadvise64_64) || defined(TARGET_NR_arm_fadvise64_64)
6109#ifdef TARGET_NR_fadvise64_64
6110 case TARGET_NR_fadvise64_64:
6111#endif
6112 /* This is a hint, so ignoring and returning success is ok. */
6113 ret = get_errno(0);
6114 break;
6115#endif
bellardffa65c32004-01-04 23:57:22 +00006116#ifdef TARGET_NR_madvise
bellard31e31b82003-02-18 22:55:36 +00006117 case TARGET_NR_madvise:
pbrook24836682006-04-16 14:14:53 +00006118 /* A straight passthrough may not be safe because qemu sometimes
6119 turns private flie-backed mappings into anonymous mappings.
6120 This will break MADV_DONTNEED.
6121 This is a hint, so ignoring and returning success is ok. */
6122 ret = get_errno(0);
6123 break;
bellardffa65c32004-01-04 23:57:22 +00006124#endif
blueswir1992f48a2007-10-14 16:27:31 +00006125#if TARGET_ABI_BITS == 32
bellard31e31b82003-02-18 22:55:36 +00006126 case TARGET_NR_fcntl64:
bellard77e46722003-04-29 20:39:06 +00006127 {
thsb1e341e2007-03-20 21:50:52 +00006128 int cmd;
bellard77e46722003-04-29 20:39:06 +00006129 struct flock64 fl;
pbrook53a59602006-03-25 19:31:22 +00006130 struct target_flock64 *target_fl;
pbrookce4defa2006-02-09 16:49:55 +00006131#ifdef TARGET_ARM
pbrook53a59602006-03-25 19:31:22 +00006132 struct target_eabi_flock64 *target_efl;
pbrookce4defa2006-02-09 16:49:55 +00006133#endif
bellard77e46722003-04-29 20:39:06 +00006134
thsb1e341e2007-03-20 21:50:52 +00006135 switch(arg2){
6136 case TARGET_F_GETLK64:
6137 cmd = F_GETLK64;
thsa7222582007-03-22 15:08:55 +00006138 break;
thsb1e341e2007-03-20 21:50:52 +00006139 case TARGET_F_SETLK64:
6140 cmd = F_SETLK64;
thsa7222582007-03-22 15:08:55 +00006141 break;
thsb1e341e2007-03-20 21:50:52 +00006142 case TARGET_F_SETLKW64:
6143 cmd = F_SETLK64;
thsa7222582007-03-22 15:08:55 +00006144 break;
thsb1e341e2007-03-20 21:50:52 +00006145 default:
6146 cmd = arg2;
thsa7222582007-03-22 15:08:55 +00006147 break;
thsb1e341e2007-03-20 21:50:52 +00006148 }
6149
bellard60cd49d2003-03-16 22:53:56 +00006150 switch(arg2) {
thsb1e341e2007-03-20 21:50:52 +00006151 case TARGET_F_GETLK64:
ths58134272007-03-31 18:59:32 +00006152#ifdef TARGET_ARM
6153 if (((CPUARMState *)cpu_env)->eabi) {
bellard9ee1fa22007-11-11 15:11:19 +00006154 if (!lock_user_struct(VERIFY_READ, target_efl, arg3, 1))
6155 goto efault;
ths58134272007-03-31 18:59:32 +00006156 fl.l_type = tswap16(target_efl->l_type);
6157 fl.l_whence = tswap16(target_efl->l_whence);
6158 fl.l_start = tswap64(target_efl->l_start);
6159 fl.l_len = tswap64(target_efl->l_len);
6160 fl.l_pid = tswapl(target_efl->l_pid);
6161 unlock_user_struct(target_efl, arg3, 0);
6162 } else
6163#endif
6164 {
bellard9ee1fa22007-11-11 15:11:19 +00006165 if (!lock_user_struct(VERIFY_READ, target_fl, arg3, 1))
6166 goto efault;
ths58134272007-03-31 18:59:32 +00006167 fl.l_type = tswap16(target_fl->l_type);
6168 fl.l_whence = tswap16(target_fl->l_whence);
6169 fl.l_start = tswap64(target_fl->l_start);
6170 fl.l_len = tswap64(target_fl->l_len);
6171 fl.l_pid = tswapl(target_fl->l_pid);
6172 unlock_user_struct(target_fl, arg3, 0);
6173 }
thsb1e341e2007-03-20 21:50:52 +00006174 ret = get_errno(fcntl(arg1, cmd, &fl));
bellard77e46722003-04-29 20:39:06 +00006175 if (ret == 0) {
pbrookce4defa2006-02-09 16:49:55 +00006176#ifdef TARGET_ARM
6177 if (((CPUARMState *)cpu_env)->eabi) {
bellard9ee1fa22007-11-11 15:11:19 +00006178 if (!lock_user_struct(VERIFY_WRITE, target_efl, arg3, 0))
6179 goto efault;
pbrookce4defa2006-02-09 16:49:55 +00006180 target_efl->l_type = tswap16(fl.l_type);
6181 target_efl->l_whence = tswap16(fl.l_whence);
6182 target_efl->l_start = tswap64(fl.l_start);
6183 target_efl->l_len = tswap64(fl.l_len);
6184 target_efl->l_pid = tswapl(fl.l_pid);
pbrook53a59602006-03-25 19:31:22 +00006185 unlock_user_struct(target_efl, arg3, 1);
pbrookce4defa2006-02-09 16:49:55 +00006186 } else
6187#endif
6188 {
bellard9ee1fa22007-11-11 15:11:19 +00006189 if (!lock_user_struct(VERIFY_WRITE, target_fl, arg3, 0))
6190 goto efault;
pbrookce4defa2006-02-09 16:49:55 +00006191 target_fl->l_type = tswap16(fl.l_type);
6192 target_fl->l_whence = tswap16(fl.l_whence);
6193 target_fl->l_start = tswap64(fl.l_start);
6194 target_fl->l_len = tswap64(fl.l_len);
6195 target_fl->l_pid = tswapl(fl.l_pid);
pbrook53a59602006-03-25 19:31:22 +00006196 unlock_user_struct(target_fl, arg3, 1);
pbrookce4defa2006-02-09 16:49:55 +00006197 }
bellard77e46722003-04-29 20:39:06 +00006198 }
6199 break;
6200
thsb1e341e2007-03-20 21:50:52 +00006201 case TARGET_F_SETLK64:
6202 case TARGET_F_SETLKW64:
pbrookce4defa2006-02-09 16:49:55 +00006203#ifdef TARGET_ARM
6204 if (((CPUARMState *)cpu_env)->eabi) {
bellard9ee1fa22007-11-11 15:11:19 +00006205 if (!lock_user_struct(VERIFY_READ, target_efl, arg3, 1))
6206 goto efault;
pbrookce4defa2006-02-09 16:49:55 +00006207 fl.l_type = tswap16(target_efl->l_type);
6208 fl.l_whence = tswap16(target_efl->l_whence);
6209 fl.l_start = tswap64(target_efl->l_start);
6210 fl.l_len = tswap64(target_efl->l_len);
6211 fl.l_pid = tswapl(target_efl->l_pid);
pbrook53a59602006-03-25 19:31:22 +00006212 unlock_user_struct(target_efl, arg3, 0);
pbrookce4defa2006-02-09 16:49:55 +00006213 } else
6214#endif
6215 {
bellard9ee1fa22007-11-11 15:11:19 +00006216 if (!lock_user_struct(VERIFY_READ, target_fl, arg3, 1))
6217 goto efault;
pbrookce4defa2006-02-09 16:49:55 +00006218 fl.l_type = tswap16(target_fl->l_type);
6219 fl.l_whence = tswap16(target_fl->l_whence);
6220 fl.l_start = tswap64(target_fl->l_start);
6221 fl.l_len = tswap64(target_fl->l_len);
6222 fl.l_pid = tswapl(target_fl->l_pid);
pbrook53a59602006-03-25 19:31:22 +00006223 unlock_user_struct(target_fl, arg3, 0);
pbrookce4defa2006-02-09 16:49:55 +00006224 }
thsb1e341e2007-03-20 21:50:52 +00006225 ret = get_errno(fcntl(arg1, cmd, &fl));
bellard77e46722003-04-29 20:39:06 +00006226 break;
bellard60cd49d2003-03-16 22:53:56 +00006227 default:
bellard9ee1fa22007-11-11 15:11:19 +00006228 ret = do_fcntl(arg1, cmd, arg3);
bellard60cd49d2003-03-16 22:53:56 +00006229 break;
6230 }
bellard77e46722003-04-29 20:39:06 +00006231 break;
6232 }
bellard60cd49d2003-03-16 22:53:56 +00006233#endif
ths7d600c82006-12-08 01:32:58 +00006234#ifdef TARGET_NR_cacheflush
6235 case TARGET_NR_cacheflush:
6236 /* self-modifying code is handled automatically, so nothing needed */
6237 ret = 0;
6238 break;
6239#endif
bellardebc05482003-09-30 21:08:41 +00006240#ifdef TARGET_NR_security
bellard31e31b82003-02-18 22:55:36 +00006241 case TARGET_NR_security:
6242 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00006243#endif
bellardc573ff62004-01-04 15:51:36 +00006244#ifdef TARGET_NR_getpagesize
6245 case TARGET_NR_getpagesize:
6246 ret = TARGET_PAGE_SIZE;
6247 break;
6248#endif
bellard31e31b82003-02-18 22:55:36 +00006249 case TARGET_NR_gettid:
6250 ret = get_errno(gettid());
6251 break;
thse5febef2007-04-01 18:31:35 +00006252#ifdef TARGET_NR_readahead
bellard31e31b82003-02-18 22:55:36 +00006253 case TARGET_NR_readahead:
aurel322054ac92008-10-13 21:08:07 +00006254#if TARGET_ABI_BITS == 32
6255#ifdef TARGET_ARM
6256 if (((CPUARMState *)cpu_env)->eabi)
6257 {
6258 arg2 = arg3;
6259 arg3 = arg4;
6260 arg4 = arg5;
6261 }
6262#endif
6263 ret = get_errno(readahead(arg1, ((off64_t)arg3 << 32) | arg2, arg4));
6264#else
6265 ret = get_errno(readahead(arg1, arg2, arg3));
6266#endif
6267 break;
thse5febef2007-04-01 18:31:35 +00006268#endif
bellardebc05482003-09-30 21:08:41 +00006269#ifdef TARGET_NR_setxattr
bellard31e31b82003-02-18 22:55:36 +00006270 case TARGET_NR_setxattr:
6271 case TARGET_NR_lsetxattr:
6272 case TARGET_NR_fsetxattr:
6273 case TARGET_NR_getxattr:
6274 case TARGET_NR_lgetxattr:
6275 case TARGET_NR_fgetxattr:
6276 case TARGET_NR_listxattr:
6277 case TARGET_NR_llistxattr:
6278 case TARGET_NR_flistxattr:
6279 case TARGET_NR_removexattr:
6280 case TARGET_NR_lremovexattr:
6281 case TARGET_NR_fremovexattr:
bellard5cd43932003-03-29 16:54:36 +00006282 goto unimplemented_nowarn;
bellardebc05482003-09-30 21:08:41 +00006283#endif
6284#ifdef TARGET_NR_set_thread_area
bellard5cd43932003-03-29 16:54:36 +00006285 case TARGET_NR_set_thread_area:
bellard8d18e892007-11-14 15:18:40 +00006286#if defined(TARGET_MIPS)
ths6f5b89a2007-03-02 20:48:00 +00006287 ((CPUMIPSState *) cpu_env)->tls_value = arg1;
6288 ret = 0;
6289 break;
edgar_iglef967792009-01-07 14:19:38 +00006290#elif defined(TARGET_CRIS)
6291 if (arg1 & 0xff)
6292 ret = -TARGET_EINVAL;
6293 else {
6294 ((CPUCRISState *) cpu_env)->pregs[PR_PID] = arg1;
6295 ret = 0;
6296 }
6297 break;
bellard8d18e892007-11-14 15:18:40 +00006298#elif defined(TARGET_I386) && defined(TARGET_ABI32)
6299 ret = do_set_thread_area(cpu_env, arg1);
6300 break;
ths6f5b89a2007-03-02 20:48:00 +00006301#else
6302 goto unimplemented_nowarn;
6303#endif
6304#endif
6305#ifdef TARGET_NR_get_thread_area
bellard5cd43932003-03-29 16:54:36 +00006306 case TARGET_NR_get_thread_area:
bellard8d18e892007-11-14 15:18:40 +00006307#if defined(TARGET_I386) && defined(TARGET_ABI32)
6308 ret = do_get_thread_area(cpu_env, arg1);
6309#else
bellard5cd43932003-03-29 16:54:36 +00006310 goto unimplemented_nowarn;
bellardebc05482003-09-30 21:08:41 +00006311#endif
bellard8d18e892007-11-14 15:18:40 +00006312#endif
bellard48dc41e2006-06-21 18:15:50 +00006313#ifdef TARGET_NR_getdomainname
6314 case TARGET_NR_getdomainname:
6315 goto unimplemented_nowarn;
6316#endif
ths6f5b89a2007-03-02 20:48:00 +00006317
thsb5906f92007-03-19 13:32:45 +00006318#ifdef TARGET_NR_clock_gettime
6319 case TARGET_NR_clock_gettime:
6320 {
6321 struct timespec ts;
6322 ret = get_errno(clock_gettime(arg1, &ts));
6323 if (!is_error(ret)) {
6324 host_to_target_timespec(arg2, &ts);
6325 }
6326 break;
6327 }
6328#endif
6329#ifdef TARGET_NR_clock_getres
6330 case TARGET_NR_clock_getres:
6331 {
6332 struct timespec ts;
6333 ret = get_errno(clock_getres(arg1, &ts));
6334 if (!is_error(ret)) {
6335 host_to_target_timespec(arg2, &ts);
6336 }
6337 break;
6338 }
6339#endif
pbrook63d76512008-05-29 13:43:29 +00006340#ifdef TARGET_NR_clock_nanosleep
6341 case TARGET_NR_clock_nanosleep:
6342 {
6343 struct timespec ts;
6344 target_to_host_timespec(&ts, arg3);
6345 ret = get_errno(clock_nanosleep(arg1, arg2, &ts, arg4 ? &ts : NULL));
6346 if (arg4)
6347 host_to_target_timespec(arg4, &ts);
6348 break;
6349 }
6350#endif
thsb5906f92007-03-19 13:32:45 +00006351
ths6f5b89a2007-03-02 20:48:00 +00006352#if defined(TARGET_NR_set_tid_address) && defined(__NR_set_tid_address)
6353 case TARGET_NR_set_tid_address:
bellard579a97f2007-11-11 14:26:47 +00006354 ret = get_errno(set_tid_address((int *)g2h(arg1)));
6355 break;
ths6f5b89a2007-03-02 20:48:00 +00006356#endif
6357
ths3ae43202007-09-16 21:39:48 +00006358#if defined(TARGET_NR_tkill) && defined(__NR_tkill)
ths4cae1d12007-07-12 11:06:53 +00006359 case TARGET_NR_tkill:
pbrook4cb05962008-05-30 18:05:19 +00006360 ret = get_errno(sys_tkill((int)arg1, target_to_host_signal(arg2)));
ths4cae1d12007-07-12 11:06:53 +00006361 break;
6362#endif
6363
ths3ae43202007-09-16 21:39:48 +00006364#if defined(TARGET_NR_tgkill) && defined(__NR_tgkill)
ths71455572007-06-21 21:45:30 +00006365 case TARGET_NR_tgkill:
pbrook4cb05962008-05-30 18:05:19 +00006366 ret = get_errno(sys_tgkill((int)arg1, (int)arg2,
6367 target_to_host_signal(arg3)));
ths71455572007-06-21 21:45:30 +00006368 break;
6369#endif
6370
ths4f2b1fe2007-06-21 21:57:12 +00006371#ifdef TARGET_NR_set_robust_list
6372 case TARGET_NR_set_robust_list:
6373 goto unimplemented_nowarn;
6374#endif
6375
ths9007f0e2007-09-25 17:50:37 +00006376#if defined(TARGET_NR_utimensat) && defined(__NR_utimensat)
6377 case TARGET_NR_utimensat:
6378 {
6379 struct timespec ts[2];
6380 target_to_host_timespec(ts, arg3);
6381 target_to_host_timespec(ts+1, arg3+sizeof(struct target_timespec));
6382 if (!arg2)
6383 ret = get_errno(sys_utimensat(arg1, NULL, ts, arg4));
6384 else {
bellard579a97f2007-11-11 14:26:47 +00006385 if (!(p = lock_user_string(arg2))) {
ths0da46a62007-10-20 20:23:07 +00006386 ret = -TARGET_EFAULT;
bellard579a97f2007-11-11 14:26:47 +00006387 goto fail;
6388 }
6389 ret = get_errno(sys_utimensat(arg1, path(p), ts, arg4));
6390 unlock_user(p, arg2, 0);
ths9007f0e2007-09-25 17:50:37 +00006391 }
6392 }
6393 break;
6394#endif
pbrookbd0c5662008-05-29 14:34:11 +00006395#if defined(USE_NPTL)
6396 case TARGET_NR_futex:
6397 ret = do_futex(arg1, arg2, arg3, arg4, arg5, arg6);
6398 break;
6399#endif
aurel32dbfe4c32009-04-08 21:29:30 +00006400#if defined(TARGET_NR_inotify_init) && defined(__NR_inotify_init)
aurel3239b59762008-10-01 21:46:50 +00006401 case TARGET_NR_inotify_init:
6402 ret = get_errno(sys_inotify_init());
6403 break;
6404#endif
aurel32dbfe4c32009-04-08 21:29:30 +00006405#if defined(TARGET_NR_inotify_add_watch) && defined(__NR_inotify_add_watch)
aurel3239b59762008-10-01 21:46:50 +00006406 case TARGET_NR_inotify_add_watch:
6407 p = lock_user_string(arg2);
6408 ret = get_errno(sys_inotify_add_watch(arg1, path(p), arg3));
6409 unlock_user(p, arg2, 0);
6410 break;
6411#endif
aurel32dbfe4c32009-04-08 21:29:30 +00006412#if defined(TARGET_NR_inotify_rm_watch) && defined(__NR_inotify_rm_watch)
aurel3239b59762008-10-01 21:46:50 +00006413 case TARGET_NR_inotify_rm_watch:
6414 ret = get_errno(sys_inotify_rm_watch(arg1, arg2));
6415 break;
6416#endif
ths9007f0e2007-09-25 17:50:37 +00006417
aurel3224e10032009-04-15 16:11:43 +00006418#ifdef TARGET_NR_mq_open
6419 case TARGET_NR_mq_open:
6420 {
6421 struct mq_attr posix_mq_attr;
6422
6423 p = lock_user_string(arg1 - 1);
6424 if (arg4 != 0)
6425 copy_from_user_mq_attr (&posix_mq_attr, arg4);
6426 ret = get_errno(mq_open(p, arg2, arg3, &posix_mq_attr));
6427 unlock_user (p, arg1, 0);
6428 }
6429 break;
6430
6431 case TARGET_NR_mq_unlink:
6432 p = lock_user_string(arg1 - 1);
6433 ret = get_errno(mq_unlink(p));
6434 unlock_user (p, arg1, 0);
6435 break;
6436
6437 case TARGET_NR_mq_timedsend:
6438 {
6439 struct timespec ts;
6440
6441 p = lock_user (VERIFY_READ, arg2, arg3, 1);
6442 if (arg5 != 0) {
6443 target_to_host_timespec(&ts, arg5);
6444 ret = get_errno(mq_timedsend(arg1, p, arg3, arg4, &ts));
6445 host_to_target_timespec(arg5, &ts);
6446 }
6447 else
6448 ret = get_errno(mq_send(arg1, p, arg3, arg4));
6449 unlock_user (p, arg2, arg3);
6450 }
6451 break;
6452
6453 case TARGET_NR_mq_timedreceive:
6454 {
6455 struct timespec ts;
6456 unsigned int prio;
6457
6458 p = lock_user (VERIFY_READ, arg2, arg3, 1);
6459 if (arg5 != 0) {
6460 target_to_host_timespec(&ts, arg5);
6461 ret = get_errno(mq_timedreceive(arg1, p, arg3, &prio, &ts));
6462 host_to_target_timespec(arg5, &ts);
6463 }
6464 else
6465 ret = get_errno(mq_receive(arg1, p, arg3, &prio));
6466 unlock_user (p, arg2, arg3);
6467 if (arg4 != 0)
6468 put_user_u32(prio, arg4);
6469 }
6470 break;
6471
6472 /* Not implemented for now... */
6473/* case TARGET_NR_mq_notify: */
6474/* break; */
6475
6476 case TARGET_NR_mq_getsetattr:
6477 {
6478 struct mq_attr posix_mq_attr_in, posix_mq_attr_out;
6479 ret = 0;
6480 if (arg3 != 0) {
6481 ret = mq_getattr(arg1, &posix_mq_attr_out);
6482 copy_to_user_mq_attr(arg3, &posix_mq_attr_out);
6483 }
6484 if (arg2 != 0) {
6485 copy_from_user_mq_attr(&posix_mq_attr_in, arg2);
6486 ret |= mq_setattr(arg1, &posix_mq_attr_in, &posix_mq_attr_out);
6487 }
6488
6489 }
6490 break;
6491#endif
6492
bellard31e31b82003-02-18 22:55:36 +00006493 default:
6494 unimplemented:
bellard5cd43932003-03-29 16:54:36 +00006495 gemu_log("qemu: Unsupported syscall: %d\n", num);
ths4f2b1fe2007-06-21 21:57:12 +00006496#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 +00006497 unimplemented_nowarn:
bellard80a9d032005-01-03 23:31:27 +00006498#endif
ths0da46a62007-10-20 20:23:07 +00006499 ret = -TARGET_ENOSYS;
bellard31e31b82003-02-18 22:55:36 +00006500 break;
6501 }
bellard579a97f2007-11-11 14:26:47 +00006502fail:
bellardc573ff62004-01-04 15:51:36 +00006503#ifdef DEBUG
6504 gemu_log(" = %ld\n", ret);
6505#endif
thsb92c47c2007-11-01 00:07:38 +00006506 if(do_strace)
6507 print_syscall_ret(num, ret);
bellard31e31b82003-02-18 22:55:36 +00006508 return ret;
bellard579a97f2007-11-11 14:26:47 +00006509efault:
6510 ret = -TARGET_EFAULT;
6511 goto fail;
bellard31e31b82003-02-18 22:55:36 +00006512}