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