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