]> git.ipfire.org Git - thirdparty/qemu.git/blame - linux-user/syscall.c
linux-user/signal.c: Remove unused fenab
[thirdparty/qemu.git] / linux-user / syscall.c
CommitLineData
31e31b8a
FB
1/*
2 * Linux syscalls
5fafdf24 3 *
31e31b8a
FB
4 * 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
8167ee88 17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
31e31b8a 18 */
d5b3a9b6 19#define _ATFILE_SOURCE
31e31b8a
FB
20#include <stdlib.h>
21#include <stdio.h>
22#include <stdarg.h>
04369ff2 23#include <string.h>
31e31b8a
FB
24#include <elf.h>
25#include <endian.h>
26#include <errno.h>
27#include <unistd.h>
28#include <fcntl.h>
7854b056 29#include <time.h>
82e671d9 30#include <limits.h>
31e31b8a 31#include <sys/types.h>
d08d3bb8
TS
32#include <sys/ipc.h>
33#include <sys/msg.h>
31e31b8a
FB
34#include <sys/wait.h>
35#include <sys/time.h>
36#include <sys/stat.h>
37#include <sys/mount.h>
39b9aae1 38#include <sys/prctl.h>
31e31b8a
FB
39#include <sys/resource.h>
40#include <sys/mman.h>
41#include <sys/swap.h>
42#include <signal.h>
43#include <sched.h>
60e99246
AJ
44#ifdef __ia64__
45int __clone2(int (*fn)(void *), void *child_stack_base,
46 size_t stack_size, int flags, void *arg, ...);
47#endif
31e31b8a 48#include <sys/socket.h>
607175e0 49#include <sys/un.h>
31e31b8a 50#include <sys/uio.h>
9de5e440 51#include <sys/poll.h>
32f36bce 52#include <sys/times.h>
8853f86e 53#include <sys/shm.h>
fa294816 54#include <sys/sem.h>
56c8f68f 55#include <sys/statfs.h>
ebc05488 56#include <utime.h>
a5448a7d 57#include <sys/sysinfo.h>
3b3f24ad 58#include <sys/utsname.h>
72f03900 59//#include <sys/user.h>
8853f86e 60#include <netinet/ip.h>
7854b056 61#include <netinet/tcp.h>
86fcd946 62#include <linux/wireless.h>
0b6d3ae0 63#include <qemu-common.h>
9788c9ca 64#ifdef TARGET_GPROF
6d946cda
AJ
65#include <sys/gmon.h>
66#endif
c2882b96
RV
67#ifdef CONFIG_EVENTFD
68#include <sys/eventfd.h>
69#endif
3b6edd16
PM
70#ifdef CONFIG_EPOLL
71#include <sys/epoll.h>
72#endif
31e31b8a
FB
73
74#define termios host_termios
75#define winsize host_winsize
76#define termio host_termio
04369ff2
FB
77#define sgttyb host_sgttyb /* same as target */
78#define tchars host_tchars /* same as target */
79#define ltchars host_ltchars /* same as target */
31e31b8a
FB
80
81#include <linux/termios.h>
82#include <linux/unistd.h>
83#include <linux/utsname.h>
84#include <linux/cdrom.h>
85#include <linux/hdreg.h>
86#include <linux/soundcard.h>
19b84f3c 87#include <linux/kd.h>
8fbd6b52 88#include <linux/mtio.h>
350d1779 89#include <linux/fs.h>
dace20dc 90#if defined(CONFIG_FIEMAP)
285da2b9 91#include <linux/fiemap.h>
dace20dc 92#endif
f7680a55
UH
93#include <linux/fb.h>
94#include <linux/vt.h>
d7e4036e 95#include "linux_loop.h"
da79030f 96#include "cpu-uname.h"
31e31b8a 97
3ef693a0 98#include "qemu.h"
526ccb7a 99#include "qemu-common.h"
31e31b8a 100
2f7bb878 101#if defined(CONFIG_USE_NPTL)
d865bab5
PB
102#define CLONE_NPTL_FLAGS2 (CLONE_SETTLS | \
103 CLONE_PARENT_SETTID | CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID)
104#else
105/* XXX: Hardcode the above values. */
106#define CLONE_NPTL_FLAGS2 0
30813cea
PB
107#endif
108
72f03900 109//#define DEBUG
31e31b8a 110
1a9353d2 111//#include <linux/msdos_fs.h>
6556a833
AJ
112#define VFAT_IOCTL_READDIR_BOTH _IOR('r', 1, struct linux_dirent [2])
113#define VFAT_IOCTL_READDIR_SHORT _IOR('r', 2, struct linux_dirent [2])
1a9353d2 114
70a194b9 115
70a194b9
FB
116#undef _syscall0
117#undef _syscall1
118#undef _syscall2
119#undef _syscall3
120#undef _syscall4
121#undef _syscall5
83fcb515 122#undef _syscall6
70a194b9 123
83fcb515 124#define _syscall0(type,name) \
8fcd3692 125static type name (void) \
83fcb515
FB
126{ \
127 return syscall(__NR_##name); \
128}
70a194b9 129
83fcb515 130#define _syscall1(type,name,type1,arg1) \
8fcd3692 131static type name (type1 arg1) \
83fcb515
FB
132{ \
133 return syscall(__NR_##name, arg1); \
70a194b9
FB
134}
135
83fcb515 136#define _syscall2(type,name,type1,arg1,type2,arg2) \
8fcd3692 137static type name (type1 arg1,type2 arg2) \
83fcb515
FB
138{ \
139 return syscall(__NR_##name, arg1, arg2); \
70a194b9
FB
140}
141
83fcb515 142#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \
8fcd3692 143static type name (type1 arg1,type2 arg2,type3 arg3) \
83fcb515
FB
144{ \
145 return syscall(__NR_##name, arg1, arg2, arg3); \
70a194b9
FB
146}
147
83fcb515 148#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \
8fcd3692 149static type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4) \
83fcb515
FB
150{ \
151 return syscall(__NR_##name, arg1, arg2, arg3, arg4); \
70a194b9
FB
152}
153
83fcb515
FB
154#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
155 type5,arg5) \
8fcd3692 156static type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \
83fcb515
FB
157{ \
158 return syscall(__NR_##name, arg1, arg2, arg3, arg4, arg5); \
70a194b9
FB
159}
160
83fcb515
FB
161
162#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
163 type5,arg5,type6,arg6) \
8fcd3692
BS
164static type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5, \
165 type6 arg6) \
83fcb515
FB
166{ \
167 return syscall(__NR_##name, arg1, arg2, arg3, arg4, arg5, arg6); \
70a194b9 168}
83fcb515 169
70a194b9 170
31e31b8a 171#define __NR_sys_uname __NR_uname
92a34c10 172#define __NR_sys_faccessat __NR_faccessat
814d7977 173#define __NR_sys_fchmodat __NR_fchmodat
ccfa72b7 174#define __NR_sys_fchownat __NR_fchownat
6a24a778 175#define __NR_sys_fstatat64 __NR_fstatat64
ac8a6556 176#define __NR_sys_futimesat __NR_futimesat
72f03900 177#define __NR_sys_getcwd1 __NR_getcwd
72f03900 178#define __NR_sys_getdents __NR_getdents
dab2ed99 179#define __NR_sys_getdents64 __NR_getdents64
c6cda17a 180#define __NR_sys_getpriority __NR_getpriority
64f0ce4c 181#define __NR_sys_linkat __NR_linkat
4472ad0d 182#define __NR_sys_mkdirat __NR_mkdirat
75ac37a0 183#define __NR_sys_mknodat __NR_mknodat
9d33b76b 184#define __NR_sys_newfstatat __NR_newfstatat
82424832 185#define __NR_sys_openat __NR_openat
5e0ccb18 186#define __NR_sys_readlinkat __NR_readlinkat
722183f6 187#define __NR_sys_renameat __NR_renameat
66fb9763 188#define __NR_sys_rt_sigqueueinfo __NR_rt_sigqueueinfo
f0b6243d 189#define __NR_sys_symlinkat __NR_symlinkat
7494b0f9 190#define __NR_sys_syslog __NR_syslog
71455574 191#define __NR_sys_tgkill __NR_tgkill
4cae1d16 192#define __NR_sys_tkill __NR_tkill
8170f56b 193#define __NR_sys_unlinkat __NR_unlinkat
9007f0ef 194#define __NR_sys_utimensat __NR_utimensat
bd0c5661 195#define __NR_sys_futex __NR_futex
39b59763
AJ
196#define __NR_sys_inotify_init __NR_inotify_init
197#define __NR_sys_inotify_add_watch __NR_inotify_add_watch
198#define __NR_sys_inotify_rm_watch __NR_inotify_rm_watch
31e31b8a 199
42a39fbe
AG
200#if defined(__alpha__) || defined (__ia64__) || defined(__x86_64__) || \
201 defined(__s390x__)
9af9eaaa
FB
202#define __NR__llseek __NR_lseek
203#endif
204
72f03900 205#ifdef __NR_gettid
31e31b8a 206_syscall0(int, gettid)
72f03900 207#else
0da46a6e
TS
208/* This is a replacement for the host gettid() and must return a host
209 errno. */
72f03900
FB
210static int gettid(void) {
211 return -ENOSYS;
212}
213#endif
3b3f24ad 214_syscall3(int, sys_getdents, uint, fd, struct linux_dirent *, dirp, uint, count);
3b3f24ad
AJ
215#if defined(TARGET_NR_getdents64) && defined(__NR_getdents64)
216_syscall3(int, sys_getdents64, uint, fd, struct linux_dirent64 *, dirp, uint, count);
217#endif
218_syscall2(int, sys_getpriority, int, which, int, who);
d35b261c 219#if defined(TARGET_NR__llseek) && defined(__NR_llseek)
3b3f24ad
AJ
220_syscall5(int, _llseek, uint, fd, ulong, hi, ulong, lo,
221 loff_t *, res, uint, wh);
222#endif
223_syscall3(int,sys_rt_sigqueueinfo,int,pid,int,sig,siginfo_t *,uinfo)
224_syscall3(int,sys_syslog,int,type,char*,bufp,int,len)
225#if defined(TARGET_NR_tgkill) && defined(__NR_tgkill)
226_syscall3(int,sys_tgkill,int,tgid,int,pid,int,sig)
227#endif
228#if defined(TARGET_NR_tkill) && defined(__NR_tkill)
229_syscall2(int,sys_tkill,int,tid,int,sig)
230#endif
231#ifdef __NR_exit_group
232_syscall1(int,exit_group,int,error_code)
233#endif
234#if defined(TARGET_NR_set_tid_address) && defined(__NR_set_tid_address)
235_syscall1(int,set_tid_address,int *,tidptr)
236#endif
2f7bb878 237#if defined(CONFIG_USE_NPTL)
3b3f24ad
AJ
238#if defined(TARGET_NR_futex) && defined(__NR_futex)
239_syscall6(int,sys_futex,int *,uaddr,int,op,int,val,
240 const struct timespec *,timeout,int *,uaddr2,int,val3)
241#endif
242#endif
737de1d1
MF
243#define __NR_sys_sched_getaffinity __NR_sched_getaffinity
244_syscall3(int, sys_sched_getaffinity, pid_t, pid, unsigned int, len,
245 unsigned long *, user_mask_ptr);
246#define __NR_sys_sched_setaffinity __NR_sched_setaffinity
247_syscall3(int, sys_sched_setaffinity, pid_t, pid, unsigned int, len,
248 unsigned long *, user_mask_ptr);
3b3f24ad
AJ
249
250static bitmask_transtbl fcntl_flags_tbl[] = {
251 { TARGET_O_ACCMODE, TARGET_O_WRONLY, O_ACCMODE, O_WRONLY, },
252 { TARGET_O_ACCMODE, TARGET_O_RDWR, O_ACCMODE, O_RDWR, },
253 { TARGET_O_CREAT, TARGET_O_CREAT, O_CREAT, O_CREAT, },
254 { TARGET_O_EXCL, TARGET_O_EXCL, O_EXCL, O_EXCL, },
255 { TARGET_O_NOCTTY, TARGET_O_NOCTTY, O_NOCTTY, O_NOCTTY, },
256 { TARGET_O_TRUNC, TARGET_O_TRUNC, O_TRUNC, O_TRUNC, },
257 { TARGET_O_APPEND, TARGET_O_APPEND, O_APPEND, O_APPEND, },
258 { TARGET_O_NONBLOCK, TARGET_O_NONBLOCK, O_NONBLOCK, O_NONBLOCK, },
259 { TARGET_O_SYNC, TARGET_O_SYNC, O_SYNC, O_SYNC, },
260 { TARGET_FASYNC, TARGET_FASYNC, FASYNC, FASYNC, },
261 { TARGET_O_DIRECTORY, TARGET_O_DIRECTORY, O_DIRECTORY, O_DIRECTORY, },
262 { TARGET_O_NOFOLLOW, TARGET_O_NOFOLLOW, O_NOFOLLOW, O_NOFOLLOW, },
263 { TARGET_O_LARGEFILE, TARGET_O_LARGEFILE, O_LARGEFILE, O_LARGEFILE, },
264#if defined(O_DIRECT)
265 { TARGET_O_DIRECT, TARGET_O_DIRECT, O_DIRECT, O_DIRECT, },
266#endif
267 { 0, 0, 0, 0 }
268};
269
270#define COPY_UTSNAME_FIELD(dest, src) \
271 do { \
272 /* __NEW_UTS_LEN doesn't include terminating null */ \
273 (void) strncpy((dest), (src), __NEW_UTS_LEN); \
274 (dest)[__NEW_UTS_LEN] = '\0'; \
275 } while (0)
276
277static int sys_uname(struct new_utsname *buf)
278{
279 struct utsname uts_buf;
280
281 if (uname(&uts_buf) < 0)
282 return (-1);
283
284 /*
285 * Just in case these have some differences, we
286 * translate utsname to new_utsname (which is the
287 * struct linux kernel uses).
288 */
289
67bd9ede 290 memset(buf, 0, sizeof(*buf));
3b3f24ad
AJ
291 COPY_UTSNAME_FIELD(buf->sysname, uts_buf.sysname);
292 COPY_UTSNAME_FIELD(buf->nodename, uts_buf.nodename);
293 COPY_UTSNAME_FIELD(buf->release, uts_buf.release);
294 COPY_UTSNAME_FIELD(buf->version, uts_buf.version);
295 COPY_UTSNAME_FIELD(buf->machine, uts_buf.machine);
296#ifdef _GNU_SOURCE
297 COPY_UTSNAME_FIELD(buf->domainname, uts_buf.domainname);
298#endif
299 return (0);
300
301#undef COPY_UTSNAME_FIELD
302}
303
304static int sys_getcwd1(char *buf, size_t size)
305{
306 if (getcwd(buf, size) == NULL) {
307 /* getcwd() sets errno */
308 return (-1);
309 }
aaf4ad39 310 return strlen(buf)+1;
3b3f24ad
AJ
311}
312
313#ifdef CONFIG_ATFILE
314/*
315 * Host system seems to have atfile syscall stubs available. We
316 * now enable them one by one as specified by target syscall_nr.h.
317 */
318
319#ifdef TARGET_NR_faccessat
465c9f06 320static int sys_faccessat(int dirfd, const char *pathname, int mode)
3b3f24ad 321{
465c9f06 322 return (faccessat(dirfd, pathname, mode, 0));
3b3f24ad
AJ
323}
324#endif
325#ifdef TARGET_NR_fchmodat
465c9f06 326static int sys_fchmodat(int dirfd, const char *pathname, mode_t mode)
3b3f24ad 327{
465c9f06 328 return (fchmodat(dirfd, pathname, mode, 0));
3b3f24ad
AJ
329}
330#endif
0c866a7e 331#if defined(TARGET_NR_fchownat)
3b3f24ad
AJ
332static int sys_fchownat(int dirfd, const char *pathname, uid_t owner,
333 gid_t group, int flags)
334{
335 return (fchownat(dirfd, pathname, owner, group, flags));
336}
337#endif
338#ifdef __NR_fstatat64
339static int sys_fstatat64(int dirfd, const char *pathname, struct stat *buf,
340 int flags)
341{
342 return (fstatat(dirfd, pathname, buf, flags));
343}
344#endif
345#ifdef __NR_newfstatat
346static int sys_newfstatat(int dirfd, const char *pathname, struct stat *buf,
347 int flags)
348{
349 return (fstatat(dirfd, pathname, buf, flags));
350}
351#endif
352#ifdef TARGET_NR_futimesat
353static int sys_futimesat(int dirfd, const char *pathname,
354 const struct timeval times[2])
355{
356 return (futimesat(dirfd, pathname, times));
357}
358#endif
359#ifdef TARGET_NR_linkat
360static int sys_linkat(int olddirfd, const char *oldpath,
361 int newdirfd, const char *newpath, int flags)
362{
363 return (linkat(olddirfd, oldpath, newdirfd, newpath, flags));
364}
365#endif
366#ifdef TARGET_NR_mkdirat
367static int sys_mkdirat(int dirfd, const char *pathname, mode_t mode)
368{
369 return (mkdirat(dirfd, pathname, mode));
370}
371#endif
372#ifdef TARGET_NR_mknodat
373static int sys_mknodat(int dirfd, const char *pathname, mode_t mode,
374 dev_t dev)
375{
376 return (mknodat(dirfd, pathname, mode, dev));
377}
378#endif
379#ifdef TARGET_NR_openat
380static int sys_openat(int dirfd, const char *pathname, int flags, ...)
381{
382 /*
383 * open(2) has extra parameter 'mode' when called with
384 * flag O_CREAT.
385 */
386 if ((flags & O_CREAT) != 0) {
387 va_list ap;
388 mode_t mode;
389
390 /*
391 * Get the 'mode' parameter and translate it to
392 * host bits.
393 */
394 va_start(ap, flags);
395 mode = va_arg(ap, mode_t);
396 mode = target_to_host_bitmask(mode, fcntl_flags_tbl);
397 va_end(ap);
398
399 return (openat(dirfd, pathname, flags, mode));
400 }
401 return (openat(dirfd, pathname, flags));
402}
403#endif
404#ifdef TARGET_NR_readlinkat
405static int sys_readlinkat(int dirfd, const char *pathname, char *buf, size_t bufsiz)
406{
407 return (readlinkat(dirfd, pathname, buf, bufsiz));
408}
409#endif
410#ifdef TARGET_NR_renameat
411static int sys_renameat(int olddirfd, const char *oldpath,
412 int newdirfd, const char *newpath)
413{
414 return (renameat(olddirfd, oldpath, newdirfd, newpath));
415}
416#endif
417#ifdef TARGET_NR_symlinkat
418static int sys_symlinkat(const char *oldpath, int newdirfd, const char *newpath)
419{
420 return (symlinkat(oldpath, newdirfd, newpath));
421}
422#endif
423#ifdef TARGET_NR_unlinkat
424static int sys_unlinkat(int dirfd, const char *pathname, int flags)
425{
426 return (unlinkat(dirfd, pathname, flags));
427}
428#endif
3b3f24ad
AJ
429#else /* !CONFIG_ATFILE */
430
431/*
432 * Try direct syscalls instead
433 */
92a34c10 434#if defined(TARGET_NR_faccessat) && defined(__NR_faccessat)
465c9f06 435_syscall3(int,sys_faccessat,int,dirfd,const char *,pathname,int,mode)
92a34c10 436#endif
814d7977 437#if defined(TARGET_NR_fchmodat) && defined(__NR_fchmodat)
465c9f06 438_syscall3(int,sys_fchmodat,int,dirfd,const char *,pathname, mode_t,mode)
814d7977 439#endif
0c866a7e 440#if defined(TARGET_NR_fchownat) && defined(__NR_fchownat)
ccfa72b7
TS
441_syscall5(int,sys_fchownat,int,dirfd,const char *,pathname,
442 uid_t,owner,gid_t,group,int,flags)
443#endif
9d33b76b
AJ
444#if (defined(TARGET_NR_fstatat64) || defined(TARGET_NR_newfstatat)) && \
445 defined(__NR_fstatat64)
6a24a778
AZ
446_syscall4(int,sys_fstatat64,int,dirfd,const char *,pathname,
447 struct stat *,buf,int,flags)
448#endif
ac8a6556
AZ
449#if defined(TARGET_NR_futimesat) && defined(__NR_futimesat)
450_syscall3(int,sys_futimesat,int,dirfd,const char *,pathname,
451 const struct timeval *,times)
452#endif
3b3f24ad
AJ
453#if (defined(TARGET_NR_newfstatat) || defined(TARGET_NR_fstatat64) ) && \
454 defined(__NR_newfstatat)
455_syscall4(int,sys_newfstatat,int,dirfd,const char *,pathname,
456 struct stat *,buf,int,flags)
8fcd3692 457#endif
64f0ce4c
TS
458#if defined(TARGET_NR_linkat) && defined(__NR_linkat)
459_syscall5(int,sys_linkat,int,olddirfd,const char *,oldpath,
3b3f24ad 460 int,newdirfd,const char *,newpath,int,flags)
64f0ce4c 461#endif
4472ad0d
TS
462#if defined(TARGET_NR_mkdirat) && defined(__NR_mkdirat)
463_syscall3(int,sys_mkdirat,int,dirfd,const char *,pathname,mode_t,mode)
464#endif
75ac37a0
TS
465#if defined(TARGET_NR_mknodat) && defined(__NR_mknodat)
466_syscall4(int,sys_mknodat,int,dirfd,const char *,pathname,
467 mode_t,mode,dev_t,dev)
468#endif
82424832
TS
469#if defined(TARGET_NR_openat) && defined(__NR_openat)
470_syscall4(int,sys_openat,int,dirfd,const char *,pathname,int,flags,mode_t,mode)
471#endif
5e0ccb18
TS
472#if defined(TARGET_NR_readlinkat) && defined(__NR_readlinkat)
473_syscall4(int,sys_readlinkat,int,dirfd,const char *,pathname,
474 char *,buf,size_t,bufsize)
475#endif
722183f6
TS
476#if defined(TARGET_NR_renameat) && defined(__NR_renameat)
477_syscall4(int,sys_renameat,int,olddirfd,const char *,oldpath,
478 int,newdirfd,const char *,newpath)
479#endif
b51eaa82 480#if defined(TARGET_NR_symlinkat) && defined(__NR_symlinkat)
f0b6243d
TS
481_syscall3(int,sys_symlinkat,const char *,oldpath,
482 int,newdirfd,const char *,newpath)
483#endif
8170f56b
TS
484#if defined(TARGET_NR_unlinkat) && defined(__NR_unlinkat)
485_syscall3(int,sys_unlinkat,int,dirfd,const char *,pathname,int,flags)
486#endif
ebc996f3
RV
487
488#endif /* CONFIG_ATFILE */
489
490#ifdef CONFIG_UTIMENSAT
491static int sys_utimensat(int dirfd, const char *pathname,
492 const struct timespec times[2], int flags)
493{
494 if (pathname == NULL)
495 return futimens(dirfd, times);
496 else
497 return utimensat(dirfd, pathname, times, flags);
498}
499#else
9007f0ef
TS
500#if defined(TARGET_NR_utimensat) && defined(__NR_utimensat)
501_syscall4(int,sys_utimensat,int,dirfd,const char *,pathname,
502 const struct timespec *,tsp,int,flags)
503#endif
ebc996f3 504#endif /* CONFIG_UTIMENSAT */
3b3f24ad
AJ
505
506#ifdef CONFIG_INOTIFY
8690e420 507#include <sys/inotify.h>
3b3f24ad 508
39b59763 509#if defined(TARGET_NR_inotify_init) && defined(__NR_inotify_init)
3b3f24ad
AJ
510static int sys_inotify_init(void)
511{
512 return (inotify_init());
513}
39b59763
AJ
514#endif
515#if defined(TARGET_NR_inotify_add_watch) && defined(__NR_inotify_add_watch)
3b3f24ad
AJ
516static int sys_inotify_add_watch(int fd,const char *pathname, int32_t mask)
517{
518 return (inotify_add_watch(fd, pathname, mask));
519}
39b59763
AJ
520#endif
521#if defined(TARGET_NR_inotify_rm_watch) && defined(__NR_inotify_rm_watch)
3b3f24ad
AJ
522static int sys_inotify_rm_watch(int fd, int32_t wd)
523{
8690e420 524 return (inotify_rm_watch(fd, wd));
3b3f24ad 525}
bd0c5661 526#endif
c05c7a73
RV
527#ifdef CONFIG_INOTIFY1
528#if defined(TARGET_NR_inotify_init1) && defined(__NR_inotify_init1)
529static int sys_inotify_init1(int flags)
530{
531 return (inotify_init1(flags));
532}
533#endif
534#endif
3b3f24ad
AJ
535#else
536/* Userspace can usually survive runtime without inotify */
537#undef TARGET_NR_inotify_init
c05c7a73 538#undef TARGET_NR_inotify_init1
3b3f24ad
AJ
539#undef TARGET_NR_inotify_add_watch
540#undef TARGET_NR_inotify_rm_watch
541#endif /* CONFIG_INOTIFY */
542
d8035d4c
MF
543#if defined(TARGET_NR_ppoll)
544#ifndef __NR_ppoll
545# define __NR_ppoll -1
546#endif
547#define __NR_sys_ppoll __NR_ppoll
548_syscall5(int, sys_ppoll, struct pollfd *, fds, nfds_t, nfds,
549 struct timespec *, timeout, const __sigset_t *, sigmask,
550 size_t, sigsetsize)
551#endif
66fb9763 552
055e0906
MF
553#if defined(TARGET_NR_pselect6)
554#ifndef __NR_pselect6
555# define __NR_pselect6 -1
556#endif
557#define __NR_sys_pselect6 __NR_pselect6
558_syscall6(int, sys_pselect6, int, nfds, fd_set *, readfds, fd_set *, writefds,
559 fd_set *, exceptfds, struct timespec *, timeout, void *, sig);
560#endif
561
66fb9763 562extern int personality(int);
9de5e440
FB
563extern int flock(int, int);
564extern int setfsuid(int);
565extern int setfsgid(int);
19b84f3c 566extern int setgroups(int, gid_t *);
31e31b8a 567
b92c47c1
TS
568#define ERRNO_TABLE_SIZE 1200
569
570/* target_to_host_errno_table[] is initialized from
571 * host_to_target_errno_table[] in syscall_init(). */
572static uint16_t target_to_host_errno_table[ERRNO_TABLE_SIZE] = {
573};
574
637947f1 575/*
fe8f096b 576 * This list is the union of errno values overridden in asm-<arch>/errno.h
637947f1
TS
577 * minus the errnos that are not actually generic to all archs.
578 */
b92c47c1 579static uint16_t host_to_target_errno_table[ERRNO_TABLE_SIZE] = {
637947f1
TS
580 [EIDRM] = TARGET_EIDRM,
581 [ECHRNG] = TARGET_ECHRNG,
582 [EL2NSYNC] = TARGET_EL2NSYNC,
583 [EL3HLT] = TARGET_EL3HLT,
584 [EL3RST] = TARGET_EL3RST,
585 [ELNRNG] = TARGET_ELNRNG,
586 [EUNATCH] = TARGET_EUNATCH,
587 [ENOCSI] = TARGET_ENOCSI,
588 [EL2HLT] = TARGET_EL2HLT,
589 [EDEADLK] = TARGET_EDEADLK,
590 [ENOLCK] = TARGET_ENOLCK,
591 [EBADE] = TARGET_EBADE,
592 [EBADR] = TARGET_EBADR,
593 [EXFULL] = TARGET_EXFULL,
594 [ENOANO] = TARGET_ENOANO,
595 [EBADRQC] = TARGET_EBADRQC,
596 [EBADSLT] = TARGET_EBADSLT,
597 [EBFONT] = TARGET_EBFONT,
598 [ENOSTR] = TARGET_ENOSTR,
599 [ENODATA] = TARGET_ENODATA,
600 [ETIME] = TARGET_ETIME,
601 [ENOSR] = TARGET_ENOSR,
602 [ENONET] = TARGET_ENONET,
603 [ENOPKG] = TARGET_ENOPKG,
604 [EREMOTE] = TARGET_EREMOTE,
605 [ENOLINK] = TARGET_ENOLINK,
606 [EADV] = TARGET_EADV,
607 [ESRMNT] = TARGET_ESRMNT,
608 [ECOMM] = TARGET_ECOMM,
609 [EPROTO] = TARGET_EPROTO,
610 [EDOTDOT] = TARGET_EDOTDOT,
611 [EMULTIHOP] = TARGET_EMULTIHOP,
612 [EBADMSG] = TARGET_EBADMSG,
613 [ENAMETOOLONG] = TARGET_ENAMETOOLONG,
614 [EOVERFLOW] = TARGET_EOVERFLOW,
615 [ENOTUNIQ] = TARGET_ENOTUNIQ,
616 [EBADFD] = TARGET_EBADFD,
617 [EREMCHG] = TARGET_EREMCHG,
618 [ELIBACC] = TARGET_ELIBACC,
619 [ELIBBAD] = TARGET_ELIBBAD,
620 [ELIBSCN] = TARGET_ELIBSCN,
621 [ELIBMAX] = TARGET_ELIBMAX,
622 [ELIBEXEC] = TARGET_ELIBEXEC,
623 [EILSEQ] = TARGET_EILSEQ,
624 [ENOSYS] = TARGET_ENOSYS,
625 [ELOOP] = TARGET_ELOOP,
626 [ERESTART] = TARGET_ERESTART,
627 [ESTRPIPE] = TARGET_ESTRPIPE,
628 [ENOTEMPTY] = TARGET_ENOTEMPTY,
629 [EUSERS] = TARGET_EUSERS,
630 [ENOTSOCK] = TARGET_ENOTSOCK,
631 [EDESTADDRREQ] = TARGET_EDESTADDRREQ,
632 [EMSGSIZE] = TARGET_EMSGSIZE,
633 [EPROTOTYPE] = TARGET_EPROTOTYPE,
634 [ENOPROTOOPT] = TARGET_ENOPROTOOPT,
635 [EPROTONOSUPPORT] = TARGET_EPROTONOSUPPORT,
636 [ESOCKTNOSUPPORT] = TARGET_ESOCKTNOSUPPORT,
637 [EOPNOTSUPP] = TARGET_EOPNOTSUPP,
638 [EPFNOSUPPORT] = TARGET_EPFNOSUPPORT,
639 [EAFNOSUPPORT] = TARGET_EAFNOSUPPORT,
640 [EADDRINUSE] = TARGET_EADDRINUSE,
641 [EADDRNOTAVAIL] = TARGET_EADDRNOTAVAIL,
642 [ENETDOWN] = TARGET_ENETDOWN,
643 [ENETUNREACH] = TARGET_ENETUNREACH,
644 [ENETRESET] = TARGET_ENETRESET,
645 [ECONNABORTED] = TARGET_ECONNABORTED,
646 [ECONNRESET] = TARGET_ECONNRESET,
647 [ENOBUFS] = TARGET_ENOBUFS,
648 [EISCONN] = TARGET_EISCONN,
649 [ENOTCONN] = TARGET_ENOTCONN,
650 [EUCLEAN] = TARGET_EUCLEAN,
651 [ENOTNAM] = TARGET_ENOTNAM,
652 [ENAVAIL] = TARGET_ENAVAIL,
653 [EISNAM] = TARGET_EISNAM,
654 [EREMOTEIO] = TARGET_EREMOTEIO,
655 [ESHUTDOWN] = TARGET_ESHUTDOWN,
656 [ETOOMANYREFS] = TARGET_ETOOMANYREFS,
657 [ETIMEDOUT] = TARGET_ETIMEDOUT,
658 [ECONNREFUSED] = TARGET_ECONNREFUSED,
659 [EHOSTDOWN] = TARGET_EHOSTDOWN,
660 [EHOSTUNREACH] = TARGET_EHOSTUNREACH,
661 [EALREADY] = TARGET_EALREADY,
662 [EINPROGRESS] = TARGET_EINPROGRESS,
663 [ESTALE] = TARGET_ESTALE,
664 [ECANCELED] = TARGET_ECANCELED,
665 [ENOMEDIUM] = TARGET_ENOMEDIUM,
666 [EMEDIUMTYPE] = TARGET_EMEDIUMTYPE,
b7fe5db7 667#ifdef ENOKEY
637947f1 668 [ENOKEY] = TARGET_ENOKEY,
b7fe5db7
TS
669#endif
670#ifdef EKEYEXPIRED
637947f1 671 [EKEYEXPIRED] = TARGET_EKEYEXPIRED,
b7fe5db7
TS
672#endif
673#ifdef EKEYREVOKED
637947f1 674 [EKEYREVOKED] = TARGET_EKEYREVOKED,
b7fe5db7
TS
675#endif
676#ifdef EKEYREJECTED
637947f1 677 [EKEYREJECTED] = TARGET_EKEYREJECTED,
b7fe5db7
TS
678#endif
679#ifdef EOWNERDEAD
637947f1 680 [EOWNERDEAD] = TARGET_EOWNERDEAD,
b7fe5db7
TS
681#endif
682#ifdef ENOTRECOVERABLE
637947f1 683 [ENOTRECOVERABLE] = TARGET_ENOTRECOVERABLE,
b7fe5db7 684#endif
b92c47c1 685};
637947f1
TS
686
687static inline int host_to_target_errno(int err)
688{
689 if(host_to_target_errno_table[err])
690 return host_to_target_errno_table[err];
691 return err;
692}
693
b92c47c1
TS
694static inline int target_to_host_errno(int err)
695{
696 if (target_to_host_errno_table[err])
697 return target_to_host_errno_table[err];
698 return err;
699}
700
992f48a0 701static inline abi_long get_errno(abi_long ret)
31e31b8a
FB
702{
703 if (ret == -1)
637947f1 704 return -host_to_target_errno(errno);
31e31b8a
FB
705 else
706 return ret;
707}
708
992f48a0 709static inline int is_error(abi_long ret)
31e31b8a 710{
992f48a0 711 return (abi_ulong)ret >= (abi_ulong)(-4096);
31e31b8a
FB
712}
713
b92c47c1
TS
714char *target_strerror(int err)
715{
716 return strerror(target_to_host_errno(err));
717}
718
992f48a0
BS
719static abi_ulong target_brk;
720static abi_ulong target_original_brk;
4d1de87c 721static abi_ulong brk_page;
31e31b8a 722
992f48a0 723void target_set_brk(abi_ulong new_brk)
31e31b8a 724{
4c1de73d 725 target_original_brk = target_brk = HOST_PAGE_ALIGN(new_brk);
4d1de87c 726 brk_page = HOST_PAGE_ALIGN(target_brk);
31e31b8a
FB
727}
728
4d1de87c
CV
729//#define DEBUGF_BRK(message, args...) do { fprintf(stderr, (message), ## args); } while (0)
730#define DEBUGF_BRK(message, args...)
731
0da46a6e 732/* do_brk() must return target values and target errnos. */
992f48a0 733abi_long do_brk(abi_ulong new_brk)
31e31b8a 734{
992f48a0 735 abi_long mapped_addr;
31e31b8a
FB
736 int new_alloc_size;
737
4d1de87c
CV
738 DEBUGF_BRK("do_brk(%#010x) -> ", new_brk);
739
740 if (!new_brk) {
741 DEBUGF_BRK("%#010x (!new_brk)\n", target_brk);
53a5960a 742 return target_brk;
4d1de87c
CV
743 }
744 if (new_brk < target_original_brk) {
745 DEBUGF_BRK("%#010x (new_brk < target_original_brk)\n", target_brk);
7ab240ad 746 return target_brk;
4d1de87c 747 }
3b46e624 748
4d1de87c
CV
749 /* If the new brk is less than the highest page reserved to the
750 * target heap allocation, set it and we're almost done... */
751 if (new_brk <= brk_page) {
752 /* Heap contents are initialized to zero, as for anonymous
753 * mapped pages. */
754 if (new_brk > target_brk) {
755 memset(g2h(target_brk), 0, new_brk - target_brk);
756 }
31e31b8a 757 target_brk = new_brk;
4d1de87c 758 DEBUGF_BRK("%#010x (new_brk <= brk_page)\n", target_brk);
53a5960a 759 return target_brk;
31e31b8a
FB
760 }
761
00faf08c
PM
762 /* We need to allocate more memory after the brk... Note that
763 * we don't use MAP_FIXED because that will map over the top of
764 * any existing mapping (like the one with the host libc or qemu
765 * itself); instead we treat "mapped but at wrong address" as
766 * a failure and unmap again.
767 */
4d1de87c 768 new_alloc_size = HOST_PAGE_ALIGN(new_brk - brk_page);
5fafdf24 769 mapped_addr = get_errno(target_mmap(brk_page, new_alloc_size,
54936004 770 PROT_READ|PROT_WRITE,
00faf08c
PM
771 MAP_ANON|MAP_PRIVATE, 0, 0));
772
773 if (mapped_addr == brk_page) {
774 target_brk = new_brk;
4d1de87c
CV
775 brk_page = HOST_PAGE_ALIGN(target_brk);
776 DEBUGF_BRK("%#010x (mapped_addr == brk_page)\n", target_brk);
00faf08c
PM
777 return target_brk;
778 } else if (mapped_addr != -1) {
779 /* Mapped but at wrong address, meaning there wasn't actually
780 * enough space for this brk.
781 */
782 target_munmap(mapped_addr, new_alloc_size);
783 mapped_addr = -1;
4d1de87c
CV
784 DEBUGF_BRK("%#010x (mapped_addr != -1)\n", target_brk);
785 }
786 else {
787 DEBUGF_BRK("%#010x (otherwise)\n", target_brk);
00faf08c 788 }
7ab240ad 789
7dd46c02
RH
790#if defined(TARGET_ALPHA)
791 /* We (partially) emulate OSF/1 on Alpha, which requires we
792 return a proper errno, not an unchanged brk value. */
00faf08c 793 return -TARGET_ENOMEM;
7dd46c02 794#endif
00faf08c 795 /* For everything else, return the previous break. */
7ab240ad 796 return target_brk;
31e31b8a
FB
797}
798
26edcf41
TS
799static inline abi_long copy_from_user_fdset(fd_set *fds,
800 abi_ulong target_fds_addr,
801 int n)
31e31b8a 802{
26edcf41
TS
803 int i, nw, j, k;
804 abi_ulong b, *target_fds;
805
806 nw = (n + TARGET_ABI_BITS - 1) / TARGET_ABI_BITS;
807 if (!(target_fds = lock_user(VERIFY_READ,
808 target_fds_addr,
809 sizeof(abi_ulong) * nw,
810 1)))
811 return -TARGET_EFAULT;
812
813 FD_ZERO(fds);
814 k = 0;
815 for (i = 0; i < nw; i++) {
816 /* grab the abi_ulong */
817 __get_user(b, &target_fds[i]);
818 for (j = 0; j < TARGET_ABI_BITS; j++) {
819 /* check the bit inside the abi_ulong */
820 if ((b >> j) & 1)
821 FD_SET(k, fds);
822 k++;
31e31b8a 823 }
31e31b8a 824 }
26edcf41
TS
825
826 unlock_user(target_fds, target_fds_addr, 0);
827
828 return 0;
31e31b8a
FB
829}
830
055e0906
MF
831static inline abi_ulong copy_from_user_fdset_ptr(fd_set *fds, fd_set **fds_ptr,
832 abi_ulong target_fds_addr,
833 int n)
834{
835 if (target_fds_addr) {
836 if (copy_from_user_fdset(fds, target_fds_addr, n))
837 return -TARGET_EFAULT;
838 *fds_ptr = fds;
839 } else {
840 *fds_ptr = NULL;
841 }
842 return 0;
843}
844
26edcf41
TS
845static inline abi_long copy_to_user_fdset(abi_ulong target_fds_addr,
846 const fd_set *fds,
847 int n)
31e31b8a 848{
31e31b8a 849 int i, nw, j, k;
992f48a0 850 abi_long v;
26edcf41 851 abi_ulong *target_fds;
31e31b8a 852
26edcf41
TS
853 nw = (n + TARGET_ABI_BITS - 1) / TARGET_ABI_BITS;
854 if (!(target_fds = lock_user(VERIFY_WRITE,
855 target_fds_addr,
856 sizeof(abi_ulong) * nw,
857 0)))
858 return -TARGET_EFAULT;
859
860 k = 0;
861 for (i = 0; i < nw; i++) {
862 v = 0;
863 for (j = 0; j < TARGET_ABI_BITS; j++) {
864 v |= ((FD_ISSET(k, fds) != 0) << j);
865 k++;
31e31b8a 866 }
26edcf41 867 __put_user(v, &target_fds[i]);
31e31b8a 868 }
26edcf41
TS
869
870 unlock_user(target_fds, target_fds_addr, sizeof(abi_ulong) * nw);
871
872 return 0;
31e31b8a
FB
873}
874
c596ed17
FB
875#if defined(__alpha__)
876#define HOST_HZ 1024
877#else
878#define HOST_HZ 100
879#endif
880
992f48a0 881static inline abi_long host_to_target_clock_t(long ticks)
c596ed17
FB
882{
883#if HOST_HZ == TARGET_HZ
884 return ticks;
885#else
886 return ((int64_t)ticks * TARGET_HZ) / HOST_HZ;
887#endif
888}
889
579a97f7
FB
890static inline abi_long host_to_target_rusage(abi_ulong target_addr,
891 const struct rusage *rusage)
b409186b 892{
53a5960a
PB
893 struct target_rusage *target_rusage;
894
579a97f7
FB
895 if (!lock_user_struct(VERIFY_WRITE, target_rusage, target_addr, 0))
896 return -TARGET_EFAULT;
b409186b
FB
897 target_rusage->ru_utime.tv_sec = tswapl(rusage->ru_utime.tv_sec);
898 target_rusage->ru_utime.tv_usec = tswapl(rusage->ru_utime.tv_usec);
899 target_rusage->ru_stime.tv_sec = tswapl(rusage->ru_stime.tv_sec);
900 target_rusage->ru_stime.tv_usec = tswapl(rusage->ru_stime.tv_usec);
901 target_rusage->ru_maxrss = tswapl(rusage->ru_maxrss);
902 target_rusage->ru_ixrss = tswapl(rusage->ru_ixrss);
903 target_rusage->ru_idrss = tswapl(rusage->ru_idrss);
904 target_rusage->ru_isrss = tswapl(rusage->ru_isrss);
905 target_rusage->ru_minflt = tswapl(rusage->ru_minflt);
906 target_rusage->ru_majflt = tswapl(rusage->ru_majflt);
907 target_rusage->ru_nswap = tswapl(rusage->ru_nswap);
908 target_rusage->ru_inblock = tswapl(rusage->ru_inblock);
909 target_rusage->ru_oublock = tswapl(rusage->ru_oublock);
910 target_rusage->ru_msgsnd = tswapl(rusage->ru_msgsnd);
911 target_rusage->ru_msgrcv = tswapl(rusage->ru_msgrcv);
912 target_rusage->ru_nsignals = tswapl(rusage->ru_nsignals);
913 target_rusage->ru_nvcsw = tswapl(rusage->ru_nvcsw);
914 target_rusage->ru_nivcsw = tswapl(rusage->ru_nivcsw);
53a5960a 915 unlock_user_struct(target_rusage, target_addr, 1);
579a97f7
FB
916
917 return 0;
b409186b
FB
918}
919
81bbe906
TY
920static inline rlim_t target_to_host_rlim(target_ulong target_rlim)
921{
922 if (target_rlim == TARGET_RLIM_INFINITY)
923 return RLIM_INFINITY;
924 else
925 return tswapl(target_rlim);
926}
927
928static inline target_ulong host_to_target_rlim(rlim_t rlim)
929{
930 if (rlim == RLIM_INFINITY || rlim != (target_long)rlim)
931 return TARGET_RLIM_INFINITY;
932 else
933 return tswapl(rlim);
934}
935
788f5ec4
TS
936static inline abi_long copy_from_user_timeval(struct timeval *tv,
937 abi_ulong target_tv_addr)
31e31b8a 938{
53a5960a
PB
939 struct target_timeval *target_tv;
940
788f5ec4 941 if (!lock_user_struct(VERIFY_READ, target_tv, target_tv_addr, 1))
579a97f7 942 return -TARGET_EFAULT;
788f5ec4
TS
943
944 __get_user(tv->tv_sec, &target_tv->tv_sec);
945 __get_user(tv->tv_usec, &target_tv->tv_usec);
946
947 unlock_user_struct(target_tv, target_tv_addr, 0);
579a97f7
FB
948
949 return 0;
31e31b8a
FB
950}
951
788f5ec4
TS
952static inline abi_long copy_to_user_timeval(abi_ulong target_tv_addr,
953 const struct timeval *tv)
31e31b8a 954{
53a5960a
PB
955 struct target_timeval *target_tv;
956
788f5ec4 957 if (!lock_user_struct(VERIFY_WRITE, target_tv, target_tv_addr, 0))
579a97f7 958 return -TARGET_EFAULT;
788f5ec4
TS
959
960 __put_user(tv->tv_sec, &target_tv->tv_sec);
961 __put_user(tv->tv_usec, &target_tv->tv_usec);
962
963 unlock_user_struct(target_tv, target_tv_addr, 1);
579a97f7
FB
964
965 return 0;
31e31b8a
FB
966}
967
8ec9cf89
NF
968#if defined(TARGET_NR_mq_open) && defined(__NR_mq_open)
969#include <mqueue.h>
970
24e1003a
AJ
971static inline abi_long copy_from_user_mq_attr(struct mq_attr *attr,
972 abi_ulong target_mq_attr_addr)
973{
974 struct target_mq_attr *target_mq_attr;
975
976 if (!lock_user_struct(VERIFY_READ, target_mq_attr,
977 target_mq_attr_addr, 1))
978 return -TARGET_EFAULT;
979
980 __get_user(attr->mq_flags, &target_mq_attr->mq_flags);
981 __get_user(attr->mq_maxmsg, &target_mq_attr->mq_maxmsg);
982 __get_user(attr->mq_msgsize, &target_mq_attr->mq_msgsize);
983 __get_user(attr->mq_curmsgs, &target_mq_attr->mq_curmsgs);
984
985 unlock_user_struct(target_mq_attr, target_mq_attr_addr, 0);
986
987 return 0;
988}
989
990static inline abi_long copy_to_user_mq_attr(abi_ulong target_mq_attr_addr,
991 const struct mq_attr *attr)
992{
993 struct target_mq_attr *target_mq_attr;
994
995 if (!lock_user_struct(VERIFY_WRITE, target_mq_attr,
996 target_mq_attr_addr, 0))
997 return -TARGET_EFAULT;
998
999 __put_user(attr->mq_flags, &target_mq_attr->mq_flags);
1000 __put_user(attr->mq_maxmsg, &target_mq_attr->mq_maxmsg);
1001 __put_user(attr->mq_msgsize, &target_mq_attr->mq_msgsize);
1002 __put_user(attr->mq_curmsgs, &target_mq_attr->mq_curmsgs);
1003
1004 unlock_user_struct(target_mq_attr, target_mq_attr_addr, 1);
1005
1006 return 0;
1007}
8ec9cf89 1008#endif
31e31b8a 1009
055e0906 1010#if defined(TARGET_NR_select) || defined(TARGET_NR__newselect)
0da46a6e 1011/* do_select() must return target values and target errnos. */
992f48a0 1012static abi_long do_select(int n,
26edcf41
TS
1013 abi_ulong rfd_addr, abi_ulong wfd_addr,
1014 abi_ulong efd_addr, abi_ulong target_tv_addr)
31e31b8a
FB
1015{
1016 fd_set rfds, wfds, efds;
1017 fd_set *rfds_ptr, *wfds_ptr, *efds_ptr;
1018 struct timeval tv, *tv_ptr;
992f48a0 1019 abi_long ret;
31e31b8a 1020
055e0906
MF
1021 ret = copy_from_user_fdset_ptr(&rfds, &rfds_ptr, rfd_addr, n);
1022 if (ret) {
1023 return ret;
53a5960a 1024 }
055e0906
MF
1025 ret = copy_from_user_fdset_ptr(&wfds, &wfds_ptr, wfd_addr, n);
1026 if (ret) {
1027 return ret;
53a5960a 1028 }
055e0906
MF
1029 ret = copy_from_user_fdset_ptr(&efds, &efds_ptr, efd_addr, n);
1030 if (ret) {
1031 return ret;
53a5960a 1032 }
3b46e624 1033
26edcf41 1034 if (target_tv_addr) {
788f5ec4
TS
1035 if (copy_from_user_timeval(&tv, target_tv_addr))
1036 return -TARGET_EFAULT;
31e31b8a
FB
1037 tv_ptr = &tv;
1038 } else {
1039 tv_ptr = NULL;
1040 }
26edcf41 1041
31e31b8a 1042 ret = get_errno(select(n, rfds_ptr, wfds_ptr, efds_ptr, tv_ptr));
53a5960a 1043
26edcf41
TS
1044 if (!is_error(ret)) {
1045 if (rfd_addr && copy_to_user_fdset(rfd_addr, &rfds, n))
1046 return -TARGET_EFAULT;
1047 if (wfd_addr && copy_to_user_fdset(wfd_addr, &wfds, n))
1048 return -TARGET_EFAULT;
1049 if (efd_addr && copy_to_user_fdset(efd_addr, &efds, n))
1050 return -TARGET_EFAULT;
31e31b8a 1051
788f5ec4
TS
1052 if (target_tv_addr && copy_to_user_timeval(target_tv_addr, &tv))
1053 return -TARGET_EFAULT;
31e31b8a 1054 }
579a97f7 1055
31e31b8a
FB
1056 return ret;
1057}
055e0906 1058#endif
31e31b8a 1059
099d6b0f
RV
1060static abi_long do_pipe2(int host_pipe[], int flags)
1061{
1062#ifdef CONFIG_PIPE2
1063 return pipe2(host_pipe, flags);
1064#else
1065 return -ENOSYS;
1066#endif
1067}
1068
fb41a66e
RH
1069static abi_long do_pipe(void *cpu_env, abi_ulong pipedes,
1070 int flags, int is_pipe2)
099d6b0f
RV
1071{
1072 int host_pipe[2];
1073 abi_long ret;
1074 ret = flags ? do_pipe2(host_pipe, flags) : pipe(host_pipe);
1075
1076 if (is_error(ret))
1077 return get_errno(ret);
fb41a66e
RH
1078
1079 /* Several targets have special calling conventions for the original
1080 pipe syscall, but didn't replicate this into the pipe2 syscall. */
1081 if (!is_pipe2) {
1082#if defined(TARGET_ALPHA)
1083 ((CPUAlphaState *)cpu_env)->ir[IR_A4] = host_pipe[1];
1084 return host_pipe[0];
1085#elif defined(TARGET_MIPS)
1086 ((CPUMIPSState*)cpu_env)->active_tc.gpr[3] = host_pipe[1];
1087 return host_pipe[0];
1088#elif defined(TARGET_SH4)
597c0212 1089 ((CPUSH4State*)cpu_env)->gregs[1] = host_pipe[1];
fb41a66e 1090 return host_pipe[0];
597c0212 1091#endif
fb41a66e
RH
1092 }
1093
099d6b0f
RV
1094 if (put_user_s32(host_pipe[0], pipedes)
1095 || put_user_s32(host_pipe[1], pipedes + sizeof(host_pipe[0])))
1096 return -TARGET_EFAULT;
099d6b0f
RV
1097 return get_errno(ret);
1098}
1099
b975b83b
LL
1100static inline abi_long target_to_host_ip_mreq(struct ip_mreqn *mreqn,
1101 abi_ulong target_addr,
1102 socklen_t len)
1103{
1104 struct target_ip_mreqn *target_smreqn;
1105
1106 target_smreqn = lock_user(VERIFY_READ, target_addr, len, 1);
1107 if (!target_smreqn)
1108 return -TARGET_EFAULT;
1109 mreqn->imr_multiaddr.s_addr = target_smreqn->imr_multiaddr.s_addr;
1110 mreqn->imr_address.s_addr = target_smreqn->imr_address.s_addr;
1111 if (len == sizeof(struct target_ip_mreqn))
1112 mreqn->imr_ifindex = tswapl(target_smreqn->imr_ifindex);
1113 unlock_user(target_smreqn, target_addr, 0);
1114
1115 return 0;
1116}
1117
579a97f7
FB
1118static inline abi_long target_to_host_sockaddr(struct sockaddr *addr,
1119 abi_ulong target_addr,
1120 socklen_t len)
7854b056 1121{
607175e0
AJ
1122 const socklen_t unix_maxlen = sizeof (struct sockaddr_un);
1123 sa_family_t sa_family;
53a5960a
PB
1124 struct target_sockaddr *target_saddr;
1125
579a97f7
FB
1126 target_saddr = lock_user(VERIFY_READ, target_addr, len, 1);
1127 if (!target_saddr)
1128 return -TARGET_EFAULT;
607175e0
AJ
1129
1130 sa_family = tswap16(target_saddr->sa_family);
1131
1132 /* Oops. The caller might send a incomplete sun_path; sun_path
1133 * must be terminated by \0 (see the manual page), but
1134 * unfortunately it is quite common to specify sockaddr_un
1135 * length as "strlen(x->sun_path)" while it should be
1136 * "strlen(...) + 1". We'll fix that here if needed.
1137 * Linux kernel has a similar feature.
1138 */
1139
1140 if (sa_family == AF_UNIX) {
1141 if (len < unix_maxlen && len > 0) {
1142 char *cp = (char*)target_saddr;
1143
1144 if ( cp[len-1] && !cp[len] )
1145 len++;
1146 }
1147 if (len > unix_maxlen)
1148 len = unix_maxlen;
1149 }
1150
53a5960a 1151 memcpy(addr, target_saddr, len);
607175e0 1152 addr->sa_family = sa_family;
53a5960a 1153 unlock_user(target_saddr, target_addr, 0);
579a97f7
FB
1154
1155 return 0;
7854b056
FB
1156}
1157
579a97f7
FB
1158static inline abi_long host_to_target_sockaddr(abi_ulong target_addr,
1159 struct sockaddr *addr,
1160 socklen_t len)
7854b056 1161{
53a5960a
PB
1162 struct target_sockaddr *target_saddr;
1163
579a97f7
FB
1164 target_saddr = lock_user(VERIFY_WRITE, target_addr, len, 0);
1165 if (!target_saddr)
1166 return -TARGET_EFAULT;
53a5960a
PB
1167 memcpy(target_saddr, addr, len);
1168 target_saddr->sa_family = tswap16(addr->sa_family);
1169 unlock_user(target_saddr, target_addr, len);
579a97f7
FB
1170
1171 return 0;
7854b056
FB
1172}
1173
53a5960a 1174/* ??? Should this also swap msgh->name? */
5a4a898d
FB
1175static inline abi_long target_to_host_cmsg(struct msghdr *msgh,
1176 struct target_msghdr *target_msgh)
7854b056
FB
1177{
1178 struct cmsghdr *cmsg = CMSG_FIRSTHDR(msgh);
5a4a898d
FB
1179 abi_long msg_controllen;
1180 abi_ulong target_cmsg_addr;
1181 struct target_cmsghdr *target_cmsg;
7854b056 1182 socklen_t space = 0;
5a4a898d
FB
1183
1184 msg_controllen = tswapl(target_msgh->msg_controllen);
1185 if (msg_controllen < sizeof (struct target_cmsghdr))
1186 goto the_end;
1187 target_cmsg_addr = tswapl(target_msgh->msg_control);
1188 target_cmsg = lock_user(VERIFY_READ, target_cmsg_addr, msg_controllen, 1);
1189 if (!target_cmsg)
1190 return -TARGET_EFAULT;
7854b056
FB
1191
1192 while (cmsg && target_cmsg) {
1193 void *data = CMSG_DATA(cmsg);
1194 void *target_data = TARGET_CMSG_DATA(target_cmsg);
1195
5fafdf24 1196 int len = tswapl(target_cmsg->cmsg_len)
7854b056
FB
1197 - TARGET_CMSG_ALIGN(sizeof (struct target_cmsghdr));
1198
1199 space += CMSG_SPACE(len);
1200 if (space > msgh->msg_controllen) {
1201 space -= CMSG_SPACE(len);
31febb71 1202 gemu_log("Host cmsg overflow\n");
7854b056
FB
1203 break;
1204 }
1205
1206 cmsg->cmsg_level = tswap32(target_cmsg->cmsg_level);
1207 cmsg->cmsg_type = tswap32(target_cmsg->cmsg_type);
1208 cmsg->cmsg_len = CMSG_LEN(len);
1209
3532fa74 1210 if (cmsg->cmsg_level != TARGET_SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS) {
7854b056
FB
1211 gemu_log("Unsupported ancillary data: %d/%d\n", cmsg->cmsg_level, cmsg->cmsg_type);
1212 memcpy(data, target_data, len);
1213 } else {
1214 int *fd = (int *)data;
1215 int *target_fd = (int *)target_data;
1216 int i, numfds = len / sizeof(int);
1217
1218 for (i = 0; i < numfds; i++)
1219 fd[i] = tswap32(target_fd[i]);
1220 }
1221
1222 cmsg = CMSG_NXTHDR(msgh, cmsg);
1223 target_cmsg = TARGET_CMSG_NXTHDR(target_msgh, target_cmsg);
1224 }
5a4a898d
FB
1225 unlock_user(target_cmsg, target_cmsg_addr, 0);
1226 the_end:
7854b056 1227 msgh->msg_controllen = space;
5a4a898d 1228 return 0;
7854b056
FB
1229}
1230
53a5960a 1231/* ??? Should this also swap msgh->name? */
5a4a898d
FB
1232static inline abi_long host_to_target_cmsg(struct target_msghdr *target_msgh,
1233 struct msghdr *msgh)
7854b056
FB
1234{
1235 struct cmsghdr *cmsg = CMSG_FIRSTHDR(msgh);
5a4a898d
FB
1236 abi_long msg_controllen;
1237 abi_ulong target_cmsg_addr;
1238 struct target_cmsghdr *target_cmsg;
7854b056
FB
1239 socklen_t space = 0;
1240
5a4a898d
FB
1241 msg_controllen = tswapl(target_msgh->msg_controllen);
1242 if (msg_controllen < sizeof (struct target_cmsghdr))
1243 goto the_end;
1244 target_cmsg_addr = tswapl(target_msgh->msg_control);
1245 target_cmsg = lock_user(VERIFY_WRITE, target_cmsg_addr, msg_controllen, 0);
1246 if (!target_cmsg)
1247 return -TARGET_EFAULT;
1248
7854b056
FB
1249 while (cmsg && target_cmsg) {
1250 void *data = CMSG_DATA(cmsg);
1251 void *target_data = TARGET_CMSG_DATA(target_cmsg);
1252
1253 int len = cmsg->cmsg_len - CMSG_ALIGN(sizeof (struct cmsghdr));
1254
1255 space += TARGET_CMSG_SPACE(len);
5a4a898d 1256 if (space > msg_controllen) {
7854b056 1257 space -= TARGET_CMSG_SPACE(len);
31febb71 1258 gemu_log("Target cmsg overflow\n");
7854b056
FB
1259 break;
1260 }
1261
1262 target_cmsg->cmsg_level = tswap32(cmsg->cmsg_level);
1263 target_cmsg->cmsg_type = tswap32(cmsg->cmsg_type);
1264 target_cmsg->cmsg_len = tswapl(TARGET_CMSG_LEN(len));
1265
3532fa74 1266 if (cmsg->cmsg_level != TARGET_SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS) {
7854b056
FB
1267 gemu_log("Unsupported ancillary data: %d/%d\n", cmsg->cmsg_level, cmsg->cmsg_type);
1268 memcpy(target_data, data, len);
1269 } else {
1270 int *fd = (int *)data;
1271 int *target_fd = (int *)target_data;
1272 int i, numfds = len / sizeof(int);
1273
1274 for (i = 0; i < numfds; i++)
1275 target_fd[i] = tswap32(fd[i]);
1276 }
1277
1278 cmsg = CMSG_NXTHDR(msgh, cmsg);
1279 target_cmsg = TARGET_CMSG_NXTHDR(target_msgh, target_cmsg);
1280 }
5a4a898d
FB
1281 unlock_user(target_cmsg, target_cmsg_addr, space);
1282 the_end:
1283 target_msgh->msg_controllen = tswapl(space);
1284 return 0;
7854b056
FB
1285}
1286
0da46a6e 1287/* do_setsockopt() Must return target values and target errnos. */
992f48a0 1288static abi_long do_setsockopt(int sockfd, int level, int optname,
2f619698 1289 abi_ulong optval_addr, socklen_t optlen)
7854b056 1290{
992f48a0 1291 abi_long ret;
32407103 1292 int val;
b975b83b 1293 struct ip_mreqn *ip_mreq;
6e3cb58f 1294 struct ip_mreq_source *ip_mreq_source;
3b46e624 1295
8853f86e
FB
1296 switch(level) {
1297 case SOL_TCP:
7854b056 1298 /* TCP options all take an 'int' value. */
7854b056 1299 if (optlen < sizeof(uint32_t))
0da46a6e 1300 return -TARGET_EINVAL;
3b46e624 1301
2f619698
FB
1302 if (get_user_u32(val, optval_addr))
1303 return -TARGET_EFAULT;
8853f86e
FB
1304 ret = get_errno(setsockopt(sockfd, level, optname, &val, sizeof(val)));
1305 break;
1306 case SOL_IP:
1307 switch(optname) {
2efbe911
FB
1308 case IP_TOS:
1309 case IP_TTL:
8853f86e 1310 case IP_HDRINCL:
2efbe911
FB
1311 case IP_ROUTER_ALERT:
1312 case IP_RECVOPTS:
1313 case IP_RETOPTS:
1314 case IP_PKTINFO:
1315 case IP_MTU_DISCOVER:
1316 case IP_RECVERR:
1317 case IP_RECVTOS:
1318#ifdef IP_FREEBIND
1319 case IP_FREEBIND:
1320#endif
1321 case IP_MULTICAST_TTL:
1322 case IP_MULTICAST_LOOP:
8853f86e
FB
1323 val = 0;
1324 if (optlen >= sizeof(uint32_t)) {
2f619698
FB
1325 if (get_user_u32(val, optval_addr))
1326 return -TARGET_EFAULT;
8853f86e 1327 } else if (optlen >= 1) {
2f619698
FB
1328 if (get_user_u8(val, optval_addr))
1329 return -TARGET_EFAULT;
8853f86e
FB
1330 }
1331 ret = get_errno(setsockopt(sockfd, level, optname, &val, sizeof(val)));
1332 break;
b975b83b
LL
1333 case IP_ADD_MEMBERSHIP:
1334 case IP_DROP_MEMBERSHIP:
1335 if (optlen < sizeof (struct target_ip_mreq) ||
1336 optlen > sizeof (struct target_ip_mreqn))
1337 return -TARGET_EINVAL;
1338
1339 ip_mreq = (struct ip_mreqn *) alloca(optlen);
1340 target_to_host_ip_mreq(ip_mreq, optval_addr, optlen);
1341 ret = get_errno(setsockopt(sockfd, level, optname, ip_mreq, optlen));
1342 break;
1343
6e3cb58f
LL
1344 case IP_BLOCK_SOURCE:
1345 case IP_UNBLOCK_SOURCE:
1346 case IP_ADD_SOURCE_MEMBERSHIP:
1347 case IP_DROP_SOURCE_MEMBERSHIP:
1348 if (optlen != sizeof (struct target_ip_mreq_source))
1349 return -TARGET_EINVAL;
1350
1351 ip_mreq_source = lock_user(VERIFY_READ, optval_addr, optlen, 1);
1352 ret = get_errno(setsockopt(sockfd, level, optname, ip_mreq_source, optlen));
1353 unlock_user (ip_mreq_source, optval_addr, 0);
1354 break;
1355
8853f86e
FB
1356 default:
1357 goto unimplemented;
1358 }
1359 break;
3532fa74 1360 case TARGET_SOL_SOCKET:
8853f86e
FB
1361 switch (optname) {
1362 /* Options with 'int' argument. */
3532fa74
FB
1363 case TARGET_SO_DEBUG:
1364 optname = SO_DEBUG;
1365 break;
1366 case TARGET_SO_REUSEADDR:
1367 optname = SO_REUSEADDR;
1368 break;
1369 case TARGET_SO_TYPE:
1370 optname = SO_TYPE;
1371 break;
1372 case TARGET_SO_ERROR:
1373 optname = SO_ERROR;
1374 break;
1375 case TARGET_SO_DONTROUTE:
1376 optname = SO_DONTROUTE;
1377 break;
1378 case TARGET_SO_BROADCAST:
1379 optname = SO_BROADCAST;
1380 break;
1381 case TARGET_SO_SNDBUF:
1382 optname = SO_SNDBUF;
1383 break;
1384 case TARGET_SO_RCVBUF:
1385 optname = SO_RCVBUF;
1386 break;
1387 case TARGET_SO_KEEPALIVE:
1388 optname = SO_KEEPALIVE;
1389 break;
1390 case TARGET_SO_OOBINLINE:
1391 optname = SO_OOBINLINE;
1392 break;
1393 case TARGET_SO_NO_CHECK:
1394 optname = SO_NO_CHECK;
1395 break;
1396 case TARGET_SO_PRIORITY:
1397 optname = SO_PRIORITY;
1398 break;
5e83e8e3 1399#ifdef SO_BSDCOMPAT
3532fa74
FB
1400 case TARGET_SO_BSDCOMPAT:
1401 optname = SO_BSDCOMPAT;
1402 break;
5e83e8e3 1403#endif
3532fa74
FB
1404 case TARGET_SO_PASSCRED:
1405 optname = SO_PASSCRED;
1406 break;
1407 case TARGET_SO_TIMESTAMP:
1408 optname = SO_TIMESTAMP;
1409 break;
1410 case TARGET_SO_RCVLOWAT:
1411 optname = SO_RCVLOWAT;
1412 break;
1413 case TARGET_SO_RCVTIMEO:
1414 optname = SO_RCVTIMEO;
1415 break;
1416 case TARGET_SO_SNDTIMEO:
1417 optname = SO_SNDTIMEO;
1418 break;
8853f86e
FB
1419 break;
1420 default:
1421 goto unimplemented;
1422 }
3532fa74 1423 if (optlen < sizeof(uint32_t))
2f619698 1424 return -TARGET_EINVAL;
3532fa74 1425
2f619698
FB
1426 if (get_user_u32(val, optval_addr))
1427 return -TARGET_EFAULT;
3532fa74 1428 ret = get_errno(setsockopt(sockfd, SOL_SOCKET, optname, &val, sizeof(val)));
8853f86e 1429 break;
7854b056 1430 default:
8853f86e
FB
1431 unimplemented:
1432 gemu_log("Unsupported setsockopt level=%d optname=%d \n", level, optname);
6fa13c17 1433 ret = -TARGET_ENOPROTOOPT;
7854b056 1434 }
8853f86e 1435 return ret;
7854b056
FB
1436}
1437
0da46a6e 1438/* do_getsockopt() Must return target values and target errnos. */
992f48a0 1439static abi_long do_getsockopt(int sockfd, int level, int optname,
2f619698 1440 abi_ulong optval_addr, abi_ulong optlen)
7854b056 1441{
992f48a0 1442 abi_long ret;
b55266b5
BS
1443 int len, val;
1444 socklen_t lv;
8853f86e
FB
1445
1446 switch(level) {
3532fa74 1447 case TARGET_SOL_SOCKET:
f3b974cd
JL
1448 level = SOL_SOCKET;
1449 switch (optname) {
1450 /* These don't just return a single integer */
1451 case TARGET_SO_LINGER:
1452 case TARGET_SO_RCVTIMEO:
1453 case TARGET_SO_SNDTIMEO:
1454 case TARGET_SO_PEERCRED:
1455 case TARGET_SO_PEERNAME:
1456 goto unimplemented;
1457 /* Options with 'int' argument. */
1458 case TARGET_SO_DEBUG:
1459 optname = SO_DEBUG;
1460 goto int_case;
1461 case TARGET_SO_REUSEADDR:
1462 optname = SO_REUSEADDR;
1463 goto int_case;
1464 case TARGET_SO_TYPE:
1465 optname = SO_TYPE;
1466 goto int_case;
1467 case TARGET_SO_ERROR:
1468 optname = SO_ERROR;
1469 goto int_case;
1470 case TARGET_SO_DONTROUTE:
1471 optname = SO_DONTROUTE;
1472 goto int_case;
1473 case TARGET_SO_BROADCAST:
1474 optname = SO_BROADCAST;
1475 goto int_case;
1476 case TARGET_SO_SNDBUF:
1477 optname = SO_SNDBUF;
1478 goto int_case;
1479 case TARGET_SO_RCVBUF:
1480 optname = SO_RCVBUF;
1481 goto int_case;
1482 case TARGET_SO_KEEPALIVE:
1483 optname = SO_KEEPALIVE;
1484 goto int_case;
1485 case TARGET_SO_OOBINLINE:
1486 optname = SO_OOBINLINE;
1487 goto int_case;
1488 case TARGET_SO_NO_CHECK:
1489 optname = SO_NO_CHECK;
1490 goto int_case;
1491 case TARGET_SO_PRIORITY:
1492 optname = SO_PRIORITY;
1493 goto int_case;
1494#ifdef SO_BSDCOMPAT
1495 case TARGET_SO_BSDCOMPAT:
1496 optname = SO_BSDCOMPAT;
1497 goto int_case;
1498#endif
1499 case TARGET_SO_PASSCRED:
1500 optname = SO_PASSCRED;
1501 goto int_case;
1502 case TARGET_SO_TIMESTAMP:
1503 optname = SO_TIMESTAMP;
1504 goto int_case;
1505 case TARGET_SO_RCVLOWAT:
1506 optname = SO_RCVLOWAT;
1507 goto int_case;
8853f86e 1508 default:
2efbe911
FB
1509 goto int_case;
1510 }
1511 break;
1512 case SOL_TCP:
1513 /* TCP options all take an 'int' value. */
1514 int_case:
2f619698
FB
1515 if (get_user_u32(len, optlen))
1516 return -TARGET_EFAULT;
2efbe911 1517 if (len < 0)
0da46a6e 1518 return -TARGET_EINVAL;
73160d95 1519 lv = sizeof(lv);
2efbe911
FB
1520 ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
1521 if (ret < 0)
1522 return ret;
2efbe911
FB
1523 if (len > lv)
1524 len = lv;
2f619698
FB
1525 if (len == 4) {
1526 if (put_user_u32(val, optval_addr))
1527 return -TARGET_EFAULT;
1528 } else {
1529 if (put_user_u8(val, optval_addr))
1530 return -TARGET_EFAULT;
f3b974cd 1531 }
2f619698
FB
1532 if (put_user_u32(len, optlen))
1533 return -TARGET_EFAULT;
2efbe911
FB
1534 break;
1535 case SOL_IP:
1536 switch(optname) {
1537 case IP_TOS:
1538 case IP_TTL:
1539 case IP_HDRINCL:
1540 case IP_ROUTER_ALERT:
1541 case IP_RECVOPTS:
1542 case IP_RETOPTS:
1543 case IP_PKTINFO:
1544 case IP_MTU_DISCOVER:
1545 case IP_RECVERR:
1546 case IP_RECVTOS:
1547#ifdef IP_FREEBIND
1548 case IP_FREEBIND:
1549#endif
1550 case IP_MULTICAST_TTL:
1551 case IP_MULTICAST_LOOP:
2f619698
FB
1552 if (get_user_u32(len, optlen))
1553 return -TARGET_EFAULT;
8853f86e 1554 if (len < 0)
0da46a6e 1555 return -TARGET_EINVAL;
73160d95 1556 lv = sizeof(lv);
8853f86e
FB
1557 ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
1558 if (ret < 0)
1559 return ret;
2efbe911 1560 if (len < sizeof(int) && len > 0 && val >= 0 && val < 255) {
2efbe911 1561 len = 1;
2f619698
FB
1562 if (put_user_u32(len, optlen)
1563 || put_user_u8(val, optval_addr))
1564 return -TARGET_EFAULT;
2efbe911 1565 } else {
2efbe911
FB
1566 if (len > sizeof(int))
1567 len = sizeof(int);
2f619698
FB
1568 if (put_user_u32(len, optlen)
1569 || put_user_u32(val, optval_addr))
1570 return -TARGET_EFAULT;
2efbe911 1571 }
8853f86e 1572 break;
2efbe911 1573 default:
c02f499e
TS
1574 ret = -TARGET_ENOPROTOOPT;
1575 break;
8853f86e
FB
1576 }
1577 break;
1578 default:
1579 unimplemented:
1580 gemu_log("getsockopt level=%d optname=%d not yet supported\n",
1581 level, optname);
c02f499e 1582 ret = -TARGET_EOPNOTSUPP;
8853f86e
FB
1583 break;
1584 }
1585 return ret;
7854b056
FB
1586}
1587
579a97f7
FB
1588/* FIXME
1589 * lock_iovec()/unlock_iovec() have a return code of 0 for success where
1590 * other lock functions have a return code of 0 for failure.
1591 */
1592static abi_long lock_iovec(int type, struct iovec *vec, abi_ulong target_addr,
1593 int count, int copy)
53a5960a
PB
1594{
1595 struct target_iovec *target_vec;
992f48a0 1596 abi_ulong base;
d732dcb4 1597 int i;
53a5960a 1598
579a97f7
FB
1599 target_vec = lock_user(VERIFY_READ, target_addr, count * sizeof(struct target_iovec), 1);
1600 if (!target_vec)
1601 return -TARGET_EFAULT;
53a5960a
PB
1602 for(i = 0;i < count; i++) {
1603 base = tswapl(target_vec[i].iov_base);
1604 vec[i].iov_len = tswapl(target_vec[i].iov_len);
41df8411
FB
1605 if (vec[i].iov_len != 0) {
1606 vec[i].iov_base = lock_user(type, base, vec[i].iov_len, copy);
d732dcb4
AZ
1607 /* Don't check lock_user return value. We must call writev even
1608 if a element has invalid base address. */
41df8411
FB
1609 } else {
1610 /* zero length pointer is ignored */
1611 vec[i].iov_base = NULL;
1612 }
579a97f7
FB
1613 }
1614 unlock_user (target_vec, target_addr, 0);
1615 return 0;
53a5960a
PB
1616}
1617
579a97f7
FB
1618static abi_long unlock_iovec(struct iovec *vec, abi_ulong target_addr,
1619 int count, int copy)
53a5960a
PB
1620{
1621 struct target_iovec *target_vec;
992f48a0 1622 abi_ulong base;
53a5960a
PB
1623 int i;
1624
579a97f7
FB
1625 target_vec = lock_user(VERIFY_READ, target_addr, count * sizeof(struct target_iovec), 1);
1626 if (!target_vec)
1627 return -TARGET_EFAULT;
53a5960a 1628 for(i = 0;i < count; i++) {
d732dcb4
AZ
1629 if (target_vec[i].iov_base) {
1630 base = tswapl(target_vec[i].iov_base);
1631 unlock_user(vec[i].iov_base, base, copy ? vec[i].iov_len : 0);
1632 }
53a5960a
PB
1633 }
1634 unlock_user (target_vec, target_addr, 0);
579a97f7
FB
1635
1636 return 0;
53a5960a
PB
1637}
1638
0da46a6e 1639/* do_socket() Must return target values and target errnos. */
992f48a0 1640static abi_long do_socket(int domain, int type, int protocol)
3532fa74
FB
1641{
1642#if defined(TARGET_MIPS)
1643 switch(type) {
1644 case TARGET_SOCK_DGRAM:
1645 type = SOCK_DGRAM;
1646 break;
1647 case TARGET_SOCK_STREAM:
1648 type = SOCK_STREAM;
1649 break;
1650 case TARGET_SOCK_RAW:
1651 type = SOCK_RAW;
1652 break;
1653 case TARGET_SOCK_RDM:
1654 type = SOCK_RDM;
1655 break;
1656 case TARGET_SOCK_SEQPACKET:
1657 type = SOCK_SEQPACKET;
1658 break;
1659 case TARGET_SOCK_PACKET:
1660 type = SOCK_PACKET;
1661 break;
1662 }
1663#endif
12bc92ab
AZ
1664 if (domain == PF_NETLINK)
1665 return -EAFNOSUPPORT; /* do not NETLINK socket connections possible */
3532fa74
FB
1666 return get_errno(socket(domain, type, protocol));
1667}
1668
0da46a6e 1669/* do_bind() Must return target values and target errnos. */
992f48a0
BS
1670static abi_long do_bind(int sockfd, abi_ulong target_addr,
1671 socklen_t addrlen)
3532fa74 1672{
8f7aeaf6 1673 void *addr;
917507b0 1674 abi_long ret;
8f7aeaf6 1675
38724253 1676 if ((int)addrlen < 0) {
8f7aeaf6 1677 return -TARGET_EINVAL;
38724253 1678 }
8f7aeaf6 1679
607175e0 1680 addr = alloca(addrlen+1);
3b46e624 1681
917507b0
AP
1682 ret = target_to_host_sockaddr(addr, target_addr, addrlen);
1683 if (ret)
1684 return ret;
1685
3532fa74
FB
1686 return get_errno(bind(sockfd, addr, addrlen));
1687}
1688
0da46a6e 1689/* do_connect() Must return target values and target errnos. */
992f48a0
BS
1690static abi_long do_connect(int sockfd, abi_ulong target_addr,
1691 socklen_t addrlen)
3532fa74 1692{
8f7aeaf6 1693 void *addr;
917507b0 1694 abi_long ret;
8f7aeaf6 1695
38724253 1696 if ((int)addrlen < 0) {
8f7aeaf6 1697 return -TARGET_EINVAL;
38724253 1698 }
8f7aeaf6
AJ
1699
1700 addr = alloca(addrlen);
3b46e624 1701
917507b0
AP
1702 ret = target_to_host_sockaddr(addr, target_addr, addrlen);
1703 if (ret)
1704 return ret;
1705
3532fa74
FB
1706 return get_errno(connect(sockfd, addr, addrlen));
1707}
1708
0da46a6e 1709/* do_sendrecvmsg() Must return target values and target errnos. */
992f48a0
BS
1710static abi_long do_sendrecvmsg(int fd, abi_ulong target_msg,
1711 int flags, int send)
3532fa74 1712{
6de645c7 1713 abi_long ret, len;
3532fa74
FB
1714 struct target_msghdr *msgp;
1715 struct msghdr msg;
1716 int count;
1717 struct iovec *vec;
992f48a0 1718 abi_ulong target_vec;
3532fa74 1719
579a97f7
FB
1720 /* FIXME */
1721 if (!lock_user_struct(send ? VERIFY_READ : VERIFY_WRITE,
1722 msgp,
1723 target_msg,
1724 send ? 1 : 0))
1725 return -TARGET_EFAULT;
3532fa74
FB
1726 if (msgp->msg_name) {
1727 msg.msg_namelen = tswap32(msgp->msg_namelen);
1728 msg.msg_name = alloca(msg.msg_namelen);
917507b0 1729 ret = target_to_host_sockaddr(msg.msg_name, tswapl(msgp->msg_name),
3532fa74 1730 msg.msg_namelen);
917507b0
AP
1731 if (ret) {
1732 unlock_user_struct(msgp, target_msg, send ? 0 : 1);
1733 return ret;
1734 }
3532fa74
FB
1735 } else {
1736 msg.msg_name = NULL;
1737 msg.msg_namelen = 0;
1738 }
1739 msg.msg_controllen = 2 * tswapl(msgp->msg_controllen);
1740 msg.msg_control = alloca(msg.msg_controllen);
1741 msg.msg_flags = tswap32(msgp->msg_flags);
3b46e624 1742
3532fa74
FB
1743 count = tswapl(msgp->msg_iovlen);
1744 vec = alloca(count * sizeof(struct iovec));
1745 target_vec = tswapl(msgp->msg_iov);
579a97f7 1746 lock_iovec(send ? VERIFY_READ : VERIFY_WRITE, vec, target_vec, count, send);
3532fa74
FB
1747 msg.msg_iovlen = count;
1748 msg.msg_iov = vec;
3b46e624 1749
3532fa74 1750 if (send) {
5a4a898d
FB
1751 ret = target_to_host_cmsg(&msg, msgp);
1752 if (ret == 0)
1753 ret = get_errno(sendmsg(fd, &msg, flags));
3532fa74
FB
1754 } else {
1755 ret = get_errno(recvmsg(fd, &msg, flags));
6de645c7
AZ
1756 if (!is_error(ret)) {
1757 len = ret;
5a4a898d 1758 ret = host_to_target_cmsg(msgp, &msg);
6de645c7
AZ
1759 if (!is_error(ret))
1760 ret = len;
1761 }
3532fa74
FB
1762 }
1763 unlock_iovec(vec, target_vec, count, !send);
579a97f7 1764 unlock_user_struct(msgp, target_msg, send ? 0 : 1);
3532fa74
FB
1765 return ret;
1766}
1767
0da46a6e 1768/* do_accept() Must return target values and target errnos. */
992f48a0 1769static abi_long do_accept(int fd, abi_ulong target_addr,
2f619698 1770 abi_ulong target_addrlen_addr)
1be9e1dc 1771{
2f619698
FB
1772 socklen_t addrlen;
1773 void *addr;
992f48a0 1774 abi_long ret;
1be9e1dc 1775
917507b0
AP
1776 if (target_addr == 0)
1777 return get_errno(accept(fd, NULL, NULL));
1778
1779 /* linux returns EINVAL if addrlen pointer is invalid */
2f619698 1780 if (get_user_u32(addrlen, target_addrlen_addr))
917507b0 1781 return -TARGET_EINVAL;
2f619698 1782
38724253 1783 if ((int)addrlen < 0) {
8f7aeaf6 1784 return -TARGET_EINVAL;
38724253 1785 }
8f7aeaf6 1786
917507b0
AP
1787 if (!access_ok(VERIFY_WRITE, target_addr, addrlen))
1788 return -TARGET_EINVAL;
1789
2f619698
FB
1790 addr = alloca(addrlen);
1791
1be9e1dc
PB
1792 ret = get_errno(accept(fd, addr, &addrlen));
1793 if (!is_error(ret)) {
1794 host_to_target_sockaddr(target_addr, addr, addrlen);
2f619698
FB
1795 if (put_user_u32(addrlen, target_addrlen_addr))
1796 ret = -TARGET_EFAULT;
1be9e1dc
PB
1797 }
1798 return ret;
1799}
1800
0da46a6e 1801/* do_getpeername() Must return target values and target errnos. */
992f48a0 1802static abi_long do_getpeername(int fd, abi_ulong target_addr,
2f619698 1803 abi_ulong target_addrlen_addr)
1be9e1dc 1804{
2f619698
FB
1805 socklen_t addrlen;
1806 void *addr;
992f48a0 1807 abi_long ret;
1be9e1dc 1808
2f619698
FB
1809 if (get_user_u32(addrlen, target_addrlen_addr))
1810 return -TARGET_EFAULT;
1811
38724253 1812 if ((int)addrlen < 0) {
8f7aeaf6 1813 return -TARGET_EINVAL;
38724253 1814 }
8f7aeaf6 1815
917507b0
AP
1816 if (!access_ok(VERIFY_WRITE, target_addr, addrlen))
1817 return -TARGET_EFAULT;
1818
2f619698
FB
1819 addr = alloca(addrlen);
1820
1be9e1dc
PB
1821 ret = get_errno(getpeername(fd, addr, &addrlen));
1822 if (!is_error(ret)) {
1823 host_to_target_sockaddr(target_addr, addr, addrlen);
2f619698
FB
1824 if (put_user_u32(addrlen, target_addrlen_addr))
1825 ret = -TARGET_EFAULT;
1be9e1dc
PB
1826 }
1827 return ret;
1828}
1829
0da46a6e 1830/* do_getsockname() Must return target values and target errnos. */
992f48a0 1831static abi_long do_getsockname(int fd, abi_ulong target_addr,
2f619698 1832 abi_ulong target_addrlen_addr)
1be9e1dc 1833{
2f619698
FB
1834 socklen_t addrlen;
1835 void *addr;
992f48a0 1836 abi_long ret;
1be9e1dc 1837
2f619698
FB
1838 if (get_user_u32(addrlen, target_addrlen_addr))
1839 return -TARGET_EFAULT;
1840
38724253 1841 if ((int)addrlen < 0) {
8f7aeaf6 1842 return -TARGET_EINVAL;
38724253 1843 }
8f7aeaf6 1844
917507b0
AP
1845 if (!access_ok(VERIFY_WRITE, target_addr, addrlen))
1846 return -TARGET_EFAULT;
1847
2f619698
FB
1848 addr = alloca(addrlen);
1849
1be9e1dc
PB
1850 ret = get_errno(getsockname(fd, addr, &addrlen));
1851 if (!is_error(ret)) {
1852 host_to_target_sockaddr(target_addr, addr, addrlen);
2f619698
FB
1853 if (put_user_u32(addrlen, target_addrlen_addr))
1854 ret = -TARGET_EFAULT;
1be9e1dc
PB
1855 }
1856 return ret;
1857}
1858
0da46a6e 1859/* do_socketpair() Must return target values and target errnos. */
992f48a0 1860static abi_long do_socketpair(int domain, int type, int protocol,
2f619698 1861 abi_ulong target_tab_addr)
1be9e1dc
PB
1862{
1863 int tab[2];
992f48a0 1864 abi_long ret;
1be9e1dc
PB
1865
1866 ret = get_errno(socketpair(domain, type, protocol, tab));
1867 if (!is_error(ret)) {
2f619698
FB
1868 if (put_user_s32(tab[0], target_tab_addr)
1869 || put_user_s32(tab[1], target_tab_addr + sizeof(tab[0])))
1870 ret = -TARGET_EFAULT;
1be9e1dc
PB
1871 }
1872 return ret;
1873}
1874
0da46a6e 1875/* do_sendto() Must return target values and target errnos. */
992f48a0
BS
1876static abi_long do_sendto(int fd, abi_ulong msg, size_t len, int flags,
1877 abi_ulong target_addr, socklen_t addrlen)
1be9e1dc
PB
1878{
1879 void *addr;
1880 void *host_msg;
992f48a0 1881 abi_long ret;
1be9e1dc 1882
38724253 1883 if ((int)addrlen < 0) {
8f7aeaf6 1884 return -TARGET_EINVAL;
38724253 1885 }
8f7aeaf6 1886
579a97f7
FB
1887 host_msg = lock_user(VERIFY_READ, msg, len, 1);
1888 if (!host_msg)
1889 return -TARGET_EFAULT;
1be9e1dc
PB
1890 if (target_addr) {
1891 addr = alloca(addrlen);
917507b0
AP
1892 ret = target_to_host_sockaddr(addr, target_addr, addrlen);
1893 if (ret) {
1894 unlock_user(host_msg, msg, 0);
1895 return ret;
1896 }
1be9e1dc
PB
1897 ret = get_errno(sendto(fd, host_msg, len, flags, addr, addrlen));
1898 } else {
1899 ret = get_errno(send(fd, host_msg, len, flags));
1900 }
1901 unlock_user(host_msg, msg, 0);
1902 return ret;
1903}
1904
0da46a6e 1905/* do_recvfrom() Must return target values and target errnos. */
992f48a0
BS
1906static abi_long do_recvfrom(int fd, abi_ulong msg, size_t len, int flags,
1907 abi_ulong target_addr,
1908 abi_ulong target_addrlen)
1be9e1dc
PB
1909{
1910 socklen_t addrlen;
1911 void *addr;
1912 void *host_msg;
992f48a0 1913 abi_long ret;
1be9e1dc 1914
579a97f7
FB
1915 host_msg = lock_user(VERIFY_WRITE, msg, len, 0);
1916 if (!host_msg)
1917 return -TARGET_EFAULT;
1be9e1dc 1918 if (target_addr) {
2f619698
FB
1919 if (get_user_u32(addrlen, target_addrlen)) {
1920 ret = -TARGET_EFAULT;
1921 goto fail;
1922 }
38724253 1923 if ((int)addrlen < 0) {
8f7aeaf6
AJ
1924 ret = -TARGET_EINVAL;
1925 goto fail;
1926 }
1be9e1dc
PB
1927 addr = alloca(addrlen);
1928 ret = get_errno(recvfrom(fd, host_msg, len, flags, addr, &addrlen));
1929 } else {
1930 addr = NULL; /* To keep compiler quiet. */
1931 ret = get_errno(recv(fd, host_msg, len, flags));
1932 }
1933 if (!is_error(ret)) {
1934 if (target_addr) {
1935 host_to_target_sockaddr(target_addr, addr, addrlen);
2f619698
FB
1936 if (put_user_u32(addrlen, target_addrlen)) {
1937 ret = -TARGET_EFAULT;
1938 goto fail;
1939 }
1be9e1dc
PB
1940 }
1941 unlock_user(host_msg, msg, len);
1942 } else {
2f619698 1943fail:
1be9e1dc
PB
1944 unlock_user(host_msg, msg, 0);
1945 }
1946 return ret;
1947}
1948
32407103 1949#ifdef TARGET_NR_socketcall
0da46a6e 1950/* do_socketcall() Must return target values and target errnos. */
992f48a0 1951static abi_long do_socketcall(int num, abi_ulong vptr)
31e31b8a 1952{
992f48a0
BS
1953 abi_long ret;
1954 const int n = sizeof(abi_ulong);
31e31b8a
FB
1955
1956 switch(num) {
1957 case SOCKOP_socket:
7854b056 1958 {
98818189 1959 abi_ulong domain, type, protocol;
2f619698 1960
98818189
UH
1961 if (get_user_ual(domain, vptr)
1962 || get_user_ual(type, vptr + n)
1963 || get_user_ual(protocol, vptr + 2 * n))
2f619698
FB
1964 return -TARGET_EFAULT;
1965
3532fa74 1966 ret = do_socket(domain, type, protocol);
7854b056 1967 }
31e31b8a
FB
1968 break;
1969 case SOCKOP_bind:
7854b056 1970 {
98818189 1971 abi_ulong sockfd;
2f619698
FB
1972 abi_ulong target_addr;
1973 socklen_t addrlen;
1974
98818189 1975 if (get_user_ual(sockfd, vptr)
2f619698 1976 || get_user_ual(target_addr, vptr + n)
98818189 1977 || get_user_ual(addrlen, vptr + 2 * n))
2f619698
FB
1978 return -TARGET_EFAULT;
1979
3532fa74 1980 ret = do_bind(sockfd, target_addr, addrlen);
7854b056 1981 }
31e31b8a
FB
1982 break;
1983 case SOCKOP_connect:
7854b056 1984 {
98818189 1985 abi_ulong sockfd;
2f619698
FB
1986 abi_ulong target_addr;
1987 socklen_t addrlen;
1988
98818189 1989 if (get_user_ual(sockfd, vptr)
2f619698 1990 || get_user_ual(target_addr, vptr + n)
98818189 1991 || get_user_ual(addrlen, vptr + 2 * n))
2f619698
FB
1992 return -TARGET_EFAULT;
1993
3532fa74 1994 ret = do_connect(sockfd, target_addr, addrlen);
7854b056 1995 }
31e31b8a
FB
1996 break;
1997 case SOCKOP_listen:
7854b056 1998 {
98818189 1999 abi_ulong sockfd, backlog;
2f619698 2000
98818189
UH
2001 if (get_user_ual(sockfd, vptr)
2002 || get_user_ual(backlog, vptr + n))
2f619698
FB
2003 return -TARGET_EFAULT;
2004
7854b056
FB
2005 ret = get_errno(listen(sockfd, backlog));
2006 }
31e31b8a
FB
2007 break;
2008 case SOCKOP_accept:
2009 {
98818189 2010 abi_ulong sockfd;
2f619698
FB
2011 abi_ulong target_addr, target_addrlen;
2012
98818189 2013 if (get_user_ual(sockfd, vptr)
2f619698 2014 || get_user_ual(target_addr, vptr + n)
98818189 2015 || get_user_ual(target_addrlen, vptr + 2 * n))
2f619698
FB
2016 return -TARGET_EFAULT;
2017
1be9e1dc 2018 ret = do_accept(sockfd, target_addr, target_addrlen);
31e31b8a
FB
2019 }
2020 break;
2021 case SOCKOP_getsockname:
2022 {
98818189 2023 abi_ulong sockfd;
2f619698
FB
2024 abi_ulong target_addr, target_addrlen;
2025
98818189 2026 if (get_user_ual(sockfd, vptr)
2f619698 2027 || get_user_ual(target_addr, vptr + n)
98818189 2028 || get_user_ual(target_addrlen, vptr + 2 * n))
2f619698
FB
2029 return -TARGET_EFAULT;
2030
1be9e1dc 2031 ret = do_getsockname(sockfd, target_addr, target_addrlen);
31e31b8a
FB
2032 }
2033 break;
2034 case SOCKOP_getpeername:
2035 {
98818189 2036 abi_ulong sockfd;
2f619698
FB
2037 abi_ulong target_addr, target_addrlen;
2038
98818189 2039 if (get_user_ual(sockfd, vptr)
2f619698 2040 || get_user_ual(target_addr, vptr + n)
98818189 2041 || get_user_ual(target_addrlen, vptr + 2 * n))
2f619698
FB
2042 return -TARGET_EFAULT;
2043
1be9e1dc 2044 ret = do_getpeername(sockfd, target_addr, target_addrlen);
31e31b8a
FB
2045 }
2046 break;
2047 case SOCKOP_socketpair:
2048 {
98818189 2049 abi_ulong domain, type, protocol;
2f619698
FB
2050 abi_ulong tab;
2051
98818189
UH
2052 if (get_user_ual(domain, vptr)
2053 || get_user_ual(type, vptr + n)
2054 || get_user_ual(protocol, vptr + 2 * n)
2f619698
FB
2055 || get_user_ual(tab, vptr + 3 * n))
2056 return -TARGET_EFAULT;
2057
1be9e1dc 2058 ret = do_socketpair(domain, type, protocol, tab);
31e31b8a
FB
2059 }
2060 break;
2061 case SOCKOP_send:
7854b056 2062 {
98818189 2063 abi_ulong sockfd;
2f619698
FB
2064 abi_ulong msg;
2065 size_t len;
98818189 2066 abi_ulong flags;
2f619698 2067
98818189 2068 if (get_user_ual(sockfd, vptr)
2f619698
FB
2069 || get_user_ual(msg, vptr + n)
2070 || get_user_ual(len, vptr + 2 * n)
98818189 2071 || get_user_ual(flags, vptr + 3 * n))
2f619698
FB
2072 return -TARGET_EFAULT;
2073
1be9e1dc 2074 ret = do_sendto(sockfd, msg, len, flags, 0, 0);
7854b056 2075 }
31e31b8a
FB
2076 break;
2077 case SOCKOP_recv:
7854b056 2078 {
98818189 2079 abi_ulong sockfd;
2f619698
FB
2080 abi_ulong msg;
2081 size_t len;
98818189 2082 abi_ulong flags;
2f619698 2083
98818189 2084 if (get_user_ual(sockfd, vptr)
2f619698
FB
2085 || get_user_ual(msg, vptr + n)
2086 || get_user_ual(len, vptr + 2 * n)
98818189 2087 || get_user_ual(flags, vptr + 3 * n))
2f619698
FB
2088 return -TARGET_EFAULT;
2089
1be9e1dc 2090 ret = do_recvfrom(sockfd, msg, len, flags, 0, 0);
7854b056 2091 }
31e31b8a
FB
2092 break;
2093 case SOCKOP_sendto:
7854b056 2094 {
98818189 2095 abi_ulong sockfd;
2f619698
FB
2096 abi_ulong msg;
2097 size_t len;
98818189 2098 abi_ulong flags;
2f619698
FB
2099 abi_ulong addr;
2100 socklen_t addrlen;
2101
98818189 2102 if (get_user_ual(sockfd, vptr)
2f619698
FB
2103 || get_user_ual(msg, vptr + n)
2104 || get_user_ual(len, vptr + 2 * n)
98818189 2105 || get_user_ual(flags, vptr + 3 * n)
2f619698 2106 || get_user_ual(addr, vptr + 4 * n)
98818189 2107 || get_user_ual(addrlen, vptr + 5 * n))
2f619698
FB
2108 return -TARGET_EFAULT;
2109
1be9e1dc 2110 ret = do_sendto(sockfd, msg, len, flags, addr, addrlen);
7854b056 2111 }
31e31b8a
FB
2112 break;
2113 case SOCKOP_recvfrom:
2114 {
98818189 2115 abi_ulong sockfd;
2f619698
FB
2116 abi_ulong msg;
2117 size_t len;
98818189 2118 abi_ulong flags;
2f619698
FB
2119 abi_ulong addr;
2120 socklen_t addrlen;
2121
98818189 2122 if (get_user_ual(sockfd, vptr)
2f619698
FB
2123 || get_user_ual(msg, vptr + n)
2124 || get_user_ual(len, vptr + 2 * n)
98818189 2125 || get_user_ual(flags, vptr + 3 * n)
2f619698 2126 || get_user_ual(addr, vptr + 4 * n)
98818189 2127 || get_user_ual(addrlen, vptr + 5 * n))
2f619698
FB
2128 return -TARGET_EFAULT;
2129
1be9e1dc 2130 ret = do_recvfrom(sockfd, msg, len, flags, addr, addrlen);
31e31b8a
FB
2131 }
2132 break;
2133 case SOCKOP_shutdown:
7854b056 2134 {
98818189 2135 abi_ulong sockfd, how;
2f619698 2136
98818189
UH
2137 if (get_user_ual(sockfd, vptr)
2138 || get_user_ual(how, vptr + n))
2f619698 2139 return -TARGET_EFAULT;
7854b056
FB
2140
2141 ret = get_errno(shutdown(sockfd, how));
2142 }
31e31b8a
FB
2143 break;
2144 case SOCKOP_sendmsg:
2145 case SOCKOP_recvmsg:
1a9353d2 2146 {
98818189 2147 abi_ulong fd;
992f48a0 2148 abi_ulong target_msg;
98818189 2149 abi_ulong flags;
1a9353d2 2150
98818189 2151 if (get_user_ual(fd, vptr)
2f619698 2152 || get_user_ual(target_msg, vptr + n)
98818189 2153 || get_user_ual(flags, vptr + 2 * n))
2f619698 2154 return -TARGET_EFAULT;
3532fa74 2155
5fafdf24 2156 ret = do_sendrecvmsg(fd, target_msg, flags,
3532fa74 2157 (num == SOCKOP_sendmsg));
1a9353d2
FB
2158 }
2159 break;
31e31b8a 2160 case SOCKOP_setsockopt:
7854b056 2161 {
98818189
UH
2162 abi_ulong sockfd;
2163 abi_ulong level;
2164 abi_ulong optname;
2f619698
FB
2165 abi_ulong optval;
2166 socklen_t optlen;
2167
98818189
UH
2168 if (get_user_ual(sockfd, vptr)
2169 || get_user_ual(level, vptr + n)
2170 || get_user_ual(optname, vptr + 2 * n)
2f619698 2171 || get_user_ual(optval, vptr + 3 * n)
98818189 2172 || get_user_ual(optlen, vptr + 4 * n))
2f619698 2173 return -TARGET_EFAULT;
7854b056
FB
2174
2175 ret = do_setsockopt(sockfd, level, optname, optval, optlen);
2176 }
2177 break;
31e31b8a 2178 case SOCKOP_getsockopt:
7854b056 2179 {
98818189
UH
2180 abi_ulong sockfd;
2181 abi_ulong level;
2182 abi_ulong optname;
2f619698
FB
2183 abi_ulong optval;
2184 socklen_t optlen;
2185
98818189
UH
2186 if (get_user_ual(sockfd, vptr)
2187 || get_user_ual(level, vptr + n)
2188 || get_user_ual(optname, vptr + 2 * n)
2f619698 2189 || get_user_ual(optval, vptr + 3 * n)
98818189 2190 || get_user_ual(optlen, vptr + 4 * n))
2f619698 2191 return -TARGET_EFAULT;
7854b056 2192
2f619698 2193 ret = do_getsockopt(sockfd, level, optname, optval, optlen);
7854b056
FB
2194 }
2195 break;
31e31b8a
FB
2196 default:
2197 gemu_log("Unsupported socketcall: %d\n", num);
0da46a6e 2198 ret = -TARGET_ENOSYS;
31e31b8a
FB
2199 break;
2200 }
2201 return ret;
2202}
32407103 2203#endif
31e31b8a 2204
8853f86e
FB
2205#define N_SHM_REGIONS 32
2206
2207static struct shm_region {
5a4a898d
FB
2208 abi_ulong start;
2209 abi_ulong size;
8853f86e
FB
2210} shm_regions[N_SHM_REGIONS];
2211
3eb6b044
TS
2212struct target_ipc_perm
2213{
992f48a0
BS
2214 abi_long __key;
2215 abi_ulong uid;
2216 abi_ulong gid;
2217 abi_ulong cuid;
2218 abi_ulong cgid;
3eb6b044
TS
2219 unsigned short int mode;
2220 unsigned short int __pad1;
2221 unsigned short int __seq;
2222 unsigned short int __pad2;
992f48a0
BS
2223 abi_ulong __unused1;
2224 abi_ulong __unused2;
3eb6b044
TS
2225};
2226
2227struct target_semid_ds
2228{
2229 struct target_ipc_perm sem_perm;
992f48a0
BS
2230 abi_ulong sem_otime;
2231 abi_ulong __unused1;
2232 abi_ulong sem_ctime;
2233 abi_ulong __unused2;
2234 abi_ulong sem_nsems;
2235 abi_ulong __unused3;
2236 abi_ulong __unused4;
3eb6b044
TS
2237};
2238
579a97f7
FB
2239static inline abi_long target_to_host_ipc_perm(struct ipc_perm *host_ip,
2240 abi_ulong target_addr)
3eb6b044
TS
2241{
2242 struct target_ipc_perm *target_ip;
2243 struct target_semid_ds *target_sd;
2244
579a97f7
FB
2245 if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
2246 return -TARGET_EFAULT;
e8bbe36c 2247 target_ip = &(target_sd->sem_perm);
3eb6b044
TS
2248 host_ip->__key = tswapl(target_ip->__key);
2249 host_ip->uid = tswapl(target_ip->uid);
2250 host_ip->gid = tswapl(target_ip->gid);
2251 host_ip->cuid = tswapl(target_ip->cuid);
2252 host_ip->cgid = tswapl(target_ip->cgid);
2253 host_ip->mode = tswapl(target_ip->mode);
2254 unlock_user_struct(target_sd, target_addr, 0);
579a97f7 2255 return 0;
3eb6b044
TS
2256}
2257
579a97f7
FB
2258static inline abi_long host_to_target_ipc_perm(abi_ulong target_addr,
2259 struct ipc_perm *host_ip)
3eb6b044
TS
2260{
2261 struct target_ipc_perm *target_ip;
2262 struct target_semid_ds *target_sd;
2263
579a97f7
FB
2264 if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
2265 return -TARGET_EFAULT;
3eb6b044
TS
2266 target_ip = &(target_sd->sem_perm);
2267 target_ip->__key = tswapl(host_ip->__key);
2268 target_ip->uid = tswapl(host_ip->uid);
2269 target_ip->gid = tswapl(host_ip->gid);
2270 target_ip->cuid = tswapl(host_ip->cuid);
2271 target_ip->cgid = tswapl(host_ip->cgid);
2272 target_ip->mode = tswapl(host_ip->mode);
2273 unlock_user_struct(target_sd, target_addr, 1);
579a97f7 2274 return 0;
3eb6b044
TS
2275}
2276
579a97f7
FB
2277static inline abi_long target_to_host_semid_ds(struct semid_ds *host_sd,
2278 abi_ulong target_addr)
3eb6b044
TS
2279{
2280 struct target_semid_ds *target_sd;
2281
579a97f7
FB
2282 if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
2283 return -TARGET_EFAULT;
e5289087
AJ
2284 if (target_to_host_ipc_perm(&(host_sd->sem_perm),target_addr))
2285 return -TARGET_EFAULT;
3eb6b044
TS
2286 host_sd->sem_nsems = tswapl(target_sd->sem_nsems);
2287 host_sd->sem_otime = tswapl(target_sd->sem_otime);
2288 host_sd->sem_ctime = tswapl(target_sd->sem_ctime);
2289 unlock_user_struct(target_sd, target_addr, 0);
579a97f7 2290 return 0;
3eb6b044
TS
2291}
2292
579a97f7
FB
2293static inline abi_long host_to_target_semid_ds(abi_ulong target_addr,
2294 struct semid_ds *host_sd)
3eb6b044
TS
2295{
2296 struct target_semid_ds *target_sd;
2297
579a97f7
FB
2298 if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
2299 return -TARGET_EFAULT;
e5289087
AJ
2300 if (host_to_target_ipc_perm(target_addr,&(host_sd->sem_perm)))
2301 return -TARGET_EFAULT;;
3eb6b044
TS
2302 target_sd->sem_nsems = tswapl(host_sd->sem_nsems);
2303 target_sd->sem_otime = tswapl(host_sd->sem_otime);
2304 target_sd->sem_ctime = tswapl(host_sd->sem_ctime);
2305 unlock_user_struct(target_sd, target_addr, 1);
579a97f7 2306 return 0;
3eb6b044
TS
2307}
2308
e5289087
AJ
2309struct target_seminfo {
2310 int semmap;
2311 int semmni;
2312 int semmns;
2313 int semmnu;
2314 int semmsl;
2315 int semopm;
2316 int semume;
2317 int semusz;
2318 int semvmx;
2319 int semaem;
2320};
2321
2322static inline abi_long host_to_target_seminfo(abi_ulong target_addr,
2323 struct seminfo *host_seminfo)
2324{
2325 struct target_seminfo *target_seminfo;
2326 if (!lock_user_struct(VERIFY_WRITE, target_seminfo, target_addr, 0))
2327 return -TARGET_EFAULT;
2328 __put_user(host_seminfo->semmap, &target_seminfo->semmap);
2329 __put_user(host_seminfo->semmni, &target_seminfo->semmni);
2330 __put_user(host_seminfo->semmns, &target_seminfo->semmns);
2331 __put_user(host_seminfo->semmnu, &target_seminfo->semmnu);
2332 __put_user(host_seminfo->semmsl, &target_seminfo->semmsl);
2333 __put_user(host_seminfo->semopm, &target_seminfo->semopm);
2334 __put_user(host_seminfo->semume, &target_seminfo->semume);
2335 __put_user(host_seminfo->semusz, &target_seminfo->semusz);
2336 __put_user(host_seminfo->semvmx, &target_seminfo->semvmx);
2337 __put_user(host_seminfo->semaem, &target_seminfo->semaem);
2338 unlock_user_struct(target_seminfo, target_addr, 1);
2339 return 0;
2340}
2341
fa294816
TS
2342union semun {
2343 int val;
3eb6b044 2344 struct semid_ds *buf;
fa294816 2345 unsigned short *array;
e5289087 2346 struct seminfo *__buf;
fa294816
TS
2347};
2348
3eb6b044
TS
2349union target_semun {
2350 int val;
e5289087
AJ
2351 abi_ulong buf;
2352 abi_ulong array;
2353 abi_ulong __buf;
3eb6b044
TS
2354};
2355
e5289087
AJ
2356static inline abi_long target_to_host_semarray(int semid, unsigned short **host_array,
2357 abi_ulong target_addr)
3eb6b044 2358{
e5289087
AJ
2359 int nsems;
2360 unsigned short *array;
2361 union semun semun;
2362 struct semid_ds semid_ds;
2363 int i, ret;
3eb6b044 2364
e5289087
AJ
2365 semun.buf = &semid_ds;
2366
2367 ret = semctl(semid, 0, IPC_STAT, semun);
2368 if (ret == -1)
2369 return get_errno(ret);
2370
2371 nsems = semid_ds.sem_nsems;
2372
2373 *host_array = malloc(nsems*sizeof(unsigned short));
2374 array = lock_user(VERIFY_READ, target_addr,
2375 nsems*sizeof(unsigned short), 1);
2376 if (!array)
2377 return -TARGET_EFAULT;
2378
2379 for(i=0; i<nsems; i++) {
2380 __get_user((*host_array)[i], &array[i]);
3eb6b044 2381 }
e5289087
AJ
2382 unlock_user(array, target_addr, 0);
2383
579a97f7 2384 return 0;
3eb6b044
TS
2385}
2386
e5289087
AJ
2387static inline abi_long host_to_target_semarray(int semid, abi_ulong target_addr,
2388 unsigned short **host_array)
3eb6b044 2389{
e5289087
AJ
2390 int nsems;
2391 unsigned short *array;
2392 union semun semun;
2393 struct semid_ds semid_ds;
2394 int i, ret;
3eb6b044 2395
e5289087
AJ
2396 semun.buf = &semid_ds;
2397
2398 ret = semctl(semid, 0, IPC_STAT, semun);
2399 if (ret == -1)
2400 return get_errno(ret);
2401
2402 nsems = semid_ds.sem_nsems;
2403
2404 array = lock_user(VERIFY_WRITE, target_addr,
2405 nsems*sizeof(unsigned short), 0);
2406 if (!array)
2407 return -TARGET_EFAULT;
2408
2409 for(i=0; i<nsems; i++) {
2410 __put_user((*host_array)[i], &array[i]);
3eb6b044 2411 }
e5289087
AJ
2412 free(*host_array);
2413 unlock_user(array, target_addr, 1);
2414
579a97f7 2415 return 0;
3eb6b044
TS
2416}
2417
e5289087
AJ
2418static inline abi_long do_semctl(int semid, int semnum, int cmd,
2419 union target_semun target_su)
3eb6b044
TS
2420{
2421 union semun arg;
2422 struct semid_ds dsarg;
7b8118e8 2423 unsigned short *array = NULL;
e5289087
AJ
2424 struct seminfo seminfo;
2425 abi_long ret = -TARGET_EINVAL;
2426 abi_long err;
2427 cmd &= 0xff;
3eb6b044
TS
2428
2429 switch( cmd ) {
2430 case GETVAL:
3eb6b044 2431 case SETVAL:
e5289087
AJ
2432 arg.val = tswapl(target_su.val);
2433 ret = get_errno(semctl(semid, semnum, cmd, arg));
2434 target_su.val = tswapl(arg.val);
3eb6b044
TS
2435 break;
2436 case GETALL:
3eb6b044 2437 case SETALL:
e5289087
AJ
2438 err = target_to_host_semarray(semid, &array, target_su.array);
2439 if (err)
2440 return err;
2441 arg.array = array;
2442 ret = get_errno(semctl(semid, semnum, cmd, arg));
2443 err = host_to_target_semarray(semid, target_su.array, &array);
2444 if (err)
2445 return err;
3eb6b044
TS
2446 break;
2447 case IPC_STAT:
3eb6b044 2448 case IPC_SET:
e5289087
AJ
2449 case SEM_STAT:
2450 err = target_to_host_semid_ds(&dsarg, target_su.buf);
2451 if (err)
2452 return err;
2453 arg.buf = &dsarg;
2454 ret = get_errno(semctl(semid, semnum, cmd, arg));
2455 err = host_to_target_semid_ds(target_su.buf, &dsarg);
2456 if (err)
2457 return err;
2458 break;
2459 case IPC_INFO:
2460 case SEM_INFO:
2461 arg.__buf = &seminfo;
2462 ret = get_errno(semctl(semid, semnum, cmd, arg));
2463 err = host_to_target_seminfo(target_su.__buf, &seminfo);
2464 if (err)
2465 return err;
2466 break;
2467 case IPC_RMID:
2468 case GETPID:
2469 case GETNCNT:
2470 case GETZCNT:
2471 ret = get_errno(semctl(semid, semnum, cmd, NULL));
3eb6b044 2472 break;
3eb6b044
TS
2473 }
2474
2475 return ret;
2476}
2477
e5289087
AJ
2478struct target_sembuf {
2479 unsigned short sem_num;
2480 short sem_op;
2481 short sem_flg;
2482};
2483
2484static inline abi_long target_to_host_sembuf(struct sembuf *host_sembuf,
2485 abi_ulong target_addr,
2486 unsigned nsops)
2487{
2488 struct target_sembuf *target_sembuf;
2489 int i;
2490
2491 target_sembuf = lock_user(VERIFY_READ, target_addr,
2492 nsops*sizeof(struct target_sembuf), 1);
2493 if (!target_sembuf)
2494 return -TARGET_EFAULT;
2495
2496 for(i=0; i<nsops; i++) {
2497 __get_user(host_sembuf[i].sem_num, &target_sembuf[i].sem_num);
2498 __get_user(host_sembuf[i].sem_op, &target_sembuf[i].sem_op);
2499 __get_user(host_sembuf[i].sem_flg, &target_sembuf[i].sem_flg);
2500 }
2501
2502 unlock_user(target_sembuf, target_addr, 0);
2503
2504 return 0;
2505}
2506
2507static inline abi_long do_semop(int semid, abi_long ptr, unsigned nsops)
2508{
2509 struct sembuf sops[nsops];
2510
2511 if (target_to_host_sembuf(sops, ptr, nsops))
2512 return -TARGET_EFAULT;
2513
2514 return semop(semid, sops, nsops);
2515}
2516
1bc012f6
TS
2517struct target_msqid_ds
2518{
1c54ff97
AJ
2519 struct target_ipc_perm msg_perm;
2520 abi_ulong msg_stime;
2521#if TARGET_ABI_BITS == 32
2522 abi_ulong __unused1;
2523#endif
2524 abi_ulong msg_rtime;
2525#if TARGET_ABI_BITS == 32
2526 abi_ulong __unused2;
2527#endif
2528 abi_ulong msg_ctime;
2529#if TARGET_ABI_BITS == 32
2530 abi_ulong __unused3;
2531#endif
2532 abi_ulong __msg_cbytes;
2533 abi_ulong msg_qnum;
2534 abi_ulong msg_qbytes;
2535 abi_ulong msg_lspid;
2536 abi_ulong msg_lrpid;
2537 abi_ulong __unused4;
2538 abi_ulong __unused5;
1bc012f6
TS
2539};
2540
579a97f7
FB
2541static inline abi_long target_to_host_msqid_ds(struct msqid_ds *host_md,
2542 abi_ulong target_addr)
1bc012f6
TS
2543{
2544 struct target_msqid_ds *target_md;
2545
579a97f7
FB
2546 if (!lock_user_struct(VERIFY_READ, target_md, target_addr, 1))
2547 return -TARGET_EFAULT;
1c54ff97
AJ
2548 if (target_to_host_ipc_perm(&(host_md->msg_perm),target_addr))
2549 return -TARGET_EFAULT;
1bc012f6
TS
2550 host_md->msg_stime = tswapl(target_md->msg_stime);
2551 host_md->msg_rtime = tswapl(target_md->msg_rtime);
2552 host_md->msg_ctime = tswapl(target_md->msg_ctime);
2553 host_md->__msg_cbytes = tswapl(target_md->__msg_cbytes);
2554 host_md->msg_qnum = tswapl(target_md->msg_qnum);
2555 host_md->msg_qbytes = tswapl(target_md->msg_qbytes);
2556 host_md->msg_lspid = tswapl(target_md->msg_lspid);
2557 host_md->msg_lrpid = tswapl(target_md->msg_lrpid);
2558 unlock_user_struct(target_md, target_addr, 0);
579a97f7 2559 return 0;
1bc012f6
TS
2560}
2561
579a97f7
FB
2562static inline abi_long host_to_target_msqid_ds(abi_ulong target_addr,
2563 struct msqid_ds *host_md)
1bc012f6
TS
2564{
2565 struct target_msqid_ds *target_md;
2566
579a97f7
FB
2567 if (!lock_user_struct(VERIFY_WRITE, target_md, target_addr, 0))
2568 return -TARGET_EFAULT;
1c54ff97
AJ
2569 if (host_to_target_ipc_perm(target_addr,&(host_md->msg_perm)))
2570 return -TARGET_EFAULT;
1bc012f6
TS
2571 target_md->msg_stime = tswapl(host_md->msg_stime);
2572 target_md->msg_rtime = tswapl(host_md->msg_rtime);
2573 target_md->msg_ctime = tswapl(host_md->msg_ctime);
2574 target_md->__msg_cbytes = tswapl(host_md->__msg_cbytes);
2575 target_md->msg_qnum = tswapl(host_md->msg_qnum);
2576 target_md->msg_qbytes = tswapl(host_md->msg_qbytes);
2577 target_md->msg_lspid = tswapl(host_md->msg_lspid);
2578 target_md->msg_lrpid = tswapl(host_md->msg_lrpid);
2579 unlock_user_struct(target_md, target_addr, 1);
579a97f7 2580 return 0;
1bc012f6
TS
2581}
2582
1c54ff97
AJ
2583struct target_msginfo {
2584 int msgpool;
2585 int msgmap;
2586 int msgmax;
2587 int msgmnb;
2588 int msgmni;
2589 int msgssz;
2590 int msgtql;
2591 unsigned short int msgseg;
2592};
2593
2594static inline abi_long host_to_target_msginfo(abi_ulong target_addr,
2595 struct msginfo *host_msginfo)
2596{
2597 struct target_msginfo *target_msginfo;
2598 if (!lock_user_struct(VERIFY_WRITE, target_msginfo, target_addr, 0))
2599 return -TARGET_EFAULT;
2600 __put_user(host_msginfo->msgpool, &target_msginfo->msgpool);
2601 __put_user(host_msginfo->msgmap, &target_msginfo->msgmap);
2602 __put_user(host_msginfo->msgmax, &target_msginfo->msgmax);
2603 __put_user(host_msginfo->msgmnb, &target_msginfo->msgmnb);
2604 __put_user(host_msginfo->msgmni, &target_msginfo->msgmni);
2605 __put_user(host_msginfo->msgssz, &target_msginfo->msgssz);
2606 __put_user(host_msginfo->msgtql, &target_msginfo->msgtql);
2607 __put_user(host_msginfo->msgseg, &target_msginfo->msgseg);
2608 unlock_user_struct(target_msginfo, target_addr, 1);
00b229ac 2609 return 0;
1c54ff97
AJ
2610}
2611
2612static inline abi_long do_msgctl(int msgid, int cmd, abi_long ptr)
1bc012f6
TS
2613{
2614 struct msqid_ds dsarg;
1c54ff97
AJ
2615 struct msginfo msginfo;
2616 abi_long ret = -TARGET_EINVAL;
2617
2618 cmd &= 0xff;
2619
2620 switch (cmd) {
1bc012f6
TS
2621 case IPC_STAT:
2622 case IPC_SET:
1c54ff97
AJ
2623 case MSG_STAT:
2624 if (target_to_host_msqid_ds(&dsarg,ptr))
2625 return -TARGET_EFAULT;
2626 ret = get_errno(msgctl(msgid, cmd, &dsarg));
2627 if (host_to_target_msqid_ds(ptr,&dsarg))
2628 return -TARGET_EFAULT;
2629 break;
2630 case IPC_RMID:
2631 ret = get_errno(msgctl(msgid, cmd, NULL));
2632 break;
2633 case IPC_INFO:
2634 case MSG_INFO:
2635 ret = get_errno(msgctl(msgid, cmd, (struct msqid_ds *)&msginfo));
2636 if (host_to_target_msginfo(ptr, &msginfo))
2637 return -TARGET_EFAULT;
2638 break;
1bc012f6 2639 }
1c54ff97 2640
1bc012f6
TS
2641 return ret;
2642}
2643
2644struct target_msgbuf {
1c54ff97
AJ
2645 abi_long mtype;
2646 char mtext[1];
1bc012f6
TS
2647};
2648
992f48a0
BS
2649static inline abi_long do_msgsnd(int msqid, abi_long msgp,
2650 unsigned int msgsz, int msgflg)
1bc012f6
TS
2651{
2652 struct target_msgbuf *target_mb;
2653 struct msgbuf *host_mb;
992f48a0 2654 abi_long ret = 0;
1bc012f6 2655
579a97f7
FB
2656 if (!lock_user_struct(VERIFY_READ, target_mb, msgp, 0))
2657 return -TARGET_EFAULT;
1bc012f6 2658 host_mb = malloc(msgsz+sizeof(long));
1c54ff97
AJ
2659 host_mb->mtype = (abi_long) tswapl(target_mb->mtype);
2660 memcpy(host_mb->mtext, target_mb->mtext, msgsz);
1bc012f6
TS
2661 ret = get_errno(msgsnd(msqid, host_mb, msgsz, msgflg));
2662 free(host_mb);
2663 unlock_user_struct(target_mb, msgp, 0);
2664
2665 return ret;
2666}
2667
992f48a0 2668static inline abi_long do_msgrcv(int msqid, abi_long msgp,
1c54ff97 2669 unsigned int msgsz, abi_long msgtyp,
992f48a0 2670 int msgflg)
1bc012f6
TS
2671{
2672 struct target_msgbuf *target_mb;
579a97f7 2673 char *target_mtext;
1bc012f6 2674 struct msgbuf *host_mb;
992f48a0 2675 abi_long ret = 0;
1bc012f6 2676
579a97f7
FB
2677 if (!lock_user_struct(VERIFY_WRITE, target_mb, msgp, 0))
2678 return -TARGET_EFAULT;
1c54ff97 2679
1bc012f6 2680 host_mb = malloc(msgsz+sizeof(long));
1c54ff97
AJ
2681 ret = get_errno(msgrcv(msqid, host_mb, msgsz, tswapl(msgtyp), msgflg));
2682
579a97f7
FB
2683 if (ret > 0) {
2684 abi_ulong target_mtext_addr = msgp + sizeof(abi_ulong);
2685 target_mtext = lock_user(VERIFY_WRITE, target_mtext_addr, ret, 0);
2686 if (!target_mtext) {
2687 ret = -TARGET_EFAULT;
2688 goto end;
2689 }
1c54ff97 2690 memcpy(target_mb->mtext, host_mb->mtext, ret);
579a97f7
FB
2691 unlock_user(target_mtext, target_mtext_addr, ret);
2692 }
1c54ff97 2693
1bc012f6
TS
2694 target_mb->mtype = tswapl(host_mb->mtype);
2695 free(host_mb);
1bc012f6 2696
579a97f7
FB
2697end:
2698 if (target_mb)
2699 unlock_user_struct(target_mb, msgp, 1);
1bc012f6
TS
2700 return ret;
2701}
2702
88a8c984
RV
2703struct target_shmid_ds
2704{
2705 struct target_ipc_perm shm_perm;
2706 abi_ulong shm_segsz;
2707 abi_ulong shm_atime;
2708#if TARGET_ABI_BITS == 32
2709 abi_ulong __unused1;
2710#endif
2711 abi_ulong shm_dtime;
2712#if TARGET_ABI_BITS == 32
2713 abi_ulong __unused2;
2714#endif
2715 abi_ulong shm_ctime;
2716#if TARGET_ABI_BITS == 32
2717 abi_ulong __unused3;
2718#endif
2719 int shm_cpid;
2720 int shm_lpid;
2721 abi_ulong shm_nattch;
2722 unsigned long int __unused4;
2723 unsigned long int __unused5;
2724};
2725
2726static inline abi_long target_to_host_shmid_ds(struct shmid_ds *host_sd,
2727 abi_ulong target_addr)
2728{
2729 struct target_shmid_ds *target_sd;
2730
2731 if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
2732 return -TARGET_EFAULT;
2733 if (target_to_host_ipc_perm(&(host_sd->shm_perm), target_addr))
2734 return -TARGET_EFAULT;
2735 __get_user(host_sd->shm_segsz, &target_sd->shm_segsz);
2736 __get_user(host_sd->shm_atime, &target_sd->shm_atime);
2737 __get_user(host_sd->shm_dtime, &target_sd->shm_dtime);
2738 __get_user(host_sd->shm_ctime, &target_sd->shm_ctime);
2739 __get_user(host_sd->shm_cpid, &target_sd->shm_cpid);
2740 __get_user(host_sd->shm_lpid, &target_sd->shm_lpid);
2741 __get_user(host_sd->shm_nattch, &target_sd->shm_nattch);
2742 unlock_user_struct(target_sd, target_addr, 0);
2743 return 0;
2744}
2745
2746static inline abi_long host_to_target_shmid_ds(abi_ulong target_addr,
2747 struct shmid_ds *host_sd)
2748{
2749 struct target_shmid_ds *target_sd;
2750
2751 if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
2752 return -TARGET_EFAULT;
2753 if (host_to_target_ipc_perm(target_addr, &(host_sd->shm_perm)))
2754 return -TARGET_EFAULT;
2755 __put_user(host_sd->shm_segsz, &target_sd->shm_segsz);
2756 __put_user(host_sd->shm_atime, &target_sd->shm_atime);
2757 __put_user(host_sd->shm_dtime, &target_sd->shm_dtime);
2758 __put_user(host_sd->shm_ctime, &target_sd->shm_ctime);
2759 __put_user(host_sd->shm_cpid, &target_sd->shm_cpid);
2760 __put_user(host_sd->shm_lpid, &target_sd->shm_lpid);
2761 __put_user(host_sd->shm_nattch, &target_sd->shm_nattch);
2762 unlock_user_struct(target_sd, target_addr, 1);
2763 return 0;
2764}
2765
2766struct target_shminfo {
2767 abi_ulong shmmax;
2768 abi_ulong shmmin;
2769 abi_ulong shmmni;
2770 abi_ulong shmseg;
2771 abi_ulong shmall;
2772};
2773
2774static inline abi_long host_to_target_shminfo(abi_ulong target_addr,
2775 struct shminfo *host_shminfo)
2776{
2777 struct target_shminfo *target_shminfo;
2778 if (!lock_user_struct(VERIFY_WRITE, target_shminfo, target_addr, 0))
2779 return -TARGET_EFAULT;
2780 __put_user(host_shminfo->shmmax, &target_shminfo->shmmax);
2781 __put_user(host_shminfo->shmmin, &target_shminfo->shmmin);
2782 __put_user(host_shminfo->shmmni, &target_shminfo->shmmni);
2783 __put_user(host_shminfo->shmseg, &target_shminfo->shmseg);
2784 __put_user(host_shminfo->shmall, &target_shminfo->shmall);
2785 unlock_user_struct(target_shminfo, target_addr, 1);
2786 return 0;
2787}
2788
2789struct target_shm_info {
2790 int used_ids;
2791 abi_ulong shm_tot;
2792 abi_ulong shm_rss;
2793 abi_ulong shm_swp;
2794 abi_ulong swap_attempts;
2795 abi_ulong swap_successes;
2796};
2797
2798static inline abi_long host_to_target_shm_info(abi_ulong target_addr,
2799 struct shm_info *host_shm_info)
2800{
2801 struct target_shm_info *target_shm_info;
2802 if (!lock_user_struct(VERIFY_WRITE, target_shm_info, target_addr, 0))
2803 return -TARGET_EFAULT;
2804 __put_user(host_shm_info->used_ids, &target_shm_info->used_ids);
2805 __put_user(host_shm_info->shm_tot, &target_shm_info->shm_tot);
2806 __put_user(host_shm_info->shm_rss, &target_shm_info->shm_rss);
2807 __put_user(host_shm_info->shm_swp, &target_shm_info->shm_swp);
2808 __put_user(host_shm_info->swap_attempts, &target_shm_info->swap_attempts);
2809 __put_user(host_shm_info->swap_successes, &target_shm_info->swap_successes);
2810 unlock_user_struct(target_shm_info, target_addr, 1);
2811 return 0;
2812}
2813
2814static inline abi_long do_shmctl(int shmid, int cmd, abi_long buf)
2815{
2816 struct shmid_ds dsarg;
2817 struct shminfo shminfo;
2818 struct shm_info shm_info;
2819 abi_long ret = -TARGET_EINVAL;
2820
2821 cmd &= 0xff;
2822
2823 switch(cmd) {
2824 case IPC_STAT:
2825 case IPC_SET:
2826 case SHM_STAT:
2827 if (target_to_host_shmid_ds(&dsarg, buf))
2828 return -TARGET_EFAULT;
2829 ret = get_errno(shmctl(shmid, cmd, &dsarg));
2830 if (host_to_target_shmid_ds(buf, &dsarg))
2831 return -TARGET_EFAULT;
2832 break;
2833 case IPC_INFO:
2834 ret = get_errno(shmctl(shmid, cmd, (struct shmid_ds *)&shminfo));
2835 if (host_to_target_shminfo(buf, &shminfo))
2836 return -TARGET_EFAULT;
2837 break;
2838 case SHM_INFO:
2839 ret = get_errno(shmctl(shmid, cmd, (struct shmid_ds *)&shm_info));
2840 if (host_to_target_shm_info(buf, &shm_info))
2841 return -TARGET_EFAULT;
2842 break;
2843 case IPC_RMID:
2844 case SHM_LOCK:
2845 case SHM_UNLOCK:
2846 ret = get_errno(shmctl(shmid, cmd, NULL));
2847 break;
2848 }
2849
2850 return ret;
2851}
2852
2853static inline abi_ulong do_shmat(int shmid, abi_ulong shmaddr, int shmflg)
2854{
2855 abi_long raddr;
2856 void *host_raddr;
2857 struct shmid_ds shm_info;
2858 int i,ret;
2859
2860 /* find out the length of the shared memory segment */
2861 ret = get_errno(shmctl(shmid, IPC_STAT, &shm_info));
2862 if (is_error(ret)) {
2863 /* can't get length, bail out */
2864 return ret;
2865 }
2866
2867 mmap_lock();
2868
2869 if (shmaddr)
2870 host_raddr = shmat(shmid, (void *)g2h(shmaddr), shmflg);
2871 else {
2872 abi_ulong mmap_start;
2873
2874 mmap_start = mmap_find_vma(0, shm_info.shm_segsz);
2875
2876 if (mmap_start == -1) {
2877 errno = ENOMEM;
2878 host_raddr = (void *)-1;
2879 } else
2880 host_raddr = shmat(shmid, g2h(mmap_start), shmflg | SHM_REMAP);
2881 }
2882
2883 if (host_raddr == (void *)-1) {
2884 mmap_unlock();
2885 return get_errno((long)host_raddr);
2886 }
2887 raddr=h2g((unsigned long)host_raddr);
2888
2889 page_set_flags(raddr, raddr + shm_info.shm_segsz,
2890 PAGE_VALID | PAGE_READ |
2891 ((shmflg & SHM_RDONLY)? 0 : PAGE_WRITE));
2892
2893 for (i = 0; i < N_SHM_REGIONS; i++) {
2894 if (shm_regions[i].start == 0) {
2895 shm_regions[i].start = raddr;
2896 shm_regions[i].size = shm_info.shm_segsz;
2897 break;
2898 }
2899 }
2900
2901 mmap_unlock();
2902 return raddr;
2903
2904}
2905
2906static inline abi_long do_shmdt(abi_ulong shmaddr)
2907{
2908 int i;
2909
2910 for (i = 0; i < N_SHM_REGIONS; ++i) {
2911 if (shm_regions[i].start == shmaddr) {
2912 shm_regions[i].start = 0;
e00ac249 2913 page_set_flags(shmaddr, shmaddr + shm_regions[i].size, 0);
88a8c984
RV
2914 break;
2915 }
2916 }
2917
2918 return get_errno(shmdt(g2h(shmaddr)));
2919}
2920
1c54ff97 2921#ifdef TARGET_NR_ipc
53a5960a 2922/* ??? This only works with linear mappings. */
0da46a6e 2923/* do_ipc() must return target values and target errnos. */
992f48a0
BS
2924static abi_long do_ipc(unsigned int call, int first,
2925 int second, int third,
2926 abi_long ptr, abi_long fifth)
8853f86e
FB
2927{
2928 int version;
992f48a0 2929 abi_long ret = 0;
8853f86e
FB
2930
2931 version = call >> 16;
2932 call &= 0xffff;
2933
2934 switch (call) {
fa294816 2935 case IPCOP_semop:
e5289087 2936 ret = do_semop(first, ptr, second);
fa294816
TS
2937 break;
2938
2939 case IPCOP_semget:
2940 ret = get_errno(semget(first, second, third));
2941 break;
2942
2943 case IPCOP_semctl:
e5289087 2944 ret = do_semctl(first, second, third, (union target_semun)(abi_ulong) ptr);
fa294816 2945 break;
d96372ef 2946
1c54ff97
AJ
2947 case IPCOP_msgget:
2948 ret = get_errno(msgget(first, second));
2949 break;
d96372ef 2950
1c54ff97
AJ
2951 case IPCOP_msgsnd:
2952 ret = do_msgsnd(first, ptr, second, third);
2953 break;
d96372ef 2954
1c54ff97
AJ
2955 case IPCOP_msgctl:
2956 ret = do_msgctl(first, second, ptr);
2957 break;
d96372ef 2958
1c54ff97
AJ
2959 case IPCOP_msgrcv:
2960 switch (version) {
2961 case 0:
2962 {
2963 struct target_ipc_kludge {
2964 abi_long msgp;
2965 abi_long msgtyp;
2966 } *tmp;
2967
2968 if (!lock_user_struct(VERIFY_READ, tmp, ptr, 1)) {
2969 ret = -TARGET_EFAULT;
2970 break;
2971 }
d96372ef 2972
1c54ff97 2973 ret = do_msgrcv(first, tmp->msgp, second, tmp->msgtyp, third);
d96372ef 2974
1c54ff97
AJ
2975 unlock_user_struct(tmp, ptr, 0);
2976 break;
2977 }
2978 default:
2979 ret = do_msgrcv(first, ptr, second, fifth, third);
2980 }
2981 break;
d96372ef 2982
8853f86e 2983 case IPCOP_shmat:
88a8c984
RV
2984 switch (version) {
2985 default:
5a4a898d
FB
2986 {
2987 abi_ulong raddr;
88a8c984
RV
2988 raddr = do_shmat(first, ptr, second);
2989 if (is_error(raddr))
2990 return get_errno(raddr);
2f619698 2991 if (put_user_ual(raddr, third))
5a4a898d 2992 return -TARGET_EFAULT;
88a8c984
RV
2993 break;
2994 }
2995 case 1:
2996 ret = -TARGET_EINVAL;
2997 break;
5a4a898d 2998 }
8853f86e
FB
2999 break;
3000 case IPCOP_shmdt:
88a8c984 3001 ret = do_shmdt(ptr);
8853f86e
FB
3002 break;
3003
3004 case IPCOP_shmget:
3005 /* IPC_* flag values are the same on all linux platforms */
3006 ret = get_errno(shmget(first, second, third));
3007 break;
3008
3009 /* IPC_* and SHM_* command values are the same on all linux platforms */
3010 case IPCOP_shmctl:
88a8c984 3011 ret = do_shmctl(first, second, third);
8853f86e
FB
3012 break;
3013 default:
32407103 3014 gemu_log("Unsupported ipc call: %d (version %d)\n", call, version);
0da46a6e 3015 ret = -TARGET_ENOSYS;
8853f86e
FB
3016 break;
3017 }
3018 return ret;
3019}
32407103 3020#endif
8853f86e 3021
31e31b8a 3022/* kernel structure types definitions */
31e31b8a 3023
001faf32 3024#define STRUCT(name, ...) STRUCT_ ## name,
31e31b8a
FB
3025#define STRUCT_SPECIAL(name) STRUCT_ ## name,
3026enum {
3027#include "syscall_types.h"
3028};
3029#undef STRUCT
3030#undef STRUCT_SPECIAL
3031
001faf32 3032#define STRUCT(name, ...) static const argtype struct_ ## name ## _def[] = { __VA_ARGS__, TYPE_NULL };
31e31b8a
FB
3033#define STRUCT_SPECIAL(name)
3034#include "syscall_types.h"
3035#undef STRUCT
3036#undef STRUCT_SPECIAL
3037
d2ef05bb
PM
3038typedef struct IOCTLEntry IOCTLEntry;
3039
3040typedef abi_long do_ioctl_fn(const IOCTLEntry *ie, uint8_t *buf_temp,
3041 int fd, abi_long cmd, abi_long arg);
3042
3043struct IOCTLEntry {
2ab83ea7
FB
3044 unsigned int target_cmd;
3045 unsigned int host_cmd;
31e31b8a
FB
3046 const char *name;
3047 int access;
d2ef05bb 3048 do_ioctl_fn *do_ioctl;
1a9353d2 3049 const argtype arg_type[5];
d2ef05bb 3050};
31e31b8a
FB
3051
3052#define IOC_R 0x0001
3053#define IOC_W 0x0002
3054#define IOC_RW (IOC_R | IOC_W)
3055
3056#define MAX_STRUCT_SIZE 4096
3057
dace20dc 3058#ifdef CONFIG_FIEMAP
285da2b9
PM
3059/* So fiemap access checks don't overflow on 32 bit systems.
3060 * This is very slightly smaller than the limit imposed by
3061 * the underlying kernel.
3062 */
3063#define FIEMAP_MAX_EXTENTS ((UINT_MAX - sizeof(struct fiemap)) \
3064 / sizeof(struct fiemap_extent))
3065
3066static abi_long do_ioctl_fs_ioc_fiemap(const IOCTLEntry *ie, uint8_t *buf_temp,
3067 int fd, abi_long cmd, abi_long arg)
3068{
3069 /* The parameter for this ioctl is a struct fiemap followed
3070 * by an array of struct fiemap_extent whose size is set
3071 * in fiemap->fm_extent_count. The array is filled in by the
3072 * ioctl.
3073 */
3074 int target_size_in, target_size_out;
3075 struct fiemap *fm;
3076 const argtype *arg_type = ie->arg_type;
3077 const argtype extent_arg_type[] = { MK_STRUCT(STRUCT_fiemap_extent) };
3078 void *argptr, *p;
3079 abi_long ret;
3080 int i, extent_size = thunk_type_size(extent_arg_type, 0);
3081 uint32_t outbufsz;
3082 int free_fm = 0;
3083
3084 assert(arg_type[0] == TYPE_PTR);
3085 assert(ie->access == IOC_RW);
3086 arg_type++;
3087 target_size_in = thunk_type_size(arg_type, 0);
3088 argptr = lock_user(VERIFY_READ, arg, target_size_in, 1);
3089 if (!argptr) {
3090 return -TARGET_EFAULT;
3091 }
3092 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
3093 unlock_user(argptr, arg, 0);
3094 fm = (struct fiemap *)buf_temp;
3095 if (fm->fm_extent_count > FIEMAP_MAX_EXTENTS) {
3096 return -TARGET_EINVAL;
3097 }
3098
3099 outbufsz = sizeof (*fm) +
3100 (sizeof(struct fiemap_extent) * fm->fm_extent_count);
3101
3102 if (outbufsz > MAX_STRUCT_SIZE) {
3103 /* We can't fit all the extents into the fixed size buffer.
3104 * Allocate one that is large enough and use it instead.
3105 */
3106 fm = malloc(outbufsz);
3107 if (!fm) {
3108 return -TARGET_ENOMEM;
3109 }
3110 memcpy(fm, buf_temp, sizeof(struct fiemap));
3111 free_fm = 1;
3112 }
3113 ret = get_errno(ioctl(fd, ie->host_cmd, fm));
3114 if (!is_error(ret)) {
3115 target_size_out = target_size_in;
3116 /* An extent_count of 0 means we were only counting the extents
3117 * so there are no structs to copy
3118 */
3119 if (fm->fm_extent_count != 0) {
3120 target_size_out += fm->fm_mapped_extents * extent_size;
3121 }
3122 argptr = lock_user(VERIFY_WRITE, arg, target_size_out, 0);
3123 if (!argptr) {
3124 ret = -TARGET_EFAULT;
3125 } else {
3126 /* Convert the struct fiemap */
3127 thunk_convert(argptr, fm, arg_type, THUNK_TARGET);
3128 if (fm->fm_extent_count != 0) {
3129 p = argptr + target_size_in;
3130 /* ...and then all the struct fiemap_extents */
3131 for (i = 0; i < fm->fm_mapped_extents; i++) {
3132 thunk_convert(p, &fm->fm_extents[i], extent_arg_type,
3133 THUNK_TARGET);
3134 p += extent_size;
3135 }
3136 }
3137 unlock_user(argptr, arg, target_size_out);
3138 }
3139 }
3140 if (free_fm) {
3141 free(fm);
3142 }
3143 return ret;
3144}
dace20dc 3145#endif
285da2b9 3146
059c2f2c
LV
3147static abi_long do_ioctl_ifconf(const IOCTLEntry *ie, uint8_t *buf_temp,
3148 int fd, abi_long cmd, abi_long arg)
3149{
3150 const argtype *arg_type = ie->arg_type;
3151 int target_size;
3152 void *argptr;
3153 int ret;
3154 struct ifconf *host_ifconf;
3155 uint32_t outbufsz;
3156 const argtype ifreq_arg_type[] = { MK_STRUCT(STRUCT_sockaddr_ifreq) };
3157 int target_ifreq_size;
3158 int nb_ifreq;
3159 int free_buf = 0;
3160 int i;
3161 int target_ifc_len;
3162 abi_long target_ifc_buf;
3163 int host_ifc_len;
3164 char *host_ifc_buf;
3165
3166 assert(arg_type[0] == TYPE_PTR);
3167 assert(ie->access == IOC_RW);
3168
3169 arg_type++;
3170 target_size = thunk_type_size(arg_type, 0);
3171
3172 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
3173 if (!argptr)
3174 return -TARGET_EFAULT;
3175 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
3176 unlock_user(argptr, arg, 0);
3177
3178 host_ifconf = (struct ifconf *)(unsigned long)buf_temp;
3179 target_ifc_len = host_ifconf->ifc_len;
3180 target_ifc_buf = (abi_long)(unsigned long)host_ifconf->ifc_buf;
3181
3182 target_ifreq_size = thunk_type_size(ifreq_arg_type, 0);
3183 nb_ifreq = target_ifc_len / target_ifreq_size;
3184 host_ifc_len = nb_ifreq * sizeof(struct ifreq);
3185
3186 outbufsz = sizeof(*host_ifconf) + host_ifc_len;
3187 if (outbufsz > MAX_STRUCT_SIZE) {
3188 /* We can't fit all the extents into the fixed size buffer.
3189 * Allocate one that is large enough and use it instead.
3190 */
3191 host_ifconf = malloc(outbufsz);
3192 if (!host_ifconf) {
3193 return -TARGET_ENOMEM;
3194 }
3195 memcpy(host_ifconf, buf_temp, sizeof(*host_ifconf));
3196 free_buf = 1;
3197 }
3198 host_ifc_buf = (char*)host_ifconf + sizeof(*host_ifconf);
3199
3200 host_ifconf->ifc_len = host_ifc_len;
3201 host_ifconf->ifc_buf = host_ifc_buf;
3202
3203 ret = get_errno(ioctl(fd, ie->host_cmd, host_ifconf));
3204 if (!is_error(ret)) {
3205 /* convert host ifc_len to target ifc_len */
3206
3207 nb_ifreq = host_ifconf->ifc_len / sizeof(struct ifreq);
3208 target_ifc_len = nb_ifreq * target_ifreq_size;
3209 host_ifconf->ifc_len = target_ifc_len;
3210
3211 /* restore target ifc_buf */
3212
3213 host_ifconf->ifc_buf = (char *)(unsigned long)target_ifc_buf;
3214
3215 /* copy struct ifconf to target user */
3216
3217 argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
3218 if (!argptr)
3219 return -TARGET_EFAULT;
3220 thunk_convert(argptr, host_ifconf, arg_type, THUNK_TARGET);
3221 unlock_user(argptr, arg, target_size);
3222
3223 /* copy ifreq[] to target user */
3224
3225 argptr = lock_user(VERIFY_WRITE, target_ifc_buf, target_ifc_len, 0);
3226 for (i = 0; i < nb_ifreq ; i++) {
3227 thunk_convert(argptr + i * target_ifreq_size,
3228 host_ifc_buf + i * sizeof(struct ifreq),
3229 ifreq_arg_type, THUNK_TARGET);
3230 }
3231 unlock_user(argptr, target_ifc_buf, target_ifc_len);
3232 }
3233
3234 if (free_buf) {
3235 free(host_ifconf);
3236 }
3237
3238 return ret;
3239}
3240
9f106a75 3241static IOCTLEntry ioctl_entries[] = {
001faf32 3242#define IOCTL(cmd, access, ...) \
d2ef05bb
PM
3243 { TARGET_ ## cmd, cmd, #cmd, access, 0, { __VA_ARGS__ } },
3244#define IOCTL_SPECIAL(cmd, access, dofn, ...) \
3245 { TARGET_ ## cmd, cmd, #cmd, access, dofn, { __VA_ARGS__ } },
31e31b8a
FB
3246#include "ioctls.h"
3247 { 0, 0, },
3248};
3249
53a5960a 3250/* ??? Implement proper locking for ioctls. */
0da46a6e 3251/* do_ioctl() Must return target values and target errnos. */
992f48a0 3252static abi_long do_ioctl(int fd, abi_long cmd, abi_long arg)
31e31b8a
FB
3253{
3254 const IOCTLEntry *ie;
3255 const argtype *arg_type;
992f48a0 3256 abi_long ret;
31e31b8a 3257 uint8_t buf_temp[MAX_STRUCT_SIZE];
53a5960a
PB
3258 int target_size;
3259 void *argptr;
31e31b8a
FB
3260
3261 ie = ioctl_entries;
3262 for(;;) {
3263 if (ie->target_cmd == 0) {
32407103 3264 gemu_log("Unsupported ioctl: cmd=0x%04lx\n", (long)cmd);
0da46a6e 3265 return -TARGET_ENOSYS;
31e31b8a
FB
3266 }
3267 if (ie->target_cmd == cmd)
3268 break;
3269 ie++;
3270 }
3271 arg_type = ie->arg_type;
9de5e440 3272#if defined(DEBUG)
32407103 3273 gemu_log("ioctl: cmd=0x%04lx (%s)\n", (long)cmd, ie->name);
72f03900 3274#endif
d2ef05bb
PM
3275 if (ie->do_ioctl) {
3276 return ie->do_ioctl(ie, buf_temp, fd, cmd, arg);
3277 }
3278
31e31b8a
FB
3279 switch(arg_type[0]) {
3280 case TYPE_NULL:
3281 /* no argument */
3282 ret = get_errno(ioctl(fd, ie->host_cmd));
3283 break;
3284 case TYPE_PTRVOID:
3285 case TYPE_INT:
3286 /* int argment */
3287 ret = get_errno(ioctl(fd, ie->host_cmd, arg));
3288 break;
3289 case TYPE_PTR:
3290 arg_type++;
53a5960a 3291 target_size = thunk_type_size(arg_type, 0);
31e31b8a
FB
3292 switch(ie->access) {
3293 case IOC_R:
3294 ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
3295 if (!is_error(ret)) {
579a97f7
FB
3296 argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
3297 if (!argptr)
3298 return -TARGET_EFAULT;
53a5960a
PB
3299 thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
3300 unlock_user(argptr, arg, target_size);
31e31b8a
FB
3301 }
3302 break;
3303 case IOC_W:
579a97f7
FB
3304 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
3305 if (!argptr)
3306 return -TARGET_EFAULT;
53a5960a
PB
3307 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
3308 unlock_user(argptr, arg, 0);
31e31b8a
FB
3309 ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
3310 break;
3311 default:
3312 case IOC_RW:
579a97f7
FB
3313 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
3314 if (!argptr)
3315 return -TARGET_EFAULT;
53a5960a
PB
3316 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
3317 unlock_user(argptr, arg, 0);
31e31b8a
FB
3318 ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
3319 if (!is_error(ret)) {
579a97f7
FB
3320 argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
3321 if (!argptr)
3322 return -TARGET_EFAULT;
53a5960a
PB
3323 thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
3324 unlock_user(argptr, arg, target_size);
31e31b8a
FB
3325 }
3326 break;
3327 }
3328 break;
3329 default:
32407103
JM
3330 gemu_log("Unsupported ioctl type: cmd=0x%04lx type=%d\n",
3331 (long)cmd, arg_type[0]);
0da46a6e 3332 ret = -TARGET_ENOSYS;
31e31b8a
FB
3333 break;
3334 }
3335 return ret;
3336}
3337
b39bc503 3338static const bitmask_transtbl iflag_tbl[] = {
31e31b8a
FB
3339 { TARGET_IGNBRK, TARGET_IGNBRK, IGNBRK, IGNBRK },
3340 { TARGET_BRKINT, TARGET_BRKINT, BRKINT, BRKINT },
3341 { TARGET_IGNPAR, TARGET_IGNPAR, IGNPAR, IGNPAR },
3342 { TARGET_PARMRK, TARGET_PARMRK, PARMRK, PARMRK },
3343 { TARGET_INPCK, TARGET_INPCK, INPCK, INPCK },
3344 { TARGET_ISTRIP, TARGET_ISTRIP, ISTRIP, ISTRIP },
3345 { TARGET_INLCR, TARGET_INLCR, INLCR, INLCR },
3346 { TARGET_IGNCR, TARGET_IGNCR, IGNCR, IGNCR },
3347 { TARGET_ICRNL, TARGET_ICRNL, ICRNL, ICRNL },
3348 { TARGET_IUCLC, TARGET_IUCLC, IUCLC, IUCLC },
3349 { TARGET_IXON, TARGET_IXON, IXON, IXON },
3350 { TARGET_IXANY, TARGET_IXANY, IXANY, IXANY },
3351 { TARGET_IXOFF, TARGET_IXOFF, IXOFF, IXOFF },
3352 { TARGET_IMAXBEL, TARGET_IMAXBEL, IMAXBEL, IMAXBEL },
3353 { 0, 0, 0, 0 }
3354};
3355
b39bc503 3356static const bitmask_transtbl oflag_tbl[] = {
31e31b8a
FB
3357 { TARGET_OPOST, TARGET_OPOST, OPOST, OPOST },
3358 { TARGET_OLCUC, TARGET_OLCUC, OLCUC, OLCUC },
3359 { TARGET_ONLCR, TARGET_ONLCR, ONLCR, ONLCR },
3360 { TARGET_OCRNL, TARGET_OCRNL, OCRNL, OCRNL },
3361 { TARGET_ONOCR, TARGET_ONOCR, ONOCR, ONOCR },
3362 { TARGET_ONLRET, TARGET_ONLRET, ONLRET, ONLRET },
3363 { TARGET_OFILL, TARGET_OFILL, OFILL, OFILL },
3364 { TARGET_OFDEL, TARGET_OFDEL, OFDEL, OFDEL },
3365 { TARGET_NLDLY, TARGET_NL0, NLDLY, NL0 },
3366 { TARGET_NLDLY, TARGET_NL1, NLDLY, NL1 },
3367 { TARGET_CRDLY, TARGET_CR0, CRDLY, CR0 },
3368 { TARGET_CRDLY, TARGET_CR1, CRDLY, CR1 },
3369 { TARGET_CRDLY, TARGET_CR2, CRDLY, CR2 },
3370 { TARGET_CRDLY, TARGET_CR3, CRDLY, CR3 },
3371 { TARGET_TABDLY, TARGET_TAB0, TABDLY, TAB0 },
3372 { TARGET_TABDLY, TARGET_TAB1, TABDLY, TAB1 },
3373 { TARGET_TABDLY, TARGET_TAB2, TABDLY, TAB2 },
3374 { TARGET_TABDLY, TARGET_TAB3, TABDLY, TAB3 },
3375 { TARGET_BSDLY, TARGET_BS0, BSDLY, BS0 },
3376 { TARGET_BSDLY, TARGET_BS1, BSDLY, BS1 },
3377 { TARGET_VTDLY, TARGET_VT0, VTDLY, VT0 },
3378 { TARGET_VTDLY, TARGET_VT1, VTDLY, VT1 },
3379 { TARGET_FFDLY, TARGET_FF0, FFDLY, FF0 },
3380 { TARGET_FFDLY, TARGET_FF1, FFDLY, FF1 },
3381 { 0, 0, 0, 0 }
3382};
3383
b39bc503 3384static const bitmask_transtbl cflag_tbl[] = {
31e31b8a
FB
3385 { TARGET_CBAUD, TARGET_B0, CBAUD, B0 },
3386 { TARGET_CBAUD, TARGET_B50, CBAUD, B50 },
3387 { TARGET_CBAUD, TARGET_B75, CBAUD, B75 },
3388 { TARGET_CBAUD, TARGET_B110, CBAUD, B110 },
3389 { TARGET_CBAUD, TARGET_B134, CBAUD, B134 },
3390 { TARGET_CBAUD, TARGET_B150, CBAUD, B150 },
3391 { TARGET_CBAUD, TARGET_B200, CBAUD, B200 },
3392 { TARGET_CBAUD, TARGET_B300, CBAUD, B300 },
3393 { TARGET_CBAUD, TARGET_B600, CBAUD, B600 },
3394 { TARGET_CBAUD, TARGET_B1200, CBAUD, B1200 },
3395 { TARGET_CBAUD, TARGET_B1800, CBAUD, B1800 },
3396 { TARGET_CBAUD, TARGET_B2400, CBAUD, B2400 },
3397 { TARGET_CBAUD, TARGET_B4800, CBAUD, B4800 },
3398 { TARGET_CBAUD, TARGET_B9600, CBAUD, B9600 },
3399 { TARGET_CBAUD, TARGET_B19200, CBAUD, B19200 },
3400 { TARGET_CBAUD, TARGET_B38400, CBAUD, B38400 },
3401 { TARGET_CBAUD, TARGET_B57600, CBAUD, B57600 },
3402 { TARGET_CBAUD, TARGET_B115200, CBAUD, B115200 },
3403 { TARGET_CBAUD, TARGET_B230400, CBAUD, B230400 },
3404 { TARGET_CBAUD, TARGET_B460800, CBAUD, B460800 },
3405 { TARGET_CSIZE, TARGET_CS5, CSIZE, CS5 },
3406 { TARGET_CSIZE, TARGET_CS6, CSIZE, CS6 },
3407 { TARGET_CSIZE, TARGET_CS7, CSIZE, CS7 },
3408 { TARGET_CSIZE, TARGET_CS8, CSIZE, CS8 },
3409 { TARGET_CSTOPB, TARGET_CSTOPB, CSTOPB, CSTOPB },
3410 { TARGET_CREAD, TARGET_CREAD, CREAD, CREAD },
3411 { TARGET_PARENB, TARGET_PARENB, PARENB, PARENB },
3412 { TARGET_PARODD, TARGET_PARODD, PARODD, PARODD },
3413 { TARGET_HUPCL, TARGET_HUPCL, HUPCL, HUPCL },
3414 { TARGET_CLOCAL, TARGET_CLOCAL, CLOCAL, CLOCAL },
3415 { TARGET_CRTSCTS, TARGET_CRTSCTS, CRTSCTS, CRTSCTS },
3416 { 0, 0, 0, 0 }
3417};
3418
b39bc503 3419static const bitmask_transtbl lflag_tbl[] = {
31e31b8a
FB
3420 { TARGET_ISIG, TARGET_ISIG, ISIG, ISIG },
3421 { TARGET_ICANON, TARGET_ICANON, ICANON, ICANON },
3422 { TARGET_XCASE, TARGET_XCASE, XCASE, XCASE },
3423 { TARGET_ECHO, TARGET_ECHO, ECHO, ECHO },
3424 { TARGET_ECHOE, TARGET_ECHOE, ECHOE, ECHOE },
3425 { TARGET_ECHOK, TARGET_ECHOK, ECHOK, ECHOK },
3426 { TARGET_ECHONL, TARGET_ECHONL, ECHONL, ECHONL },
3427 { TARGET_NOFLSH, TARGET_NOFLSH, NOFLSH, NOFLSH },
3428 { TARGET_TOSTOP, TARGET_TOSTOP, TOSTOP, TOSTOP },
3429 { TARGET_ECHOCTL, TARGET_ECHOCTL, ECHOCTL, ECHOCTL },
3430 { TARGET_ECHOPRT, TARGET_ECHOPRT, ECHOPRT, ECHOPRT },
3431 { TARGET_ECHOKE, TARGET_ECHOKE, ECHOKE, ECHOKE },
3432 { TARGET_FLUSHO, TARGET_FLUSHO, FLUSHO, FLUSHO },
3433 { TARGET_PENDIN, TARGET_PENDIN, PENDIN, PENDIN },
3434 { TARGET_IEXTEN, TARGET_IEXTEN, IEXTEN, IEXTEN },
3435 { 0, 0, 0, 0 }
3436};
3437
3438static void target_to_host_termios (void *dst, const void *src)
3439{
3440 struct host_termios *host = dst;
3441 const struct target_termios *target = src;
3b46e624 3442
5fafdf24 3443 host->c_iflag =
31e31b8a 3444 target_to_host_bitmask(tswap32(target->c_iflag), iflag_tbl);
5fafdf24 3445 host->c_oflag =
31e31b8a 3446 target_to_host_bitmask(tswap32(target->c_oflag), oflag_tbl);
5fafdf24 3447 host->c_cflag =
31e31b8a 3448 target_to_host_bitmask(tswap32(target->c_cflag), cflag_tbl);
5fafdf24 3449 host->c_lflag =
31e31b8a
FB
3450 target_to_host_bitmask(tswap32(target->c_lflag), lflag_tbl);
3451 host->c_line = target->c_line;
3b46e624 3452
44607123 3453 memset(host->c_cc, 0, sizeof(host->c_cc));
5fafdf24
TS
3454 host->c_cc[VINTR] = target->c_cc[TARGET_VINTR];
3455 host->c_cc[VQUIT] = target->c_cc[TARGET_VQUIT];
3b46e624 3456 host->c_cc[VERASE] = target->c_cc[TARGET_VERASE];
5fafdf24 3457 host->c_cc[VKILL] = target->c_cc[TARGET_VKILL];
3b46e624 3458 host->c_cc[VEOF] = target->c_cc[TARGET_VEOF];
5fafdf24 3459 host->c_cc[VTIME] = target->c_cc[TARGET_VTIME];
3b46e624 3460 host->c_cc[VMIN] = target->c_cc[TARGET_VMIN];
5fafdf24 3461 host->c_cc[VSWTC] = target->c_cc[TARGET_VSWTC];
3b46e624 3462 host->c_cc[VSTART] = target->c_cc[TARGET_VSTART];
5fafdf24
TS
3463 host->c_cc[VSTOP] = target->c_cc[TARGET_VSTOP];
3464 host->c_cc[VSUSP] = target->c_cc[TARGET_VSUSP];
3b46e624
TS
3465 host->c_cc[VEOL] = target->c_cc[TARGET_VEOL];
3466 host->c_cc[VREPRINT] = target->c_cc[TARGET_VREPRINT];
3467 host->c_cc[VDISCARD] = target->c_cc[TARGET_VDISCARD];
3468 host->c_cc[VWERASE] = target->c_cc[TARGET_VWERASE];
3469 host->c_cc[VLNEXT] = target->c_cc[TARGET_VLNEXT];
5fafdf24 3470 host->c_cc[VEOL2] = target->c_cc[TARGET_VEOL2];
31e31b8a 3471}
3b46e624 3472
31e31b8a
FB
3473static void host_to_target_termios (void *dst, const void *src)
3474{
3475 struct target_termios *target = dst;
3476 const struct host_termios *host = src;
3477
5fafdf24 3478 target->c_iflag =
31e31b8a 3479 tswap32(host_to_target_bitmask(host->c_iflag, iflag_tbl));
5fafdf24 3480 target->c_oflag =
31e31b8a 3481 tswap32(host_to_target_bitmask(host->c_oflag, oflag_tbl));
5fafdf24 3482 target->c_cflag =
31e31b8a 3483 tswap32(host_to_target_bitmask(host->c_cflag, cflag_tbl));
5fafdf24 3484 target->c_lflag =
31e31b8a
FB
3485 tswap32(host_to_target_bitmask(host->c_lflag, lflag_tbl));
3486 target->c_line = host->c_line;
3b46e624 3487
44607123 3488 memset(target->c_cc, 0, sizeof(target->c_cc));
31e31b8a
FB
3489 target->c_cc[TARGET_VINTR] = host->c_cc[VINTR];
3490 target->c_cc[TARGET_VQUIT] = host->c_cc[VQUIT];
3491 target->c_cc[TARGET_VERASE] = host->c_cc[VERASE];
3492 target->c_cc[TARGET_VKILL] = host->c_cc[VKILL];
3493 target->c_cc[TARGET_VEOF] = host->c_cc[VEOF];
3494 target->c_cc[TARGET_VTIME] = host->c_cc[VTIME];
3495 target->c_cc[TARGET_VMIN] = host->c_cc[VMIN];
3496 target->c_cc[TARGET_VSWTC] = host->c_cc[VSWTC];
3497 target->c_cc[TARGET_VSTART] = host->c_cc[VSTART];
3498 target->c_cc[TARGET_VSTOP] = host->c_cc[VSTOP];
3499 target->c_cc[TARGET_VSUSP] = host->c_cc[VSUSP];
3500 target->c_cc[TARGET_VEOL] = host->c_cc[VEOL];
3501 target->c_cc[TARGET_VREPRINT] = host->c_cc[VREPRINT];
3502 target->c_cc[TARGET_VDISCARD] = host->c_cc[VDISCARD];
3503 target->c_cc[TARGET_VWERASE] = host->c_cc[VWERASE];
3504 target->c_cc[TARGET_VLNEXT] = host->c_cc[VLNEXT];
3505 target->c_cc[TARGET_VEOL2] = host->c_cc[VEOL2];
3506}
3507
8e853dc7 3508static const StructEntry struct_termios_def = {
31e31b8a
FB
3509 .convert = { host_to_target_termios, target_to_host_termios },
3510 .size = { sizeof(struct target_termios), sizeof(struct host_termios) },
3511 .align = { __alignof__(struct target_termios), __alignof__(struct host_termios) },
3512};
3513
5286db75
FB
3514static bitmask_transtbl mmap_flags_tbl[] = {
3515 { TARGET_MAP_SHARED, TARGET_MAP_SHARED, MAP_SHARED, MAP_SHARED },
3516 { TARGET_MAP_PRIVATE, TARGET_MAP_PRIVATE, MAP_PRIVATE, MAP_PRIVATE },
3517 { TARGET_MAP_FIXED, TARGET_MAP_FIXED, MAP_FIXED, MAP_FIXED },
3518 { TARGET_MAP_ANONYMOUS, TARGET_MAP_ANONYMOUS, MAP_ANONYMOUS, MAP_ANONYMOUS },
3519 { TARGET_MAP_GROWSDOWN, TARGET_MAP_GROWSDOWN, MAP_GROWSDOWN, MAP_GROWSDOWN },
3520 { TARGET_MAP_DENYWRITE, TARGET_MAP_DENYWRITE, MAP_DENYWRITE, MAP_DENYWRITE },
3521 { TARGET_MAP_EXECUTABLE, TARGET_MAP_EXECUTABLE, MAP_EXECUTABLE, MAP_EXECUTABLE },
3522 { TARGET_MAP_LOCKED, TARGET_MAP_LOCKED, MAP_LOCKED, MAP_LOCKED },
3523 { 0, 0, 0, 0 }
3524};
3525
2ab83ea7 3526#if defined(TARGET_I386)
6dbad63e
FB
3527
3528/* NOTE: there is really one LDT for all the threads */
b1d8e52e 3529static uint8_t *ldt_table;
6dbad63e 3530
03acab66 3531static abi_long read_ldt(abi_ulong ptr, unsigned long bytecount)
6dbad63e
FB
3532{
3533 int size;
53a5960a 3534 void *p;
6dbad63e
FB
3535
3536 if (!ldt_table)
3537 return 0;
3538 size = TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE;
3539 if (size > bytecount)
3540 size = bytecount;
579a97f7
FB
3541 p = lock_user(VERIFY_WRITE, ptr, size, 0);
3542 if (!p)
03acab66 3543 return -TARGET_EFAULT;
579a97f7 3544 /* ??? Should this by byteswapped? */
53a5960a
PB
3545 memcpy(p, ldt_table, size);
3546 unlock_user(p, ptr, size);
6dbad63e
FB
3547 return size;
3548}
3549
3550/* XXX: add locking support */
03acab66
FB
3551static abi_long write_ldt(CPUX86State *env,
3552 abi_ulong ptr, unsigned long bytecount, int oldmode)
6dbad63e
FB
3553{
3554 struct target_modify_ldt_ldt_s ldt_info;
53a5960a 3555 struct target_modify_ldt_ldt_s *target_ldt_info;
6dbad63e 3556 int seg_32bit, contents, read_exec_only, limit_in_pages;
8d18e893 3557 int seg_not_present, useable, lm;
6dbad63e
FB
3558 uint32_t *lp, entry_1, entry_2;
3559
3560 if (bytecount != sizeof(ldt_info))
03acab66 3561 return -TARGET_EINVAL;
579a97f7 3562 if (!lock_user_struct(VERIFY_READ, target_ldt_info, ptr, 1))
03acab66 3563 return -TARGET_EFAULT;
53a5960a
PB
3564 ldt_info.entry_number = tswap32(target_ldt_info->entry_number);
3565 ldt_info.base_addr = tswapl(target_ldt_info->base_addr);
3566 ldt_info.limit = tswap32(target_ldt_info->limit);
3567 ldt_info.flags = tswap32(target_ldt_info->flags);
3568 unlock_user_struct(target_ldt_info, ptr, 0);
3b46e624 3569
6dbad63e 3570 if (ldt_info.entry_number >= TARGET_LDT_ENTRIES)
03acab66 3571 return -TARGET_EINVAL;
6dbad63e
FB
3572 seg_32bit = ldt_info.flags & 1;
3573 contents = (ldt_info.flags >> 1) & 3;
3574 read_exec_only = (ldt_info.flags >> 3) & 1;
3575 limit_in_pages = (ldt_info.flags >> 4) & 1;
3576 seg_not_present = (ldt_info.flags >> 5) & 1;
3577 useable = (ldt_info.flags >> 6) & 1;
8d18e893
FB
3578#ifdef TARGET_ABI32
3579 lm = 0;
3580#else
3581 lm = (ldt_info.flags >> 7) & 1;
3582#endif
6dbad63e
FB
3583 if (contents == 3) {
3584 if (oldmode)
03acab66 3585 return -TARGET_EINVAL;
6dbad63e 3586 if (seg_not_present == 0)
03acab66 3587 return -TARGET_EINVAL;
6dbad63e
FB
3588 }
3589 /* allocate the LDT */
3590 if (!ldt_table) {
e441570f
AZ
3591 env->ldt.base = target_mmap(0,
3592 TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE,
3593 PROT_READ|PROT_WRITE,
3594 MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
3595 if (env->ldt.base == -1)
03acab66 3596 return -TARGET_ENOMEM;
e441570f
AZ
3597 memset(g2h(env->ldt.base), 0,
3598 TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE);
6dbad63e 3599 env->ldt.limit = 0xffff;
e441570f 3600 ldt_table = g2h(env->ldt.base);
6dbad63e
FB
3601 }
3602
3603 /* NOTE: same code as Linux kernel */
3604 /* Allow LDTs to be cleared by the user. */
3605 if (ldt_info.base_addr == 0 && ldt_info.limit == 0) {
3606 if (oldmode ||
3607 (contents == 0 &&
3608 read_exec_only == 1 &&
3609 seg_32bit == 0 &&
3610 limit_in_pages == 0 &&
3611 seg_not_present == 1 &&
3612 useable == 0 )) {
3613 entry_1 = 0;
3614 entry_2 = 0;
3615 goto install;
3616 }
3617 }
3b46e624 3618
6dbad63e
FB
3619 entry_1 = ((ldt_info.base_addr & 0x0000ffff) << 16) |
3620 (ldt_info.limit & 0x0ffff);
3621 entry_2 = (ldt_info.base_addr & 0xff000000) |
3622 ((ldt_info.base_addr & 0x00ff0000) >> 16) |
3623 (ldt_info.limit & 0xf0000) |
3624 ((read_exec_only ^ 1) << 9) |
3625 (contents << 10) |
3626 ((seg_not_present ^ 1) << 15) |
3627 (seg_32bit << 22) |
3628 (limit_in_pages << 23) |
8d18e893 3629 (lm << 21) |
6dbad63e
FB
3630 0x7000;
3631 if (!oldmode)
3632 entry_2 |= (useable << 20);
14ae3ba7 3633
6dbad63e
FB
3634 /* Install the new entry ... */
3635install:
3636 lp = (uint32_t *)(ldt_table + (ldt_info.entry_number << 3));
3637 lp[0] = tswap32(entry_1);
3638 lp[1] = tswap32(entry_2);
3639 return 0;
3640}
3641
3642/* specific and weird i386 syscalls */
8fcd3692
BS
3643static abi_long do_modify_ldt(CPUX86State *env, int func, abi_ulong ptr,
3644 unsigned long bytecount)
6dbad63e 3645{
03acab66 3646 abi_long ret;
3b46e624 3647
6dbad63e
FB
3648 switch (func) {
3649 case 0:
3650 ret = read_ldt(ptr, bytecount);
3651 break;
3652 case 1:
3653 ret = write_ldt(env, ptr, bytecount, 1);
3654 break;
3655 case 0x11:
3656 ret = write_ldt(env, ptr, bytecount, 0);
3657 break;
03acab66
FB
3658 default:
3659 ret = -TARGET_ENOSYS;
3660 break;
6dbad63e
FB
3661 }
3662 return ret;
3663}
1b6b029e 3664
4583f589 3665#if defined(TARGET_I386) && defined(TARGET_ABI32)
8fcd3692 3666static abi_long do_set_thread_area(CPUX86State *env, abi_ulong ptr)
8d18e893
FB
3667{
3668 uint64_t *gdt_table = g2h(env->gdt.base);
3669 struct target_modify_ldt_ldt_s ldt_info;
3670 struct target_modify_ldt_ldt_s *target_ldt_info;
3671 int seg_32bit, contents, read_exec_only, limit_in_pages;
3672 int seg_not_present, useable, lm;
3673 uint32_t *lp, entry_1, entry_2;
3674 int i;
3675
3676 lock_user_struct(VERIFY_WRITE, target_ldt_info, ptr, 1);
3677 if (!target_ldt_info)
3678 return -TARGET_EFAULT;
3679 ldt_info.entry_number = tswap32(target_ldt_info->entry_number);
3680 ldt_info.base_addr = tswapl(target_ldt_info->base_addr);
3681 ldt_info.limit = tswap32(target_ldt_info->limit);
3682 ldt_info.flags = tswap32(target_ldt_info->flags);
3683 if (ldt_info.entry_number == -1) {
3684 for (i=TARGET_GDT_ENTRY_TLS_MIN; i<=TARGET_GDT_ENTRY_TLS_MAX; i++) {
3685 if (gdt_table[i] == 0) {
3686 ldt_info.entry_number = i;
3687 target_ldt_info->entry_number = tswap32(i);
3688 break;
3689 }
3690 }
3691 }
3692 unlock_user_struct(target_ldt_info, ptr, 1);
3693
3694 if (ldt_info.entry_number < TARGET_GDT_ENTRY_TLS_MIN ||
3695 ldt_info.entry_number > TARGET_GDT_ENTRY_TLS_MAX)
3696 return -TARGET_EINVAL;
3697 seg_32bit = ldt_info.flags & 1;
3698 contents = (ldt_info.flags >> 1) & 3;
3699 read_exec_only = (ldt_info.flags >> 3) & 1;
3700 limit_in_pages = (ldt_info.flags >> 4) & 1;
3701 seg_not_present = (ldt_info.flags >> 5) & 1;
3702 useable = (ldt_info.flags >> 6) & 1;
3703#ifdef TARGET_ABI32
3704 lm = 0;
3705#else
3706 lm = (ldt_info.flags >> 7) & 1;
3707#endif
3708
3709 if (contents == 3) {
3710 if (seg_not_present == 0)
3711 return -TARGET_EINVAL;
3712 }
3713
3714 /* NOTE: same code as Linux kernel */
3715 /* Allow LDTs to be cleared by the user. */
3716 if (ldt_info.base_addr == 0 && ldt_info.limit == 0) {
3717 if ((contents == 0 &&
3718 read_exec_only == 1 &&
3719 seg_32bit == 0 &&
3720 limit_in_pages == 0 &&
3721 seg_not_present == 1 &&
3722 useable == 0 )) {
3723 entry_1 = 0;
3724 entry_2 = 0;
3725 goto install;
3726 }
3727 }
3728
3729 entry_1 = ((ldt_info.base_addr & 0x0000ffff) << 16) |
3730 (ldt_info.limit & 0x0ffff);
3731 entry_2 = (ldt_info.base_addr & 0xff000000) |
3732 ((ldt_info.base_addr & 0x00ff0000) >> 16) |
3733 (ldt_info.limit & 0xf0000) |
3734 ((read_exec_only ^ 1) << 9) |
3735 (contents << 10) |
3736 ((seg_not_present ^ 1) << 15) |
3737 (seg_32bit << 22) |
3738 (limit_in_pages << 23) |
3739 (useable << 20) |
3740 (lm << 21) |
3741 0x7000;
3742
3743 /* Install the new entry ... */
3744install:
3745 lp = (uint32_t *)(gdt_table + ldt_info.entry_number);
3746 lp[0] = tswap32(entry_1);
3747 lp[1] = tswap32(entry_2);
3748 return 0;
3749}
3750
8fcd3692 3751static abi_long do_get_thread_area(CPUX86State *env, abi_ulong ptr)
8d18e893
FB
3752{
3753 struct target_modify_ldt_ldt_s *target_ldt_info;
3754 uint64_t *gdt_table = g2h(env->gdt.base);
3755 uint32_t base_addr, limit, flags;
3756 int seg_32bit, contents, read_exec_only, limit_in_pages, idx;
3757 int seg_not_present, useable, lm;
3758 uint32_t *lp, entry_1, entry_2;
3759
3760 lock_user_struct(VERIFY_WRITE, target_ldt_info, ptr, 1);
3761 if (!target_ldt_info)
3762 return -TARGET_EFAULT;
3763 idx = tswap32(target_ldt_info->entry_number);
3764 if (idx < TARGET_GDT_ENTRY_TLS_MIN ||
3765 idx > TARGET_GDT_ENTRY_TLS_MAX) {
3766 unlock_user_struct(target_ldt_info, ptr, 1);
3767 return -TARGET_EINVAL;
3768 }
3769 lp = (uint32_t *)(gdt_table + idx);
3770 entry_1 = tswap32(lp[0]);
3771 entry_2 = tswap32(lp[1]);
3772
3773 read_exec_only = ((entry_2 >> 9) & 1) ^ 1;
3774 contents = (entry_2 >> 10) & 3;
3775 seg_not_present = ((entry_2 >> 15) & 1) ^ 1;
3776 seg_32bit = (entry_2 >> 22) & 1;
3777 limit_in_pages = (entry_2 >> 23) & 1;
3778 useable = (entry_2 >> 20) & 1;
3779#ifdef TARGET_ABI32
3780 lm = 0;
3781#else
3782 lm = (entry_2 >> 21) & 1;
3783#endif
3784 flags = (seg_32bit << 0) | (contents << 1) |
3785 (read_exec_only << 3) | (limit_in_pages << 4) |
3786 (seg_not_present << 5) | (useable << 6) | (lm << 7);
3787 limit = (entry_1 & 0xffff) | (entry_2 & 0xf0000);
3788 base_addr = (entry_1 >> 16) |
3789 (entry_2 & 0xff000000) |
3790 ((entry_2 & 0xff) << 16);
3791 target_ldt_info->base_addr = tswapl(base_addr);
3792 target_ldt_info->limit = tswap32(limit);
3793 target_ldt_info->flags = tswap32(flags);
3794 unlock_user_struct(target_ldt_info, ptr, 1);
3795 return 0;
3796}
4583f589 3797#endif /* TARGET_I386 && TARGET_ABI32 */
8d18e893 3798
d2fd1af7 3799#ifndef TARGET_ABI32
8fcd3692 3800static abi_long do_arch_prctl(CPUX86State *env, int code, abi_ulong addr)
d2fd1af7 3801{
1add8698 3802 abi_long ret = 0;
d2fd1af7
FB
3803 abi_ulong val;
3804 int idx;
1add8698 3805
d2fd1af7
FB
3806 switch(code) {
3807 case TARGET_ARCH_SET_GS:
3808 case TARGET_ARCH_SET_FS:
3809 if (code == TARGET_ARCH_SET_GS)
3810 idx = R_GS;
3811 else
3812 idx = R_FS;
3813 cpu_x86_load_seg(env, idx, 0);
3814 env->segs[idx].base = addr;
3815 break;
3816 case TARGET_ARCH_GET_GS:
3817 case TARGET_ARCH_GET_FS:
3818 if (code == TARGET_ARCH_GET_GS)
3819 idx = R_GS;
3820 else
3821 idx = R_FS;
3822 val = env->segs[idx].base;
3823 if (put_user(val, addr, abi_ulong))
1add8698 3824 ret = -TARGET_EFAULT;
d2fd1af7
FB
3825 break;
3826 default:
3827 ret = -TARGET_EINVAL;
3828 break;
3829 }
1add8698 3830 return ret;
d2fd1af7
FB
3831}
3832#endif
3833
2ab83ea7
FB
3834#endif /* defined(TARGET_I386) */
3835
05098a93 3836#define NEW_STACK_SIZE 0x40000
d865bab5 3837
05098a93 3838#if defined(CONFIG_USE_NPTL)
d865bab5
PB
3839
3840static pthread_mutex_t clone_lock = PTHREAD_MUTEX_INITIALIZER;
3841typedef struct {
3842 CPUState *env;
3843 pthread_mutex_t mutex;
3844 pthread_cond_t cond;
3845 pthread_t thread;
3846 uint32_t tid;
3847 abi_ulong child_tidptr;
3848 abi_ulong parent_tidptr;
3849 sigset_t sigmask;
3850} new_thread_info;
3851
3852static void *clone_func(void *arg)
3853{
3854 new_thread_info *info = arg;
3855 CPUState *env;
edf8e2af 3856 TaskState *ts;
d865bab5
PB
3857
3858 env = info->env;
3859 thread_env = env;
edf8e2af 3860 ts = (TaskState *)thread_env->opaque;
d865bab5 3861 info->tid = gettid();
1e9fa730 3862 env->host_tid = info->tid;
edf8e2af 3863 task_settid(ts);
d865bab5
PB
3864 if (info->child_tidptr)
3865 put_user_u32(info->tid, info->child_tidptr);
3866 if (info->parent_tidptr)
3867 put_user_u32(info->tid, info->parent_tidptr);
3868 /* Enable signals. */
3869 sigprocmask(SIG_SETMASK, &info->sigmask, NULL);
3870 /* Signal to the parent that we're ready. */
3871 pthread_mutex_lock(&info->mutex);
3872 pthread_cond_broadcast(&info->cond);
3873 pthread_mutex_unlock(&info->mutex);
3874 /* Wait until the parent has finshed initializing the tls state. */
3875 pthread_mutex_lock(&clone_lock);
3876 pthread_mutex_unlock(&clone_lock);
3877 cpu_loop(env);
3878 /* never exits */
3879 return NULL;
3880}
3881#else
1b6b029e
FB
3882
3883static int clone_func(void *arg)
3884{
2ab83ea7 3885 CPUState *env = arg;
1b6b029e
FB
3886 cpu_loop(env);
3887 /* never exits */
3888 return 0;
3889}
d865bab5 3890#endif
1b6b029e 3891
0da46a6e
TS
3892/* do_fork() Must return host values and target errnos (unlike most
3893 do_*() functions). */
d865bab5
PB
3894static int do_fork(CPUState *env, unsigned int flags, abi_ulong newsp,
3895 abi_ulong parent_tidptr, target_ulong newtls,
3896 abi_ulong child_tidptr)
1b6b029e
FB
3897{
3898 int ret;
5cd4393b 3899 TaskState *ts;
2ab83ea7 3900 CPUState *new_env;
2f7bb878 3901#if defined(CONFIG_USE_NPTL)
d865bab5
PB
3902 unsigned int nptl_flags;
3903 sigset_t sigmask;
9190749f
RV
3904#else
3905 uint8_t *new_stack;
d865bab5 3906#endif
3b46e624 3907
436d124b
AZ
3908 /* Emulate vfork() with fork() */
3909 if (flags & CLONE_VFORK)
3910 flags &= ~(CLONE_VFORK | CLONE_VM);
3911
1b6b029e 3912 if (flags & CLONE_VM) {
edf8e2af 3913 TaskState *parent_ts = (TaskState *)env->opaque;
2f7bb878 3914#if defined(CONFIG_USE_NPTL)
d865bab5
PB
3915 new_thread_info info;
3916 pthread_attr_t attr;
bd0c5661 3917#endif
48e15fc2 3918 ts = qemu_mallocz(sizeof(TaskState));
624f7979 3919 init_task_state(ts);
1b6b029e 3920 /* we create a new CPU instance. */
c5be9f08 3921 new_env = cpu_copy(env);
b4558d74
BS
3922#if defined(TARGET_I386) || defined(TARGET_SPARC) || defined(TARGET_PPC)
3923 cpu_reset(new_env);
3924#endif
6e68e076
PB
3925 /* Init regs that differ from the parent. */
3926 cpu_clone_regs(new_env, newsp);
5cd4393b 3927 new_env->opaque = ts;
edf8e2af
MW
3928 ts->bprm = parent_ts->bprm;
3929 ts->info = parent_ts->info;
2f7bb878 3930#if defined(CONFIG_USE_NPTL)
d865bab5
PB
3931 nptl_flags = flags;
3932 flags &= ~CLONE_NPTL_FLAGS2;
3933
c2764719
PB
3934 if (nptl_flags & CLONE_CHILD_CLEARTID) {
3935 ts->child_tidptr = child_tidptr;
3936 }
3937
d865bab5
PB
3938 if (nptl_flags & CLONE_SETTLS)
3939 cpu_set_tls (new_env, newtls);
3940
3941 /* Grab a mutex so that thread setup appears atomic. */
3942 pthread_mutex_lock(&clone_lock);
3943
3944 memset(&info, 0, sizeof(info));
3945 pthread_mutex_init(&info.mutex, NULL);
3946 pthread_mutex_lock(&info.mutex);
3947 pthread_cond_init(&info.cond, NULL);
3948 info.env = new_env;
3949 if (nptl_flags & CLONE_CHILD_SETTID)
3950 info.child_tidptr = child_tidptr;
3951 if (nptl_flags & CLONE_PARENT_SETTID)
3952 info.parent_tidptr = parent_tidptr;
3953
3954 ret = pthread_attr_init(&attr);
48e15fc2
NF
3955 ret = pthread_attr_setstacksize(&attr, NEW_STACK_SIZE);
3956 ret = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
d865bab5
PB
3957 /* It is not safe to deliver signals until the child has finished
3958 initializing, so temporarily block all signals. */
3959 sigfillset(&sigmask);
3960 sigprocmask(SIG_BLOCK, &sigmask, &info.sigmask);
3961
3962 ret = pthread_create(&info.thread, &attr, clone_func, &info);
c2764719 3963 /* TODO: Free new CPU state if thread creation failed. */
d865bab5
PB
3964
3965 sigprocmask(SIG_SETMASK, &info.sigmask, NULL);
3966 pthread_attr_destroy(&attr);
3967 if (ret == 0) {
3968 /* Wait for the child to initialize. */
3969 pthread_cond_wait(&info.cond, &info.mutex);
3970 ret = info.tid;
3971 if (flags & CLONE_PARENT_SETTID)
3972 put_user_u32(ret, parent_tidptr);
3973 } else {
3974 ret = -1;
3975 }
3976 pthread_mutex_unlock(&info.mutex);
3977 pthread_cond_destroy(&info.cond);
3978 pthread_mutex_destroy(&info.mutex);
3979 pthread_mutex_unlock(&clone_lock);
3980#else
3981 if (flags & CLONE_NPTL_FLAGS2)
3982 return -EINVAL;
3983 /* This is probably going to die very quickly, but do it anyway. */
48e15fc2 3984 new_stack = qemu_mallocz (NEW_STACK_SIZE);
27725c1d 3985#ifdef __ia64__
60e99246 3986 ret = __clone2(clone_func, new_stack, NEW_STACK_SIZE, flags, new_env);
27725c1d
FB
3987#else
3988 ret = clone(clone_func, new_stack + NEW_STACK_SIZE, flags, new_env);
d865bab5 3989#endif
27725c1d 3990#endif
1b6b029e
FB
3991 } else {
3992 /* if no CLONE_VM, we consider it is a fork */
d865bab5 3993 if ((flags & ~(CSIGNAL | CLONE_NPTL_FLAGS2)) != 0)
1b6b029e 3994 return -EINVAL;
d865bab5 3995 fork_start();
1b6b029e 3996 ret = fork();
d865bab5 3997 if (ret == 0) {
2b1319c8 3998 /* Child Process. */
d865bab5
PB
3999 cpu_clone_regs(env, newsp);
4000 fork_end(1);
2f7bb878 4001#if defined(CONFIG_USE_NPTL)
2b1319c8
AJ
4002 /* There is a race condition here. The parent process could
4003 theoretically read the TID in the child process before the child
4004 tid is set. This would require using either ptrace
4005 (not implemented) or having *_tidptr to point at a shared memory
4006 mapping. We can't repeat the spinlock hack used above because
4007 the child process gets its own copy of the lock. */
d865bab5
PB
4008 if (flags & CLONE_CHILD_SETTID)
4009 put_user_u32(gettid(), child_tidptr);
4010 if (flags & CLONE_PARENT_SETTID)
4011 put_user_u32(gettid(), parent_tidptr);
4012 ts = (TaskState *)env->opaque;
4013 if (flags & CLONE_SETTLS)
4014 cpu_set_tls (env, newtls);
c2764719
PB
4015 if (flags & CLONE_CHILD_CLEARTID)
4016 ts->child_tidptr = child_tidptr;
2b1319c8 4017#endif
d865bab5
PB
4018 } else {
4019 fork_end(0);
4020 }
1b6b029e
FB
4021 }
4022 return ret;
4023}
4024
5f106811
APR
4025/* warning : doesn't handle linux specific flags... */
4026static int target_to_host_fcntl_cmd(int cmd)
4027{
4028 switch(cmd) {
4029 case TARGET_F_DUPFD:
4030 case TARGET_F_GETFD:
4031 case TARGET_F_SETFD:
4032 case TARGET_F_GETFL:
4033 case TARGET_F_SETFL:
4034 return cmd;
4035 case TARGET_F_GETLK:
4036 return F_GETLK;
4037 case TARGET_F_SETLK:
4038 return F_SETLK;
4039 case TARGET_F_SETLKW:
4040 return F_SETLKW;
4041 case TARGET_F_GETOWN:
4042 return F_GETOWN;
4043 case TARGET_F_SETOWN:
4044 return F_SETOWN;
4045 case TARGET_F_GETSIG:
4046 return F_GETSIG;
4047 case TARGET_F_SETSIG:
4048 return F_SETSIG;
4049#if TARGET_ABI_BITS == 32
4050 case TARGET_F_GETLK64:
4051 return F_GETLK64;
4052 case TARGET_F_SETLK64:
4053 return F_SETLK64;
4054 case TARGET_F_SETLKW64:
4055 return F_SETLKW64;
4056#endif
7e22e546
UH
4057 case TARGET_F_SETLEASE:
4058 return F_SETLEASE;
4059 case TARGET_F_GETLEASE:
4060 return F_GETLEASE;
fbd5de9b 4061#ifdef F_DUPFD_CLOEXEC
7e22e546
UH
4062 case TARGET_F_DUPFD_CLOEXEC:
4063 return F_DUPFD_CLOEXEC;
fbd5de9b 4064#endif
7e22e546
UH
4065 case TARGET_F_NOTIFY:
4066 return F_NOTIFY;
5f106811
APR
4067 default:
4068 return -TARGET_EINVAL;
4069 }
4070 return -TARGET_EINVAL;
4071}
4072
992f48a0 4073static abi_long do_fcntl(int fd, int cmd, abi_ulong arg)
7775e9ec
FB
4074{
4075 struct flock fl;
53a5960a 4076 struct target_flock *target_fl;
43f238d7
TS
4077 struct flock64 fl64;
4078 struct target_flock64 *target_fl64;
992f48a0 4079 abi_long ret;
5f106811
APR
4080 int host_cmd = target_to_host_fcntl_cmd(cmd);
4081
4082 if (host_cmd == -TARGET_EINVAL)
4083 return host_cmd;
53a5960a 4084
7775e9ec
FB
4085 switch(cmd) {
4086 case TARGET_F_GETLK:
579a97f7
FB
4087 if (!lock_user_struct(VERIFY_READ, target_fl, arg, 1))
4088 return -TARGET_EFAULT;
5813427b
TS
4089 fl.l_type = tswap16(target_fl->l_type);
4090 fl.l_whence = tswap16(target_fl->l_whence);
4091 fl.l_start = tswapl(target_fl->l_start);
4092 fl.l_len = tswapl(target_fl->l_len);
7e22e546 4093 fl.l_pid = tswap32(target_fl->l_pid);
5813427b 4094 unlock_user_struct(target_fl, arg, 0);
5f106811 4095 ret = get_errno(fcntl(fd, host_cmd, &fl));
7775e9ec 4096 if (ret == 0) {
579a97f7
FB
4097 if (!lock_user_struct(VERIFY_WRITE, target_fl, arg, 0))
4098 return -TARGET_EFAULT;
7775e9ec
FB
4099 target_fl->l_type = tswap16(fl.l_type);
4100 target_fl->l_whence = tswap16(fl.l_whence);
4101 target_fl->l_start = tswapl(fl.l_start);
4102 target_fl->l_len = tswapl(fl.l_len);
7e22e546 4103 target_fl->l_pid = tswap32(fl.l_pid);
53a5960a 4104 unlock_user_struct(target_fl, arg, 1);
7775e9ec
FB
4105 }
4106 break;
3b46e624 4107
7775e9ec
FB
4108 case TARGET_F_SETLK:
4109 case TARGET_F_SETLKW:
579a97f7
FB
4110 if (!lock_user_struct(VERIFY_READ, target_fl, arg, 1))
4111 return -TARGET_EFAULT;
7775e9ec
FB
4112 fl.l_type = tswap16(target_fl->l_type);
4113 fl.l_whence = tswap16(target_fl->l_whence);
4114 fl.l_start = tswapl(target_fl->l_start);
4115 fl.l_len = tswapl(target_fl->l_len);
7e22e546 4116 fl.l_pid = tswap32(target_fl->l_pid);
53a5960a 4117 unlock_user_struct(target_fl, arg, 0);
5f106811 4118 ret = get_errno(fcntl(fd, host_cmd, &fl));
7775e9ec 4119 break;
3b46e624 4120
7775e9ec 4121 case TARGET_F_GETLK64:
579a97f7
FB
4122 if (!lock_user_struct(VERIFY_READ, target_fl64, arg, 1))
4123 return -TARGET_EFAULT;
5813427b
TS
4124 fl64.l_type = tswap16(target_fl64->l_type) >> 1;
4125 fl64.l_whence = tswap16(target_fl64->l_whence);
4126 fl64.l_start = tswapl(target_fl64->l_start);
4127 fl64.l_len = tswapl(target_fl64->l_len);
7e22e546 4128 fl64.l_pid = tswap32(target_fl64->l_pid);
5813427b 4129 unlock_user_struct(target_fl64, arg, 0);
5f106811 4130 ret = get_errno(fcntl(fd, host_cmd, &fl64));
43f238d7 4131 if (ret == 0) {
579a97f7
FB
4132 if (!lock_user_struct(VERIFY_WRITE, target_fl64, arg, 0))
4133 return -TARGET_EFAULT;
43f238d7
TS
4134 target_fl64->l_type = tswap16(fl64.l_type) >> 1;
4135 target_fl64->l_whence = tswap16(fl64.l_whence);
4136 target_fl64->l_start = tswapl(fl64.l_start);
4137 target_fl64->l_len = tswapl(fl64.l_len);
7e22e546 4138 target_fl64->l_pid = tswap32(fl64.l_pid);
43f238d7
TS
4139 unlock_user_struct(target_fl64, arg, 1);
4140 }
9ee1fa2c 4141 break;
7775e9ec
FB
4142 case TARGET_F_SETLK64:
4143 case TARGET_F_SETLKW64:
579a97f7
FB
4144 if (!lock_user_struct(VERIFY_READ, target_fl64, arg, 1))
4145 return -TARGET_EFAULT;
43f238d7
TS
4146 fl64.l_type = tswap16(target_fl64->l_type) >> 1;
4147 fl64.l_whence = tswap16(target_fl64->l_whence);
4148 fl64.l_start = tswapl(target_fl64->l_start);
4149 fl64.l_len = tswapl(target_fl64->l_len);
7e22e546 4150 fl64.l_pid = tswap32(target_fl64->l_pid);
43f238d7 4151 unlock_user_struct(target_fl64, arg, 0);
5f106811 4152 ret = get_errno(fcntl(fd, host_cmd, &fl64));
7775e9ec
FB
4153 break;
4154
5f106811
APR
4155 case TARGET_F_GETFL:
4156 ret = get_errno(fcntl(fd, host_cmd, arg));
9ee1fa2c
FB
4157 if (ret >= 0) {
4158 ret = host_to_target_bitmask(ret, fcntl_flags_tbl);
4159 }
ffa65c3b
FB
4160 break;
4161
5f106811
APR
4162 case TARGET_F_SETFL:
4163 ret = get_errno(fcntl(fd, host_cmd, target_to_host_bitmask(arg, fcntl_flags_tbl)));
4164 break;
4165
4166 case TARGET_F_SETOWN:
4167 case TARGET_F_GETOWN:
4168 case TARGET_F_SETSIG:
4169 case TARGET_F_GETSIG:
7e22e546
UH
4170 case TARGET_F_SETLEASE:
4171 case TARGET_F_GETLEASE:
5f106811 4172 ret = get_errno(fcntl(fd, host_cmd, arg));
ffa65c3b
FB
4173 break;
4174
7775e9ec 4175 default:
9ee1fa2c 4176 ret = get_errno(fcntl(fd, cmd, arg));
7775e9ec
FB
4177 break;
4178 }
4179 return ret;
4180}
4181
67867308 4182#ifdef USE_UID16
7775e9ec 4183
67867308
FB
4184static inline int high2lowuid(int uid)
4185{
4186 if (uid > 65535)
4187 return 65534;
4188 else
4189 return uid;
4190}
4191
4192static inline int high2lowgid(int gid)
4193{
4194 if (gid > 65535)
4195 return 65534;
4196 else
4197 return gid;
4198}
4199
4200static inline int low2highuid(int uid)
4201{
4202 if ((int16_t)uid == -1)
4203 return -1;
4204 else
4205 return uid;
4206}
4207
4208static inline int low2highgid(int gid)
4209{
4210 if ((int16_t)gid == -1)
4211 return -1;
4212 else
4213 return gid;
4214}
0c866a7e
RV
4215static inline int tswapid(int id)
4216{
4217 return tswap16(id);
4218}
4219#else /* !USE_UID16 */
4220static inline int high2lowuid(int uid)
4221{
4222 return uid;
4223}
4224static inline int high2lowgid(int gid)
4225{
4226 return gid;
4227}
4228static inline int low2highuid(int uid)
4229{
4230 return uid;
4231}
4232static inline int low2highgid(int gid)
4233{
4234 return gid;
4235}
4236static inline int tswapid(int id)
4237{
4238 return tswap32(id);
4239}
67867308 4240#endif /* USE_UID16 */
1b6b029e 4241
31e31b8a
FB
4242void syscall_init(void)
4243{
2ab83ea7
FB
4244 IOCTLEntry *ie;
4245 const argtype *arg_type;
4246 int size;
b92c47c1 4247 int i;
2ab83ea7 4248
001faf32 4249#define STRUCT(name, ...) thunk_register_struct(STRUCT_ ## name, #name, struct_ ## name ## _def);
5fafdf24 4250#define STRUCT_SPECIAL(name) thunk_register_struct_direct(STRUCT_ ## name, #name, &struct_ ## name ## _def);
31e31b8a
FB
4251#include "syscall_types.h"
4252#undef STRUCT
4253#undef STRUCT_SPECIAL
2ab83ea7
FB
4254
4255 /* we patch the ioctl size if necessary. We rely on the fact that
4256 no ioctl has all the bits at '1' in the size field */
4257 ie = ioctl_entries;
4258 while (ie->target_cmd != 0) {
4259 if (((ie->target_cmd >> TARGET_IOC_SIZESHIFT) & TARGET_IOC_SIZEMASK) ==
4260 TARGET_IOC_SIZEMASK) {
4261 arg_type = ie->arg_type;
4262 if (arg_type[0] != TYPE_PTR) {
5fafdf24 4263 fprintf(stderr, "cannot patch size for ioctl 0x%x\n",
2ab83ea7
FB
4264 ie->target_cmd);
4265 exit(1);
4266 }
4267 arg_type++;
4268 size = thunk_type_size(arg_type, 0);
5fafdf24 4269 ie->target_cmd = (ie->target_cmd &
2ab83ea7
FB
4270 ~(TARGET_IOC_SIZEMASK << TARGET_IOC_SIZESHIFT)) |
4271 (size << TARGET_IOC_SIZESHIFT);
4272 }
b92c47c1
TS
4273
4274 /* Build target_to_host_errno_table[] table from
4275 * host_to_target_errno_table[]. */
4276 for (i=0; i < ERRNO_TABLE_SIZE; i++)
4277 target_to_host_errno_table[host_to_target_errno_table[i]] = i;
4278
2ab83ea7 4279 /* automatic consistency check if same arch */
872ea0c0
AZ
4280#if (defined(__i386__) && defined(TARGET_I386) && defined(TARGET_ABI32)) || \
4281 (defined(__x86_64__) && defined(TARGET_X86_64))
4282 if (unlikely(ie->target_cmd != ie->host_cmd)) {
4283 fprintf(stderr, "ERROR: ioctl(%s): target=0x%x host=0x%x\n",
4284 ie->name, ie->target_cmd, ie->host_cmd);
2ab83ea7
FB
4285 }
4286#endif
4287 ie++;
4288 }
31e31b8a 4289}
c573ff67 4290
992f48a0 4291#if TARGET_ABI_BITS == 32
ce4defa0
PB
4292static inline uint64_t target_offset64(uint32_t word0, uint32_t word1)
4293{
af325d36 4294#ifdef TARGET_WORDS_BIGENDIAN
ce4defa0
PB
4295 return ((uint64_t)word0 << 32) | word1;
4296#else
4297 return ((uint64_t)word1 << 32) | word0;
4298#endif
4299}
992f48a0 4300#else /* TARGET_ABI_BITS == 32 */
32407103
JM
4301static inline uint64_t target_offset64(uint64_t word0, uint64_t word1)
4302{
4303 return word0;
4304}
992f48a0 4305#endif /* TARGET_ABI_BITS != 32 */
ce4defa0
PB
4306
4307#ifdef TARGET_NR_truncate64
992f48a0
BS
4308static inline abi_long target_truncate64(void *cpu_env, const char *arg1,
4309 abi_long arg2,
4310 abi_long arg3,
4311 abi_long arg4)
ce4defa0
PB
4312{
4313#ifdef TARGET_ARM
4314 if (((CPUARMState *)cpu_env)->eabi)
4315 {
4316 arg2 = arg3;
4317 arg3 = arg4;
4318 }
4319#endif
4320 return get_errno(truncate64(arg1, target_offset64(arg2, arg3)));
4321}
4322#endif
4323
4324#ifdef TARGET_NR_ftruncate64
992f48a0
BS
4325static inline abi_long target_ftruncate64(void *cpu_env, abi_long arg1,
4326 abi_long arg2,
4327 abi_long arg3,
4328 abi_long arg4)
ce4defa0
PB
4329{
4330#ifdef TARGET_ARM
4331 if (((CPUARMState *)cpu_env)->eabi)
4332 {
4333 arg2 = arg3;
4334 arg3 = arg4;
4335 }
4336#endif
4337 return get_errno(ftruncate64(arg1, target_offset64(arg2, arg3)));
4338}
4339#endif
4340
579a97f7
FB
4341static inline abi_long target_to_host_timespec(struct timespec *host_ts,
4342 abi_ulong target_addr)
53a5960a
PB
4343{
4344 struct target_timespec *target_ts;
4345
579a97f7
FB
4346 if (!lock_user_struct(VERIFY_READ, target_ts, target_addr, 1))
4347 return -TARGET_EFAULT;
53a5960a
PB
4348 host_ts->tv_sec = tswapl(target_ts->tv_sec);
4349 host_ts->tv_nsec = tswapl(target_ts->tv_nsec);
4350 unlock_user_struct(target_ts, target_addr, 0);
b255bfa8 4351 return 0;
53a5960a
PB
4352}
4353
579a97f7
FB
4354static inline abi_long host_to_target_timespec(abi_ulong target_addr,
4355 struct timespec *host_ts)
53a5960a
PB
4356{
4357 struct target_timespec *target_ts;
4358
579a97f7
FB
4359 if (!lock_user_struct(VERIFY_WRITE, target_ts, target_addr, 0))
4360 return -TARGET_EFAULT;
53a5960a
PB
4361 target_ts->tv_sec = tswapl(host_ts->tv_sec);
4362 target_ts->tv_nsec = tswapl(host_ts->tv_nsec);
4363 unlock_user_struct(target_ts, target_addr, 1);
b255bfa8 4364 return 0;
53a5960a
PB
4365}
4366
9d33b76b 4367#if defined(TARGET_NR_stat64) || defined(TARGET_NR_newfstatat)
6a24a778
AZ
4368static inline abi_long host_to_target_stat64(void *cpu_env,
4369 abi_ulong target_addr,
4370 struct stat *host_st)
4371{
4372#ifdef TARGET_ARM
4373 if (((CPUARMState *)cpu_env)->eabi) {
4374 struct target_eabi_stat64 *target_st;
4375
4376 if (!lock_user_struct(VERIFY_WRITE, target_st, target_addr, 0))
4377 return -TARGET_EFAULT;
4378 memset(target_st, 0, sizeof(struct target_eabi_stat64));
4379 __put_user(host_st->st_dev, &target_st->st_dev);
4380 __put_user(host_st->st_ino, &target_st->st_ino);
4381#ifdef TARGET_STAT64_HAS_BROKEN_ST_INO
4382 __put_user(host_st->st_ino, &target_st->__st_ino);
4383#endif
4384 __put_user(host_st->st_mode, &target_st->st_mode);
4385 __put_user(host_st->st_nlink, &target_st->st_nlink);
4386 __put_user(host_st->st_uid, &target_st->st_uid);
4387 __put_user(host_st->st_gid, &target_st->st_gid);
4388 __put_user(host_st->st_rdev, &target_st->st_rdev);
4389 __put_user(host_st->st_size, &target_st->st_size);
4390 __put_user(host_st->st_blksize, &target_st->st_blksize);
4391 __put_user(host_st->st_blocks, &target_st->st_blocks);
4392 __put_user(host_st->st_atime, &target_st->target_st_atime);
4393 __put_user(host_st->st_mtime, &target_st->target_st_mtime);
4394 __put_user(host_st->st_ctime, &target_st->target_st_ctime);
4395 unlock_user_struct(target_st, target_addr, 1);
4396 } else
4397#endif
4398 {
ed18c5ce 4399#if TARGET_ABI_BITS == 64 && !defined(TARGET_ALPHA)
9d33b76b
AJ
4400 struct target_stat *target_st;
4401#else
6a24a778 4402 struct target_stat64 *target_st;
9d33b76b 4403#endif
6a24a778
AZ
4404
4405 if (!lock_user_struct(VERIFY_WRITE, target_st, target_addr, 0))
4406 return -TARGET_EFAULT;
9d33b76b 4407 memset(target_st, 0, sizeof(*target_st));
6a24a778
AZ
4408 __put_user(host_st->st_dev, &target_st->st_dev);
4409 __put_user(host_st->st_ino, &target_st->st_ino);
4410#ifdef TARGET_STAT64_HAS_BROKEN_ST_INO
4411 __put_user(host_st->st_ino, &target_st->__st_ino);
4412#endif
4413 __put_user(host_st->st_mode, &target_st->st_mode);
4414 __put_user(host_st->st_nlink, &target_st->st_nlink);
4415 __put_user(host_st->st_uid, &target_st->st_uid);
4416 __put_user(host_st->st_gid, &target_st->st_gid);
4417 __put_user(host_st->st_rdev, &target_st->st_rdev);
4418 /* XXX: better use of kernel struct */
4419 __put_user(host_st->st_size, &target_st->st_size);
4420 __put_user(host_st->st_blksize, &target_st->st_blksize);
4421 __put_user(host_st->st_blocks, &target_st->st_blocks);
4422 __put_user(host_st->st_atime, &target_st->target_st_atime);
4423 __put_user(host_st->st_mtime, &target_st->target_st_mtime);
4424 __put_user(host_st->st_ctime, &target_st->target_st_ctime);
4425 unlock_user_struct(target_st, target_addr, 1);
4426 }
4427
4428 return 0;
4429}
4430#endif
4431
2f7bb878 4432#if defined(CONFIG_USE_NPTL)
bd0c5661
PB
4433/* ??? Using host futex calls even when target atomic operations
4434 are not really atomic probably breaks things. However implementing
4435 futexes locally would make futexes shared between multiple processes
4436 tricky. However they're probably useless because guest atomic
4437 operations won't work either. */
8fcd3692
BS
4438static int do_futex(target_ulong uaddr, int op, int val, target_ulong timeout,
4439 target_ulong uaddr2, int val3)
bd0c5661
PB
4440{
4441 struct timespec ts, *pts;
a16aae0c 4442 int base_op;
bd0c5661
PB
4443
4444 /* ??? We assume FUTEX_* constants are the same on both host
4445 and target. */
a29ccd63 4446#ifdef FUTEX_CMD_MASK
a16aae0c 4447 base_op = op & FUTEX_CMD_MASK;
a29ccd63 4448#else
a16aae0c 4449 base_op = op;
a29ccd63 4450#endif
a16aae0c 4451 switch (base_op) {
bd0c5661
PB
4452 case FUTEX_WAIT:
4453 if (timeout) {
4454 pts = &ts;
4455 target_to_host_timespec(pts, timeout);
4456 } else {
4457 pts = NULL;
4458 }
a29ccd63 4459 return get_errno(sys_futex(g2h(uaddr), op, tswap32(val),
bd0c5661
PB
4460 pts, NULL, 0));
4461 case FUTEX_WAKE:
a29ccd63 4462 return get_errno(sys_futex(g2h(uaddr), op, val, NULL, NULL, 0));
bd0c5661 4463 case FUTEX_FD:
a29ccd63 4464 return get_errno(sys_futex(g2h(uaddr), op, val, NULL, NULL, 0));
bd0c5661 4465 case FUTEX_REQUEUE:
bd0c5661 4466 case FUTEX_CMP_REQUEUE:
a16aae0c
NF
4467 case FUTEX_WAKE_OP:
4468 /* For FUTEX_REQUEUE, FUTEX_CMP_REQUEUE, and FUTEX_WAKE_OP, the
4469 TIMEOUT parameter is interpreted as a uint32_t by the kernel.
4470 But the prototype takes a `struct timespec *'; insert casts
4471 to satisfy the compiler. We do not need to tswap TIMEOUT
4472 since it's not compared to guest memory. */
4473 pts = (struct timespec *)(uintptr_t) timeout;
4474 return get_errno(sys_futex(g2h(uaddr), op, val, pts,
4475 g2h(uaddr2),
4476 (base_op == FUTEX_CMP_REQUEUE
4477 ? tswap32(val3)
4478 : val3)));
bd0c5661
PB
4479 default:
4480 return -TARGET_ENOSYS;
4481 }
4482}
4483#endif
4484
1d9d8b55
PB
4485/* Map host to target signal numbers for the wait family of syscalls.
4486 Assume all other status bits are the same. */
4487static int host_to_target_waitstatus(int status)
4488{
4489 if (WIFSIGNALED(status)) {
4490 return host_to_target_signal(WTERMSIG(status)) | (status & ~0x7f);
4491 }
4492 if (WIFSTOPPED(status)) {
4493 return (host_to_target_signal(WSTOPSIG(status)) << 8)
4494 | (status & 0xff);
4495 }
4496 return status;
4497}
4498
a745ec6d
PB
4499int get_osversion(void)
4500{
4501 static int osversion;
4502 struct new_utsname buf;
4503 const char *s;
4504 int i, n, tmp;
4505 if (osversion)
4506 return osversion;
4507 if (qemu_uname_release && *qemu_uname_release) {
4508 s = qemu_uname_release;
4509 } else {
4510 if (sys_uname(&buf))
4511 return 0;
4512 s = buf.release;
4513 }
4514 tmp = 0;
4515 for (i = 0; i < 3; i++) {
4516 n = 0;
4517 while (*s >= '0' && *s <= '9') {
4518 n *= 10;
4519 n += *s - '0';
4520 s++;
4521 }
4522 tmp = (tmp << 8) + n;
4523 if (*s == '.')
4524 s++;
4525 }
4526 osversion = tmp;
4527 return osversion;
4528}
4529
0da46a6e
TS
4530/* do_syscall() should always have a single exit point at the end so
4531 that actions, such as logging of syscall results, can be performed.
4532 All errnos that do_syscall() returns must be -TARGET_<errcode>. */
992f48a0
BS
4533abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
4534 abi_long arg2, abi_long arg3, abi_long arg4,
5945cfcb
PM
4535 abi_long arg5, abi_long arg6, abi_long arg7,
4536 abi_long arg8)
31e31b8a 4537{
992f48a0 4538 abi_long ret;
31e31b8a 4539 struct stat st;
56c8f68f 4540 struct statfs stfs;
53a5960a 4541 void *p;
3b46e624 4542
72f03900 4543#ifdef DEBUG
c573ff67 4544 gemu_log("syscall %d", num);
72f03900 4545#endif
b92c47c1
TS
4546 if(do_strace)
4547 print_syscall(num, arg1, arg2, arg3, arg4, arg5, arg6);
4548
31e31b8a
FB
4549 switch(num) {
4550 case TARGET_NR_exit:
2f7bb878 4551#ifdef CONFIG_USE_NPTL
c2764719
PB
4552 /* In old applications this may be used to implement _exit(2).
4553 However in threaded applictions it is used for thread termination,
4554 and _exit_group is used for application termination.
4555 Do thread termination if we have more then one thread. */
4556 /* FIXME: This probably breaks if a signal arrives. We should probably
4557 be disabling signals. */
4558 if (first_cpu->next_cpu) {
1e9fa730 4559 TaskState *ts;
c2764719
PB
4560 CPUState **lastp;
4561 CPUState *p;
4562
4563 cpu_list_lock();
4564 lastp = &first_cpu;
4565 p = first_cpu;
4566 while (p && p != (CPUState *)cpu_env) {
4567 lastp = &p->next_cpu;
4568 p = p->next_cpu;
4569 }
4570 /* If we didn't find the CPU for this thread then something is
4571 horribly wrong. */
4572 if (!p)
4573 abort();
4574 /* Remove the CPU from the list. */
4575 *lastp = p->next_cpu;
4576 cpu_list_unlock();
1e9fa730 4577 ts = ((CPUState *)cpu_env)->opaque;
c2764719
PB
4578 if (ts->child_tidptr) {
4579 put_user_u32(0, ts->child_tidptr);
4580 sys_futex(g2h(ts->child_tidptr), FUTEX_WAKE, INT_MAX,
4581 NULL, NULL, 0);
4582 }
48e15fc2
NF
4583 thread_env = NULL;
4584 qemu_free(cpu_env);
4585 qemu_free(ts);
c2764719
PB
4586 pthread_exit(NULL);
4587 }
4588#endif
9788c9ca 4589#ifdef TARGET_GPROF
7d13299d
FB
4590 _mcleanup();
4591#endif
e9009676 4592 gdb_exit(cpu_env, arg1);
c2764719 4593 _exit(arg1);
31e31b8a
FB
4594 ret = 0; /* avoid warning */
4595 break;
4596 case TARGET_NR_read:
38d840e6
AJ
4597 if (arg3 == 0)
4598 ret = 0;
4599 else {
4600 if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
4601 goto efault;
4602 ret = get_errno(read(arg1, p, arg3));
4603 unlock_user(p, arg2, ret);
4604 }
31e31b8a
FB
4605 break;
4606 case TARGET_NR_write:
579a97f7
FB
4607 if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
4608 goto efault;
53a5960a
PB
4609 ret = get_errno(write(arg1, p, arg3));
4610 unlock_user(p, arg2, 0);
31e31b8a
FB
4611 break;
4612 case TARGET_NR_open:
2f619698
FB
4613 if (!(p = lock_user_string(arg1)))
4614 goto efault;
53a5960a 4615 ret = get_errno(open(path(p),
ffa65c3b
FB
4616 target_to_host_bitmask(arg2, fcntl_flags_tbl),
4617 arg3));
53a5960a 4618 unlock_user(p, arg1, 0);
31e31b8a 4619 break;
82424832
TS
4620#if defined(TARGET_NR_openat) && defined(__NR_openat)
4621 case TARGET_NR_openat:
579a97f7
FB
4622 if (!(p = lock_user_string(arg2)))
4623 goto efault;
4624 ret = get_errno(sys_openat(arg1,
4625 path(p),
4626 target_to_host_bitmask(arg3, fcntl_flags_tbl),
4627 arg4));
4628 unlock_user(p, arg2, 0);
82424832
TS
4629 break;
4630#endif
31e31b8a
FB
4631 case TARGET_NR_close:
4632 ret = get_errno(close(arg1));
4633 break;
4634 case TARGET_NR_brk:
53a5960a 4635 ret = do_brk(arg1);
31e31b8a
FB
4636 break;
4637 case TARGET_NR_fork:
d865bab5 4638 ret = get_errno(do_fork(cpu_env, SIGCHLD, 0, 0, 0, 0));
31e31b8a 4639 break;
e5febef5 4640#ifdef TARGET_NR_waitpid
31e31b8a
FB
4641 case TARGET_NR_waitpid:
4642 {
53a5960a
PB
4643 int status;
4644 ret = get_errno(waitpid(arg1, &status, arg3));
2f619698 4645 if (!is_error(ret) && arg2
1d9d8b55 4646 && put_user_s32(host_to_target_waitstatus(status), arg2))
2f619698 4647 goto efault;
31e31b8a
FB
4648 }
4649 break;
e5febef5 4650#endif
f0cbb613
PB
4651#ifdef TARGET_NR_waitid
4652 case TARGET_NR_waitid:
4653 {
4654 siginfo_t info;
4655 info.si_pid = 0;
4656 ret = get_errno(waitid(arg1, arg2, &info, arg4));
4657 if (!is_error(ret) && arg3 && info.si_pid != 0) {
c227f099 4658 if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_siginfo_t), 0)))
f0cbb613
PB
4659 goto efault;
4660 host_to_target_siginfo(p, &info);
c227f099 4661 unlock_user(p, arg3, sizeof(target_siginfo_t));
f0cbb613
PB
4662 }
4663 }
4664 break;
4665#endif
7a3148a9 4666#ifdef TARGET_NR_creat /* not on alpha */
31e31b8a 4667 case TARGET_NR_creat:
579a97f7
FB
4668 if (!(p = lock_user_string(arg1)))
4669 goto efault;
53a5960a
PB
4670 ret = get_errno(creat(p, arg2));
4671 unlock_user(p, arg1, 0);
31e31b8a 4672 break;
7a3148a9 4673#endif
31e31b8a 4674 case TARGET_NR_link:
53a5960a
PB
4675 {
4676 void * p2;
4677 p = lock_user_string(arg1);
4678 p2 = lock_user_string(arg2);
579a97f7
FB
4679 if (!p || !p2)
4680 ret = -TARGET_EFAULT;
4681 else
4682 ret = get_errno(link(p, p2));
53a5960a
PB
4683 unlock_user(p2, arg2, 0);
4684 unlock_user(p, arg1, 0);
4685 }
31e31b8a 4686 break;
64f0ce4c
TS
4687#if defined(TARGET_NR_linkat) && defined(__NR_linkat)
4688 case TARGET_NR_linkat:
64f0ce4c
TS
4689 {
4690 void * p2 = NULL;
579a97f7
FB
4691 if (!arg2 || !arg4)
4692 goto efault;
64f0ce4c
TS
4693 p = lock_user_string(arg2);
4694 p2 = lock_user_string(arg4);
579a97f7 4695 if (!p || !p2)
0da46a6e 4696 ret = -TARGET_EFAULT;
64f0ce4c
TS
4697 else
4698 ret = get_errno(sys_linkat(arg1, p, arg3, p2, arg5));
579a97f7
FB
4699 unlock_user(p, arg2, 0);
4700 unlock_user(p2, arg4, 0);
64f0ce4c
TS
4701 }
4702 break;
4703#endif
31e31b8a 4704 case TARGET_NR_unlink:
579a97f7
FB
4705 if (!(p = lock_user_string(arg1)))
4706 goto efault;
53a5960a
PB
4707 ret = get_errno(unlink(p));
4708 unlock_user(p, arg1, 0);
31e31b8a 4709 break;
8170f56b
TS
4710#if defined(TARGET_NR_unlinkat) && defined(__NR_unlinkat)
4711 case TARGET_NR_unlinkat:
579a97f7
FB
4712 if (!(p = lock_user_string(arg2)))
4713 goto efault;
4714 ret = get_errno(sys_unlinkat(arg1, p, arg3));
4715 unlock_user(p, arg2, 0);
ed494d87 4716 break;
b7d35e65 4717#endif
31e31b8a 4718 case TARGET_NR_execve:
7854b056
FB
4719 {
4720 char **argp, **envp;
f7341ff4 4721 int argc, envc;
992f48a0
BS
4722 abi_ulong gp;
4723 abi_ulong guest_argp;
4724 abi_ulong guest_envp;
4725 abi_ulong addr;
7854b056
FB
4726 char **q;
4727
f7341ff4 4728 argc = 0;
53a5960a 4729 guest_argp = arg2;
da94d263 4730 for (gp = guest_argp; gp; gp += sizeof(abi_ulong)) {
03aa1976 4731 if (get_user_ual(addr, gp))
2f619698 4732 goto efault;
03aa1976 4733 if (!addr)
2f619698 4734 break;
7854b056 4735 argc++;
2f619698 4736 }
f7341ff4 4737 envc = 0;
53a5960a 4738 guest_envp = arg3;
da94d263 4739 for (gp = guest_envp; gp; gp += sizeof(abi_ulong)) {
03aa1976 4740 if (get_user_ual(addr, gp))
2f619698 4741 goto efault;
03aa1976 4742 if (!addr)
2f619698 4743 break;
7854b056 4744 envc++;
2f619698 4745 }
7854b056 4746
f7341ff4
FB
4747 argp = alloca((argc + 1) * sizeof(void *));
4748 envp = alloca((envc + 1) * sizeof(void *));
7854b056 4749
da94d263 4750 for (gp = guest_argp, q = argp; gp;
992f48a0 4751 gp += sizeof(abi_ulong), q++) {
2f619698
FB
4752 if (get_user_ual(addr, gp))
4753 goto execve_efault;
53a5960a
PB
4754 if (!addr)
4755 break;
2f619698
FB
4756 if (!(*q = lock_user_string(addr)))
4757 goto execve_efault;
53a5960a 4758 }
f7341ff4
FB
4759 *q = NULL;
4760
da94d263 4761 for (gp = guest_envp, q = envp; gp;
992f48a0 4762 gp += sizeof(abi_ulong), q++) {
2f619698
FB
4763 if (get_user_ual(addr, gp))
4764 goto execve_efault;
53a5960a
PB
4765 if (!addr)
4766 break;
2f619698
FB
4767 if (!(*q = lock_user_string(addr)))
4768 goto execve_efault;
53a5960a 4769 }
f7341ff4 4770 *q = NULL;
7854b056 4771
2f619698
FB
4772 if (!(p = lock_user_string(arg1)))
4773 goto execve_efault;
53a5960a
PB
4774 ret = get_errno(execve(p, argp, envp));
4775 unlock_user(p, arg1, 0);
4776
2f619698
FB
4777 goto execve_end;
4778
4779 execve_efault:
4780 ret = -TARGET_EFAULT;
4781
4782 execve_end:
53a5960a 4783 for (gp = guest_argp, q = argp; *q;
992f48a0 4784 gp += sizeof(abi_ulong), q++) {
2f619698
FB
4785 if (get_user_ual(addr, gp)
4786 || !addr)
4787 break;
53a5960a
PB
4788 unlock_user(*q, addr, 0);
4789 }
4790 for (gp = guest_envp, q = envp; *q;
992f48a0 4791 gp += sizeof(abi_ulong), q++) {
2f619698
FB
4792 if (get_user_ual(addr, gp)
4793 || !addr)
4794 break;
53a5960a
PB
4795 unlock_user(*q, addr, 0);
4796 }
7854b056 4797 }
31e31b8a
FB
4798 break;
4799 case TARGET_NR_chdir:
579a97f7
FB
4800 if (!(p = lock_user_string(arg1)))
4801 goto efault;
53a5960a
PB
4802 ret = get_errno(chdir(p));
4803 unlock_user(p, arg1, 0);
31e31b8a 4804 break;
a315a145 4805#ifdef TARGET_NR_time
31e31b8a
FB
4806 case TARGET_NR_time:
4807 {
53a5960a
PB
4808 time_t host_time;
4809 ret = get_errno(time(&host_time));
2f619698
FB
4810 if (!is_error(ret)
4811 && arg1
4812 && put_user_sal(host_time, arg1))
4813 goto efault;
31e31b8a
FB
4814 }
4815 break;
a315a145 4816#endif
31e31b8a 4817 case TARGET_NR_mknod:
579a97f7
FB
4818 if (!(p = lock_user_string(arg1)))
4819 goto efault;
53a5960a
PB
4820 ret = get_errno(mknod(p, arg2, arg3));
4821 unlock_user(p, arg1, 0);
31e31b8a 4822 break;
75ac37a0
TS
4823#if defined(TARGET_NR_mknodat) && defined(__NR_mknodat)
4824 case TARGET_NR_mknodat:
579a97f7
FB
4825 if (!(p = lock_user_string(arg2)))
4826 goto efault;
4827 ret = get_errno(sys_mknodat(arg1, p, arg3, arg4));
4828 unlock_user(p, arg2, 0);
75ac37a0
TS
4829 break;
4830#endif
31e31b8a 4831 case TARGET_NR_chmod:
579a97f7
FB
4832 if (!(p = lock_user_string(arg1)))
4833 goto efault;
53a5960a
PB
4834 ret = get_errno(chmod(p, arg2));
4835 unlock_user(p, arg1, 0);
31e31b8a 4836 break;
ebc05488 4837#ifdef TARGET_NR_break
31e31b8a
FB
4838 case TARGET_NR_break:
4839 goto unimplemented;
ebc05488
FB
4840#endif
4841#ifdef TARGET_NR_oldstat
31e31b8a
FB
4842 case TARGET_NR_oldstat:
4843 goto unimplemented;
ebc05488 4844#endif
31e31b8a
FB
4845 case TARGET_NR_lseek:
4846 ret = get_errno(lseek(arg1, arg2, arg3));
4847 break;
9231733a
RH
4848#if defined(TARGET_NR_getxpid) && defined(TARGET_ALPHA)
4849 /* Alpha specific */
7a3148a9 4850 case TARGET_NR_getxpid:
9231733a
RH
4851 ((CPUAlphaState *)cpu_env)->ir[IR_A4] = getppid();
4852 ret = get_errno(getpid());
4853 break;
7a3148a9 4854#endif
9231733a
RH
4855#ifdef TARGET_NR_getpid
4856 case TARGET_NR_getpid:
31e31b8a
FB
4857 ret = get_errno(getpid());
4858 break;
9231733a 4859#endif
31e31b8a 4860 case TARGET_NR_mount:
80265918
TS
4861 {
4862 /* need to look at the data field */
4863 void *p2, *p3;
4864 p = lock_user_string(arg1);
4865 p2 = lock_user_string(arg2);
4866 p3 = lock_user_string(arg3);
579a97f7
FB
4867 if (!p || !p2 || !p3)
4868 ret = -TARGET_EFAULT;
dab46405 4869 else {
579a97f7
FB
4870 /* FIXME - arg5 should be locked, but it isn't clear how to
4871 * do that since it's not guaranteed to be a NULL-terminated
4872 * string.
4873 */
dab46405
JSM
4874 if ( ! arg5 )
4875 ret = get_errno(mount(p, p2, p3, (unsigned long)arg4, NULL));
4876 else
4877 ret = get_errno(mount(p, p2, p3, (unsigned long)arg4, g2h(arg5)));
4878 }
579a97f7
FB
4879 unlock_user(p, arg1, 0);
4880 unlock_user(p2, arg2, 0);
4881 unlock_user(p3, arg3, 0);
80265918
TS
4882 break;
4883 }
e5febef5 4884#ifdef TARGET_NR_umount
31e31b8a 4885 case TARGET_NR_umount:
579a97f7
FB
4886 if (!(p = lock_user_string(arg1)))
4887 goto efault;
53a5960a
PB
4888 ret = get_errno(umount(p));
4889 unlock_user(p, arg1, 0);
31e31b8a 4890 break;
e5febef5 4891#endif
7a3148a9 4892#ifdef TARGET_NR_stime /* not on alpha */
31e31b8a
FB
4893 case TARGET_NR_stime:
4894 {
53a5960a 4895 time_t host_time;
2f619698
FB
4896 if (get_user_sal(host_time, arg1))
4897 goto efault;
53a5960a 4898 ret = get_errno(stime(&host_time));
31e31b8a
FB
4899 }
4900 break;
7a3148a9 4901#endif
31e31b8a
FB
4902 case TARGET_NR_ptrace:
4903 goto unimplemented;
7a3148a9 4904#ifdef TARGET_NR_alarm /* not on alpha */
31e31b8a
FB
4905 case TARGET_NR_alarm:
4906 ret = alarm(arg1);
4907 break;
7a3148a9 4908#endif
ebc05488 4909#ifdef TARGET_NR_oldfstat
31e31b8a
FB
4910 case TARGET_NR_oldfstat:
4911 goto unimplemented;
ebc05488 4912#endif
7a3148a9 4913#ifdef TARGET_NR_pause /* not on alpha */
31e31b8a
FB
4914 case TARGET_NR_pause:
4915 ret = get_errno(pause());
4916 break;
7a3148a9 4917#endif
e5febef5 4918#ifdef TARGET_NR_utime
31e31b8a 4919 case TARGET_NR_utime:
ebc05488 4920 {
53a5960a
PB
4921 struct utimbuf tbuf, *host_tbuf;
4922 struct target_utimbuf *target_tbuf;
4923 if (arg2) {
579a97f7
FB
4924 if (!lock_user_struct(VERIFY_READ, target_tbuf, arg2, 1))
4925 goto efault;
53a5960a
PB
4926 tbuf.actime = tswapl(target_tbuf->actime);
4927 tbuf.modtime = tswapl(target_tbuf->modtime);
4928 unlock_user_struct(target_tbuf, arg2, 0);
4929 host_tbuf = &tbuf;
f72e8ff4 4930 } else {
53a5960a 4931 host_tbuf = NULL;
f72e8ff4 4932 }
579a97f7
FB
4933 if (!(p = lock_user_string(arg1)))
4934 goto efault;
53a5960a
PB
4935 ret = get_errno(utime(p, host_tbuf));
4936 unlock_user(p, arg1, 0);
ebc05488
FB
4937 }
4938 break;
e5febef5 4939#endif
978a66ff
FB
4940 case TARGET_NR_utimes:
4941 {
978a66ff 4942 struct timeval *tvp, tv[2];
53a5960a 4943 if (arg2) {
788f5ec4
TS
4944 if (copy_from_user_timeval(&tv[0], arg2)
4945 || copy_from_user_timeval(&tv[1],
4946 arg2 + sizeof(struct target_timeval)))
4947 goto efault;
978a66ff
FB
4948 tvp = tv;
4949 } else {
4950 tvp = NULL;
4951 }
579a97f7
FB
4952 if (!(p = lock_user_string(arg1)))
4953 goto efault;
53a5960a
PB
4954 ret = get_errno(utimes(p, tvp));
4955 unlock_user(p, arg1, 0);
978a66ff
FB
4956 }
4957 break;
ac8a6556
AZ
4958#if defined(TARGET_NR_futimesat) && defined(__NR_futimesat)
4959 case TARGET_NR_futimesat:
4960 {
4961 struct timeval *tvp, tv[2];
4962 if (arg3) {
4963 if (copy_from_user_timeval(&tv[0], arg3)
4964 || copy_from_user_timeval(&tv[1],
4965 arg3 + sizeof(struct target_timeval)))
4966 goto efault;
4967 tvp = tv;
4968 } else {
4969 tvp = NULL;
4970 }
4971 if (!(p = lock_user_string(arg2)))
4972 goto efault;
4973 ret = get_errno(sys_futimesat(arg1, path(p), tvp));
4974 unlock_user(p, arg2, 0);
4975 }
4976 break;
4977#endif
ebc05488 4978#ifdef TARGET_NR_stty
31e31b8a
FB
4979 case TARGET_NR_stty:
4980 goto unimplemented;
ebc05488
FB
4981#endif
4982#ifdef TARGET_NR_gtty
31e31b8a
FB
4983 case TARGET_NR_gtty:
4984 goto unimplemented;
ebc05488 4985#endif
31e31b8a 4986 case TARGET_NR_access:
579a97f7
FB
4987 if (!(p = lock_user_string(arg1)))
4988 goto efault;
719f908e 4989 ret = get_errno(access(path(p), arg2));
53a5960a 4990 unlock_user(p, arg1, 0);
31e31b8a 4991 break;
92a34c10
TS
4992#if defined(TARGET_NR_faccessat) && defined(__NR_faccessat)
4993 case TARGET_NR_faccessat:
579a97f7
FB
4994 if (!(p = lock_user_string(arg2)))
4995 goto efault;
465c9f06 4996 ret = get_errno(sys_faccessat(arg1, p, arg3));
579a97f7 4997 unlock_user(p, arg2, 0);
92a34c10
TS
4998 break;
4999#endif
7a3148a9 5000#ifdef TARGET_NR_nice /* not on alpha */
31e31b8a
FB
5001 case TARGET_NR_nice:
5002 ret = get_errno(nice(arg1));
5003 break;
7a3148a9 5004#endif
ebc05488 5005#ifdef TARGET_NR_ftime
31e31b8a
FB
5006 case TARGET_NR_ftime:
5007 goto unimplemented;
ebc05488 5008#endif
31e31b8a 5009 case TARGET_NR_sync:
04369ff2
FB
5010 sync();
5011 ret = 0;
31e31b8a
FB
5012 break;
5013 case TARGET_NR_kill:
4cb05961 5014 ret = get_errno(kill(arg1, target_to_host_signal(arg2)));
31e31b8a
FB
5015 break;
5016 case TARGET_NR_rename:
53a5960a
PB
5017 {
5018 void *p2;
5019 p = lock_user_string(arg1);
5020 p2 = lock_user_string(arg2);
579a97f7
FB
5021 if (!p || !p2)
5022 ret = -TARGET_EFAULT;
5023 else
5024 ret = get_errno(rename(p, p2));
53a5960a
PB
5025 unlock_user(p2, arg2, 0);
5026 unlock_user(p, arg1, 0);
5027 }
31e31b8a 5028 break;
722183f6
TS
5029#if defined(TARGET_NR_renameat) && defined(__NR_renameat)
5030 case TARGET_NR_renameat:
722183f6 5031 {
579a97f7 5032 void *p2;
722183f6
TS
5033 p = lock_user_string(arg2);
5034 p2 = lock_user_string(arg4);
579a97f7 5035 if (!p || !p2)
0da46a6e 5036 ret = -TARGET_EFAULT;
722183f6
TS
5037 else
5038 ret = get_errno(sys_renameat(arg1, p, arg3, p2));
579a97f7
FB
5039 unlock_user(p2, arg4, 0);
5040 unlock_user(p, arg2, 0);
722183f6
TS
5041 }
5042 break;
5043#endif
31e31b8a 5044 case TARGET_NR_mkdir:
579a97f7
FB
5045 if (!(p = lock_user_string(arg1)))
5046 goto efault;
53a5960a
PB
5047 ret = get_errno(mkdir(p, arg2));
5048 unlock_user(p, arg1, 0);
31e31b8a 5049 break;
4472ad0d
TS
5050#if defined(TARGET_NR_mkdirat) && defined(__NR_mkdirat)
5051 case TARGET_NR_mkdirat:
579a97f7
FB
5052 if (!(p = lock_user_string(arg2)))
5053 goto efault;
5054 ret = get_errno(sys_mkdirat(arg1, p, arg3));
5055 unlock_user(p, arg2, 0);
4472ad0d
TS
5056 break;
5057#endif
31e31b8a 5058 case TARGET_NR_rmdir:
579a97f7
FB
5059 if (!(p = lock_user_string(arg1)))
5060 goto efault;
53a5960a
PB
5061 ret = get_errno(rmdir(p));
5062 unlock_user(p, arg1, 0);
31e31b8a
FB
5063 break;
5064 case TARGET_NR_dup:
5065 ret = get_errno(dup(arg1));
5066 break;
5067 case TARGET_NR_pipe:
fb41a66e 5068 ret = do_pipe(cpu_env, arg1, 0, 0);
099d6b0f
RV
5069 break;
5070#ifdef TARGET_NR_pipe2
5071 case TARGET_NR_pipe2:
fb41a66e 5072 ret = do_pipe(cpu_env, arg1, arg2, 1);
31e31b8a 5073 break;
099d6b0f 5074#endif
31e31b8a 5075 case TARGET_NR_times:
32f36bce 5076 {
53a5960a 5077 struct target_tms *tmsp;
32f36bce
FB
5078 struct tms tms;
5079 ret = get_errno(times(&tms));
53a5960a 5080 if (arg1) {
579a97f7
FB
5081 tmsp = lock_user(VERIFY_WRITE, arg1, sizeof(struct target_tms), 0);
5082 if (!tmsp)
5083 goto efault;
c596ed17
FB
5084 tmsp->tms_utime = tswapl(host_to_target_clock_t(tms.tms_utime));
5085 tmsp->tms_stime = tswapl(host_to_target_clock_t(tms.tms_stime));
5086 tmsp->tms_cutime = tswapl(host_to_target_clock_t(tms.tms_cutime));
5087 tmsp->tms_cstime = tswapl(host_to_target_clock_t(tms.tms_cstime));
32f36bce 5088 }
c596ed17
FB
5089 if (!is_error(ret))
5090 ret = host_to_target_clock_t(ret);
32f36bce
FB
5091 }
5092 break;
ebc05488 5093#ifdef TARGET_NR_prof
31e31b8a
FB
5094 case TARGET_NR_prof:
5095 goto unimplemented;
ebc05488 5096#endif
e5febef5 5097#ifdef TARGET_NR_signal
31e31b8a
FB
5098 case TARGET_NR_signal:
5099 goto unimplemented;
e5febef5 5100#endif
31e31b8a 5101 case TARGET_NR_acct:
38d840e6
AJ
5102 if (arg1 == 0) {
5103 ret = get_errno(acct(NULL));
5104 } else {
5105 if (!(p = lock_user_string(arg1)))
5106 goto efault;
5107 ret = get_errno(acct(path(p)));
5108 unlock_user(p, arg1, 0);
5109 }
24836689 5110 break;
7a3148a9 5111#ifdef TARGET_NR_umount2 /* not on alpha */
31e31b8a 5112 case TARGET_NR_umount2:
579a97f7
FB
5113 if (!(p = lock_user_string(arg1)))
5114 goto efault;
53a5960a
PB
5115 ret = get_errno(umount2(p, arg2));
5116 unlock_user(p, arg1, 0);
31e31b8a 5117 break;
7a3148a9 5118#endif
ebc05488 5119#ifdef TARGET_NR_lock
31e31b8a
FB
5120 case TARGET_NR_lock:
5121 goto unimplemented;
ebc05488 5122#endif
31e31b8a
FB
5123 case TARGET_NR_ioctl:
5124 ret = do_ioctl(arg1, arg2, arg3);
5125 break;
5126 case TARGET_NR_fcntl:
9ee1fa2c 5127 ret = do_fcntl(arg1, arg2, arg3);
31e31b8a 5128 break;
ebc05488 5129#ifdef TARGET_NR_mpx
31e31b8a
FB
5130 case TARGET_NR_mpx:
5131 goto unimplemented;
ebc05488 5132#endif
31e31b8a
FB
5133 case TARGET_NR_setpgid:
5134 ret = get_errno(setpgid(arg1, arg2));
5135 break;
ebc05488 5136#ifdef TARGET_NR_ulimit
31e31b8a
FB
5137 case TARGET_NR_ulimit:
5138 goto unimplemented;
ebc05488
FB
5139#endif
5140#ifdef TARGET_NR_oldolduname
31e31b8a
FB
5141 case TARGET_NR_oldolduname:
5142 goto unimplemented;
ebc05488 5143#endif
31e31b8a
FB
5144 case TARGET_NR_umask:
5145 ret = get_errno(umask(arg1));
5146 break;
5147 case TARGET_NR_chroot:
579a97f7
FB
5148 if (!(p = lock_user_string(arg1)))
5149 goto efault;
53a5960a
PB
5150 ret = get_errno(chroot(p));
5151 unlock_user(p, arg1, 0);
31e31b8a
FB
5152 break;
5153 case TARGET_NR_ustat:
5154 goto unimplemented;
5155 case TARGET_NR_dup2:
5156 ret = get_errno(dup2(arg1, arg2));
5157 break;
d0927938
UH
5158#if defined(CONFIG_DUP3) && defined(TARGET_NR_dup3)
5159 case TARGET_NR_dup3:
5160 ret = get_errno(dup3(arg1, arg2, arg3));
5161 break;
5162#endif
7a3148a9 5163#ifdef TARGET_NR_getppid /* not on alpha */
31e31b8a
FB
5164 case TARGET_NR_getppid:
5165 ret = get_errno(getppid());
5166 break;
7a3148a9 5167#endif
31e31b8a
FB
5168 case TARGET_NR_getpgrp:
5169 ret = get_errno(getpgrp());
5170 break;
5171 case TARGET_NR_setsid:
5172 ret = get_errno(setsid());
5173 break;
e5febef5 5174#ifdef TARGET_NR_sigaction
31e31b8a 5175 case TARGET_NR_sigaction:
31e31b8a 5176 {
6049f4f8
RH
5177#if defined(TARGET_ALPHA)
5178 struct target_sigaction act, oact, *pact = 0;
53a5960a 5179 struct target_old_sigaction *old_act;
53a5960a 5180 if (arg2) {
579a97f7
FB
5181 if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1))
5182 goto efault;
66fb9763
FB
5183 act._sa_handler = old_act->_sa_handler;
5184 target_siginitset(&act.sa_mask, old_act->sa_mask);
5185 act.sa_flags = old_act->sa_flags;
6049f4f8 5186 act.sa_restorer = 0;
53a5960a 5187 unlock_user_struct(old_act, arg2, 0);
66fb9763 5188 pact = &act;
66fb9763
FB
5189 }
5190 ret = get_errno(do_sigaction(arg1, pact, &oact));
53a5960a 5191 if (!is_error(ret) && arg3) {
579a97f7
FB
5192 if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0))
5193 goto efault;
53a5960a
PB
5194 old_act->_sa_handler = oact._sa_handler;
5195 old_act->sa_mask = oact.sa_mask.sig[0];
5196 old_act->sa_flags = oact.sa_flags;
53a5960a 5197 unlock_user_struct(old_act, arg3, 1);
66fb9763 5198 }
6049f4f8 5199#elif defined(TARGET_MIPS)
106ec879
FB
5200 struct target_sigaction act, oact, *pact, *old_act;
5201
5202 if (arg2) {
579a97f7
FB
5203 if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1))
5204 goto efault;
106ec879
FB
5205 act._sa_handler = old_act->_sa_handler;
5206 target_siginitset(&act.sa_mask, old_act->sa_mask.sig[0]);
5207 act.sa_flags = old_act->sa_flags;
5208 unlock_user_struct(old_act, arg2, 0);
5209 pact = &act;
5210 } else {
5211 pact = NULL;
5212 }
5213
5214 ret = get_errno(do_sigaction(arg1, pact, &oact));
5215
5216 if (!is_error(ret) && arg3) {
579a97f7
FB
5217 if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0))
5218 goto efault;
106ec879
FB
5219 old_act->_sa_handler = oact._sa_handler;
5220 old_act->sa_flags = oact.sa_flags;
5221 old_act->sa_mask.sig[0] = oact.sa_mask.sig[0];
5222 old_act->sa_mask.sig[1] = 0;
5223 old_act->sa_mask.sig[2] = 0;
5224 old_act->sa_mask.sig[3] = 0;
5225 unlock_user_struct(old_act, arg3, 1);
5226 }
6049f4f8
RH
5227#else
5228 struct target_old_sigaction *old_act;
5229 struct target_sigaction act, oact, *pact;
5230 if (arg2) {
5231 if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1))
5232 goto efault;
5233 act._sa_handler = old_act->_sa_handler;
5234 target_siginitset(&act.sa_mask, old_act->sa_mask);
5235 act.sa_flags = old_act->sa_flags;
5236 act.sa_restorer = old_act->sa_restorer;
5237 unlock_user_struct(old_act, arg2, 0);
5238 pact = &act;
5239 } else {
5240 pact = NULL;
5241 }
5242 ret = get_errno(do_sigaction(arg1, pact, &oact));
5243 if (!is_error(ret) && arg3) {
5244 if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0))
5245 goto efault;
5246 old_act->_sa_handler = oact._sa_handler;
5247 old_act->sa_mask = oact.sa_mask.sig[0];
5248 old_act->sa_flags = oact.sa_flags;
5249 old_act->sa_restorer = oact.sa_restorer;
5250 unlock_user_struct(old_act, arg3, 1);
5251 }
388bb21a 5252#endif
31e31b8a
FB
5253 }
5254 break;
e5febef5 5255#endif
66fb9763 5256 case TARGET_NR_rt_sigaction:
53a5960a 5257 {
6049f4f8
RH
5258#if defined(TARGET_ALPHA)
5259 struct target_sigaction act, oact, *pact = 0;
5260 struct target_rt_sigaction *rt_act;
5261 /* ??? arg4 == sizeof(sigset_t). */
5262 if (arg2) {
5263 if (!lock_user_struct(VERIFY_READ, rt_act, arg2, 1))
5264 goto efault;
5265 act._sa_handler = rt_act->_sa_handler;
5266 act.sa_mask = rt_act->sa_mask;
5267 act.sa_flags = rt_act->sa_flags;
5268 act.sa_restorer = arg5;
5269 unlock_user_struct(rt_act, arg2, 0);
5270 pact = &act;
5271 }
5272 ret = get_errno(do_sigaction(arg1, pact, &oact));
5273 if (!is_error(ret) && arg3) {
5274 if (!lock_user_struct(VERIFY_WRITE, rt_act, arg3, 0))
5275 goto efault;
5276 rt_act->_sa_handler = oact._sa_handler;
5277 rt_act->sa_mask = oact.sa_mask;
5278 rt_act->sa_flags = oact.sa_flags;
5279 unlock_user_struct(rt_act, arg3, 1);
5280 }
5281#else
53a5960a
PB
5282 struct target_sigaction *act;
5283 struct target_sigaction *oact;
5284
579a97f7
FB
5285 if (arg2) {
5286 if (!lock_user_struct(VERIFY_READ, act, arg2, 1))
5287 goto efault;
5288 } else
53a5960a 5289 act = NULL;
579a97f7
FB
5290 if (arg3) {
5291 if (!lock_user_struct(VERIFY_WRITE, oact, arg3, 0)) {
5292 ret = -TARGET_EFAULT;
5293 goto rt_sigaction_fail;
5294 }
5295 } else
53a5960a
PB
5296 oact = NULL;
5297 ret = get_errno(do_sigaction(arg1, act, oact));
579a97f7
FB
5298 rt_sigaction_fail:
5299 if (act)
53a5960a 5300 unlock_user_struct(act, arg2, 0);
579a97f7 5301 if (oact)
53a5960a 5302 unlock_user_struct(oact, arg3, 1);
6049f4f8 5303#endif
53a5960a 5304 }
66fb9763 5305 break;
7a3148a9 5306#ifdef TARGET_NR_sgetmask /* not on alpha */
31e31b8a 5307 case TARGET_NR_sgetmask:
66fb9763
FB
5308 {
5309 sigset_t cur_set;
992f48a0 5310 abi_ulong target_set;
66fb9763
FB
5311 sigprocmask(0, NULL, &cur_set);
5312 host_to_target_old_sigset(&target_set, &cur_set);
5313 ret = target_set;
5314 }
5315 break;
7a3148a9
JM
5316#endif
5317#ifdef TARGET_NR_ssetmask /* not on alpha */
31e31b8a 5318 case TARGET_NR_ssetmask:
66fb9763
FB
5319 {
5320 sigset_t set, oset, cur_set;
992f48a0 5321 abi_ulong target_set = arg1;
66fb9763
FB
5322 sigprocmask(0, NULL, &cur_set);
5323 target_to_host_old_sigset(&set, &target_set);
5324 sigorset(&set, &set, &cur_set);
5325 sigprocmask(SIG_SETMASK, &set, &oset);
5326 host_to_target_old_sigset(&target_set, &oset);
5327 ret = target_set;
5328 }
5329 break;
7a3148a9 5330#endif
e5febef5 5331#ifdef TARGET_NR_sigprocmask
66fb9763
FB
5332 case TARGET_NR_sigprocmask:
5333 {
a5b3b13b
RH
5334#if defined(TARGET_ALPHA)
5335 sigset_t set, oldset;
5336 abi_ulong mask;
5337 int how;
5338
5339 switch (arg1) {
5340 case TARGET_SIG_BLOCK:
5341 how = SIG_BLOCK;
5342 break;
5343 case TARGET_SIG_UNBLOCK:
5344 how = SIG_UNBLOCK;
5345 break;
5346 case TARGET_SIG_SETMASK:
5347 how = SIG_SETMASK;
5348 break;
5349 default:
5350 ret = -TARGET_EINVAL;
5351 goto fail;
5352 }
5353 mask = arg2;
5354 target_to_host_old_sigset(&set, &mask);
5355
5356 ret = get_errno(sigprocmask(how, &set, &oldset));
5357
5358 if (!is_error(ret)) {
5359 host_to_target_old_sigset(&mask, &oldset);
5360 ret = mask;
5361 ((CPUAlphaState *)cpu_env)->[IR_V0] = 0; /* force no error */
5362 }
5363#else
66fb9763 5364 sigset_t set, oldset, *set_ptr;
a5b3b13b 5365 int how;
3b46e624 5366
53a5960a 5367 if (arg2) {
a5b3b13b 5368 switch (arg1) {
66fb9763
FB
5369 case TARGET_SIG_BLOCK:
5370 how = SIG_BLOCK;
5371 break;
5372 case TARGET_SIG_UNBLOCK:
5373 how = SIG_UNBLOCK;
5374 break;
5375 case TARGET_SIG_SETMASK:
5376 how = SIG_SETMASK;
5377 break;
5378 default:
0da46a6e 5379 ret = -TARGET_EINVAL;
66fb9763
FB
5380 goto fail;
5381 }
c227f099 5382 if (!(p = lock_user(VERIFY_READ, arg2, sizeof(target_sigset_t), 1)))
579a97f7 5383 goto efault;
53a5960a
PB
5384 target_to_host_old_sigset(&set, p);
5385 unlock_user(p, arg2, 0);
66fb9763
FB
5386 set_ptr = &set;
5387 } else {
5388 how = 0;
5389 set_ptr = NULL;
5390 }
a5b3b13b 5391 ret = get_errno(sigprocmask(how, set_ptr, &oldset));
53a5960a 5392 if (!is_error(ret) && arg3) {
c227f099 5393 if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0)))
579a97f7 5394 goto efault;
53a5960a 5395 host_to_target_old_sigset(p, &oldset);
c227f099 5396 unlock_user(p, arg3, sizeof(target_sigset_t));
66fb9763 5397 }
a5b3b13b 5398#endif
66fb9763
FB
5399 }
5400 break;
e5febef5 5401#endif
66fb9763
FB
5402 case TARGET_NR_rt_sigprocmask:
5403 {
5404 int how = arg1;
5405 sigset_t set, oldset, *set_ptr;
3b46e624 5406
53a5960a 5407 if (arg2) {
66fb9763
FB
5408 switch(how) {
5409 case TARGET_SIG_BLOCK:
5410 how = SIG_BLOCK;
5411 break;
5412 case TARGET_SIG_UNBLOCK:
5413 how = SIG_UNBLOCK;
5414 break;
5415 case TARGET_SIG_SETMASK:
5416 how = SIG_SETMASK;
5417 break;
5418 default:
0da46a6e 5419 ret = -TARGET_EINVAL;
66fb9763
FB
5420 goto fail;
5421 }
c227f099 5422 if (!(p = lock_user(VERIFY_READ, arg2, sizeof(target_sigset_t), 1)))
579a97f7 5423 goto efault;
53a5960a
PB
5424 target_to_host_sigset(&set, p);
5425 unlock_user(p, arg2, 0);
66fb9763
FB
5426 set_ptr = &set;
5427 } else {
5428 how = 0;
5429 set_ptr = NULL;
5430 }
5431 ret = get_errno(sigprocmask(how, set_ptr, &oldset));
53a5960a 5432 if (!is_error(ret) && arg3) {
c227f099 5433 if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0)))
579a97f7 5434 goto efault;
53a5960a 5435 host_to_target_sigset(p, &oldset);
c227f099 5436 unlock_user(p, arg3, sizeof(target_sigset_t));
66fb9763
FB
5437 }
5438 }
5439 break;
e5febef5 5440#ifdef TARGET_NR_sigpending
66fb9763
FB
5441 case TARGET_NR_sigpending:
5442 {
5443 sigset_t set;
5444 ret = get_errno(sigpending(&set));
5445 if (!is_error(ret)) {
c227f099 5446 if (!(p = lock_user(VERIFY_WRITE, arg1, sizeof(target_sigset_t), 0)))
579a97f7 5447 goto efault;
53a5960a 5448 host_to_target_old_sigset(p, &set);
c227f099 5449 unlock_user(p, arg1, sizeof(target_sigset_t));
66fb9763
FB
5450 }
5451 }
5452 break;
e5febef5 5453#endif
66fb9763
FB
5454 case TARGET_NR_rt_sigpending:
5455 {
5456 sigset_t set;
5457 ret = get_errno(sigpending(&set));
5458 if (!is_error(ret)) {
c227f099 5459 if (!(p = lock_user(VERIFY_WRITE, arg1, sizeof(target_sigset_t), 0)))
579a97f7 5460 goto efault;
53a5960a 5461 host_to_target_sigset(p, &set);
c227f099 5462 unlock_user(p, arg1, sizeof(target_sigset_t));
66fb9763
FB
5463 }
5464 }
5465 break;
e5febef5 5466#ifdef TARGET_NR_sigsuspend
66fb9763
FB
5467 case TARGET_NR_sigsuspend:
5468 {
5469 sigset_t set;
f43ce12b
RH
5470#if defined(TARGET_ALPHA)
5471 abi_ulong mask = arg1;
5472 target_to_host_old_sigset(&set, &mask);
5473#else
c227f099 5474 if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
579a97f7 5475 goto efault;
53a5960a
PB
5476 target_to_host_old_sigset(&set, p);
5477 unlock_user(p, arg1, 0);
f43ce12b 5478#endif
66fb9763
FB
5479 ret = get_errno(sigsuspend(&set));
5480 }
5481 break;
e5febef5 5482#endif
66fb9763
FB
5483 case TARGET_NR_rt_sigsuspend:
5484 {
5485 sigset_t set;
c227f099 5486 if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
579a97f7 5487 goto efault;
53a5960a
PB
5488 target_to_host_sigset(&set, p);
5489 unlock_user(p, arg1, 0);
66fb9763
FB
5490 ret = get_errno(sigsuspend(&set));
5491 }
5492 break;
5493 case TARGET_NR_rt_sigtimedwait:
5494 {
66fb9763
FB
5495 sigset_t set;
5496 struct timespec uts, *puts;
5497 siginfo_t uinfo;
3b46e624 5498
c227f099 5499 if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
579a97f7 5500 goto efault;
53a5960a
PB
5501 target_to_host_sigset(&set, p);
5502 unlock_user(p, arg1, 0);
5503 if (arg3) {
66fb9763 5504 puts = &uts;
53a5960a 5505 target_to_host_timespec(puts, arg3);
66fb9763
FB
5506 } else {
5507 puts = NULL;
5508 }
5509 ret = get_errno(sigtimedwait(&set, &uinfo, puts));
53a5960a 5510 if (!is_error(ret) && arg2) {
c227f099 5511 if (!(p = lock_user(VERIFY_WRITE, arg2, sizeof(target_siginfo_t), 0)))
579a97f7 5512 goto efault;
53a5960a 5513 host_to_target_siginfo(p, &uinfo);
c227f099 5514 unlock_user(p, arg2, sizeof(target_siginfo_t));
66fb9763
FB
5515 }
5516 }
5517 break;
5518 case TARGET_NR_rt_sigqueueinfo:
5519 {
5520 siginfo_t uinfo;
c227f099 5521 if (!(p = lock_user(VERIFY_READ, arg3, sizeof(target_sigset_t), 1)))
579a97f7 5522 goto efault;
53a5960a
PB
5523 target_to_host_siginfo(&uinfo, p);
5524 unlock_user(p, arg1, 0);
66fb9763
FB
5525 ret = get_errno(sys_rt_sigqueueinfo(arg1, arg2, &uinfo));
5526 }
5527 break;
e5febef5 5528#ifdef TARGET_NR_sigreturn
66fb9763
FB
5529 case TARGET_NR_sigreturn:
5530 /* NOTE: ret is eax, so not transcoding must be done */
5531 ret = do_sigreturn(cpu_env);
5532 break;
e5febef5 5533#endif
66fb9763
FB
5534 case TARGET_NR_rt_sigreturn:
5535 /* NOTE: ret is eax, so not transcoding must be done */
5536 ret = do_rt_sigreturn(cpu_env);
5537 break;
31e31b8a 5538 case TARGET_NR_sethostname:
579a97f7
FB
5539 if (!(p = lock_user_string(arg1)))
5540 goto efault;
53a5960a
PB
5541 ret = get_errno(sethostname(p, arg2));
5542 unlock_user(p, arg1, 0);
31e31b8a
FB
5543 break;
5544 case TARGET_NR_setrlimit:
9de5e440 5545 {
9de5e440 5546 int resource = arg1;
53a5960a 5547 struct target_rlimit *target_rlim;
9de5e440 5548 struct rlimit rlim;
579a97f7
FB
5549 if (!lock_user_struct(VERIFY_READ, target_rlim, arg2, 1))
5550 goto efault;
81bbe906
TY
5551 rlim.rlim_cur = target_to_host_rlim(target_rlim->rlim_cur);
5552 rlim.rlim_max = target_to_host_rlim(target_rlim->rlim_max);
53a5960a 5553 unlock_user_struct(target_rlim, arg2, 0);
9de5e440
FB
5554 ret = get_errno(setrlimit(resource, &rlim));
5555 }
5556 break;
31e31b8a 5557 case TARGET_NR_getrlimit:
9de5e440 5558 {
9de5e440 5559 int resource = arg1;
53a5960a 5560 struct target_rlimit *target_rlim;
9de5e440 5561 struct rlimit rlim;
3b46e624 5562
9de5e440
FB
5563 ret = get_errno(getrlimit(resource, &rlim));
5564 if (!is_error(ret)) {
579a97f7
FB
5565 if (!lock_user_struct(VERIFY_WRITE, target_rlim, arg2, 0))
5566 goto efault;
81bbe906
TY
5567 target_rlim->rlim_cur = host_to_target_rlim(rlim.rlim_cur);
5568 target_rlim->rlim_max = host_to_target_rlim(rlim.rlim_max);
53a5960a 5569 unlock_user_struct(target_rlim, arg2, 1);
9de5e440
FB
5570 }
5571 }
5572 break;
31e31b8a 5573 case TARGET_NR_getrusage:
b409186b
FB
5574 {
5575 struct rusage rusage;
b409186b
FB
5576 ret = get_errno(getrusage(arg1, &rusage));
5577 if (!is_error(ret)) {
53a5960a 5578 host_to_target_rusage(arg2, &rusage);
b409186b
FB
5579 }
5580 }
5581 break;
31e31b8a
FB
5582 case TARGET_NR_gettimeofday:
5583 {
31e31b8a
FB
5584 struct timeval tv;
5585 ret = get_errno(gettimeofday(&tv, NULL));
5586 if (!is_error(ret)) {
788f5ec4
TS
5587 if (copy_to_user_timeval(arg1, &tv))
5588 goto efault;
31e31b8a
FB
5589 }
5590 }
5591 break;
5592 case TARGET_NR_settimeofday:
5593 {
31e31b8a 5594 struct timeval tv;
788f5ec4
TS
5595 if (copy_from_user_timeval(&tv, arg1))
5596 goto efault;
31e31b8a
FB
5597 ret = get_errno(settimeofday(&tv, NULL));
5598 }
5599 break;
a4c075f1 5600#if defined(TARGET_NR_select) && !defined(TARGET_S390X) && !defined(TARGET_S390)
31e31b8a 5601 case TARGET_NR_select:
f2674e31 5602 {
53a5960a 5603 struct target_sel_arg_struct *sel;
992f48a0 5604 abi_ulong inp, outp, exp, tvp;
53a5960a
PB
5605 long nsel;
5606
579a97f7
FB
5607 if (!lock_user_struct(VERIFY_READ, sel, arg1, 1))
5608 goto efault;
53a5960a
PB
5609 nsel = tswapl(sel->n);
5610 inp = tswapl(sel->inp);
5611 outp = tswapl(sel->outp);
5612 exp = tswapl(sel->exp);
5613 tvp = tswapl(sel->tvp);
5614 unlock_user_struct(sel, arg1, 0);
5615 ret = do_select(nsel, inp, outp, exp, tvp);
f2674e31
FB
5616 }
5617 break;
9e42382f
RV
5618#endif
5619#ifdef TARGET_NR_pselect6
5620 case TARGET_NR_pselect6:
055e0906
MF
5621 {
5622 abi_long rfd_addr, wfd_addr, efd_addr, n, ts_addr;
5623 fd_set rfds, wfds, efds;
5624 fd_set *rfds_ptr, *wfds_ptr, *efds_ptr;
5625 struct timespec ts, *ts_ptr;
5626
5627 /*
5628 * The 6th arg is actually two args smashed together,
5629 * so we cannot use the C library.
5630 */
5631 sigset_t set;
5632 struct {
5633 sigset_t *set;
5634 size_t size;
5635 } sig, *sig_ptr;
5636
5637 abi_ulong arg_sigset, arg_sigsize, *arg7;
5638 target_sigset_t *target_sigset;
5639
5640 n = arg1;
5641 rfd_addr = arg2;
5642 wfd_addr = arg3;
5643 efd_addr = arg4;
5644 ts_addr = arg5;
5645
5646 ret = copy_from_user_fdset_ptr(&rfds, &rfds_ptr, rfd_addr, n);
5647 if (ret) {
5648 goto fail;
5649 }
5650 ret = copy_from_user_fdset_ptr(&wfds, &wfds_ptr, wfd_addr, n);
5651 if (ret) {
5652 goto fail;
5653 }
5654 ret = copy_from_user_fdset_ptr(&efds, &efds_ptr, efd_addr, n);
5655 if (ret) {
5656 goto fail;
5657 }
5658
5659 /*
5660 * This takes a timespec, and not a timeval, so we cannot
5661 * use the do_select() helper ...
5662 */
5663 if (ts_addr) {
5664 if (target_to_host_timespec(&ts, ts_addr)) {
5665 goto efault;
5666 }
5667 ts_ptr = &ts;
5668 } else {
5669 ts_ptr = NULL;
5670 }
5671
5672 /* Extract the two packed args for the sigset */
5673 if (arg6) {
5674 sig_ptr = &sig;
5675 sig.size = _NSIG / 8;
5676
5677 arg7 = lock_user(VERIFY_READ, arg6, sizeof(*arg7) * 2, 1);
5678 if (!arg7) {
5679 goto efault;
5680 }
5681 arg_sigset = tswapl(arg7[0]);
5682 arg_sigsize = tswapl(arg7[1]);
5683 unlock_user(arg7, arg6, 0);
5684
5685 if (arg_sigset) {
5686 sig.set = &set;
5687 target_sigset = lock_user(VERIFY_READ, arg_sigset,
5688 sizeof(*target_sigset), 1);
5689 if (!target_sigset) {
5690 goto efault;
5691 }
5692 target_to_host_sigset(&set, target_sigset);
5693 unlock_user(target_sigset, arg_sigset, 0);
5694 } else {
5695 sig.set = NULL;
5696 }
5697 } else {
5698 sig_ptr = NULL;
5699 }
5700
5701 ret = get_errno(sys_pselect6(n, rfds_ptr, wfds_ptr, efds_ptr,
5702 ts_ptr, sig_ptr));
5703
5704 if (!is_error(ret)) {
5705 if (rfd_addr && copy_to_user_fdset(rfd_addr, &rfds, n))
5706 goto efault;
5707 if (wfd_addr && copy_to_user_fdset(wfd_addr, &wfds, n))
5708 goto efault;
5709 if (efd_addr && copy_to_user_fdset(efd_addr, &efds, n))
5710 goto efault;
5711
5712 if (ts_addr && host_to_target_timespec(ts_addr, &ts))
5713 goto efault;
5714 }
5715 }
5716 break;
048f6b4d 5717#endif
31e31b8a 5718 case TARGET_NR_symlink:
53a5960a
PB
5719 {
5720 void *p2;
5721 p = lock_user_string(arg1);
5722 p2 = lock_user_string(arg2);
579a97f7
FB
5723 if (!p || !p2)
5724 ret = -TARGET_EFAULT;
5725 else
5726 ret = get_errno(symlink(p, p2));
53a5960a
PB
5727 unlock_user(p2, arg2, 0);
5728 unlock_user(p, arg1, 0);
5729 }
31e31b8a 5730 break;
f0b6243d
TS
5731#if defined(TARGET_NR_symlinkat) && defined(__NR_symlinkat)
5732 case TARGET_NR_symlinkat:
f0b6243d 5733 {
579a97f7 5734 void *p2;
f0b6243d
TS
5735 p = lock_user_string(arg1);
5736 p2 = lock_user_string(arg3);
579a97f7 5737 if (!p || !p2)
0da46a6e 5738 ret = -TARGET_EFAULT;
f0b6243d
TS
5739 else
5740 ret = get_errno(sys_symlinkat(p, arg2, p2));
579a97f7
FB
5741 unlock_user(p2, arg3, 0);
5742 unlock_user(p, arg1, 0);
f0b6243d
TS
5743 }
5744 break;
5745#endif
ebc05488 5746#ifdef TARGET_NR_oldlstat
31e31b8a
FB
5747 case TARGET_NR_oldlstat:
5748 goto unimplemented;
ebc05488 5749#endif
31e31b8a 5750 case TARGET_NR_readlink:
53a5960a 5751 {
d088d664 5752 void *p2, *temp;
53a5960a 5753 p = lock_user_string(arg1);
579a97f7
FB
5754 p2 = lock_user(VERIFY_WRITE, arg2, arg3, 0);
5755 if (!p || !p2)
5756 ret = -TARGET_EFAULT;
d088d664
AJ
5757 else {
5758 if (strncmp((const char *)p, "/proc/self/exe", 14) == 0) {
5759 char real[PATH_MAX];
5760 temp = realpath(exec_path,real);
5761 ret = (temp==NULL) ? get_errno(-1) : strlen(real) ;
5762 snprintf((char *)p2, arg3, "%s", real);
5763 }
5764 else
5765 ret = get_errno(readlink(path(p), p2, arg3));
d088d664 5766 }
53a5960a
PB
5767 unlock_user(p2, arg2, ret);
5768 unlock_user(p, arg1, 0);
5769 }
31e31b8a 5770 break;
5e0ccb18
TS
5771#if defined(TARGET_NR_readlinkat) && defined(__NR_readlinkat)
5772 case TARGET_NR_readlinkat:
5e0ccb18 5773 {
579a97f7 5774 void *p2;
5e0ccb18 5775 p = lock_user_string(arg2);
579a97f7
FB
5776 p2 = lock_user(VERIFY_WRITE, arg3, arg4, 0);
5777 if (!p || !p2)
0da46a6e 5778 ret = -TARGET_EFAULT;
5e0ccb18
TS
5779 else
5780 ret = get_errno(sys_readlinkat(arg1, path(p), p2, arg4));
579a97f7
FB
5781 unlock_user(p2, arg3, ret);
5782 unlock_user(p, arg2, 0);
5e0ccb18
TS
5783 }
5784 break;
5785#endif
e5febef5 5786#ifdef TARGET_NR_uselib
31e31b8a
FB
5787 case TARGET_NR_uselib:
5788 goto unimplemented;
e5febef5
TS
5789#endif
5790#ifdef TARGET_NR_swapon
31e31b8a 5791 case TARGET_NR_swapon:
579a97f7
FB
5792 if (!(p = lock_user_string(arg1)))
5793 goto efault;
53a5960a
PB
5794 ret = get_errno(swapon(p, arg2));
5795 unlock_user(p, arg1, 0);
31e31b8a 5796 break;
e5febef5 5797#endif
31e31b8a
FB
5798 case TARGET_NR_reboot:
5799 goto unimplemented;
e5febef5 5800#ifdef TARGET_NR_readdir
31e31b8a
FB
5801 case TARGET_NR_readdir:
5802 goto unimplemented;
e5febef5
TS
5803#endif
5804#ifdef TARGET_NR_mmap
31e31b8a 5805 case TARGET_NR_mmap:
a4c075f1
UH
5806#if (defined(TARGET_I386) && defined(TARGET_ABI32)) || defined(TARGET_ARM) || \
5807 defined(TARGET_M68K) || defined(TARGET_CRIS) || defined(TARGET_MICROBLAZE) \
5808 || defined(TARGET_S390X)
31e31b8a 5809 {
992f48a0
BS
5810 abi_ulong *v;
5811 abi_ulong v1, v2, v3, v4, v5, v6;
579a97f7
FB
5812 if (!(v = lock_user(VERIFY_READ, arg1, 6 * sizeof(abi_ulong), 1)))
5813 goto efault;
53a5960a
PB
5814 v1 = tswapl(v[0]);
5815 v2 = tswapl(v[1]);
5816 v3 = tswapl(v[2]);
5817 v4 = tswapl(v[3]);
5818 v5 = tswapl(v[4]);
5819 v6 = tswapl(v[5]);
5820 unlock_user(v, arg1, 0);
5fafdf24 5821 ret = get_errno(target_mmap(v1, v2, v3,
5286db75
FB
5822 target_to_host_bitmask(v4, mmap_flags_tbl),
5823 v5, v6));
31e31b8a 5824 }
31e31b8a 5825#else
5fafdf24
TS
5826 ret = get_errno(target_mmap(arg1, arg2, arg3,
5827 target_to_host_bitmask(arg4, mmap_flags_tbl),
6fb883e8
FB
5828 arg5,
5829 arg6));
31e31b8a 5830#endif
6fb883e8 5831 break;
e5febef5 5832#endif
a315a145 5833#ifdef TARGET_NR_mmap2
6fb883e8 5834 case TARGET_NR_mmap2:
bb7ec043 5835#ifndef MMAP_SHIFT
c573ff67 5836#define MMAP_SHIFT 12
c573ff67 5837#endif
5fafdf24
TS
5838 ret = get_errno(target_mmap(arg1, arg2, arg3,
5839 target_to_host_bitmask(arg4, mmap_flags_tbl),
5286db75 5840 arg5,
c573ff67 5841 arg6 << MMAP_SHIFT));
31e31b8a 5842 break;
a315a145 5843#endif
31e31b8a 5844 case TARGET_NR_munmap:
54936004 5845 ret = get_errno(target_munmap(arg1, arg2));
31e31b8a 5846 break;
9de5e440 5847 case TARGET_NR_mprotect:
97374d38
PB
5848 {
5849 TaskState *ts = ((CPUState *)cpu_env)->opaque;
5850 /* Special hack to detect libc making the stack executable. */
5851 if ((arg3 & PROT_GROWSDOWN)
5852 && arg1 >= ts->info->stack_limit
5853 && arg1 <= ts->info->start_stack) {
5854 arg3 &= ~PROT_GROWSDOWN;
5855 arg2 = arg2 + arg1 - ts->info->stack_limit;
5856 arg1 = ts->info->stack_limit;
5857 }
5858 }
54936004 5859 ret = get_errno(target_mprotect(arg1, arg2, arg3));
9de5e440 5860 break;
e5febef5 5861#ifdef TARGET_NR_mremap
9de5e440 5862 case TARGET_NR_mremap:
54936004 5863 ret = get_errno(target_mremap(arg1, arg2, arg3, arg4, arg5));
9de5e440 5864 break;
e5febef5 5865#endif
53a5960a 5866 /* ??? msync/mlock/munlock are broken for softmmu. */
e5febef5 5867#ifdef TARGET_NR_msync
9de5e440 5868 case TARGET_NR_msync:
53a5960a 5869 ret = get_errno(msync(g2h(arg1), arg2, arg3));
9de5e440 5870 break;
e5febef5
TS
5871#endif
5872#ifdef TARGET_NR_mlock
9de5e440 5873 case TARGET_NR_mlock:
53a5960a 5874 ret = get_errno(mlock(g2h(arg1), arg2));
9de5e440 5875 break;
e5febef5
TS
5876#endif
5877#ifdef TARGET_NR_munlock
9de5e440 5878 case TARGET_NR_munlock:
53a5960a 5879 ret = get_errno(munlock(g2h(arg1), arg2));
9de5e440 5880 break;
e5febef5
TS
5881#endif
5882#ifdef TARGET_NR_mlockall
9de5e440
FB
5883 case TARGET_NR_mlockall:
5884 ret = get_errno(mlockall(arg1));
5885 break;
e5febef5
TS
5886#endif
5887#ifdef TARGET_NR_munlockall
9de5e440
FB
5888 case TARGET_NR_munlockall:
5889 ret = get_errno(munlockall());
5890 break;
e5febef5 5891#endif
31e31b8a 5892 case TARGET_NR_truncate:
579a97f7
FB
5893 if (!(p = lock_user_string(arg1)))
5894 goto efault;
53a5960a
PB
5895 ret = get_errno(truncate(p, arg2));
5896 unlock_user(p, arg1, 0);
31e31b8a
FB
5897 break;
5898 case TARGET_NR_ftruncate:
5899 ret = get_errno(ftruncate(arg1, arg2));
5900 break;
5901 case TARGET_NR_fchmod:
5902 ret = get_errno(fchmod(arg1, arg2));
5903 break;
814d7977
TS
5904#if defined(TARGET_NR_fchmodat) && defined(__NR_fchmodat)
5905 case TARGET_NR_fchmodat:
579a97f7
FB
5906 if (!(p = lock_user_string(arg2)))
5907 goto efault;
465c9f06 5908 ret = get_errno(sys_fchmodat(arg1, p, arg3));
579a97f7 5909 unlock_user(p, arg2, 0);
814d7977
TS
5910 break;
5911#endif
31e31b8a 5912 case TARGET_NR_getpriority:
c6cda17a
TS
5913 /* libc does special remapping of the return value of
5914 * sys_getpriority() so it's just easiest to call
5915 * sys_getpriority() directly rather than through libc. */
69137206 5916 ret = get_errno(sys_getpriority(arg1, arg2));
31e31b8a
FB
5917 break;
5918 case TARGET_NR_setpriority:
5919 ret = get_errno(setpriority(arg1, arg2, arg3));
5920 break;
ebc05488 5921#ifdef TARGET_NR_profil
31e31b8a
FB
5922 case TARGET_NR_profil:
5923 goto unimplemented;
ebc05488 5924#endif
31e31b8a 5925 case TARGET_NR_statfs:
579a97f7
FB
5926 if (!(p = lock_user_string(arg1)))
5927 goto efault;
53a5960a
PB
5928 ret = get_errno(statfs(path(p), &stfs));
5929 unlock_user(p, arg1, 0);
31e31b8a
FB
5930 convert_statfs:
5931 if (!is_error(ret)) {
53a5960a 5932 struct target_statfs *target_stfs;
3b46e624 5933
579a97f7
FB
5934 if (!lock_user_struct(VERIFY_WRITE, target_stfs, arg2, 0))
5935 goto efault;
5936 __put_user(stfs.f_type, &target_stfs->f_type);
5937 __put_user(stfs.f_bsize, &target_stfs->f_bsize);
5938 __put_user(stfs.f_blocks, &target_stfs->f_blocks);
5939 __put_user(stfs.f_bfree, &target_stfs->f_bfree);
5940 __put_user(stfs.f_bavail, &target_stfs->f_bavail);
5941 __put_user(stfs.f_files, &target_stfs->f_files);
5942 __put_user(stfs.f_ffree, &target_stfs->f_ffree);
5943 __put_user(stfs.f_fsid.__val[0], &target_stfs->f_fsid.val[0]);
5944 __put_user(stfs.f_fsid.__val[1], &target_stfs->f_fsid.val[1]);
5945 __put_user(stfs.f_namelen, &target_stfs->f_namelen);
53a5960a 5946 unlock_user_struct(target_stfs, arg2, 1);
31e31b8a
FB
5947 }
5948 break;
5949 case TARGET_NR_fstatfs:
56c8f68f 5950 ret = get_errno(fstatfs(arg1, &stfs));
31e31b8a 5951 goto convert_statfs;
56c8f68f
FB
5952#ifdef TARGET_NR_statfs64
5953 case TARGET_NR_statfs64:
579a97f7
FB
5954 if (!(p = lock_user_string(arg1)))
5955 goto efault;
53a5960a
PB
5956 ret = get_errno(statfs(path(p), &stfs));
5957 unlock_user(p, arg1, 0);
56c8f68f
FB
5958 convert_statfs64:
5959 if (!is_error(ret)) {
53a5960a 5960 struct target_statfs64 *target_stfs;
3b46e624 5961
579a97f7
FB
5962 if (!lock_user_struct(VERIFY_WRITE, target_stfs, arg3, 0))
5963 goto efault;
5964 __put_user(stfs.f_type, &target_stfs->f_type);
5965 __put_user(stfs.f_bsize, &target_stfs->f_bsize);
5966 __put_user(stfs.f_blocks, &target_stfs->f_blocks);
5967 __put_user(stfs.f_bfree, &target_stfs->f_bfree);
5968 __put_user(stfs.f_bavail, &target_stfs->f_bavail);
5969 __put_user(stfs.f_files, &target_stfs->f_files);
5970 __put_user(stfs.f_ffree, &target_stfs->f_ffree);
5971 __put_user(stfs.f_fsid.__val[0], &target_stfs->f_fsid.val[0]);
5972 __put_user(stfs.f_fsid.__val[1], &target_stfs->f_fsid.val[1]);
5973 __put_user(stfs.f_namelen, &target_stfs->f_namelen);
5974 unlock_user_struct(target_stfs, arg3, 1);
56c8f68f
FB
5975 }
5976 break;
5977 case TARGET_NR_fstatfs64:
5978 ret = get_errno(fstatfs(arg1, &stfs));
5979 goto convert_statfs64;
5980#endif
ebc05488 5981#ifdef TARGET_NR_ioperm
31e31b8a
FB
5982 case TARGET_NR_ioperm:
5983 goto unimplemented;
ebc05488 5984#endif
e5febef5 5985#ifdef TARGET_NR_socketcall
31e31b8a 5986 case TARGET_NR_socketcall:
53a5960a 5987 ret = do_socketcall(arg1, arg2);
31e31b8a 5988 break;
e5febef5 5989#endif
3532fa74
FB
5990#ifdef TARGET_NR_accept
5991 case TARGET_NR_accept:
1be9e1dc 5992 ret = do_accept(arg1, arg2, arg3);
3532fa74
FB
5993 break;
5994#endif
5995#ifdef TARGET_NR_bind
5996 case TARGET_NR_bind:
5997 ret = do_bind(arg1, arg2, arg3);
5998 break;
5999#endif
6000#ifdef TARGET_NR_connect
6001 case TARGET_NR_connect:
6002 ret = do_connect(arg1, arg2, arg3);
6003 break;
6004#endif
6005#ifdef TARGET_NR_getpeername
6006 case TARGET_NR_getpeername:
1be9e1dc 6007 ret = do_getpeername(arg1, arg2, arg3);
3532fa74
FB
6008 break;
6009#endif
6010#ifdef TARGET_NR_getsockname
6011 case TARGET_NR_getsockname:
1be9e1dc 6012 ret = do_getsockname(arg1, arg2, arg3);
3532fa74
FB
6013 break;
6014#endif
6015#ifdef TARGET_NR_getsockopt
6016 case TARGET_NR_getsockopt:
6017 ret = do_getsockopt(arg1, arg2, arg3, arg4, arg5);
6018 break;
6019#endif
6020#ifdef TARGET_NR_listen
6021 case TARGET_NR_listen:
1be9e1dc 6022 ret = get_errno(listen(arg1, arg2));
3532fa74
FB
6023 break;
6024#endif
6025#ifdef TARGET_NR_recv
6026 case TARGET_NR_recv:
214201bd 6027 ret = do_recvfrom(arg1, arg2, arg3, arg4, 0, 0);
3532fa74
FB
6028 break;
6029#endif
6030#ifdef TARGET_NR_recvfrom
6031 case TARGET_NR_recvfrom:
214201bd 6032 ret = do_recvfrom(arg1, arg2, arg3, arg4, arg5, arg6);
3532fa74
FB
6033 break;
6034#endif
6035#ifdef TARGET_NR_recvmsg
6036 case TARGET_NR_recvmsg:
6037 ret = do_sendrecvmsg(arg1, arg2, arg3, 0);
6038 break;
6039#endif
6040#ifdef TARGET_NR_send
6041 case TARGET_NR_send:
1be9e1dc 6042 ret = do_sendto(arg1, arg2, arg3, arg4, 0, 0);
3532fa74
FB
6043 break;
6044#endif
6045#ifdef TARGET_NR_sendmsg
6046 case TARGET_NR_sendmsg:
6047 ret = do_sendrecvmsg(arg1, arg2, arg3, 1);
6048 break;
6049#endif
6050#ifdef TARGET_NR_sendto
6051 case TARGET_NR_sendto:
1be9e1dc 6052 ret = do_sendto(arg1, arg2, arg3, arg4, arg5, arg6);
3532fa74
FB
6053 break;
6054#endif
6055#ifdef TARGET_NR_shutdown
6056 case TARGET_NR_shutdown:
1be9e1dc 6057 ret = get_errno(shutdown(arg1, arg2));
3532fa74
FB
6058 break;
6059#endif
6060#ifdef TARGET_NR_socket
6061 case TARGET_NR_socket:
6062 ret = do_socket(arg1, arg2, arg3);
6063 break;
6064#endif
6065#ifdef TARGET_NR_socketpair
6066 case TARGET_NR_socketpair:
1be9e1dc 6067 ret = do_socketpair(arg1, arg2, arg3, arg4);
3532fa74
FB
6068 break;
6069#endif
6070#ifdef TARGET_NR_setsockopt
6071 case TARGET_NR_setsockopt:
6072 ret = do_setsockopt(arg1, arg2, arg3, arg4, (socklen_t) arg5);
6073 break;
6074#endif
7494b0f9 6075
31e31b8a 6076 case TARGET_NR_syslog:
579a97f7
FB
6077 if (!(p = lock_user_string(arg2)))
6078 goto efault;
e5574487
TS
6079 ret = get_errno(sys_syslog((int)arg1, p, (int)arg3));
6080 unlock_user(p, arg2, 0);
7494b0f9
TS
6081 break;
6082
31e31b8a 6083 case TARGET_NR_setitimer:
66fb9763 6084 {
66fb9763
FB
6085 struct itimerval value, ovalue, *pvalue;
6086
53a5960a 6087 if (arg2) {
66fb9763 6088 pvalue = &value;
788f5ec4
TS
6089 if (copy_from_user_timeval(&pvalue->it_interval, arg2)
6090 || copy_from_user_timeval(&pvalue->it_value,
6091 arg2 + sizeof(struct target_timeval)))
6092 goto efault;
66fb9763
FB
6093 } else {
6094 pvalue = NULL;
6095 }
6096 ret = get_errno(setitimer(arg1, pvalue, &ovalue));
53a5960a 6097 if (!is_error(ret) && arg3) {
788f5ec4
TS
6098 if (copy_to_user_timeval(arg3,
6099 &ovalue.it_interval)
6100 || copy_to_user_timeval(arg3 + sizeof(struct target_timeval),
6101 &ovalue.it_value))
6102 goto efault;
66fb9763
FB
6103 }
6104 }
6105 break;
31e31b8a 6106 case TARGET_NR_getitimer:
66fb9763 6107 {
66fb9763 6108 struct itimerval value;
3b46e624 6109
66fb9763 6110 ret = get_errno(getitimer(arg1, &value));
53a5960a 6111 if (!is_error(ret) && arg2) {
788f5ec4
TS
6112 if (copy_to_user_timeval(arg2,
6113 &value.it_interval)
6114 || copy_to_user_timeval(arg2 + sizeof(struct target_timeval),
6115 &value.it_value))
6116 goto efault;
66fb9763
FB
6117 }
6118 }
6119 break;
31e31b8a 6120 case TARGET_NR_stat:
579a97f7
FB
6121 if (!(p = lock_user_string(arg1)))
6122 goto efault;
53a5960a
PB
6123 ret = get_errno(stat(path(p), &st));
6124 unlock_user(p, arg1, 0);
31e31b8a
FB
6125 goto do_stat;
6126 case TARGET_NR_lstat:
579a97f7
FB
6127 if (!(p = lock_user_string(arg1)))
6128 goto efault;
53a5960a
PB
6129 ret = get_errno(lstat(path(p), &st));
6130 unlock_user(p, arg1, 0);
31e31b8a
FB
6131 goto do_stat;
6132 case TARGET_NR_fstat:
6133 {
6134 ret = get_errno(fstat(arg1, &st));
6135 do_stat:
6136 if (!is_error(ret)) {
53a5960a 6137 struct target_stat *target_st;
e3584658 6138
579a97f7
FB
6139 if (!lock_user_struct(VERIFY_WRITE, target_st, arg2, 0))
6140 goto efault;
12727917 6141 memset(target_st, 0, sizeof(*target_st));
d2fd1af7
FB
6142 __put_user(st.st_dev, &target_st->st_dev);
6143 __put_user(st.st_ino, &target_st->st_ino);
6144 __put_user(st.st_mode, &target_st->st_mode);
6145 __put_user(st.st_uid, &target_st->st_uid);
6146 __put_user(st.st_gid, &target_st->st_gid);
6147 __put_user(st.st_nlink, &target_st->st_nlink);
6148 __put_user(st.st_rdev, &target_st->st_rdev);
6149 __put_user(st.st_size, &target_st->st_size);
6150 __put_user(st.st_blksize, &target_st->st_blksize);
6151 __put_user(st.st_blocks, &target_st->st_blocks);
6152 __put_user(st.st_atime, &target_st->target_st_atime);
6153 __put_user(st.st_mtime, &target_st->target_st_mtime);
6154 __put_user(st.st_ctime, &target_st->target_st_ctime);
53a5960a 6155 unlock_user_struct(target_st, arg2, 1);
31e31b8a
FB
6156 }
6157 }
6158 break;
ebc05488 6159#ifdef TARGET_NR_olduname
31e31b8a
FB
6160 case TARGET_NR_olduname:
6161 goto unimplemented;
ebc05488
FB
6162#endif
6163#ifdef TARGET_NR_iopl
31e31b8a
FB
6164 case TARGET_NR_iopl:
6165 goto unimplemented;
ebc05488 6166#endif
31e31b8a
FB
6167 case TARGET_NR_vhangup:
6168 ret = get_errno(vhangup());
6169 break;
ebc05488 6170#ifdef TARGET_NR_idle
31e31b8a
FB
6171 case TARGET_NR_idle:
6172 goto unimplemented;
42ad6ae9
FB
6173#endif
6174#ifdef TARGET_NR_syscall
6175 case TARGET_NR_syscall:
5945cfcb
PM
6176 ret = do_syscall(cpu_env, arg1 & 0xffff, arg2, arg3, arg4, arg5,
6177 arg6, arg7, arg8, 0);
6178 break;
ebc05488 6179#endif
31e31b8a
FB
6180 case TARGET_NR_wait4:
6181 {
6182 int status;
992f48a0 6183 abi_long status_ptr = arg2;
31e31b8a 6184 struct rusage rusage, *rusage_ptr;
992f48a0 6185 abi_ulong target_rusage = arg4;
31e31b8a
FB
6186 if (target_rusage)
6187 rusage_ptr = &rusage;
6188 else
6189 rusage_ptr = NULL;
6190 ret = get_errno(wait4(arg1, &status, arg3, rusage_ptr));
6191 if (!is_error(ret)) {
2f619698 6192 if (status_ptr) {
1d9d8b55 6193 status = host_to_target_waitstatus(status);
2f619698
FB
6194 if (put_user_s32(status, status_ptr))
6195 goto efault;
31e31b8a 6196 }
2f619698
FB
6197 if (target_rusage)
6198 host_to_target_rusage(target_rusage, &rusage);
31e31b8a
FB
6199 }
6200 }
6201 break;
e5febef5 6202#ifdef TARGET_NR_swapoff
31e31b8a 6203 case TARGET_NR_swapoff:
579a97f7
FB
6204 if (!(p = lock_user_string(arg1)))
6205 goto efault;
53a5960a
PB
6206 ret = get_errno(swapoff(p));
6207 unlock_user(p, arg1, 0);
31e31b8a 6208 break;
e5febef5 6209#endif
31e31b8a 6210 case TARGET_NR_sysinfo:
a5448a7d 6211 {
53a5960a 6212 struct target_sysinfo *target_value;
a5448a7d
FB
6213 struct sysinfo value;
6214 ret = get_errno(sysinfo(&value));
53a5960a 6215 if (!is_error(ret) && arg1)
a5448a7d 6216 {
579a97f7
FB
6217 if (!lock_user_struct(VERIFY_WRITE, target_value, arg1, 0))
6218 goto efault;
a5448a7d
FB
6219 __put_user(value.uptime, &target_value->uptime);
6220 __put_user(value.loads[0], &target_value->loads[0]);
6221 __put_user(value.loads[1], &target_value->loads[1]);
6222 __put_user(value.loads[2], &target_value->loads[2]);
6223 __put_user(value.totalram, &target_value->totalram);
6224 __put_user(value.freeram, &target_value->freeram);
6225 __put_user(value.sharedram, &target_value->sharedram);
6226 __put_user(value.bufferram, &target_value->bufferram);
6227 __put_user(value.totalswap, &target_value->totalswap);
6228 __put_user(value.freeswap, &target_value->freeswap);
6229 __put_user(value.procs, &target_value->procs);
6230 __put_user(value.totalhigh, &target_value->totalhigh);
6231 __put_user(value.freehigh, &target_value->freehigh);
6232 __put_user(value.mem_unit, &target_value->mem_unit);
53a5960a 6233 unlock_user_struct(target_value, arg1, 1);
a5448a7d
FB
6234 }
6235 }
6236 break;
e5febef5 6237#ifdef TARGET_NR_ipc
31e31b8a 6238 case TARGET_NR_ipc:
8853f86e
FB
6239 ret = do_ipc(arg1, arg2, arg3, arg4, arg5, arg6);
6240 break;
e5febef5 6241#endif
e5289087
AJ
6242#ifdef TARGET_NR_semget
6243 case TARGET_NR_semget:
6244 ret = get_errno(semget(arg1, arg2, arg3));
6245 break;
6246#endif
6247#ifdef TARGET_NR_semop
6248 case TARGET_NR_semop:
6249 ret = get_errno(do_semop(arg1, arg2, arg3));
6250 break;
6251#endif
6252#ifdef TARGET_NR_semctl
6253 case TARGET_NR_semctl:
6254 ret = do_semctl(arg1, arg2, arg3, (union target_semun)(abi_ulong)arg4);
6255 break;
6256#endif
eeb438c1
AJ
6257#ifdef TARGET_NR_msgctl
6258 case TARGET_NR_msgctl:
6259 ret = do_msgctl(arg1, arg2, arg3);
6260 break;
6261#endif
6262#ifdef TARGET_NR_msgget
6263 case TARGET_NR_msgget:
6264 ret = get_errno(msgget(arg1, arg2));
6265 break;
6266#endif
6267#ifdef TARGET_NR_msgrcv
6268 case TARGET_NR_msgrcv:
6269 ret = do_msgrcv(arg1, arg2, arg3, arg4, arg5);
6270 break;
6271#endif
6272#ifdef TARGET_NR_msgsnd
6273 case TARGET_NR_msgsnd:
6274 ret = do_msgsnd(arg1, arg2, arg3, arg4);
6275 break;
88a8c984
RV
6276#endif
6277#ifdef TARGET_NR_shmget
6278 case TARGET_NR_shmget:
6279 ret = get_errno(shmget(arg1, arg2, arg3));
6280 break;
6281#endif
6282#ifdef TARGET_NR_shmctl
6283 case TARGET_NR_shmctl:
6284 ret = do_shmctl(arg1, arg2, arg3);
6285 break;
6286#endif
6287#ifdef TARGET_NR_shmat
6288 case TARGET_NR_shmat:
6289 ret = do_shmat(arg1, arg2, arg3);
6290 break;
6291#endif
6292#ifdef TARGET_NR_shmdt
6293 case TARGET_NR_shmdt:
6294 ret = do_shmdt(arg1);
6295 break;
eeb438c1 6296#endif
31e31b8a
FB
6297 case TARGET_NR_fsync:
6298 ret = get_errno(fsync(arg1));
6299 break;
31e31b8a 6300 case TARGET_NR_clone:
a4b388ff 6301#if defined(TARGET_SH4) || defined(TARGET_ALPHA)
0b6d3ae0 6302 ret = get_errno(do_fork(cpu_env, arg1, arg2, arg3, arg5, arg4));
b15ad61c
EI
6303#elif defined(TARGET_CRIS)
6304 ret = get_errno(do_fork(cpu_env, arg2, arg1, arg3, arg4, arg5));
a4c075f1
UH
6305#elif defined(TARGET_S390X)
6306 ret = get_errno(do_fork(cpu_env, arg2, arg1, arg3, arg5, arg4));
0b6d3ae0 6307#else
d865bab5 6308 ret = get_errno(do_fork(cpu_env, arg1, arg2, arg3, arg4, arg5));
0b6d3ae0 6309#endif
1b6b029e 6310 break;
ec86b0fb
FB
6311#ifdef __NR_exit_group
6312 /* new thread calls */
6313 case TARGET_NR_exit_group:
9788c9ca 6314#ifdef TARGET_GPROF
6d946cda
AJ
6315 _mcleanup();
6316#endif
e9009676 6317 gdb_exit(cpu_env, arg1);
ec86b0fb
FB
6318 ret = get_errno(exit_group(arg1));
6319 break;
6320#endif
31e31b8a 6321 case TARGET_NR_setdomainname:
579a97f7
FB
6322 if (!(p = lock_user_string(arg1)))
6323 goto efault;
53a5960a
PB
6324 ret = get_errno(setdomainname(p, arg2));
6325 unlock_user(p, arg1, 0);
31e31b8a
FB
6326 break;
6327 case TARGET_NR_uname:
6328 /* no need to transcode because we use the linux syscall */
29e619b1
FB
6329 {
6330 struct new_utsname * buf;
3b46e624 6331
579a97f7
FB
6332 if (!lock_user_struct(VERIFY_WRITE, buf, arg1, 0))
6333 goto efault;
29e619b1
FB
6334 ret = get_errno(sys_uname(buf));
6335 if (!is_error(ret)) {
6336 /* Overrite the native machine name with whatever is being
6337 emulated. */
da79030f 6338 strcpy (buf->machine, cpu_to_uname_machine(cpu_env));
c5937220
PB
6339 /* Allow the user to override the reported release. */
6340 if (qemu_uname_release && *qemu_uname_release)
6341 strcpy (buf->release, qemu_uname_release);
29e619b1 6342 }
53a5960a 6343 unlock_user_struct(buf, arg1, 1);
29e619b1 6344 }
31e31b8a 6345 break;
6dbad63e 6346#ifdef TARGET_I386
31e31b8a 6347 case TARGET_NR_modify_ldt:
03acab66 6348 ret = do_modify_ldt(cpu_env, arg1, arg2, arg3);
5cd4393b 6349 break;
84409ddb 6350#if !defined(TARGET_X86_64)
5cd4393b
FB
6351 case TARGET_NR_vm86old:
6352 goto unimplemented;
6353 case TARGET_NR_vm86:
53a5960a 6354 ret = do_vm86(cpu_env, arg1, arg2);
6dbad63e 6355 break;
84409ddb 6356#endif
6dbad63e 6357#endif
31e31b8a
FB
6358 case TARGET_NR_adjtimex:
6359 goto unimplemented;
e5febef5 6360#ifdef TARGET_NR_create_module
31e31b8a 6361 case TARGET_NR_create_module:
e5febef5 6362#endif
31e31b8a
FB
6363 case TARGET_NR_init_module:
6364 case TARGET_NR_delete_module:
e5febef5 6365#ifdef TARGET_NR_get_kernel_syms
31e31b8a 6366 case TARGET_NR_get_kernel_syms:
e5febef5 6367#endif
31e31b8a
FB
6368 goto unimplemented;
6369 case TARGET_NR_quotactl:
6370 goto unimplemented;
6371 case TARGET_NR_getpgid:
6372 ret = get_errno(getpgid(arg1));
6373 break;
6374 case TARGET_NR_fchdir:
6375 ret = get_errno(fchdir(arg1));
6376 break;
84409ddb 6377#ifdef TARGET_NR_bdflush /* not on x86_64 */
31e31b8a
FB
6378 case TARGET_NR_bdflush:
6379 goto unimplemented;
84409ddb 6380#endif
e5febef5 6381#ifdef TARGET_NR_sysfs
31e31b8a
FB
6382 case TARGET_NR_sysfs:
6383 goto unimplemented;
e5febef5 6384#endif
31e31b8a 6385 case TARGET_NR_personality:
1b6b029e 6386 ret = get_errno(personality(arg1));
31e31b8a 6387 break;
e5febef5 6388#ifdef TARGET_NR_afs_syscall
31e31b8a
FB
6389 case TARGET_NR_afs_syscall:
6390 goto unimplemented;
e5febef5 6391#endif
7a3148a9 6392#ifdef TARGET_NR__llseek /* Not on alpha */
31e31b8a
FB
6393 case TARGET_NR__llseek:
6394 {
0c1592d9 6395 int64_t res;
d35b261c 6396#if !defined(__NR_llseek)
0c1592d9
PM
6397 res = lseek(arg1, ((uint64_t)arg2 << 32) | arg3, arg5);
6398 if (res == -1) {
6399 ret = get_errno(res);
6400 } else {
6401 ret = 0;
6402 }
4f2ac237 6403#else
31e31b8a 6404 ret = get_errno(_llseek(arg1, arg2, arg3, &res, arg5));
4f2ac237 6405#endif
0c1592d9
PM
6406 if ((ret == 0) && put_user_s64(res, arg4)) {
6407 goto efault;
6408 }
31e31b8a
FB
6409 }
6410 break;
7a3148a9 6411#endif
31e31b8a 6412 case TARGET_NR_getdents:
d83c8733 6413#if TARGET_ABI_BITS == 32 && HOST_LONG_BITS == 64
4add45b4 6414 {
53a5960a 6415 struct target_dirent *target_dirp;
6556a833 6416 struct linux_dirent *dirp;
992f48a0 6417 abi_long count = arg3;
4add45b4
FB
6418
6419 dirp = malloc(count);
0da46a6e 6420 if (!dirp) {
579a97f7 6421 ret = -TARGET_ENOMEM;
0da46a6e
TS
6422 goto fail;
6423 }
3b46e624 6424
4add45b4
FB
6425 ret = get_errno(sys_getdents(arg1, dirp, count));
6426 if (!is_error(ret)) {
6556a833 6427 struct linux_dirent *de;
4add45b4
FB
6428 struct target_dirent *tde;
6429 int len = ret;
6430 int reclen, treclen;
6431 int count1, tnamelen;
6432
6433 count1 = 0;
6434 de = dirp;
579a97f7
FB
6435 if (!(target_dirp = lock_user(VERIFY_WRITE, arg2, count, 0)))
6436 goto efault;
4add45b4
FB
6437 tde = target_dirp;
6438 while (len > 0) {
6439 reclen = de->d_reclen;
992f48a0 6440 treclen = reclen - (2 * (sizeof(long) - sizeof(abi_long)));
4add45b4
FB
6441 tde->d_reclen = tswap16(treclen);
6442 tde->d_ino = tswapl(de->d_ino);
6443 tde->d_off = tswapl(de->d_off);
992f48a0 6444 tnamelen = treclen - (2 * sizeof(abi_long) + 2);
4add45b4
FB
6445 if (tnamelen > 256)
6446 tnamelen = 256;
80a9d035 6447 /* XXX: may not be correct */
be15b141 6448 pstrcpy(tde->d_name, tnamelen, de->d_name);
6556a833 6449 de = (struct linux_dirent *)((char *)de + reclen);
4add45b4 6450 len -= reclen;
1c5bf3bf 6451 tde = (struct target_dirent *)((char *)tde + treclen);
4add45b4
FB
6452 count1 += treclen;
6453 }
6454 ret = count1;
579a97f7 6455 unlock_user(target_dirp, arg2, ret);
4add45b4
FB
6456 }
6457 free(dirp);
6458 }
6459#else
31e31b8a 6460 {
6556a833 6461 struct linux_dirent *dirp;
992f48a0 6462 abi_long count = arg3;
dab2ed99 6463
579a97f7
FB
6464 if (!(dirp = lock_user(VERIFY_WRITE, arg2, count, 0)))
6465 goto efault;
72f03900 6466 ret = get_errno(sys_getdents(arg1, dirp, count));
31e31b8a 6467 if (!is_error(ret)) {
6556a833 6468 struct linux_dirent *de;
31e31b8a
FB
6469 int len = ret;
6470 int reclen;
6471 de = dirp;
6472 while (len > 0) {
8083a3e5 6473 reclen = de->d_reclen;
31e31b8a
FB
6474 if (reclen > len)
6475 break;
8083a3e5 6476 de->d_reclen = tswap16(reclen);
31e31b8a
FB
6477 tswapls(&de->d_ino);
6478 tswapls(&de->d_off);
6556a833 6479 de = (struct linux_dirent *)((char *)de + reclen);
31e31b8a
FB
6480 len -= reclen;
6481 }
6482 }
53a5960a 6483 unlock_user(dirp, arg2, ret);
31e31b8a 6484 }
4add45b4 6485#endif
31e31b8a 6486 break;
3ae43202 6487#if defined(TARGET_NR_getdents64) && defined(__NR_getdents64)
dab2ed99
FB
6488 case TARGET_NR_getdents64:
6489 {
6556a833 6490 struct linux_dirent64 *dirp;
992f48a0 6491 abi_long count = arg3;
579a97f7
FB
6492 if (!(dirp = lock_user(VERIFY_WRITE, arg2, count, 0)))
6493 goto efault;
dab2ed99
FB
6494 ret = get_errno(sys_getdents64(arg1, dirp, count));
6495 if (!is_error(ret)) {
6556a833 6496 struct linux_dirent64 *de;
dab2ed99
FB
6497 int len = ret;
6498 int reclen;
6499 de = dirp;
6500 while (len > 0) {
8083a3e5 6501 reclen = de->d_reclen;
dab2ed99
FB
6502 if (reclen > len)
6503 break;
8083a3e5 6504 de->d_reclen = tswap16(reclen);
8582a53a
FB
6505 tswap64s((uint64_t *)&de->d_ino);
6506 tswap64s((uint64_t *)&de->d_off);
6556a833 6507 de = (struct linux_dirent64 *)((char *)de + reclen);
dab2ed99
FB
6508 len -= reclen;
6509 }
6510 }
53a5960a 6511 unlock_user(dirp, arg2, ret);
dab2ed99
FB
6512 }
6513 break;
a541f297 6514#endif /* TARGET_NR_getdents64 */
a4c075f1
UH
6515#if defined(TARGET_NR__newselect) || defined(TARGET_S390X)
6516#ifdef TARGET_S390X
6517 case TARGET_NR_select:
6518#else
31e31b8a 6519 case TARGET_NR__newselect:
a4c075f1 6520#endif
53a5960a 6521 ret = do_select(arg1, arg2, arg3, arg4, arg5);
31e31b8a 6522 break;
e5febef5 6523#endif
d8035d4c
MF
6524#if defined(TARGET_NR_poll) || defined(TARGET_NR_ppoll)
6525# ifdef TARGET_NR_poll
9de5e440 6526 case TARGET_NR_poll:
d8035d4c
MF
6527# endif
6528# ifdef TARGET_NR_ppoll
6529 case TARGET_NR_ppoll:
6530# endif
9de5e440 6531 {
53a5960a 6532 struct target_pollfd *target_pfd;
9de5e440
FB
6533 unsigned int nfds = arg2;
6534 int timeout = arg3;
6535 struct pollfd *pfd;
7854b056 6536 unsigned int i;
9de5e440 6537
579a97f7
FB
6538 target_pfd = lock_user(VERIFY_WRITE, arg1, sizeof(struct target_pollfd) * nfds, 1);
6539 if (!target_pfd)
6540 goto efault;
d8035d4c 6541
9de5e440
FB
6542 pfd = alloca(sizeof(struct pollfd) * nfds);
6543 for(i = 0; i < nfds; i++) {
5cd4393b
FB
6544 pfd[i].fd = tswap32(target_pfd[i].fd);
6545 pfd[i].events = tswap16(target_pfd[i].events);
9de5e440 6546 }
d8035d4c
MF
6547
6548# ifdef TARGET_NR_ppoll
6549 if (num == TARGET_NR_ppoll) {
6550 struct timespec _timeout_ts, *timeout_ts = &_timeout_ts;
6551 target_sigset_t *target_set;
6552 sigset_t _set, *set = &_set;
6553
6554 if (arg3) {
6555 if (target_to_host_timespec(timeout_ts, arg3)) {
6556 unlock_user(target_pfd, arg1, 0);
6557 goto efault;
6558 }
6559 } else {
6560 timeout_ts = NULL;
6561 }
6562
6563 if (arg4) {
6564 target_set = lock_user(VERIFY_READ, arg4, sizeof(target_sigset_t), 1);
6565 if (!target_set) {
6566 unlock_user(target_pfd, arg1, 0);
6567 goto efault;
6568 }
6569 target_to_host_sigset(set, target_set);
6570 } else {
6571 set = NULL;
6572 }
6573
6574 ret = get_errno(sys_ppoll(pfd, nfds, timeout_ts, set, _NSIG/8));
6575
6576 if (!is_error(ret) && arg3) {
6577 host_to_target_timespec(arg3, timeout_ts);
6578 }
6579 if (arg4) {
6580 unlock_user(target_set, arg4, 0);
6581 }
6582 } else
6583# endif
6584 ret = get_errno(poll(pfd, nfds, timeout));
6585
9de5e440
FB
6586 if (!is_error(ret)) {
6587 for(i = 0; i < nfds; i++) {
5cd4393b 6588 target_pfd[i].revents = tswap16(pfd[i].revents);
9de5e440
FB
6589 }
6590 }
30cb4cde 6591 unlock_user(target_pfd, arg1, sizeof(struct target_pollfd) * nfds);
9de5e440
FB
6592 }
6593 break;
e5febef5 6594#endif
31e31b8a 6595 case TARGET_NR_flock:
9de5e440
FB
6596 /* NOTE: the flock constant seems to be the same for every
6597 Linux platform */
6598 ret = get_errno(flock(arg1, arg2));
31e31b8a
FB
6599 break;
6600 case TARGET_NR_readv:
6601 {
6602 int count = arg3;
31e31b8a 6603 struct iovec *vec;
31e31b8a
FB
6604
6605 vec = alloca(count * sizeof(struct iovec));
41df8411
FB
6606 if (lock_iovec(VERIFY_WRITE, vec, arg2, count, 0) < 0)
6607 goto efault;
31e31b8a 6608 ret = get_errno(readv(arg1, vec, count));
53a5960a 6609 unlock_iovec(vec, arg2, count, 1);
31e31b8a
FB
6610 }
6611 break;
6612 case TARGET_NR_writev:
6613 {
6614 int count = arg3;
31e31b8a 6615 struct iovec *vec;
31e31b8a
FB
6616
6617 vec = alloca(count * sizeof(struct iovec));
41df8411
FB
6618 if (lock_iovec(VERIFY_READ, vec, arg2, count, 1) < 0)
6619 goto efault;
31e31b8a 6620 ret = get_errno(writev(arg1, vec, count));
53a5960a 6621 unlock_iovec(vec, arg2, count, 0);
31e31b8a
FB
6622 }
6623 break;
6624 case TARGET_NR_getsid:
6625 ret = get_errno(getsid(arg1));
6626 break;
7a3148a9 6627#if defined(TARGET_NR_fdatasync) /* Not on alpha (osf_datasync ?) */
31e31b8a 6628 case TARGET_NR_fdatasync:
5cd4393b
FB
6629 ret = get_errno(fdatasync(arg1));
6630 break;
7a3148a9 6631#endif
31e31b8a 6632 case TARGET_NR__sysctl:
0da46a6e 6633 /* We don't implement this, but ENOTDIR is always a safe
29e619b1 6634 return value. */
0da46a6e
TS
6635 ret = -TARGET_ENOTDIR;
6636 break;
737de1d1
MF
6637 case TARGET_NR_sched_getaffinity:
6638 {
6639 unsigned int mask_size;
6640 unsigned long *mask;
6641
6642 /*
6643 * sched_getaffinity needs multiples of ulong, so need to take
6644 * care of mismatches between target ulong and host ulong sizes.
6645 */
6646 if (arg2 & (sizeof(abi_ulong) - 1)) {
6647 ret = -TARGET_EINVAL;
6648 break;
6649 }
6650 mask_size = (arg2 + (sizeof(*mask) - 1)) & ~(sizeof(*mask) - 1);
6651
6652 mask = alloca(mask_size);
6653 ret = get_errno(sys_sched_getaffinity(arg1, mask_size, mask));
6654
6655 if (!is_error(ret)) {
cd18f05e 6656 if (copy_to_user(arg3, mask, ret)) {
737de1d1
MF
6657 goto efault;
6658 }
737de1d1
MF
6659 }
6660 }
6661 break;
6662 case TARGET_NR_sched_setaffinity:
6663 {
6664 unsigned int mask_size;
6665 unsigned long *mask;
6666
6667 /*
6668 * sched_setaffinity needs multiples of ulong, so need to take
6669 * care of mismatches between target ulong and host ulong sizes.
6670 */
6671 if (arg2 & (sizeof(abi_ulong) - 1)) {
6672 ret = -TARGET_EINVAL;
6673 break;
6674 }
6675 mask_size = (arg2 + (sizeof(*mask) - 1)) & ~(sizeof(*mask) - 1);
6676
6677 mask = alloca(mask_size);
6678 if (!lock_user_struct(VERIFY_READ, p, arg3, 1)) {
6679 goto efault;
6680 }
6681 memcpy(mask, p, arg2);
6682 unlock_user_struct(p, arg2, 0);
6683
6684 ret = get_errno(sys_sched_setaffinity(arg1, mask_size, mask));
6685 }
6686 break;
31e31b8a 6687 case TARGET_NR_sched_setparam:
5cd4393b 6688 {
53a5960a 6689 struct sched_param *target_schp;
5cd4393b 6690 struct sched_param schp;
53a5960a 6691
579a97f7
FB
6692 if (!lock_user_struct(VERIFY_READ, target_schp, arg2, 1))
6693 goto efault;
5cd4393b 6694 schp.sched_priority = tswap32(target_schp->sched_priority);
53a5960a 6695 unlock_user_struct(target_schp, arg2, 0);
5cd4393b
FB
6696 ret = get_errno(sched_setparam(arg1, &schp));
6697 }
6698 break;
31e31b8a 6699 case TARGET_NR_sched_getparam:
5cd4393b 6700 {
53a5960a 6701 struct sched_param *target_schp;
5cd4393b
FB
6702 struct sched_param schp;
6703 ret = get_errno(sched_getparam(arg1, &schp));
6704 if (!is_error(ret)) {
579a97f7
FB
6705 if (!lock_user_struct(VERIFY_WRITE, target_schp, arg2, 0))
6706 goto efault;
5cd4393b 6707 target_schp->sched_priority = tswap32(schp.sched_priority);
53a5960a 6708 unlock_user_struct(target_schp, arg2, 1);
5cd4393b
FB
6709 }
6710 }
6711 break;
31e31b8a 6712 case TARGET_NR_sched_setscheduler:
5cd4393b 6713 {
53a5960a 6714 struct sched_param *target_schp;
5cd4393b 6715 struct sched_param schp;
579a97f7
FB
6716 if (!lock_user_struct(VERIFY_READ, target_schp, arg3, 1))
6717 goto efault;
5cd4393b 6718 schp.sched_priority = tswap32(target_schp->sched_priority);
53a5960a 6719 unlock_user_struct(target_schp, arg3, 0);
5cd4393b
FB
6720 ret = get_errno(sched_setscheduler(arg1, arg2, &schp));
6721 }
6722 break;
31e31b8a 6723 case TARGET_NR_sched_getscheduler:
5cd4393b
FB
6724 ret = get_errno(sched_getscheduler(arg1));
6725 break;
31e31b8a
FB
6726 case TARGET_NR_sched_yield:
6727 ret = get_errno(sched_yield());
6728 break;
6729 case TARGET_NR_sched_get_priority_max:
5cd4393b
FB
6730 ret = get_errno(sched_get_priority_max(arg1));
6731 break;
31e31b8a 6732 case TARGET_NR_sched_get_priority_min:
5cd4393b
FB
6733 ret = get_errno(sched_get_priority_min(arg1));
6734 break;
31e31b8a 6735 case TARGET_NR_sched_rr_get_interval:
5cd4393b 6736 {
5cd4393b
FB
6737 struct timespec ts;
6738 ret = get_errno(sched_rr_get_interval(arg1, &ts));
6739 if (!is_error(ret)) {
53a5960a 6740 host_to_target_timespec(arg2, &ts);
5cd4393b
FB
6741 }
6742 }
6743 break;
31e31b8a 6744 case TARGET_NR_nanosleep:
1b6b029e 6745 {
1b6b029e 6746 struct timespec req, rem;
53a5960a 6747 target_to_host_timespec(&req, arg1);
1b6b029e 6748 ret = get_errno(nanosleep(&req, &rem));
53a5960a
PB
6749 if (is_error(ret) && arg2) {
6750 host_to_target_timespec(arg2, &rem);
1b6b029e
FB
6751 }
6752 }
6753 break;
e5febef5 6754#ifdef TARGET_NR_query_module
31e31b8a 6755 case TARGET_NR_query_module:
5cd4393b 6756 goto unimplemented;
e5febef5
TS
6757#endif
6758#ifdef TARGET_NR_nfsservctl
31e31b8a 6759 case TARGET_NR_nfsservctl:
5cd4393b 6760 goto unimplemented;
e5febef5 6761#endif
31e31b8a 6762 case TARGET_NR_prctl:
e5574487
TS
6763 switch (arg1)
6764 {
6765 case PR_GET_PDEATHSIG:
6766 {
6767 int deathsig;
6768 ret = get_errno(prctl(arg1, &deathsig, arg3, arg4, arg5));
2f619698
FB
6769 if (!is_error(ret) && arg2
6770 && put_user_ual(deathsig, arg2))
6771 goto efault;
e5574487
TS
6772 }
6773 break;
6774 default:
6775 ret = get_errno(prctl(arg1, arg2, arg3, arg4, arg5));
6776 break;
6777 }
39b9aae1 6778 break;
d2fd1af7
FB
6779#ifdef TARGET_NR_arch_prctl
6780 case TARGET_NR_arch_prctl:
6781#if defined(TARGET_I386) && !defined(TARGET_ABI32)
6782 ret = do_arch_prctl(cpu_env, arg1, arg2);
6783 break;
6784#else
6785 goto unimplemented;
6786#endif
6787#endif
67867308 6788#ifdef TARGET_NR_pread
31e31b8a 6789 case TARGET_NR_pread:
a4ae00bc
AZ
6790#ifdef TARGET_ARM
6791 if (((CPUARMState *)cpu_env)->eabi)
6792 arg4 = arg5;
6793#endif
579a97f7
FB
6794 if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
6795 goto efault;
53a5960a
PB
6796 ret = get_errno(pread(arg1, p, arg3, arg4));
6797 unlock_user(p, arg2, ret);
206f0fa7 6798 break;
31e31b8a 6799 case TARGET_NR_pwrite:
a4ae00bc
AZ
6800#ifdef TARGET_ARM
6801 if (((CPUARMState *)cpu_env)->eabi)
6802 arg4 = arg5;
6803#endif
579a97f7
FB
6804 if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
6805 goto efault;
53a5960a
PB
6806 ret = get_errno(pwrite(arg1, p, arg3, arg4));
6807 unlock_user(p, arg2, 0);
206f0fa7 6808 break;
f2c7ba15
AJ
6809#endif
6810#ifdef TARGET_NR_pread64
6811 case TARGET_NR_pread64:
6812 if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
6813 goto efault;
6814 ret = get_errno(pread64(arg1, p, arg3, target_offset64(arg4, arg5)));
6815 unlock_user(p, arg2, ret);
6816 break;
6817 case TARGET_NR_pwrite64:
6818 if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
6819 goto efault;
6820 ret = get_errno(pwrite64(arg1, p, arg3, target_offset64(arg4, arg5)));
6821 unlock_user(p, arg2, 0);
6822 break;
67867308 6823#endif
31e31b8a 6824 case TARGET_NR_getcwd:
579a97f7
FB
6825 if (!(p = lock_user(VERIFY_WRITE, arg1, arg2, 0)))
6826 goto efault;
53a5960a
PB
6827 ret = get_errno(sys_getcwd1(p, arg2));
6828 unlock_user(p, arg1, ret);
31e31b8a
FB
6829 break;
6830 case TARGET_NR_capget:
5cd4393b 6831 goto unimplemented;
31e31b8a 6832 case TARGET_NR_capset:
5cd4393b 6833 goto unimplemented;
31e31b8a 6834 case TARGET_NR_sigaltstack:
198a74de 6835#if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_MIPS) || \
c761c154 6836 defined(TARGET_SPARC) || defined(TARGET_PPC) || defined(TARGET_ALPHA) || \
a4c075f1 6837 defined(TARGET_M68K) || defined(TARGET_S390X)
579a97f7 6838 ret = do_sigaltstack(arg1, arg2, get_sp_from_cpustate((CPUState *)cpu_env));
a04e134a
TS
6839 break;
6840#else
5cd4393b 6841 goto unimplemented;
a04e134a 6842#endif
31e31b8a 6843 case TARGET_NR_sendfile:
5cd4393b 6844 goto unimplemented;
ebc05488 6845#ifdef TARGET_NR_getpmsg
31e31b8a 6846 case TARGET_NR_getpmsg:
5cd4393b 6847 goto unimplemented;
ebc05488
FB
6848#endif
6849#ifdef TARGET_NR_putpmsg
31e31b8a 6850 case TARGET_NR_putpmsg:
5cd4393b 6851 goto unimplemented;
ebc05488 6852#endif
048f6b4d 6853#ifdef TARGET_NR_vfork
31e31b8a 6854 case TARGET_NR_vfork:
d865bab5
PB
6855 ret = get_errno(do_fork(cpu_env, CLONE_VFORK | CLONE_VM | SIGCHLD,
6856 0, 0, 0, 0));
31e31b8a 6857 break;
048f6b4d 6858#endif
ebc05488 6859#ifdef TARGET_NR_ugetrlimit
31e31b8a 6860 case TARGET_NR_ugetrlimit:
728584be
FB
6861 {
6862 struct rlimit rlim;
6863 ret = get_errno(getrlimit(arg1, &rlim));
6864 if (!is_error(ret)) {
53a5960a 6865 struct target_rlimit *target_rlim;
579a97f7
FB
6866 if (!lock_user_struct(VERIFY_WRITE, target_rlim, arg2, 0))
6867 goto efault;
81bbe906
TY
6868 target_rlim->rlim_cur = host_to_target_rlim(rlim.rlim_cur);
6869 target_rlim->rlim_max = host_to_target_rlim(rlim.rlim_max);
53a5960a 6870 unlock_user_struct(target_rlim, arg2, 1);
728584be
FB
6871 }
6872 break;
6873 }
ebc05488 6874#endif
a315a145 6875#ifdef TARGET_NR_truncate64
31e31b8a 6876 case TARGET_NR_truncate64:
579a97f7
FB
6877 if (!(p = lock_user_string(arg1)))
6878 goto efault;
53a5960a
PB
6879 ret = target_truncate64(cpu_env, p, arg2, arg3, arg4);
6880 unlock_user(p, arg1, 0);
667f38b1 6881 break;
a315a145
FB
6882#endif
6883#ifdef TARGET_NR_ftruncate64
31e31b8a 6884 case TARGET_NR_ftruncate64:
ce4defa0 6885 ret = target_ftruncate64(cpu_env, arg1, arg2, arg3, arg4);
667f38b1 6886 break;
a315a145
FB
6887#endif
6888#ifdef TARGET_NR_stat64
31e31b8a 6889 case TARGET_NR_stat64:
579a97f7
FB
6890 if (!(p = lock_user_string(arg1)))
6891 goto efault;
53a5960a
PB
6892 ret = get_errno(stat(path(p), &st));
6893 unlock_user(p, arg1, 0);
6a24a778
AZ
6894 if (!is_error(ret))
6895 ret = host_to_target_stat64(cpu_env, arg2, &st);
6896 break;
a315a145
FB
6897#endif
6898#ifdef TARGET_NR_lstat64
31e31b8a 6899 case TARGET_NR_lstat64:
579a97f7
FB
6900 if (!(p = lock_user_string(arg1)))
6901 goto efault;
53a5960a
PB
6902 ret = get_errno(lstat(path(p), &st));
6903 unlock_user(p, arg1, 0);
6a24a778
AZ
6904 if (!is_error(ret))
6905 ret = host_to_target_stat64(cpu_env, arg2, &st);
6906 break;
a315a145
FB
6907#endif
6908#ifdef TARGET_NR_fstat64
31e31b8a 6909 case TARGET_NR_fstat64:
6a24a778
AZ
6910 ret = get_errno(fstat(arg1, &st));
6911 if (!is_error(ret))
6912 ret = host_to_target_stat64(cpu_env, arg2, &st);
6913 break;
ce4defa0 6914#endif
9d33b76b
AJ
6915#if (defined(TARGET_NR_fstatat64) || defined(TARGET_NR_newfstatat)) && \
6916 (defined(__NR_fstatat64) || defined(__NR_newfstatat))
6917#ifdef TARGET_NR_fstatat64
6a24a778 6918 case TARGET_NR_fstatat64:
9d33b76b
AJ
6919#endif
6920#ifdef TARGET_NR_newfstatat
6921 case TARGET_NR_newfstatat:
6922#endif
6a24a778
AZ
6923 if (!(p = lock_user_string(arg2)))
6924 goto efault;
9d33b76b 6925#ifdef __NR_fstatat64
6a24a778 6926 ret = get_errno(sys_fstatat64(arg1, path(p), &st, arg4));
9d33b76b
AJ
6927#else
6928 ret = get_errno(sys_newfstatat(arg1, path(p), &st, arg4));
6929#endif
6a24a778
AZ
6930 if (!is_error(ret))
6931 ret = host_to_target_stat64(cpu_env, arg3, &st);
60cd49d5 6932 break;
a315a145 6933#endif
67867308 6934 case TARGET_NR_lchown:
579a97f7
FB
6935 if (!(p = lock_user_string(arg1)))
6936 goto efault;
53a5960a
PB
6937 ret = get_errno(lchown(p, low2highuid(arg2), low2highgid(arg3)));
6938 unlock_user(p, arg1, 0);
67867308 6939 break;
0c866a7e 6940#ifdef TARGET_NR_getuid
67867308
FB
6941 case TARGET_NR_getuid:
6942 ret = get_errno(high2lowuid(getuid()));
6943 break;
0c866a7e
RV
6944#endif
6945#ifdef TARGET_NR_getgid
67867308
FB
6946 case TARGET_NR_getgid:
6947 ret = get_errno(high2lowgid(getgid()));
6948 break;
0c866a7e
RV
6949#endif
6950#ifdef TARGET_NR_geteuid
67867308
FB
6951 case TARGET_NR_geteuid:
6952 ret = get_errno(high2lowuid(geteuid()));
6953 break;
0c866a7e
RV
6954#endif
6955#ifdef TARGET_NR_getegid
67867308
FB
6956 case TARGET_NR_getegid:
6957 ret = get_errno(high2lowgid(getegid()));
6958 break;
0c866a7e 6959#endif
67867308
FB
6960 case TARGET_NR_setreuid:
6961 ret = get_errno(setreuid(low2highuid(arg1), low2highuid(arg2)));
6962 break;
6963 case TARGET_NR_setregid:
6964 ret = get_errno(setregid(low2highgid(arg1), low2highgid(arg2)));
6965 break;
6966 case TARGET_NR_getgroups:
6967 {
6968 int gidsetsize = arg1;
0c866a7e 6969 target_id *target_grouplist;
67867308
FB
6970 gid_t *grouplist;
6971 int i;
6972
6973 grouplist = alloca(gidsetsize * sizeof(gid_t));
6974 ret = get_errno(getgroups(gidsetsize, grouplist));
cb3bc233
AZ
6975 if (gidsetsize == 0)
6976 break;
67867308 6977 if (!is_error(ret)) {
579a97f7
FB
6978 target_grouplist = lock_user(VERIFY_WRITE, arg2, gidsetsize * 2, 0);
6979 if (!target_grouplist)
6980 goto efault;
a2155fcc 6981 for(i = 0;i < ret; i++)
0c866a7e 6982 target_grouplist[i] = tswapid(high2lowgid(grouplist[i]));
53a5960a 6983 unlock_user(target_grouplist, arg2, gidsetsize * 2);
67867308
FB
6984 }
6985 }
6986 break;
6987 case TARGET_NR_setgroups:
6988 {
6989 int gidsetsize = arg1;
0c866a7e 6990 target_id *target_grouplist;
67867308
FB
6991 gid_t *grouplist;
6992 int i;
6993
6994 grouplist = alloca(gidsetsize * sizeof(gid_t));
579a97f7
FB
6995 target_grouplist = lock_user(VERIFY_READ, arg2, gidsetsize * 2, 1);
6996 if (!target_grouplist) {
6997 ret = -TARGET_EFAULT;
6998 goto fail;
6999 }
67867308 7000 for(i = 0;i < gidsetsize; i++)
0c866a7e 7001 grouplist[i] = low2highgid(tswapid(target_grouplist[i]));
53a5960a 7002 unlock_user(target_grouplist, arg2, 0);
67867308
FB
7003 ret = get_errno(setgroups(gidsetsize, grouplist));
7004 }
7005 break;
7006 case TARGET_NR_fchown:
7007 ret = get_errno(fchown(arg1, low2highuid(arg2), low2highgid(arg3)));
7008 break;
ccfa72b7
TS
7009#if defined(TARGET_NR_fchownat) && defined(__NR_fchownat)
7010 case TARGET_NR_fchownat:
579a97f7
FB
7011 if (!(p = lock_user_string(arg2)))
7012 goto efault;
7013 ret = get_errno(sys_fchownat(arg1, p, low2highuid(arg3), low2highgid(arg4), arg5));
7014 unlock_user(p, arg2, 0);
ccfa72b7
TS
7015 break;
7016#endif
67867308
FB
7017#ifdef TARGET_NR_setresuid
7018 case TARGET_NR_setresuid:
5fafdf24
TS
7019 ret = get_errno(setresuid(low2highuid(arg1),
7020 low2highuid(arg2),
67867308
FB
7021 low2highuid(arg3)));
7022 break;
7023#endif
7024#ifdef TARGET_NR_getresuid
7025 case TARGET_NR_getresuid:
7026 {
53a5960a 7027 uid_t ruid, euid, suid;
67867308
FB
7028 ret = get_errno(getresuid(&ruid, &euid, &suid));
7029 if (!is_error(ret)) {
2f619698
FB
7030 if (put_user_u16(high2lowuid(ruid), arg1)
7031 || put_user_u16(high2lowuid(euid), arg2)
7032 || put_user_u16(high2lowuid(suid), arg3))
7033 goto efault;
67867308
FB
7034 }
7035 }
7036 break;
7037#endif
7038#ifdef TARGET_NR_getresgid
7039 case TARGET_NR_setresgid:
5fafdf24
TS
7040 ret = get_errno(setresgid(low2highgid(arg1),
7041 low2highgid(arg2),
67867308
FB
7042 low2highgid(arg3)));
7043 break;
7044#endif
7045#ifdef TARGET_NR_getresgid
7046 case TARGET_NR_getresgid:
7047 {
53a5960a 7048 gid_t rgid, egid, sgid;
67867308
FB
7049 ret = get_errno(getresgid(&rgid, &egid, &sgid));
7050 if (!is_error(ret)) {
2f619698
FB
7051 if (put_user_u16(high2lowgid(rgid), arg1)
7052 || put_user_u16(high2lowgid(egid), arg2)
7053 || put_user_u16(high2lowgid(sgid), arg3))
7054 goto efault;
67867308
FB
7055 }
7056 }
7057 break;
7058#endif
7059 case TARGET_NR_chown:
579a97f7
FB
7060 if (!(p = lock_user_string(arg1)))
7061 goto efault;
53a5960a
PB
7062 ret = get_errno(chown(p, low2highuid(arg2), low2highgid(arg3)));
7063 unlock_user(p, arg1, 0);
67867308
FB
7064 break;
7065 case TARGET_NR_setuid:
7066 ret = get_errno(setuid(low2highuid(arg1)));
7067 break;
7068 case TARGET_NR_setgid:
7069 ret = get_errno(setgid(low2highgid(arg1)));
7070 break;
7071 case TARGET_NR_setfsuid:
7072 ret = get_errno(setfsuid(arg1));
7073 break;
7074 case TARGET_NR_setfsgid:
7075 ret = get_errno(setfsgid(arg1));
7076 break;
67867308 7077
a315a145 7078#ifdef TARGET_NR_lchown32
31e31b8a 7079 case TARGET_NR_lchown32:
579a97f7
FB
7080 if (!(p = lock_user_string(arg1)))
7081 goto efault;
53a5960a
PB
7082 ret = get_errno(lchown(p, arg2, arg3));
7083 unlock_user(p, arg1, 0);
b03c60f3 7084 break;
a315a145
FB
7085#endif
7086#ifdef TARGET_NR_getuid32
31e31b8a 7087 case TARGET_NR_getuid32:
b03c60f3
FB
7088 ret = get_errno(getuid());
7089 break;
a315a145 7090#endif
64b4d28c
AJ
7091
7092#if defined(TARGET_NR_getxuid) && defined(TARGET_ALPHA)
7093 /* Alpha specific */
7094 case TARGET_NR_getxuid:
ba0e276d
RH
7095 {
7096 uid_t euid;
7097 euid=geteuid();
7098 ((CPUAlphaState *)cpu_env)->ir[IR_A4]=euid;
7099 }
64b4d28c
AJ
7100 ret = get_errno(getuid());
7101 break;
7102#endif
7103#if defined(TARGET_NR_getxgid) && defined(TARGET_ALPHA)
7104 /* Alpha specific */
7105 case TARGET_NR_getxgid:
ba0e276d
RH
7106 {
7107 uid_t egid;
7108 egid=getegid();
7109 ((CPUAlphaState *)cpu_env)->ir[IR_A4]=egid;
7110 }
64b4d28c
AJ
7111 ret = get_errno(getgid());
7112 break;
7113#endif
ba0e276d
RH
7114#if defined(TARGET_NR_osf_getsysinfo) && defined(TARGET_ALPHA)
7115 /* Alpha specific */
7116 case TARGET_NR_osf_getsysinfo:
7117 ret = -TARGET_EOPNOTSUPP;
7118 switch (arg1) {
7119 case TARGET_GSI_IEEE_FP_CONTROL:
7120 {
7121 uint64_t swcr, fpcr = cpu_alpha_load_fpcr (cpu_env);
7122
7123 /* Copied from linux ieee_fpcr_to_swcr. */
7124 swcr = (fpcr >> 35) & SWCR_STATUS_MASK;
7125 swcr |= (fpcr >> 36) & SWCR_MAP_DMZ;
7126 swcr |= (~fpcr >> 48) & (SWCR_TRAP_ENABLE_INV
7127 | SWCR_TRAP_ENABLE_DZE
7128 | SWCR_TRAP_ENABLE_OVF);
7129 swcr |= (~fpcr >> 57) & (SWCR_TRAP_ENABLE_UNF
7130 | SWCR_TRAP_ENABLE_INE);
7131 swcr |= (fpcr >> 47) & SWCR_MAP_UMZ;
7132 swcr |= (~fpcr >> 41) & SWCR_TRAP_ENABLE_DNO;
7133
7134 if (put_user_u64 (swcr, arg2))
7135 goto efault;
7136 ret = 0;
7137 }
7138 break;
7139
7140 /* case GSI_IEEE_STATE_AT_SIGNAL:
7141 -- Not implemented in linux kernel.
7142 case GSI_UACPROC:
7143 -- Retrieves current unaligned access state; not much used.
7144 case GSI_PROC_TYPE:
7145 -- Retrieves implver information; surely not used.
7146 case GSI_GET_HWRPB:
7147 -- Grabs a copy of the HWRPB; surely not used.
7148 */
7149 }
7150 break;
7151#endif
7152#if defined(TARGET_NR_osf_setsysinfo) && defined(TARGET_ALPHA)
7153 /* Alpha specific */
7154 case TARGET_NR_osf_setsysinfo:
7155 ret = -TARGET_EOPNOTSUPP;
7156 switch (arg1) {
7157 case TARGET_SSI_IEEE_FP_CONTROL:
7158 case TARGET_SSI_IEEE_RAISE_EXCEPTION:
7159 {
7160 uint64_t swcr, fpcr, orig_fpcr;
7161
7162 if (get_user_u64 (swcr, arg2))
7163 goto efault;
7164 orig_fpcr = cpu_alpha_load_fpcr (cpu_env);
7165 fpcr = orig_fpcr & FPCR_DYN_MASK;
7166
7167 /* Copied from linux ieee_swcr_to_fpcr. */
7168 fpcr |= (swcr & SWCR_STATUS_MASK) << 35;
7169 fpcr |= (swcr & SWCR_MAP_DMZ) << 36;
7170 fpcr |= (~swcr & (SWCR_TRAP_ENABLE_INV
7171 | SWCR_TRAP_ENABLE_DZE
7172 | SWCR_TRAP_ENABLE_OVF)) << 48;
7173 fpcr |= (~swcr & (SWCR_TRAP_ENABLE_UNF
7174 | SWCR_TRAP_ENABLE_INE)) << 57;
7175 fpcr |= (swcr & SWCR_MAP_UMZ ? FPCR_UNDZ | FPCR_UNFD : 0);
7176 fpcr |= (~swcr & SWCR_TRAP_ENABLE_DNO) << 41;
7177
7178 cpu_alpha_store_fpcr (cpu_env, fpcr);
7179 ret = 0;
7180
7181 if (arg1 == TARGET_SSI_IEEE_RAISE_EXCEPTION) {
7182 /* Old exceptions are not signaled. */
7183 fpcr &= ~(orig_fpcr & FPCR_STATUS_MASK);
7184
7185 /* If any exceptions set by this call, and are unmasked,
7186 send a signal. */
7187 /* ??? FIXME */
7188 }
7189 }
7190 break;
7191
7192 /* case SSI_NVPAIRS:
7193 -- Used with SSIN_UACPROC to enable unaligned accesses.
7194 case SSI_IEEE_STATE_AT_SIGNAL:
7195 case SSI_IEEE_IGNORE_STATE_AT_SIGNAL:
7196 -- Not implemented in linux kernel
7197 */
7198 }
7199 break;
7200#endif
7201#ifdef TARGET_NR_osf_sigprocmask
7202 /* Alpha specific. */
7203 case TARGET_NR_osf_sigprocmask:
7204 {
7205 abi_ulong mask;
bc088ba1 7206 int how;
ba0e276d
RH
7207 sigset_t set, oldset;
7208
7209 switch(arg1) {
7210 case TARGET_SIG_BLOCK:
7211 how = SIG_BLOCK;
7212 break;
7213 case TARGET_SIG_UNBLOCK:
7214 how = SIG_UNBLOCK;
7215 break;
7216 case TARGET_SIG_SETMASK:
7217 how = SIG_SETMASK;
7218 break;
7219 default:
7220 ret = -TARGET_EINVAL;
7221 goto fail;
7222 }
7223 mask = arg2;
7224 target_to_host_old_sigset(&set, &mask);
bc088ba1 7225 sigprocmask(how, &set, &oldset);
ba0e276d
RH
7226 host_to_target_old_sigset(&mask, &oldset);
7227 ret = mask;
7228 }
7229 break;
7230#endif
64b4d28c 7231
a315a145 7232#ifdef TARGET_NR_getgid32
31e31b8a 7233 case TARGET_NR_getgid32:
b03c60f3
FB
7234 ret = get_errno(getgid());
7235 break;
a315a145
FB
7236#endif
7237#ifdef TARGET_NR_geteuid32
31e31b8a 7238 case TARGET_NR_geteuid32:
b03c60f3
FB
7239 ret = get_errno(geteuid());
7240 break;
a315a145
FB
7241#endif
7242#ifdef TARGET_NR_getegid32
31e31b8a 7243 case TARGET_NR_getegid32:
b03c60f3
FB
7244 ret = get_errno(getegid());
7245 break;
a315a145
FB
7246#endif
7247#ifdef TARGET_NR_setreuid32
31e31b8a 7248 case TARGET_NR_setreuid32:
b03c60f3
FB
7249 ret = get_errno(setreuid(arg1, arg2));
7250 break;
a315a145
FB
7251#endif
7252#ifdef TARGET_NR_setregid32
31e31b8a 7253 case TARGET_NR_setregid32:
b03c60f3
FB
7254 ret = get_errno(setregid(arg1, arg2));
7255 break;
a315a145
FB
7256#endif
7257#ifdef TARGET_NR_getgroups32
31e31b8a 7258 case TARGET_NR_getgroups32:
99c475ab
FB
7259 {
7260 int gidsetsize = arg1;
53a5960a 7261 uint32_t *target_grouplist;
99c475ab
FB
7262 gid_t *grouplist;
7263 int i;
7264
7265 grouplist = alloca(gidsetsize * sizeof(gid_t));
7266 ret = get_errno(getgroups(gidsetsize, grouplist));
cb3bc233
AZ
7267 if (gidsetsize == 0)
7268 break;
99c475ab 7269 if (!is_error(ret)) {
579a97f7
FB
7270 target_grouplist = lock_user(VERIFY_WRITE, arg2, gidsetsize * 4, 0);
7271 if (!target_grouplist) {
7272 ret = -TARGET_EFAULT;
7273 goto fail;
7274 }
a2155fcc 7275 for(i = 0;i < ret; i++)
53a5960a
PB
7276 target_grouplist[i] = tswap32(grouplist[i]);
7277 unlock_user(target_grouplist, arg2, gidsetsize * 4);
99c475ab
FB
7278 }
7279 }
7280 break;
a315a145
FB
7281#endif
7282#ifdef TARGET_NR_setgroups32
31e31b8a 7283 case TARGET_NR_setgroups32:
99c475ab
FB
7284 {
7285 int gidsetsize = arg1;
53a5960a 7286 uint32_t *target_grouplist;
99c475ab
FB
7287 gid_t *grouplist;
7288 int i;
3b46e624 7289
99c475ab 7290 grouplist = alloca(gidsetsize * sizeof(gid_t));
579a97f7
FB
7291 target_grouplist = lock_user(VERIFY_READ, arg2, gidsetsize * 4, 1);
7292 if (!target_grouplist) {
7293 ret = -TARGET_EFAULT;
7294 goto fail;
7295 }
99c475ab 7296 for(i = 0;i < gidsetsize; i++)
53a5960a
PB
7297 grouplist[i] = tswap32(target_grouplist[i]);
7298 unlock_user(target_grouplist, arg2, 0);
99c475ab
FB
7299 ret = get_errno(setgroups(gidsetsize, grouplist));
7300 }
7301 break;
a315a145
FB
7302#endif
7303#ifdef TARGET_NR_fchown32
31e31b8a 7304 case TARGET_NR_fchown32:
b03c60f3
FB
7305 ret = get_errno(fchown(arg1, arg2, arg3));
7306 break;
a315a145
FB
7307#endif
7308#ifdef TARGET_NR_setresuid32
31e31b8a 7309 case TARGET_NR_setresuid32:
b03c60f3
FB
7310 ret = get_errno(setresuid(arg1, arg2, arg3));
7311 break;
a315a145
FB
7312#endif
7313#ifdef TARGET_NR_getresuid32
31e31b8a 7314 case TARGET_NR_getresuid32:
b03c60f3 7315 {
53a5960a 7316 uid_t ruid, euid, suid;
b03c60f3
FB
7317 ret = get_errno(getresuid(&ruid, &euid, &suid));
7318 if (!is_error(ret)) {
2f619698
FB
7319 if (put_user_u32(ruid, arg1)
7320 || put_user_u32(euid, arg2)
7321 || put_user_u32(suid, arg3))
7322 goto efault;
b03c60f3
FB
7323 }
7324 }
7325 break;
a315a145
FB
7326#endif
7327#ifdef TARGET_NR_setresgid32
31e31b8a 7328 case TARGET_NR_setresgid32:
b03c60f3
FB
7329 ret = get_errno(setresgid(arg1, arg2, arg3));
7330 break;
a315a145
FB
7331#endif
7332#ifdef TARGET_NR_getresgid32
31e31b8a 7333 case TARGET_NR_getresgid32:
b03c60f3 7334 {
53a5960a 7335 gid_t rgid, egid, sgid;
b03c60f3
FB
7336 ret = get_errno(getresgid(&rgid, &egid, &sgid));
7337 if (!is_error(ret)) {
2f619698
FB
7338 if (put_user_u32(rgid, arg1)
7339 || put_user_u32(egid, arg2)
7340 || put_user_u32(sgid, arg3))
7341 goto efault;
b03c60f3
FB
7342 }
7343 }
7344 break;
a315a145
FB
7345#endif
7346#ifdef TARGET_NR_chown32
31e31b8a 7347 case TARGET_NR_chown32:
579a97f7
FB
7348 if (!(p = lock_user_string(arg1)))
7349 goto efault;
53a5960a
PB
7350 ret = get_errno(chown(p, arg2, arg3));
7351 unlock_user(p, arg1, 0);
b03c60f3 7352 break;
a315a145
FB
7353#endif
7354#ifdef TARGET_NR_setuid32
31e31b8a 7355 case TARGET_NR_setuid32:
b03c60f3
FB
7356 ret = get_errno(setuid(arg1));
7357 break;
a315a145
FB
7358#endif
7359#ifdef TARGET_NR_setgid32
31e31b8a 7360 case TARGET_NR_setgid32:
b03c60f3
FB
7361 ret = get_errno(setgid(arg1));
7362 break;
a315a145
FB
7363#endif
7364#ifdef TARGET_NR_setfsuid32
31e31b8a 7365 case TARGET_NR_setfsuid32:
b03c60f3
FB
7366 ret = get_errno(setfsuid(arg1));
7367 break;
a315a145
FB
7368#endif
7369#ifdef TARGET_NR_setfsgid32
31e31b8a 7370 case TARGET_NR_setfsgid32:
b03c60f3
FB
7371 ret = get_errno(setfsgid(arg1));
7372 break;
a315a145 7373#endif
67867308 7374
31e31b8a 7375 case TARGET_NR_pivot_root:
b03c60f3 7376 goto unimplemented;
ffa65c3b 7377#ifdef TARGET_NR_mincore
31e31b8a 7378 case TARGET_NR_mincore:
04bb9ace
AJ
7379 {
7380 void *a;
7381 ret = -TARGET_EFAULT;
7382 if (!(a = lock_user(VERIFY_READ, arg1,arg2, 0)))
7383 goto efault;
7384 if (!(p = lock_user_string(arg3)))
7385 goto mincore_fail;
7386 ret = get_errno(mincore(a, arg2, p));
7387 unlock_user(p, arg3, ret);
7388 mincore_fail:
7389 unlock_user(a, arg1, 0);
7390 }
7391 break;
ffa65c3b 7392#endif
408321b6
AJ
7393#ifdef TARGET_NR_arm_fadvise64_64
7394 case TARGET_NR_arm_fadvise64_64:
7395 {
7396 /*
7397 * arm_fadvise64_64 looks like fadvise64_64 but
7398 * with different argument order
7399 */
7400 abi_long temp;
7401 temp = arg3;
7402 arg3 = arg4;
7403 arg4 = temp;
7404 }
7405#endif
e72d2cc7 7406#if defined(TARGET_NR_fadvise64_64) || defined(TARGET_NR_arm_fadvise64_64) || defined(TARGET_NR_fadvise64)
408321b6
AJ
7407#ifdef TARGET_NR_fadvise64_64
7408 case TARGET_NR_fadvise64_64:
7409#endif
e72d2cc7
UH
7410#ifdef TARGET_NR_fadvise64
7411 case TARGET_NR_fadvise64:
7412#endif
7413#ifdef TARGET_S390X
7414 switch (arg4) {
7415 case 4: arg4 = POSIX_FADV_NOREUSE + 1; break; /* make sure it's an invalid value */
7416 case 5: arg4 = POSIX_FADV_NOREUSE + 2; break; /* ditto */
7417 case 6: arg4 = POSIX_FADV_DONTNEED; break;
7418 case 7: arg4 = POSIX_FADV_NOREUSE; break;
7419 default: break;
7420 }
7421#endif
7422 ret = -posix_fadvise(arg1, arg2, arg3, arg4);
408321b6
AJ
7423 break;
7424#endif
ffa65c3b 7425#ifdef TARGET_NR_madvise
31e31b8a 7426 case TARGET_NR_madvise:
24836689
PB
7427 /* A straight passthrough may not be safe because qemu sometimes
7428 turns private flie-backed mappings into anonymous mappings.
7429 This will break MADV_DONTNEED.
7430 This is a hint, so ignoring and returning success is ok. */
7431 ret = get_errno(0);
7432 break;
ffa65c3b 7433#endif
992f48a0 7434#if TARGET_ABI_BITS == 32
31e31b8a 7435 case TARGET_NR_fcntl64:
77e4672d 7436 {
b1e341eb 7437 int cmd;
77e4672d 7438 struct flock64 fl;
53a5960a 7439 struct target_flock64 *target_fl;
ce4defa0 7440#ifdef TARGET_ARM
53a5960a 7441 struct target_eabi_flock64 *target_efl;
ce4defa0 7442#endif
77e4672d 7443
5f106811
APR
7444 cmd = target_to_host_fcntl_cmd(arg2);
7445 if (cmd == -TARGET_EINVAL)
7446 return cmd;
b1e341eb 7447
60cd49d5 7448 switch(arg2) {
b1e341eb 7449 case TARGET_F_GETLK64:
5813427b
TS
7450#ifdef TARGET_ARM
7451 if (((CPUARMState *)cpu_env)->eabi) {
9ee1fa2c
FB
7452 if (!lock_user_struct(VERIFY_READ, target_efl, arg3, 1))
7453 goto efault;
5813427b
TS
7454 fl.l_type = tswap16(target_efl->l_type);
7455 fl.l_whence = tswap16(target_efl->l_whence);
7456 fl.l_start = tswap64(target_efl->l_start);
7457 fl.l_len = tswap64(target_efl->l_len);
7e22e546 7458 fl.l_pid = tswap32(target_efl->l_pid);
5813427b
TS
7459 unlock_user_struct(target_efl, arg3, 0);
7460 } else
7461#endif
7462 {
9ee1fa2c
FB
7463 if (!lock_user_struct(VERIFY_READ, target_fl, arg3, 1))
7464 goto efault;
5813427b
TS
7465 fl.l_type = tswap16(target_fl->l_type);
7466 fl.l_whence = tswap16(target_fl->l_whence);
7467 fl.l_start = tswap64(target_fl->l_start);
7468 fl.l_len = tswap64(target_fl->l_len);
7e22e546 7469 fl.l_pid = tswap32(target_fl->l_pid);
5813427b
TS
7470 unlock_user_struct(target_fl, arg3, 0);
7471 }
b1e341eb 7472 ret = get_errno(fcntl(arg1, cmd, &fl));
77e4672d 7473 if (ret == 0) {
ce4defa0
PB
7474#ifdef TARGET_ARM
7475 if (((CPUARMState *)cpu_env)->eabi) {
9ee1fa2c
FB
7476 if (!lock_user_struct(VERIFY_WRITE, target_efl, arg3, 0))
7477 goto efault;
ce4defa0
PB
7478 target_efl->l_type = tswap16(fl.l_type);
7479 target_efl->l_whence = tswap16(fl.l_whence);
7480 target_efl->l_start = tswap64(fl.l_start);
7481 target_efl->l_len = tswap64(fl.l_len);
7e22e546 7482 target_efl->l_pid = tswap32(fl.l_pid);
53a5960a 7483 unlock_user_struct(target_efl, arg3, 1);
ce4defa0
PB
7484 } else
7485#endif
7486 {
9ee1fa2c
FB
7487 if (!lock_user_struct(VERIFY_WRITE, target_fl, arg3, 0))
7488 goto efault;
ce4defa0
PB
7489 target_fl->l_type = tswap16(fl.l_type);
7490 target_fl->l_whence = tswap16(fl.l_whence);
7491 target_fl->l_start = tswap64(fl.l_start);
7492 target_fl->l_len = tswap64(fl.l_len);
7e22e546 7493 target_fl->l_pid = tswap32(fl.l_pid);
53a5960a 7494 unlock_user_struct(target_fl, arg3, 1);
ce4defa0 7495 }
77e4672d
FB
7496 }
7497 break;
7498
b1e341eb
TS
7499 case TARGET_F_SETLK64:
7500 case TARGET_F_SETLKW64:
ce4defa0
PB
7501#ifdef TARGET_ARM
7502 if (((CPUARMState *)cpu_env)->eabi) {
9ee1fa2c
FB
7503 if (!lock_user_struct(VERIFY_READ, target_efl, arg3, 1))
7504 goto efault;
ce4defa0
PB
7505 fl.l_type = tswap16(target_efl->l_type);
7506 fl.l_whence = tswap16(target_efl->l_whence);
7507 fl.l_start = tswap64(target_efl->l_start);
7508 fl.l_len = tswap64(target_efl->l_len);
7e22e546 7509 fl.l_pid = tswap32(target_efl->l_pid);
53a5960a 7510 unlock_user_struct(target_efl, arg3, 0);
ce4defa0
PB
7511 } else
7512#endif
7513 {
9ee1fa2c
FB
7514 if (!lock_user_struct(VERIFY_READ, target_fl, arg3, 1))
7515 goto efault;
ce4defa0
PB
7516 fl.l_type = tswap16(target_fl->l_type);
7517 fl.l_whence = tswap16(target_fl->l_whence);
7518 fl.l_start = tswap64(target_fl->l_start);
7519 fl.l_len = tswap64(target_fl->l_len);
7e22e546 7520 fl.l_pid = tswap32(target_fl->l_pid);
53a5960a 7521 unlock_user_struct(target_fl, arg3, 0);
ce4defa0 7522 }
b1e341eb 7523 ret = get_errno(fcntl(arg1, cmd, &fl));
77e4672d 7524 break;
60cd49d5 7525 default:
5f106811 7526 ret = do_fcntl(arg1, arg2, arg3);
60cd49d5
FB
7527 break;
7528 }
77e4672d
FB
7529 break;
7530 }
60cd49d5 7531#endif
7d600c80
TS
7532#ifdef TARGET_NR_cacheflush
7533 case TARGET_NR_cacheflush:
7534 /* self-modifying code is handled automatically, so nothing needed */
7535 ret = 0;
7536 break;
7537#endif
ebc05488 7538#ifdef TARGET_NR_security
31e31b8a
FB
7539 case TARGET_NR_security:
7540 goto unimplemented;
c573ff67
FB
7541#endif
7542#ifdef TARGET_NR_getpagesize
7543 case TARGET_NR_getpagesize:
7544 ret = TARGET_PAGE_SIZE;
7545 break;
ebc05488 7546#endif
31e31b8a
FB
7547 case TARGET_NR_gettid:
7548 ret = get_errno(gettid());
7549 break;
e5febef5 7550#ifdef TARGET_NR_readahead
31e31b8a 7551 case TARGET_NR_readahead:
2054ac9b
AJ
7552#if TARGET_ABI_BITS == 32
7553#ifdef TARGET_ARM
7554 if (((CPUARMState *)cpu_env)->eabi)
7555 {
7556 arg2 = arg3;
7557 arg3 = arg4;
7558 arg4 = arg5;
7559 }
7560#endif
7561 ret = get_errno(readahead(arg1, ((off64_t)arg3 << 32) | arg2, arg4));
7562#else
7563 ret = get_errno(readahead(arg1, arg2, arg3));
7564#endif
7565 break;
e5febef5 7566#endif
ebc05488 7567#ifdef TARGET_NR_setxattr
31e31b8a
FB
7568 case TARGET_NR_setxattr:
7569 case TARGET_NR_lsetxattr:
7570 case TARGET_NR_fsetxattr:
7571 case TARGET_NR_getxattr:
7572 case TARGET_NR_lgetxattr:
7573 case TARGET_NR_fgetxattr:
7574 case TARGET_NR_listxattr:
7575 case TARGET_NR_llistxattr:
7576 case TARGET_NR_flistxattr:
7577 case TARGET_NR_removexattr:
7578 case TARGET_NR_lremovexattr:
7579 case TARGET_NR_fremovexattr:
6f932f91
AP
7580 ret = -TARGET_EOPNOTSUPP;
7581 break;
ebc05488
FB
7582#endif
7583#ifdef TARGET_NR_set_thread_area
5cd4393b 7584 case TARGET_NR_set_thread_area:
8d18e893 7585#if defined(TARGET_MIPS)
6f5b89a0
TS
7586 ((CPUMIPSState *) cpu_env)->tls_value = arg1;
7587 ret = 0;
7588 break;
ef96779b
EI
7589#elif defined(TARGET_CRIS)
7590 if (arg1 & 0xff)
7591 ret = -TARGET_EINVAL;
7592 else {
7593 ((CPUCRISState *) cpu_env)->pregs[PR_PID] = arg1;
7594 ret = 0;
7595 }
7596 break;
8d18e893
FB
7597#elif defined(TARGET_I386) && defined(TARGET_ABI32)
7598 ret = do_set_thread_area(cpu_env, arg1);
7599 break;
6f5b89a0
TS
7600#else
7601 goto unimplemented_nowarn;
7602#endif
7603#endif
7604#ifdef TARGET_NR_get_thread_area
5cd4393b 7605 case TARGET_NR_get_thread_area:
8d18e893
FB
7606#if defined(TARGET_I386) && defined(TARGET_ABI32)
7607 ret = do_get_thread_area(cpu_env, arg1);
7608#else
5cd4393b 7609 goto unimplemented_nowarn;
48dc41eb 7610#endif
8d18e893 7611#endif
48dc41eb
FB
7612#ifdef TARGET_NR_getdomainname
7613 case TARGET_NR_getdomainname:
7614 goto unimplemented_nowarn;
ebc05488 7615#endif
6f5b89a0 7616
b5906f95
TS
7617#ifdef TARGET_NR_clock_gettime
7618 case TARGET_NR_clock_gettime:
7619 {
7620 struct timespec ts;
7621 ret = get_errno(clock_gettime(arg1, &ts));
7622 if (!is_error(ret)) {
7623 host_to_target_timespec(arg2, &ts);
7624 }
7625 break;
7626 }
7627#endif
7628#ifdef TARGET_NR_clock_getres
7629 case TARGET_NR_clock_getres:
7630 {
7631 struct timespec ts;
7632 ret = get_errno(clock_getres(arg1, &ts));
7633 if (!is_error(ret)) {
7634 host_to_target_timespec(arg2, &ts);
7635 }
7636 break;
7637 }
7638#endif
63d7651b
PB
7639#ifdef TARGET_NR_clock_nanosleep
7640 case TARGET_NR_clock_nanosleep:
7641 {
7642 struct timespec ts;
7643 target_to_host_timespec(&ts, arg3);
7644 ret = get_errno(clock_nanosleep(arg1, arg2, &ts, arg4 ? &ts : NULL));
7645 if (arg4)
7646 host_to_target_timespec(arg4, &ts);
7647 break;
7648 }
7649#endif
b5906f95 7650
6f5b89a0
TS
7651#if defined(TARGET_NR_set_tid_address) && defined(__NR_set_tid_address)
7652 case TARGET_NR_set_tid_address:
579a97f7
FB
7653 ret = get_errno(set_tid_address((int *)g2h(arg1)));
7654 break;
6f5b89a0
TS
7655#endif
7656
3ae43202 7657#if defined(TARGET_NR_tkill) && defined(__NR_tkill)
4cae1d16 7658 case TARGET_NR_tkill:
4cb05961 7659 ret = get_errno(sys_tkill((int)arg1, target_to_host_signal(arg2)));
4cae1d16
TS
7660 break;
7661#endif
7662
3ae43202 7663#if defined(TARGET_NR_tgkill) && defined(__NR_tgkill)
71455574 7664 case TARGET_NR_tgkill:
4cb05961
PB
7665 ret = get_errno(sys_tgkill((int)arg1, (int)arg2,
7666 target_to_host_signal(arg3)));
71455574
TS
7667 break;
7668#endif
7669
4f2b1fe8
TS
7670#ifdef TARGET_NR_set_robust_list
7671 case TARGET_NR_set_robust_list:
7672 goto unimplemented_nowarn;
7673#endif
7674
9007f0ef
TS
7675#if defined(TARGET_NR_utimensat) && defined(__NR_utimensat)
7676 case TARGET_NR_utimensat:
7677 {
ebc996f3
RV
7678 struct timespec *tsp, ts[2];
7679 if (!arg3) {
7680 tsp = NULL;
7681 } else {
7682 target_to_host_timespec(ts, arg3);
7683 target_to_host_timespec(ts+1, arg3+sizeof(struct target_timespec));
7684 tsp = ts;
7685 }
9007f0ef 7686 if (!arg2)
ebc996f3 7687 ret = get_errno(sys_utimensat(arg1, NULL, tsp, arg4));
9007f0ef 7688 else {
579a97f7 7689 if (!(p = lock_user_string(arg2))) {
0da46a6e 7690 ret = -TARGET_EFAULT;
579a97f7
FB
7691 goto fail;
7692 }
ebc996f3 7693 ret = get_errno(sys_utimensat(arg1, path(p), tsp, arg4));
579a97f7 7694 unlock_user(p, arg2, 0);
9007f0ef
TS
7695 }
7696 }
7697 break;
7698#endif
2f7bb878 7699#if defined(CONFIG_USE_NPTL)
bd0c5661
PB
7700 case TARGET_NR_futex:
7701 ret = do_futex(arg1, arg2, arg3, arg4, arg5, arg6);
7702 break;
7703#endif
dbfe4c36 7704#if defined(TARGET_NR_inotify_init) && defined(__NR_inotify_init)
39b59763
AJ
7705 case TARGET_NR_inotify_init:
7706 ret = get_errno(sys_inotify_init());
7707 break;
7708#endif
a1606b0b 7709#ifdef CONFIG_INOTIFY1
c05c7a73
RV
7710#if defined(TARGET_NR_inotify_init1) && defined(__NR_inotify_init1)
7711 case TARGET_NR_inotify_init1:
7712 ret = get_errno(sys_inotify_init1(arg1));
7713 break;
7714#endif
a1606b0b 7715#endif
dbfe4c36 7716#if defined(TARGET_NR_inotify_add_watch) && defined(__NR_inotify_add_watch)
39b59763
AJ
7717 case TARGET_NR_inotify_add_watch:
7718 p = lock_user_string(arg2);
7719 ret = get_errno(sys_inotify_add_watch(arg1, path(p), arg3));
7720 unlock_user(p, arg2, 0);
7721 break;
7722#endif
dbfe4c36 7723#if defined(TARGET_NR_inotify_rm_watch) && defined(__NR_inotify_rm_watch)
39b59763
AJ
7724 case TARGET_NR_inotify_rm_watch:
7725 ret = get_errno(sys_inotify_rm_watch(arg1, arg2));
7726 break;
7727#endif
9007f0ef 7728
8ec9cf89 7729#if defined(TARGET_NR_mq_open) && defined(__NR_mq_open)
24e1003a
AJ
7730 case TARGET_NR_mq_open:
7731 {
7732 struct mq_attr posix_mq_attr;
7733
7734 p = lock_user_string(arg1 - 1);
7735 if (arg4 != 0)
7736 copy_from_user_mq_attr (&posix_mq_attr, arg4);
7737 ret = get_errno(mq_open(p, arg2, arg3, &posix_mq_attr));
7738 unlock_user (p, arg1, 0);
7739 }
7740 break;
7741
7742 case TARGET_NR_mq_unlink:
7743 p = lock_user_string(arg1 - 1);
7744 ret = get_errno(mq_unlink(p));
7745 unlock_user (p, arg1, 0);
7746 break;
7747
7748 case TARGET_NR_mq_timedsend:
7749 {
7750 struct timespec ts;
7751
7752 p = lock_user (VERIFY_READ, arg2, arg3, 1);
7753 if (arg5 != 0) {
7754 target_to_host_timespec(&ts, arg5);
7755 ret = get_errno(mq_timedsend(arg1, p, arg3, arg4, &ts));
7756 host_to_target_timespec(arg5, &ts);
7757 }
7758 else
7759 ret = get_errno(mq_send(arg1, p, arg3, arg4));
7760 unlock_user (p, arg2, arg3);
7761 }
7762 break;
7763
7764 case TARGET_NR_mq_timedreceive:
7765 {
7766 struct timespec ts;
7767 unsigned int prio;
7768
7769 p = lock_user (VERIFY_READ, arg2, arg3, 1);
7770 if (arg5 != 0) {
7771 target_to_host_timespec(&ts, arg5);
7772 ret = get_errno(mq_timedreceive(arg1, p, arg3, &prio, &ts));
7773 host_to_target_timespec(arg5, &ts);
7774 }
7775 else
7776 ret = get_errno(mq_receive(arg1, p, arg3, &prio));
7777 unlock_user (p, arg2, arg3);
7778 if (arg4 != 0)
7779 put_user_u32(prio, arg4);
7780 }
7781 break;
7782
7783 /* Not implemented for now... */
7784/* case TARGET_NR_mq_notify: */
7785/* break; */
7786
7787 case TARGET_NR_mq_getsetattr:
7788 {
7789 struct mq_attr posix_mq_attr_in, posix_mq_attr_out;
7790 ret = 0;
7791 if (arg3 != 0) {
7792 ret = mq_getattr(arg1, &posix_mq_attr_out);
7793 copy_to_user_mq_attr(arg3, &posix_mq_attr_out);
7794 }
7795 if (arg2 != 0) {
7796 copy_from_user_mq_attr(&posix_mq_attr_in, arg2);
7797 ret |= mq_setattr(arg1, &posix_mq_attr_in, &posix_mq_attr_out);
7798 }
7799
7800 }
7801 break;
7802#endif
7803
3ce34dfb
VS
7804#ifdef CONFIG_SPLICE
7805#ifdef TARGET_NR_tee
7806 case TARGET_NR_tee:
7807 {
7808 ret = get_errno(tee(arg1,arg2,arg3,arg4));
7809 }
7810 break;
7811#endif
7812#ifdef TARGET_NR_splice
7813 case TARGET_NR_splice:
7814 {
7815 loff_t loff_in, loff_out;
7816 loff_t *ploff_in = NULL, *ploff_out = NULL;
7817 if(arg2) {
7818 get_user_u64(loff_in, arg2);
7819 ploff_in = &loff_in;
7820 }
7821 if(arg4) {
7822 get_user_u64(loff_out, arg2);
7823 ploff_out = &loff_out;
7824 }
7825 ret = get_errno(splice(arg1, ploff_in, arg3, ploff_out, arg5, arg6));
7826 }
7827 break;
7828#endif
7829#ifdef TARGET_NR_vmsplice
7830 case TARGET_NR_vmsplice:
7831 {
7832 int count = arg3;
7833 struct iovec *vec;
7834
7835 vec = alloca(count * sizeof(struct iovec));
7836 if (lock_iovec(VERIFY_READ, vec, arg2, count, 1) < 0)
7837 goto efault;
7838 ret = get_errno(vmsplice(arg1, vec, count, arg4));
7839 unlock_iovec(vec, arg2, count, 0);
7840 }
7841 break;
7842#endif
7843#endif /* CONFIG_SPLICE */
c2882b96
RV
7844#ifdef CONFIG_EVENTFD
7845#if defined(TARGET_NR_eventfd)
7846 case TARGET_NR_eventfd:
7847 ret = get_errno(eventfd(arg1, 0));
7848 break;
7849#endif
7850#if defined(TARGET_NR_eventfd2)
7851 case TARGET_NR_eventfd2:
7852 ret = get_errno(eventfd(arg1, arg2));
7853 break;
7854#endif
7855#endif /* CONFIG_EVENTFD */
d0927938
UH
7856#if defined(CONFIG_FALLOCATE) && defined(TARGET_NR_fallocate)
7857 case TARGET_NR_fallocate:
7858 ret = get_errno(fallocate(arg1, arg2, arg3, arg4));
7859 break;
c727f47d
PM
7860#endif
7861#if defined(CONFIG_SYNC_FILE_RANGE)
7862#if defined(TARGET_NR_sync_file_range)
7863 case TARGET_NR_sync_file_range:
7864#if TARGET_ABI_BITS == 32
7865 ret = get_errno(sync_file_range(arg1, target_offset64(arg2, arg3),
7866 target_offset64(arg4, arg5), arg6));
7867#else
7868 ret = get_errno(sync_file_range(arg1, arg2, arg3, arg4));
7869#endif
7870 break;
7871#endif
7872#if defined(TARGET_NR_sync_file_range2)
7873 case TARGET_NR_sync_file_range2:
7874 /* This is like sync_file_range but the arguments are reordered */
7875#if TARGET_ABI_BITS == 32
7876 ret = get_errno(sync_file_range(arg1, target_offset64(arg3, arg4),
7877 target_offset64(arg5, arg6), arg2));
7878#else
7879 ret = get_errno(sync_file_range(arg1, arg3, arg4, arg2));
7880#endif
7881 break;
7882#endif
3b6edd16
PM
7883#endif
7884#if defined(CONFIG_EPOLL)
7885#if defined(TARGET_NR_epoll_create)
7886 case TARGET_NR_epoll_create:
7887 ret = get_errno(epoll_create(arg1));
7888 break;
7889#endif
7890#if defined(TARGET_NR_epoll_create1) && defined(CONFIG_EPOLL_CREATE1)
7891 case TARGET_NR_epoll_create1:
7892 ret = get_errno(epoll_create1(arg1));
7893 break;
7894#endif
7895#if defined(TARGET_NR_epoll_ctl)
7896 case TARGET_NR_epoll_ctl:
7897 {
7898 struct epoll_event ep;
7899 struct epoll_event *epp = 0;
7900 if (arg4) {
7901 struct target_epoll_event *target_ep;
7902 if (!lock_user_struct(VERIFY_READ, target_ep, arg4, 1)) {
7903 goto efault;
7904 }
7905 ep.events = tswap32(target_ep->events);
7906 /* The epoll_data_t union is just opaque data to the kernel,
7907 * so we transfer all 64 bits across and need not worry what
7908 * actual data type it is.
7909 */
7910 ep.data.u64 = tswap64(target_ep->data.u64);
7911 unlock_user_struct(target_ep, arg4, 0);
7912 epp = &ep;
7913 }
7914 ret = get_errno(epoll_ctl(arg1, arg2, arg3, epp));
7915 break;
7916 }
7917#endif
7918
7919#if defined(TARGET_NR_epoll_pwait) && defined(CONFIG_EPOLL_PWAIT)
7920#define IMPLEMENT_EPOLL_PWAIT
7921#endif
7922#if defined(TARGET_NR_epoll_wait) || defined(IMPLEMENT_EPOLL_PWAIT)
7923#if defined(TARGET_NR_epoll_wait)
7924 case TARGET_NR_epoll_wait:
7925#endif
7926#if defined(IMPLEMENT_EPOLL_PWAIT)
7927 case TARGET_NR_epoll_pwait:
7928#endif
7929 {
7930 struct target_epoll_event *target_ep;
7931 struct epoll_event *ep;
7932 int epfd = arg1;
7933 int maxevents = arg3;
7934 int timeout = arg4;
7935
7936 target_ep = lock_user(VERIFY_WRITE, arg2,
7937 maxevents * sizeof(struct target_epoll_event), 1);
7938 if (!target_ep) {
7939 goto efault;
7940 }
7941
7942 ep = alloca(maxevents * sizeof(struct epoll_event));
7943
7944 switch (num) {
7945#if defined(IMPLEMENT_EPOLL_PWAIT)
7946 case TARGET_NR_epoll_pwait:
7947 {
7948 target_sigset_t *target_set;
7949 sigset_t _set, *set = &_set;
7950
7951 if (arg5) {
7952 target_set = lock_user(VERIFY_READ, arg5,
7953 sizeof(target_sigset_t), 1);
7954 if (!target_set) {
7955 unlock_user(target_ep, arg2, 0);
7956 goto efault;
7957 }
7958 target_to_host_sigset(set, target_set);
7959 unlock_user(target_set, arg5, 0);
7960 } else {
7961 set = NULL;
7962 }
7963
7964 ret = get_errno(epoll_pwait(epfd, ep, maxevents, timeout, set));
7965 break;
7966 }
7967#endif
7968#if defined(TARGET_NR_epoll_wait)
7969 case TARGET_NR_epoll_wait:
7970 ret = get_errno(epoll_wait(epfd, ep, maxevents, timeout));
7971 break;
7972#endif
7973 default:
7974 ret = -TARGET_ENOSYS;
7975 }
7976 if (!is_error(ret)) {
7977 int i;
7978 for (i = 0; i < ret; i++) {
7979 target_ep[i].events = tswap32(ep[i].events);
7980 target_ep[i].data.u64 = tswap64(ep[i].data.u64);
7981 }
7982 }
7983 unlock_user(target_ep, arg2, ret * sizeof(struct target_epoll_event));
7984 break;
7985 }
7986#endif
d0927938 7987#endif
31e31b8a
FB
7988 default:
7989 unimplemented:
5cd4393b 7990 gemu_log("qemu: Unsupported syscall: %d\n", num);
4f2b1fe8 7991#if defined(TARGET_NR_setxattr) || defined(TARGET_NR_get_thread_area) || defined(TARGET_NR_getdomainname) || defined(TARGET_NR_set_robust_list)
5cd4393b 7992 unimplemented_nowarn:
80a9d035 7993#endif
0da46a6e 7994 ret = -TARGET_ENOSYS;
31e31b8a
FB
7995 break;
7996 }
579a97f7 7997fail:
c573ff67 7998#ifdef DEBUG
0bf9e31a 7999 gemu_log(" = " TARGET_ABI_FMT_ld "\n", ret);
c573ff67 8000#endif
b92c47c1
TS
8001 if(do_strace)
8002 print_syscall_ret(num, ret);
31e31b8a 8003 return ret;
579a97f7
FB
8004efault:
8005 ret = -TARGET_EFAULT;
8006 goto fail;
31e31b8a 8007}