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